summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/cryptohi/seckey.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/cryptohi/seckey.c')
-rw-r--r--security/nss/lib/cryptohi/seckey.c129
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, &params,
&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,
&params);
- 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,
+ &params);
+ 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);
}