security/nss/cmd/ecperf/ecperf.c

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "blapi.h"
     6 #include "ec.h"
     7 #include "ecl-curve.h"
     8 #include "nss.h"
     9 #include "secutil.h"
    10 #include "pkcs11.h"
    11 #include <nspr.h>
    12 #include <stdio.h>
    13 #include <strings.h>
    14 #include <assert.h>
    16 #include <time.h>
    17 #include <sys/time.h>
    18 #include <sys/resource.h>
    20 #define __PASTE(x,y)    x##y
    22 /*
    23  * Get the NSS specific PKCS #11 function names.
    24  */
    25 #undef CK_PKCS11_FUNCTION_INFO
    26 #undef CK_NEED_ARG_LIST
    28 #define CK_EXTERN extern
    29 #define CK_PKCS11_FUNCTION_INFO(func) \
    30 		CK_RV __PASTE(NS,func)
    31 #define CK_NEED_ARG_LIST	1
    33 #include "pkcs11f.h"
    37 /* mapping between ECCurveName enum and pointers to ECCurveParams */
    38 static SECOidTag ecCurve_oid_map[] = {
    39     SEC_OID_UNKNOWN,	/* ECCurve_noName */
    40     SEC_OID_ANSIX962_EC_PRIME192V1,    /* ECCurve_NIST_P192 */
    41     SEC_OID_SECG_EC_SECP224R1,    /* ECCurve_NIST_P224 */
    42     SEC_OID_ANSIX962_EC_PRIME256V1,    /* ECCurve_NIST_P256 */
    43     SEC_OID_SECG_EC_SECP384R1,    /* ECCurve_NIST_P384 */
    44     SEC_OID_SECG_EC_SECP521R1,    /* ECCurve_NIST_P521 */
    45     SEC_OID_SECG_EC_SECT163K1,    /* ECCurve_NIST_K163 */
    46     SEC_OID_SECG_EC_SECT163R1,    /* ECCurve_NIST_B163 */
    47     SEC_OID_SECG_EC_SECT233K1,    /* ECCurve_NIST_K233 */
    48     SEC_OID_SECG_EC_SECT233R1,    /* ECCurve_NIST_B233 */
    49     SEC_OID_SECG_EC_SECT283K1,    /* ECCurve_NIST_K283 */
    50     SEC_OID_SECG_EC_SECT283R1,    /* ECCurve_NIST_B283 */
    51     SEC_OID_SECG_EC_SECT409K1,    /* ECCurve_NIST_K409 */
    52     SEC_OID_SECG_EC_SECT409R1,    /* ECCurve_NIST_B409 */
    53     SEC_OID_SECG_EC_SECT571K1,    /* ECCurve_NIST_K571 */
    54     SEC_OID_SECG_EC_SECT571R1,    /* ECCurve_NIST_B571 */
    55     SEC_OID_ANSIX962_EC_PRIME192V2,    
    56     SEC_OID_ANSIX962_EC_PRIME192V3,
    57     SEC_OID_ANSIX962_EC_PRIME239V1,
    58     SEC_OID_ANSIX962_EC_PRIME239V2,
    59     SEC_OID_ANSIX962_EC_PRIME239V3,
    60 	SEC_OID_ANSIX962_EC_C2PNB163V1,
    61 	SEC_OID_ANSIX962_EC_C2PNB163V2,
    62 	SEC_OID_ANSIX962_EC_C2PNB163V3,
    63     SEC_OID_ANSIX962_EC_C2PNB176V1,
    64     SEC_OID_ANSIX962_EC_C2TNB191V1,
    65     SEC_OID_ANSIX962_EC_C2TNB191V2,
    66     SEC_OID_ANSIX962_EC_C2TNB191V3,
    67     SEC_OID_ANSIX962_EC_C2PNB208W1,
    68     SEC_OID_ANSIX962_EC_C2TNB239V1,
    69     SEC_OID_ANSIX962_EC_C2TNB239V2,
    70     SEC_OID_ANSIX962_EC_C2TNB239V3,
    71     SEC_OID_ANSIX962_EC_C2PNB272W1,
    72     SEC_OID_ANSIX962_EC_C2PNB304W1,
    73     SEC_OID_ANSIX962_EC_C2TNB359V1,
    74     SEC_OID_ANSIX962_EC_C2PNB368W1,
    75     SEC_OID_ANSIX962_EC_C2TNB431R1,
    76     SEC_OID_SECG_EC_SECP112R1,
    77     SEC_OID_SECG_EC_SECP112R2,
    78     SEC_OID_SECG_EC_SECP128R1,
    79     SEC_OID_SECG_EC_SECP128R2,
    80     SEC_OID_SECG_EC_SECP160K1,
    81     SEC_OID_SECG_EC_SECP160R1,
    82     SEC_OID_SECG_EC_SECP160R2,
    83     SEC_OID_SECG_EC_SECP192K1,
    84     SEC_OID_SECG_EC_SECP224K1,
    85     SEC_OID_SECG_EC_SECP256K1,
    86     SEC_OID_SECG_EC_SECT113R1,
    87     SEC_OID_SECG_EC_SECT113R2,
    88     SEC_OID_SECG_EC_SECT131R1,
    89     SEC_OID_SECG_EC_SECT131R2,
    90     SEC_OID_SECG_EC_SECT163R1,
    91     SEC_OID_SECG_EC_SECT193R1,
    92     SEC_OID_SECG_EC_SECT193R2,
    93     SEC_OID_SECG_EC_SECT239K1,
    94     SEC_OID_UNKNOWN	    /* ECCurve_pastLastCurve */
    95 };
    97 typedef SECStatus (*op_func) (void *, void *, void *);
    98 typedef SECStatus (*pk11_op_func) (CK_SESSION_HANDLE, void *, void *, void *);
   100 typedef struct ThreadDataStr {
   101     op_func op;
   102     void *p1;
   103     void *p2;
   104     void *p3;
   105     int iters;
   106     PRLock *lock;
   107     int count;
   108     SECStatus status;
   109     int isSign;
   110 } ThreadData;
   112 void PKCS11Thread(void *data)
   113 {
   114     ThreadData *threadData = (ThreadData *)data;
   115     pk11_op_func op = (pk11_op_func) threadData->op;
   116     int iters = threadData->iters;
   117     unsigned char sigData [256];
   118     SECItem sig;
   119     CK_SESSION_HANDLE session;
   120     CK_RV crv;
   122     threadData->status = SECSuccess;
   123     threadData->count = 0;
   125     /* get our thread's session */
   126     PR_Lock(threadData->lock);
   127     crv = NSC_OpenSession(1, CKF_SERIAL_SESSION, NULL, 0, &session);
   128     PR_Unlock(threadData->lock);
   130     if (threadData->isSign) {
   131     sig.data = sigData;
   132     sig.len = sizeof(sigData);
   133     threadData->p2 = (void *)&sig;
   134     }
   136     while (iters --) {
   137     threadData->status = (*op)(session, threadData->p1, 
   138 	       threadData->p2, threadData->p3);
   139     if (threadData->status != SECSuccess) {
   140 	break;
   141     }
   142     threadData->count++;
   143     }
   144     return;
   145 }
   147 void genericThread(void *data)
   148 {
   149     ThreadData *threadData = (ThreadData *)data;
   150     int iters = threadData->iters;
   151     unsigned char sigData [256];
   152     SECItem sig;
   154     threadData->status = SECSuccess;
   155     threadData->count = 0;
   157     if (threadData->isSign) {
   158     sig.data = sigData;
   159     sig.len = sizeof(sigData);
   160     threadData->p2 = (void *)&sig;
   161     }
   163     while (iters --) {
   164     threadData->status = (*threadData->op)(threadData->p1, 
   165 	       threadData->p2, threadData->p3);
   166     if (threadData->status != SECSuccess) {
   167 	break;
   168     }
   169     threadData->count++;
   170     }
   171     return;
   172 }
   175 /* Time iter repetitions of operation op. */
   176 SECStatus
   177 M_TimeOperation(void (*threadFunc)(void *), 
   178 	op_func opfunc, char *op, void *param1, void *param2, 
   179 	void *param3, int iters, int numThreads, PRLock *lock, 
   180 	CK_SESSION_HANDLE session, int isSign, double *rate)
   181 {
   182     double dUserTime;
   183     int i, total;
   184     PRIntervalTime startTime, totalTime;
   185     PRThread **threadIDs;
   186     ThreadData *threadData;
   187     pk11_op_func pk11_op = (pk11_op_func) opfunc;
   188     SECStatus rv;
   190     /* verify operation works before testing performance */
   191     if (session) {
   192 	rv = (*pk11_op)(session, param1, param2, param3);
   193     } else {
   194 	rv = (*opfunc)(param1, param2, param3);
   195     }
   196     if (rv != SECSuccess) {
   197 	SECU_PrintError("Error:", op); 
   198 	return rv;
   199     }
   201     /* get Data structures */
   202     threadIDs = (PRThread **)PORT_Alloc(numThreads*sizeof(PRThread *)); 
   203     threadData = (ThreadData *)PORT_Alloc(numThreads*sizeof(ThreadData));
   205     startTime = PR_Now();
   206     if (numThreads == 1) {
   207     for (i=0; i < iters; i++) {
   208 	if (session) {
   209 	    rv = (*pk11_op)(session, param1, param2, param3);
   210 	} else {
   211 	    rv = (*opfunc)(param1, param2, param3);
   212 	}
   213     }
   214 	total = iters;
   215     } else {
   216 	for (i = 0; i < numThreads; i++) {
   217 	    threadData[i].op = opfunc; 
   218 	    threadData[i].p1 = (void *)param1;
   219 	    threadData[i].p2 = (void *)param2;
   220 	    threadData[i].p3 = (void *)param3;
   221 	    threadData[i].iters = iters;
   222 	    threadData[i].lock = lock;
   223 	    threadData[i].isSign = isSign;
   224 	    threadIDs[i] = PR_CreateThread(PR_USER_THREAD, threadFunc,
   225 	                   (void *)&threadData[i], PR_PRIORITY_NORMAL,
   226 	                   PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
   227 	} 
   229 	total = 0;
   230 	for (i = 0; i < numThreads; i++) {
   231 	    PR_JoinThread(threadIDs[i]);
   232 	    /* check the status */
   233 	    total += threadData[i].count;
   234 	}
   236 	PORT_Free(threadIDs);
   237 	PORT_Free(threadData);
   238     }
   240     totalTime = PR_Now()- startTime; 
   241     /* SecondsToInterval seems to be broken here ... */
   242     dUserTime = (double)totalTime/(double)1000000;
   243     if (dUserTime) {
   244 	printf("    %-15s count:%4d sec: %3.2f op/sec: %6.2f\n", 
   245 	    op, total, dUserTime, (double)total/dUserTime); 
   246 	if (rate) {
   247 	   *rate = ((double)total)/dUserTime;
   248 	}
   249     }
   250     return SECSuccess;
   251 }
   253 #define GFP_POPULATE(params,name_v) \
   254     params.name = name_v; \
   255     if ((params.name < ECCurve_noName) || \
   256 	    (params.name > ECCurve_pastLastCurve)) goto cleanup; \
   257     params.type = ec_params_named; \
   258     params.curveOID.data = NULL; \
   259     params.curveOID.len = 0; \
   260     params.curve.seed.data = NULL; \
   261     params.curve.seed.len = 0; \
   262     params.DEREncoding.data = NULL; \
   263     params.DEREncoding.len = 0; \
   264     params.arena = NULL; \
   265     params.fieldID.size = ecCurve_map[name_v]->size; \
   266     params.fieldID.type = ec_field_GFp; \
   267     hexString2SECItem(params.arena, &params.fieldID.u.prime, \
   268 	    ecCurve_map[name_v]->irr); \
   269     hexString2SECItem(params.arena, &params.curve.a, \
   270 	    ecCurve_map[name_v]->curvea); \
   271     hexString2SECItem(params.arena, &params.curve.b, \
   272 	    ecCurve_map[name_v]->curveb); \
   273     genenc[0] = '0'; \
   274     genenc[1] = '4'; \
   275     genenc[2] = '\0'; \
   276     strcat(genenc, ecCurve_map[name_v]->genx); \
   277     strcat(genenc, ecCurve_map[name_v]->geny); \
   278     hexString2SECItem(params.arena, &params.base, \
   279 	    genenc); \
   280     hexString2SECItem(params.arena, &params.order, \
   281 	    ecCurve_map[name_v]->order); \
   282     params.cofactor = ecCurve_map[name_v]->cofactor;
   285 /* Test curve using specific field arithmetic. */
   286 #define ECTEST_NAMED_GFP(name_c, name_v) \
   287     if (usefreebl) { \
   288 	printf("Testing %s using freebl implementation...\n", name_c); \
   289 	rv = ectest_curve_freebl(name_v, iterations, numThreads); \
   290 	    if (rv != SECSuccess) goto cleanup; \
   291 	printf("... okay.\n"); \
   292 	} \
   293     if (usepkcs11) { \
   294 	printf("Testing %s using pkcs11 implementation...\n", name_c); \
   295 	rv = ectest_curve_pkcs11(name_v, iterations, numThreads); \
   296 	    if (rv != SECSuccess) goto cleanup; \
   297 	printf("... okay.\n"); \
   298      }
   300 /*
   301  * Initializes a SECItem from a hexadecimal string
   302  *
   303  * Warning: This function ignores leading 00's, so any leading 00's
   304  * in the hexadecimal string must be optional.
   305  */
   306 static SECItem *
   307 hexString2SECItem(PLArenaPool *arena, SECItem *item, const char *str)
   308 {
   309     int i = 0;
   310     int byteval = 0;
   311     int tmp = PORT_Strlen(str);
   313     if ((tmp % 2) != 0) return NULL;
   315     /* skip leading 00's unless the hex string is "00" */
   316     while ((tmp > 2) && (str[0] == '0') && (str[1] == '0')) {
   317 	str += 2;
   318 	tmp -= 2;
   319     }
   321     item->data = (unsigned char *) PORT_Alloc( tmp/2);
   322     if (item->data == NULL) return NULL;
   323     item->len = tmp/2;
   325     while (str[i]) {
   326 	if ((str[i] >= '0') && (str[i] <= '9'))
   327 	    tmp = str[i] - '0';
   328 	else if ((str[i] >= 'a') && (str[i] <= 'f'))
   329 	    tmp = str[i] - 'a' + 10;
   330 	else if ((str[i] >= 'A') && (str[i] <= 'F'))
   331 	    tmp = str[i] - 'A' + 10;
   332 	else
   333 	    return NULL;
   335 	byteval = byteval * 16 + tmp;
   336 	if ((i % 2) != 0) {
   337 	    item->data[i/2] = byteval;
   338 	    byteval = 0;
   339 	}
   340 	i++;
   341     }
   343     return item;
   344 }
   346 #define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \
   347 		(x)->pValue=(v); (x)->ulValueLen = (l);
   350 SECStatus
   351 PKCS11_Derive(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *hKey, 
   352 	  CK_MECHANISM *pMech , int *dummy)
   353 {
   354     CK_RV crv;
   355     CK_OBJECT_HANDLE newKey;
   356     CK_BBOOL cktrue = CK_TRUE;
   357     CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
   358     CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
   359     CK_ATTRIBUTE keyTemplate[3];
   360     CK_ATTRIBUTE *attrs = keyTemplate;
   362     PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass));
   363     attrs++;
   364     PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType));
   365     attrs++;
   366     PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, 1); attrs++;
   369    crv = NSC_DeriveKey(session, pMech, *hKey, keyTemplate, 3, &newKey);
   370    if (crv != CKR_OK) {
   371 	printf("Derive Failed CK_RV=0x%x\n", (int)crv);
   372 	return SECFailure;
   373    }
   374    return SECSuccess;
   375 }
   377 SECStatus
   378 PKCS11_Sign(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *hKey, 
   379 	SECItem *sig, SECItem *digest)
   380 {
   381    CK_RV crv;
   382    CK_MECHANISM mech;
   384    mech.mechanism = CKM_ECDSA;
   385    mech.pParameter = NULL;
   386    mech.ulParameterLen = 0;
   388    crv = NSC_SignInit(session, &mech, *hKey);
   389    if (crv != CKR_OK) {
   390     printf("Sign Failed CK_RV=0x%x\n", (int)crv);
   391     return SECFailure;
   392    }
   393    crv = NSC_Sign(session, digest->data, digest->len, sig->data, 
   394 	(CK_ULONG_PTR)&sig->len);
   395    if (crv != CKR_OK) {
   396     printf("Sign Failed CK_RV=0x%x\n", (int)crv);
   397     return SECFailure;
   398    }
   399    return SECSuccess;
   400 }
   402 SECStatus
   403 PKCS11_Verify(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *hKey, 
   404 	SECItem *sig, SECItem *digest)
   405 {
   406    CK_RV crv;
   407    CK_MECHANISM mech;
   409    mech.mechanism = CKM_ECDSA;
   410    mech.pParameter = NULL;
   411    mech.ulParameterLen = 0;
   413    crv = NSC_VerifyInit(session, &mech, *hKey);
   414    if (crv != CKR_OK) {
   415     printf("Verify Failed CK_RV=0x%x\n", (int)crv);
   416     return SECFailure;
   417    }
   418    crv = NSC_Verify(session, digest->data, digest->len, sig->data, sig->len);
   419    if (crv != CKR_OK) {
   420     printf("Verify Failed CK_RV=0x%x\n", (int)crv);
   421     return SECFailure;
   422    }
   423    return SECSuccess;
   424 }
   426 static SECStatus
   427 ecName2params(ECCurveName curve, SECKEYECParams * params)
   428 {
   429     SECOidData *oidData = NULL;
   431     if ((curve < ECCurve_noName) || (curve > ECCurve_pastLastCurve) ||
   432 	((oidData = SECOID_FindOIDByTag(ecCurve_oid_map[curve])) == NULL)) {
   433 	PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
   434 	return SECFailure;
   435     }
   437     SECITEM_AllocItem(NULL, params, (2 + oidData->oid.len));
   438     /*
   439      * params->data needs to contain the ASN encoding of an object ID (OID)
   440      * representing the named curve. The actual OID is in
   441      * oidData->oid.data so we simply prepend 0x06 and OID length
   442      */
   443     params->data[0] = SEC_ASN1_OBJECT_ID;
   444     params->data[1] = oidData->oid.len;
   445     memcpy(params->data + 2, oidData->oid.data, oidData->oid.len);
   447     return SECSuccess;
   448 }
   452 /* Performs basic tests of elliptic curve cryptography over prime fields.
   453  * If tests fail, then it prints an error message, aborts, and returns an
   454  * error code. Otherwise, returns 0. */
   455 SECStatus
   456 ectest_curve_pkcs11(ECCurveName curve, int iterations, int numThreads)
   457 {
   458     CK_OBJECT_HANDLE ecPriv;
   459     CK_OBJECT_HANDLE ecPub;
   460     CK_SESSION_HANDLE session;
   461     SECItem sig;
   462     SECItem digest;
   463     SECKEYECParams ecParams;
   464     CK_MECHANISM mech;
   465     CK_ECDH1_DERIVE_PARAMS ecdh_params;
   466     unsigned char sigData [256];
   467     unsigned char digestData[20];
   468     unsigned char pubKeyData[256];
   469     PRLock *lock = NULL;
   470     double signRate, deriveRate;
   471     CK_ATTRIBUTE template;
   472     SECStatus rv;
   473     CK_RV crv;
   475     ecParams.data = NULL;
   476     ecParams.len = 0;
   477     rv = ecName2params(curve, &ecParams);
   478     if (rv != SECSuccess) {
   479     goto cleanup;
   480     }
   482     crv = NSC_OpenSession(1, CKF_SERIAL_SESSION, NULL, 0, &session);
   483     if (crv != CKR_OK) {
   484     printf("OpenSession Failed CK_RV=0x%x\n", (int)crv);
   485     return SECFailure;
   486     }
   488     PORT_Memset(digestData, 0xa5, sizeof(digestData));
   489     digest.data = digestData;
   490     digest.len = sizeof(digestData);
   491     sig.data = sigData;
   492     sig.len = sizeof(sigData);
   494     template.type = CKA_EC_PARAMS;
   495     template.pValue = ecParams.data;
   496     template.ulValueLen = ecParams.len;
   497     mech.mechanism = CKM_EC_KEY_PAIR_GEN;
   498     mech.pParameter = NULL;
   499     mech.ulParameterLen = 0;
   500     crv = NSC_GenerateKeyPair(session, &mech, 
   501 		  &template, 1, NULL, 0, &ecPub, &ecPriv);
   502     if (crv != CKR_OK) {
   503     printf("GenerateKeyPair Failed CK_RV=0x%x\n", (int)crv);
   504     return SECFailure;
   505     }
   507     template.type = CKA_EC_POINT;
   508     template.pValue = pubKeyData;
   509     template.ulValueLen = sizeof(pubKeyData);
   510     crv = NSC_GetAttributeValue(session, ecPub, &template, 1);
   511     if (crv != CKR_OK) {
   512     printf("GenerateKeyPair Failed CK_RV=0x%x\n", (int)crv);
   513     return SECFailure;
   514     }
   516     ecdh_params.kdf = CKD_NULL;
   517     ecdh_params.ulSharedDataLen = 0;
   518     ecdh_params.pSharedData = NULL;
   519     ecdh_params.ulPublicDataLen = template.ulValueLen;
   520     ecdh_params.pPublicData = template.pValue;
   522     mech.mechanism = CKM_ECDH1_DERIVE;
   523     mech.pParameter = (void *)&ecdh_params;
   524     mech.ulParameterLen = sizeof(ecdh_params);
   526     lock = PR_NewLock();
   528     rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Derive, "ECDH_Derive",
   529 	    &ecPriv, &mech,  NULL, iterations, numThreads, 
   530 	    lock, session, 0, &deriveRate);
   531     if (rv != SECSuccess) goto cleanup;
   532     rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Sign, "ECDSA_Sign",
   533 	    (void *)&ecPriv, &sig, &digest, iterations, numThreads,
   534 	    lock, session, 1, &signRate);
   535     if (rv != SECSuccess) goto cleanup;
   536     printf("        ECDHE max rate = %.2f\n", (deriveRate+signRate)/4.0);
   537     /* get a signature */
   538     rv = PKCS11_Sign(session, &ecPriv, &sig, &digest);
   539     if (rv != SECSuccess) goto cleanup;
   540     rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Verify, "ECDSA_Verify",
   541 	    (void *)&ecPub, &sig, &digest, iterations, numThreads,
   542 	    lock, session, 0, NULL);
   543     if (rv != SECSuccess) goto cleanup;
   545 cleanup:
   546     if (lock) {
   547     PR_DestroyLock(lock);
   548     }
   549     return rv;
   550 }
   552 SECStatus
   553 ECDH_DeriveWrap(ECPrivateKey *priv, ECPublicKey *pub, int *dummy)
   554 {
   555     SECItem secret;
   556     unsigned char secretData[256];
   557     SECStatus rv;
   559     secret.data = secretData;
   560     secret.len = sizeof(secretData);
   562     rv = ECDH_Derive(&pub->publicValue, &pub->ecParams, 
   563 	&priv->privateValue, 0, &secret);
   564 #ifdef notdef
   565     if (rv == SECSuccess) {
   566     PORT_Free(secret.data);
   567     }
   568 #endif
   569     return rv;
   570 }
   572 /* Performs basic tests of elliptic curve cryptography over prime fields.
   573  * If tests fail, then it prints an error message, aborts, and returns an
   574  * error code. Otherwise, returns 0. */
   575 SECStatus
   576 ectest_curve_freebl(ECCurveName curve, int iterations, int numThreads)
   577 {
   578     ECParams      ecParams;
   579     ECPrivateKey *ecPriv = NULL;
   580     ECPublicKey ecPub;
   581     SECItem sig;
   582     SECItem digest;
   583     unsigned char sigData [256];
   584     unsigned char digestData[20];
   585     double signRate, deriveRate;
   586     char genenc[3 + 2 * 2 * MAX_ECKEY_LEN];
   587     SECStatus rv;
   590     GFP_POPULATE(ecParams, curve);
   592     PORT_Memset(digestData, 0xa5, sizeof(digestData));
   593     digest.data = digestData;
   594     digest.len = sizeof(digestData);
   595     sig.data = sigData;
   596     sig.len = sizeof(sigData);
   598     rv = EC_NewKey(&ecParams, &ecPriv);
   599     if (rv != SECSuccess) {
   600     return SECFailure;
   601     }
   602     ecPub.ecParams = ecParams;
   603     ecPub.publicValue = ecPriv->publicValue;
   605     M_TimeOperation(genericThread, (op_func) ECDH_DeriveWrap, "ECDH_Derive",
   606 	    ecPriv, &ecPub, NULL, iterations, numThreads, 0, 0, 0, &deriveRate);
   607     if (rv != SECSuccess) goto cleanup;
   608     M_TimeOperation(genericThread, (op_func) ECDSA_SignDigest, "ECDSA_Sign",
   609 	    ecPriv, &sig, &digest, iterations, numThreads, 0, 0, 1, &signRate);
   610     if (rv != SECSuccess) goto cleanup;
   611     printf("        ECDHE max rate = %.2f\n", (deriveRate+signRate)/4.0);
   612     rv = ECDSA_SignDigest(ecPriv, &sig, &digest);
   613     if (rv != SECSuccess) goto cleanup;
   614     M_TimeOperation(genericThread, (op_func) ECDSA_VerifyDigest, "ECDSA_Verify",
   615 	    &ecPub, &sig, &digest, iterations, numThreads, 0, 0, 0, NULL);
   616     if (rv != SECSuccess) goto cleanup;
   618 cleanup:
   619     return rv;
   620 }
   622 /* Prints help information. */
   623 void
   624 printUsage(char *prog)
   625 {
   626     printf("Usage: %s [-i iterations] [-t threads ] [-ans] [-fp] [-A]\n",prog);
   627 }
   629 /* Performs tests of elliptic curve cryptography over prime fields If
   630  * tests fail, then it prints an error message, aborts, and returns an
   631  * error code. Otherwise, returns 0. */
   632 int
   633 main(int argv, char **argc)
   634 {
   635     int ansi = 0;
   636     int nist = 0;
   637     int secp = 0;
   638     int usefreebl = 0;
   639     int usepkcs11 = 0;
   640     int i;
   641     SECStatus rv = SECSuccess;
   642     int iterations = 100;
   643     int numThreads = 1;
   645     /* read command-line arguments */
   646     for (i = 1; i < argv; i++) {
   647 	if (strcasecmp(argc[i], "-i") == 0) {
   648 	    i++;
   649 	    iterations = atoi(argc[i]);
   650 	} else if (strcasecmp(argc[i], "-t") == 0) {
   651 	    i++;
   652 	    numThreads = atoi(argc[i]);
   653 	} else if (strcasecmp(argc[i], "-A") == 0) {
   654 	    ansi = nist = secp = 1;
   655 	    usepkcs11 = usefreebl = 1;
   656 	} else if (strcasecmp(argc[i], "-a") == 0) {
   657 	    ansi = 1;
   658 	} else if (strcasecmp(argc[i], "-n") == 0) {
   659 	    nist = 1;
   660 	} else if (strcasecmp(argc[i], "-s") == 0) {
   661 	    secp = 1;
   662 	} else if (strcasecmp(argc[i], "-p") == 0) {
   663 	    usepkcs11 = 1;
   664 	} else if (strcasecmp(argc[i], "-f") == 0) {
   665 	    usefreebl = 1;
   666 	} else {
   667 	    printUsage(argc[0]);
   668 	    return 0;
   669 	}
   670     }
   672     if ((ansi | nist | secp) == 0) {
   673 	nist = 1;
   674     }
   675     if ((usepkcs11|usefreebl) == 0) {
   676 	usefreebl = 1;
   677     }
   679     rv = NSS_NoDB_Init(NULL);
   680     if (rv != SECSuccess) {
   681 	SECU_PrintError("Error:", "NSS_NoDB_Init"); 
   682 	goto cleanup;
   683     }
   685     /* specific arithmetic tests */
   686     if (nist) {
   687         ECTEST_NAMED_GFP("SECP-160K1", ECCurve_SECG_PRIME_160K1);
   688         ECTEST_NAMED_GFP("NIST-P192", ECCurve_NIST_P192);
   689         ECTEST_NAMED_GFP("NIST-P224", ECCurve_NIST_P224);
   690         ECTEST_NAMED_GFP("NIST-P256", ECCurve_NIST_P256);
   691         ECTEST_NAMED_GFP("NIST-P384", ECCurve_NIST_P384);
   692         ECTEST_NAMED_GFP("NIST-P521", ECCurve_NIST_P521);
   693     }
   694     if (ansi) {
   695         ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v1", ECCurve_X9_62_PRIME_192V1);
   696         ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v2", ECCurve_X9_62_PRIME_192V2);
   697         ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v3", ECCurve_X9_62_PRIME_192V3);
   698         ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v1", ECCurve_X9_62_PRIME_239V1);
   699         ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v2", ECCurve_X9_62_PRIME_239V2);
   700         ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v3", ECCurve_X9_62_PRIME_239V3);
   701         ECTEST_NAMED_GFP("ANSI X9.62 PRIME256v1", ECCurve_X9_62_PRIME_256V1);
   702     }
   703     if (secp) {
   704         ECTEST_NAMED_GFP("SECP-112R1", ECCurve_SECG_PRIME_112R1);
   705         ECTEST_NAMED_GFP("SECP-112R2", ECCurve_SECG_PRIME_112R2);
   706         ECTEST_NAMED_GFP("SECP-128R1", ECCurve_SECG_PRIME_128R1);
   707         ECTEST_NAMED_GFP("SECP-128R2", ECCurve_SECG_PRIME_128R2);
   708         ECTEST_NAMED_GFP("SECP-160K1", ECCurve_SECG_PRIME_160K1);
   709         ECTEST_NAMED_GFP("SECP-160R1", ECCurve_SECG_PRIME_160R1);
   710         ECTEST_NAMED_GFP("SECP-160R2", ECCurve_SECG_PRIME_160R2);
   711         ECTEST_NAMED_GFP("SECP-192K1", ECCurve_SECG_PRIME_192K1);
   712         ECTEST_NAMED_GFP("SECP-192R1", ECCurve_SECG_PRIME_192R1);
   713         ECTEST_NAMED_GFP("SECP-224K1", ECCurve_SECG_PRIME_224K1);
   714         ECTEST_NAMED_GFP("SECP-224R1", ECCurve_SECG_PRIME_224R1);
   715         ECTEST_NAMED_GFP("SECP-256K1", ECCurve_SECG_PRIME_256K1);
   716         ECTEST_NAMED_GFP("SECP-256R1", ECCurve_SECG_PRIME_256R1);
   717         ECTEST_NAMED_GFP("SECP-384R1", ECCurve_SECG_PRIME_384R1);
   718         ECTEST_NAMED_GFP("SECP-521R1", ECCurve_SECG_PRIME_521R1);
   719     }
   721   cleanup:
   722     if (rv != SECSuccess) {
   723 	printf("Error: exiting with error value\n");
   724     }
   725     return rv;
   726 }

mercurial