mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-09-28 05:55:58 +00:00
276 lines
7.4 KiB
C
276 lines
7.4 KiB
C
/* 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 "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 <stdio.h>
|
|
|
|
typedef struct {
|
|
ECCurveName curve;
|
|
int iterations;
|
|
char *privhex;
|
|
char *our_pubhex;
|
|
char *their_pubhex;
|
|
char *common_key;
|
|
char *name;
|
|
ECFieldType fieldType;
|
|
} ECDH_KAT;
|
|
|
|
typedef struct {
|
|
ECCurveName curve;
|
|
char *point;
|
|
char *name;
|
|
ECFieldType fieldType;
|
|
} ECDH_BAD;
|
|
|
|
#include "testvecs.h"
|
|
|
|
void
|
|
printBuf(const SECItem *item)
|
|
{
|
|
int i;
|
|
if (!item || !item->len) {
|
|
printf("(null)\n");
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < item->len; i++) {
|
|
printf("%02x", item->data[i]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
/* Initialise test with basic curve populate with only the necessary things */
|
|
SECStatus
|
|
init_params(ECParams *ecParams, ECCurveName curve, PLArenaPool **arena,
|
|
ECFieldType type)
|
|
{
|
|
if ((curve < ECCurve_noName) || (curve > ECCurve_pastLastCurve)) {
|
|
return SECFailure;
|
|
}
|
|
*arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
|
if (!*arena) {
|
|
return SECFailure;
|
|
}
|
|
ecParams->name = curve;
|
|
ecParams->type = ec_params_named;
|
|
ecParams->curveOID.data = NULL;
|
|
ecParams->curveOID.len = 0;
|
|
ecParams->curve.seed.data = NULL;
|
|
ecParams->curve.seed.len = 0;
|
|
ecParams->DEREncoding.data = NULL;
|
|
ecParams->DEREncoding.len = 0;
|
|
ecParams->arena = *arena;
|
|
ecParams->fieldID.size = ecCurve_map[curve]->size;
|
|
ecParams->fieldID.type = type;
|
|
ecParams->cofactor = ecCurve_map[curve]->cofactor;
|
|
|
|
return SECSuccess;
|
|
}
|
|
|
|
SECStatus
|
|
ectest_ecdh_kat(ECDH_KAT *kat)
|
|
{
|
|
ECCurveName curve = kat->curve;
|
|
ECParams ecParams = { 0 };
|
|
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 };
|
|
int i;
|
|
|
|
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
|
if (!arena) {
|
|
return SECFailure;
|
|
}
|
|
|
|
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);
|
|
}
|
|
SECU_HexString2SECItem(arena, &seed, kat->privhex);
|
|
rv = EC_NewKeyFromSeed(&ecParams, &ecPriv, seed.data, seed.len);
|
|
if (rv != SECSuccess) {
|
|
rv = SECFailure;
|
|
goto cleanup;
|
|
}
|
|
if (kat->our_pubhex) {
|
|
if (SECITEM_CompareItem(&answer, &ecPriv->publicValue) != SECEqual) {
|
|
rv = SECFailure;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
SECU_HexString2SECItem(arena, &theirKey, kat->their_pubhex);
|
|
SECU_HexString2SECItem(arena, &answer2, kat->common_key);
|
|
|
|
rv = EC_ValidatePublicKey(&ecParams, &theirKey);
|
|
if (rv != SECSuccess) {
|
|
printf("EC_ValidatePublicKey failed\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
for (i = 0; i < kat->iterations; ++i) {
|
|
rv = ECDH_Derive(&theirKey, &ecParams, &ecPriv->privateValue, PR_TRUE, &derived);
|
|
if (rv != SECSuccess) {
|
|
rv = SECFailure;
|
|
goto cleanup;
|
|
}
|
|
rv = SECITEM_CopyItem(ecParams.arena, &theirKey, &ecPriv->privateValue);
|
|
if (rv != SECSuccess) {
|
|
goto cleanup;
|
|
}
|
|
rv = SECITEM_CopyItem(ecParams.arena, &ecPriv->privateValue, &derived);
|
|
if (rv != SECSuccess) {
|
|
goto cleanup;
|
|
}
|
|
SECITEM_FreeItem(&derived, PR_FALSE);
|
|
}
|
|
|
|
if (SECITEM_CompareItem(&answer2, &ecPriv->privateValue) != SECEqual) {
|
|
printf("expected: ");
|
|
printBuf(&answer2);
|
|
printf("derived: ");
|
|
printBuf(&ecPriv->privateValue);
|
|
rv = SECFailure;
|
|
goto cleanup;
|
|
}
|
|
|
|
cleanup:
|
|
SECITEM_FreeItem(&ecEncodedParams, PR_FALSE);
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
if (ecPriv) {
|
|
PORT_FreeArena(ecPriv->ecParams.arena, PR_FALSE);
|
|
}
|
|
if (derived.data) {
|
|
SECITEM_FreeItem(&derived, PR_FALSE);
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
SECStatus
|
|
ectest_validate_point(ECDH_BAD *bad)
|
|
{
|
|
ECParams ecParams = { 0 };
|
|
SECItem point = { siBuffer, NULL, 0 };
|
|
SECStatus rv = SECFailure;
|
|
PLArenaPool *arena = NULL;
|
|
|
|
rv = init_params(&ecParams, bad->curve, &arena, bad->fieldType);
|
|
if (rv != SECSuccess) {
|
|
return rv;
|
|
}
|
|
|
|
SECU_HexString2SECItem(arena, &point, bad->point);
|
|
rv = EC_ValidatePublicKey(&ecParams, &point);
|
|
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
return rv;
|
|
}
|
|
|
|
void
|
|
printUsage(char *prog)
|
|
{
|
|
printf("Usage: %s [-fp] [-nd]\n"
|
|
"\t-n: NIST curves\n"
|
|
"\t-d: non-NIST curves\n"
|
|
"You have to specify at at least one of n or d.\n"
|
|
"By default no tests are executed.\n",
|
|
prog);
|
|
}
|
|
|
|
/* Performs tests of elliptic curve cryptography over prime fields If
|
|
* tests fail, then it prints an error message, aborts, and returns an
|
|
* error code. Otherwise, returns 0. */
|
|
int
|
|
main(int argv, char **argc)
|
|
{
|
|
SECStatus rv = SECSuccess;
|
|
int numkats = 0;
|
|
int i = 0;
|
|
int nist = 0;
|
|
int nonnist = 0;
|
|
|
|
for (i = 1; i < argv; i++) {
|
|
if (PL_strcasecmp(argc[i], "-n") == 0) {
|
|
nist = 1;
|
|
} else if (PL_strcasecmp(argc[i], "-d") == 0) {
|
|
nonnist = 1;
|
|
} else {
|
|
printUsage(argc[0]);
|
|
return 1;
|
|
}
|
|
}
|
|
if (!nist && !nonnist) {
|
|
printUsage(argc[0]);
|
|
return 1;
|
|
}
|
|
|
|
rv = SECOID_Init();
|
|
if (rv != SECSuccess) {
|
|
SECU_PrintError("Error:", "SECOID_Init");
|
|
goto cleanup;
|
|
}
|
|
|
|
/* Test P256, P384, P521 */
|
|
if (nist) {
|
|
while (ecdh_testvecs[numkats].curve != ECCurve_pastLastCurve) {
|
|
numkats++;
|
|
}
|
|
printf("1..%d\n", numkats);
|
|
for (i = 0; ecdh_testvecs[i].curve != ECCurve_pastLastCurve; i++) {
|
|
if (ectest_ecdh_kat(&ecdh_testvecs[i]) != SECSuccess) {
|
|
printf("not okay %d - %s\n", i + 1, ecdh_testvecs[i].name);
|
|
rv = SECFailure;
|
|
} else {
|
|
printf("okay %d - %s\n", i + 1, ecdh_testvecs[i].name);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Test KAT for non-NIST curves */
|
|
if (nonnist) {
|
|
for (i = 0; nonnist_testvecs[i].curve != ECCurve_pastLastCurve; i++) {
|
|
if (ectest_ecdh_kat(&nonnist_testvecs[i]) != SECSuccess) {
|
|
printf("not okay %d - %s\n", i + 1, nonnist_testvecs[i].name);
|
|
rv = SECFailure;
|
|
} else {
|
|
printf("okay %d - %s\n", i + 1, nonnist_testvecs[i].name);
|
|
}
|
|
}
|
|
for (i = 0; nonnist_testvecs_bad_values[i].curve != ECCurve_pastLastCurve; i++) {
|
|
if (ectest_validate_point(&nonnist_testvecs_bad_values[i]) == SECSuccess) {
|
|
printf("not okay %d - %s\n", i + 1, nonnist_testvecs_bad_values[i].name);
|
|
rv = SECFailure;
|
|
} else {
|
|
printf("okay %d - %s\n", i + 1, nonnist_testvecs_bad_values[i].name);
|
|
}
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
rv |= SECOID_Shutdown();
|
|
|
|
if (rv != SECSuccess) {
|
|
printf("Error: exiting with error value\n");
|
|
}
|
|
return rv;
|
|
}
|