security/nss/cmd/ecperf/ecperf.c

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:35389cc12a09
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/. */
4
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>
15
16 #include <time.h>
17 #include <sys/time.h>
18 #include <sys/resource.h>
19
20 #define __PASTE(x,y) x##y
21
22 /*
23 * Get the NSS specific PKCS #11 function names.
24 */
25 #undef CK_PKCS11_FUNCTION_INFO
26 #undef CK_NEED_ARG_LIST
27
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
32
33 #include "pkcs11f.h"
34
35
36
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 };
96
97 typedef SECStatus (*op_func) (void *, void *, void *);
98 typedef SECStatus (*pk11_op_func) (CK_SESSION_HANDLE, void *, void *, void *);
99
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;
111
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;
121
122 threadData->status = SECSuccess;
123 threadData->count = 0;
124
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);
129
130 if (threadData->isSign) {
131 sig.data = sigData;
132 sig.len = sizeof(sigData);
133 threadData->p2 = (void *)&sig;
134 }
135
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 }
146
147 void genericThread(void *data)
148 {
149 ThreadData *threadData = (ThreadData *)data;
150 int iters = threadData->iters;
151 unsigned char sigData [256];
152 SECItem sig;
153
154 threadData->status = SECSuccess;
155 threadData->count = 0;
156
157 if (threadData->isSign) {
158 sig.data = sigData;
159 sig.len = sizeof(sigData);
160 threadData->p2 = (void *)&sig;
161 }
162
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 }
173
174
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;
189
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 }
200
201 /* get Data structures */
202 threadIDs = (PRThread **)PORT_Alloc(numThreads*sizeof(PRThread *));
203 threadData = (ThreadData *)PORT_Alloc(numThreads*sizeof(ThreadData));
204
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 }
228
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 }
235
236 PORT_Free(threadIDs);
237 PORT_Free(threadData);
238 }
239
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 }
252
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;
283
284
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 }
299
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);
312
313 if ((tmp % 2) != 0) return NULL;
314
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 }
320
321 item->data = (unsigned char *) PORT_Alloc( tmp/2);
322 if (item->data == NULL) return NULL;
323 item->len = tmp/2;
324
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;
334
335 byteval = byteval * 16 + tmp;
336 if ((i % 2) != 0) {
337 item->data[i/2] = byteval;
338 byteval = 0;
339 }
340 i++;
341 }
342
343 return item;
344 }
345
346 #define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \
347 (x)->pValue=(v); (x)->ulValueLen = (l);
348
349
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;
361
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++;
367
368
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 }
376
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;
383
384 mech.mechanism = CKM_ECDSA;
385 mech.pParameter = NULL;
386 mech.ulParameterLen = 0;
387
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 }
401
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;
408
409 mech.mechanism = CKM_ECDSA;
410 mech.pParameter = NULL;
411 mech.ulParameterLen = 0;
412
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 }
425
426 static SECStatus
427 ecName2params(ECCurveName curve, SECKEYECParams * params)
428 {
429 SECOidData *oidData = NULL;
430
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 }
436
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);
446
447 return SECSuccess;
448 }
449
450
451
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;
474
475 ecParams.data = NULL;
476 ecParams.len = 0;
477 rv = ecName2params(curve, &ecParams);
478 if (rv != SECSuccess) {
479 goto cleanup;
480 }
481
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 }
487
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);
493
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 }
506
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 }
515
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;
521
522 mech.mechanism = CKM_ECDH1_DERIVE;
523 mech.pParameter = (void *)&ecdh_params;
524 mech.ulParameterLen = sizeof(ecdh_params);
525
526 lock = PR_NewLock();
527
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;
544
545 cleanup:
546 if (lock) {
547 PR_DestroyLock(lock);
548 }
549 return rv;
550 }
551
552 SECStatus
553 ECDH_DeriveWrap(ECPrivateKey *priv, ECPublicKey *pub, int *dummy)
554 {
555 SECItem secret;
556 unsigned char secretData[256];
557 SECStatus rv;
558
559 secret.data = secretData;
560 secret.len = sizeof(secretData);
561
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 }
571
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;
588
589
590 GFP_POPULATE(ecParams, curve);
591
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);
597
598 rv = EC_NewKey(&ecParams, &ecPriv);
599 if (rv != SECSuccess) {
600 return SECFailure;
601 }
602 ecPub.ecParams = ecParams;
603 ecPub.publicValue = ecPriv->publicValue;
604
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;
617
618 cleanup:
619 return rv;
620 }
621
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 }
628
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;
644
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 }
671
672 if ((ansi | nist | secp) == 0) {
673 nist = 1;
674 }
675 if ((usepkcs11|usefreebl) == 0) {
676 usefreebl = 1;
677 }
678
679 rv = NSS_NoDB_Init(NULL);
680 if (rv != SECSuccess) {
681 SECU_PrintError("Error:", "NSS_NoDB_Init");
682 goto cleanup;
683 }
684
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 }
720
721 cleanup:
722 if (rv != SECSuccess) {
723 printf("Error: exiting with error value\n");
724 }
725 return rv;
726 }

mercurial