diff options
Diffstat (limited to 'security/nss/lib/cryptohi/seckey.c')
-rw-r--r-- | security/nss/lib/cryptohi/seckey.c | 129 |
1 files changed, 124 insertions, 5 deletions
diff --git a/security/nss/lib/cryptohi/seckey.c b/security/nss/lib/cryptohi/seckey.c index 1762c1a143..1a68104978 100644 --- a/security/nss/lib/cryptohi/seckey.c +++ b/security/nss/lib/cryptohi/seckey.c @@ -235,6 +235,33 @@ SECKEY_CreateECPrivateKey(SECKEYECParams *param, SECKEYPublicKey **pubk, void *c return (privk); } +SECKEYPrivateKey * +SECKEY_CreateEDPrivateKey(SECKEYECParams *param, SECKEYPublicKey **pubk, void *cx) +{ + SECKEYPrivateKey *privk; + PK11SlotInfo *slot = PK11_GetBestSlot(CKM_EC_EDWARDS_KEY_PAIR_GEN, cx); + if (!slot) { + return NULL; + } + + privk = PK11_GenerateKeyPairWithOpFlags(slot, CKM_EC_EDWARDS_KEY_PAIR_GEN, + param, pubk, + PK11_ATTR_SESSION | + PK11_ATTR_INSENSITIVE | + PK11_ATTR_PUBLIC, + CKF_SIGN, CKF_SIGN, cx); + if (!privk) + privk = PK11_GenerateKeyPairWithOpFlags(slot, CKM_EC_EDWARDS_KEY_PAIR_GEN, + param, pubk, + PK11_ATTR_SESSION | + PK11_ATTR_SENSITIVE | + PK11_ATTR_PRIVATE, + CKF_SIGN, CKF_SIGN, cx); + + PK11_FreeSlot(slot); + return (privk); +} + void SECKEY_DestroyPrivateKey(SECKEYPrivateKey *privk) { @@ -329,7 +356,7 @@ seckey_UpdateCertPQGChain(CERTCertificate *subjectCert, int count) * * Question: do we really need to do this for EC keys. They don't have * PQG parameters, but they do have parameters. The question is does - * the child cert inherit thost parameters for EC from the parent, or + * the child cert inherit those parameters for EC from the parent, or * do we always include those parameters in each cert. */ @@ -339,6 +366,7 @@ seckey_UpdateCertPQGChain(CERTCertificate *subjectCert, int count) (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST) && (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) && (tag != SEC_OID_SDN702_DSA_SIGNATURE) && + (tag != SEC_OID_ED25519_PUBLIC_KEY) && (tag != SEC_OID_ANSIX962_EC_PUBLIC_KEY)) { return SECSuccess; @@ -383,6 +411,7 @@ seckey_UpdateCertPQGChain(CERTCertificate *subjectCert, int count) (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST) && (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) && (tag != SEC_OID_SDN702_DSA_SIGNATURE) && + (tag != SEC_OID_ED25519_PUBLIC_KEY) && (tag != SEC_OID_ANSIX962_EC_PUBLIC_KEY)) { rv = SECFailure; goto loser; @@ -521,6 +550,9 @@ seckey_GetKeyType(SECOidTag tag) case SEC_OID_ANSIX962_EC_PUBLIC_KEY: keyType = ecKey; break; + case SEC_OID_ED25519_PUBLIC_KEY: + keyType = edKey; + break; /* accommodate applications that hand us a signature type when they * should be handing us a cipher type */ case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: @@ -637,6 +669,37 @@ seckey_ExtractPublicKey(const CERTSubjectPublicKeyInfo *spki) if (rv == SECSuccess) return pubk; break; + case SEC_OID_ED25519_PUBLIC_KEY: + /* A basic consistency check on inputs. */ + if (newOs.len == 0) { + PORT_SetError(SEC_ERROR_INPUT_LEN); + break; + } + + /* Currently supporting only (Pure)Ed25519 .*/ + if (spki->algorithm.parameters.len != 0) { + PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); + break; + } + + pubk->keyType = edKey; + pubk->u.ec.size = 0; + + SECOidData *oidEd25519 = SECOID_FindOIDByTag(SEC_OID_ED25519_PUBLIC_KEY); + + if (!SECITEM_AllocItem(arena, &pubk->u.ec.DEREncodedParams, oidEd25519->oid.len + 2)) { + rv = SECFailure; + break; + } + pubk->u.ec.DEREncodedParams.data[0] = SEC_ASN1_OBJECT_ID; + pubk->u.ec.DEREncodedParams.data[1] = oidEd25519->oid.len; + PORT_Memcpy(pubk->u.ec.DEREncodedParams.data + 2, oidEd25519->oid.data, oidEd25519->oid.len); + + rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &newOs); + if (rv != SECSuccess) { + break; + } + return pubk; case SEC_OID_ANSIX962_EC_PUBLIC_KEY: /* A basic sanity check on inputs. */ if (spki->algorithm.parameters.len == 0 || newOs.len == 0) { @@ -811,6 +874,7 @@ SECKEY_ECParamsToKeySize(const SECItem *encodedParams) return 571; case SEC_OID_CURVE25519: + case SEC_OID_ED25519_PUBLIC_KEY: return 255; default: @@ -961,6 +1025,7 @@ SECKEY_ECParamsToBasePointOrderLen(const SECItem *encodedParams) return 570; case SEC_OID_CURVE25519: + case SEC_OID_ED25519_PUBLIC_KEY: return 255; default: @@ -1032,6 +1097,7 @@ SECKEY_PublicKeyStrengthInBits(const SECKEYPublicKey *pubk) bitSize = SECKEY_BigIntegerBitLength(&pubk->u.dh.prime); break; case ecKey: + case edKey: bitSize = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams); break; default: @@ -1113,6 +1179,7 @@ SECKEY_SignatureLen(const SECKEYPublicKey *pubk) case dsaKey: return pubk->u.dsa.params.subPrime.len * 2; case ecKey: + case edKey: /* Get the base point order length in bits and adjust */ size = SECKEY_ECParamsToBasePointOrderLen( &pubk->u.ec.DEREncodedParams); @@ -1239,6 +1306,7 @@ SECKEY_CopyPublicKey(const SECKEYPublicKey *pubk) &pubk->u.dh.publicValue); break; case ecKey: + case edKey: copyk->u.ec.size = pubk->u.ec.size; rv = seckey_HasCurveOID(pubk); if (rv != SECSuccess) { @@ -1465,6 +1533,28 @@ SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk) * overwrite the old value */ pubk->u.ec.publicValue = decodedPoint; } + + pubk->u.ec.encoding = ECPoint_Undefined; + return pubk; + case edKey: + rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID, + CKA_EC_PARAMS, arena, &pubk->u.ec.DEREncodedParams); + if (rv != SECSuccess) { + break; + } + rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID, + CKA_EC_POINT, arena, &pubk->u.ec.publicValue); + if (rv != SECSuccess || pubk->u.ec.publicValue.len == 0) { + pubKeyHandle = seckey_FindPublicKeyHandle(privk, pubk); + if (pubKeyHandle == CK_INVALID_HANDLE) { + break; + } + rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle, + CKA_EC_POINT, arena, &pubk->u.ec.publicValue); + if (rv != SECSuccess) { + break; + } + } pubk->u.ec.encoding = ECPoint_Undefined; return pubk; default: @@ -1483,6 +1573,7 @@ seckey_CreateSubjectPublicKeyInfo_helper(SECKEYPublicKey *pubk) CERTSubjectPublicKeyInfo *spki; PLArenaPool *arena; SECItem params = { siBuffer, NULL, 0 }; + SECOidTag tag; arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) { @@ -1555,14 +1646,41 @@ seckey_CreateSubjectPublicKeyInfo_helper(SECKEYPublicKey *pubk) case ecKey: rv = SECITEM_CopyItem(arena, ¶ms, &pubk->u.ec.DEREncodedParams); - if (rv != SECSuccess) + if (rv != SECSuccess) { break; + } + tag = SEC_OID_ANSIX962_EC_PUBLIC_KEY; rv = SECOID_SetAlgorithmID(arena, &spki->algorithm, - SEC_OID_ANSIX962_EC_PUBLIC_KEY, + tag, ¶ms); - if (rv != SECSuccess) + if (rv != SECSuccess) { + break; + } + + rv = SECITEM_CopyItem(arena, &spki->subjectPublicKey, + &pubk->u.ec.publicValue); + + if (rv == SECSuccess) { + /* + * The stored value is supposed to be a BIT_STRING, + * so convert the length. + */ + spki->subjectPublicKey.len <<= 3; + /* + * We got a good one; return it. + */ + return spki; + } + break; + case edKey: + tag = SECKEY_GetECCOid(&pubk->u.ec.DEREncodedParams); + rv = SECOID_SetAlgorithmID(arena, &spki->algorithm, + tag, + ¶ms); + if (rv != SECSuccess) { break; + } rv = SECITEM_CopyItem(arena, &spki->subjectPublicKey, &pubk->u.ec.publicValue); @@ -1669,8 +1787,9 @@ SECKEY_DecodeDERSubjectPublicKeyInfo(const SECItem *spkider) rv = SEC_QuickDERDecodeItem(arena, spki, CERT_SubjectPublicKeyInfoTemplate, &newSpkider); } - if (rv == SECSuccess) + if (rv == SECSuccess) { return spki; + } } else { PORT_SetError(SEC_ERROR_NO_MEMORY); } |