From dc1565216a5d20ae0d75872151523252309a1292 Mon Sep 17 00:00:00 2001 From: Lorry Tar Creator Date: Wed, 4 Jan 2017 14:24:24 +0000 Subject: nss-3.28.1 --- nss/lib/freebl/ec.c | 832 ++++++++++++++++++++++++++++------------------------ 1 file changed, 449 insertions(+), 383 deletions(-) (limited to 'nss/lib/freebl/ec.c') diff --git a/nss/lib/freebl/ec.c b/nss/lib/freebl/ec.c index 4435f91..a9b7c05 100644 --- a/nss/lib/freebl/ec.c +++ b/nss/lib/freebl/ec.c @@ -6,7 +6,6 @@ #include "stubs.h" #endif - #include "blapi.h" #include "prerr.h" #include "secerr.h" @@ -18,7 +17,25 @@ #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 */ PRBool @@ -27,25 +44,23 @@ ec_point_at_infinity(SECItem *pointP) unsigned int i; for (i = 1; i < pointP->len; i++) { - if (pointP->data[i] != 0x00) return PR_FALSE; + if (pointP->data[i] != 0x00) + return PR_FALSE; } return PR_TRUE; } -/* +/* * Computes scalar point multiplication pointQ = k1 * G + k2 * pointP for * the curve whose parameters are encoded in params with base point G. */ -SECStatus +SECStatus ec_points_mul(const ECParams *params, const mp_int *k1, const mp_int *k2, - const SECItem *pointP, SECItem *pointQ) + const SECItem *pointP, SECItem *pointQ) { mp_int Px, Py, Qx, Qy; mp_int Gx, Gy, order, irreducible, a, b; -#if 0 /* currently don't support non-named curves */ - unsigned int irr_arr[5]; -#endif ECGroup *group = NULL; SECStatus rv = SECFailure; mp_err err = MP_OKAY; @@ -56,120 +71,96 @@ ec_points_mul(const ECParams *params, const mp_int *k1, const mp_int *k2, char mpstr[256]; printf("ec_points_mul: params [len=%d]:", params->DEREncoding.len); - for (i = 0; i < params->DEREncoding.len; i++) - printf("%02x:", params->DEREncoding.data[i]); + for (i = 0; i < params->DEREncoding.len; i++) + printf("%02x:", params->DEREncoding.data[i]); printf("\n"); - if (k1 != NULL) { - mp_tohex(k1, mpstr); - printf("ec_points_mul: scalar k1: %s\n", mpstr); - mp_todecimal(k1, mpstr); - printf("ec_points_mul: scalar k1: %s (dec)\n", mpstr); - } - - if (k2 != NULL) { - mp_tohex(k2, mpstr); - printf("ec_points_mul: scalar k2: %s\n", mpstr); - mp_todecimal(k2, mpstr); - printf("ec_points_mul: scalar k2: %s (dec)\n", mpstr); - } - - if (pointP != NULL) { - printf("ec_points_mul: pointP [len=%d]:", pointP->len); - for (i = 0; i < pointP->len; i++) - printf("%02x:", pointP->data[i]); - printf("\n"); - } -#endif + if (k1 != NULL) { + mp_tohex((mp_int *)k1, mpstr); + printf("ec_points_mul: scalar k1: %s\n", mpstr); + mp_todecimal((mp_int *)k1, mpstr); + printf("ec_points_mul: scalar k1: %s (dec)\n", mpstr); + } - /* NOTE: We only support uncompressed points for now */ - len = (params->fieldID.size + 7) >> 3; - if (pointP != NULL) { - if ((pointP->data[0] != EC_POINT_FORM_UNCOMPRESSED) || - (pointP->len != (2 * len + 1))) { - PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM); - return SECFailure; - }; - } - - MP_DIGITS(&Px) = 0; - MP_DIGITS(&Py) = 0; - MP_DIGITS(&Qx) = 0; - MP_DIGITS(&Qy) = 0; - MP_DIGITS(&Gx) = 0; - MP_DIGITS(&Gy) = 0; - MP_DIGITS(&order) = 0; - MP_DIGITS(&irreducible) = 0; - MP_DIGITS(&a) = 0; - MP_DIGITS(&b) = 0; - CHECK_MPI_OK( mp_init(&Px) ); - CHECK_MPI_OK( mp_init(&Py) ); - CHECK_MPI_OK( mp_init(&Qx) ); - CHECK_MPI_OK( mp_init(&Qy) ); - CHECK_MPI_OK( mp_init(&Gx) ); - CHECK_MPI_OK( mp_init(&Gy) ); - CHECK_MPI_OK( mp_init(&order) ); - CHECK_MPI_OK( mp_init(&irreducible) ); - CHECK_MPI_OK( mp_init(&a) ); - CHECK_MPI_OK( mp_init(&b) ); - - if ((k2 != NULL) && (pointP != NULL)) { - /* Initialize Px and Py */ - CHECK_MPI_OK( mp_read_unsigned_octets(&Px, pointP->data + 1, (mp_size) len) ); - CHECK_MPI_OK( mp_read_unsigned_octets(&Py, pointP->data + 1 + len, (mp_size) len) ); - } - - /* construct from named params, if possible */ - if (params->name != ECCurve_noName) { - group = ECGroup_fromName(params->name); - } - -#if 0 /* currently don't support non-named curves */ - if (group == NULL) { - /* Set up mp_ints containing the curve coefficients */ - CHECK_MPI_OK( mp_read_unsigned_octets(&Gx, params->base.data + 1, - (mp_size) len) ); - CHECK_MPI_OK( mp_read_unsigned_octets(&Gy, params->base.data + 1 + len, - (mp_size) len) ); - SECITEM_TO_MPINT( params->order, &order ); - SECITEM_TO_MPINT( params->curve.a, &a ); - SECITEM_TO_MPINT( params->curve.b, &b ); - if (params->fieldID.type == ec_field_GFp) { - SECITEM_TO_MPINT( params->fieldID.u.prime, &irreducible ); - group = ECGroup_consGFp(&irreducible, &a, &b, &Gx, &Gy, &order, params->cofactor); - } else { - SECITEM_TO_MPINT( params->fieldID.u.poly, &irreducible ); - irr_arr[0] = params->fieldID.size; - irr_arr[1] = params->fieldID.k1; - irr_arr[2] = params->fieldID.k2; - irr_arr[3] = params->fieldID.k3; - irr_arr[4] = 0; - group = ECGroup_consGF2m(&irreducible, irr_arr, &a, &b, &Gx, &Gy, &order, params->cofactor); - } - } + if (k2 != NULL) { + mp_tohex((mp_int *)k2, mpstr); + printf("ec_points_mul: scalar k2: %s\n", mpstr); + mp_todecimal((mp_int *)k2, mpstr); + printf("ec_points_mul: scalar k2: %s (dec)\n", mpstr); + } + + if (pointP != NULL) { + printf("ec_points_mul: pointP [len=%d]:", pointP->len); + for (i = 0; i < pointP->len; i++) + printf("%02x:", pointP->data[i]); + printf("\n"); + } #endif - if (group == NULL) - goto cleanup; - if ((k2 != NULL) && (pointP != NULL)) { - CHECK_MPI_OK( ECPoints_mul(group, k1, k2, &Px, &Py, &Qx, &Qy) ); - } else { - CHECK_MPI_OK( ECPoints_mul(group, k1, NULL, NULL, NULL, &Qx, &Qy) ); + /* NOTE: We only support uncompressed points for now */ + len = (params->fieldID.size + 7) >> 3; + if (pointP != NULL) { + if ((pointP->data[0] != EC_POINT_FORM_UNCOMPRESSED) || + (pointP->len != (2 * len + 1))) { + PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM); + return SECFailure; + }; + } + + MP_DIGITS(&Px) = 0; + MP_DIGITS(&Py) = 0; + MP_DIGITS(&Qx) = 0; + MP_DIGITS(&Qy) = 0; + MP_DIGITS(&Gx) = 0; + MP_DIGITS(&Gy) = 0; + MP_DIGITS(&order) = 0; + MP_DIGITS(&irreducible) = 0; + MP_DIGITS(&a) = 0; + MP_DIGITS(&b) = 0; + CHECK_MPI_OK(mp_init(&Px)); + CHECK_MPI_OK(mp_init(&Py)); + CHECK_MPI_OK(mp_init(&Qx)); + CHECK_MPI_OK(mp_init(&Qy)); + CHECK_MPI_OK(mp_init(&Gx)); + CHECK_MPI_OK(mp_init(&Gy)); + CHECK_MPI_OK(mp_init(&order)); + CHECK_MPI_OK(mp_init(&irreducible)); + CHECK_MPI_OK(mp_init(&a)); + CHECK_MPI_OK(mp_init(&b)); + + if ((k2 != NULL) && (pointP != NULL)) { + /* Initialize Px and Py */ + CHECK_MPI_OK(mp_read_unsigned_octets(&Px, pointP->data + 1, (mp_size)len)); + CHECK_MPI_OK(mp_read_unsigned_octets(&Py, pointP->data + 1 + len, (mp_size)len)); + } + + /* construct from named params, if possible */ + if (params->name != ECCurve_noName) { + group = ECGroup_fromName(params->name); + } + + if (group == NULL) + goto cleanup; + + if ((k2 != NULL) && (pointP != NULL)) { + CHECK_MPI_OK(ECPoints_mul(group, k1, k2, &Px, &Py, &Qx, &Qy)); + } else { + CHECK_MPI_OK(ECPoints_mul(group, k1, NULL, NULL, NULL, &Qx, &Qy)); } /* Construct the SECItem representation of point Q */ pointQ->data[0] = EC_POINT_FORM_UNCOMPRESSED; - CHECK_MPI_OK( mp_to_fixlen_octets(&Qx, pointQ->data + 1, - (mp_size) len) ); - CHECK_MPI_OK( mp_to_fixlen_octets(&Qy, pointQ->data + 1 + len, - (mp_size) len) ); + CHECK_MPI_OK(mp_to_fixlen_octets(&Qx, pointQ->data + 1, + (mp_size)len)); + CHECK_MPI_OK(mp_to_fixlen_octets(&Qy, pointQ->data + 1 + len, + (mp_size)len)); rv = SECSuccess; #if EC_DEBUG printf("ec_points_mul: pointQ [len=%d]:", pointQ->len); - for (i = 0; i < pointQ->len; i++) - printf("%02x:", pointQ->data[i]); + for (i = 0; i < pointQ->len; i++) + printf("%02x:", pointQ->data[i]); printf("\n"); #endif @@ -186,8 +177,8 @@ cleanup: mp_clear(&a); mp_clear(&b); if (err) { - MP_TO_SEC_ERROR(err); - rv = SECFailure; + MP_TO_SEC_ERROR(err); + rv = SECFailure; } return rv; @@ -195,12 +186,12 @@ cleanup: #endif /* NSS_DISABLE_ECC */ /* Generates a new EC key pair. The private key is a supplied - * value and the public key is the result of performing a scalar + * value and the public key is the result of performing a scalar * point multiplication of that value with the curve's base point. */ -SECStatus -ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey, - const unsigned char *privKeyBytes, int privKeyLen) +SECStatus +ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey, + const unsigned char *privKeyBytes, int privKeyLen) { SECStatus rv = SECFailure; #ifndef NSS_DISABLE_ECC @@ -215,19 +206,20 @@ ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey, #endif MP_DIGITS(&k) = 0; - if (!ecParams || !privKey || !privKeyBytes || (privKeyLen < 0)) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; + if (!ecParams || !privKey || !privKeyBytes || (privKeyLen < 0) || + !ecParams->name) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; } /* Initialize an arena for the EC key. */ if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE))) - return SECFailure; + return SECFailure; key = (ECPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(ECPrivateKey)); if (!key) { - PORT_FreeArena(arena, PR_TRUE); - return SECFailure; + PORT_FreeArena(arena, PR_TRUE); + return SECFailure; } /* Set the version number (SEC 1 section C.4 says it should be 1) */ @@ -241,80 +233,98 @@ 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) { - CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.prime, - &ecParams->fieldID.u.prime)); + 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 { - CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.poly, - &ecParams->fieldID.u.poly)); + CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.poly, + &ecParams->fieldID.u.poly)); } key->ecParams.fieldID.k1 = ecParams->fieldID.k1; key->ecParams.fieldID.k2 = ecParams->fieldID.k2; key->ecParams.fieldID.k3 = ecParams->fieldID.k3; CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.a, - &ecParams->curve.a)); + &ecParams->curve.a)); CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.b, - &ecParams->curve.b)); + &ecParams->curve.b)); CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.seed, - &ecParams->curve.seed)); + &ecParams->curve.seed)); CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.base, - &ecParams->base)); + &ecParams->base)); CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.order, - &ecParams->order)); + &ecParams->order)); key->ecParams.cofactor = ecParams->cofactor; CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.DEREncoding, - &ecParams->DEREncoding)); + &ecParams->DEREncoding)); key->ecParams.name = ecParams->name; CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curveOID, - &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); /* Copy private key */ if (privKeyLen >= len) { - memcpy(key->privateValue.data, privKeyBytes, len); + memcpy(key->privateValue.data, privKeyBytes, len); } else { - memset(key->privateValue.data, 0, (len - privKeyLen)); - memcpy(key->privateValue.data + (len - privKeyLen), privKeyBytes, privKeyLen); + memset(key->privateValue.data, 0, (len - privKeyLen)); + memcpy(key->privateValue.data + (len - privKeyLen), privKeyBytes, privKeyLen); } /* Compute corresponding public key */ - CHECK_MPI_OK( mp_init(&k) ); - CHECK_MPI_OK( mp_read_unsigned_octets(&k, key->privateValue.data, - (mp_size) len) ); + + /* 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) goto cleanup; + if (rv != SECSuccess) { + goto cleanup; + } + +done: *privKey = key; cleanup: mp_clear(&k); - if (rv) - PORT_FreeArena(arena, PR_TRUE); + if (rv) { + PORT_FreeArena(arena, PR_TRUE); + } #if EC_DEBUG - printf("ec_NewKey returning %s\n", - (rv == SECSuccess) ? "success" : "failure"); + printf("ec_NewKey returning %s\n", + (rv == SECSuccess) ? "success" : "failure"); #endif #else PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); #endif /* NSS_DISABLE_ECC */ return rv; - } /* Generates a new EC key pair. The private key is a supplied - * random value (in seed) and the public key is the result of - * performing a scalar point multiplication of that value with + * random value (in seed) and the public key is the result of + * performing a scalar point multiplication of that value with * the curve's base point. */ -SECStatus -EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey, - const unsigned char *seed, int seedlen) +SECStatus +EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey, + const unsigned char *seed, int seedlen) { SECStatus rv = SECFailure; #ifndef NSS_DISABLE_ECC @@ -349,35 +359,36 @@ ec_GenerateRandomPrivateKey(const unsigned char *order, int len) MP_DIGITS(&privKeyVal) = 0; MP_DIGITS(&order_1) = 0; MP_DIGITS(&one) = 0; - CHECK_MPI_OK( mp_init(&privKeyVal) ); - CHECK_MPI_OK( mp_init(&order_1) ); - CHECK_MPI_OK( mp_init(&one) ); + CHECK_MPI_OK(mp_init(&privKeyVal)); + CHECK_MPI_OK(mp_init(&order_1)); + CHECK_MPI_OK(mp_init(&one)); /* Generates 2*len random bytes using the global random bit generator * (which implements Algorithm 1 of FIPS 186-2 Change Notice 1) then * reduces modulo the group order. */ - if ((privKeyBytes = PORT_Alloc(2*len)) == NULL) goto cleanup; - CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(privKeyBytes, 2*len) ); - CHECK_MPI_OK( mp_read_unsigned_octets(&privKeyVal, privKeyBytes, 2*len) ); - CHECK_MPI_OK( mp_read_unsigned_octets(&order_1, order, len) ); - CHECK_MPI_OK( mp_set_int(&one, 1) ); - CHECK_MPI_OK( mp_sub(&order_1, &one, &order_1) ); - CHECK_MPI_OK( mp_mod(&privKeyVal, &order_1, &privKeyVal) ); - CHECK_MPI_OK( mp_add(&privKeyVal, &one, &privKeyVal) ); - CHECK_MPI_OK( mp_to_fixlen_octets(&privKeyVal, privKeyBytes, len) ); - memset(privKeyBytes+len, 0, len); + if ((privKeyBytes = PORT_Alloc(2 * len)) == NULL) + goto cleanup; + CHECK_SEC_OK(RNG_GenerateGlobalRandomBytes(privKeyBytes, 2 * len)); + CHECK_MPI_OK(mp_read_unsigned_octets(&privKeyVal, privKeyBytes, 2 * len)); + CHECK_MPI_OK(mp_read_unsigned_octets(&order_1, order, len)); + CHECK_MPI_OK(mp_set_int(&one, 1)); + CHECK_MPI_OK(mp_sub(&order_1, &one, &order_1)); + CHECK_MPI_OK(mp_mod(&privKeyVal, &order_1, &privKeyVal)); + CHECK_MPI_OK(mp_add(&privKeyVal, &one, &privKeyVal)); + CHECK_MPI_OK(mp_to_fixlen_octets(&privKeyVal, privKeyBytes, len)); + memset(privKeyBytes + len, 0, len); cleanup: mp_clear(&privKeyVal); mp_clear(&order_1); mp_clear(&one); if (err < MP_OKAY) { - MP_TO_SEC_ERROR(err); - rv = SECFailure; + MP_TO_SEC_ERROR(err); + rv = SECFailure; } if (rv != SECSuccess && privKeyBytes) { - PORT_Free(privKeyBytes); - privKeyBytes = NULL; + PORT_ZFree(privKeyBytes, 2 * len); + privKeyBytes = NULL; } return privKeyBytes; } @@ -387,7 +398,7 @@ cleanup: * the public key is the result of performing a scalar point multiplication * of that value with the curve's base point. */ -SECStatus +SECStatus EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey) { SECStatus rv = SECFailure; @@ -396,38 +407,39 @@ EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey) unsigned char *privKeyBytes = NULL; if (!ecParams) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; } len = ecParams->order.len; privKeyBytes = ec_GenerateRandomPrivateKey(ecParams->order.data, len); - if (privKeyBytes == NULL) goto cleanup; + if (privKeyBytes == NULL) + goto cleanup; /* generate public key */ - CHECK_SEC_OK( ec_NewKey(ecParams, privKey, privKeyBytes, len) ); + CHECK_SEC_OK(ec_NewKey(ecParams, privKey, privKeyBytes, len)); cleanup: if (privKeyBytes) { - PORT_ZFree(privKeyBytes, len); + PORT_ZFree(privKeyBytes, len); } #if EC_DEBUG - printf("EC_NewKey returning %s\n", - (rv == SECSuccess) ? "success" : "failure"); + printf("EC_NewKey returning %s\n", + (rv == SECSuccess) ? "success" : "failure"); #endif #else PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); #endif /* NSS_DISABLE_ECC */ - + return rv; } /* Validates an EC public key as described in Section 5.2.2 of * X9.62. The ECDH primitive when used without the cofactor does * not address small subgroup attacks, which may occur when the - * public key is not valid. These attacks can be prevented by + * public key is not valid. These attacks can be prevented by * validating the public key before using ECDH. */ -SECStatus +SECStatus EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue) { #ifndef NSS_DISABLE_ECC @@ -437,59 +449,70 @@ EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue) mp_err err = MP_OKAY; int len; - if (!ecParams || !publicValue) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; + 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 */ + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + 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) { - PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM); - return SECFailure; + PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM); + return SECFailure; } else if (publicValue->len != (2 * len + 1)) { - PORT_SetError(SEC_ERROR_BAD_KEY); - return SECFailure; + PORT_SetError(SEC_ERROR_BAD_KEY); + return SECFailure; } MP_DIGITS(&Px) = 0; MP_DIGITS(&Py) = 0; - CHECK_MPI_OK( mp_init(&Px) ); - CHECK_MPI_OK( mp_init(&Py) ); + CHECK_MPI_OK(mp_init(&Px)); + CHECK_MPI_OK(mp_init(&Py)); /* Initialize Px and Py */ - CHECK_MPI_OK( mp_read_unsigned_octets(&Px, publicValue->data + 1, (mp_size) len) ); - CHECK_MPI_OK( mp_read_unsigned_octets(&Py, publicValue->data + 1 + len, (mp_size) len) ); + CHECK_MPI_OK(mp_read_unsigned_octets(&Px, publicValue->data + 1, (mp_size)len)); + CHECK_MPI_OK(mp_read_unsigned_octets(&Py, publicValue->data + 1 + len, (mp_size)len)); /* construct from named params */ group = ECGroup_fromName(ecParams->name); if (group == NULL) { - /* - * ECGroup_fromName fails if ecParams->name is not a valid - * ECCurveName value, or if we run out of memory, or perhaps - * for other reasons. Unfortunately if ecParams->name is a - * valid ECCurveName value, we don't know what the right error - * code should be because ECGroup_fromName doesn't return an - * error code to the caller. Set err to MP_UNDEF because - * that's what ECGroup_fromName uses internally. - */ - if ((ecParams->name <= ECCurve_noName) || - (ecParams->name >= ECCurve_pastLastCurve)) { - err = MP_BADARG; - } else { - err = MP_UNDEF; - } - goto cleanup; + /* + * ECGroup_fromName fails if ecParams->name is not a valid + * ECCurveName value, or if we run out of memory, or perhaps + * for other reasons. Unfortunately if ecParams->name is a + * valid ECCurveName value, we don't know what the right error + * code should be because ECGroup_fromName doesn't return an + * error code to the caller. Set err to MP_UNDEF because + * that's what ECGroup_fromName uses internally. + */ + if ((ecParams->name <= ECCurve_noName) || + (ecParams->name >= ECCurve_pastLastCurve)) { + err = MP_BADARG; + } else { + err = MP_UNDEF; + } + goto cleanup; } /* validate public point */ if ((err = ECPoint_validate(group, &Px, &Py)) < MP_YES) { - if (err == MP_NO) { - PORT_SetError(SEC_ERROR_BAD_KEY); - rv = SECFailure; - err = MP_OKAY; /* don't change the error code */ - } - goto cleanup; + if (err == MP_NO) { + PORT_SetError(SEC_ERROR_BAD_KEY); + rv = SECFailure; + err = MP_OKAY; /* don't change the error code */ + } + goto cleanup; } rv = SECSuccess; @@ -499,8 +522,8 @@ cleanup: mp_clear(&Px); mp_clear(&Py); if (err) { - MP_TO_SEC_ERROR(err); - rv = SECFailure; + MP_TO_SEC_ERROR(err); + rv = SECFailure; } return rv; #else @@ -509,7 +532,7 @@ cleanup: #endif /* NSS_DISABLE_ECC */ } -/* +/* ** Performs an ECDH key derivation by computing the scalar point ** multiplication of privateValue and publicValue (with or without the ** cofactor) and returns the x-coordinate of the resulting elliptic @@ -519,17 +542,17 @@ cleanup: ** produced. It is the caller's responsibility to free the allocated ** buffer containing the derived secret. */ -SECStatus -ECDH_Derive(SECItem *publicValue, +SECStatus +ECDH_Derive(SECItem *publicValue, ECParams *ecParams, - SECItem *privateValue, - PRBool withCofactor, - SECItem *derivedSecret) + SECItem *privateValue, + PRBool withCofactor, + SECItem *derivedSecret) { SECStatus rv = SECFailure; #ifndef NSS_DISABLE_ECC unsigned int len = 0; - SECItem pointQ = {siBuffer, NULL, 0}; + SECItem pointQ = { siBuffer, NULL, 0 }; mp_int k; /* to hold the private value */ mp_int cofactor; mp_err err = MP_OKAY; @@ -537,10 +560,32 @@ ECDH_Derive(SECItem *publicValue, int i; #endif - if (!publicValue || !ecParams || !privateValue || - !derivedSecret) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; + 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)); + 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); } /* @@ -548,34 +593,36 @@ ECDH_Derive(SECItem *publicValue, * this produces predictable results. */ if (ec_point_at_infinity(publicValue)) { - PORT_SetError(SEC_ERROR_BAD_KEY); - return SECFailure; + PORT_SetError(SEC_ERROR_BAD_KEY); + return SECFailure; } 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) goto cleanup; + len = (ecParams->fieldID.size + 7) >> 3; + pointQ.len = ecParams->pointSize; + if ((pointQ.data = PORT_Alloc(ecParams->pointSize)) == NULL) + goto cleanup; - CHECK_MPI_OK( mp_init(&k) ); - CHECK_MPI_OK( mp_read_unsigned_octets(&k, privateValue->data, - (mp_size) privateValue->len) ); + CHECK_MPI_OK(mp_init(&k)); + CHECK_MPI_OK(mp_read_unsigned_octets(&k, privateValue->data, + (mp_size)privateValue->len)); if (withCofactor && (ecParams->cofactor != 1)) { - /* multiply k with the cofactor */ - MP_DIGITS(&cofactor) = 0; - CHECK_MPI_OK( mp_init(&cofactor) ); - mp_set(&cofactor, ecParams->cofactor); - CHECK_MPI_OK( mp_mul(&k, &cofactor, &k) ); + /* multiply k with the cofactor */ + MP_DIGITS(&cofactor) = 0; + CHECK_MPI_OK(mp_init(&cofactor)); + mp_set(&cofactor, ecParams->cofactor); + CHECK_MPI_OK(mp_mul(&k, &cofactor, &k)); } /* Multiply our private key and peer's public point */ - if (ec_points_mul(ecParams, NULL, &k, publicValue, &pointQ) != SECSuccess) - goto cleanup; + 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; + PORT_SetError(SEC_ERROR_BAD_KEY); /* XXX better error code? */ + goto cleanup; } /* Allocate memory for the derived secret and copy @@ -588,8 +635,8 @@ ECDH_Derive(SECItem *publicValue, #if EC_DEBUG printf("derived_secret:\n"); - for (i = 0; i < derivedSecret->len; i++) - printf("%02x:", derivedSecret->data[i]); + for (i = 0; i < derivedSecret->len; i++) + printf("%02x:", derivedSecret->data[i]); printf("\n"); #endif @@ -597,11 +644,11 @@ cleanup: mp_clear(&k); if (err) { - MP_TO_SEC_ERROR(err); + MP_TO_SEC_ERROR(err); } if (pointQ.data) { - PORT_ZFree(pointQ.data, 2*len + 1); + PORT_ZFree(pointQ.data, ecParams->pointSize); } #else PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); @@ -614,22 +661,24 @@ cleanup: * on the digest using the given key and the random value kb (used in * computing s). */ -SECStatus -ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, - const SECItem *digest, const unsigned char *kb, const int kblen) +SECStatus +ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, + const SECItem *digest, const unsigned char *kb, const int kblen) { SECStatus rv = SECFailure; #ifndef NSS_DISABLE_ECC mp_int x1; - mp_int d, k; /* private key, random integer */ - mp_int r, s; /* tuple (r, s) is the signature */ + mp_int d, k; /* private key, random integer */ + mp_int r, s; /* tuple (r, s) is the signature */ + mp_int t; /* holding tmp values */ mp_int n; mp_err err = MP_OKAY; ECParams *ecParams = NULL; - SECItem kGpoint = { siBuffer, NULL, 0}; - int flen = 0; /* length in bytes of the field size */ - unsigned olen; /* length in bytes of the base point order */ - unsigned obits; /* length in bits of the base point order */ + SECItem kGpoint = { siBuffer, NULL, 0 }; + int flen = 0; /* length in bytes of the field size */ + unsigned olen; /* length in bytes of the base point order */ + unsigned obits; /* length in bits of the base point order */ + unsigned char *t2 = NULL; #if EC_DEBUG char mpstr[256]; @@ -643,48 +692,49 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, MP_DIGITS(&r) = 0; MP_DIGITS(&s) = 0; MP_DIGITS(&n) = 0; + MP_DIGITS(&t) = 0; /* Check args */ if (!key || !signature || !digest || !kb || (kblen < 0)) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - goto cleanup; + PORT_SetError(SEC_ERROR_INVALID_ARGS); + goto cleanup; } ecParams = &(key->ecParams); flen = (ecParams->fieldID.size + 7) >> 3; - olen = ecParams->order.len; + olen = ecParams->order.len; if (signature->data == NULL) { - /* a call to get the signature length only */ - goto finish; + /* a call to get the signature length only */ + goto finish; } - if (signature->len < 2*olen) { - PORT_SetError(SEC_ERROR_OUTPUT_LEN); - goto cleanup; + if (signature->len < 2 * olen) { + PORT_SetError(SEC_ERROR_OUTPUT_LEN); + goto cleanup; } + CHECK_MPI_OK(mp_init(&x1)); + CHECK_MPI_OK(mp_init(&d)); + CHECK_MPI_OK(mp_init(&k)); + CHECK_MPI_OK(mp_init(&r)); + CHECK_MPI_OK(mp_init(&s)); + CHECK_MPI_OK(mp_init(&n)); + CHECK_MPI_OK(mp_init(&t)); - CHECK_MPI_OK( mp_init(&x1) ); - CHECK_MPI_OK( mp_init(&d) ); - CHECK_MPI_OK( mp_init(&k) ); - CHECK_MPI_OK( mp_init(&r) ); - CHECK_MPI_OK( mp_init(&s) ); - CHECK_MPI_OK( mp_init(&n) ); - - SECITEM_TO_MPINT( ecParams->order, &n ); - SECITEM_TO_MPINT( key->privateValue, &d ); + SECITEM_TO_MPINT(ecParams->order, &n); + SECITEM_TO_MPINT(key->privateValue, &d); - CHECK_MPI_OK( mp_read_unsigned_octets(&k, kb, kblen) ); + CHECK_MPI_OK(mp_read_unsigned_octets(&k, kb, kblen)); /* Make sure k is in the interval [1, n-1] */ if ((mp_cmp_z(&k) <= 0) || (mp_cmp(&k, &n) >= 0)) { #if EC_DEBUG printf("k is outside [1, n-1]\n"); mp_tohex(&k, mpstr); - printf("k : %s \n", mpstr); + printf("k : %s \n", mpstr); mp_tohex(&n, mpstr); - printf("n : %s \n", mpstr); + printf("n : %s \n", mpstr); #endif - PORT_SetError(SEC_ERROR_NEED_RANDOM); - goto cleanup; + PORT_SetError(SEC_ERROR_NEED_RANDOM); + goto cleanup; } /* @@ -703,61 +753,60 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, ** final value has exactly one more bit than n. Thus, we ** always end up with a value that exactly one more bit than n. */ - CHECK_MPI_OK( mp_add(&k, &n, &k) ); + CHECK_MPI_OK(mp_add(&k, &n, &k)); if (mpl_significant_bits(&k) <= mpl_significant_bits(&n)) { - CHECK_MPI_OK( mp_add(&k, &n, &k) ); + CHECK_MPI_OK(mp_add(&k, &n, &k)); } - /* + /* ** ANSI X9.62, Section 5.3.2, Step 2 ** ** 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; + (ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint) != SECSuccess)) + goto cleanup; - /* + /* ** ANSI X9.62, Section 5.3.3, Step 1 ** ** Extract the x co-ordinate of kG into x1 */ - CHECK_MPI_OK( mp_read_unsigned_octets(&x1, kGpoint.data + 1, - (mp_size) flen) ); + CHECK_MPI_OK(mp_read_unsigned_octets(&x1, kGpoint.data + 1, + (mp_size)flen)); - /* + /* ** ANSI X9.62, Section 5.3.3, Step 2 ** ** r = x1 mod n NOTE: n is the order of the curve */ - CHECK_MPI_OK( mp_mod(&x1, &n, &r) ); + CHECK_MPI_OK(mp_mod(&x1, &n, &r)); /* ** ANSI X9.62, Section 5.3.3, Step 3 ** - ** verify r != 0 + ** verify r != 0 */ if (mp_cmp_z(&r) == 0) { - PORT_SetError(SEC_ERROR_NEED_RANDOM); - goto cleanup; + PORT_SetError(SEC_ERROR_NEED_RANDOM); + goto cleanup; } - /* + /* ** ANSI X9.62, Section 5.3.3, Step 4 ** - ** s = (k**-1 * (HASH(M) + d*r)) mod n + ** s = (k**-1 * (HASH(M) + d*r)) mod n */ - SECITEM_TO_MPINT(*digest, &s); /* s = HASH(M) */ + SECITEM_TO_MPINT(*digest, &s); /* s = HASH(M) */ /* In the definition of EC signing, digests are truncated - * to the length of n in bits. + * to the length of n in bits. * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/ - CHECK_MPI_OK( (obits = mpl_significant_bits(&n)) ); - if (digest->len*8 > obits) { - mpl_rsh(&s,&s,digest->len*8 - obits); + CHECK_MPI_OK((obits = mpl_significant_bits(&n))); + if (digest->len * 8 > obits) { + mpl_rsh(&s, &s, digest->len * 8 - obits); } #if EC_DEBUG @@ -775,10 +824,22 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, printf("r : %s\n", mpstr); #endif - CHECK_MPI_OK( mp_invmod(&k, &n, &k) ); /* k = k**-1 mod n */ - CHECK_MPI_OK( mp_mulmod(&d, &r, &n, &d) ); /* d = d * r mod n */ - CHECK_MPI_OK( mp_addmod(&s, &d, &n, &s) ); /* s = s + d mod n */ - CHECK_MPI_OK( mp_mulmod(&s, &k, &n, &s) ); /* s = s * k mod n */ + if ((t2 = PORT_Alloc(2 * ecParams->order.len)) == NULL) { + rv = SECFailure; + goto cleanup; + } + if (RNG_GenerateGlobalRandomBytes(t2, 2 * ecParams->order.len) != SECSuccess) { + PORT_SetError(SEC_ERROR_NEED_RANDOM); + rv = SECFailure; + goto cleanup; + } + CHECK_MPI_OK(mp_read_unsigned_octets(&t, t2, 2 * ecParams->order.len)); /* t <-$ Zn */ + CHECK_MPI_OK(mp_mulmod(&k, &t, &n, &k)); /* k = k * t mod n */ + CHECK_MPI_OK(mp_invmod(&k, &n, &k)); /* k = k**-1 mod n */ + CHECK_MPI_OK(mp_mulmod(&k, &t, &n, &k)); /* k = k * t mod n */ + CHECK_MPI_OK(mp_mulmod(&d, &r, &n, &d)); /* d = d * r mod n */ + CHECK_MPI_OK(mp_addmod(&s, &d, &n, &s)); /* s = s + d mod n */ + CHECK_MPI_OK(mp_mulmod(&s, &k, &n, &s)); /* s = s * k mod n */ #if EC_DEBUG mp_todecimal(&s, mpstr); @@ -793,18 +854,18 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, ** verify s != 0 */ if (mp_cmp_z(&s) == 0) { - PORT_SetError(SEC_ERROR_NEED_RANDOM); - goto cleanup; + PORT_SetError(SEC_ERROR_NEED_RANDOM); + goto cleanup; } - /* + /* ** ** Signature is tuple (r, s) */ - CHECK_MPI_OK( mp_to_fixlen_octets(&r, signature->data, olen) ); - CHECK_MPI_OK( mp_to_fixlen_octets(&s, signature->data + olen, olen) ); + CHECK_MPI_OK(mp_to_fixlen_octets(&r, signature->data, olen)); + CHECK_MPI_OK(mp_to_fixlen_octets(&s, signature->data + olen, olen)); finish: - signature->len = 2*olen; + signature->len = 2 * olen; rv = SECSuccess; err = MP_OKAY; @@ -815,60 +876,66 @@ cleanup: mp_clear(&r); mp_clear(&s); mp_clear(&n); + mp_clear(&t); + + if (t2) { + PORT_Free(t2); + } if (kGpoint.data) { - PORT_ZFree(kGpoint.data, 2*flen + 1); + PORT_ZFree(kGpoint.data, ecParams->pointSize); } if (err) { - MP_TO_SEC_ERROR(err); - rv = SECFailure; + MP_TO_SEC_ERROR(err); + rv = SECFailure; } #if EC_DEBUG printf("ECDSA signing with seed %s\n", - (rv == SECSuccess) ? "succeeded" : "failed"); + (rv == SECSuccess) ? "succeeded" : "failed"); #endif #else PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); #endif /* NSS_DISABLE_ECC */ - return rv; + return rv; } /* -** Computes the ECDSA signature on the digest using the given key +** Computes the ECDSA signature on the digest using the given key ** and a random seed. */ -SECStatus +SECStatus ECDSA_SignDigest(ECPrivateKey *key, SECItem *signature, const SECItem *digest) { SECStatus rv = SECFailure; #ifndef NSS_DISABLE_ECC int len; - unsigned char *kBytes= NULL; + unsigned char *kBytes = NULL; if (!key) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; } /* Generate random value k */ len = key->ecParams.order.len; kBytes = ec_GenerateRandomPrivateKey(key->ecParams.order.data, len); - if (kBytes == NULL) goto cleanup; + if (kBytes == NULL) + goto cleanup; /* Generate ECDSA signature with the specified k value */ rv = ECDSA_SignDigestWithSeed(key, signature, digest, kBytes, len); -cleanup: +cleanup: if (kBytes) { - PORT_ZFree(kBytes, len); + PORT_ZFree(kBytes, len); } #if EC_DEBUG printf("ECDSA signing %s\n", - (rv == SECSuccess) ? "succeeded" : "failed"); + (rv == SECSuccess) ? "succeeded" : "failed"); #endif #else PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); @@ -885,14 +952,14 @@ cleanup: ** of this function is undefined. In cases where a public key might ** not be valid, use EC_ValidatePublicKey to check. */ -SECStatus -ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature, - const SECItem *digest) +SECStatus +ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature, + const SECItem *digest) { SECStatus rv = SECFailure; #ifndef NSS_DISABLE_ECC - mp_int r_, s_; /* tuple (r', s') is received signature) */ - mp_int c, u1, u2, v; /* intermediate values used in verification */ + mp_int r_, s_; /* tuple (r', s') is received signature) */ + mp_int c, u1, u2, v; /* intermediate values used in verification */ mp_int x1; mp_int n; mp_err err = MP_OKAY; @@ -916,45 +983,45 @@ ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature, MP_DIGITS(&u1) = 0; MP_DIGITS(&u2) = 0; MP_DIGITS(&x1) = 0; - MP_DIGITS(&v) = 0; - MP_DIGITS(&n) = 0; + MP_DIGITS(&v) = 0; + MP_DIGITS(&n) = 0; /* Check args */ if (!key || !signature || !digest) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - goto cleanup; + PORT_SetError(SEC_ERROR_INVALID_ARGS); + goto cleanup; } ecParams = &(key->ecParams); - flen = (ecParams->fieldID.size + 7) >> 3; - olen = ecParams->order.len; - if (signature->len == 0 || signature->len%2 != 0 || - signature->len > 2*olen) { - PORT_SetError(SEC_ERROR_INPUT_LEN); - goto cleanup; + flen = (ecParams->fieldID.size + 7) >> 3; + olen = ecParams->order.len; + if (signature->len == 0 || signature->len % 2 != 0 || + signature->len > 2 * olen) { + PORT_SetError(SEC_ERROR_INPUT_LEN); + goto cleanup; } - slen = signature->len/2; + slen = signature->len / 2; - SECITEM_AllocItem(NULL, &pointC, 2*flen + 1); + SECITEM_AllocItem(NULL, &pointC, ecParams->pointSize); if (pointC.data == NULL) - goto cleanup; + goto cleanup; - CHECK_MPI_OK( mp_init(&r_) ); - CHECK_MPI_OK( mp_init(&s_) ); - CHECK_MPI_OK( mp_init(&c) ); - CHECK_MPI_OK( mp_init(&u1) ); - CHECK_MPI_OK( mp_init(&u2) ); - CHECK_MPI_OK( mp_init(&x1) ); - CHECK_MPI_OK( mp_init(&v) ); - CHECK_MPI_OK( mp_init(&n) ); + CHECK_MPI_OK(mp_init(&r_)); + CHECK_MPI_OK(mp_init(&s_)); + CHECK_MPI_OK(mp_init(&c)); + CHECK_MPI_OK(mp_init(&u1)); + CHECK_MPI_OK(mp_init(&u2)); + CHECK_MPI_OK(mp_init(&x1)); + CHECK_MPI_OK(mp_init(&v)); + CHECK_MPI_OK(mp_init(&n)); /* ** Convert received signature (r', s') into MPI integers. */ - CHECK_MPI_OK( mp_read_unsigned_octets(&r_, signature->data, slen) ); - CHECK_MPI_OK( mp_read_unsigned_octets(&s_, signature->data + slen, slen) ); - - /* + CHECK_MPI_OK(mp_read_unsigned_octets(&r_, signature->data, slen)); + CHECK_MPI_OK(mp_read_unsigned_octets(&s_, signature->data + slen, slen)); + + /* ** ANSI X9.62, Section 5.4.2, Steps 1 and 2 ** ** Verify that 0 < r' < n and 0 < s' < n @@ -962,8 +1029,8 @@ ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature, SECITEM_TO_MPINT(ecParams->order, &n); if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 || mp_cmp(&r_, &n) >= 0 || mp_cmp(&s_, &n) >= 0) { - PORT_SetError(SEC_ERROR_BAD_SIGNATURE); - goto cleanup; /* will return rv == SECFailure */ + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + goto cleanup; /* will return rv == SECFailure */ } /* @@ -971,21 +1038,21 @@ ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature, ** ** c = (s')**-1 mod n */ - CHECK_MPI_OK( mp_invmod(&s_, &n, &c) ); /* c = (s')**-1 mod n */ + CHECK_MPI_OK(mp_invmod(&s_, &n, &c)); /* c = (s')**-1 mod n */ /* ** ANSI X9.62, Section 5.4.2, Step 4 ** ** u1 = ((HASH(M')) * c) mod n */ - SECITEM_TO_MPINT(*digest, &u1); /* u1 = HASH(M) */ + SECITEM_TO_MPINT(*digest, &u1); /* u1 = HASH(M) */ /* In the definition of EC signing, digests are truncated - * to the length of n in bits. + * to the length of n in bits. * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/ - CHECK_MPI_OK( (obits = mpl_significant_bits(&n)) ); - if (digest->len*8 > obits) { /* u1 = HASH(M') */ - mpl_rsh(&u1,&u1,digest->len*8 - obits); + CHECK_MPI_OK((obits = mpl_significant_bits(&n))); + if (digest->len * 8 > obits) { /* u1 = HASH(M') */ + mpl_rsh(&u1, &u1, digest->len * 8 - obits); } #if EC_DEBUG @@ -999,14 +1066,14 @@ ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature, printf("digest: %s (dec)\n", mpstr); #endif - CHECK_MPI_OK( mp_mulmod(&u1, &c, &n, &u1) ); /* u1 = u1 * c mod n */ + CHECK_MPI_OK(mp_mulmod(&u1, &c, &n, &u1)); /* u1 = u1 * c mod n */ /* ** ANSI X9.62, Section 5.4.2, Step 4 ** ** u2 = ((r') * c) mod n */ - CHECK_MPI_OK( mp_mulmod(&r_, &c, &n, &u2) ); + CHECK_MPI_OK(mp_mulmod(&r_, &c, &n, &u2)); /* ** ANSI X9.62, Section 5.4.3, Step 1 @@ -1015,25 +1082,24 @@ ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature, ** Here, A = u1.G B = u2.Q and C = A + B ** If the result, C, is the point at infinity, reject the signature */ - if (ec_points_mul(ecParams, &u1, &u2, &key->publicValue, &pointC) - != SECSuccess) { - rv = SECFailure; - goto cleanup; + if (ec_points_mul(ecParams, &u1, &u2, &key->publicValue, &pointC) != SECSuccess) { + rv = SECFailure; + goto cleanup; } if (ec_point_at_infinity(&pointC)) { - PORT_SetError(SEC_ERROR_BAD_SIGNATURE); - rv = SECFailure; - goto cleanup; + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + rv = SECFailure; + goto cleanup; } - CHECK_MPI_OK( mp_read_unsigned_octets(&x1, pointC.data + 1, flen) ); + CHECK_MPI_OK(mp_read_unsigned_octets(&x1, pointC.data + 1, flen)); /* ** ANSI X9.62, Section 5.4.4, Step 2 ** ** v = x1 mod n */ - CHECK_MPI_OK( mp_mod(&x1, &n, &v) ); + CHECK_MPI_OK(mp_mod(&x1, &n, &v)); #if EC_DEBUG mp_todecimal(&r_, mpstr); @@ -1048,10 +1114,10 @@ ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature, ** Verification: v == r' */ if (mp_cmp(&v, &r_)) { - PORT_SetError(SEC_ERROR_BAD_SIGNATURE); - rv = SECFailure; /* Signature failed to verify. */ + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + rv = SECFailure; /* Signature failed to verify. */ } else { - rv = SECSuccess; /* Signature verified. */ + rv = SECSuccess; /* Signature verified. */ } #if EC_DEBUG @@ -1075,15 +1141,16 @@ cleanup: mp_clear(&v); mp_clear(&n); - if (pointC.data) SECITEM_FreeItem(&pointC, PR_FALSE); + if (pointC.data) + SECITEM_ZfreeItem(&pointC, PR_FALSE); if (err) { - MP_TO_SEC_ERROR(err); - rv = SECFailure; + MP_TO_SEC_ERROR(err); + rv = SECFailure; } #if EC_DEBUG printf("ECDSA verification %s\n", - (rv == SECSuccess) ? "succeeded" : "failed"); + (rv == SECSuccess) ? "succeeded" : "failed"); #endif #else PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); @@ -1091,4 +1158,3 @@ cleanup: return rv; } - -- cgit v1.2.1