summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/pk11wrap/pk11pk12.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--security/nss/lib/pk11wrap/pk11pk12.c80
1 files changed, 77 insertions, 3 deletions
diff --git a/security/nss/lib/pk11wrap/pk11pk12.c b/security/nss/lib/pk11wrap/pk11pk12.c
index 917b7f0f67..5d8b00d3d0 100644
--- a/security/nss/lib/pk11wrap/pk11pk12.c
+++ b/security/nss/lib/pk11wrap/pk11pk12.c
@@ -180,6 +180,13 @@ const SEC_ASN1Template SECKEY_ECPrivateKeyExportTemplate[] = {
{ 0 }
};
+/* The template operates a private key consisting only of private key. */
+const SEC_ASN1Template SECKEY_EDPrivateKeyExportTemplate[] = {
+ { SEC_ASN1_OCTET_STRING,
+ offsetof(SECKEYRawPrivateKey, u.ec.privateValue) },
+ { 0 }
+};
+
const SEC_ASN1Template SECKEY_EncryptedPrivateKeyInfoTemplate[] = {
{ SEC_ASN1_SEQUENCE,
0, NULL, sizeof(SECKEYEncryptedPrivateKeyInfo) },
@@ -270,8 +277,10 @@ PK11_ImportDERPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot, SECItem *derPKI,
SECStatus rv = SECFailure;
temparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (!temparena)
+ if (!temparena) {
return rv;
+ }
+
pki = PORT_ArenaZNew(temparena, SECKEYPrivateKeyInfo);
if (!pki) {
PORT_FreeArena(temparena, PR_FALSE);
@@ -523,13 +532,31 @@ PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk,
lpk->u.ec.publicValue.len);
attrs++;
break;
+ case edKey:
+ keyType = CKK_EC_EDWARDS;
+ PK11_SETATTRS(attrs, CKA_SIGN, &cktrue, sizeof(CK_BBOOL));
+ attrs++;
+ if (nickname) {
+ PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
+ attrs++;
+ }
+
+ /* No signed attrs for EC */
+ /* curveOID always is a copy of AlgorithmID.parameters. */
+ PK11_SETATTRS(attrs, CKA_EC_PARAMS, lpk->u.ec.curveOID.data,
+ lpk->u.ec.curveOID.len);
+ attrs++;
+ PK11_SETATTRS(attrs, CKA_VALUE, lpk->u.ec.privateValue.data,
+ lpk->u.ec.privateValue.len);
+ attrs++;
+ break;
default:
PORT_SetError(SEC_ERROR_BAD_KEY);
goto loser;
}
templateCount = attrs - theTemplate;
PORT_Assert(templateCount <= sizeof(theTemplate) / sizeof(CK_ATTRIBUTE));
- if (lpk->keyType != ecKey) {
+ if (lpk->keyType != ecKey && lpk->keyType != edKey) {
PORT_Assert(signedattr);
signedcount = attrs - signedattr;
for (ap = signedattr; signedcount; ap++, signedcount--) {
@@ -604,6 +631,12 @@ PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot,
paramDest = NULL;
lpk->keyType = dhKey;
break;
+ case SEC_OID_ED25519_PUBLIC_KEY:
+ keyTemplate = SECKEY_EDPrivateKeyExportTemplate;
+ paramTemplate = NULL;
+ paramDest = NULL;
+ lpk->keyType = edKey;
+ break;
case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
prepare_ec_priv_key_export_for_asn1(lpk);
keyTemplate = SECKEY_ECPrivateKeyExportTemplate;
@@ -641,6 +674,26 @@ PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot,
}
}
+ if (lpk->keyType == edKey) {
+ /* Convert length in bits to length in bytes. */
+ lpk->u.ec.publicValue.len >>= 3;
+
+ if (pki->algorithm.parameters.len != 0) {
+ /* Currently supporting only (Pure)Ed25519 .*/
+ PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
+ goto loser;
+ }
+
+ SECOidData *oidEd25519 = SECOID_FindOIDByTag(SEC_OID_ED25519_PUBLIC_KEY);
+
+ if (!SECITEM_AllocItem(arena, &lpk->u.ec.curveOID, oidEd25519->oid.len + 2)) {
+ goto loser;
+ }
+ lpk->u.ec.curveOID.data[0] = SEC_ASN1_OBJECT_ID;
+ lpk->u.ec.curveOID.data[1] = oidEd25519->oid.len;
+ PORT_Memcpy(lpk->u.ec.curveOID.data + 2, oidEd25519->oid.data, oidEd25519->oid.len);
+ }
+
if (paramDest && paramTemplate) {
rv = SEC_ASN1DecodeItem(arena, paramDest, paramTemplate,
&(pki->algorithm.parameters));
@@ -651,7 +704,6 @@ PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot,
rv = PK11_ImportAndReturnPrivateKey(slot, lpk, nickname, publicValue, isPerm,
isPrivate, keyUsage, privk, wincx);
-
loser:
if (arena != NULL) {
PORT_FreeArena(arena, PR_TRUE);
@@ -800,6 +852,28 @@ PK11_ExportPrivKeyInfo(SECKEYPrivateKey *pk, void *wincx)
}
} break;
+ case edKey: {
+ rawKey.u.ec.version.type = siUnsignedInteger;
+ rawKey.u.ec.version.data = (unsigned char *)PORT_ArenaAlloc(arena, 1);
+ if (!rawKey.u.ec.version.data) {
+ goto loser;
+ }
+ rawKey.u.ec.version.data[0] = ecVersion;
+ rawKey.u.ec.version.len = 1;
+
+ if (!ReadAttribute(pk, CKA_VALUE, arena,
+ &rawKey.u.ec.privateValue)) {
+ goto loser;
+ }
+
+ keyTemplate = SECKEY_EDPrivateKeyExportTemplate;
+ /* Currently, ED25519 does not support any parameter. */
+ rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, SEC_OID_ED25519_PUBLIC_KEY, NULL);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ } break;
default: {
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
goto loser;