diff options
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, ©k->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, ©k->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, ¶ms->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 |