Backed out changeset 703f8f3f2379 (needs additional fixes)
authorFranziskus Kiefer <franziskuskiefer@gmail.com>
Thu, 16 Mar 2017 17:37:27 +0100
changeset 13222 2ecf722b68469212a4bf330fa415d0e9cd2f1011
parent 13221 703f8f3f23793f8954473bf889767d2f6d9206c7
child 13223 8721c96a9a7d1991ee52683ce976e1922eb909c3
push id2092
push userfranziskuskiefer@gmail.com
push dateThu, 16 Mar 2017 16:37:46 +0000
backs out703f8f3f23793f8954473bf889767d2f6d9206c7
Backed out changeset 703f8f3f2379 (needs additional fixes)
cmd/bltest/blapitest.c
cmd/ecperf/ecperf.c
cmd/fbectest/fbectest.c
cmd/lib/secutil.c
cmd/lib/secutil.h
lib/freebl/ecdecode.c
lib/freebl/ecl/ecl-curve.h
lib/freebl/ecl/ecl.c
lib/freebl/ecl/ecl.h
lib/freebl/ecl/ecl_curve.c
lib/freebl/ecl/eclt.h
lib/freebl/exports.gyp
lib/freebl/freebl_base.gypi
lib/freebl/manifest.mn
--- a/cmd/bltest/blapitest.c
+++ b/cmd/bltest/blapitest.c
@@ -2825,17 +2825,17 @@ print_td:
 #ifndef NSS_DISABLE_ECC
         case bltestECDSA:
             if (td) {
                 fprintf(stdout, "%12s", "ec_curve");
             } else {
                 ECPrivateKey *key = (ECPrivateKey *)info->params.asymk.privKey;
                 ECCurveName curveName = key->ecParams.name;
                 fprintf(stdout, "%12s",
-                        ecCurve_mapB[curveName] ? ecCurve_mapB[curveName]->text : "Unsupported curve");
+                        ecCurve_map[curveName] ? ecCurve_map[curveName]->text : "Unsupported curve");
             }
             break;
 #endif
         case bltestMD2:
         case bltestMD5:
         case bltestSHA1:
         case bltestSHA256:
         case bltestSHA384:
--- a/cmd/ecperf/ecperf.c
+++ b/cmd/ecperf/ecperf.c
@@ -4,17 +4,16 @@
 
 #include "blapi.h"
 #include "ec.h"
 #include "ecl-curve.h"
 #include "prprf.h"
 #include "basicutil.h"
 #include "pkcs11.h"
 #include "nspr.h"
-#include "secutil.h"
 #include <stdio.h>
 
 #define __PASTE(x, y) x##y
 
 /*
  * Get the NSS specific PKCS #11 function names.
  */
 #undef CK_PKCS11_FUNCTION_INFO
@@ -22,16 +21,80 @@
 
 #define CK_EXTERN extern
 #define CK_PKCS11_FUNCTION_INFO(func) \
     CK_RV __PASTE(NS, func)
 #define CK_NEED_ARG_LIST 1
 
 #include "pkcs11f.h"
 
+/* mapping between ECCurveName enum and pointers to ECCurveParams */
+static SECOidTag ecCurve_oid_map[] = {
+    SEC_OID_UNKNOWN,                /* ECCurve_noName */
+    SEC_OID_ANSIX962_EC_PRIME192V1, /* ECCurve_NIST_P192 */
+    SEC_OID_SECG_EC_SECP224R1,      /* ECCurve_NIST_P224 */
+    SEC_OID_ANSIX962_EC_PRIME256V1, /* ECCurve_NIST_P256 */
+    SEC_OID_SECG_EC_SECP384R1,      /* ECCurve_NIST_P384 */
+    SEC_OID_SECG_EC_SECP521R1,      /* ECCurve_NIST_P521 */
+    SEC_OID_SECG_EC_SECT163K1,      /* ECCurve_NIST_K163 */
+    SEC_OID_SECG_EC_SECT163R1,      /* ECCurve_NIST_B163 */
+    SEC_OID_SECG_EC_SECT233K1,      /* ECCurve_NIST_K233 */
+    SEC_OID_SECG_EC_SECT233R1,      /* ECCurve_NIST_B233 */
+    SEC_OID_SECG_EC_SECT283K1,      /* ECCurve_NIST_K283 */
+    SEC_OID_SECG_EC_SECT283R1,      /* ECCurve_NIST_B283 */
+    SEC_OID_SECG_EC_SECT409K1,      /* ECCurve_NIST_K409 */
+    SEC_OID_SECG_EC_SECT409R1,      /* ECCurve_NIST_B409 */
+    SEC_OID_SECG_EC_SECT571K1,      /* ECCurve_NIST_K571 */
+    SEC_OID_SECG_EC_SECT571R1,      /* ECCurve_NIST_B571 */
+    SEC_OID_ANSIX962_EC_PRIME192V2,
+    SEC_OID_ANSIX962_EC_PRIME192V3,
+    SEC_OID_ANSIX962_EC_PRIME239V1,
+    SEC_OID_ANSIX962_EC_PRIME239V2,
+    SEC_OID_ANSIX962_EC_PRIME239V3,
+    SEC_OID_ANSIX962_EC_C2PNB163V1,
+    SEC_OID_ANSIX962_EC_C2PNB163V2,
+    SEC_OID_ANSIX962_EC_C2PNB163V3,
+    SEC_OID_ANSIX962_EC_C2PNB176V1,
+    SEC_OID_ANSIX962_EC_C2TNB191V1,
+    SEC_OID_ANSIX962_EC_C2TNB191V2,
+    SEC_OID_ANSIX962_EC_C2TNB191V3,
+    SEC_OID_ANSIX962_EC_C2PNB208W1,
+    SEC_OID_ANSIX962_EC_C2TNB239V1,
+    SEC_OID_ANSIX962_EC_C2TNB239V2,
+    SEC_OID_ANSIX962_EC_C2TNB239V3,
+    SEC_OID_ANSIX962_EC_C2PNB272W1,
+    SEC_OID_ANSIX962_EC_C2PNB304W1,
+    SEC_OID_ANSIX962_EC_C2TNB359V1,
+    SEC_OID_ANSIX962_EC_C2PNB368W1,
+    SEC_OID_ANSIX962_EC_C2TNB431R1,
+    SEC_OID_SECG_EC_SECP112R1,
+    SEC_OID_SECG_EC_SECP112R2,
+    SEC_OID_SECG_EC_SECP128R1,
+    SEC_OID_SECG_EC_SECP128R2,
+    SEC_OID_SECG_EC_SECP160K1,
+    SEC_OID_SECG_EC_SECP160R1,
+    SEC_OID_SECG_EC_SECP160R2,
+    SEC_OID_SECG_EC_SECP192K1,
+    SEC_OID_SECG_EC_SECP224K1,
+    SEC_OID_SECG_EC_SECP256K1,
+    SEC_OID_SECG_EC_SECT113R1,
+    SEC_OID_SECG_EC_SECT113R2,
+    SEC_OID_SECG_EC_SECT131R1,
+    SEC_OID_SECG_EC_SECT131R2,
+    SEC_OID_SECG_EC_SECT163R1,
+    SEC_OID_SECG_EC_SECT193R1,
+    SEC_OID_SECG_EC_SECT193R2,
+    SEC_OID_SECG_EC_SECT239K1,
+    SEC_OID_UNKNOWN, /* ECCurve_WTLS_1 */
+    SEC_OID_UNKNOWN, /* ECCurve_WTLS_8 */
+    SEC_OID_UNKNOWN, /* ECCurve_WTLS_9 */
+    SEC_OID_CURVE25519,
+    SEC_OID_UNKNOWN /* ECCurve_pastLastCurve */
+};
+
 typedef SECStatus (*op_func)(void *, void *, void *);
 typedef SECStatus (*pk11_op_func)(CK_SESSION_HANDLE, void *, void *, void *);
 
 typedef struct ThreadDataStr {
     op_func op;
     void *p1;
     void *p2;
     void *p3;
@@ -306,16 +369,40 @@ PKCS11_Verify(CK_SESSION_HANDLE session,
     crv = NSC_Verify(session, digest->data, digest->len, sig->data, sig->len);
     if (crv != CKR_OK) {
         printf("Verify Failed CK_RV=0x%x\n", (int)crv);
         return SECFailure;
     }
     return SECSuccess;
 }
 
+static SECStatus
+ecName2params(ECCurveName curve, SECKEYECParams *params)
+{
+    SECOidData *oidData = NULL;
+
+    if ((curve < ECCurve_noName) || (curve > ECCurve_pastLastCurve) ||
+        ((oidData = SECOID_FindOIDByTag(ecCurve_oid_map[curve])) == NULL)) {
+        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
+        return SECFailure;
+    }
+
+    SECITEM_AllocItem(NULL, params, (2 + oidData->oid.len));
+    /*
+     * params->data needs to contain the ASN encoding of an object ID (OID)
+     * representing the named curve. The actual OID is in
+     * oidData->oid.data so we simply prepend 0x06 and OID length
+     */
+    params->data[0] = SEC_ASN1_OBJECT_ID;
+    params->data[1] = oidData->oid.len;
+    memcpy(params->data + 2, oidData->oid.data, oidData->oid.len);
+
+    return SECSuccess;
+}
+
 /* Performs basic 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. */
 SECStatus
 ectest_curve_pkcs11(ECCurveName curve, int iterations, int numThreads)
 {
     CK_OBJECT_HANDLE ecPriv;
     CK_OBJECT_HANDLE ecPub;
@@ -331,17 +418,17 @@ ectest_curve_pkcs11(ECCurveName curve, i
     PRLock *lock = NULL;
     double signRate, deriveRate = 0;
     CK_ATTRIBUTE template;
     SECStatus rv;
     CK_RV crv;
 
     ecParams.data = NULL;
     ecParams.len = 0;
-    rv = SECU_ecName2params(curve, &ecParams);
+    rv = ecName2params(curve, &ecParams);
     if (rv != SECSuccess) {
         goto cleanup;
     }
 
     crv = NSC_OpenSession(1, CKF_SERIAL_SESSION, NULL, 0, &session);
     if (crv != CKR_OK) {
         printf("OpenSession Failed CK_RV=0x%x\n", (int)crv);
         return SECFailure;
@@ -382,26 +469,26 @@ ectest_curve_pkcs11(ECCurveName curve, i
     ecdh_params.pPublicData = template.pValue;
 
     mech.mechanism = CKM_ECDH1_DERIVE;
     mech.pParameter = (void *)&ecdh_params;
     mech.ulParameterLen = sizeof(ecdh_params);
 
     lock = PR_NewLock();
 
-    if (ecCurve_mapB[curve]->usage & KU_KEY_AGREEMENT) {
+    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;
         }
     }
 
-    if (ecCurve_mapB[curve]->usage & KU_DIGITAL_SIGNATURE) {
+    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 */
@@ -450,58 +537,75 @@ ectest_curve_freebl(ECCurveName curve, i
     ECParams ecParams = { 0 };
     ECPrivateKey *ecPriv = NULL;
     ECPublicKey ecPub;
     SECItem sig;
     SECItem digest;
     unsigned char sigData[256];
     unsigned char digestData[20];
     double signRate, deriveRate = 0;
+    char genenc[3 + 2 * 2 * MAX_ECKEY_LEN];
     SECStatus rv = SECFailure;
     PLArenaPool *arena;
-    SECItem ecEncodedParams = { siBuffer, NULL, 0 };
 
     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
     if (!arena) {
         return SECFailure;
     }
 
     if ((curve < ECCurve_noName) || (curve > ECCurve_pastLastCurve)) {
         PORT_FreeArena(arena, PR_FALSE);
         return SECFailure;
     }
 
-    rv = SECU_ecName2params(curve, &ecEncodedParams);
-    if (rv != SECSuccess) {
-        goto cleanup;
-    }
-    EC_FillParams(arena, &ecEncodedParams, &ecParams);
+    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 = fieldType;
+    SECU_HexString2SECItem(arena, &ecParams.fieldID.u.prime, ecCurve_map[curve]->irr);
+    SECU_HexString2SECItem(arena, &ecParams.curve.a, ecCurve_map[curve]->curvea);
+    SECU_HexString2SECItem(arena, &ecParams.curve.b, ecCurve_map[curve]->curveb);
+    genenc[0] = '0';
+    genenc[1] = '4';
+    genenc[2] = '\0';
+    strcat(genenc, ecCurve_map[curve]->genx);
+    strcat(genenc, ecCurve_map[curve]->geny);
+    SECU_HexString2SECItem(arena, &ecParams.base, genenc);
+    SECU_HexString2SECItem(arena, &ecParams.order, ecCurve_map[curve]->order);
+    ecParams.cofactor = ecCurve_map[curve]->cofactor;
 
     PORT_Memset(digestData, 0xa5, sizeof(digestData));
     digest.data = digestData;
     digest.len = sizeof(digestData);
     sig.data = sigData;
     sig.len = sizeof(sigData);
 
     rv = EC_NewKey(&ecParams, &ecPriv);
     if (rv != SECSuccess) {
         return SECFailure;
     }
     ecPub.ecParams = ecParams;
     ecPub.publicValue = ecPriv->publicValue;
 
-    if (ecCurve_mapB[curve]->usage & KU_KEY_AGREEMENT) {
+    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;
         }
     }
 
-    if (ecCurve_mapB[curve]->usage & KU_DIGITAL_SIGNATURE) {
+    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;
--- a/cmd/fbectest/fbectest.c
+++ b/cmd/fbectest/fbectest.c
@@ -5,17 +5,16 @@
 #include "blapi.h"
 #include "ec.h"
 #include "ecl-curve.h"
 #include "prprf.h"
 #include "basicutil.h"
 #include "secder.h"
 #include "secitem.h"
 #include "nspr.h"
-#include "secutil.h"
 #include <stdio.h>
 
 typedef struct {
     ECCurveName curve;
     int iterations;
     char *privhex;
     char *our_pubhex;
     char *their_pubhex;
@@ -64,19 +63,19 @@ init_params(ECParams *ecParams, ECCurveN
     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_mapB[curve]->size;
+    ecParams->fieldID.size = ecCurve_map[curve]->size;
     ecParams->fieldID.type = type;
-    ecParams->cofactor = ecCurve_mapB[curve]->cofactor;
+    ecParams->cofactor = ecCurve_map[curve]->cofactor;
 
     return SECSuccess;
 }
 
 SECStatus
 ectest_ecdh_kat(ECDH_KAT *kat)
 {
     ECCurveName curve = kat->curve;
@@ -84,29 +83,36 @@ ectest_ecdh_kat(ECDH_KAT *kat)
     ECPrivateKey *ecPriv = NULL;
     SECItem theirKey = { siBuffer, NULL, 0 };
     SECStatus rv = SECFailure;
     PLArenaPool *arena = NULL;
     SECItem seed = { siBuffer, NULL, 0 };
     SECItem answer = { siBuffer, NULL, 0 };
     SECItem answer2 = { siBuffer, NULL, 0 };
     SECItem derived = { siBuffer, NULL, 0 };
-    SECItem ecEncodedParams = { siBuffer, NULL, 0 };
+    char genenc[3 + 2 * 2 * MAX_ECKEY_LEN];
     int i;
 
-    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-    if (!arena) {
-        return SECFailure;
+    rv = init_params(&ecParams, curve, &arena, kat->fieldType);
+    if (rv != SECSuccess) {
+        return rv;
     }
 
-    rv = SECU_ecName2params(curve, &ecEncodedParams);
-    if (rv != SECSuccess) {
-        goto cleanup;
-    }
-    EC_FillParams(arena, &ecEncodedParams, &ecParams);
+    SECU_HexString2SECItem(arena, &ecParams.fieldID.u.prime, ecCurve_map[curve]->irr);
+    SECU_HexString2SECItem(arena, &ecParams.curve.a, ecCurve_map[curve]->curvea);
+    SECU_HexString2SECItem(arena, &ecParams.curve.b, ecCurve_map[curve]->curveb);
+    genenc[0] = '0';
+    genenc[1] = '4';
+    genenc[2] = '\0';
+    PORT_Assert(PR_ARRAY_SIZE(genenc) >= PORT_Strlen(ecCurve_map[curve]->genx));
+    PORT_Assert(PR_ARRAY_SIZE(genenc) >= PORT_Strlen(ecCurve_map[curve]->geny));
+    strcat(genenc, ecCurve_map[curve]->genx);
+    strcat(genenc, ecCurve_map[curve]->geny);
+    SECU_HexString2SECItem(arena, &ecParams.base, genenc);
+    SECU_HexString2SECItem(arena, &ecParams.order, ecCurve_map[curve]->order);
 
     if (kat->our_pubhex) {
         SECU_HexString2SECItem(arena, &answer, kat->our_pubhex);
     }
     SECU_HexString2SECItem(arena, &seed, kat->privhex);
     rv = EC_NewKeyFromSeed(&ecParams, &ecPriv, seed.data, seed.len);
     if (rv != SECSuccess) {
         rv = SECFailure;
--- a/cmd/lib/secutil.c
+++ b/cmd/lib/secutil.c
@@ -3955,98 +3955,8 @@ done:
         PORT_Free(groups);
         return SECFailure;
     }
 
     *enabledGroupsCount = count;
     *enabledGroups = groups;
     return SECSuccess;
 }
-
-/* mapping between ECCurveName enum and SECOidTags */
-static SECOidTag ecCurve_oid_map[] = {
-    SEC_OID_UNKNOWN,                /* ECCurve_noName */
-    SEC_OID_ANSIX962_EC_PRIME192V1, /* ECCurve_NIST_P192 */
-    SEC_OID_SECG_EC_SECP224R1,      /* ECCurve_NIST_P224 */
-    SEC_OID_ANSIX962_EC_PRIME256V1, /* ECCurve_NIST_P256 */
-    SEC_OID_SECG_EC_SECP384R1,      /* ECCurve_NIST_P384 */
-    SEC_OID_SECG_EC_SECP521R1,      /* ECCurve_NIST_P521 */
-    SEC_OID_SECG_EC_SECT163K1,      /* ECCurve_NIST_K163 */
-    SEC_OID_SECG_EC_SECT163R1,      /* ECCurve_NIST_B163 */
-    SEC_OID_SECG_EC_SECT233K1,      /* ECCurve_NIST_K233 */
-    SEC_OID_SECG_EC_SECT233R1,      /* ECCurve_NIST_B233 */
-    SEC_OID_SECG_EC_SECT283K1,      /* ECCurve_NIST_K283 */
-    SEC_OID_SECG_EC_SECT283R1,      /* ECCurve_NIST_B283 */
-    SEC_OID_SECG_EC_SECT409K1,      /* ECCurve_NIST_K409 */
-    SEC_OID_SECG_EC_SECT409R1,      /* ECCurve_NIST_B409 */
-    SEC_OID_SECG_EC_SECT571K1,      /* ECCurve_NIST_K571 */
-    SEC_OID_SECG_EC_SECT571R1,      /* ECCurve_NIST_B571 */
-    SEC_OID_ANSIX962_EC_PRIME192V2,
-    SEC_OID_ANSIX962_EC_PRIME192V3,
-    SEC_OID_ANSIX962_EC_PRIME239V1,
-    SEC_OID_ANSIX962_EC_PRIME239V2,
-    SEC_OID_ANSIX962_EC_PRIME239V3,
-    SEC_OID_ANSIX962_EC_C2PNB163V1,
-    SEC_OID_ANSIX962_EC_C2PNB163V2,
-    SEC_OID_ANSIX962_EC_C2PNB163V3,
-    SEC_OID_ANSIX962_EC_C2PNB176V1,
-    SEC_OID_ANSIX962_EC_C2TNB191V1,
-    SEC_OID_ANSIX962_EC_C2TNB191V2,
-    SEC_OID_ANSIX962_EC_C2TNB191V3,
-    SEC_OID_ANSIX962_EC_C2PNB208W1,
-    SEC_OID_ANSIX962_EC_C2TNB239V1,
-    SEC_OID_ANSIX962_EC_C2TNB239V2,
-    SEC_OID_ANSIX962_EC_C2TNB239V3,
-    SEC_OID_ANSIX962_EC_C2PNB272W1,
-    SEC_OID_ANSIX962_EC_C2PNB304W1,
-    SEC_OID_ANSIX962_EC_C2TNB359V1,
-    SEC_OID_ANSIX962_EC_C2PNB368W1,
-    SEC_OID_ANSIX962_EC_C2TNB431R1,
-    SEC_OID_SECG_EC_SECP112R1,
-    SEC_OID_SECG_EC_SECP112R2,
-    SEC_OID_SECG_EC_SECP128R1,
-    SEC_OID_SECG_EC_SECP128R2,
-    SEC_OID_SECG_EC_SECP160K1,
-    SEC_OID_SECG_EC_SECP160R1,
-    SEC_OID_SECG_EC_SECP160R2,
-    SEC_OID_SECG_EC_SECP192K1,
-    SEC_OID_SECG_EC_SECP224K1,
-    SEC_OID_SECG_EC_SECP256K1,
-    SEC_OID_SECG_EC_SECT113R1,
-    SEC_OID_SECG_EC_SECT113R2,
-    SEC_OID_SECG_EC_SECT131R1,
-    SEC_OID_SECG_EC_SECT131R2,
-    SEC_OID_SECG_EC_SECT163R1,
-    SEC_OID_SECG_EC_SECT193R1,
-    SEC_OID_SECG_EC_SECT193R2,
-    SEC_OID_SECG_EC_SECT239K1,
-    SEC_OID_UNKNOWN, /* ECCurve_WTLS_1 */
-    SEC_OID_UNKNOWN, /* ECCurve_WTLS_8 */
-    SEC_OID_UNKNOWN, /* ECCurve_WTLS_9 */
-    SEC_OID_CURVE25519,
-    SEC_OID_UNKNOWN /* ECCurve_pastLastCurve */
-};
-
-SECStatus
-SECU_ecName2params(ECCurveName curve, SECKEYECParams *params)
-{
-    SECOidData *oidData = NULL;
-
-    if ((curve < ECCurve_noName) || (curve > ECCurve_pastLastCurve) ||
-        ((oidData = SECOID_FindOIDByTag(ecCurve_oid_map[curve])) == NULL)) {
-        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
-        return SECFailure;
-    }
-
-    if (SECITEM_AllocItem(NULL, params, (2 + oidData->oid.len)) == NULL) {
-        return SECFailure;
-    }
-    /*
-     * params->data needs to contain the ASN encoding of an object ID (OID)
-     * representing the named curve. The actual OID is in
-     * oidData->oid.data so we simply prepend 0x06 and OID length
-     */
-    params->data[0] = SEC_ASN1_OBJECT_ID;
-    params->data[1] = oidData->oid.len;
-    memcpy(params->data + 2, oidData->oid.data, oidData->oid.len);
-
-    return SECSuccess;
-}
--- a/cmd/lib/secutil.h
+++ b/cmd/lib/secutil.h
@@ -13,17 +13,16 @@
 #include "secpkcs7.h"
 #include "secasn1.h"
 #include "secder.h"
 #include <stdio.h>
 
 #include "basicutil.h"
 #include "sslerr.h"
 #include "sslt.h"
-#include "blapi.h"
 
 #define SEC_CT_PRIVATE_KEY "private-key"
 #define SEC_CT_PUBLIC_KEY "public-key"
 #define SEC_CT_CERTIFICATE "certificate"
 #define SEC_CT_CERTIFICATE_REQUEST "certificate-request"
 #define SEC_CT_CERTIFICATE_ID "certificate-identity"
 #define SEC_CT_PKCS7 "pkcs7"
 #define SEC_CT_CRL "crl"
@@ -408,18 +407,16 @@ SECU_ParseSSLVersionRangeString(const ch
 */
 extern SECItem *SECU_HexString2SECItem(PLArenaPool *arena, SECItem *item,
                                        const char *str);
 
 SECStatus parseGroupList(const char *arg, SSLNamedGroup **enabledGroups,
                          unsigned int *enabledGroupsCount);
 SSLNamedGroup groupNameToNamedGroup(char *name);
 
-extern SECStatus SECU_ecName2params(ECCurveName curve, SECKEYECParams *params);
-
 /*
  *
  *  Error messaging
  *
  */
 
 void printflags(char *trusts, unsigned int flags);
 
--- a/lib/freebl/ecdecode.c
+++ b/lib/freebl/ecdecode.c
@@ -17,16 +17,67 @@
 
 #define CHECK_OK(func) \
     if (func == NULL)  \
     goto cleanup
 #define CHECK_SEC_OK(func)         \
     if (SECSuccess != (rv = func)) \
     goto cleanup
 
+/*
+ * Initializes a SECItem from a hexadecimal string
+ *
+ * Warning: This function ignores leading 00's, so any leading 00's
+ * in the hexadecimal string must be optional.
+ */
+static SECItem *
+hexString2SECItem(PLArenaPool *arena, SECItem *item, const char *str)
+{
+    int i = 0;
+    int byteval = 0;
+    int tmp = PORT_Strlen(str);
+
+    PORT_Assert(arena);
+    PORT_Assert(item);
+
+    if ((tmp % 2) != 0)
+        return NULL;
+
+    /* skip leading 00's unless the hex string is "00" */
+    while ((tmp > 2) && (str[0] == '0') && (str[1] == '0')) {
+        str += 2;
+        tmp -= 2;
+    }
+
+    item->data = (unsigned char *)PORT_ArenaAlloc(arena, tmp / 2);
+    if (item->data == NULL)
+        return NULL;
+    item->len = tmp / 2;
+
+    while (str[i]) {
+        if ((str[i] >= '0') && (str[i] <= '9'))
+            tmp = str[i] - '0';
+        else if ((str[i] >= 'a') && (str[i] <= 'f'))
+            tmp = str[i] - 'a' + 10;
+        else if ((str[i] >= 'A') && (str[i] <= 'F'))
+            tmp = str[i] - 'A' + 10;
+        else
+            return NULL;
+
+        byteval = byteval * 16 + tmp;
+        if ((i % 2) != 0) {
+            item->data[i / 2] = byteval;
+            byteval = 0;
+        }
+        i++;
+    }
+
+    return item;
+}
+
 /* Copy all of the fields from srcParams into dstParams
  */
 SECStatus
 EC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
               const ECParams *srcParams)
 {
     SECStatus rv = SECFailure;
 
@@ -64,41 +115,50 @@ EC_CopyParams(PLArenaPool *arena, ECPara
 
     return SECSuccess;
 
 cleanup:
     return SECFailure;
 }
 
 static SECStatus
-gf_populate_params_bytes(ECCurveName name, ECFieldType field_type, ECParams *params)
+gf_populate_params(ECCurveName name, ECFieldType field_type, ECParams *params)
 {
     SECStatus rv = SECFailure;
-    const ECCurveBytes *curveParams;
+    const ECCurveParams *curveParams;
+    /* 2 ['0'+'4'] + MAX_ECKEY_LEN * 2 [x,y] * 2 [hex string] + 1 ['\0'] */
+    char genenc[3 + 2 * 2 * MAX_ECKEY_LEN];
 
     if ((name < ECCurve_noName) || (name > ECCurve_pastLastCurve))
         goto cleanup;
     params->name = name;
-    curveParams = ecCurve_mapB[params->name];
+    curveParams = ecCurve_map[params->name];
     CHECK_OK(curveParams);
     params->fieldID.size = curveParams->size;
     params->fieldID.type = field_type;
-    if (field_type != ec_field_GFp && field_type != ec_field_plain) {
-        return SECFailure;
+    if (field_type == ec_field_GFp ||
+        field_type == ec_field_plain) {
+        CHECK_OK(hexString2SECItem(params->arena, &params->fieldID.u.prime,
+                                   curveParams->irr));
+    } else {
+        CHECK_OK(hexString2SECItem(params->arena, &params->fieldID.u.poly,
+                                   curveParams->irr));
     }
-    params->fieldID.u.prime.len = curveParams->scalarSize;
-    params->fieldID.u.prime.data = (unsigned char *)curveParams->irr;
-    params->curve.a.len = curveParams->scalarSize;
-    params->curve.a.data = (unsigned char *)curveParams->curvea;
-    params->curve.b.len = curveParams->scalarSize;
-    params->curve.b.data = (unsigned char *)curveParams->curveb;
-    params->base.len = curveParams->pointSize;
-    params->base.data = (unsigned char *)curveParams->base;
-    params->order.len = curveParams->scalarSize;
-    params->order.data = (unsigned char *)curveParams->order;
+    CHECK_OK(hexString2SECItem(params->arena, &params->curve.a,
+                               curveParams->curvea));
+    CHECK_OK(hexString2SECItem(params->arena, &params->curve.b,
+                               curveParams->curveb));
+    genenc[0] = '0';
+    genenc[1] = '4';
+    genenc[2] = '\0';
+    strcat(genenc, curveParams->genx);
+    strcat(genenc, curveParams->geny);
+    CHECK_OK(hexString2SECItem(params->arena, &params->base, genenc));
+    CHECK_OK(hexString2SECItem(params->arena, &params->order,
+                               curveParams->order));
     params->cofactor = curveParams->cofactor;
 
     rv = SECSuccess;
 
 cleanup:
     return rv;
 }
 
@@ -151,40 +211,39 @@ EC_FillParams(PLArenaPool *arena, const 
     printf("Curve: %s\n", SECOID_FindOIDTagDescription(tag));
 #endif
 
     switch (tag) {
         case SEC_OID_ANSIX962_EC_PRIME256V1:
             /* Populate params for prime256v1 aka secp256r1
              * (the NIST P-256 curve)
              */
-            CHECK_SEC_OK(gf_populate_params_bytes(ECCurve_X9_62_PRIME_256V1,
-                                                  ec_field_GFp, params));
+            CHECK_SEC_OK(gf_populate_params(ECCurve_X9_62_PRIME_256V1, ec_field_GFp,
+                                            params));
             break;
 
         case SEC_OID_SECG_EC_SECP384R1:
             /* Populate params for secp384r1
              * (the NIST P-384 curve)
              */
-            CHECK_SEC_OK(gf_populate_params_bytes(ECCurve_SECG_PRIME_384R1,
-                                                  ec_field_GFp, params));
+            CHECK_SEC_OK(gf_populate_params(ECCurve_SECG_PRIME_384R1, ec_field_GFp,
+                                            params));
             break;
 
         case SEC_OID_SECG_EC_SECP521R1:
             /* Populate params for secp521r1
              * (the NIST P-521 curve)
              */
-            CHECK_SEC_OK(gf_populate_params_bytes(ECCurve_SECG_PRIME_521R1,
-                                                  ec_field_GFp, params));
+            CHECK_SEC_OK(gf_populate_params(ECCurve_SECG_PRIME_521R1, ec_field_GFp,
+                                            params));
             break;
 
         case SEC_OID_CURVE25519:
             /* Populate params for Curve25519 */
-            CHECK_SEC_OK(gf_populate_params_bytes(ECCurve25519, ec_field_plain,
-                                                  params));
+            CHECK_SEC_OK(gf_populate_params(ECCurve25519, ec_field_plain, params));
             break;
 
         default:
             break;
     };
 
 cleanup:
     if (!params->cofactor) {
@@ -232,25 +291,21 @@ EC_DecodeParams(const SECItem *encodedPa
         return SECSuccess;
     }
 }
 
 int
 EC_GetPointSize(const ECParams *params)
 {
     ECCurveName name = params->name;
-    const ECCurveBytes *curveParams;
+    const ECCurveParams *curveParams;
 
     if ((name < ECCurve_noName) || (name > ECCurve_pastLastCurve) ||
-        ((curveParams = ecCurve_mapB[name]) == NULL)) {
-        /* unknown curve, calculate point size from params. assume standard curves with 2 points
+        ((curveParams = ecCurve_map[name]) == NULL)) {
+        /* unknown curve, calculate point size from params. assume standard curves with 2 points 
          * and a point compression indicator byte */
         int sizeInBytes = (params->fieldID.size + 7) / 8;
         return sizeInBytes * 2 + 1;
     }
-    if (name == ECCurve25519) {
-        /* Only X here */
-        return curveParams->scalarSize;
-    }
-    return curveParams->pointSize - 1;
+    return curveParams->pointSize;
 }
 
 #endif /* NSS_DISABLE_ECC */
--- a/lib/freebl/ecl/ecl-curve.h
+++ b/lib/freebl/ecl/ecl-curve.h
@@ -1,218 +1,68 @@
 /* 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 "ecl-exp.h"
-#include "eclt.h"
 #include <stdlib.h>
 
 #ifndef __ecl_curve_h_
 #define __ecl_curve_h_
 
 /* copied from certt.h */
 #define KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */
 #define KU_KEY_AGREEMENT (0x08)     /* bit 4 */
 
-static const PRUint8 irr256[32] =
-    { 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
-      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-static const PRUint8 a256[32] =
-    { 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
-      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC };
-static const PRUint8 b256[32] =
-    { 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55,
-      0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6,
-      0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B };
-static const PRUint8 x256[32] =
-    { 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
-      0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
-      0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96 };
-static const PRUint8 y256[32] =
-    { 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A,
-      0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE,
-      0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5 };
-static const PRUint8 order256[32] =
-    { 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
-      0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
-      0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51 };
-static const PRUint8 base256[66] =
-    { 0x04, 0x00,
-      0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
-      0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
-      0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96,
-      0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A,
-      0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE,
-      0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5 };
-
-static const ECCurveBytes ecCurve_NIST_P256 = {
+static const ECCurveParams ecCurve_NIST_P256 = {
     "NIST-P256", ECField_GFp, 256,
-    irr256, a256, b256, x256, y256, order256, base256,
-    1, 128, 66, 32,
-    KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
-};
-
-static const PRUint8 irr384[48] =
-    { 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, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF };
-static const PRUint8 a384[48] =
-    { 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, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC };
-static const PRUint8 b384[48] =
-    { 0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B,
-      0xE3, 0xF8, 0x2D, 0x19, 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12,
-      0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, 0xC6, 0x56, 0x39, 0x8D,
-      0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF };
-static const PRUint8 x384[48] =
-    { 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,
-      0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
-      0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D,
-      0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7 };
-static const PRUint8 y384[48] =
-    { 0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F, 0x5D, 0x9E, 0x98, 0xBF,
-      0x92, 0x92, 0xDC, 0x29, 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C,
-      0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0, 0x0A, 0x60, 0xB1, 0xCE,
-      0x1D, 0x7E, 0x81, 0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F };
-static const PRUint8 order384[48] =
-    { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-      0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2,
-      0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73 };
-static const PRUint8 base384[98] =
-    { 0x04, 0x00,
-      0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,
-      0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
-      0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D,
-      0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7,
-      0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F, 0x5D, 0x9E, 0x98, 0xBF,
-      0x92, 0x92, 0xDC, 0x29, 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C,
-      0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0, 0x0A, 0x60, 0xB1, 0xCE,
-      0x1D, 0x7E, 0x81, 0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F };
-
-static const ECCurveBytes ecCurve_NIST_P384 = {
-    "NIST-P384", ECField_GFp, 384,
-    irr384, a384, b384, x384, y384, order384, base384,
-    1, 192, 98, 48,
-    KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
+    "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
+    "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
+    "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
+    "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
+    "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
+    "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
+    1, 128, 65, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
 };
 
-static const PRUint8 irr521[66] =
-    { 0x01, 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, 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, 0xFF, 0xFF, 0xFF };
-static const PRUint8 a521[66] =
-    { 0x01, 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, 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, 0xFF, 0xFF, 0xFC };
-static const PRUint8 b521[66] =
-    { 0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A,
-      0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3,
-      0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19,
-      0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1,
-      0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45,
-      0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00 };
-static const PRUint8 x521[66] =
-    { 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
-      0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
-      0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
-      0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
-      0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
-      0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66 };
-static const PRUint8 y521[66] =
-    { 0x01, 0x18, 0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B, 0xC0, 0x04, 0x5C, 0x8A,
-      0x5F, 0xB4, 0x2C, 0x7D, 0x1B, 0xD9, 0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B,
-      0x44, 0x68, 0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E, 0x66, 0x2C, 0x97, 0xEE,
-      0x72, 0x99, 0x5E, 0xF4, 0x26, 0x40, 0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD,
-      0x07, 0x61, 0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72, 0xC2, 0x40, 0x88, 0xBE,
-      0x94, 0x76, 0x9F, 0xD1, 0x66, 0x50 };
-static const PRUint8 order521[66] =
-    { 0x01, 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, 0xFF, 0xFA, 0x51, 0x86,
-      0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
-      0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F,
-      0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09 };
-static const PRUint8 base521[134] =
-    {
-      0x04, 0x00,
-      0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
-      0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
-      0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
-      0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
-      0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
-      0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66,
-      0x01, 0x18, 0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B, 0xC0, 0x04, 0x5C, 0x8A,
-      0x5F, 0xB4, 0x2C, 0x7D, 0x1B, 0xD9, 0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B,
-      0x44, 0x68, 0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E, 0x66, 0x2C, 0x97, 0xEE,
-      0x72, 0x99, 0x5E, 0xF4, 0x26, 0x40, 0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD,
-      0x07, 0x61, 0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72, 0xC2, 0x40, 0x88, 0xBE,
-      0x94, 0x76, 0x9F, 0xD1, 0x66, 0x50
-    };
-
-static const ECCurveBytes ecCurve_NIST_P521 = {
-    "NIST-P521", ECField_GFp, 521,
-    irr521, a521, b521, x521, y521, order521, base521,
-    1, 256, 134, 66,
-    KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
+static const ECCurveParams ecCurve_NIST_P384 = {
+    "NIST-P384", ECField_GFp, 384,
+    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
+    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
+    "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
+    "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
+    "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
+    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
+    1, 192, 97, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
 };
 
-static const PRUint8 irr25519[32] =
-    { 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 };
-static const PRUint8 a25519[32] =
-    { 0x06, 0x6d, 0x07, 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 };
-static const PRUint8 b25519[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 };
-static const PRUint8 x25519[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, 0x09 };
-static const PRUint8 y25519[32] =
-    { 0xd9, 0xd3, 0xce, 0x7e, 0xa2, 0xc5, 0xe9, 0x29, 0xb2, 0x61, 0x7c, 0x6d,
-      0x7e, 0x4d, 0x3d, 0x92, 0x4c, 0xd1, 0x48, 0x77, 0x2c, 0xdd, 0x1e, 0xe0,
-      0xb4, 0x86, 0xa0, 0xb8, 0xa1, 0x19, 0xae, 0x20 };
-static const PRUint8 order25519[32] =
-    { 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2,
-      0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 };
-static const PRUint8 base25519[66] =
-    { 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, 0x09,
-      0xd9, 0xd3, 0xce, 0x7e, 0xa2, 0xc5, 0xe9, 0x29, 0xb2, 0x61, 0x7c, 0x6d,
-      0x7e, 0x4d, 0x3d, 0x92, 0x4c, 0xd1, 0x48, 0x77, 0x2c, 0xdd, 0x1e, 0xe0,
-      0xb4, 0x86, 0xa0, 0xb8, 0xa1, 0x19, 0xae, 0x20, 0x00, 0x04 };
+static const ECCurveParams ecCurve_NIST_P521 = {
+    "NIST-P521", ECField_GFp, 521,
+    "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+    "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
+    "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
+    "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
+    "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
+    "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
+    1, 256, 133, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
+};
 
-static const ECCurveBytes ecCurve_25519 = {
+static const ECCurveParams ecCurve25519 = {
     "Curve25519", ECField_GFp, 255,
-    irr25519, a25519, b25519, x25519, y25519, order25519, base25519,
-    8, 128, 66, 32,
-    KU_KEY_AGREEMENT
+    "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed",
+    "076D06",
+    "00",
+    "0900000000000000000000000000000000000000000000000000000000000000",
+    "20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9",
+    "1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed",
+    8, 128, 32, KU_KEY_AGREEMENT
 };
 
 /* mapping between ECCurveName enum and pointers to ECCurveParams */
-static const ECCurveBytes *ecCurve_mapB[] = {
+static const ECCurveParams *ecCurve_map[] = {
     NULL,               /* ECCurve_noName */
     NULL,               /* ECCurve_NIST_P192 */
     NULL,               /* ECCurve_NIST_P224 */
     &ecCurve_NIST_P256, /* ECCurve_NIST_P256 */
     &ecCurve_NIST_P384, /* ECCurve_NIST_P384 */
     &ecCurve_NIST_P521, /* ECCurve_NIST_P521 */
     NULL,               /* ECCurve_NIST_K163 */
     NULL,               /* ECCurve_NIST_B163 */
@@ -261,13 +111,13 @@ static const ECCurveBytes *ecCurve_mapB[
     NULL,               /* ECCurve_SECG_CHAR2_131R2 */
     NULL,               /* ECCurve_SECG_CHAR2_163R1 */
     NULL,               /* ECCurve_SECG_CHAR2_193R1 */
     NULL,               /* ECCurve_SECG_CHAR2_193R2 */
     NULL,               /* ECCurve_SECG_CHAR2_239K1 */
     NULL,               /* ECCurve_WTLS_1 */
     NULL,               /* ECCurve_WTLS_8 */
     NULL,               /* ECCurve_WTLS_9 */
-    &ecCurve_25519,     /* ECCurve25519 */
+    &ecCurve25519,      /* ECCurve25519 */
     NULL                /* ECCurve_pastLastCurve */
 };
 
 #endif
--- a/lib/freebl/ecl/ecl.c
+++ b/lib/freebl/ecl/ecl.c
@@ -2,17 +2,16 @@
  * 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 "mpi.h"
 #include "mplogic.h"
 #include "ecl.h"
 #include "ecl-priv.h"
 #include "ecp.h"
-#include "ecl-curve.h"
 #include <stdlib.h>
 #include <string.h>
 
 /* Allocate memory for a new ECGroup object. */
 ECGroup *
 ECGroup_new()
 {
     mp_err res = MP_OKAY;
@@ -124,171 +123,146 @@ ECGroup_consGFp_mont(const mp_int *irr, 
 CLEANUP:
     if (res != MP_OKAY) {
         ECGroup_free(group);
         return NULL;
     }
     return group;
 }
 
-/* Construct an ECGroup. */
+/* Construct ECGroup from hex parameters and name, if any. Called by
+ * ECGroup_fromHex and ECGroup_fromName. */
 ECGroup *
-construct_ecgroup(const ECCurveName name, mp_int irr, mp_int curvea,
-                  mp_int curveb, mp_int genx, mp_int geny, mp_int order,
-                  int cofactor, ECField field, const char *text)
-{
-    int bits;
-    ECGroup *group = NULL;
-    mp_err res = MP_OKAY;
-
-    /* determine number of bits */
-    bits = mpl_significant_bits(&irr) - 1;
-    if (bits < MP_OKAY) {
-        res = bits;
-        goto CLEANUP;
-    }
-
-    /* determine which optimizations (if any) to use */
-    if (field == ECField_GFp) {
-        switch (name) {
-            case ECCurve_SECG_PRIME_256R1:
-                group =
-                    ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
-                                    &order, cofactor);
-                if (group == NULL) {
-                    res = MP_UNDEF;
-                    goto CLEANUP;
-                }
-                MP_CHECKOK(ec_group_set_gfp256(group, name));
-                MP_CHECKOK(ec_group_set_gfp256_32(group, name));
-                break;
-            case ECCurve_SECG_PRIME_521R1:
-                group =
-                    ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
-                                    &order, cofactor);
-                if (group == NULL) {
-                    res = MP_UNDEF;
-                    goto CLEANUP;
-                }
-                MP_CHECKOK(ec_group_set_gfp521(group, name));
-                break;
-            default:
-                /* use generic arithmetic */
-                group =
-                    ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny,
-                                         &order, cofactor);
-                if (group == NULL) {
-                    res = MP_UNDEF;
-                    goto CLEANUP;
-                }
-        }
-    } else {
-        res = MP_UNDEF;
-        goto CLEANUP;
-    }
-
-    /* set name, if any */
-    if ((group != NULL) && (text != NULL)) {
-        group->text = strdup(text);
-        if (group->text == NULL) {
-            res = MP_MEM;
-        }
-    }
-
-CLEANUP:
-    if (group && res != MP_OKAY) {
-        ECGroup_free(group);
-        return NULL;
-    }
-    return group;
-}
-
-/* Construct ECGroup from parameters and name, if any. */
-ECGroup *
-ecgroup_fromName(const ECCurveName name,
-                 const ECCurveBytes *params)
+ecgroup_fromNameAndHex(const ECCurveName name,
+                       const ECCurveParams *params)
 {
     mp_int irr, curvea, curveb, genx, geny, order;
+    int bits;
     ECGroup *group = NULL;
     mp_err res = MP_OKAY;
 
     /* initialize values */
     MP_DIGITS(&irr) = 0;
     MP_DIGITS(&curvea) = 0;
     MP_DIGITS(&curveb) = 0;
     MP_DIGITS(&genx) = 0;
     MP_DIGITS(&geny) = 0;
     MP_DIGITS(&order) = 0;
     MP_CHECKOK(mp_init(&irr));
     MP_CHECKOK(mp_init(&curvea));
     MP_CHECKOK(mp_init(&curveb));
     MP_CHECKOK(mp_init(&genx));
     MP_CHECKOK(mp_init(&geny));
     MP_CHECKOK(mp_init(&order));
-    MP_CHECKOK(mp_read_unsigned_octets(&irr, params->irr, params->scalarSize));
-    MP_CHECKOK(mp_read_unsigned_octets(&curvea, params->curvea, params->scalarSize));
-    MP_CHECKOK(mp_read_unsigned_octets(&curveb, params->curveb, params->scalarSize));
-    MP_CHECKOK(mp_read_unsigned_octets(&genx, params->genx, params->scalarSize));
-    MP_CHECKOK(mp_read_unsigned_octets(&geny, params->geny, params->scalarSize));
-    MP_CHECKOK(mp_read_unsigned_octets(&order, params->order, params->scalarSize));
+    MP_CHECKOK(mp_read_radix(&irr, params->irr, 16));
+    MP_CHECKOK(mp_read_radix(&curvea, params->curvea, 16));
+    MP_CHECKOK(mp_read_radix(&curveb, params->curveb, 16));
+    MP_CHECKOK(mp_read_radix(&genx, params->genx, 16));
+    MP_CHECKOK(mp_read_radix(&geny, params->geny, 16));
+    MP_CHECKOK(mp_read_radix(&order, params->order, 16));
+
+    /* determine number of bits */
+    bits = mpl_significant_bits(&irr) - 1;
+    if (bits < MP_OKAY) {
+        res = bits;
+        goto CLEANUP;
+    }
 
-    group = construct_ecgroup(name, irr, curvea, curveb, genx, geny, order,
-                              params->cofactor, params->field, params->text);
+    /* determine which optimizations (if any) to use */
+    if (params->field == ECField_GFp) {
+        switch (name) {
+            case ECCurve_SECG_PRIME_256R1:
+                group =
+                    ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
+                                    &order, params->cofactor);
+                if (group == NULL) {
+                    res = MP_UNDEF;
+                    goto CLEANUP;
+                }
+                MP_CHECKOK(ec_group_set_gfp256(group, name));
+                MP_CHECKOK(ec_group_set_gfp256_32(group, name));
+                break;
+            case ECCurve_SECG_PRIME_521R1:
+                group =
+                    ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
+                                    &order, params->cofactor);
+                if (group == NULL) {
+                    res = MP_UNDEF;
+                    goto CLEANUP;
+                }
+                MP_CHECKOK(ec_group_set_gfp521(group, name));
+                break;
+            default:
+                /* use generic arithmetic */
+                group =
+                    ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny,
+                                         &order, params->cofactor);
+                if (group == NULL) {
+                    res = MP_UNDEF;
+                    goto CLEANUP;
+                }
+        }
+    } else {
+        res = MP_UNDEF;
+        goto CLEANUP;
+    }
+
+    /* set name, if any */
+    if ((group != NULL) && (params->text != NULL)) {
+        group->text = strdup(params->text);
+        if (group->text == NULL) {
+            res = MP_MEM;
+        }
+    }
 
 CLEANUP:
     mp_clear(&irr);
     mp_clear(&curvea);
     mp_clear(&curveb);
     mp_clear(&genx);
     mp_clear(&geny);
     mp_clear(&order);
-    if (group && res != MP_OKAY) {
+    if (res != MP_OKAY) {
         ECGroup_free(group);
         return NULL;
     }
     return group;
 }
 
-/* Construct ECCurveBytes from an ECCurveName */
-const ECCurveBytes *
-ec_GetNamedCurveParams(const ECCurveName name)
+/* Construct ECGroup from hexadecimal representations of parameters. */
+ECGroup *
+ECGroup_fromHex(const ECCurveParams *params)
 {
-    if ((name <= ECCurve_noName) || (ECCurve_pastLastCurve <= name) ||
-        (ecCurve_mapB[name] == NULL)) {
-        return NULL;
-    } else {
-        return ecCurve_mapB[name];
-    }
+    return ecgroup_fromNameAndHex(ECCurve_noName, params);
 }
 
 /* Construct ECGroup from named parameters. */
 ECGroup *
 ECGroup_fromName(const ECCurveName name)
 {
     ECGroup *group = NULL;
-    const ECCurveBytes *params = NULL;
+    ECCurveParams *params = NULL;
     mp_err res = MP_OKAY;
 
-    /* This doesn't work with Curve25519 but it's not necessary to. */
-    PORT_Assert(name != ECCurve25519);
-
-    params = ec_GetNamedCurveParams(name);
+    params = EC_GetNamedCurveParams(name);
     if (params == NULL) {
         res = MP_UNDEF;
         goto CLEANUP;
     }
 
     /* construct actual group */
-    group = ecgroup_fromName(name, params);
+    group = ecgroup_fromNameAndHex(name, params);
     if (group == NULL) {
         res = MP_UNDEF;
+        goto CLEANUP;
     }
 
 CLEANUP:
-    if (group && res != MP_OKAY) {
+    EC_FreeCurveParams(params);
+    if (res != MP_OKAY) {
         ECGroup_free(group);
         return NULL;
     }
     return group;
 }
 
 /* Validates an EC public key as described in Section 5.2.2 of X9.62. */
 mp_err
--- a/lib/freebl/ecl/ecl.h
+++ b/lib/freebl/ecl/ecl.h
@@ -6,27 +6,38 @@
  * curve point operations will need to include it. */
 
 #ifndef __ecl_h_
 #define __ecl_h_
 
 #include "blapi.h"
 #include "ecl-exp.h"
 #include "mpi.h"
-#include "eclt.h"
 
 struct ECGroupStr;
 typedef struct ECGroupStr ECGroup;
 
+/* Construct ECGroup from hexadecimal representations of parameters. */
+ECGroup *ECGroup_fromHex(const ECCurveParams *params);
+
 /* Construct ECGroup from named parameters. */
 ECGroup *ECGroup_fromName(const ECCurveName name);
 
 /* Free an allocated ECGroup. */
 void ECGroup_free(ECGroup *group);
 
+/* Construct ECCurveParams from an ECCurveName */
+ECCurveParams *EC_GetNamedCurveParams(const ECCurveName name);
+
+/* Duplicates an ECCurveParams */
+ECCurveParams *ECCurveParams_dup(const ECCurveParams *params);
+
+/* Free an allocated ECCurveParams */
+void EC_FreeCurveParams(ECCurveParams *params);
+
 /* Elliptic curve scalar-point multiplication. Computes Q(x, y) = k * P(x,
  * y).  If x, y = NULL, then P is assumed to be the generator (base point)
  * of the group of points on the elliptic curve. Input and output values
  * are assumed to be NOT field-encoded. */
 mp_err ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px,
                    const mp_int *py, mp_int *qx, mp_int *qy);
 
 /* Elliptic curve scalar-point multiplication. Computes Q(x, y) = k1 * G +
new file mode 100644
--- /dev/null
+++ b/lib/freebl/ecl/ecl_curve.c
@@ -0,0 +1,93 @@
+/* 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 "ecl.h"
+#include "ecl-curve.h"
+#include "ecl-priv.h"
+#include <stdlib.h>
+#include <string.h>
+
+#define CHECK(func)       \
+    if ((func) == NULL) { \
+        res = 0;          \
+        goto CLEANUP;     \
+    }
+
+/* Duplicates an ECCurveParams */
+ECCurveParams *
+ECCurveParams_dup(const ECCurveParams *params)
+{
+    int res = 1;
+    ECCurveParams *ret = NULL;
+
+    CHECK(ret = (ECCurveParams *)calloc(1, sizeof(ECCurveParams)));
+    if (params->text != NULL) {
+        CHECK(ret->text = strdup(params->text));
+    }
+    ret->field = params->field;
+    ret->size = params->size;
+    if (params->irr != NULL) {
+        CHECK(ret->irr = strdup(params->irr));
+    }
+    if (params->curvea != NULL) {
+        CHECK(ret->curvea = strdup(params->curvea));
+    }
+    if (params->curveb != NULL) {
+        CHECK(ret->curveb = strdup(params->curveb));
+    }
+    if (params->genx != NULL) {
+        CHECK(ret->genx = strdup(params->genx));
+    }
+    if (params->geny != NULL) {
+        CHECK(ret->geny = strdup(params->geny));
+    }
+    if (params->order != NULL) {
+        CHECK(ret->order = strdup(params->order));
+    }
+    ret->cofactor = params->cofactor;
+
+CLEANUP:
+    if (res != 1) {
+        EC_FreeCurveParams(ret);
+        return NULL;
+    }
+    return ret;
+}
+
+#undef CHECK
+
+/* Construct ECCurveParams from an ECCurveName */
+ECCurveParams *
+EC_GetNamedCurveParams(const ECCurveName name)
+{
+    if ((name <= ECCurve_noName) || (ECCurve_pastLastCurve <= name) ||
+        (ecCurve_map[name] == NULL)) {
+        return NULL;
+    } else {
+        return ECCurveParams_dup(ecCurve_map[name]);
+    }
+}
+
+/* Free the memory allocated (if any) to an ECCurveParams object. */
+void
+EC_FreeCurveParams(ECCurveParams *params)
+{
+    if (params == NULL)
+        return;
+    if (params->text != NULL)
+        free(params->text);
+    if (params->irr != NULL)
+        free(params->irr);
+    if (params->curvea != NULL)
+        free(params->curvea);
+    if (params->curveb != NULL)
+        free(params->curveb);
+    if (params->genx != NULL)
+        free(params->genx);
+    if (params->geny != NULL)
+        free(params->geny);
+    if (params->order != NULL)
+        free(params->order);
+    free(params);
+}
deleted file mode 100644
--- a/lib/freebl/ecl/eclt.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* 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/. */
-
-/* This header holds ECC types and must not be exported publicly. */
-
-#ifndef __eclt_h_
-#define __eclt_h_
-
-/* byte encoding of curve parameters */
-struct ECCurveBytesStr {
-    char *text;
-    ECField field;
-    size_t size;
-    const PRUint8 *irr;
-    const PRUint8 *curvea;
-    const PRUint8 *curveb;
-    const PRUint8 *genx;
-    const PRUint8 *geny;
-    const PRUint8 *order;
-    const PRUint8 *base;
-    int cofactor;
-    int security;
-    size_t pointSize;
-    size_t scalarSize;
-    unsigned int usage;
-};
-typedef struct ECCurveBytesStr ECCurveBytes;
-
-#endif /* __ecl_h_ */
--- a/lib/freebl/exports.gyp
+++ b/lib/freebl/exports.gyp
@@ -28,17 +28,16 @@
         {
           'files': [
             'alghmac.h',
             'blapi.h',
             'chacha20poly1305.h',
             'ec.h',
             'ecl/ecl-curve.h',
             'ecl/ecl.h',
-            'ecl/eclt.h',
             'hmacct.h',
             'secmpi.h',
             'secrng.h'
           ],
           'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
--- a/lib/freebl/freebl_base.gypi
+++ b/lib/freebl/freebl_base.gypi
@@ -16,16 +16,17 @@
     'desblapi.c',
     'dh.c',
     'drbg.c',
     'dsa.c',
     'ec.c',
     'ecdecode.c',
     'ecl/ec_naf.c',
     'ecl/ecl.c',
+    'ecl/ecl_curve.c',
     'ecl/ecl_gf.c',
     'ecl/ecl_mult.c',
     'ecl/ecp_25519.c',
     'ecl/ecp_256.c',
     'ecl/ecp_256_32.c',
     'ecl/ecp_384.c',
     'ecl/ecp_521.c',
     'ecl/ecp_aff.c',
--- a/lib/freebl/manifest.mn
+++ b/lib/freebl/manifest.mn
@@ -89,26 +89,25 @@ PRIVATE_EXPORTS = \
 	blapi.h \
 	chacha20poly1305.h \
 	hmacct.h \
 	secmpi.h \
 	secrng.h \
 	ec.h \
 	ecl.h \
 	ecl-curve.h \
-	eclt.h \
 	$(NULL)
 
 MPI_HDRS = mpi-config.h mpi.h mpi-priv.h mplogic.h mpprime.h logtab.h mp_gf2m.h
 MPI_SRCS = mpprime.c mpmontg.c mplogic.c mpi.c mp_gf2m.c
 
 
 ECL_HDRS = ecl-exp.h ecl.h ecp.h ecl-priv.h
 ifndef NSS_DISABLE_ECC
-ECL_SRCS = ecl.c ecl_mult.c ecl_gf.c \
+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_25519.c
 else
 ECL_SRCS = $(NULL)
 endif
 SHA_SRCS = sha_fast.c
 MPCPU_SRCS = mpcpucache.c