summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/bltest/blapitest.c4
-rw-r--r--cmd/certutil/certutil.c2
-rw-r--r--cmd/certutil/keystuff.c1
-rw-r--r--cmd/ecperf/ecperf.c143
-rwxr-xr-xcmd/ecperf/manifest.mn6
-rw-r--r--cmd/ectest/ectest.c324
-rw-r--r--cmd/ectest/testvecs.h392
-rw-r--r--cmd/fipstest/fipstest.c2
-rw-r--r--lib/cryptohi/keyi.h7
-rw-r--r--lib/cryptohi/keythi.h8
-rw-r--r--lib/cryptohi/manifest.mn3
-rw-r--r--lib/cryptohi/seckey.c61
-rw-r--r--lib/freebl/Makefile34
-rw-r--r--lib/freebl/blapit.h4
-rw-r--r--lib/freebl/ec.c105
-rw-r--r--lib/freebl/ec.h8
-rw-r--r--lib/freebl/ecdecode.c19
-rw-r--r--lib/freebl/ecl/curve25519_32.c390
-rw-r--r--lib/freebl/ecl/curve25519_64.c514
-rw-r--r--lib/freebl/ecl/ecl-curve.h20
-rw-r--r--lib/freebl/ecl/ecl-exp.h5
-rw-r--r--lib/freebl/ecl/ecl-priv.h1
-rw-r--r--lib/freebl/ecl/ecl.h4
-rw-r--r--lib/freebl/ecl/ecp_25519.c120
-rw-r--r--lib/freebl/ecl/tests/ecp_test.c1
-rw-r--r--lib/freebl/ecl/uint128.c87
-rw-r--r--lib/freebl/ecl/uint128.h35
-rw-r--r--lib/freebl/manifest.mn2
-rw-r--r--lib/pk11wrap/pk11akey.c22
-rw-r--r--lib/pk11wrap/pk11skey.c21
-rw-r--r--lib/softoken/pkcs11.c28
-rw-r--r--lib/softoken/pkcs11c.c12
-rw-r--r--lib/ssl/ssl3ecc.c1
-rw-r--r--lib/util/eccutil.h14
-rw-r--r--lib/util/manifest.mn1
-rw-r--r--lib/util/secoid.c8
-rw-r--r--lib/util/secoidt.h2
-rwxr-xr-xtests/ec/ecperf.sh1
-rw-r--r--tests/ec/ectest.sh2
39 files changed, 2081 insertions, 333 deletions
diff --git a/cmd/bltest/blapitest.c b/cmd/bltest/blapitest.c
index b231b0f3f..9d9dbef0a 100644
--- a/cmd/bltest/blapitest.c
+++ b/cmd/bltest/blapitest.c
@@ -159,7 +159,7 @@ Usage()
PRINTUSAGE("", "", " c2onb239v4, c2onb239v5, c2pnb272w1, c2pnb304w1,");
PRINTUSAGE("", "", " c2tnb359w1, c2pnb368w1, c2tnb431r1, secp112r1,");
PRINTUSAGE("", "", " secp112r2, secp128r1, secp128r2, sect113r1, sect113r2,");
- PRINTUSAGE("", "", " sect131r1, sect131r2");
+ PRINTUSAGE("", "", " sect131r1, sect131r2, curve25519");
#endif
PRINTUSAGE("", "-p", "do performance test");
PRINTUSAGE("", "-4", "run test in multithread mode. th_num number of parallel threads");
@@ -496,6 +496,7 @@ static CurveNameTagPair nameTagPair[] =
{ "sect113r2", SEC_OID_SECG_EC_SECT113R2 },
{ "sect131r1", SEC_OID_SECG_EC_SECT131R1 },
{ "sect131r2", SEC_OID_SECG_EC_SECT131R2 },
+ { "curve25519", SEC_OID_CURVE25519 },
};
static SECItem *
@@ -1887,6 +1888,7 @@ bltest_ecdsa_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
pubkey->ecParams.DEREncoding.len = key->ecParams.DEREncoding.len;
pubkey->ecParams.DEREncoding.data = key->ecParams.DEREncoding.data;
pubkey->ecParams.name = key->ecParams.name;
+ pubkey->ecParams.pointSize = key->ecParams.pointSize;
pubkey->publicValue.len = key->publicValue.len;
pubkey->publicValue.data = key->publicValue.data;
asymk->pubKey = pubkey;
diff --git a/cmd/certutil/certutil.c b/cmd/certutil/certutil.c
index 08ecac6f2..3cb5277fe 100644
--- a/cmd/certutil/certutil.c
+++ b/cmd/certutil/certutil.c
@@ -1257,7 +1257,7 @@ luG(enum usage_level ul, const char *command)
#ifndef NSS_DISABLE_ECC
FPS "%-20s Elliptic curve name (ec only)\n",
" -q curve-name");
- FPS "%-20s One of nistp256, nistp384, nistp521\n", "");
+ FPS "%-20s One of nistp256, nistp384, nistp521, curve25519\n", "");
#ifdef NSS_ECC_MORE_THAN_SUITE_B
FPS "%-20s sect163k1, nistk163, sect163r1, sect163r2,\n", "");
FPS "%-20s nistb163, sect193r1, sect193r2, sect233k1, nistk233,\n", "");
diff --git a/cmd/certutil/keystuff.c b/cmd/certutil/keystuff.c
index 27a38450b..4c25e4e57 100644
--- a/cmd/certutil/keystuff.c
+++ b/cmd/certutil/keystuff.c
@@ -476,6 +476,7 @@ static CurveNameTagPair nameTagPair[] =
{ "sect113r2", SEC_OID_SECG_EC_SECT113R2 },
{ "sect131r1", SEC_OID_SECG_EC_SECT131R1 },
{ "sect131r2", SEC_OID_SECG_EC_SECT131R2 },
+ { "curve25519", SEC_OID_CURVE25519 },
};
static SECKEYECParams *
diff --git a/cmd/ecperf/ecperf.c b/cmd/ecperf/ecperf.c
index 5adfe99e8..7ee7b48bc 100644
--- a/cmd/ecperf/ecperf.c
+++ b/cmd/ecperf/ecperf.c
@@ -86,7 +86,8 @@ static SECOidTag ecCurve_oid_map[] = {
SEC_OID_UNKNOWN, /* ECCurve_WTLS_1 */
SEC_OID_UNKNOWN, /* ECCurve_WTLS_8 */
SEC_OID_UNKNOWN, /* ECCurve_WTLS_9 */
- SEC_OID_UNKNOWN /* ECCurve_pastLastCurve */
+ SEC_OID_CURVE25519,
+ SEC_OID_UNKNOWN /* ECCurve_pastLastCurve */
};
typedef SECStatus (*op_func)(void *, void *, void *);
@@ -258,20 +259,37 @@ M_TimeOperation(void (*threadFunc)(void *),
}
/* Test curve using specific field arithmetic. */
-#define ECTEST_NAMED_GFP(name_c, name_v) \
- if (usefreebl) { \
- printf("Testing %s using freebl implementation...\n", name_c); \
- rv = ectest_curve_freebl(name_v, iterations, numThreads); \
- if (rv != SECSuccess) \
- goto cleanup; \
- printf("... okay.\n"); \
- } \
- if (usepkcs11) { \
- printf("Testing %s using pkcs11 implementation...\n", name_c); \
- rv = ectest_curve_pkcs11(name_v, iterations, numThreads); \
- if (rv != SECSuccess) \
- goto cleanup; \
- printf("... okay.\n"); \
+#define ECTEST_NAMED_GFP(name_c, name_v) \
+ if (usefreebl) { \
+ printf("Testing %s using freebl implementation...\n", name_c); \
+ rv = ectest_curve_freebl(name_v, iterations, numThreads, ec_field_GFp); \
+ if (rv != SECSuccess) \
+ goto cleanup; \
+ printf("... okay.\n"); \
+ } \
+ if (usepkcs11) { \
+ printf("Testing %s using pkcs11 implementation...\n", name_c); \
+ rv = ectest_curve_pkcs11(name_v, iterations, numThreads); \
+ if (rv != SECSuccess) \
+ goto cleanup; \
+ printf("... okay.\n"); \
+ }
+
+/* Test curve using specific field arithmetic. */
+#define ECTEST_NAMED_CUSTOM(name_c, name_v) \
+ if (usefreebl) { \
+ printf("Testing %s using freebl implementation...\n", name_c); \
+ rv = ectest_curve_freebl(name_v, iterations, numThreads, ec_field_plain); \
+ if (rv != SECSuccess) \
+ goto cleanup; \
+ printf("... okay.\n"); \
+ } \
+ if (usepkcs11) { \
+ printf("Testing %s using pkcs11 implementation...\n", name_c); \
+ rv = ectest_curve_pkcs11(name_v, iterations, numThreads); \
+ if (rv != SECSuccess) \
+ goto cleanup; \
+ printf("... okay.\n"); \
}
/*
@@ -510,29 +528,34 @@ ectest_curve_pkcs11(ECCurveName curve, int iterations, int numThreads)
lock = PR_NewLock();
- rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Derive, "ECDH_Derive",
- &ecPriv, &mech, NULL, iterations, numThreads,
- lock, session, 0, &deriveRate);
- if (rv != SECSuccess) {
- goto cleanup;
- }
- rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Sign, "ECDSA_Sign",
- (void *)&ecPriv, &sig, &digest, iterations, numThreads,
- lock, session, 1, &signRate);
- if (rv != SECSuccess) {
- goto cleanup;
- }
- printf(" ECDHE max rate = %.2f\n", (deriveRate + signRate) / 4.0);
- /* get a signature */
- rv = PKCS11_Sign(session, &ecPriv, &sig, &digest);
- if (rv != SECSuccess) {
- goto cleanup;
+ if (ecCurve_map[curve]->usage & KU_KEY_AGREEMENT) {
+ rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Derive, "ECDH_Derive",
+ &ecPriv, &mech, NULL, iterations, numThreads,
+ lock, session, 0, &deriveRate);
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
}
- rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Verify, "ECDSA_Verify",
- (void *)&ecPub, &sig, &digest, iterations, numThreads,
- lock, session, 0, NULL);
- if (rv != SECSuccess) {
- goto cleanup;
+
+ if (ecCurve_map[curve]->usage & KU_DIGITAL_SIGNATURE) {
+ rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Sign, "ECDSA_Sign",
+ (void *)&ecPriv, &sig, &digest, iterations, numThreads,
+ lock, session, 1, &signRate);
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
+ printf(" ECDHE max rate = %.2f\n", (deriveRate + signRate) / 4.0);
+ /* get a signature */
+ rv = PKCS11_Sign(session, &ecPriv, &sig, &digest);
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
+ rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Verify, "ECDSA_Verify",
+ (void *)&ecPub, &sig, &digest, iterations, numThreads,
+ lock, session, 0, NULL);
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
}
cleanup:
@@ -562,7 +585,8 @@ ECDH_DeriveWrap(ECPrivateKey *priv, ECPublicKey *pub, int *dummy)
* If tests fail, then it prints an error message, aborts, and returns an
* error code. Otherwise, returns 0. */
SECStatus
-ectest_curve_freebl(ECCurveName curve, int iterations, int numThreads)
+ectest_curve_freebl(ECCurveName curve, int iterations, int numThreads,
+ ECFieldType fieldType)
{
ECParams ecParams = { 0 };
ECPrivateKey *ecPriv = NULL;
@@ -594,9 +618,10 @@ ectest_curve_freebl(ECCurveName curve, int iterations, int numThreads)
ecParams.curve.seed.len = 0;
ecParams.DEREncoding.data = NULL;
ecParams.DEREncoding.len = 0;
+ ecParams.pointSize = ecCurve_map[curve]->pointSize;
ecParams.fieldID.size = ecCurve_map[curve]->size;
- ecParams.fieldID.type = ec_field_GFp;
+ ecParams.fieldID.type = fieldType;
hexString2SECItem(arena, &ecParams.fieldID.u.prime, ecCurve_map[curve]->irr);
hexString2SECItem(arena, &ecParams.curve.a, ecCurve_map[curve]->curvea);
hexString2SECItem(arena, &ecParams.curve.b, ecCurve_map[curve]->curveb);
@@ -622,24 +647,29 @@ ectest_curve_freebl(ECCurveName curve, int iterations, int numThreads)
ecPub.ecParams = ecParams;
ecPub.publicValue = ecPriv->publicValue;
- rv = M_TimeOperation(genericThread, (op_func)ECDH_DeriveWrap, "ECDH_Derive",
- ecPriv, &ecPub, NULL, iterations, numThreads, 0, 0, 0, &deriveRate);
- if (rv != SECSuccess) {
- goto cleanup;
- }
- rv = M_TimeOperation(genericThread, (op_func)ECDSA_SignDigest, "ECDSA_Sign",
- ecPriv, &sig, &digest, iterations, numThreads, 0, 0, 1, &signRate);
- if (rv != SECSuccess)
- goto cleanup;
- printf(" ECDHE max rate = %.2f\n", (deriveRate + signRate) / 4.0);
- rv = ECDSA_SignDigest(ecPriv, &sig, &digest);
- if (rv != SECSuccess) {
- goto cleanup;
+ if (ecCurve_map[curve]->usage & KU_KEY_AGREEMENT) {
+ rv = M_TimeOperation(genericThread, (op_func)ECDH_DeriveWrap, "ECDH_Derive",
+ ecPriv, &ecPub, NULL, iterations, numThreads, 0, 0, 0, &deriveRate);
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
}
- rv = M_TimeOperation(genericThread, (op_func)ECDSA_VerifyDigest, "ECDSA_Verify",
- &ecPub, &sig, &digest, iterations, numThreads, 0, 0, 0, NULL);
- if (rv != SECSuccess) {
- goto cleanup;
+
+ if (ecCurve_map[curve]->usage & KU_DIGITAL_SIGNATURE) {
+ rv = M_TimeOperation(genericThread, (op_func)ECDSA_SignDigest, "ECDSA_Sign",
+ ecPriv, &sig, &digest, iterations, numThreads, 0, 0, 1, &signRate);
+ if (rv != SECSuccess)
+ goto cleanup;
+ printf(" ECDHE max rate = %.2f\n", (deriveRate + signRate) / 4.0);
+ rv = ECDSA_SignDigest(ecPriv, &sig, &digest);
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
+ rv = M_TimeOperation(genericThread, (op_func)ECDSA_VerifyDigest, "ECDSA_Verify",
+ &ecPub, &sig, &digest, iterations, numThreads, 0, 0, 0, NULL);
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
}
cleanup:
@@ -743,6 +773,7 @@ main(int argv, char **argc)
ECTEST_NAMED_GFP("NIST-P256", ECCurve_NIST_P256);
ECTEST_NAMED_GFP("NIST-P384", ECCurve_NIST_P384);
ECTEST_NAMED_GFP("NIST-P521", ECCurve_NIST_P521);
+ ECTEST_NAMED_CUSTOM("Curve25519", ECCurve25519);
}
#ifdef NSS_ECC_MORE_THAN_SUITE_B
if (ansi) {
diff --git a/cmd/ecperf/manifest.mn b/cmd/ecperf/manifest.mn
index 2931a11ad..96cdc5ac8 100755
--- a/cmd/ecperf/manifest.mn
+++ b/cmd/ecperf/manifest.mn
@@ -11,12 +11,6 @@ MODULE = nss
INCLUDES += -I$(CORE_DEPTH)/nss/lib/softoken
-# This next line is used by .mk files
-# and gets translated into $LINCS in manifest.mnw
-REQUIRES = dbm seccmd
-
-# DIRS =
-
CSRCS = ecperf.c
PROGRAM = ecperf
diff --git a/cmd/ectest/ectest.c b/cmd/ectest/ectest.c
index 545fbddcd..a6a9669c6 100644
--- a/cmd/ectest/ectest.c
+++ b/cmd/ectest/ectest.c
@@ -5,22 +5,31 @@
#include "blapi.h"
#include "ec.h"
#include "ecl-curve.h"
-#include "prprf.h"
-#include "basicutil.h"
-#include "secder.h"
+#include "nss.h"
+#include "secutil.h"
#include "secitem.h"
#include "nspr.h"
+#include "pk11pub.h"
#include <stdio.h>
typedef struct {
ECCurveName curve;
+ int iterations;
char *privhex;
char *our_pubhex;
char *their_pubhex;
char *common_key;
char *name;
+ ECFieldType fieldType;
} ECDH_KAT;
+typedef struct {
+ ECCurveName curve;
+ char *point;
+ char *name;
+ ECFieldType fieldType;
+} ECDH_BAD;
+
#include "testvecs.h"
/*
@@ -69,6 +78,50 @@ hexString2SECItem(PLArenaPool *arena, SECItem *item, const char *str)
return item;
}
+void
+printBuf(const SECItem *item)
+{
+ int i;
+ if (!item || !item->len) {
+ printf("(null)\n");
+ return;
+ }
+
+ for (i = 0; i < item->len; i++) {
+ printf("%02x", item->data[i]);
+ }
+ printf("\n");
+}
+
+/* Initialise test with basic curve populate with only the necessary things */
+SECStatus
+init_params(ECParams *ecParams, ECCurveName curve, PLArenaPool **arena,
+ ECFieldType type)
+{
+ if ((curve < ECCurve_noName) || (curve > ECCurve_pastLastCurve)) {
+ return SECFailure;
+ }
+ *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!*arena) {
+ return SECFailure;
+ }
+ ecParams->name = curve;
+ ecParams->type = ec_params_named;
+ ecParams->curveOID.data = NULL;
+ ecParams->curveOID.len = 0;
+ ecParams->curve.seed.data = NULL;
+ ecParams->curve.seed.len = 0;
+ ecParams->DEREncoding.data = NULL;
+ ecParams->DEREncoding.len = 0;
+ ecParams->arena = *arena;
+ ecParams->fieldID.size = ecCurve_map[curve]->size;
+ ecParams->fieldID.type = type;
+ ecParams->cofactor = ecCurve_map[curve]->cofactor;
+ ecParams->pointSize = ecCurve_map[curve]->pointSize;
+
+ return SECSuccess;
+}
+
SECStatus
ectest_ecdh_kat(ECDH_KAT *kat)
{
@@ -77,33 +130,19 @@ ectest_ecdh_kat(ECDH_KAT *kat)
ECPrivateKey *ecPriv = NULL;
SECItem theirKey = { siBuffer, NULL, 0 };
SECStatus rv = SECFailure;
- PLArenaPool *arena;
+ PLArenaPool *arena = NULL;
SECItem seed = { siBuffer, NULL, 0 };
SECItem answer = { siBuffer, NULL, 0 };
SECItem answer2 = { siBuffer, NULL, 0 };
SECItem derived = { siBuffer, NULL, 0 };
char genenc[3 + 2 * 2 * MAX_ECKEY_LEN];
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (!arena) {
- return SECFailure;
- }
+ int i;
- if ((curve < ECCurve_noName) || (curve > ECCurve_pastLastCurve)) {
- PORT_FreeArena(arena, PR_FALSE);
- return SECFailure;
+ rv = init_params(&ecParams, curve, &arena, kat->fieldType);
+ if (rv != SECSuccess) {
+ return rv;
}
- ecParams.name = curve;
- ecParams.type = ec_params_named;
- ecParams.curveOID.data = NULL;
- ecParams.curveOID.len = 0;
- ecParams.curve.seed.data = NULL;
- ecParams.curve.seed.len = 0;
- ecParams.DEREncoding.data = NULL;
- ecParams.DEREncoding.len = 0;
-
- ecParams.fieldID.size = ecCurve_map[curve]->size;
- ecParams.fieldID.type = ec_field_GFp;
hexString2SECItem(arena, &ecParams.fieldID.u.prime, ecCurve_map[curve]->irr);
hexString2SECItem(arena, &ecParams.curve.a, ecCurve_map[curve]->curvea);
hexString2SECItem(arena, &ecParams.curve.b, ecCurve_map[curve]->curveb);
@@ -114,39 +153,165 @@ ectest_ecdh_kat(ECDH_KAT *kat)
strcat(genenc, ecCurve_map[curve]->geny);
hexString2SECItem(arena, &ecParams.base, genenc);
hexString2SECItem(arena, &ecParams.order, ecCurve_map[curve]->order);
- ecParams.cofactor = ecCurve_map[curve]->cofactor;
- hexString2SECItem(arena, &answer, kat->our_pubhex);
+ if (kat->our_pubhex) {
+ hexString2SECItem(arena, &answer, kat->our_pubhex);
+ }
hexString2SECItem(arena, &seed, kat->privhex);
rv = EC_NewKeyFromSeed(&ecParams, &ecPriv, seed.data, seed.len);
if (rv != SECSuccess) {
rv = SECFailure;
goto cleanup;
}
- if (SECITEM_CompareItem(&answer, &ecPriv->publicValue) != SECEqual) {
- rv = SECFailure;
- goto cleanup;
+ if (kat->our_pubhex) {
+ if (SECITEM_CompareItem(&answer, &ecPriv->publicValue) != SECEqual) {
+ rv = SECFailure;
+ goto cleanup;
+ }
}
hexString2SECItem(arena, &theirKey, kat->their_pubhex);
hexString2SECItem(arena, &answer2, kat->common_key);
- rv = ECDH_Derive(&theirKey, &ecParams, &ecPriv->privateValue, PR_TRUE, &derived);
+
+ rv = EC_ValidatePublicKey(&ecParams, &theirKey);
if (rv != SECSuccess) {
- rv = SECFailure;
+ printf("EC_ValidatePublicKey failed\n");
goto cleanup;
}
- if (SECITEM_CompareItem(&answer2, &derived) != SECEqual) {
+ for (i = 0; i < kat->iterations; ++i) {
+ rv = ECDH_Derive(&theirKey, &ecParams, &ecPriv->privateValue, PR_TRUE, &derived);
+ if (rv != SECSuccess) {
+ rv = SECFailure;
+ goto cleanup;
+ }
+ SECITEM_CopyItem(ecParams.arena, &theirKey, &ecPriv->privateValue);
+ SECITEM_CopyItem(ecParams.arena, &ecPriv->privateValue, &derived);
+ SECITEM_FreeItem(&derived, PR_FALSE);
+ }
+
+ if (SECITEM_CompareItem(&answer2, &ecPriv->privateValue) != SECEqual) {
+ printf("expected: ");
+ printBuf(&answer2);
+ printf("derived: ");
+ printBuf(&ecPriv->privateValue);
rv = SECFailure;
goto cleanup;
}
+
cleanup:
PORT_FreeArena(arena, PR_FALSE);
- PORT_FreeArena(ecPriv->ecParams.arena, PR_FALSE);
+ if (ecPriv) {
+ PORT_FreeArena(ecPriv->ecParams.arena, PR_FALSE);
+ }
SECITEM_FreeItem(&derived, PR_FALSE);
return rv;
}
+void
+PrintKey(PK11SymKey *symKey)
+{
+ char *name = PK11_GetSymKeyNickname(symKey);
+ int len = PK11_GetKeyLength(symKey);
+ int strength = PK11_GetKeyStrength(symKey, NULL);
+ SECItem *value = NULL;
+ CK_KEY_TYPE type = PK11_GetSymKeyType(symKey);
+ (void)PK11_ExtractKeyValue(symKey);
+
+ value = PK11_GetKeyData(symKey);
+ printf("%s %3d %4d %s ", name ? name : "no-name", len, strength,
+ type == CKK_GENERIC_SECRET ? "generic" : "ERROR! UNKNOWN KEY TYPE");
+ printBuf(value);
+
+ PORT_Free(name);
+}
+
+SECStatus
+ectest_curve_pkcs11(SECOidTag oid)
+{
+ SECKEYECParams pk_11_ecParams = { siBuffer, NULL, 0 };
+ SECKEYPublicKey *pubKey = NULL;
+ SECKEYPrivateKey *privKey = NULL;
+ SECOidData *oidData = NULL;
+ CK_MECHANISM_TYPE target = CKM_TLS12_MASTER_KEY_DERIVE_DH;
+ PK11SymKey *symKey = NULL;
+ SECStatus rv = SECFailure;
+
+ oidData = SECOID_FindOIDByTag(oid);
+ if (oidData == NULL) {
+ printf(" >>> SECOID_FindOIDByTag failed.\n");
+ goto cleanup;
+ }
+ PORT_Assert(oidData->oid.len < 256);
+ SECITEM_AllocItem(NULL, &pk_11_ecParams, (2 + oidData->oid.len));
+ pk_11_ecParams.data[0] = SEC_ASN1_OBJECT_ID; /* we have to prepend 0x06 */
+ pk_11_ecParams.data[1] = oidData->oid.len;
+ memcpy(pk_11_ecParams.data + 2, oidData->oid.data, oidData->oid.len);
+
+ privKey = SECKEY_CreateECPrivateKey(&pk_11_ecParams, &pubKey, NULL);
+ if (!privKey || !pubKey) {
+ printf(" >>> SECKEY_CreateECPrivateKey failed.\n");
+ goto cleanup;
+ }
+
+ symKey = PK11_PubDeriveWithKDF(privKey, pubKey, PR_FALSE, NULL, NULL,
+ CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0,
+ CKD_NULL, NULL, NULL);
+ if (!symKey) {
+ printf(" >>> PK11_PubDeriveWithKDF failed.\n");
+ goto cleanup;
+ }
+ PrintKey(symKey);
+ rv = SECSuccess;
+
+cleanup:
+ if (privKey) {
+ SECKEY_DestroyPrivateKey(privKey);
+ }
+ if (pubKey) {
+ SECKEY_DestroyPublicKey(pubKey);
+ }
+ if (symKey) {
+ PK11_FreeSymKey(symKey);
+ }
+ SECITEM_FreeItem(&pk_11_ecParams, PR_FALSE);
+
+ return rv;
+}
+
+SECStatus
+ectest_validate_point(ECDH_BAD *bad)
+{
+ ECParams ecParams = { 0 };
+ SECItem point = { siBuffer, NULL, 0 };
+ SECStatus rv = SECFailure;
+ PLArenaPool *arena = NULL;
+
+ rv = init_params(&ecParams, bad->curve, &arena, bad->fieldType);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+
+ hexString2SECItem(arena, &point, bad->point);
+ rv = EC_ValidatePublicKey(&ecParams, &point);
+
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+void
+printUsage(char *prog)
+{
+ printf("Usage: %s [-fp] [-nd]\n"
+ "\t-f: usefreebl\n"
+ "\t-p: usepkcs11\n"
+ "\t-n: NIST curves\n"
+ "\t-d: non-NIST curves\n"
+ "You have to specify at least f or p and n or d.\n"
+ "By default no tests are executed.\n",
+ prog);
+}
+
/* Performs tests of elliptic curve cryptography over prime fields If
* tests fail, then it prints an error message, aborts, and returns an
* error code. Otherwise, returns 0. */
@@ -156,28 +321,101 @@ main(int argv, char **argc)
SECStatus rv = SECSuccess;
int numkats = 0;
int i = 0;
+ int usepkcs11 = 0;
+ int usefreebl = 0;
+ int nist = 0;
+ int nonnist = 0;
+ SECOidTag nistOids[3] = { SEC_OID_SECG_EC_SECP256R1,
+ SEC_OID_SECG_EC_SECP384R1,
+ SEC_OID_SECG_EC_SECP521R1 };
- rv = SECOID_Init();
+ for (i = 1; i < argv; i++) {
+ if (PL_strcasecmp(argc[i], "-p") == 0) {
+ usepkcs11 = 1;
+ } else if (PL_strcasecmp(argc[i], "-f") == 0) {
+ usefreebl = 1;
+ } else if (PL_strcasecmp(argc[i], "-n") == 0) {
+ nist = 1;
+ } else if (PL_strcasecmp(argc[i], "-d") == 0) {
+ nonnist = 1;
+ } else {
+ printUsage(argc[0]);
+ return 1;
+ }
+ }
+ if (!(usepkcs11 || usefreebl) || !(nist || nonnist)) {
+ printUsage(argc[0]);
+ return 1;
+ }
+
+ rv = NSS_NoDB_Init(NULL);
if (rv != SECSuccess) {
- SECU_PrintError("Error:", "SECOID_Init");
+ SECU_PrintError("Error:", "NSS_NoDB_Init");
goto cleanup;
}
- while (ecdh_testvecs[numkats].curve != ECCurve_pastLastCurve) {
- numkats++;
+ /* Test P256, P384, P521 */
+ if (usefreebl) {
+ if (nist) {
+ while (ecdh_testvecs[numkats].curve != ECCurve_pastLastCurve) {
+ numkats++;
+ }
+ printf("1..%d\n", numkats);
+ for (i = 0; ecdh_testvecs[i].curve != ECCurve_pastLastCurve; i++) {
+ if (ectest_ecdh_kat(&ecdh_testvecs[i]) != SECSuccess) {
+ printf("not okay %d - %s\n", i + 1, ecdh_testvecs[i].name);
+ rv = SECFailure;
+ } else {
+ printf("okay %d - %s\n", i + 1, ecdh_testvecs[i].name);
+ }
+ }
+ }
+
+ /* Test KAT for non-NIST curves */
+ if (nonnist) {
+ for (i = 0; nonnist_testvecs[i].curve != ECCurve_pastLastCurve; i++) {
+ if (ectest_ecdh_kat(&nonnist_testvecs[i]) != SECSuccess) {
+ printf("not okay %d - %s\n", i + 1, nonnist_testvecs[i].name);
+ rv = SECFailure;
+ } else {
+ printf("okay %d - %s\n", i + 1, nonnist_testvecs[i].name);
+ }
+ }
+ for (i = 0; nonnist_testvecs_bad_values[i].curve != ECCurve_pastLastCurve; i++) {
+ if (ectest_validate_point(&nonnist_testvecs_bad_values[i]) == SECSuccess) {
+ printf("not okay %d - %s\n", i + 1, nonnist_testvecs_bad_values[i].name);
+ rv = SECFailure;
+ } else {
+ printf("okay %d - %s\n", i + 1, nonnist_testvecs_bad_values[i].name);
+ }
+ }
+ }
}
- printf("1..%d\n", numkats);
- for (i = 0; ecdh_testvecs[i].curve != ECCurve_pastLastCurve; i++) {
- rv = ectest_ecdh_kat(&ecdh_testvecs[i]);
- if (rv != SECSuccess) {
- printf("not okay %d - %s\n", i + 1, ecdh_testvecs[i].name);
- } else {
- printf("okay %d - %s\n", i + 1, ecdh_testvecs[i].name);
+
+ /* Test PK11 for non-NIST curves */
+ if (usepkcs11) {
+ if (nonnist) {
+ if (ectest_curve_pkcs11(SEC_OID_CURVE25519) != SECSuccess) {
+ printf("not okay (OID %d) - PK11 test\n", SEC_OID_CURVE25519);
+ rv = SECFailure;
+ } else {
+ printf("okay (OID %d) - PK11 test\n", SEC_OID_CURVE25519);
+ }
+ }
+ if (nist) {
+ for (i = 0; i < 3; ++i) {
+ if (ectest_curve_pkcs11(nistOids[i]) != SECSuccess) {
+ printf("not okay (OID %d) - PK11 test\n", nistOids[i]);
+ rv = SECFailure;
+ } else {
+ printf("okay (OID %d) - PK11 test\n", nistOids[i]);
+ }
+ }
}
}
cleanup:
- rv |= SECOID_Shutdown();
+ rv |= NSS_Shutdown();
if (rv != SECSuccess) {
printf("Error: exiting with error value\n");
diff --git a/cmd/ectest/testvecs.h b/cmd/ectest/testvecs.h
index 3f764406e..e66a2bfb8 100644
--- a/cmd/ectest/testvecs.h
+++ b/cmd/ectest/testvecs.h
@@ -1,405 +1,405 @@
static ECDH_KAT ecdh_testvecs[] = {
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534",
"04ead218590119e8876b29146ff89ca61770c4edbbf97d38ce385ed281d8a6b23028af61281fd35e2fa7002523acc85a429cb06ee6648325389f59edfce1405141",
"04700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac",
"46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b",
- "curve: P256 vector: 0" },
+ "curve: P256 vector: 0", ec_field_GFp },
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"38f65d6dce47676044d58ce5139582d568f64bb16098d179dbab07741dd5caf5",
"04119f2f047902782ab0c9e27a54aff5eb9b964829ca99c06b02ddba95b0a3f6d08f52b726664cac366fc98ac7a012b2682cbd962e5acb544671d41b9445704d1d",
"04809f04289c64348c01515eb03d5ce7ac1a8cb9498f5caa50197e58d43a86a7aeb29d84e811197f25eba8f5194092cb6ff440e26d4421011372461f579271cda3",
"057d636096cb80b67a8c038c890e887d1adfa4195e9b3ce241c8a778c59cda67",
- "curve: P256 vector: 1" },
+ "curve: P256 vector: 1", ec_field_GFp },
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"1accfaf1b97712b85a6f54b148985a1bdc4c9bec0bd258cad4b3d603f49f32c8",
"04d9f2b79c172845bfdb560bbb01447ca5ecc0470a09513b6126902c6b4f8d1051f815ef5ec32128d3487834764678702e64e164ff7315185e23aff5facd96d7bc",
"04a2339c12d4a03c33546de533268b4ad667debf458b464d77443636440ee7fec3ef48a3ab26e20220bcda2c1851076839dae88eae962869a497bf73cb66faf536",
"2d457b78b4614132477618a5b077965ec90730a8c81a1c75d6d4ec68005d67ec",
- "curve: P256 vector: 2" },
+ "curve: P256 vector: 2", ec_field_GFp },
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"207c43a79bfee03db6f4b944f53d2fb76cc49ef1c9c4d34d51b6c65c4db6932d",
"0424277c33f450462dcb3d4801d57b9ced05188f16c28eda873258048cd1607e0dc4789753e2b1f63b32ff014ec42cd6a69fac81dfe6d0d6fd4af372ae27c46f88",
"04df3989b9fa55495719b3cf46dccd28b5153f7808191dd518eff0c3cff2b705ed422294ff46003429d739a33206c8752552c8ba54a270defc06e221e0feaf6ac4",
"96441259534b80f6aee3d287a6bb17b5094dd4277d9e294f8fe73e48bf2a0024",
- "curve: P256 vector: 3" },
+ "curve: P256 vector: 3", ec_field_GFp },
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"59137e38152350b195c9718d39673d519838055ad908dd4757152fd8255c09bf",
"04a8c5fdce8b62c5ada598f141adb3b26cf254c280b2857a63d2ad783a73115f6b806e1aafec4af80a0d786b3de45375b517a7e5b51ffb2c356537c9e6ef227d4a",
"0441192d2813e79561e6a1d6f53c8bc1a433a199c835e141b05a74a97b0faeb9221af98cc45e98a7e041b01cf35f462b7562281351c8ebf3ffa02e33a0722a1328",
"19d44c8d63e8e8dd12c22a87b8cd4ece27acdde04dbf47f7f27537a6999a8e62",
- "curve: P256 vector: 4" },
+ "curve: P256 vector: 4", ec_field_GFp },
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"f5f8e0174610a661277979b58ce5c90fee6c9b3bb346a90a7196255e40b132ef",
"047b861dcd2844a5a8363f6b8ef8d493640f55879217189d80326aad9480dfc149c4675b45eeb306405f6c33c38bc69eb2bdec9b75ad5af4706aab84543b9cc63a",
"0433e82092a0f1fb38f5649d5867fba28b503172b7035574bf8e5b7100a3052792f2cf6b601e0a05945e335550bf648d782f46186c772c0f20d3cd0d6b8ca14b2f",
"664e45d5bba4ac931cd65d52017e4be9b19a515f669bea4703542a2c525cd3d3",
- "curve: P256 vector: 5" },
+ "curve: P256 vector: 5", ec_field_GFp },
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"3b589af7db03459c23068b64f63f28d3c3c6bc25b5bf76ac05f35482888b5190",
"049fb38e2d58ea1baf7622e96720101cae3cde4ba6c1e9fa26d9b1de0899102863d5561b900406edf50802dd7d73e89395f8aed72fba0e1d1b61fe1d22302260f0",
"046a9e0c3f916e4e315c91147be571686d90464e8bf981d34a90b6353bca6eeba740f9bead39c2f2bcc2602f75b8a73ec7bdffcbcead159d0174c6c4d3c5357f05",
"ca342daa50dc09d61be7c196c85e60a80c5cb04931746820be548cdde055679d",
- "curve: P256 vector: 6" },
+ "curve: P256 vector: 6", ec_field_GFp },
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"d8bf929a20ea7436b2461b541a11c80e61d826c0a4c9d322b31dd54e7f58b9c8",
"0420f07631e4a6512a89ad487c4e9d63039e579cb0d7a556cb9e661cd59c1e7fa46de91846b3eee8a5ec09c2ab1f41e21bd83620ccdd1bdce3ab7ea6e02dd274f5",
"04a9c0acade55c2a73ead1a86fb0a9713223c82475791cd0e210b046412ce224bbf6de0afa20e93e078467c053d241903edad734c6b403ba758c2b5ff04c9d4229",
"35aa9b52536a461bfde4e85fc756be928c7de97923f0416c7a3ac8f88b3d4489",
- "curve: P256 vector: 7" },
+ "curve: P256 vector: 7", ec_field_GFp },
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"0f9883ba0ef32ee75ded0d8bda39a5146a29f1f2507b3bd458dbea0b2bb05b4d",
"04abb61b423be5d6c26e21c605832c9142dc1dfe5a5fff28726737936e6fbf516d733d2513ef58beab202090586fac91bf0fee31e80ab33473ab23a2d89e58fad6",
"0494e94f16a98255fff2b9ac0c9598aac35487b3232d3231bd93b7db7df36f9eb9d8049a43579cfa90b8093a94416cbefbf93386f15b3f6e190b6e3455fedfe69a",
"605c16178a9bc875dcbff54d63fe00df699c03e8a888e9e94dfbab90b25f39b4",
- "curve: P256 vector: 8" },
+ "curve: P256 vector: 8", ec_field_GFp },
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"2beedb04b05c6988f6a67500bb813faf2cae0d580c9253b6339e4a3337bb6c08",
"043d63e429cb5fa895a9247129bf4e48e89f35d7b11de8158efeb3e106a2a873950cae9e477ef41e7c8c1064379bb7b554ddcbcae79f9814281f1e50f0403c61f3",
"04e099bf2a4d557460b5544430bbf6da11004d127cb5d67f64ab07c94fcdf5274fd9c50dbe70d714edb5e221f4e020610eeb6270517e688ca64fb0e98c7ef8c1c5",
"f96e40a1b72840854bb62bc13c40cc2795e373d4e715980b261476835a092e0b",
- "curve: P256 vector: 9" },
+ "curve: P256 vector: 9", ec_field_GFp },
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"77c15dcf44610e41696bab758943eff1409333e4d5a11bbe72c8f6c395e9f848",
"04ad5d13c3db508ddcd38457e5991434a251bed49cf5ddcb59cdee73865f138c9f62cec1e70588aa4fdfc7b9a09daa678081c04e1208b9d662b8a2214bf8e81a21",
"04f75a5fe56bda34f3c1396296626ef012dc07e4825838778a645c8248cff0165833bbdf1b1772d8059df568b061f3f1122f28a8d819167c97be448e3dc3fb0c3c",
"8388fa79c4babdca02a8e8a34f9e43554976e420a4ad273c81b26e4228e9d3a3",
- "curve: P256 vector: 10" },
+ "curve: P256 vector: 10", ec_field_GFp },
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"42a83b985011d12303db1a800f2610f74aa71cdf19c67d54ce6c9ed951e9093e",
"04ab48caa61ea35f13f8ed07ffa6a13e8db224dfecfae1a7df8b1bb6ebaf0cb97d1274530ca2c385a3218bddfbcbf0b4024c9badd5243bff834ebff24a8618dccb",
"042db4540d50230756158abf61d9835712b6486c74312183ccefcaef2797b7674d62f57f314e3f3495dc4e099012f5e0ba71770f9660a1eada54104cdfde77243e",
"72877cea33ccc4715038d4bcbdfe0e43f42a9e2c0c3b017fc2370f4b9acbda4a",
- "curve: P256 vector: 11" },
+ "curve: P256 vector: 11", ec_field_GFp },
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"ceed35507b5c93ead5989119b9ba342cfe38e6e638ba6eea343a55475de2800b",
"049a8cd9bd72e71752df91440f77c547509a84df98114e7de4f26cdb39234a625dd07cfc84c8e144fab2839f5189bb1d7c88631d579bbc58012ed9a2327da52f62",
"04cd94fc9497e8990750309e9a8534fd114b0a6e54da89c4796101897041d14ecbc3def4b5fe04faee0a11932229fff563637bfdee0e79c6deeaf449f85401c5c4",
"e4e7408d85ff0e0e9c838003f28cdbd5247cdce31f32f62494b70e5f1bc36307",
- "curve: P256 vector: 12" },
+ "curve: P256 vector: 12", ec_field_GFp },
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"43e0e9d95af4dc36483cdd1968d2b7eeb8611fcce77f3a4e7d059ae43e509604",
"04f989cf8ee956a82e7ebd9881cdbfb2fd946189b08db53559bc8cfdd48071eb145eff28f1a18a616b04b7d337868679f6dd84f9a7b3d7b6f8af276c19611a541d",
"0415b9e467af4d290c417402e040426fe4cf236bae72baa392ed89780dfccdb471cdf4e9170fb904302b8fd93a820ba8cc7ed4efd3a6f2d6b05b80b2ff2aee4e77",
"ed56bcf695b734142c24ecb1fc1bb64d08f175eb243a31f37b3d9bb4407f3b96",
- "curve: P256 vector: 13" },
+ "curve: P256 vector: 13", ec_field_GFp },
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"b2f3600df3368ef8a0bb85ab22f41fc0e5f4fdd54be8167a5c3cd4b08db04903",
"0469c627625b36a429c398b45c38677cb35d8beb1cf78a571e40e99fe4eac1cd4e81690112b0a88f20f7136b28d7d47e5fbc2ada3c8edd87589bc19ec9590637bd",
"0449c503ba6c4fa605182e186b5e81113f075bc11dcfd51c932fb21e951eee2fa18af706ff0922d87b3f0c5e4e31d8b259aeb260a9269643ed520a13bb25da5924",
"bc5c7055089fc9d6c89f83c1ea1ada879d9934b2ea28fcf4e4a7e984b28ad2cf",
- "curve: P256 vector: 14" },
+ "curve: P256 vector: 14", ec_field_GFp },
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"4002534307f8b62a9bf67ff641ddc60fef593b17c3341239e95bdb3e579bfdc8",
"045fe964671315a18aa68a2a6e3dd1fde7e23b8ce7181471cfac43c99e1ae80262d5827be282e62c84de531b963884ba832db5d6b2c3a256f0e604fe7e6b8a7f72",
"0419b38de39fdd2f70f7091631a4f75d1993740ba9429162c2a45312401636b29c09aed7232b28e060941741b6828bcdfa2bc49cc844f3773611504f82a390a5ae",
"9a4e8e657f6b0e097f47954a63c75d74fcba71a30d83651e3e5a91aa7ccd8343",
- "curve: P256 vector: 15" },
+ "curve: P256 vector: 15", ec_field_GFp },
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"4dfa12defc60319021b681b3ff84a10a511958c850939ed45635934ba4979147",
"04c9b2b8496f1440bd4a2d1e52752fd372835b364885e154a7dac49295f281ec7cfbe6b926a8a4de26ccc83b802b1212400754be25d9f3eeaf008b09870ae76321",
"042c91c61f33adfe9311c942fdbff6ba47020feff416b7bb63cec13faf9b0999546cab31b06419e5221fca014fb84ec870622a1b12bab5ae43682aa7ea73ea08d0",
"3ca1fc7ad858fb1a6aba232542f3e2a749ffc7203a2374a3f3d3267f1fc97b78",
- "curve: P256 vector: 16" },
+ "curve: P256 vector: 16", ec_field_GFp },
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"1331f6d874a4ed3bc4a2c6e9c74331d3039796314beee3b7152fcdba5556304e",
"0459e1e101521046ad9cf1d082e9d2ec7dd22530cce064991f1e55c5bcf5fcb591482f4f673176c8fdaa0bb6e59b15a3e47454e3a04297d3863c9338d98add1f37",
"04a28a2edf58025668f724aaf83a50956b7ac1cfbbff79b08c3bf87dfd2828d767dfa7bfffd4c766b86abeaf5c99b6e50cb9ccc9d9d00b7ffc7804b0491b67bc03",
"1aaabe7ee6e4a6fa732291202433a237df1b49bc53866bfbe00db96a0f58224f",
- "curve: P256 vector: 17" },
+ "curve: P256 vector: 17", ec_field_GFp },
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"dd5e9f70ae740073ca0204df60763fb6036c45709bf4a7bb4e671412fad65da3",
"0430b9db2e2e977bcdc98cb87dd736cbd8e78552121925cf16e1933657c2fb23146a45028800b81291bce5c2e1fed7ded650620ebbe6050c6f3a7f0dfb4673ab5c",
"04a2ef857a081f9d6eb206a81c4cf78a802bdf598ae380c8886ecd85fdc1ed7644563c4c20419f07bc17d0539fade1855e34839515b892c0f5d26561f97fa04d1a",
"430e6a4fba4449d700d2733e557f66a3bf3d50517c1271b1ddae1161b7ac798c",
- "curve: P256 vector: 18" },
+ "curve: P256 vector: 18", ec_field_GFp },
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"5ae026cfc060d55600717e55b8a12e116d1d0df34af831979057607c2d9c2f76",
"0446c9ebd1a4a3c8c0b6d572b5dcfba12467603208a9cb5d2acfbb733c40cf639146c913a27d044185d38b467ace011e04d4d9bbbb8cb9ae25fa92aaf15a595e86",
"04ccd8a2d86bc92f2e01bce4d6922cf7fe1626aed044685e95e2eebd464505f01fe9ddd583a9635a667777d5b8a8f31b0f79eba12c75023410b54b8567dddc0f38",
"1ce9e6740529499f98d1f1d71329147a33df1d05e4765b539b11cf615d6974d3",
- "curve: P256 vector: 19" },
+ "curve: P256 vector: 19", ec_field_GFp },
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"b601ac425d5dbf9e1735c5e2d5bdb79ca98b3d5be4a2cfd6f2273f150e064d9d",
"047c9e950841d26c8dde8994398b8f5d475a022bc63de7773fcf8d552e01f1ba0acc42b9885c9b3bee0f8d8c57d3a8f6355016c019c4062fa22cff2f209b5cc2e1",
"04c188ffc8947f7301fb7b53e36746097c2134bf9cc981ba74b4e9c4361f595e4ebf7d2f2056e72421ef393f0c0f2b0e00130e3cac4abbcc00286168e85ec55051",
"4690e3743c07d643f1bc183636ab2a9cb936a60a802113c49bb1b3f2d0661660",
- "curve: P256 vector: 20" },
+ "curve: P256 vector: 20", ec_field_GFp },
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"fefb1dda1845312b5fce6b81b2be205af2f3a274f5a212f66c0d9fc33d7ae535",
"0438b54db85500cb20c61056edd3d88b6a9dc26780a047f213a6e1b900f76596eb6387e4e5781571e4eb8ae62991a33b5dc33301c5bc7e125d53794a39160d8fd0",
"04317e1020ff53fccef18bf47bb7f2dd7707fb7b7a7578e04f35b3beed222a0eb609420ce5a19d77c6fe1ee587e6a49fbaf8f280e8df033d75403302e5a27db2ae",
"30c2261bd0004e61feda2c16aa5e21ffa8d7e7f7dbf6ec379a43b48e4b36aeb0",
- "curve: P256 vector: 21" },
+ "curve: P256 vector: 21", ec_field_GFp },
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"334ae0c4693d23935a7e8e043ebbde21e168a7cba3fa507c9be41d7681e049ce",
"043f2bf1589abf3047bf3e54ac9a95379bff95f8f55405f64eca36a7eebe8ffca75212a94e66c5ae9a8991872f66a72723d80ec5b2e925745c456f5371943b3a06",
"0445fb02b2ceb9d7c79d9c2fa93e9c7967c2fa4df5789f9640b24264b1e524fcb15c6e8ecf1f7d3023893b7b1ca1e4d178972ee2a230757ddc564ffe37f5c5a321",
"2adae4a138a239dcd93c243a3803c3e4cf96e37fe14e6a9b717be9599959b11c",
- "curve: P256 vector: 22" },
+ "curve: P256 vector: 22", ec_field_GFp },
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"2c4bde40214fcc3bfc47d4cf434b629acbe9157f8fd0282540331de7942cf09d",
"0429c0807f10cbc42fb45c9989da50681eead716daa7b9e91fd32e062f5eb92ca0ff1d6d1955d7376b2da24fe1163a271659136341bc2eb1195fc706dc62e7f34d",
"04a19ef7bff98ada781842fbfc51a47aff39b5935a1c7d9625c8d323d511c92de6e9c184df75c955e02e02e400ffe45f78f339e1afe6d056fb3245f4700ce606ef",
"2e277ec30f5ea07d6ce513149b9479b96e07f4b6913b1b5c11305c1444a1bc0b",
- "curve: P256 vector: 23" },
+ "curve: P256 vector: 23", ec_field_GFp },
- { ECCurve_NIST_P256,
+ { ECCurve_NIST_P256, 1,
"85a268f9d7772f990c36b42b0a331adc92b5941de0b862d5d89a347cbf8faab0",
"049cf4b98581ca1779453cc816ff28b4100af56cf1bf2e5bc312d83b6b1b21d3337a5504fcac5231a0d12d658218284868229c844a04a3450d6c7381abe080bf3b",
"04356c5a444c049a52fee0adeb7e5d82ae5aa83030bfff31bbf8ce2096cf161c4b57d128de8b2a57a094d1a001e572173f96e8866ae352bf29cddaf92fc85b2f92",
"1e51373bd2c6044c129c436e742a55be2a668a85ae08441b6756445df5493857",
- "curve: P256 vector: 24" },
+ "curve: P256 vector: 24", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"3cc3122a68f0d95027ad38c067916ba0eb8c38894d22e1b15618b6818a661774ad463b205da88cf699ab4d43c9cf98a1",
"049803807f2f6d2fd966cdd0290bd410c0190352fbec7ff6247de1302df86f25d34fe4a97bef60cff548355c015dbb3e5"
"fba26ca69ec2f5b5d9dad20cc9da711383a9dbe34ea3fa5a2af75b46502629ad54dd8b7d73a8abb06a3a3be47d650cc99",
"04a7c76b970c3b5fe8b05d2838ae04ab47697b9eaf52e764592efda27fe7513272734466b400091adbf2d68c58e0c5006"
"6ac68f19f2e1cb879aed43a9969b91a0839c4c38a49749b661efedf243451915ed0905a32b060992b468c64766fc8437a",
"5f9d29dc5e31a163060356213669c8ce132e22f57c9a04f40ba7fcead493b457e5621e766c40a2e3d4d6a04b25e533f1",
- "curve: P384 vector: 0" },
+ "curve: P384 vector: 0", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"92860c21bde06165f8e900c687f8ef0a05d14f290b3f07d8b3a8cc6404366e5d5119cd6d03fb12dc58e89f13df9cd783",
"04ea4018f5a307c379180bf6a62fd2ceceebeeb7d4df063a66fb838aa35243419791f7e2c9d4803c9319aa0eb03c416b"
"6668835a91484f05ef028284df6436fb88ffebabcdd69ab0133e6735a1bcfb37203d10d340a8328a7b68770ca75878a1a6",
"0430f43fcf2b6b00de53f624f1543090681839717d53c7c955d1d69efaf0349b7363acb447240101cbb3af6641ce4b88e0"
"25e46c0c54f0162a77efcc27b6ea792002ae2ba82714299c860857a68153ab62e525ec0530d81b5aa15897981e858757",
"a23742a2c267d7425fda94b93f93bbcc24791ac51cd8fd501a238d40812f4cbfc59aac9520d758cf789c76300c69d2ff",
- "curve: P384 vector: 1" },
+ "curve: P384 vector: 1", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"12cf6a223a72352543830f3f18530d5cb37f26880a0b294482c8a8ef8afad09aa78b7dc2f2789a78c66af5d1cc553853",
"04fcfcea085e8cf74d0dced1620ba8423694f903a219bbf901b0b59d6ac81baad316a242ba32bde85cb248119b852fab6"
"6972e3c68c7ab402c5836f2a16ed451a33120a7750a6039f3ff15388ee622b7065f7122bf6d51aefbc29b37b03404581b",
"041aefbfa2c6c8c855a1a216774550b79a24cda37607bb1f7cc906650ee4b3816d68f6a9c75da6e4242cebfb6652f65180"
"419d28b723ebadb7658fcebb9ad9b7adea674f1da3dc6b6397b55da0f61a3eddacb4acdb14441cb214b04a0844c02fa3",
"3d2e640f350805eed1ff43b40a72b2abed0a518bcebe8f2d15b111b6773223da3c3489121db173d414b5bd5ad7153435",
- "curve: P384 vector: 2" },
+ "curve: P384 vector: 2", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"8dd48063a3a058c334b5cc7a4ce07d02e5ee6d8f1f3c51a1600962cbab462690ae3cd974fb39e40b0e843daa0fd32de1",
"04e38c9846248123c3421861ea4d32669a7b5c3c08376ad28104399494c84ff5efa3894adb2c6cbe8c3c913ef2eec5bd3"
"c9fa84024a1028796df84021f7b6c9d02f0f4bd1a612a03cbf75a0beea43fef8ae84b48c60172aadf09c1ad016d0bf3ce",
"048bc089326ec55b9cf59b34f0eb754d93596ca290fcb3444c83d4de3a5607037ec397683f8cef07eab2fe357eae36c44"
"9d9d16ce8ac85b3f1e94568521aae534e67139e310ec72693526aa2e927b5b322c95a1a033c229cb6770c957cd3148dd7",
"6a42cfc392aba0bfd3d17b7ccf062b91fc09bbf3417612d02a90bdde62ae40c54bb2e56e167d6b70db670097eb8db854",
- "curve: P384 vector: 3" },
+ "curve: P384 vector: 3", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"84ece6cc3429309bd5b23e959793ed2b111ec5cb43b6c18085fcaea9efa0685d98a6262ee0d330ee250bc8a67d0e733f",
"043222063a2997b302ee60ee1961108ff4c7acf1c0ef1d5fb0d164b84bce71c431705cb9aea9a45f5d73806655a058bee"
"3e61fa9e7fbe7cd43abf99596a3d3a039e99fa9dc93b0bdd9cad81966d17eeaf557068afa7c78466bb5b22032d1100fa6",
"04eb952e2d9ac0c20c6cc48fb225c2ad154f53c8750b003fd3b4ed8ed1dc0defac61bcdde02a2bcfee7067d75d342ed2b"
"0f1828205baece82d1b267d0d7ff2f9c9e15b69a72df47058a97f3891005d1fb38858f5603de840e591dfa4f6e7d489e1",
"ce7ba454d4412729a32bb833a2d1fd2ae612d4667c3a900e069214818613447df8c611de66da200db7c375cf913e4405",
- "curve: P384 vector: 4" },
+ "curve: P384 vector: 4", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"68fce2121dc3a1e37b10f1dde309f9e2e18fac47cd1770951451c3484cdb77cb136d00e731260597cc2859601c01a25b",
"04868be0e694841830e424d913d8e7d86b84ee1021d82b0ecf523f09fe89a76c0c95c49f2dfbcf829c1e39709d55efbb"
"3b9195eb183675b40fd92f51f37713317e4a9b4f715c8ab22e0773b1bc71d3a219f05b8116074658ee86b52e36f3897116",
"04441d029e244eb7168d647d4df50db5f4e4974ab3fdaf022aff058b3695d0b8c814cc88da6285dc6df1ac55c55388500"
"3e8025ac23a41d4b1ea2aa46c50c6e479946b59b6d76497cd9249977e0bfe4a6262622f13d42a3c43d66bdbb30403c345",
"ba69f0acdf3e1ca95caaac4ecaf475bbe51b54777efce01ca381f45370e486fe87f9f419b150c61e329a286d1aa265ec",
- "curve: P384 vector: 5" },
+ "curve: P384 vector: 5", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"b1764c54897e7aae6de9e7751f2f37de849291f88f0f91093155b858d1cc32a3a87980f706b86cc83f927bdfdbeae0bd",
"04c371222feaa6770c6f3ea3e0dac9740def4fcf821378b7f91ff937c21e0470f70f3a31d5c6b2912195f10926942b48ae"
"047d6b4d765123563f81116bc665b7b8cc6207830d805fd84da7cb805a65baa7c12fd592d1b5b5e3e65d9672a9ef7662",
"043d4e6bf08a73404accc1629873468e4269e82d90d832e58ad72142639b5a056ad8d35c66c60e8149fac0c797bceb7c2"
"f9b0308dc7f0e6d29f8c277acbc65a21e5adb83d11e6873bc0a07fda0997f482504602f59e10bc5cb476b83d0a4f75e71",
"1a6688ee1d6e59865d8e3ada37781d36bb0c2717eef92e61964d3927cb765c2965ea80f7f63e58c322ba0397faeaf62b",
- "curve: P384 vector: 6" },
+ "curve: P384 vector: 6", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"f0f7a96e70d98fd5a30ad6406cf56eb5b72a510e9f192f50e1f84524dbf3d2439f7287bb36f5aa912a79deaab4adea82",
"0499c8c41cb1ab5e0854a346e4b08a537c1706a61553387c8d94943ab15196d40dbaa55b8210a77a5d00915f2c4ea69e"
"ab5531065bdcf17bfb3cb55a02e41a57c7f694c383ad289f900fbd656c2233a93c92e933e7a26f54cbb56f0ad875c51bb0",
"04f5f6bef1d110da03be0017eac760cc34b24d092f736f237bc7054b3865312a813bcb62d297fb10a4f7abf54708fe2d3d"
"06fdf8d7dc032f4e10010bf19cbf6159321252ff415fb91920d438f24e67e60c2eb0463204679fa356af44cea9c9ebf5",
"d06a568bf2336b90cbac325161be7695eacb2295f599500d787f072612aca313ee5d874f807ddef6c1f023fe2b6e7cd0",
- "curve: P384 vector: 7" },
+ "curve: P384 vector: 7", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"9efb87ddc61d43c482ba66e1b143aef678fbd0d1bebc2000941fabe677fe5b706bf78fce36d100b17cc787ead74bbca2",
"044c34efee8f0c95565d2065d1bbac2a2dd25ae964320eb6bccedc5f3a9b42a881a1afca1bb6b880584fa27b01c193cd9"
"2d8fb01dbf7cd0a3868c26b951f393c3c56c2858cee901f7793ff5d271925d13a41f8e52409f4eba1990f33acb0bac669",
"047cdec77e0737ea37c67b89b7137fe38818010f4464438ee4d1d35a0c488cad3fde2f37d00885d36d3b795b9f93d23a6"
"728c42ee8d6027c56cf979ba4c229fdb01d234944f8ac433650112c3cf0f02844e888a3569dfef7828a8a884589aa055e",
"bb3b1eda9c6560d82ff5bee403339f1e80342338a991344853b56b24f109a4d94b92f654f0425edd4c205903d7586104",
- "curve: P384 vector: 8" },
+ "curve: P384 vector: 8", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"d787a57fde22ec656a0a525cf3c738b30d73af61e743ea90893ecb2d7b622add2f94ee25c2171467afb093f3f84d0018",
"04171546923b87b2cbbad664f01ce932bf09d6a6118168678446bfa9f0938608cb4667a98f4ec8ac1462285c2508f7486"
"2fa41cb4db68ae71f1f8a3e8939dc52c2dec61a83c983beb2a02baf29ec49278088882ed0cf56c74b5c173b552ccf63cf",
"048eeea3a319c8df99fbc29cb55f243a720d95509515ee5cc587a5c5ae22fbbd009e626db3e911def0b99a4f7ae304b1b"
"a73877dc94db9adddc0d9a4b24e8976c22d73c844370e1ee857f8d1b129a3bd5f63f40caf3bd0533e38a5f5777074ff9e",
"1e97b60add7cb35c7403dd884c0a75795b7683fff8b49f9d8672a8206bfdcf0a106b8768f983258c74167422e44e4d14",
- "curve: P384 vector: 9" },
+ "curve: P384 vector: 9", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"83d70f7b164d9f4c227c767046b20eb34dfc778f5387e32e834b1e6daec20edb8ca5bb4192093f543b68e6aeb7ce788b",
"0457cd770f3bbcbe0c78c770eab0b169bc45e139f86378ffae1c2b16966727c2f2eb724572b8f3eb228d130db4ff862c"
"637ec5c8813b685558d83e924f14bc719f6eb7ae0cbb2c474227c5bda88637a4f26c64817929af999592da6f787490332f",
"04a721f6a2d4527411834b13d4d3a33c29beb83ab7682465c6cbaf6624aca6ea58c30eb0f29dd842886695400d7254f20f"
"14ba6e26355109ad35129366d5e3a640ae798505a7fa55a96a36b5dad33de00474f6670f522214dd7952140ab0a7eb68",
"1023478840e54775bfc69293a3cf97f5bc914726455c66538eb5623e218feef7df4befa23e09d77145ad577db32b41f9",
- "curve: P384 vector: 10" },
+ "curve: P384 vector: 10", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"8f558e05818b88ed383d5fca962e53413db1a0e4637eda194f761944cbea114ab9d5da175a7d57882550b0e432f395a9",
"049a2f57f4867ce753d72b0d95195df6f96c1fae934f602efd7b6a54582f556cfa539d89005ca2edac08ad9b72dd1f60b"
"ad9b94ee82da9cc601f346044998ba387aee56404dc6ecc8ab2b590443319d0b2b6176f9d0eac2d44678ed561607d09a9",
"04d882a8505c2d5cb9b8851fc676677bb0087681ad53faceba1738286b45827561e7da37b880276c656cfc38b32ade847"
"e34b314bdc134575654573cffaf40445da2e6aaf987f7e913cd4c3091523058984a25d8f21da8326192456c6a0fa5f60c",
"6ad6b9dc8a6cf0d3691c501cbb967867f6e4bbb764b60dbff8fcff3ed42dbba39d63cf325b4b4078858495ddee75f954",
- "curve: P384 vector: 11" },
+ "curve: P384 vector: 11", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"0f5dee0affa7bbf239d5dff32987ebb7cf84fcceed643e1d3c62d0b3352aec23b6e5ac7fa4105c8cb26126ad2d1892cb",
"0423346bdfbc9d7c7c736e02bdf607671ff6082fdd27334a8bc75f3b23681ebe614d0597dd614fae58677c835a9f0b273"
"b82ba36290d2f94db41479eb45ab4eaf67928a2315138d59eecc9b5285dfddd6714f77557216ea44cc6fc119d8243efaf",
"04815c9d773dbf5fb6a1b86799966247f4006a23c92e68c55e9eaa998b17d8832dd4d84d927d831d4f68dac67c6488219f"
"e79269948b2611484560fd490feec887cb55ef99a4b524880fa7499d6a07283aae2afa33feab97deca40bc606c4d8764",
"cc9e063566d46b357b3fcae21827377331e5e290a36e60cd7c39102b828ae0b918dc5a02216b07fe6f1958d834e42437",
- "curve: P384 vector: 12" },
+ "curve: P384 vector: 12", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"037b633b5b8ba857c0fc85656868232e2febf59578718391b81da8541a00bfe53c30ae04151847f27499f8d7abad8cf4",
"048878ac8a947f7d5cb2b47aad24fbb8210d86126585399a2871f84aa9c5fde3074ae540c6bf82275ca822d0feb862bc7"
"4632f5cd2f900c2711c32f8930728eb647d31edd8d650f9654e7d33e5ed1b475489d08daa30d8cbcba6bfc3b60d9b5a37",
"041c0eeda7a2be000c5bdcda0478aed4db733d2a9e341224379123ad847030f29e3b168fa18e89a3c0fba2a6ce1c28fc3"
"bec8c1c83c118c4dbea94271869f2d868eb65e8b44e21e6f14b0f4d9b38c068daefa27114255b9a41d084cc4a1ad85456",
"deff7f03bd09865baf945e73edff6d5122c03fb561db87dec8662e09bed4340b28a9efe118337bb7d3d4f7f568635ff9",
- "curve: P384 vector: 13" },
+ "curve: P384 vector: 13", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"e3d07106bedcc096e7d91630ffd3094df2c7859db8d7edbb2e37b4ac47f429a637d06a67d2fba33838764ef203464991",
"04e74a1a2b85f1cbf8dbbdf050cf1aff8acb02fda2fb6591f9d3cfe4e79d0ae938a9c1483e7b75f8db24505d65065cdb1"
"81773ee591822f7abaa856a1a60bc0a5203548dbd1cb5025466eff8481bd07614eaa04a16c3db76905913e972a5b6b59d",
"04c95c185e256bf997f30b311548ae7f768a38dee43eeeef43083f3077be70e2bf39ac1d4daf360c514c8c6be623443d1"
"a3e63a663eaf75d8a765ab2b9a35513d7933fa5e26420a5244550ec6c3b6f033b96db2aca3d6ac6aab052ce929595aea5",
"c8b1038f735ad3bb3e4637c3e47eab487637911a6b7950a4e461948329d3923b969e5db663675623611a457fcda35a71",
- "curve: P384 vector: 14" },
+ "curve: P384 vector: 14", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"f3f9b0c65a49a506632c8a45b10f66b5316f9eeb06fae218f2da62333f99905117b141c760e8974efc4af10570635791",
"04a4ad77aa7d86e5361118a6b921710c820721210712f4c347985fdee58aa4effa1e28be80a17b120b139f96300f89b4"
"9b1ddf22e07e03f1560d8f45a480094560dba9fae7f9531130c1b57ebb95982496524f31d3797793396fa823f22bdb4328",
"043497238a7e6ad166df2dac039aa4dac8d17aa925e7c7631eb3b56e3aaa1c545fcd54d2e5985807910fb202b1fc191d2a"
"a49e5c487dcc7aa40a8f234c979446040d9174e3ad357d404d7765183195aed3f913641b90c81a306ebf0d8913861316",
"d337eaa32b9f716b8747b005b97a553c59dab0c51df41a2d49039cdae705aa75c7b9e7bc0b6a0e8c578c902bc4fff23e",
- "curve: P384 vector: 15" },
+ "curve: P384 vector: 15", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"59fce7fad7de28bac0230690c95710c720e528f9a4e54d3a6a8cd5fc5c5f21637031ce1c5b4e3d39647d8dcb9b794664",
"049c43bf971edf09402876ee742095381f78b1bd3aa39b5132af75dbfe7e98bd78bde10fe2e903c2b6379e1deee175a1b"
"0a6c58ecea5a477bb01bd543b339f1cc49f1371a2cda4d46eb4e53e250597942351a99665a122ffea9bde0636c375daf2",
"0490a34737d45b1aa65f74e0bd0659bc118f8e4b774b761944ffa6573c6df4f41dec0d11b697abd934d390871d4b453240"
"9b590719bb3307c149a7817be355d684893a307764b512eeffe07cb699edb5a6ffbf8d6032e6c79d5e93e94212c2aa4e",
"32d292b695a4488e42a7b7922e1ae537d76a3d21a0b2e36875f60e9f6d3e8779c2afb3a413b9dd79ae18e70b47d337c1",
- "curve: P384 vector: 16" },
+ "curve: P384 vector: 16", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"3e49fbf950a424c5d80228dc4bc35e9f6c6c0c1d04440998da0a609a877575dbe437d6a5cedaa2ddd2a1a17fd112aded",
"045a949594228b1a3d6f599eb3db0d06070fbc551c657b58234ba164ce3fe415fa5f3eb823c08dc29b8c341219c77b6b3"
"d2baad447c8c290cfed25edd9031c41d0b76921457327f42db31122b81f337bbf0b1039ec830ce9061a3761953c75e4a8",
"04dda546acfc8f903d11e2e3920669636d44b2068aeb66ff07aa266f0030e1535b0ed0203cb8a460ac990f1394faf22f1"
"d15bbb2597913035faadf413476f4c70f7279769a40c986f470c427b4ee4962abdf8173bbad81874772925fd32f0b159f",
"1220e7e6cad7b25df98e5bbdcc6c0b65ca6c2a50c5ff6c41dca71e475646fd489615979ca92fb4389aeadefde79a24f1",
- "curve: P384 vector: 17" },
+ "curve: P384 vector: 17", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"50ccc1f7076e92f4638e85f2db98e0b483e6e2204c92bdd440a6deea04e37a07c6e72791c190ad4e4e86e01efba84269",
"04756c07df0ce32c839dac9fb4733c9c28b70113a676a7057c38d223f22a3a9095a8d564653af528e04c7e1824be4a651"
"217c2ce6962cbd2a2e066297b39d57dd9bb4680f0191d390f70b4e461419b2972ce68ad46127fdda6c39195774ea86df3",
"04788be2336c52f4454d63ee944b1e49bfb619a08371048e6da92e584eae70bde1f171c4df378bd1f3c0ab03048a237802"
"4673ebd8db604eaf41711748bab2968a23ca4476ce144e728247f08af752929157b5830f1e26067466bdfa8b65145a33",
"793bb9cd22a93cf468faf804a38d12b78cb12189ec679ddd2e9aa21fa9a5a0b049ab16a23574fe04c1c3c02343b91beb",
- "curve: P384 vector: 18" },
+ "curve: P384 vector: 18", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"06f132b71f74d87bf99857e1e4350a594e5fe35533b888552ceccbc0d8923c902e36141d7691e28631b8bc9bafe5e064",
"042a3cc6b8ff5cde926e7e3a189a1bd029c9b586351af8838f4f201cb8f4b70ef3b0da06d352c80fc26baf8f42b784459"
"ebf9985960176da6d23c7452a2954ffcbbcb24249b43019a2a023e0b3dabd461f19ad3e775c364f3f11ad49f3099400d3",
"04d09bb822eb99e38060954747c82bb3278cf96bbf36fece3400f4c873838a40c135eb3babb9293bd1001bf3ecdee7bf2"
"6d416db6e1b87bbb7427788a3b6c7a7ab2c165b1e366f9608df512037584f213a648d47f16ac326e19aae972f63fd76c9",
"012d191cf7404a523678c6fc075de8285b243720a903047708bb33e501e0dbee5bcc40d7c3ef6c6da39ea24d830da1e8",
- "curve: P384 vector: 19" },
+ "curve: P384 vector: 19", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"12048ebb4331ec19a1e23f1a2c773b664ccfe90a28bfb846fc12f81dff44b7443c77647164bf1e9e67fd2c07a6766241",
"04bc18836bc7a9fdf54b5352f37d7528ab8fa8ec544a8c6180511cbfdd49cce377c39e34c031b5240dc9980503ed2f26"
"2c8086cbe338191080f0b7a16c7afc4c7b0326f9ac66f58552ef4bb9d24de3429ed5d3277ed58fcf48f2b5f61326bec6c6",
"0413741262ede5861dad71063dfd204b91ea1d3b7c631df68eb949969527d79a1dc59295ef7d2bca6743e8cd77b04d1"
"b580baaeadc7e19d74a8a04451a135f1be1b02fe299f9dc00bfdf201e83d995c6950bcc1cb89d6f7b30bf54656b9a4da586",
"ad0fd3ddffe8884b9263f3c15fe1f07f2a5a22ffdc7e967085eea45f0cd959f20f18f522763e28bcc925e496a52dda98",
- "curve: P384 vector: 20" },
+ "curve: P384 vector: 20", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"34d61a699ca576169fcdc0cc7e44e4e1221db0fe63d16850c8104029f7d48449714b9884328cae189978754ab460b486",
"04867f81104ccd6b163a7902b670ef406042cb0cce7dcdc63d1dfc91b2c40e3cdf7595834bf9eceb79849f1636fc8462f"
"c9d4bde8e875ec49697d258d1d59465f8431c6f5531e1c59e9f9ebe3cf164a8d9ce10a12f1979283a959bad244dd83863",
"049e22cbc18657f516a864b37b783348b66f1aa9626cd631f4fa1bd32ad88cf11db52057c660860d39d11fbf024fabd44"
"46b0d53c79681c28116df71e9cee74fd56c8b7f04b39f1198cc72284e98be9562e35926fb4f48a9fbecafe729309e8b6f",
"dc4ca392dc15e20185f2c6a8ea5ec31dfc96f56153a47394b3072b13d0015f5d4ae13beb3bed54d65848f9b8383e6c95",
- "curve: P384 vector: 21" },
+ "curve: P384 vector: 21", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"dc60fa8736d702135ff16aab992bb88eac397f5972456c72ec447374d0d8ce61153831bfc86ad5a6eb5b60bfb96a862c",
"04b69beede85d0f829fec1b893ccb9c3e052ff692e13b974537bc5b0f9feaf7b22e84f03231629b24866bdb4b8cf9089"
"1466f85e2bfcaba2843285b0e14ebc07ef7dafff8b424416fee647b59897b619f20eed95a632e6a4206bf7da429c04c560",
"042db5da5f940eaa884f4db5ec2139b0469f38e4e6fbbcc52df15c0f7cf7fcb1808c749764b6be85d2fdc5b16f58ad5d"
"c022e8b02dcf33e1b5a083849545f84ad5e43f77cb71546dbbac0d11bdb2ee202e9d3872e8d028c08990746c5e1dde9989",
"d765b208112d2b9ed5ad10c4046e2e3b0dbf57c469329519e239ac28b25c7d852bf757d5de0ee271cadd021d86cfd347",
- "curve: P384 vector: 22" },
+ "curve: P384 vector: 22", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"6fa6a1c704730987aa634b0516a826aba8c6d6411d3a4c89772d7a62610256a2e2f289f5c3440b0ec1e70fa339e251ce",
"0453de1fc1328e8de14aecab29ad8a40d6b13768f86f7d298433d20fec791f86f8bc73f358098b256a298bb488de257bf"
"4ac28944fd27f17b82946c04c66c41f0053d3692f275da55cd8739a95bd8cd3af2f96e4de959ea8344d8945375905858b",
"04329647baa354224eb4414829c5368c82d7893b39804e08cbb2180f459befc4b347a389a70c91a23bd9d30c83be5295d"
"3cc8f61923fad2aa8e505d6cfa126b9fabd5af9dce290b75660ef06d1caa73681d06089c33bc4246b3aa30dbcd2435b12",
"d3778850aeb58804fbe9dfe6f38b9fa8e20c2ca4e0dec335aafceca0333e3f2490b53c0c1a14a831ba37c4b9d74be0f2",
- "curve: P384 vector: 23" },
+ "curve: P384 vector: 23", ec_field_GFp },
- { ECCurve_NIST_P384,
+ { ECCurve_NIST_P384, 1,
"74ad8386c1cb2ca0fcdeb31e0869bb3f48c036afe2ef110ca302bc8b910f621c9fcc54cec32bb89ec7caa84c7b8e54a8",
"0427a3e83cfb9d5122e73129d801615857da7cc089cccc9c54ab3032a19e0a0a9f677346e37f08a0b3ed8da6e5dd69106"
"38d60e44aa5e0fd30c918456796af37f0e41957901645e5c596c6d989f5859b03a0bd7d1f4e77936fff3c74d204e5388e",
"0429d8a36d22200a75b7aea1bb47cdfcb1b7fd66de967041434728ab5d533a060df732130600fe6f75852a871fb2938e3"
"9e19b53db528395de897a45108967715eb8cb55c3fcbf23379372c0873a058d57544b102ecce722b2ccabb1a603774fd5",
"81e1e71575bb4505498de097350186430a6242fa6c57b85a5f984a23371123d2d1424eefbf804258392bc723e4ef1e35",
- "curve: P384 vector: 24" },
+ "curve: P384 vector: 24", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"017eecc07ab4b329068fba65e56a1f8890aa935e57134ae0ffcce802735151f4eac6564f6ee9974c5e6887a1fefee5743"
"ae2241bfeb95d5ce31ddcb6f9edb4d6fc47",
"0400602f9d0cf9e526b29e22381c203c48a886c2b0673033366314f1ffbcba240ba42f4ef38a76174635f91e6b4ed3427"
@@ -410,9 +410,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"a83bde99e0f6716939e632bc8986fa18dccd443a348b6c3e522497955a4f3c302f676",
"005fc70477c3e63bc3954bd0df3ea0d1f41ee21746ed95fc5e1fdf90930d5e136672d72cc770742d1711c3c3a4c334a0ad9"
"759436a4d3c5bf6e74b9578fac148c831",
- "curve: P521 vector: 0" },
+ "curve: P521 vector: 0", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"00816f19c1fb10ef94d4a1d81c156ec3d1de08b66761f03f06ee4bb9dcebbbfe1eaa1ed49a6a990838d8ed318c14d74cc"
"872f95d05d07ad50f621ceb620cd905cfb8",
"0400d45615ed5d37fde699610a62cd43ba76bedd8f85ed31005fe00d6450fbbd101291abd96d4945a8b57bc73b3fe9f46"
@@ -423,9 +423,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"7d4505d9b0a96b3bfac041e4c6a6990ae7f700e5b4a6640229112deafa0cd8bb0d089b0",
"000b3920ac830ade812c8f96805da2236e002acbbf13596a9ab254d44d0e91b6255ebf1229f366fb5a05c5884ef46032c2"
"6d42189273ca4efa4c3db6bd12a6853759",
- "curve: P521 vector: 1" },
+ "curve: P521 vector: 1", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"012f2e0c6d9e9d117ceb9723bced02eb3d4eebf5feeaf8ee0113ccd8057b13ddd416e0b74280c2d0ba8ed291c443bc1b14"
"1caf8afb3a71f97f57c225c03e1e4d42b0",
"0400717fcb3d4a40d103871ede044dc803db508aaa4ae74b70b9fb8d8dfd84bfecfad17871879698c292d2fd5e17b4f9343"
@@ -436,9 +436,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"60272675a548996217e4ab2b8ebce31d71fca63fcc3c08e91c1d8edd91cf6fe845f8",
"006b380a6e95679277cfee4e8353bf96ef2a1ebdd060749f2f046fe571053740bbcc9a0b55790bc9ab56c3208aa05ddf746"
"a10a3ad694daae00d980d944aabc6a08f",
- "curve: P521 vector: 2" },
+ "curve: P521 vector: 2", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"00e548a79d8b05f923b9825d11b656f222e8cb98b0f89de1d317184dc5a698f7c71161ee7dc11cd31f4f4f8ae3a981e1a3e7"
"8bdebb97d7c204b9261b4ef92e0918e0",
"04000ce800217ed243dd10a79ad73df578aa8a3f9194af528cd1094bbfee27a3b5481ad5862c8876c0c3f91294c0ab3aa806"
@@ -449,9 +449,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"3be831b915435905925b44947c592959945b4eb7c951c3b9c8cf52530ba23",
"00fbbcd0b8d05331fef6086f22a6cce4d35724ab7a2f49dd8458d0bfd57a0b8b70f246c17c4468c076874b0dff7a0336823b19e"
"98bf1cec05e4beffb0591f97713c6",
- "curve: P521 vector: 3" },
+ "curve: P521 vector: 3", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"01c8aae94bb10b8ca4f7be577b4fb32bb2381032c4942c24fc2d753e7cc5e47b483389d9f3b956d20ee9001b1eef9f23545f72"
"c5602140046839e963313c3decc864",
"040106a14e2ee8ff970aa8ab0c79b97a33bba2958e070b75b94736b77bbe3f777324fa52872771aa88a63a9e8490c3378df4dc"
@@ -462,9 +462,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"aa4965fb622f42b7391e27e5ec21c5679c5b06b59127372997d421adc1e",
"0145cfa38f25943516c96a5fd4bfebb2f645d10520117aa51971eff442808a23b4e23c187e639ff928c3725fbd1c0c2ad0d4aeb2"
"07bc1a6fb6cb6d467888dc044b3c",
- "curve: P521 vector: 4" },
+ "curve: P521 vector: 4", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"009b0af137c9696c75b7e6df7b73156bb2d45f482e5a4217324f478b10ceb76af09724cf86afa316e7f89918d31d54824a5c33"
"107a483c15c15b96edc661340b1c0e",
"0400748cdbb875d35f4bccb62abe20e82d32e4c14dc2feb5b87da2d0ccb11c9b6d4b7737b6c46f0dfb4d896e2db92fcf53cdbb"
@@ -475,9 +475,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"0fbeeb247cf6d3fba7a60697536ad03f49b80a9d1cb079673654977c5fa94",
"005c5721e96c273319fd60ecc46b5962f698e974b429f28fe6962f4ac656be2eb8674c4aafc037eab48ece612953b1e8d86101"
"6b6ad0c79805784c67f73ada96f351",
- "curve: P521 vector: 5" },
+ "curve: P521 vector: 5", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"01e48faacee6dec83ffcde944cf6bdf4ce4bae72747888ebafee455b1e91584971efb49127976a52f4142952f7c207ec0265f2b"
"718cf3ead96ea4f62c752e4f7acd3",
"04010eb1b4d9172bcc23f4f20cc9560fc54928c3f34ea61c00391dc766c76ed9fa608449377d1e4fadd1236025417330b4b91086"
@@ -488,9 +488,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"7b7e6a82091c2db874d8e7abf0f58064691344154f396dbaed188b6",
"01736d9717429b4f412e903febe2f9e0fffd81355d6ce2c06ff3f66a3be15ceec6e65e308347593f00d7f33591da4043c30763d72"
"749f72cdceebe825e4b34ecd570",
- "curve: P521 vector: 6" },
+ "curve: P521 vector: 6", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"00c29aa223ea8d64b4a1eda27f39d3bc98ea0148dd98c1cbe595f8fd2bfbde119c9e017a50f5d1fc121c08c1cef31b75885955"
"6eb3e0e042d8dd6aaac57a05ca61e3",
"04001511c848ef60d5419a98d10204db0fe58224124370061bcfa4e9249d50618c56bf3722471b259f38263bb7b280d23caf2a"
@@ -501,9 +501,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"c268ac1b6ec88bd71b7ba78e2c33c152e4bf7da5d565e4acbecf5e92c7ad662bb",
"018f2ae9476c771726a77780208dedfefa205488996b18fecc50bfd4c132753f5766b2cd744afa9918606de2e016effc63622"
"e9029e76dc6e3f0c69f7aeced565c2c",
- "curve: P521 vector: 7" },
+ "curve: P521 vector: 7", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"0028692be2bf5c4b48939846fb3d5bce74654bb2646e15f8389e23708a1afadf561511ea0d9957d0b53453819d60fba8f65a1"
"8f7b29df021b1bb01cd163293acc3cc",
"0401cfdc10c799f5c79cb6930a65fba351748e07567993e5e410ef4cacc4cd8a25784991eb4674e41050f930c7190ac812b92"
@@ -514,9 +514,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"4683f10fab84652dfe9e928c2626b5456453e1573ff60be1507467d431fbb2",
"0105a346988b92ed8c7a25ce4d79d21bc86cfcc7f99c6cd19dbb4a39f48ab943b79e4f0647348da0b80bd864b85c6b8d92536"
"d6aa544dc7537a00c858f8b66319e25",
- "curve: P521 vector: 8" },
+ "curve: P521 vector: 8", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"01194d1ee613f5366cbc44b504d21a0cf6715e209cd358f2dd5f3e71cc0d67d0e964168c42a084ebda746f9863a86bacffc81"
"9f1edf1b8c727ccfb3047240a57c435",
"04016bd15c8a58d366f7f2b2f298cc87b7485e9ee70d11d12448b8377c0a82c7626f67aff7f97be7a3546bf417eeeddf75a93"
@@ -527,9 +527,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"f074c4ccf2d634ae97b701956f67a11006c52d97197d92f585f5748bc2672eeb",
"004531b3d2c6cd12f21604c8610e6723dbf4daf80b5a459d6ba5814397d1c1f7a21d7c114be964e27376aaebe3a7bc3d6af7"
"a7f8c7befb611afe487ff032921f750f",
- "curve: P521 vector: 9" },
+ "curve: P521 vector: 9", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"01fd90e3e416e98aa3f2b6afa7f3bf368e451ad9ca5bd54b5b14aee2ed6723dde5181f5085b68169b09fbec721372ccf6b"
"284713f9a6356b8d560a8ff78ca3737c88",
"0401ebea1b10d3e3b971b7efb69fc878de11c7f472e4e4d384c31b8d6288d8071517acade9b39796c7af5163bcf71aeda7"
@@ -540,9 +540,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"3c5cdb722893ffbb2027259d594de77438809738120c6f783934f926c3fb69b40c409",
"0100c8935969077bae0ba89ef0df8161d975ec5870ac811ae7e65ca5394efba4f0633d41bf79ea5e5b9496bbd7aae000b05"
"94baa82ef8f244e6984ae87ae1ed124b7",
- "curve: P521 vector: 10" },
+ "curve: P521 vector: 10", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"009012ecfdadc85ced630afea534cdc8e9d1ab8be5f3753dcf5f2b09b40eda66fc6858549bc36e6f8df55998cfa9a0703a"
"ecf6c42799c245011064f530c09db98369",
"0400234e32be0a907131d2d128a6477e0caceb86f02479745e0fe245cb332de631c078871160482eeef584e274df7fa412c"
@@ -553,9 +553,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"e15327acaac1fa40424c395a6556cb8167312527fae5865ecffc14bbdc17da78cdcf",
"017f36af19303841d13a389d95ec0b801c7f9a679a823146c75c17bc44256e9ad422a4f8b31f14647b2c7d317b933f7c294"
"6c4b8abd1d56d620fab1b5ff1a3adc71f",
- "curve: P521 vector: 11" },
+ "curve: P521 vector: 11", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"01b5ff847f8eff20b88cfad42c06e58c3742f2f8f1fdfd64b539ba48c25926926bd5e332b45649c0b184f77255e9d58fe8"
"afa1a6d968e2cb1d4637777120c765c128",
"0401de3dc9263bc8c4969dc684be0eec54befd9a9f3dba194d8658a789341bf0d78d84da6735227cafaf093519516911975"
@@ -566,9 +566,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"c7b428d0e7f3f4d503e5d60c68cb49b13c2480cd486bed9200caddaddfe4ff8e3562",
"00062f9fc29ae1a68b2ee0dcf956cbd38c88ae5f645eaa546b00ebe87a7260bf724be20d34b9d02076655c933d056b21e30"
"4c24ddb1dedf1dd76de611fc4a2340336",
- "curve: P521 vector: 12" },
+ "curve: P521 vector: 12", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"011a6347d4e801c91923488354cc533e7e35fddf81ff0fb7f56bb0726e0c29ee5dcdc5f394ba54cf57269048aab6e055895c"
"8da24b8b0639a742314390cc04190ed6",
"0400fe30267f33ba5cdefc25cbb3c9320dad9ccb1d7d376644620ca4fadee5626a3cede25ad254624def727a7048f7145f761"
@@ -579,9 +579,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"2f14c8cbf2a68f488ab35dcdf64056271dee1f606a440ba4bd4e5a11b8b8e54f",
"0128ab09bfec5406799e610f772ba17e892249fa8e0e7b18a04b9197034b250b48294f1867fb9641518f92766066a07a8b917"
"b0e76879e1011e51ccbd9f540c54d4f",
- "curve: P521 vector: 13" },
+ "curve: P521 vector: 13", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"0022b6d2a22d71dfaa811d2d9f9f31fbed27f2e1f3d239538ddf3e4cc8c39a330266db25b7bc0a9704f17bde7f3592bf5f1f2d"
"4b56013aacc3d8d1bc02f00d3146cc",
"0400ba38cfbf9fd2518a3f61d43549e7a6a6d28b2be57ffd3e0faceb636b34ed17e044a9f249dae8fc132e937e2d9349cd2ed7"
@@ -592,9 +592,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"60d93e5b43db8789f1ec0aba47286a39ea584235acea757dbf13d53b58364",
"0101e462e9d9159968f6440e956f11dcf2227ae4aea81667122b6af9239a291eb5d6cf5a4087f358525fcacfa46bb2db01a75a"
"f1ba519b2d31da33eda87a9d565748",
- "curve: P521 vector: 14" },
+ "curve: P521 vector: 14", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"005bacfff268acf6553c3c583b464ea36a1d35e2b257a5d49eb3419d5a095087c2fb4d15cf5bf5af816d0f3ff7586490ccd3ddc1"
"a98b39ce63749c6288ce0dbdac7d",
"040036e488da7581472a9d8e628c58d6ad727311b7e6a3f6ae33a8544f34b09280249020be7196916fafd90e2ec54b66b5468d23"
@@ -605,9 +605,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"016085e71552ff488c72b7339fefb7915c38459cb20ab85aec4e45052",
"0141d6a4b719ab67eaf04a92c0a41e2dda78f4354fb90bdc35202cc7699b9b04d49616f82255debf7bbec045ae58f982a66905fc"
"fae69d689785e38c868eb4a27e7b",
- "curve: P521 vector: 15" },
+ "curve: P521 vector: 15", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"008e2c93c5423876223a637cad367c8589da69a2d0fc68612f31923ae50219df2452e7cc92615b67f17b57ffd2f52b19154bb40"
"d7715336420fde2e89fee244f59dc",
"0400fa3b35118d6c422570f724a26f90b2833b19239174cea081c53133f64db60d6940ea1261299c04c1f4587cdb0c4c39616"
@@ -618,9 +618,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"15e5701d7ceee416291ff5fed85e687f727388b9afe26a4f6feed560b218e6bb",
"00345e26e0abb1aac12b75f3a9cf41efe1c336396dffa4a067a4c2cfeb878c68b2b045faa4e5b4e6fa4678f5b603c351903b1"
"4bf9a6a70c439257199a640890b61d1",
- "curve: P521 vector: 16" },
+ "curve: P521 vector: 16", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"0004d49d39d40d8111bf16d28c5936554326b197353eebbcf47545393bc8d3aaf98f14f5be7074bfb38e6cc97b989754074da"
"ddb3045f4e4ce745669fdb3ec0d5fa8",
"04012ec226d050ce07c79b3df4d0f0891f9f7adf462e8c98dbc1a2a14f5e53a3f5ad894433587cc429a8be9ea1d84fa33b180"
@@ -631,9 +631,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"c29f7d7fb0324debadc10bbb93de68f62c35069268283f5265865db57a79f7bf7",
"006fe9de6fb8e672e7fd150fdc5e617fabb0d43906354ccfd224757c7276f7a1010091b17ed072074f8d10a5ec971eb35a5c"
"b7076603b7bc38d432cbc059f80f9488",
- "curve: P521 vector: 17" },
+ "curve: P521 vector: 17", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"011a5d1cc79cd2bf73ea106f0e60a5ace220813b53e27b739864334a07c03367efda7a4619fa6eef3a9746492283b3c445610"
"a023a9cc49bf4591140384fca5c8bb5",
"0400eb07c7332eedb7d3036059d35f7d2288d4377d5f42337ad3964079fb120ccd4c8bd384b585621055217023acd9a94fcb3"
@@ -644,9 +644,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"5561bbabaae372e9e67e6e1a3be60e19b470cdf673ec1fc393d3426e20",
"01e4e759ecedce1013baf73e6fcc0b92451d03bdd50489b78871c333114990c9ba6a9b2fc7b1a2d9a1794c1b60d9279af6f"
"146f0bbfb0683140403bfa4ccdb524a29",
- "curve: P521 vector: 18" },
+ "curve: P521 vector: 18", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"010c908caf1be74c616b625fc8c1f514446a6aec83b5937141d6afbb0a8c7666a7746fa1f7a6664a2123e8cdf6cd8bf836c5"
"6d3c0ebdcc980e43a186f938f3a78ae7",
"040031890f4c7abec3f723362285d77d2636f876817db3bbc88b01e773597b969ff6f013ea470c854ab4a7739004eb8cbea6"
@@ -657,9 +657,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"0a847c11a1ab3f1d12cc850c32e095614ca8f7e2721477b486e9ff40372977c3f65c",
"0163c9191d651039a5fe985a0eea1eba018a40ab1937fcd2b61220820ee8f2302e9799f6edfc3f5174f369d672d377ea895"
"4a8d0c8b851e81a56fda95212a6578f0e",
- "curve: P521 vector: 19" },
+ "curve: P521 vector: 19", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"01b37d6b7288de671360425d3e5ac1ccb21815079d8d73431e9b74a6f0e7ae004a357575b11ad66642ce8b775593eba9d98"
"bf25c75ef0b4d3a2098bbc641f59a2b77",
"0400189a5ee34de7e35aefeaeef9220c18071b4c29a4c3bd9d954458bd3e82a7a34da34cff5579b8101c065b1f2f527cf45"
@@ -670,9 +670,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"602380c86721e61db1830f51e139f210000bcec0d8edd39e54d73a9a129f95cd5fa979",
"015d613e267a36342e0d125cdad643d80d97ed0600afb9e6b9545c9e64a98cc6da7c5aaa3a8da0bdd9dd3b97e9788218a8"
"0abafc106ef065c8f1c4e1119ef58d298b",
- "curve: P521 vector: 20" },
+ "curve: P521 vector: 20", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"00f2661ac762f60c5fff23be5d969ccd4ec6f98e4e72618d12bdcdb9b4102162333788c0bae59f91cdfc172c7a1681ee44d9"
"6ab2135a6e5f3415ebbcd55165b1afb0",
"0400a8e25a6902d687b4787cdc94c364ac7cecc5c495483ed363dc0aa95ee2bd739c4c4d46b17006c728b076350d7d7e54c"
@@ -683,9 +683,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"1069bde6387feb71587b8ffce5b266e1bae86de29378a34e5c74b6724c4d40a719923",
"014d6082a3b5ced1ab8ca265a8106f302146c4acb8c30bb14a4c991e3c82a9731288bdb91e0e85bda313912d06384fc44"
"f2153fb13506fa9cf43c9aab5750988c943",
- "curve: P521 vector: 21" },
+ "curve: P521 vector: 21", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"00f430ca1261f09681a9282e9e970a9234227b1d5e58d558c3cc6eff44d1bdf53de16ad5ee2b18b92d62fc79586116b0e"
"fc15f79340fb7eaf5ce6c44341dcf8dde27",
"04006c1d9b5eca87de1fb871a0a32f807c725adccde9b3967453a71347d608f0c030cd09e338cdecbf4a02015bc8a6e8"
@@ -696,9 +696,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"c98e7ecdbf2b2a68e22928059f67db188007161d3ecf397e0883f0c4eb7eaf7827a62205cc",
"0020c00747cb8d492fd497e0fec54644bf027d418ab686381f109712a99cabe328b9743d2225836f9ad66e5d7fed1de2"
"47e0da92f60d5b31f9e47672e57f710598f4",
- "curve: P521 vector: 22" },
+ "curve: P521 vector: 22", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"005dc33aeda03c2eb233014ee468dff753b72f73b00991043ea353828ae69d4cd0fadeda7bb278b535d7c57406ff2e6e"
"473a5a4ff98e90f90d6dadd25100e8d85666",
"0400c825ba307373cec8dd2498eef82e21fd9862168dbfeb83593980ca9f82875333899fe94f137daf1c4189eb502937"
@@ -709,9 +709,9 @@ static ECDH_KAT ecdh_testvecs[] = {
"8a2232a0c2dbc4e8e1d09214bab38485be6e357c4200d073b52f04e4a16fc6f5247187aecb",
"00c2bfafcd7fbd3e2fd1c750fdea61e70bd4787a7e68468c574ee99ebc47eedef064e8944a73bcb7913dbab5d93dca6"
"60d216c553622362794f7a2acc71022bdb16f",
- "curve: P521 vector: 23" },
+ "curve: P521 vector: 23", ec_field_GFp },
- { ECCurve_NIST_P521,
+ { ECCurve_NIST_P521, 1,
"00df14b1f1432a7b0fb053965fd8643afee26b2451ecb6a8a53a655d5fbe16e4c64ce8647225eb11e7fdcb23627471"
"dffc5c2523bd2ae89957cba3a57a23933e5a78",
"04004e8583bbbb2ecd93f0714c332dff5ab3bc6396e62f3c560229664329baa5138c3bb1c36428abd4e23d17fcb7"
@@ -722,7 +722,97 @@ static ECDH_KAT ecdh_testvecs[] = {
"d387df67cde85003e0e427552f1cd09059aad0262e235cce5fba8cedc4fdc1463da76dcd4b6d1a46",
"01aaf24e5d47e4080c18c55ea35581cd8da30f1a079565045d2008d51b12d0abb4411cda7a0785b15d149ed301a36"
"97062f42da237aa7f07e0af3fd00eb1800d9c41",
- "curve: P521 vector: 24" },
+ "curve: P521 vector: 24", ec_field_GFp },
- { ECCurve_pastLastCurve, NULL, NULL, NULL, NULL, NULL }
+ { ECCurve_pastLastCurve, 0, NULL, NULL, NULL, NULL, NULL, 0 }
+};
+
+static ECDH_KAT nonnist_testvecs[] = {
+ { ECCurve25519, 1,
+ "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
+ NULL,
+ "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c",
+ "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552",
+ "curve: 25519 vector: 0", ec_field_plain },
+ { ECCurve25519, 1,
+ "4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d",
+ NULL,
+ "e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493",
+ "95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957",
+ "curve: 25519 vector: 1", ec_field_plain },
+ { ECCurve25519, 1,
+ "0900000000000000000000000000000000000000000000000000000000000000",
+ NULL,
+ "0900000000000000000000000000000000000000000000000000000000000000",
+ "422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079",
+ "curve: 25519 vector: 2", ec_field_plain },
+ { ECCurve25519, 1000,
+ "0900000000000000000000000000000000000000000000000000000000000000",
+ NULL,
+ "0900000000000000000000000000000000000000000000000000000000000000",
+ "684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51",
+ "curve: 25519 vector: 1000 iterations", ec_field_plain },
+#ifdef NSS_ENABLE_EXPENSIVE_TESTS
+ /* This test is disabled by default because it takes a very long time
+ * to run. */
+ { ECCurve25519, 1000000,
+ "0900000000000000000000000000000000000000000000000000000000000000",
+ NULL,
+ "0900000000000000000000000000000000000000000000000000000000000000",
+ "7c3911e0ab2586fd864497297e575e6f3bc601c0883c30df5f4dd2d24f665424",
+ "curve: 25519 vector: 1000000 iterations", ec_field_plain },
+#endif
+ { ECCurve25519, 1,
+ "174a56a75017c029e0861044d3c57c291823cf477ae6e21065cc121578bfa893",
+ NULL,
+ "7bd8396462a5788951caf3d3a28cb0904e4d081e62e6ac2d9da7152eb1310f30",
+ "28c09f6be3666a6ab3bf8f5b03eec14e95505e32726ae887053ce6a2061a9656",
+ "curve: 25519 custom vector 1", ec_field_plain },
+ { ECCurve25519, 1,
+ "577a2a7fcdacd4ccf7d7f81ba93ec83ae4bda32bec00ff7d59c294b69404f688",
+ NULL,
+ "a43b5491cbd9273abf694115f383fabe3bdc5f2baa30d2e00e43b6937a75cc5d",
+ "4aed703c32552576ca0b30a3fab53242e1eea29ddec993219d3c2b3c3e59b735",
+ "curve: 25519 custom vector 1", ec_field_plain },
+
+ { ECCurve_pastLastCurve, 0, NULL, NULL, NULL, NULL, NULL, 0 }
+};
+
+static ECDH_BAD nonnist_testvecs_bad_values[] = {
+ { ECCurve25519, "00", "curve: 25519 vector: 0 bad point", ec_field_plain },
+ { ECCurve25519,
+ "0100000000000000000000000000000000000000000000000000000000000000",
+ "curve: 25519 vector: 1 bad point", ec_field_plain },
+ { ECCurve25519,
+ "e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b8",
+ "curve: 25519 vector: 2 bad point", ec_field_plain },
+ { ECCurve25519,
+ "5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157",
+ "curve: 25519 vector: 3 bad point", ec_field_plain },
+ { ECCurve25519,
+ "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+ "curve: 25519 vector: 4 bad point", ec_field_plain },
+ { ECCurve25519,
+ "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+ "curve: 25519 vector: 5 bad point", ec_field_plain },
+ { ECCurve25519,
+ "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+ "curve: 25519 vector: 6 bad point", ec_field_plain },
+ { ECCurve25519,
+ "cdeb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b880",
+ "curve: 25519 vector: 7 bad point", ec_field_plain },
+ { ECCurve25519,
+ "4c9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f11d7",
+ "curve: 25519 vector: 8 bad point", ec_field_plain },
+ { ECCurve25519,
+ "d9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "curve: 25519 vector: 9 bad point", ec_field_plain },
+ { ECCurve25519,
+ "daffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "curve: 25519 vector: 10 bad point", ec_field_plain },
+ { ECCurve25519,
+ "dbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "curve: 25519 vector: 11 bad point", ec_field_plain },
+
+ { ECCurve_pastLastCurve, 0, NULL, 0 }
};
diff --git a/cmd/fipstest/fipstest.c b/cmd/fipstest/fipstest.c
index a6b67fe2c..c4c700cbb 100644
--- a/cmd/fipstest/fipstest.c
+++ b/cmd/fipstest/fipstest.c
@@ -2523,7 +2523,7 @@ ecdsa_pkv_test(char *reqfn)
PORT_Free(pubkey.data);
pubkey.data = NULL;
}
- SECITEM_AllocItem(NULL, &pubkey, 2 * len + 1);
+ SECITEM_AllocItem(NULL, &pubkey, ecparams->pointSize);
if (pubkey.data == NULL) {
goto loser;
}
diff --git a/lib/cryptohi/keyi.h b/lib/cryptohi/keyi.h
index f8f5f7f7d..374a4ad9b 100644
--- a/lib/cryptohi/keyi.h
+++ b/lib/cryptohi/keyi.h
@@ -17,6 +17,13 @@ KeyType seckey_GetKeyType(SECOidTag pubKeyOid);
SECStatus sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
const SECItem *param, SECOidTag *encalg, SECOidTag *hashalg);
+/*
+ * Set the point encoding of a SECKEYPublicKey from the OID.
+ * This has to be called on any SECKEYPublicKey holding a SECKEYECPublicKey
+ * before it can be used. The encoding is used to dermine the public key size.
+ */
+SECStatus seckey_SetPointEncoding(PLArenaPool *arena, SECKEYPublicKey *pubKey);
+
SEC_END_PROTOS
#endif /* _KEYHI_H_ */
diff --git a/lib/cryptohi/keythi.h b/lib/cryptohi/keythi.h
index bd26838eb..1555ce2e2 100644
--- a/lib/cryptohi/keythi.h
+++ b/lib/cryptohi/keythi.h
@@ -4,6 +4,7 @@
#ifndef _KEYTHI_H_
#define _KEYTHI_H_ 1
+#include "eccutil.h"
#include "plarena.h"
#include "pkcs11t.h"
#include "secmodt.h"
@@ -126,12 +127,7 @@ struct SECKEYECPublicKeyStr {
SECKEYECParams DEREncodedParams;
int size; /* size in bits */
SECItem publicValue; /* encoded point */
- /* XXX Even though the PKCS#11 interface takes encoded parameters,
- * we may still wish to decode them above PKCS#11 for things like
- * printing key information. For named curves, which is what
- * we initially support, we ought to have the curve name at the
- * very least.
- */
+ ECPointEncoding encoding;
};
typedef struct SECKEYECPublicKeyStr SECKEYECPublicKey;
diff --git a/lib/cryptohi/manifest.mn b/lib/cryptohi/manifest.mn
index 2050b1517..896c7ad12 100644
--- a/lib/cryptohi/manifest.mn
+++ b/lib/cryptohi/manifest.mn
@@ -6,6 +6,8 @@ CORE_DEPTH = ../..
MODULE = nss
+REQUIRES = nssutil
+
LIBRARY_NAME = cryptohi
EXPORTS = \
@@ -19,6 +21,7 @@ EXPORTS = \
$(NULL)
PRIVATE_EXPORTS = \
+ keyi.h \
$(NULL)
CSRCS = \
diff --git a/lib/cryptohi/seckey.c b/lib/cryptohi/seckey.c
index 3b9010027..c47c1023e 100644
--- a/lib/cryptohi/seckey.c
+++ b/lib/cryptohi/seckey.c
@@ -634,11 +634,17 @@ seckey_ExtractPublicKey(const CERTSubjectPublicKeyInfo *spki)
*/
rv = SECITEM_CopyItem(arena, &pubk->u.ec.DEREncodedParams,
&spki->algorithm.parameters);
- if (rv != SECSuccess)
+ if (rv != SECSuccess) {
break;
+ }
rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &newOs);
- if (rv == SECSuccess)
+ if (rv != SECSuccess) {
+ break;
+ }
+ rv = seckey_SetPointEncoding(arena, pubk);
+ if (rv == SECSuccess) {
return pubk;
+ }
break;
default:
@@ -787,6 +793,9 @@ SECKEY_ECParamsToKeySize(const SECItem *encodedParams)
case SEC_OID_SECG_EC_SECT571R1:
return 571;
+ case SEC_OID_CURVE25519:
+ return 255;
+
default:
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
return 0;
@@ -934,6 +943,9 @@ SECKEY_ECParamsToBasePointOrderLen(const SECItem *encodedParams)
case SEC_OID_SECG_EC_SECT571R1:
return 570;
+ case SEC_OID_CURVE25519:
+ return 255;
+
default:
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
return 0;
@@ -1155,8 +1167,14 @@ SECKEY_CopyPublicKey(const SECKEYPublicKey *pubk)
copyk->u.ec.size = pubk->u.ec.size;
rv = SECITEM_CopyItem(arena, &copyk->u.ec.DEREncodedParams,
&pubk->u.ec.DEREncodedParams);
- if (rv != SECSuccess)
+ if (rv != SECSuccess) {
+ break;
+ }
+ rv = seckey_SetPointEncoding(arena, copyk);
+ if (rv != SECSuccess) {
break;
+ }
+ PORT_Assert(copyk->u.ec.encoding == pubk->u.ec.encoding);
rv = SECITEM_CopyItem(arena, &copyk->u.ec.publicValue,
&pubk->u.ec.publicValue);
break;
@@ -1928,3 +1946,40 @@ SECKEY_GetECCOid(const SECKEYECParams *params)
return oidData->offset;
}
+
+/* Set curve encoding in SECKEYECPublicKey in pubKey from OID.
+ * If the encoding is not set, determining the key size of EC public keys will
+ * fail.
+ */
+SECStatus
+seckey_SetPointEncoding(PLArenaPool *arena, SECKEYPublicKey *pubKey)
+{
+ SECItem oid;
+ SECOidTag tag;
+ SECStatus rv;
+
+ /* decode the OID tag */
+ rv = SEC_QuickDERDecodeItem(arena, &oid, SEC_ASN1_GET(SEC_ObjectIDTemplate),
+ &pubKey->u.ec.DEREncodedParams);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+
+ tag = SECOID_FindOIDTag(&oid);
+ switch (tag) {
+ case SEC_OID_SECG_EC_SECP256R1:
+ /* fall through */
+ case SEC_OID_SECG_EC_SECP384R1:
+ /* fall through */
+ case SEC_OID_SECG_EC_SECP521R1:
+ pubKey->u.ec.encoding = ECPoint_Uncompressed;
+ break;
+ case SEC_OID_CURVE25519:
+ pubKey->u.ec.encoding = ECPoint_XOnly;
+ break;
+ default:
+ /* unsupported curve */
+ return SECFailure;
+ }
+ return SECSuccess;
+}
diff --git a/lib/freebl/Makefile b/lib/freebl/Makefile
index 964fe7c84..0ce1425f1 100644
--- a/lib/freebl/Makefile
+++ b/lib/freebl/Makefile
@@ -504,14 +504,19 @@ endif
# poly1305-donna-x64-sse2-incremental-source.c requires __int128 support
# in GCC 4.6.0.
-ifdef CC_IS_CLANG
- HAVE_INT128_SUPPORT = 1
-else ifeq (1,$(CC_IS_GCC))
- ifneq (,$(filter 4.6 4.7 4.8 4.9,$(word 1,$(GCC_VERSION)).$(word 2,$(GCC_VERSION))))
- HAVE_INT128_SUPPORT = 1
- endif
- ifeq (,$(filter 0 1 2 3 4,$(word 1,$(GCC_VERSION))))
- HAVE_INT128_SUPPORT = 1
+ifdef USE_64
+ ifdef CC_IS_CLANG
+ HAVE_INT128_SUPPORT = 1
+ DEFINES += -DHAVE_INT128_SUPPORT
+ else ifeq (1,$(CC_IS_GCC))
+ ifneq (,$(filter 4.6 4.7 4.8 4.9,$(word 1,$(GCC_VERSION)).$(word 2,$(GCC_VERSION))))
+ HAVE_INT128_SUPPORT = 1
+ DEFINES += -DHAVE_INT128_SUPPORT
+ endif
+ ifeq (,$(filter 0 1 2 3 4,$(word 1,$(GCC_VERSION))))
+ HAVE_INT128_SUPPORT = 1
+ DEFINES += -DHAVE_INT128_SUPPORT
+ endif
endif
endif
@@ -534,6 +539,19 @@ ifndef NSS_DISABLE_CHACHAPOLY
endif # x86_64
endif # NSS_DISABLE_CHACHAPOLY
+ifeq (,$(filter-out i386 x386 x86 x86_64,$(CPU_ARCH)))
+ # All intel architectures get the 64 bit version
+ # With custom uint128 if necessary (faster than generic 32 bit version).
+ ECL_SRCS += curve25519_64.c
+else
+ # All non intel architectures get the generic 32 bit implementation (slow!)
+ ECL_SRCS += curve25519_32.c
+endif
+
+ifndef HAVE_INT128_SUPPORT
+ ECL_SRCS += uint128.c
+endif
+
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
diff --git a/lib/freebl/blapit.h b/lib/freebl/blapit.h
index 4e2d5e7fa..062d254c9 100644
--- a/lib/freebl/blapit.h
+++ b/lib/freebl/blapit.h
@@ -343,7 +343,8 @@ typedef enum { ec_params_explicit,
} ECParamsType;
typedef enum { ec_field_GFp = 1,
- ec_field_GF2m
+ ec_field_GF2m,
+ ec_field_plain
} ECFieldType;
struct ECFieldIDStr {
@@ -381,6 +382,7 @@ struct ECParamsStr {
SECItem DEREncoding;
ECCurveName name;
SECItem curveOID;
+ int pointSize;
};
typedef struct ECParamsStr ECParams;
diff --git a/lib/freebl/ec.c b/lib/freebl/ec.c
index ebe28aef5..d6b3a1812 100644
--- a/lib/freebl/ec.c
+++ b/lib/freebl/ec.c
@@ -17,6 +17,24 @@
#ifndef NSS_DISABLE_ECC
+static const ECMethod kMethods[] = {
+ { ECCurve25519,
+ ec_Curve25519_pt_mul,
+ ec_Curve25519_pt_validate }
+};
+
+static const ECMethod *
+ec_get_method_from_name(ECCurveName name)
+{
+ int i;
+ for (i = 0; i < sizeof(kMethods) / sizeof(kMethods[0]); ++i) {
+ if (kMethods[i].name == name) {
+ return &kMethods[i];
+ }
+ }
+ return NULL;
+}
+
/*
* Returns true if pointP is the point at infinity, false otherwise
*/
@@ -188,7 +206,8 @@ ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
#endif
MP_DIGITS(&k) = 0;
- if (!ecParams || !privKey || !privKeyBytes || (privKeyLen < 0)) {
+ if (!ecParams || !privKey || !privKeyBytes || (privKeyLen < 0) ||
+ !ecParams->name) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
@@ -214,7 +233,9 @@ ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
key->ecParams.type = ecParams->type;
key->ecParams.fieldID.size = ecParams->fieldID.size;
key->ecParams.fieldID.type = ecParams->fieldID.type;
- if (ecParams->fieldID.type == ec_field_GFp) {
+ key->ecParams.pointSize = ecParams->pointSize;
+ if (ecParams->fieldID.type == ec_field_GFp ||
+ ecParams->fieldID.type == ec_field_plain) {
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.prime,
&ecParams->fieldID.u.prime));
} else {
@@ -241,8 +262,7 @@ ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curveOID,
&ecParams->curveOID));
- len = (ecParams->fieldID.size + 7) >> 3;
- SECITEM_AllocItem(arena, &key->publicValue, 2 * len + 1);
+ SECITEM_AllocItem(arena, &key->publicValue, ecParams->pointSize);
len = ecParams->order.len;
SECITEM_AllocItem(arena, &key->privateValue, len);
@@ -255,19 +275,36 @@ ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
}
/* Compute corresponding public key */
+
+ /* Use curve specific code for point multiplication */
+ if (ecParams->fieldID.type == ec_field_plain) {
+ const ECMethod *method = ec_get_method_from_name(ecParams->name);
+ if (method == NULL || method->mul == NULL) {
+ /* unknown curve */
+ rv = SECFailure;
+ goto cleanup;
+ }
+ rv = method->mul(&key->publicValue, &key->privateValue, NULL);
+ goto done;
+ }
+
CHECK_MPI_OK(mp_init(&k));
CHECK_MPI_OK(mp_read_unsigned_octets(&k, key->privateValue.data,
(mp_size)len));
rv = ec_points_mul(ecParams, &k, NULL, NULL, &(key->publicValue));
- if (rv != SECSuccess)
+ if (rv != SECSuccess) {
goto cleanup;
+ }
+
+done:
*privKey = key;
cleanup:
mp_clear(&k);
- if (rv)
+ if (rv) {
PORT_FreeArena(arena, PR_TRUE);
+ }
#if EC_DEBUG
printf("ec_NewKey returning %s\n",
@@ -412,11 +449,22 @@ EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue)
mp_err err = MP_OKAY;
int len;
- if (!ecParams || !publicValue) {
+ if (!ecParams || !publicValue || !ecParams->name) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
+ /* Uses curve specific code for point validation. */
+ if (ecParams->fieldID.type == ec_field_plain) {
+ const ECMethod *method = ec_get_method_from_name(ecParams->name);
+ if (method == NULL || method->validate == NULL) {
+ /* unknown curve */
+ rv = SECFailure;
+ goto cleanup;
+ }
+ return method->validate(publicValue);
+ }
+
/* NOTE: We only support uncompressed points for now */
len = (ecParams->fieldID.size + 7) >> 3;
if (publicValue->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
@@ -512,12 +560,34 @@ ECDH_Derive(SECItem *publicValue,
int i;
#endif
- if (!publicValue || !ecParams || !privateValue ||
- !derivedSecret) {
+ if (!publicValue || !ecParams || !privateValue || !derivedSecret ||
+ !ecParams->name) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
+ /* Perform curve specific multiplication using ECMethod */
+ if (ecParams->fieldID.type == ec_field_plain) {
+ const ECMethod *method;
+ memset(derivedSecret, 0, sizeof(*derivedSecret));
+ SECITEM_AllocItem(NULL, derivedSecret, ecParams->pointSize);
+ if (derivedSecret == NULL) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return SECFailure;
+ }
+ method = ec_get_method_from_name(ecParams->name);
+ if (method == NULL || method->validate == NULL ||
+ method->mul == NULL) {
+ PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
+ return SECFailure;
+ }
+ if (method->validate(publicValue) != SECSuccess) {
+ PORT_SetError(SEC_ERROR_BAD_KEY);
+ return SECFailure;
+ }
+ return method->mul(derivedSecret, privateValue, publicValue);
+ }
+
/*
* We fail if the public value is the point at infinity, since
* this produces predictable results.
@@ -530,8 +600,8 @@ ECDH_Derive(SECItem *publicValue,
MP_DIGITS(&k) = 0;
memset(derivedSecret, 0, sizeof *derivedSecret);
len = (ecParams->fieldID.size + 7) >> 3;
- pointQ.len = 2 * len + 1;
- if ((pointQ.data = PORT_Alloc(2 * len + 1)) == NULL)
+ pointQ.len = ecParams->pointSize;
+ if ((pointQ.data = PORT_Alloc(ecParams->pointSize)) == NULL)
goto cleanup;
CHECK_MPI_OK(mp_init(&k));
@@ -547,8 +617,9 @@ ECDH_Derive(SECItem *publicValue,
}
/* Multiply our private key and peer's public point */
- if (ec_points_mul(ecParams, NULL, &k, publicValue, &pointQ) != SECSuccess)
+ if (ec_points_mul(ecParams, NULL, &k, publicValue, &pointQ) != SECSuccess) {
goto cleanup;
+ }
if (ec_point_at_infinity(&pointQ)) {
PORT_SetError(SEC_ERROR_BAD_KEY); /* XXX better error code? */
goto cleanup;
@@ -577,7 +648,7 @@ cleanup:
}
if (pointQ.data) {
- PORT_ZFree(pointQ.data, 2 * len + 1);
+ PORT_ZFree(pointQ.data, ecParams->pointSize);
}
#else
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
@@ -692,8 +763,8 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
**
** Compute kG
*/
- kGpoint.len = 2 * flen + 1;
- kGpoint.data = PORT_Alloc(2 * flen + 1);
+ kGpoint.len = ecParams->pointSize;
+ kGpoint.data = PORT_Alloc(ecParams->pointSize);
if ((kGpoint.data == NULL) ||
(ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint) != SECSuccess))
goto cleanup;
@@ -812,7 +883,7 @@ cleanup:
}
if (kGpoint.data) {
- PORT_ZFree(kGpoint.data, 2 * flen + 1);
+ PORT_ZFree(kGpoint.data, ecParams->pointSize);
}
if (err) {
@@ -931,7 +1002,7 @@ ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature,
}
slen = signature->len / 2;
- SECITEM_AllocItem(NULL, &pointC, 2 * flen + 1);
+ SECITEM_AllocItem(NULL, &pointC, ecParams->pointSize);
if (pointC.data == NULL)
goto cleanup;
diff --git a/lib/freebl/ec.h b/lib/freebl/ec.h
index 546d6fe21..bb65e82cd 100644
--- a/lib/freebl/ec.h
+++ b/lib/freebl/ec.h
@@ -9,5 +9,13 @@
#define ANSI_X962_CURVE_OID_TOTAL_LEN 10
#define SECG_CURVE_OID_TOTAL_LEN 7
+#define PKIX_NEWCURVES_OID_TOTAL_LEN 11
+
+struct ECMethodStr {
+ ECCurveName name;
+ SECStatus (*mul)(SECItem *result, SECItem *scalar, SECItem *point);
+ SECStatus (*validate)(const SECItem *point);
+};
+typedef struct ECMethodStr ECMethod;
#endif /* __ec_h_ */
diff --git a/lib/freebl/ecdecode.c b/lib/freebl/ecdecode.c
index a06958291..cad661691 100644
--- a/lib/freebl/ecdecode.c
+++ b/lib/freebl/ecdecode.c
@@ -35,6 +35,9 @@ hexString2SECItem(PLArenaPool *arena, SECItem *item, const char *str)
int byteval = 0;
int tmp = PORT_Strlen(str);
+ PORT_Assert(arena);
+ PORT_Assert(item);
+
if ((tmp % 2) != 0)
return NULL;
@@ -82,7 +85,9 @@ EC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
dstParams->type = srcParams->type;
dstParams->fieldID.size = srcParams->fieldID.size;
dstParams->fieldID.type = srcParams->fieldID.type;
- if (srcParams->fieldID.type == ec_field_GFp) {
+ dstParams->pointSize = srcParams->pointSize;
+ if (srcParams->fieldID.type == ec_field_GFp ||
+ srcParams->fieldID.type == ec_field_plain) {
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->fieldID.u.prime,
&srcParams->fieldID.u.prime));
} else {
@@ -130,7 +135,9 @@ gf_populate_params(ECCurveName name, ECFieldType field_type, ECParams *params)
CHECK_OK(curveParams);
params->fieldID.size = curveParams->size;
params->fieldID.type = field_type;
- if (field_type == ec_field_GFp) {
+ params->pointSize = curveParams->pointSize;
+ if (field_type == ec_field_GFp ||
+ field_type == ec_field_plain) {
CHECK_OK(hexString2SECItem(params->arena, &params->fieldID.u.prime,
curveParams->irr));
} else {
@@ -176,7 +183,8 @@ EC_FillParams(PLArenaPool *arena, const SECItem *encodedParams,
#endif
if ((encodedParams->len != ANSI_X962_CURVE_OID_TOTAL_LEN) &&
- (encodedParams->len != SECG_CURVE_OID_TOTAL_LEN)) {
+ (encodedParams->len != SECG_CURVE_OID_TOTAL_LEN) &&
+ (encodedParams->len != PKIX_NEWCURVES_OID_TOTAL_LEN)) {
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
return SECFailure;
};
@@ -565,6 +573,11 @@ EC_FillParams(PLArenaPool *arena, const SECItem *encodedParams,
params));
break;
+ case SEC_OID_CURVE25519:
+ /* Populate params for Curve25519 */
+ CHECK_SEC_OK(gf_populate_params(ECCurve25519, ec_field_plain, params));
+ break;
+
default:
break;
};
diff --git a/lib/freebl/ecl/curve25519_32.c b/lib/freebl/ecl/curve25519_32.c
new file mode 100644
index 000000000..0122961e6
--- /dev/null
+++ b/lib/freebl/ecl/curve25519_32.c
@@ -0,0 +1,390 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Derived from public domain code by Matthew Dempsky and D. J. Bernstein.
+ */
+
+#include "ecl-priv.h"
+#include "mpi.h"
+
+#include <stdint.h>
+#include <stdio.h>
+
+typedef uint32_t elem[32];
+
+/*
+ * Add two field elements.
+ * out = a + b
+ */
+static void
+add(elem out, const elem a, const elem b)
+{
+ uint32_t j;
+ uint32_t u = 0;
+ for (j = 0; j < 31; ++j) {
+ u += a[j] + b[j];
+ out[j] = u & 0xFF;
+ u >>= 8;
+ }
+ u += a[31] + b[31];
+ out[31] = u;
+}
+
+/*
+ * Subtract two field elements.
+ * out = a - b
+ */
+static void
+sub(elem out, const elem a, const elem b)
+{
+ uint32_t j;
+ uint32_t u;
+ u = 218;
+ for (j = 0; j < 31; ++j) {
+ u += a[j] + 0xFF00 - b[j];
+ out[j] = u & 0xFF;
+ u >>= 8;
+ }
+ u += a[31] - b[31];
+ out[31] = u;
+}
+
+/*
+ * "Squeeze" an element after multiplication (and square).
+ */
+static void
+squeeze(elem a)
+{
+ uint32_t j;
+ uint32_t u;
+ u = 0;
+ for (j = 0; j < 31; ++j) {
+ u += a[j];
+ a[j] = u & 0xFF;
+ u >>= 8;
+ }
+ u += a[31];
+ a[31] = u & 0x7F;
+ u = 19 * (u >> 7);
+ for (j = 0; j < 31; ++j) {
+ u += a[j];
+ a[j] = u & 0xFF;
+ u >>= 8;
+ }
+ a[31] += u;
+}
+
+static const elem minusp = { 19, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 128 };
+
+/*
+ * Reduce point a by 2^255-19
+ */
+static void
+reduce(elem a)
+{
+ elem aorig;
+ uint32_t j;
+ uint32_t negative;
+
+ for (j = 0; j < 32; ++j) {
+ aorig[j] = a[j];
+ }
+ add(a, a, minusp);
+ negative = 1 + ~((a[31] >> 7) & 1);
+ for (j = 0; j < 32; ++j) {
+ a[j] ^= negative & (aorig[j] ^ a[j]);
+ }
+}
+
+/*
+ * Multiplication and squeeze
+ * out = a * b
+ */
+static void
+mult(elem out, const elem a, const elem b)
+{
+ uint32_t i;
+ uint32_t j;
+ uint32_t u;
+
+ for (i = 0; i < 32; ++i) {
+ u = 0;
+ for (j = 0; j <= i; ++j) {
+ u += a[j] * b[i - j];
+ }
+ for (j = i + 1; j < 32; ++j) {
+ u += 38 * a[j] * b[i + 32 - j];
+ }
+ out[i] = u;
+ }
+ squeeze(out);
+}
+
+/*
+ * Multiplication
+ * out = 121665 * a
+ */
+static void
+mult121665(elem out, const elem a)
+{
+ uint32_t j;
+ uint32_t u;
+
+ u = 0;
+ for (j = 0; j < 31; ++j) {
+ u += 121665 * a[j];
+ out[j] = u & 0xFF;
+ u >>= 8;
+ }
+ u += 121665 * a[31];
+ out[31] = u & 0x7F;
+ u = 19 * (u >> 7);
+ for (j = 0; j < 31; ++j) {
+ u += out[j];
+ out[j] = u & 0xFF;
+ u >>= 8;
+ }
+ u += out[j];
+ out[j] = u;
+}
+
+/*
+ * Square a and squeeze the result.
+ * out = a * a
+ */
+static void
+square(elem out, const elem a)
+{
+ uint32_t i;
+ uint32_t j;
+ uint32_t u;
+
+ for (i = 0; i < 32; ++i) {
+ u = 0;
+ for (j = 0; j < i - j; ++j) {
+ u += a[j] * a[i - j];
+ }
+ for (j = i + 1; j < i + 32 - j; ++j) {
+ u += 38 * a[j] * a[i + 32 - j];
+ }
+ u *= 2;
+ if ((i & 1) == 0) {
+ u += a[i / 2] * a[i / 2];
+ u += 38 * a[i / 2 + 16] * a[i / 2 + 16];
+ }
+ out[i] = u;
+ }
+ squeeze(out);
+}
+
+/*
+ * Constant time swap between r and s depending on b
+ */
+static void
+cswap(uint32_t p[64], uint32_t q[64], uint32_t b)
+{
+ uint32_t j;
+ uint32_t swap = 1 + ~b;
+
+ for (j = 0; j < 64; ++j) {
+ const uint32_t t = swap & (p[j] ^ q[j]);
+ p[j] ^= t;
+ q[j] ^= t;
+ }
+}
+
+/*
+ * Montgomery ladder
+ */
+static void
+monty(elem x_2_out, elem z_2_out,
+ const elem point, const elem scalar)
+{
+ uint32_t x_3[64] = { 0 };
+ uint32_t x_2[64] = { 0 };
+ uint32_t a0[64];
+ uint32_t a1[64];
+ uint32_t b0[64];
+ uint32_t b1[64];
+ uint32_t c1[64];
+ uint32_t r[32];
+ uint32_t s[32];
+ uint32_t t[32];
+ uint32_t u[32];
+ uint32_t swap = 0;
+ uint32_t k_t = 0;
+ int j;
+
+ for (j = 0; j < 32; ++j) {
+ x_3[j] = point[j];
+ }
+ x_3[32] = 1;
+ x_2[0] = 1;
+
+ for (j = 254; j >= 0; --j) {
+ k_t = (scalar[j >> 3] >> (j & 7)) & 1;
+ swap ^= k_t;
+ cswap(x_2, x_3, swap);
+ swap = k_t;
+ add(a0, x_2, x_2 + 32);
+ sub(a0 + 32, x_2, x_2 + 32);
+ add(a1, x_3, x_3 + 32);
+ sub(a1 + 32, x_3, x_3 + 32);
+ square(b0, a0);
+ square(b0 + 32, a0 + 32);
+ mult(b1, a1, a0 + 32);
+ mult(b1 + 32, a1 + 32, a0);
+ add(c1, b1, b1 + 32);
+ sub(c1 + 32, b1, b1 + 32);
+ square(r, c1 + 32);
+ sub(s, b0, b0 + 32);
+ mult121665(t, s);
+ add(u, t, b0);
+ mult(x_2, b0, b0 + 32);
+ mult(x_2 + 32, s, u);
+ square(x_3, c1);
+ mult(x_3 + 32, r, point);
+ }
+
+ cswap(x_2, x_3, swap);
+ for (j = 0; j < 32; ++j) {
+ x_2_out[j] = x_2[j];
+ }
+ for (j = 0; j < 32; ++j) {
+ z_2_out[j] = x_2[j + 32];
+ }
+}
+
+static void
+recip(elem out, const elem z)
+{
+ elem z2;
+ elem z9;
+ elem z11;
+ elem z2_5_0;
+ elem z2_10_0;
+ elem z2_20_0;
+ elem z2_50_0;
+ elem z2_100_0;
+ elem t0;
+ elem t1;
+ int i;
+
+ /* 2 */ square(z2, z);
+ /* 4 */ square(t1, z2);
+ /* 8 */ square(t0, t1);
+ /* 9 */ mult(z9, t0, z);
+ /* 11 */ mult(z11, z9, z2);
+ /* 22 */ square(t0, z11);
+ /* 2^5 - 2^0 = 31 */ mult(z2_5_0, t0, z9);
+
+ /* 2^6 - 2^1 */ square(t0, z2_5_0);
+ /* 2^7 - 2^2 */ square(t1, t0);
+ /* 2^8 - 2^3 */ square(t0, t1);
+ /* 2^9 - 2^4 */ square(t1, t0);
+ /* 2^10 - 2^5 */ square(t0, t1);
+ /* 2^10 - 2^0 */ mult(z2_10_0, t0, z2_5_0);
+
+ /* 2^11 - 2^1 */ square(t0, z2_10_0);
+ /* 2^12 - 2^2 */ square(t1, t0);
+ /* 2^20 - 2^10 */
+ for (i = 2; i < 10; i += 2) {
+ square(t0, t1);
+ square(t1, t0);
+ }
+ /* 2^20 - 2^0 */ mult(z2_20_0, t1, z2_10_0);
+
+ /* 2^21 - 2^1 */ square(t0, z2_20_0);
+ /* 2^22 - 2^2 */ square(t1, t0);
+ /* 2^40 - 2^20 */
+ for (i = 2; i < 20; i += 2) {
+ square(t0, t1);
+ square(t1, t0);
+ }
+ /* 2^40 - 2^0 */ mult(t0, t1, z2_20_0);
+
+ /* 2^41 - 2^1 */ square(t1, t0);
+ /* 2^42 - 2^2 */ square(t0, t1);
+ /* 2^50 - 2^10 */
+ for (i = 2; i < 10; i += 2) {
+ square(t1, t0);
+ square(t0, t1);
+ }
+ /* 2^50 - 2^0 */ mult(z2_50_0, t0, z2_10_0);
+
+ /* 2^51 - 2^1 */ square(t0, z2_50_0);
+ /* 2^52 - 2^2 */ square(t1, t0);
+ /* 2^100 - 2^50 */
+ for (i = 2; i < 50; i += 2) {
+ square(t0, t1);
+ square(t1, t0);
+ }
+ /* 2^100 - 2^0 */ mult(z2_100_0, t1, z2_50_0);
+
+ /* 2^101 - 2^1 */ square(t1, z2_100_0);
+ /* 2^102 - 2^2 */ square(t0, t1);
+ /* 2^200 - 2^100 */
+ for (i = 2; i < 100; i += 2) {
+ square(t1, t0);
+ square(t0, t1);
+ }
+ /* 2^200 - 2^0 */ mult(t1, t0, z2_100_0);
+
+ /* 2^201 - 2^1 */ square(t0, t1);
+ /* 2^202 - 2^2 */ square(t1, t0);
+ /* 2^250 - 2^50 */
+ for (i = 2; i < 50; i += 2) {
+ square(t0, t1);
+ square(t1, t0);
+ }
+ /* 2^250 - 2^0 */ mult(t0, t1, z2_50_0);
+
+ /* 2^251 - 2^1 */ square(t1, t0);
+ /* 2^252 - 2^2 */ square(t0, t1);
+ /* 2^253 - 2^3 */ square(t1, t0);
+ /* 2^254 - 2^4 */ square(t0, t1);
+ /* 2^255 - 2^5 */ square(t1, t0);
+ /* 2^255 - 21 */ mult(out, t1, z11);
+}
+
+/*
+ * Computes q = Curve25519(p, s)
+ */
+SECStatus
+ec_Curve25519_mul(PRUint8 *q, const PRUint8 *s, const PRUint8 *p)
+{
+ elem point = { 0 };
+ elem x_2 = { 0 };
+ elem z_2 = { 0 };
+ elem X = { 0 };
+ elem scalar = { 0 };
+ uint32_t i;
+
+ /* read and mask scalar */
+ for (i = 0; i < 32; ++i) {
+ scalar[i] = s[i];
+ }
+ scalar[0] &= 0xF8;
+ scalar[31] &= 0x7F;
+ scalar[31] |= 64;
+
+ /* read and mask point */
+ for (i = 0; i < 32; ++i) {
+ point[i] = p[i];
+ }
+ point[31] &= 0x7F;
+
+ monty(x_2, z_2, point, scalar);
+ recip(z_2, z_2);
+ mult(X, x_2, z_2);
+ reduce(X);
+ for (i = 0; i < 32; ++i) {
+ q[i] = X[i];
+ }
+ return 0;
+}
diff --git a/lib/freebl/ecl/curve25519_64.c b/lib/freebl/ecl/curve25519_64.c
new file mode 100644
index 000000000..fa6e00930
--- /dev/null
+++ b/lib/freebl/ecl/curve25519_64.c
@@ -0,0 +1,514 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Derived from public domain C code by Adan Langley and Daniel J. Bernstein
+ */
+
+#include "uint128.h"
+
+#include "ecl-priv.h"
+#include "mpi.h"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+typedef uint8_t u8;
+typedef uint64_t felem;
+
+/* Sum two numbers: output += in */
+static void
+fsum(felem *output, const felem *in)
+{
+ unsigned i;
+ for (i = 0; i < 5; ++i) {
+ output[i] += in[i];
+ }
+}
+
+/* Find the difference of two numbers: output = in - output
+ * (note the order of the arguments!)
+ */
+static void
+fdifference_backwards(felem *ioutput, const felem *iin)
+{
+ static const int64_t twotothe51 = ((int64_t)1l << 51);
+ const int64_t *in = (const int64_t *)iin;
+ int64_t *out = (int64_t *)ioutput;
+
+ out[0] = in[0] - out[0];
+ out[1] = in[1] - out[1];
+ out[2] = in[2] - out[2];
+ out[3] = in[3] - out[3];
+ out[4] = in[4] - out[4];
+
+ // An arithmetic shift right of 63 places turns a positive number to 0 and a
+ // negative number to all 1's. This gives us a bitmask that lets us avoid
+ // side-channel prone branches.
+ int64_t t;
+
+#define NEGCHAIN(a, b) \
+ t = out[a] >> 63; \
+ out[a] += twotothe51 & t; \
+ out[b] -= 1 & t;
+
+#define NEGCHAIN19(a, b) \
+ t = out[a] >> 63; \
+ out[a] += twotothe51 & t; \
+ out[b] -= 19 & t;
+
+ NEGCHAIN(0, 1);
+ NEGCHAIN(1, 2);
+ NEGCHAIN(2, 3);
+ NEGCHAIN(3, 4);
+ NEGCHAIN19(4, 0);
+ NEGCHAIN(0, 1);
+ NEGCHAIN(1, 2);
+ NEGCHAIN(2, 3);
+ NEGCHAIN(3, 4);
+}
+
+/* Multiply a number by a scalar: output = in * scalar */
+static void
+fscalar_product(felem *output, const felem *in,
+ const felem scalar)
+{
+ uint128_t tmp, tmp2;
+
+ tmp = mul6464(in[0], scalar);
+ output[0] = mask51(tmp);
+
+ tmp2 = mul6464(in[1], scalar);
+ tmp = add128(tmp2, rshift128(tmp, 51));
+ output[1] = mask51(tmp);
+
+ tmp2 = mul6464(in[2], scalar);
+ tmp = add128(tmp2, rshift128(tmp, 51));
+ output[2] = mask51(tmp);
+
+ tmp2 = mul6464(in[3], scalar);
+ tmp = add128(tmp2, rshift128(tmp, 51));
+ output[3] = mask51(tmp);
+
+ tmp2 = mul6464(in[4], scalar);
+ tmp = add128(tmp2, rshift128(tmp, 51));
+ output[4] = mask51(tmp);
+
+ output[0] += mask_lower(rshift128(tmp, 51)) * 19;
+}
+
+/* Multiply two numbers: output = in2 * in
+ *
+ * output must be distinct to both inputs. The inputs are reduced coefficient
+ * form, the output is not.
+ */
+static void
+fmul(felem *output, const felem *in2, const felem *in)
+{
+ uint128_t t0, t1, t2, t3, t4, t5, t6, t7, t8;
+
+ t0 = mul6464(in[0], in2[0]);
+ t1 = add128(mul6464(in[1], in2[0]), mul6464(in[0], in2[1]));
+ t2 = add128(add128(mul6464(in[0], in2[2]),
+ mul6464(in[2], in2[0])),
+ mul6464(in[1], in2[1]));
+ t3 = add128(add128(add128(mul6464(in[0], in2[3]),
+ mul6464(in[3], in2[0])),
+ mul6464(in[1], in2[2])),
+ mul6464(in[2], in2[1]));
+ t4 = add128(add128(add128(add128(mul6464(in[0], in2[4]),
+ mul6464(in[4], in2[0])),
+ mul6464(in[3], in2[1])),
+ mul6464(in[1], in2[3])),
+ mul6464(in[2], in2[2]));
+ t5 = add128(add128(add128(mul6464(in[4], in2[1]),
+ mul6464(in[1], in2[4])),
+ mul6464(in[2], in2[3])),
+ mul6464(in[3], in2[2]));
+ t6 = add128(add128(mul6464(in[4], in2[2]),
+ mul6464(in[2], in2[4])),
+ mul6464(in[3], in2[3]));
+ t7 = add128(mul6464(in[3], in2[4]), mul6464(in[4], in2[3]));
+ t8 = mul6464(in[4], in2[4]);
+
+ t0 = add128(t0, mul12819(t5));
+ t1 = add128(t1, mul12819(t6));
+ t2 = add128(t2, mul12819(t7));
+ t3 = add128(t3, mul12819(t8));
+
+ t1 = add128(t1, rshift128(t0, 51));
+ t0 = mask51full(t0);
+ t2 = add128(t2, rshift128(t1, 51));
+ t1 = mask51full(t1);
+ t3 = add128(t3, rshift128(t2, 51));
+ t4 = add128(t4, rshift128(t3, 51));
+ t0 = add128(t0, mul12819(rshift128(t4, 51)));
+ t1 = add128(t1, rshift128(t0, 51));
+ t2 = mask51full(t2);
+ t2 = add128(t2, rshift128(t1, 51));
+
+ output[0] = mask51(t0);
+ output[1] = mask51(t1);
+ output[2] = mask_lower(t2);
+ output[3] = mask51(t3);
+ output[4] = mask51(t4);
+}
+
+static void
+fsquare(felem *output, const felem *in)
+{
+ uint128_t t0, t1, t2, t3, t4, t5, t6, t7, t8;
+
+ t0 = mul6464(in[0], in[0]);
+ t1 = lshift128(mul6464(in[0], in[1]), 1);
+ t2 = add128(lshift128(mul6464(in[0], in[2]), 1),
+ mul6464(in[1], in[1]));
+ t3 = add128(lshift128(mul6464(in[0], in[3]), 1),
+ lshift128(mul6464(in[1], in[2]), 1));
+ t4 = add128(add128(lshift128(mul6464(in[0], in[4]), 1),
+ lshift128(mul6464(in[3], in[1]), 1)),
+ mul6464(in[2], in[2]));
+ t5 = add128(lshift128(mul6464(in[4], in[1]), 1),
+ lshift128(mul6464(in[2], in[3]), 1));
+ t6 = add128(lshift128(mul6464(in[4], in[2]), 1),
+ mul6464(in[3], in[3]));
+ t7 = lshift128(mul6464(in[3], in[4]), 1);
+ t8 = mul6464(in[4], in[4]);
+
+ t0 = add128(t0, mul12819(t5));
+ t1 = add128(t1, mul12819(t6));
+ t2 = add128(t2, mul12819(t7));
+ t3 = add128(t3, mul12819(t8));
+
+ t1 = add128(t1, rshift128(t0, 51));
+ t0 = mask51full(t0);
+ t2 = add128(t2, rshift128(t1, 51));
+ t1 = mask51full(t1);
+ t3 = add128(t3, rshift128(t2, 51));
+ t4 = add128(t4, rshift128(t3, 51));
+ t0 = add128(t0, mul12819(rshift128(t4, 51)));
+ t1 = add128(t1, rshift128(t0, 51));
+
+ output[0] = mask51(t0);
+ output[1] = mask_lower(t1);
+ output[2] = mask51(t2);
+ output[3] = mask51(t3);
+ output[4] = mask51(t4);
+}
+
+/* Take a 32-byte number and expand it into polynomial form */
+static void
+fexpand(felem *output, const u8 *in)
+{
+ output[0] = *((const uint64_t *)(in)) & MASK51;
+ output[1] = (*((const uint64_t *)(in + 6)) >> 3) & MASK51;
+ output[2] = (*((const uint64_t *)(in + 12)) >> 6) & MASK51;
+ output[3] = (*((const uint64_t *)(in + 19)) >> 1) & MASK51;
+ output[4] = (*((const uint64_t *)(in + 25)) >> 4) & MASK51;
+}
+
+/* Take a fully reduced polynomial form number and contract it into a
+ * 32-byte array
+ */
+static void
+fcontract(u8 *output, const felem *input)
+{
+ uint128_t t0 = init128x(input[0]);
+ uint128_t t1 = init128x(input[1]);
+ uint128_t t2 = init128x(input[2]);
+ uint128_t t3 = init128x(input[3]);
+ uint128_t t4 = init128x(input[4]);
+ uint128_t tmp = init128x(19);
+
+ t1 = add128(t1, rshift128(t0, 51));
+ t0 = mask51full(t0);
+ t2 = add128(t2, rshift128(t1, 51));
+ t1 = mask51full(t1);
+ t3 = add128(t3, rshift128(t2, 51));
+ t2 = mask51full(t2);
+ t4 = add128(t4, rshift128(t3, 51));
+ t3 = mask51full(t3);
+ t0 = add128(t0, mul12819(rshift128(t4, 51)));
+ t4 = mask51full(t4);
+
+ t1 = add128(t1, rshift128(t0, 51));
+ t0 = mask51full(t0);
+ t2 = add128(t2, rshift128(t1, 51));
+ t1 = mask51full(t1);
+ t3 = add128(t3, rshift128(t2, 51));
+ t2 = mask51full(t2);
+ t4 = add128(t4, rshift128(t3, 51));
+ t3 = mask51full(t3);
+ t0 = add128(t0, mul12819(rshift128(t4, 51)));
+ t4 = mask51full(t4);
+
+ /* now t is between 0 and 2^255-1, properly carried. */
+ /* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */
+
+ t0 = add128(t0, tmp);
+
+ t1 = add128(t1, rshift128(t0, 51));
+ t0 = mask51full(t0);
+ t2 = add128(t2, rshift128(t1, 51));
+ t1 = mask51full(t1);
+ t3 = add128(t3, rshift128(t2, 51));
+ t2 = mask51full(t2);
+ t4 = add128(t4, rshift128(t3, 51));
+ t3 = mask51full(t3);
+ t0 = add128(t0, mul12819(rshift128(t4, 51)));
+ t4 = mask51full(t4);
+
+ /* now between 19 and 2^255-1 in both cases, and offset by 19. */
+
+ t0 = add128(t0, init128x(0x8000000000000 - 19));
+ tmp = init128x(0x8000000000000 - 1);
+ t1 = add128(t1, tmp);
+ t2 = add128(t2, tmp);
+ t3 = add128(t3, tmp);
+ t4 = add128(t4, tmp);
+
+ /* now between 2^255 and 2^256-20, and offset by 2^255. */
+
+ t1 = add128(t1, rshift128(t0, 51));
+ t0 = mask51full(t0);
+ t2 = add128(t2, rshift128(t1, 51));
+ t1 = mask51full(t1);
+ t3 = add128(t3, rshift128(t2, 51));
+ t2 = mask51full(t2);
+ t4 = add128(t4, rshift128(t3, 51));
+ t3 = mask51full(t3);
+ t4 = mask51full(t4);
+
+ *((uint64_t *)(output)) = mask_lower(t0) | mask_lower(t1) << 51;
+ *((uint64_t *)(output + 8)) = (mask_lower(t1) >> 13) | (mask_lower(t2) << 38);
+ *((uint64_t *)(output + 16)) = (mask_lower(t2) >> 26) | (mask_lower(t3) << 25);
+ *((uint64_t *)(output + 24)) = (mask_lower(t3) >> 39) | (mask_lower(t4) << 12);
+}
+
+/* Input: Q, Q', Q-Q'
+ * Output: 2Q, Q+Q'
+ *
+ * x2 z3: long form
+ * x3 z3: long form
+ * x z: short form, destroyed
+ * xprime zprime: short form, destroyed
+ * qmqp: short form, preserved
+ */
+static void
+fmonty(felem *x2, felem *z2, /* output 2Q */
+ felem *x3, felem *z3, /* output Q + Q' */
+ felem *x, felem *z, /* input Q */
+ felem *xprime, felem *zprime, /* input Q' */
+ const felem *qmqp /* input Q - Q' */)
+{
+ felem origx[5], origxprime[5], zzz[5], xx[5], zz[5], xxprime[5], zzprime[5],
+ zzzprime[5];
+
+ memcpy(origx, x, 5 * sizeof(felem));
+ fsum(x, z);
+ fdifference_backwards(z, origx); // does x - z
+
+ memcpy(origxprime, xprime, sizeof(felem) * 5);
+ fsum(xprime, zprime);
+ fdifference_backwards(zprime, origxprime);
+ fmul(xxprime, xprime, z);
+ fmul(zzprime, x, zprime);
+ memcpy(origxprime, xxprime, sizeof(felem) * 5);
+ fsum(xxprime, zzprime);
+ fdifference_backwards(zzprime, origxprime);
+ fsquare(x3, xxprime);
+ fsquare(zzzprime, zzprime);
+ fmul(z3, zzzprime, qmqp);
+
+ fsquare(xx, x);
+ fsquare(zz, z);
+ fmul(x2, xx, zz);
+ fdifference_backwards(zz, xx); // does zz = xx - zz
+ fscalar_product(zzz, zz, 121665);
+ fsum(zzz, xx);
+ fmul(z2, zz, zzz);
+}
+
+// -----------------------------------------------------------------------------
+// Maybe swap the contents of two felem arrays (@a and @b), each @len elements
+// long. Perform the swap iff @swap is non-zero.
+//
+// This function performs the swap without leaking any side-channel
+// information.
+// -----------------------------------------------------------------------------
+static void
+swap_conditional(felem *a, felem *b, unsigned len, felem iswap)
+{
+ unsigned i;
+ const felem swap = 1 + ~iswap;
+
+ for (i = 0; i < len; ++i) {
+ const felem x = swap & (a[i] ^ b[i]);
+ a[i] ^= x;
+ b[i] ^= x;
+ }
+}
+
+/* Calculates nQ where Q is the x-coordinate of a point on the curve
+ *
+ * resultx/resultz: the x coordinate of the resulting curve point (short form)
+ * n: a 32-byte number
+ * q: a point of the curve (short form)
+ */
+static void
+cmult(felem *resultx, felem *resultz, const u8 *n, const felem *q)
+{
+ felem a[5] = { 0 }, b[5] = { 1 }, c[5] = { 1 }, d[5] = { 0 };
+ felem *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t;
+ felem e[5] = { 0 }, f[5] = { 1 }, g[5] = { 0 }, h[5] = { 1 };
+ felem *nqpqx2 = e, *nqpqz2 = f, *nqx2 = g, *nqz2 = h;
+
+ unsigned i, j;
+
+ memcpy(nqpqx, q, sizeof(felem) * 5);
+
+ for (i = 0; i < 32; ++i) {
+ u8 byte = n[31 - i];
+ for (j = 0; j < 8; ++j) {
+ const felem bit = byte >> 7;
+
+ swap_conditional(nqx, nqpqx, 5, bit);
+ swap_conditional(nqz, nqpqz, 5, bit);
+ fmonty(nqx2, nqz2, nqpqx2, nqpqz2, nqx, nqz, nqpqx, nqpqz, q);
+ swap_conditional(nqx2, nqpqx2, 5, bit);
+ swap_conditional(nqz2, nqpqz2, 5, bit);
+
+ t = nqx;
+ nqx = nqx2;
+ nqx2 = t;
+ t = nqz;
+ nqz = nqz2;
+ nqz2 = t;
+ t = nqpqx;
+ nqpqx = nqpqx2;
+ nqpqx2 = t;
+ t = nqpqz;
+ nqpqz = nqpqz2;
+ nqpqz2 = t;
+
+ byte <<= 1;
+ }
+ }
+
+ memcpy(resultx, nqx, sizeof(felem) * 5);
+ memcpy(resultz, nqz, sizeof(felem) * 5);
+}
+
+// -----------------------------------------------------------------------------
+// Shamelessly copied from djb's code
+// -----------------------------------------------------------------------------
+static void
+crecip(felem *out, const felem *z)
+{
+ felem z2[5];
+ felem z9[5];
+ felem z11[5];
+ felem z2_5_0[5];
+ felem z2_10_0[5];
+ felem z2_20_0[5];
+ felem z2_50_0[5];
+ felem z2_100_0[5];
+ felem t0[5];
+ felem t1[5];
+ int i;
+
+ /* 2 */ fsquare(z2, z);
+ /* 4 */ fsquare(t1, z2);
+ /* 8 */ fsquare(t0, t1);
+ /* 9 */ fmul(z9, t0, z);
+ /* 11 */ fmul(z11, z9, z2);
+ /* 22 */ fsquare(t0, z11);
+ /* 2^5 - 2^0 = 31 */ fmul(z2_5_0, t0, z9);
+
+ /* 2^6 - 2^1 */ fsquare(t0, z2_5_0);
+ /* 2^7 - 2^2 */ fsquare(t1, t0);
+ /* 2^8 - 2^3 */ fsquare(t0, t1);
+ /* 2^9 - 2^4 */ fsquare(t1, t0);
+ /* 2^10 - 2^5 */ fsquare(t0, t1);
+ /* 2^10 - 2^0 */ fmul(z2_10_0, t0, z2_5_0);
+
+ /* 2^11 - 2^1 */ fsquare(t0, z2_10_0);
+ /* 2^12 - 2^2 */ fsquare(t1, t0);
+ /* 2^20 - 2^10 */ for (i = 2; i < 10; i += 2) {
+ fsquare(t0, t1);
+ fsquare(t1, t0);
+ }
+ /* 2^20 - 2^0 */ fmul(z2_20_0, t1, z2_10_0);
+
+ /* 2^21 - 2^1 */ fsquare(t0, z2_20_0);
+ /* 2^22 - 2^2 */ fsquare(t1, t0);
+ /* 2^40 - 2^20 */ for (i = 2; i < 20; i += 2) {
+ fsquare(t0, t1);
+ fsquare(t1, t0);
+ }
+ /* 2^40 - 2^0 */ fmul(t0, t1, z2_20_0);
+
+ /* 2^41 - 2^1 */ fsquare(t1, t0);
+ /* 2^42 - 2^2 */ fsquare(t0, t1);
+ /* 2^50 - 2^10 */ for (i = 2; i < 10; i += 2) {
+ fsquare(t1, t0);
+ fsquare(t0, t1);
+ }
+ /* 2^50 - 2^0 */ fmul(z2_50_0, t0, z2_10_0);
+
+ /* 2^51 - 2^1 */ fsquare(t0, z2_50_0);
+ /* 2^52 - 2^2 */ fsquare(t1, t0);
+ /* 2^100 - 2^50 */ for (i = 2; i < 50; i += 2) {
+ fsquare(t0, t1);
+ fsquare(t1, t0);
+ }
+ /* 2^100 - 2^0 */ fmul(z2_100_0, t1, z2_50_0);
+
+ /* 2^101 - 2^1 */ fsquare(t1, z2_100_0);
+ /* 2^102 - 2^2 */ fsquare(t0, t1);
+ /* 2^200 - 2^100 */ for (i = 2; i < 100; i += 2) {
+ fsquare(t1, t0);
+ fsquare(t0, t1);
+ }
+ /* 2^200 - 2^0 */ fmul(t1, t0, z2_100_0);
+
+ /* 2^201 - 2^1 */ fsquare(t0, t1);
+ /* 2^202 - 2^2 */ fsquare(t1, t0);
+ /* 2^250 - 2^50 */ for (i = 2; i < 50; i += 2) {
+ fsquare(t0, t1);
+ fsquare(t1, t0);
+ }
+ /* 2^250 - 2^0 */ fmul(t0, t1, z2_50_0);
+
+ /* 2^251 - 2^1 */ fsquare(t1, t0);
+ /* 2^252 - 2^2 */ fsquare(t0, t1);
+ /* 2^253 - 2^3 */ fsquare(t1, t0);
+ /* 2^254 - 2^4 */ fsquare(t0, t1);
+ /* 2^255 - 2^5 */ fsquare(t1, t0);
+ /* 2^255 - 21 */ fmul(out, t1, z11);
+}
+
+SECStatus
+ec_Curve25519_mul(uint8_t *mypublic, const uint8_t *secret,
+ const uint8_t *basepoint)
+{
+ felem bp[5], x[5], z[5], zmone[5];
+ uint8_t e[32];
+ int i;
+
+ for (i = 0; i < 32; ++i) {
+ e[i] = secret[i];
+ }
+ e[0] &= 248;
+ e[31] &= 127;
+ e[31] |= 64;
+ fexpand(bp, basepoint);
+ cmult(x, z, e, bp);
+ crecip(zmone, z);
+ fmul(z, x, zmone);
+ fcontract(mypublic, z);
+
+ return 0;
+}
diff --git a/lib/freebl/ecl/ecl-curve.h b/lib/freebl/ecl/ecl-curve.h
index c295dd820..1d2c90247 100644
--- a/lib/freebl/ecl/ecl-curve.h
+++ b/lib/freebl/ecl/ecl-curve.h
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "certt.h"
#include "ecl-exp.h"
#include <stdlib.h>
@@ -19,7 +20,8 @@ static const ECCurveParams ecCurve_NIST_P256 = {
"5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
"6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
"4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
- "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", 1
+ "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
+ 1, 128, 65, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
};
static const ECCurveParams ecCurve_NIST_P384 = {
@@ -30,7 +32,7 @@ static const ECCurveParams ecCurve_NIST_P384 = {
"AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
"3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
- 1
+ 1, 192, 97, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
};
static const ECCurveParams ecCurve_NIST_P521 = {
@@ -41,7 +43,18 @@ static const ECCurveParams ecCurve_NIST_P521 = {
"00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
"011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
- 1
+ 1, 256, 133, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
+};
+
+static const ECCurveParams ecCurve25519 = {
+ "Curve25519", ECField_GFp, 255,
+ "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed",
+ "076D06",
+ "00",
+ "0900000000000000000000000000000000000000000000000000000000000000",
+ "20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9",
+ "1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed",
+ 8, 128, 32, KU_KEY_AGREEMENT
};
/* mapping between ECCurveName enum and pointers to ECCurveParams */
@@ -104,6 +117,7 @@ static const ECCurveParams *ecCurve_map[] = {
NULL, /* ECCurve_WTLS_1 */
NULL, /* ECCurve_WTLS_8 */
NULL, /* ECCurve_WTLS_9 */
+ &ecCurve25519, /* ECCurve25519 */
NULL /* ECCurve_pastLastCurve */
};
diff --git a/lib/freebl/ecl/ecl-exp.h b/lib/freebl/ecl/ecl-exp.h
index 0aae32d3a..8c4786ab0 100644
--- a/lib/freebl/ecl/ecl-exp.h
+++ b/lib/freebl/ecl/ecl-exp.h
@@ -23,6 +23,9 @@ struct ECCurveParamsStr {
char *geny;
char *order;
int cofactor;
+ int security;
+ int pointSize;
+ unsigned int usage;
};
typedef struct ECCurveParamsStr ECCurveParams;
@@ -128,6 +131,8 @@ typedef enum {
/* ECCurve_WTLS_11 == ECCurve_NIST_B233 */
/* ECCurve_WTLS_12 == ECCurve_NIST_P224 */
+ ECCurve25519,
+
ECCurve_pastLastCurve
} ECCurveName;
diff --git a/lib/freebl/ecl/ecl-priv.h b/lib/freebl/ecl/ecl-priv.h
index b5e1c460f..8f1f97b03 100644
--- a/lib/freebl/ecl/ecl-priv.h
+++ b/lib/freebl/ecl/ecl-priv.h
@@ -253,4 +253,5 @@ mp_err ec_group_set_nistp192_fp(ECGroup *group);
mp_err ec_group_set_nistp224_fp(ECGroup *group);
#endif
+SECStatus ec_Curve25519_mul(PRUint8 *q, const PRUint8 *s, const PRUint8 *p);
#endif /* __ecl_priv_h_ */
diff --git a/lib/freebl/ecl/ecl.h b/lib/freebl/ecl/ecl.h
index 5bfc3ec22..ddcbb1f3a 100644
--- a/lib/freebl/ecl/ecl.h
+++ b/lib/freebl/ecl/ecl.h
@@ -8,6 +8,7 @@
#ifndef __ecl_h_
#define __ecl_h_
+#include "blapi.h"
#include "ecl-exp.h"
#include "mpi.h"
@@ -53,4 +54,7 @@ mp_err ECPoints_mul(const ECGroup *group, const mp_int *k1,
* performed. */
mp_err ECPoint_validate(const ECGroup *group, const mp_int *px, const mp_int *py);
+SECStatus ec_Curve25519_pt_mul(SECItem *X, SECItem *k, SECItem *P);
+SECStatus ec_Curve25519_pt_validate(const SECItem *px);
+
#endif /* __ecl_h_ */
diff --git a/lib/freebl/ecl/ecp_25519.c b/lib/freebl/ecl/ecp_25519.c
new file mode 100644
index 000000000..a8d41520e
--- /dev/null
+++ b/lib/freebl/ecl/ecp_25519.c
@@ -0,0 +1,120 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* curve 25519 https://www.rfc-editor.org/rfc/rfc7748.txt */
+
+#ifdef FREEBL_NO_DEPEND
+#include "../stubs.h"
+#endif
+
+#include "ecl-priv.h"
+#include "ecp.h"
+#include "mpi.h"
+#include "mplogic.h"
+#include "mpi-priv.h"
+#include "secmpi.h"
+#include "secitem.h"
+#include "secport.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+/*
+ * point validation is not necessary in general. But this checks a point (px)
+ * against some known bad values.
+ */
+SECStatus
+ec_Curve25519_pt_validate(const SECItem *px)
+{
+ PRUint8 *p;
+ int i;
+ PRUint8 forbiddenValues[12][32] = {
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae,
+ 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a,
+ 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd,
+ 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00 },
+ { 0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24,
+ 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b,
+ 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86,
+ 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57 },
+ { 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f },
+ { 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f },
+ { 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f },
+ { 0xcd, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae,
+ 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a,
+ 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd,
+ 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x80 },
+ { 0x4c, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24,
+ 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b,
+ 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86,
+ 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0xd7 },
+ { 0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+ { 0xda, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+ { 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+ };
+
+ /* The point must not be longer than 32 (it can be smaller). */
+ if (px->len <= 32) {
+ p = px->data;
+ } else {
+ return SECFailure;
+ }
+
+ for (i = 0; i < PR_ARRAY_SIZE(forbiddenValues); ++i) {
+ if (NSS_SecureMemcmp(p, forbiddenValues[i], px->len) == 0) {
+ return SECFailure;
+ }
+ }
+
+ return SECSuccess;
+}
+
+/*
+ * Scalar multiplication for Curve25519.
+ * If P == NULL, the base point is used.
+ * Returns X = k*P
+ */
+SECStatus
+ec_Curve25519_pt_mul(SECItem *X, SECItem *k, SECItem *P)
+{
+ PRUint8 *px;
+ PRUint8 basePoint[32] = { 9 };
+
+ if (!P) {
+ px = basePoint;
+ } else {
+ PORT_Assert(P->len == 32);
+ if (P->len != 32) {
+ return SECFailure;
+ }
+ px = P->data;
+ }
+
+ return ec_Curve25519_mul(X->data, k->data, px);
+}
diff --git a/lib/freebl/ecl/tests/ecp_test.c b/lib/freebl/ecl/tests/ecp_test.c
index 949d8c832..dcec4d747 100644
--- a/lib/freebl/ecl/tests/ecp_test.c
+++ b/lib/freebl/ecl/tests/ecp_test.c
@@ -397,6 +397,7 @@ main(int argv, char **argc)
ECTEST_NAMED_GFP("WTLS-8 (112)", ECCurve_WTLS_8);
ECTEST_NAMED_GFP("WTLS-9 (160)", ECCurve_WTLS_9);
ECTEST_NAMED_GFP("WTLS-12 (224)", ECCurve_WTLS_12);
+ ECTEST_NAMED_GFP("Curve25519", ECCurve25519);
CLEANUP:
EC_FreeCurveParams(params);
diff --git a/lib/freebl/ecl/uint128.c b/lib/freebl/ecl/uint128.c
new file mode 100644
index 000000000..22cbd023c
--- /dev/null
+++ b/lib/freebl/ecl/uint128.c
@@ -0,0 +1,87 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "uint128.h"
+
+/* helper functions */
+uint64_t
+mask51(uint128_t x)
+{
+ return x.lo & MASK51;
+}
+
+uint64_t
+mask_lower(uint128_t x)
+{
+ return x.lo;
+}
+
+uint128_t
+mask51full(uint128_t x)
+{
+ uint128_t ret = { x.lo & MASK51, 0 };
+ return ret;
+}
+
+uint128_t
+init128x(uint64_t x)
+{
+ uint128_t ret = { x, 0 };
+ return ret;
+}
+
+/* arithmetic */
+
+uint128_t
+add128(uint128_t a, uint128_t b)
+{
+ uint128_t ret;
+ ret.lo = a.lo + b.lo;
+ ret.hi = a.hi + b.hi + (ret.lo < b.lo);
+ return ret;
+}
+
+/* out = 19 * a */
+uint128_t
+mul12819(uint128_t a)
+{
+ uint128_t ret = lshift128(a, 4);
+ ret = add128(ret, a);
+ ret = add128(ret, a);
+ ret = add128(ret, a);
+ return ret;
+}
+
+uint128_t
+mul6464(uint64_t a, uint64_t b)
+{
+ uint128_t ret;
+ uint64_t t0 = ((uint64_t)(uint32_t)a) * ((uint64_t)(uint32_t)b);
+ uint64_t t1 = (a >> 32) * ((uint64_t)(uint32_t)b) + (t0 >> 32);
+ uint64_t t2 = (b >> 32) * ((uint64_t)(uint32_t)a) + ((uint32_t)t1);
+ ret.lo = (((uint64_t)((uint32_t)t2)) << 32) + ((uint32_t)t0);
+ ret.hi = (a >> 32) * (b >> 32);
+ ret.hi += (t2 >> 32) + (t1 >> 32);
+ return ret;
+}
+
+/* only defined for n < 64 */
+uint128_t
+rshift128(uint128_t x, uint8_t n)
+{
+ uint128_t ret;
+ ret.lo = (x.lo >> n) + (x.hi << (64 - n));
+ ret.hi = x.hi >> n;
+ return ret;
+}
+
+/* only defined for n < 64 */
+uint128_t
+lshift128(uint128_t x, uint8_t n)
+{
+ uint128_t ret;
+ ret.hi = (x.hi << n) + (x.lo >> (64 - n));
+ ret.lo = x.lo << n;
+ return ret;
+}
diff --git a/lib/freebl/ecl/uint128.h b/lib/freebl/ecl/uint128.h
new file mode 100644
index 000000000..a3a71e6e7
--- /dev/null
+++ b/lib/freebl/ecl/uint128.h
@@ -0,0 +1,35 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <stdint.h>
+
+#define MASK51 0x7ffffffffffffULL
+
+#ifdef HAVE_INT128_SUPPORT
+typedef unsigned __int128 uint128_t;
+#define add128(a, b) (a) + (b)
+#define mul6464(a, b) (uint128_t)(a) * (uint128_t)(b)
+#define mul12819(a) (uint128_t)(a) * 19
+#define rshift128(x, n) (x) >> (n)
+#define lshift128(x, n) (x) << (n)
+#define mask51(x) (x) & 0x7ffffffffffff
+#define mask_lower(x) (uint64_t)(x)
+#define mask51full(x) (x) & 0x7ffffffffffff
+#define init128x(x) (x)
+#else /* uint128_t for Windows and 32 bit intel systems */
+struct uint128_t_str {
+ uint64_t lo;
+ uint64_t hi;
+};
+typedef struct uint128_t_str uint128_t;
+uint128_t add128(uint128_t a, uint128_t b);
+uint128_t mul6464(uint64_t a, uint64_t b);
+uint128_t mul12819(uint128_t a);
+uint128_t rshift128(uint128_t x, uint8_t n);
+uint128_t lshift128(uint128_t x, uint8_t n);
+uint64_t mask51(uint128_t x);
+uint64_t mask_lower(uint128_t x);
+uint128_t mask51full(uint128_t x);
+uint128_t init128x(uint64_t x);
+#endif
diff --git a/lib/freebl/manifest.mn b/lib/freebl/manifest.mn
index d12860646..8314db13e 100644
--- a/lib/freebl/manifest.mn
+++ b/lib/freebl/manifest.mn
@@ -105,7 +105,7 @@ ifndef NSS_DISABLE_ECC
ECL_SRCS = ecl.c ecl_curve.c ecl_mult.c ecl_gf.c \
ecp_aff.c ecp_jac.c ecp_mont.c \
ec_naf.c ecp_jm.c ecp_256.c ecp_384.c ecp_521.c \
- ecp_256_32.c
+ ecp_256_32.c ecp_25519.c
ifdef NSS_ECC_MORE_THAN_SUITE_B
ECL_SRCS += ec2_aff.c ec2_mont.c ec2_proj.c \
ec2_163.c ec2_193.c ec2_233.c \
diff --git a/lib/pk11wrap/pk11akey.c b/lib/pk11wrap/pk11akey.c
index b6673023e..e8cba2ed3 100644
--- a/lib/pk11wrap/pk11akey.c
+++ b/lib/pk11wrap/pk11akey.c
@@ -14,6 +14,7 @@
#include "pk11func.h"
#include "cert.h"
#include "key.h"
+#include "keyi.h"
#include "secitem.h"
#include "secasn1.h"
#include "secoid.h"
@@ -253,7 +254,8 @@ pk11_Attr2SecItem(PLArenaPool *arena, const CK_ATTRIBUTE *attr, SECItem *item)
* Point length = (Roundup(curveLenInBits/8)*2+1)
*/
static int
-pk11_get_EC_PointLenInBytes(PLArenaPool *arena, const SECItem *ecParams)
+pk11_get_EC_PointLenInBytes(PLArenaPool *arena, const SECItem *ecParams,
+ PRBool *plain)
{
SECItem oid;
SECOidTag tag;
@@ -271,6 +273,7 @@ pk11_get_EC_PointLenInBytes(PLArenaPool *arena, const SECItem *ecParams)
return 0;
}
+ *plain = PR_FALSE;
tag = SECOID_FindOIDTag(&oid);
switch (tag) {
case SEC_OID_SECG_EC_SECP112R1:
@@ -350,6 +353,9 @@ pk11_get_EC_PointLenInBytes(PLArenaPool *arena, const SECItem *ecParams)
case SEC_OID_SECG_EC_SECT571K1:
case SEC_OID_SECG_EC_SECT571R1:
return 145; /*curve len in bytes = 72 bytes */
+ case SEC_OID_CURVE25519:
+ *plain = PR_TRUE;
+ return 32; /* curve len in bytes = 32 bytes (only X) */
/* unknown or unrecognized OIDs. return unknown length */
default:
break;
@@ -371,6 +377,7 @@ pk11_get_Decoded_ECPoint(PLArenaPool *arena, const SECItem *ecParams,
SECItem encodedPublicValue;
SECStatus rv;
int keyLen;
+ PRBool plain = PR_FALSE;
if (ecPoint->ulValueLen == 0) {
return CKR_ATTRIBUTE_VALUE_INVALID;
@@ -393,11 +400,19 @@ pk11_get_Decoded_ECPoint(PLArenaPool *arena, const SECItem *ecParams,
* encoded or not heuristically. If the ecParams are invalid, it
* will return -1 for the keyLen.
*/
- keyLen = pk11_get_EC_PointLenInBytes(arena, ecParams);
+ keyLen = pk11_get_EC_PointLenInBytes(arena, ecParams, &plain);
if (keyLen < 0) {
return CKR_ATTRIBUTE_VALUE_INVALID;
}
+ /*
+ * Some curves are not encoded but we don't have the name here.
+ * Instead, pk11_get_EC_PointLenInBytes returns true plain if this is the
+ * case.
+ */
+ if (plain && ecPoint->ulValueLen == (unsigned int)keyLen) {
+ return pk11_Attr2SecItem(arena, ecPoint, publicKeyValue);
+ }
/* If the point is uncompressed and the lengths match, it
* must be an unencoded point */
@@ -702,6 +717,9 @@ PK11_ExtractPublicKey(PK11SlotInfo *slot,KeyType keyType,CK_OBJECT_HANDLE id)
crv = pk11_get_Decoded_ECPoint(arena,
&pubKey->u.ec.DEREncodedParams, value,
&pubKey->u.ec.publicValue);
+ if (seckey_SetPointEncoding(arena, pubKey) != SECSuccess) {
+ crv |= CKR_GENERAL_ERROR;
+ }
break;
case fortezzaKey:
case nullKey:
diff --git a/lib/pk11wrap/pk11skey.c b/lib/pk11wrap/pk11skey.c
index 350048d1b..15ed12204 100644
--- a/lib/pk11wrap/pk11skey.c
+++ b/lib/pk11wrap/pk11skey.c
@@ -1987,18 +1987,19 @@ PK11_PubDerive(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey,
/* Returns the size of the public key, or 0 if there
* is an error. */
static CK_ULONG
-pk11_ECPubKeySize(SECItem *publicValue)
+pk11_ECPubKeySize(SECKEYPublicKey *pubKey)
{
+ SECItem *publicValue = &pubKey->u.ec.publicValue;
+
+ if (pubKey->u.ec.encoding == ECPoint_XOnly) {
+ return publicValue->len;
+ }
if (publicValue->data[0] == 0x04) {
- /* key encoded in uncompressed form */
- return((publicValue->len - 1)/2);
- } else if ( (publicValue->data[0] == 0x02) ||
- (publicValue->data[0] == 0x03)) {
- /* key encoded in compressed form */
- return(publicValue->len - 1);
+ /* key encoded in uncompressed form */
+ return((publicValue->len - 1)/2);
}
/* key encoding not recognized */
- return(0);
+ return 0;
}
static PK11SymKey *
@@ -2059,7 +2060,7 @@ pk11_PubDeriveECKeyWithKDF(
* CKA_VALUE_LEN to be set */
switch (kdf) {
case CKD_NULL:
- key_size = pk11_ECPubKeySize(&pubKey->u.ec.publicValue);
+ key_size = pk11_ECPubKeySize(pubKey);
if (key_size == 0) {
PK11_FreeSymKey(symKey);
return NULL;
@@ -2140,7 +2141,7 @@ pk11_PubDeriveECKeyWithKDF(
CK_ULONG derivedKeySize = key_size;
keyType = CKK_GENERIC_SECRET;
- key_size = pk11_ECPubKeySize(&pubKey->u.ec.publicValue);
+ key_size = pk11_ECPubKeySize(pubKey);
if (key_size == 0) {
SECITEM_FreeItem(pubValue,PR_TRUE);
goto loser;
diff --git a/lib/softoken/pkcs11.c b/lib/softoken/pkcs11.c
index a6100f183..fcca4d34e 100644
--- a/lib/softoken/pkcs11.c
+++ b/lib/softoken/pkcs11.c
@@ -1795,24 +1795,26 @@ sftk_GetPubKey(SFTKObject *object, CK_KEY_TYPE key_type,
crv = sftk_Attribute2SSecItem(arena, &pubKey->u.ec.publicValue,
object, CKA_EC_POINT);
if (crv == CKR_OK) {
- unsigned int keyLen, curveLen;
-
- curveLen = (pubKey->u.ec.ecParams.fieldID.size + 7) / 8;
- keyLen = (2 * curveLen) + 1;
-
- /* special note: We can't just use the first byte to determine
- * between these 2 cases because both EC_POINT_FORM_UNCOMPRESSED
- * and SEC_ASN1_OCTET_STRING are 0x04 */
-
- /* handle the non-DER encoded case (UNCOMPRESSED only) */
- if (pubKey->u.ec.publicValue.data[0] == EC_POINT_FORM_UNCOMPRESSED && pubKey->u.ec.publicValue.len == keyLen) {
+ unsigned int keyLen = pubKey->u.ec.ecParams.pointSize;
+
+ /* special note: We can't just use the first byte to distinguish
+ * between EC_POINT_FORM_UNCOMPRESSED and SEC_ASN1_OCTET_STRING.
+ * Both are 0x04. */
+
+ /* Handle the non-DER encoded case.
+ * Some curves are always pressumed to be non-DER.
+ */
+ if (pubKey->u.ec.publicValue.len == keyLen &&
+ (pubKey->u.ec.ecParams.fieldID.type == ec_field_plain ||
+ pubKey->u.ec.publicValue.data[0] == EC_POINT_FORM_UNCOMPRESSED)) {
break; /* key was not DER encoded, no need to unwrap */
}
- /* if we ever support compressed, handle it here */
+ PORT_Assert(pubKey->u.ec.ecParams.name != ECCurve25519);
/* handle the encoded case */
- if ((pubKey->u.ec.publicValue.data[0] == SEC_ASN1_OCTET_STRING) && pubKey->u.ec.publicValue.len > keyLen) {
+ if ((pubKey->u.ec.publicValue.data[0] == SEC_ASN1_OCTET_STRING) &&
+ pubKey->u.ec.publicValue.len > keyLen) {
SECItem publicValue;
SECStatus rv;
diff --git a/lib/softoken/pkcs11c.c b/lib/softoken/pkcs11c.c
index 23941852a..ff15712c5 100644
--- a/lib/softoken/pkcs11c.c
+++ b/lib/softoken/pkcs11c.c
@@ -5057,19 +5057,22 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hSession,
break;
}
rv = EC_NewKey(ecParams, &ecPriv);
- PORT_FreeArena(ecParams->arena, PR_TRUE);
if (rv != SECSuccess) {
if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
sftk_fatalError = PR_TRUE;
}
+ PORT_FreeArena(ecParams->arena, PR_TRUE);
crv = sftk_MapCryptError(PORT_GetError());
break;
}
- if (PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT")) {
+ if (PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT") ||
+ ecParams->fieldID.type == ec_field_plain) {
+ PORT_FreeArena(ecParams->arena, PR_TRUE);
crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
sftk_item_expand(&ecPriv->publicValue));
} else {
+ PORT_FreeArena(ecParams->arena, PR_TRUE);
SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL,
&ecPriv->publicValue,
SEC_ASN1_GET(SEC_OctetStringTemplate));
@@ -7178,7 +7181,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
PRBool withCofactor = PR_FALSE;
unsigned char *secret;
unsigned char *keyData = NULL;
- unsigned int secretlen, curveLen, pubKeyLen;
+ unsigned int secretlen, pubKeyLen;
CK_ECDH1_DERIVE_PARAMS *mechParams;
NSSLOWKEYPrivateKey *privKey;
PLArenaPool *arena = NULL;
@@ -7204,8 +7207,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
ecPoint.data = mechParams->pPublicData;
ecPoint.len = mechParams->ulPublicDataLen;
- curveLen = (privKey->u.ec.ecParams.fieldID.size + 7) / 8;
- pubKeyLen = (2 * curveLen) + 1;
+ pubKeyLen = privKey->u.ec.ecParams.pointSize;
/* if the len is too small, can't be a valid point */
if (ecPoint.len < pubKeyLen) {
diff --git a/lib/ssl/ssl3ecc.c b/lib/ssl/ssl3ecc.c
index b659bcdc9..a46dac600 100644
--- a/lib/ssl/ssl3ecc.c
+++ b/lib/ssl/ssl3ecc.c
@@ -328,6 +328,7 @@ ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b,
serverKeyPair->pubKey->u.ec.DEREncodedParams.len;
clntPubKey.u.ec.DEREncodedParams.data =
serverKeyPair->pubKey->u.ec.DEREncodedParams.data;
+ clntPubKey.u.ec.encoding = ECPoint_Uncompressed;
rv = ssl3_ConsumeHandshakeVariable(ss, &clntPubKey.u.ec.publicValue,
1, &b, &length);
diff --git a/lib/util/eccutil.h b/lib/util/eccutil.h
new file mode 100644
index 000000000..fc1eea36b
--- /dev/null
+++ b/lib/util/eccutil.h
@@ -0,0 +1,14 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef _FREEBL_H_
+#define _FREEBL_H_
+
+/* point encoding type */
+typedef enum {
+ ECPoint_Uncompressed,
+ ECPoint_XOnly
+} ECPointEncoding;
+
+#endif /* _FREEBL_H_ */ \ No newline at end of file
diff --git a/lib/util/manifest.mn b/lib/util/manifest.mn
index 36c2d1dfe..f0a9fd0f2 100644
--- a/lib/util/manifest.mn
+++ b/lib/util/manifest.mn
@@ -7,6 +7,7 @@ CORE_DEPTH = ../..
EXPORTS = \
base64.h \
ciferfam.h \
+ eccutil.h \
hasht.h \
nssb64.h \
nssb64t.h \
diff --git a/lib/util/secoid.c b/lib/util/secoid.c
index 2dd9d4c04..f5cd68638 100644
--- a/lib/util/secoid.c
+++ b/lib/util/secoid.c
@@ -584,6 +584,11 @@ CONST_OID evIncorporationLocality[] = { EV_NAME_ATTRIBUTE, 1 };
CONST_OID evIncorporationState[] = { EV_NAME_ATTRIBUTE, 2 };
CONST_OID evIncorporationCountry[] = { EV_NAME_ATTRIBUTE, 3 };
+/* https://tools.ietf.org/html/draft-josefsson-pkix-newcurves-01
+ * 1.3.6.1.4.1.11591.15.1
+ */
+CONST_OID curve25519[] = { 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01 };
+
#define OI(x) \
{ \
siDEROID, (unsigned char *)x, sizeof x \
@@ -1743,7 +1748,8 @@ const static SECOidData oids[SEC_OID_TOTAL] = {
"TLS FFDHE 8192-bit key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
ODE(SEC_OID_TLS_DHE_CUSTOM,
"TLS DHE custom group key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
-
+ OD(curve25519, SEC_OID_CURVE25519,
+ "Curve25519", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
};
/* PRIVATE EXTENDED SECOID Table
diff --git a/lib/util/secoidt.h b/lib/util/secoidt.h
index e1d265515..fb513ada3 100644
--- a/lib/util/secoidt.h
+++ b/lib/util/secoidt.h
@@ -490,6 +490,8 @@ typedef enum {
SEC_OID_TLS_FFDHE_8192 = 353,
SEC_OID_TLS_DHE_CUSTOM = 354,
+ SEC_OID_CURVE25519 = 355,
+
SEC_OID_TOTAL
} SECOidTag;
diff --git a/tests/ec/ecperf.sh b/tests/ec/ecperf.sh
index c6723da66..501488e08 100755
--- a/tests/ec/ecperf.sh
+++ b/tests/ec/ecperf.sh
@@ -41,6 +41,7 @@ ecperf_cleanup()
ecperf_init
ECPERF_OUT=$(ecperf 2>&1)
+echo "$ECPERF_OUT"
ECPERF_OUT=`echo $ECPERF_OUT | grep -i 'failed\|Assertion failure'`
# TODO: this is a perf test we don't check for performance here but only failed
if [ -n "$ECPERF_OUT" ] ; then
diff --git a/tests/ec/ectest.sh b/tests/ec/ectest.sh
index 70ec638b0..25e48afe1 100644
--- a/tests/ec/ectest.sh
+++ b/tests/ec/ectest.sh
@@ -40,7 +40,7 @@ ectest_cleanup()
}
ectest_init
-ECTEST_OUT=$(ectest 2>&1)
+ECTEST_OUT=$(ectest -f -p -n -d 2>&1)
ECTEST_OUT=`echo $ECTEST_OUT | grep -i 'not okay\|Assertion failure'`
# TODO: expose individual tests and failures instead of overall
if [ -n "$ECTEST_OUT" ] ; then