// Get the public key matching a private key // TODO: Add support for non-RSA keys, switching on CKA_KEY_TYPE func getPublicKey(module *pkcs11.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 }
func (ps *Key) getPrivateKey(module *pkcs11.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 }