Esempio n. 1
0
// Get the public key matching a private key
// TODO: Add support for non-RSA keys, switching on CKA_KEY_TYPE
func getPublicKey(module ctx, session pkcs11.SessionHandle, privateKeyHandle pkcs11.ObjectHandle) (rsa.PublicKey, error) {
	var noKey rsa.PublicKey
	template := []*pkcs11.Attribute{
		pkcs11.NewAttribute(pkcs11.CKA_MODULUS, nil),
		pkcs11.NewAttribute(pkcs11.CKA_PUBLIC_EXPONENT, nil),
	}
	attr, err := module.GetAttributeValue(session, privateKeyHandle, template)
	if err != nil {
		return noKey, err
	}

	n := big.NewInt(0)
	e := int(0)
	gotModulus, gotExponent := false, false
	for _, a := range attr {
		if a.Type == pkcs11.CKA_MODULUS {
			n.SetBytes(a.Value)
			gotModulus = true
		} else if a.Type == pkcs11.CKA_PUBLIC_EXPONENT {
			bigE := big.NewInt(0)
			bigE.SetBytes(a.Value)
			e = int(bigE.Int64())
			gotExponent = true
		}
	}
	if !gotModulus || !gotExponent {
		return noKey, errors.New("public key missing either modulus or exponent")
	}
	return rsa.PublicKey{
		N: n,
		E: e,
	}, nil
}
Esempio n. 2
0
func (ps *Key) getPrivateKey(module ctx, session pkcs11.SessionHandle, label string) (pkcs11.ObjectHandle, error) {
	var noHandle pkcs11.ObjectHandle
	template := []*pkcs11.Attribute{
		pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PRIVATE_KEY),
		pkcs11.NewAttribute(pkcs11.CKA_LABEL, label),
	}
	if err := module.FindObjectsInit(session, template); err != nil {
		return noHandle, err
	}
	objs, _, err := module.FindObjects(session, 2)
	if err != nil {
		return noHandle, err
	}
	if err = module.FindObjectsFinal(session); err != nil {
		return noHandle, err
	}

	if len(objs) == 0 {
		return noHandle, fmt.Errorf("private key not found")
	}
	privateKeyHandle := objs[0]

	// Check whether the key has the CKA_ALWAYS_AUTHENTICATE attribute.
	// If so, fail: we don't want to have to re-authenticate for each sign
	// operation.
	attributes, err := module.GetAttributeValue(session, privateKeyHandle, []*pkcs11.Attribute{
		pkcs11.NewAttribute(pkcs11.CKA_ALWAYS_AUTHENTICATE, false),
	})
	// The PKCS#11 spec states that C_GetAttributeValue may return
	// CKR_ATTRIBUTE_TYPE_INVALID if an object simply does not posses a given
	// attribute. We don't consider that an error: the absence of the
	// CKR_ATTRIBUTE_TYPE_INVALID property is just fine.
	if err != nil && err == pkcs11.Error(pkcs11.CKR_ATTRIBUTE_TYPE_INVALID) {
		return privateKeyHandle, nil
	} else if err != nil {
		return noHandle, err
	}
	for _, attribute := range attributes {
		if len(attribute.Value) > 0 && attribute.Value[0] == 1 {
			ps.alwaysAuthenticate = true
		}
	}

	return privateKeyHandle, nil
}
Esempio n. 3
0
func getKeyType(module ctx, session pkcs11.SessionHandle, privateKeyHandle pkcs11.ObjectHandle) (c byte, err error) {
	attributes, err := module.GetAttributeValue(session, privateKeyHandle, []*pkcs11.Attribute{
		pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, false),
	})
	if err != nil {
		return
	}

	if (len(attributes) > 0) && (len(attributes[0].Value) > 0) {
		c = attributes[0].Value[0]
	} else {
		err = fmt.Errorf("No key type")
	}
	return
}
Esempio n. 4
0
// Get the public key matching an Elliptic Curve private key
func getECPublicKey(module ctx, session pkcs11.SessionHandle, privateKeyHandle pkcs11.ObjectHandle) (crypto.PublicKey, error) {
	var noKey interface{}

	// http://docs.oasis-open.org/pkcs11/pkcs11-curr/v2.40/os/pkcs11-curr-v2.40-os.html#_Toc416960012
	template := []*pkcs11.Attribute{
		// CKA_EC_PARAMS contains the OID of the curve (part of the
		// public key
		pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, nil),
		// CKA_ID will allow use to find the corresponding public key
		pkcs11.NewAttribute(pkcs11.CKA_ID, nil),
	}

	attr, err := module.GetAttributeValue(session, privateKeyHandle, template)
	if err != nil {
		return noKey, err
	}

	oid := []byte{}
	id := []byte{}
	gotOid, gotID := false, false
	for _, a := range attr {
		if a.Type == pkcs11.CKA_EC_PARAMS {
			oid = a.Value
			gotOid = true
		} else if a.Type == pkcs11.CKA_ID {
			id = a.Value
			gotID = true
		}
	}
	if !gotOid {
		return noKey, errors.New("private key missing curve parameters")
	}
	if !gotID {
		return noKey, errors.New("private key missing identifier (CKA_ID)")
	}

	poid := new(asn1.ObjectIdentifier)
	asn1.Unmarshal(oid, poid)
	curve := namedCurveFromOID(*poid)

	templateSearch := []*pkcs11.Attribute{
		pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PUBLIC_KEY),
		pkcs11.NewAttribute(pkcs11.CKA_ID, id),
	}

	if err := module.FindObjectsInit(session, templateSearch); err != nil {
		return noKey, err
	}
	objs, _, err := module.FindObjects(session, 1)
	if err != nil {
		return noKey, err
	}
	if err = module.FindObjectsFinal(session); err != nil {
		return noKey, err
	}

	if len(objs) == 0 {
		return noKey, fmt.Errorf("public key not found")
	}
	publicKeyHandle := objs[0]

	templatePub := []*pkcs11.Attribute{
		pkcs11.NewAttribute(pkcs11.CKA_EC_POINT, nil),
	}

	attrPub, err := module.GetAttributeValue(session, publicKeyHandle, templatePub)
	if err != nil {
		return noKey, err
	}

	ecPoint := []byte{}
	gotEcPoint := false
	for _, a := range attrPub {
		if a.Type == pkcs11.CKA_EC_POINT {
			ecPoint = a.Value
			gotEcPoint = true
		}
	}
	if !gotEcPoint {
		return noKey, errors.New("public key missing EC Point")
	}

	x, y := readECPoint(curve, ecPoint)
	if x == nil {
		return noKey, errors.New("invalid EC Point")
	}
	ecdsa := ecdsa.PublicKey{
		Curve: curve,
		X:     x,
		Y:     y,
	}
	return &ecdsa, nil
}
Esempio n. 5
0
// New instantiates a new handle to a PKCS #11-backed key.
func New(module, tokenLabel, pin, privLabel string, slotID int) (ps *PKCS11Key, err error) {
	// Set up a new pkcs11 object and initialize it
	p := pkcs11.New(module)
	if p == nil {
		err = errors.New("unable to load PKCS#11 module")
		return
	}

	if err = p.Initialize(); err != nil {
		return
	}

	// Initialize a partial key
	ps = &PKCS11Key{
		module:     p,
		slotID:     slotID,
		tokenLabel: tokenLabel,
		pin:        pin,
	}

	// Look up the private key
	session, err := ps.openSession()
	if err != nil {
		ps.Destroy()
		return
	}
	defer ps.closeSession(session)

	template := []*pkcs11.Attribute{
		pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PRIVATE_KEY),
		pkcs11.NewAttribute(pkcs11.CKA_LABEL, privLabel),
	}
	if err = p.FindObjectsInit(session, template); err != nil {
		ps.Destroy()
		return
	}
	objs, _, err := p.FindObjects(session, 2)
	if err != nil {
		ps.Destroy()
		return
	}
	if err = p.FindObjectsFinal(session); err != nil {
		ps.Destroy()
		return
	}

	if len(objs) == 0 {
		err = errors.New("private key not found")
		ps.Destroy()
		return
	}
	ps.privateKeyHandle = objs[0]

	// Populate the pubic key from the private key
	// TODO: Add support for non-RSA keys, switching on CKA_KEY_TYPE
	template = []*pkcs11.Attribute{
		pkcs11.NewAttribute(pkcs11.CKA_MODULUS, nil),
		pkcs11.NewAttribute(pkcs11.CKA_PUBLIC_EXPONENT, nil),
	}
	attr, err := p.GetAttributeValue(session, ps.privateKeyHandle, template)
	if err != nil {
		ps.Destroy()
		return
	}

	n := big.NewInt(0)
	e := int(0)
	gotModulus, gotExponent := false, false
	for _, a := range attr {
		if a.Type == pkcs11.CKA_MODULUS {
			n.SetBytes(a.Value)
			gotModulus = true
		} else if a.Type == pkcs11.CKA_PUBLIC_EXPONENT {
			bigE := big.NewInt(0)
			bigE.SetBytes(a.Value)
			e = int(bigE.Int64())
			gotExponent = true
		}
	}
	if !gotModulus || !gotExponent {
		ps.Destroy()
		return
	}
	ps.publicKey = rsa.PublicKey{
		N: n,
		E: e,
	}

	return
}