Commit 3d6811b6 authored by Franziskus Kiefer's avatar Franziskus Kiefer

Bug 1347975 - use bytes for curve parameter definitions, r=ttaubert

--HG--
extra : rebase_source : 905a759b7370c382cd122b986fe7f3bdd3ed7ec4
parent 3df657f3
......@@ -26,70 +26,6 @@
#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 *);
......@@ -374,30 +310,6 @@ PKCS11_Verify(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *hKey,
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. */
......@@ -423,7 +335,7 @@ ectest_curve_pkcs11(ECCurveName curve, int iterations, int numThreads)
ecParams.data = NULL;
ecParams.len = 0;
rv = ecName2params(curve, &ecParams);
rv = SECU_ecName2params(curve, &ecParams);
if (rv != SECSuccess) {
goto cleanup;
}
......@@ -542,9 +454,9 @@ ectest_curve_freebl(ECCurveName curve, int iterations, int numThreads,
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) {
......@@ -556,28 +468,11 @@ ectest_curve_freebl(ECCurveName curve, int iterations, int numThreads,
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.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;
rv = SECU_ecName2params(curve, &ecEncodedParams);
if (rv != SECSuccess) {
goto cleanup;
}
EC_FillParams(arena, &ecEncodedParams, &ecParams);
PORT_Memset(digestData, 0xa5, sizeof(digestData));
digest.data = digestData;
......@@ -618,6 +513,7 @@ ectest_curve_freebl(ECCurveName curve, int iterations, int numThreads,
}
cleanup:
SECITEM_FreeItem(&ecEncodedParams, PR_FALSE);
PORT_FreeArena(arena, PR_FALSE);
PORT_FreeArena(ecPriv->ecParams.arena, PR_FALSE);
return rv;
......
......@@ -88,26 +88,19 @@ ectest_ecdh_kat(ECDH_KAT *kat)
SECItem answer = { siBuffer, NULL, 0 };
SECItem answer2 = { siBuffer, NULL, 0 };
SECItem derived = { siBuffer, NULL, 0 };
char genenc[3 + 2 * 2 * MAX_ECKEY_LEN];
SECItem ecEncodedParams = { siBuffer, NULL, 0 };
int i;
rv = init_params(&ecParams, curve, &arena, kat->fieldType);
if (rv != SECSuccess) {
return rv;
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (!arena) {
return SECFailure;
}
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);
rv = SECU_ecName2params(curve, &ecEncodedParams);
if (rv != SECSuccess) {
goto cleanup;
}
EC_FillParams(arena, &ecEncodedParams, &ecParams);
if (kat->our_pubhex) {
SECU_HexString2SECItem(arena, &answer, kat->our_pubhex);
......@@ -161,6 +154,7 @@ ectest_ecdh_kat(ECDH_KAT *kat)
}
cleanup:
SECITEM_FreeItem(&ecEncodedParams, PR_FALSE);
PORT_FreeArena(arena, PR_FALSE);
if (ecPriv) {
PORT_FreeArena(ecPriv->ecParams.arena, PR_FALSE);
......
......@@ -774,3 +774,93 @@ SECU_HexString2SECItem(PLArenaPool *arena, SECItem *item, const char *str)
return item;
}
/* 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, SECItem *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;
}
......@@ -13,6 +13,7 @@
#include "base64.h"
#include "secasn1.h"
#include "secder.h"
#include "ecl-exp.h"
#include <stdio.h>
#ifdef SECUTIL_NEW
......@@ -86,6 +87,8 @@ SECU_SECItemHexStringToBinary(SECItem *srcdest);
extern SECItem *SECU_HexString2SECItem(PLArenaPool *arena, SECItem *item,
const char *str);
extern SECStatus SECU_ecName2params(ECCurveName curve, SECItem *params);
/*
*
* Utilities for parsing security tools command lines
......
......@@ -18,6 +18,7 @@
#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"
......@@ -402,11 +403,6 @@ SECStatus
SECU_ParseSSLVersionRangeString(const char *input,
const SSLVersionRange defaultVersionRange,
SSLVersionRange *vrange);
/*
** Read a hex string into a SecItem.
*/
extern SECItem *SECU_HexString2SECItem(PLArenaPool *arena, SECItem *item,
const char *str);
SECStatus parseGroupList(const char *arg, SSLNamedGroup **enabledGroups,
unsigned int *enabledGroupsCount);
......
......@@ -22,57 +22,6 @@
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
......@@ -120,12 +69,10 @@ cleanup:
}
static SECStatus
gf_populate_params(ECCurveName name, ECFieldType field_type, ECParams *params)
gf_populate_params_bytes(ECCurveName name, ECFieldType field_type, ECParams *params)
{
SECStatus rv = SECFailure;
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];
const ECCurveBytes *curveParams;
if ((name < ECCurve_noName) || (name > ECCurve_pastLastCurve))
goto cleanup;
......@@ -134,26 +81,19 @@ 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 ||
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));
if (field_type != ec_field_GFp && field_type != ec_field_plain) {
return SECFailure;
}
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->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;
params->cofactor = curveParams->cofactor;
rv = SECSuccess;
......@@ -216,29 +156,30 @@ EC_FillParams(PLArenaPool *arena, const SECItem *encodedParams,
/* Populate params for prime256v1 aka secp256r1
* (the NIST P-256 curve)
*/
CHECK_SEC_OK(gf_populate_params(ECCurve_X9_62_PRIME_256V1, ec_field_GFp,
params));
CHECK_SEC_OK(gf_populate_params_bytes(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(ECCurve_SECG_PRIME_384R1, ec_field_GFp,
params));
CHECK_SEC_OK(gf_populate_params_bytes(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(ECCurve_SECG_PRIME_521R1, ec_field_GFp,
params));
CHECK_SEC_OK(gf_populate_params_bytes(ECCurve_SECG_PRIME_521R1,
ec_field_GFp, params));
break;
case SEC_OID_CURVE25519:
/* Populate params for Curve25519 */
CHECK_SEC_OK(gf_populate_params(ECCurve25519, ec_field_plain, params));
CHECK_SEC_OK(gf_populate_params_bytes(ECCurve25519, ec_field_plain,
params));
break;
default:
......@@ -296,16 +237,20 @@ int
EC_GetPointSize(const ECParams *params)
{
ECCurveName name = params->name;
const ECCurveParams *curveParams;
const ECCurveBytes *curveParams;
if ((name < ECCurve_noName) || (name > ECCurve_pastLastCurve) ||
((curveParams = ecCurve_map[name]) == NULL)) {
/* unknown curve, calculate point size from params. assume standard curves with 2 points
/* 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;
}
return curveParams->pointSize;
if (name == ECCurve25519) {
/* Only X here */
return curveParams->scalarSize;
}
return curveParams->pointSize - 1;
}
#endif /* NSS_DISABLE_ECC */
This diff is collapsed.
......@@ -2,11 +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/. */
#ifdef FREEBL_NO_DEPEND
#include "../stubs.h"
#endif
#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>
......@@ -128,37 +133,16 @@ CLEANUP:
return group;
}
/* Construct ECGroup from hex parameters and name, if any. Called by
* ECGroup_fromHex and ECGroup_fromName. */
/* Construct an ECGroup. */
ECGroup *
ecgroup_fromNameAndHex(const ECCurveName name,
const ECCurveParams *params)
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)
{
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_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) {
......@@ -167,12 +151,12 @@ ecgroup_fromNameAndHex(const ECCurveName name,
}
/* determine which optimizations (if any) to use */
if (params->field == ECField_GFp) {
if (field == ECField_GFp) {
switch (name) {
case ECCurve_SECG_PRIME_256R1:
group =
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
&order, params->cofactor);
&order, cofactor);
if (group == NULL) {
res = MP_UNDEF;
goto CLEANUP;
......@@ -183,7 +167,7 @@ ecgroup_fromNameAndHex(const ECCurveName name,
case ECCurve_SECG_PRIME_521R1:
group =
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
&order, params->cofactor);
&order, cofactor);
if (group == NULL) {
res = MP_UNDEF;
goto CLEANUP;
......@@ -194,7 +178,7 @@ ecgroup_fromNameAndHex(const ECCurveName name,
/* use generic arithmetic */
group =
ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny,
&order, params->cofactor);
&order, cofactor);
if (group == NULL) {
res = MP_UNDEF;
goto CLEANUP;
......@@ -206,13 +190,53 @@ ecgroup_fromNameAndHex(const ECCurveName name,
}
/* set name, if any */
if ((group != NULL) && (params->text != NULL)) {
group->text = strdup(params->text);
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)
{
mp_int irr, curvea, curveb, genx, geny, order;
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));
group = construct_ecgroup(name, irr, curvea, curveb, genx, geny, order,
params->cofactor, params->field, params->text);
CLEANUP:
mp_clear(&irr);
mp_clear(&curvea);
......@@ -220,18 +244,23 @@ CLEANUP:
mp_clear(&genx);
mp_clear(&geny);
mp_clear(&order);
if (res != MP_OKAY) {
if (group && res != MP_OKAY) {
ECGroup_free(group);
return NULL;
}
return group;
}
/* Construct ECGroup from hexadecimal representations of parameters. */
ECGroup *
ECGroup_fromHex(const ECCurveParams *params)
/* Construct ECCurveBytes from an ECCurveName */
const ECCurveBytes *
ec_GetNamedCurveParams(const ECCurveName name)
{
return ecgroup_fromNameAndHex(ECCurve_noName, params);
if ((name <= ECCurve_noName) || (ECCurve_pastLastCurve <= name) ||
(ecCurve_map[name] == NULL)) {
return NULL;
} else {
return ecCurve_map[name];
}
}
/* Construct ECGroup from named parameters. */
......@@ -239,25 +268,26 @@ ECGroup *
ECGroup_fromName(const ECCurveName name)
{
ECGroup *group = NULL;
ECCurveParams *params = NULL;
const ECCurveBytes *params = NULL;
mp_err res = MP_OKAY;
params = EC_GetNamedCurveParams(name);
/* This doesn't work with Curve25519 but it's not necessary to. */
PORT_Assert(name != ECCurve25519);
params = ec_GetNamedCurveParams(name);
if (params == NULL) {
res = MP_UNDEF;
goto CLEANUP;
}
/* construct actual group */
group = ecgroup_fromNameAndHex(name, params);
group = ecgroup_fromName(name, params);
if (group == NULL) {
res = MP_UNDEF;
goto CLEANUP;
}
CLEANUP:
EC_FreeCurveParams(params);
if (res != MP_OKAY) {
if (group && res != MP_OKAY) {
ECGroup_free(group);
return NULL;
}
......
......@@ -11,28 +11,17 @@
#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);