File: | s/cmd/ecperf/ecperf.c |
Warning: | line 144, column 14 Function taking 4 arguments is called with fewer (3) |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 "prprf.h" | |||
9 | #include "basicutil.h" | |||
10 | #include "pkcs11.h" | |||
11 | #include "nspr.h" | |||
12 | #include <stdio.h> | |||
13 | ||||
14 | #define __PASTE(x, y)xy x##y | |||
15 | ||||
16 | /* | |||
17 | * Get the NSS specific PKCS #11 function names. | |||
18 | */ | |||
19 | #undef CK_PKCS11_FUNCTION_INFO | |||
20 | #undef CK_NEED_ARG_LIST1 | |||
21 | ||||
22 | #define CK_EXTERNextern extern | |||
23 | #define CK_PKCS11_FUNCTION_INFO(func)CK_RV NSfunc \ | |||
24 | CK_RV __PASTE(NS, func)NSfunc | |||
25 | #define CK_NEED_ARG_LIST1 1 | |||
26 | ||||
27 | #include "pkcs11f.h" | |||
28 | ||||
29 | typedef SECStatus (*op_func)(void *, void *, void *); | |||
30 | typedef SECStatus (*pk11_op_func)(CK_SESSION_HANDLE, void *, void *, void *); | |||
31 | ||||
32 | typedef struct ThreadDataStr { | |||
33 | op_func op; | |||
34 | void *p1; | |||
35 | void *p2; | |||
36 | void *p3; | |||
37 | int iters; | |||
38 | PRLock *lock; | |||
39 | int count; | |||
40 | SECStatus status; | |||
41 | int isSign; | |||
42 | } ThreadData; | |||
43 | ||||
44 | typedef SECItem SECKEYECParams; | |||
45 | ||||
46 | void | |||
47 | PKCS11Thread(void *data) | |||
48 | { | |||
49 | ThreadData *threadData = (ThreadData *)data; | |||
50 | pk11_op_func op = (pk11_op_func)threadData->op; | |||
51 | int iters = threadData->iters; | |||
52 | unsigned char sigData[256]; | |||
53 | SECItem sig; | |||
54 | CK_SESSION_HANDLE session; | |||
55 | CK_RV crv; | |||
56 | void *tmp = NULL((void*)0); | |||
57 | ||||
58 | threadData->status = SECSuccess; | |||
59 | threadData->count = 0; | |||
60 | ||||
61 | /* get our thread's session */ | |||
62 | PR_Lock(threadData->lock); | |||
63 | crv = NSC_OpenSession(1, CKF_SERIAL_SESSION0x00000004UL, NULL((void*)0), 0, &session); | |||
64 | PR_Unlock(threadData->lock); | |||
65 | if (crv != CKR_OK0x00000000UL) { | |||
66 | return; | |||
67 | } | |||
68 | ||||
69 | if (threadData->isSign) { | |||
70 | sig.data = sigData; | |||
71 | sig.len = sizeof(sigData); | |||
72 | tmp = threadData->p2; | |||
73 | threadData->p2 = (void *)&sig; | |||
74 | } | |||
75 | ||||
76 | while (iters--) { | |||
77 | threadData->status = (*op)(session, threadData->p1, | |||
78 | threadData->p2, threadData->p3); | |||
79 | if (threadData->status != SECSuccess) { | |||
80 | break; | |||
81 | } | |||
82 | threadData->count++; | |||
83 | } | |||
84 | ||||
85 | if (threadData->isSign) { | |||
86 | threadData->p2 = tmp; | |||
87 | } | |||
88 | return; | |||
89 | } | |||
90 | ||||
91 | void | |||
92 | genericThread(void *data) | |||
93 | { | |||
94 | ThreadData *threadData = (ThreadData *)data; | |||
95 | int iters = threadData->iters; | |||
96 | unsigned char sigData[256]; | |||
97 | SECItem sig; | |||
98 | void *tmp = NULL((void*)0); | |||
99 | ||||
100 | threadData->status = SECSuccess; | |||
101 | threadData->count = 0; | |||
102 | ||||
103 | if (threadData->isSign) { | |||
104 | sig.data = sigData; | |||
105 | sig.len = sizeof(sigData); | |||
106 | tmp = threadData->p2; | |||
107 | threadData->p2 = (void *)&sig; | |||
108 | } | |||
109 | ||||
110 | while (iters--) { | |||
111 | threadData->status = (*threadData->op)(threadData->p1, | |||
112 | threadData->p2, threadData->p3); | |||
113 | if (threadData->status != SECSuccess) { | |||
114 | break; | |||
115 | } | |||
116 | threadData->count++; | |||
117 | } | |||
118 | ||||
119 | if (threadData->isSign) { | |||
120 | threadData->p2 = tmp; | |||
121 | } | |||
122 | return; | |||
123 | } | |||
124 | ||||
125 | /* Time iter repetitions of operation op. */ | |||
126 | SECStatus | |||
127 | M_TimeOperation(void (*threadFunc)(void *), | |||
128 | op_func opfunc, char *op, void *param1, void *param2, | |||
129 | void *param3, int iters, int numThreads, PRLock *lock, | |||
130 | CK_SESSION_HANDLE session, int isSign, double *rate) | |||
131 | { | |||
132 | double dUserTime; | |||
133 | int i, total; | |||
134 | PRIntervalTime startTime, totalTime; | |||
135 | PRThread **threadIDs; | |||
136 | ThreadData *threadData; | |||
137 | pk11_op_func pk11_op = (pk11_op_func)opfunc; | |||
138 | SECStatus rv; | |||
139 | ||||
140 | /* verify operation works before testing performance */ | |||
141 | if (session) { | |||
142 | rv = (*pk11_op)(session, param1, param2, param3); | |||
143 | } else { | |||
144 | rv = (*opfunc)(param1, param2, param3); | |||
| ||||
145 | } | |||
146 | if (rv != SECSuccess) { | |||
147 | SECU_PrintError("Error:", op); | |||
148 | return rv; | |||
149 | } | |||
150 | ||||
151 | /* get Data structures */ | |||
152 | threadIDs = (PRThread **)PORT_AllocPORT_Alloc_Util(numThreads * sizeof(PRThread *)); | |||
153 | threadData = (ThreadData *)PORT_AllocPORT_Alloc_Util(numThreads * sizeof(ThreadData)); | |||
154 | ||||
155 | startTime = PR_Now(); | |||
156 | if (numThreads == 1) { | |||
157 | for (i = 0; i < iters; i++) { | |||
158 | if (session) { | |||
159 | rv = (*pk11_op)(session, param1, param2, param3); | |||
160 | } else { | |||
161 | rv = (*opfunc)(param1, param2, param3); | |||
162 | } | |||
163 | if (rv != SECSuccess) { | |||
164 | PORT_FreePORT_Free_Util(threadIDs); | |||
165 | PORT_FreePORT_Free_Util(threadData); | |||
166 | SECU_PrintError("Error:", op); | |||
167 | return rv; | |||
168 | } | |||
169 | } | |||
170 | total = iters; | |||
171 | } else { | |||
172 | for (i = 0; i < numThreads; i++) { | |||
173 | threadData[i].op = opfunc; | |||
174 | threadData[i].p1 = (void *)param1; | |||
175 | threadData[i].p2 = (void *)param2; | |||
176 | threadData[i].p3 = (void *)param3; | |||
177 | threadData[i].iters = iters; | |||
178 | threadData[i].lock = lock; | |||
179 | threadData[i].isSign = isSign; | |||
180 | threadIDs[i] = PR_CreateThread(PR_USER_THREAD, threadFunc, | |||
181 | (void *)&threadData[i], PR_PRIORITY_NORMAL, | |||
182 | PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); | |||
183 | } | |||
184 | ||||
185 | total = 0; | |||
186 | for (i = 0; i < numThreads; i++) { | |||
187 | PR_JoinThread(threadIDs[i]); | |||
188 | /* check the status */ | |||
189 | total += threadData[i].count; | |||
190 | } | |||
191 | } | |||
192 | ||||
193 | totalTime = PR_Now() - startTime; | |||
194 | /* SecondsToInterval seems to be broken here ... */ | |||
195 | dUserTime = (double)totalTime / (double)1000000; | |||
196 | if (dUserTime) { | |||
197 | printf(" %-15s count:%4d sec: %3.2f op/sec: %6.2f\n", | |||
198 | op, total, dUserTime, (double)total / dUserTime); | |||
199 | if (rate) { | |||
200 | *rate = ((double)total) / dUserTime; | |||
201 | } | |||
202 | } | |||
203 | PORT_FreePORT_Free_Util(threadIDs); | |||
204 | PORT_FreePORT_Free_Util(threadData); | |||
205 | ||||
206 | return SECSuccess; | |||
207 | } | |||
208 | ||||
209 | /* Test curve using specific field arithmetic. */ | |||
210 | #define ECTEST_NAMED_GFP(name_c, name_v)if (usefreebl) { printf("Testing %s using freebl implementation...\n" , name_c); rv = ectest_curve_freebl(name_v, iterations, numThreads , ec_field_GFp); if (rv != SECSuccess) goto cleanup; printf("... okay.\n" ); } if (usepkcs11) { printf("Testing %s using pkcs11 implementation...\n" , name_c); rv = ectest_curve_pkcs11(name_v, iterations, numThreads ); if (rv != SECSuccess) goto cleanup; printf("... okay.\n"); } \ | |||
211 | if (usefreebl) { \ | |||
212 | printf("Testing %s using freebl implementation...\n", name_c); \ | |||
213 | rv = ectest_curve_freebl(name_v, iterations, numThreads, ec_field_GFp); \ | |||
214 | if (rv != SECSuccess) \ | |||
215 | goto cleanup; \ | |||
216 | printf("... okay.\n"); \ | |||
217 | } \ | |||
218 | if (usepkcs11) { \ | |||
219 | printf("Testing %s using pkcs11 implementation...\n", name_c); \ | |||
220 | rv = ectest_curve_pkcs11(name_v, iterations, numThreads); \ | |||
221 | if (rv != SECSuccess) \ | |||
222 | goto cleanup; \ | |||
223 | printf("... okay.\n"); \ | |||
224 | } | |||
225 | ||||
226 | /* Test curve using specific field arithmetic. */ | |||
227 | #define ECTEST_NAMED_CUSTOM(name_c, name_v)if (usefreebl) { printf("Testing %s using freebl implementation...\n" , name_c); rv = ectest_curve_freebl(name_v, iterations, numThreads , ec_field_plain); if (rv != SECSuccess) goto cleanup; printf ("... okay.\n"); } if (usepkcs11) { printf("Testing %s using pkcs11 implementation...\n" , name_c); rv = ectest_curve_pkcs11(name_v, iterations, numThreads ); if (rv != SECSuccess) goto cleanup; printf("... okay.\n"); } \ | |||
228 | if (usefreebl) { \ | |||
229 | printf("Testing %s using freebl implementation...\n", name_c); \ | |||
230 | rv = ectest_curve_freebl(name_v, iterations, numThreads, ec_field_plain); \ | |||
231 | if (rv != SECSuccess) \ | |||
232 | goto cleanup; \ | |||
233 | printf("... okay.\n"); \ | |||
234 | } \ | |||
235 | if (usepkcs11) { \ | |||
236 | printf("Testing %s using pkcs11 implementation...\n", name_c); \ | |||
237 | rv = ectest_curve_pkcs11(name_v, iterations, numThreads); \ | |||
238 | if (rv != SECSuccess) \ | |||
239 | goto cleanup; \ | |||
240 | printf("... okay.\n"); \ | |||
241 | } | |||
242 | ||||
243 | #define PK11_SETATTRS(x, id, v, l)(x)->type = (id); (x)->pValue = (v); (x)->ulValueLen = (l); \ | |||
244 | (x)->type = (id); \ | |||
245 | (x)->pValue = (v); \ | |||
246 | (x)->ulValueLen = (l); | |||
247 | ||||
248 | SECStatus | |||
249 | PKCS11_Derive(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *hKey, | |||
250 | CK_MECHANISM *pMech, int *dummy) | |||
251 | { | |||
252 | CK_RV crv; | |||
253 | CK_OBJECT_HANDLE newKey; | |||
254 | CK_BBOOL cktrue = CK_TRUE1; | |||
255 | CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY0x00000004UL; | |||
256 | CK_KEY_TYPE keyType = CKK_GENERIC_SECRET0x00000010UL; | |||
257 | CK_ATTRIBUTE keyTemplate[3]; | |||
258 | CK_ATTRIBUTE *attrs = keyTemplate; | |||
259 | ||||
260 | PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass))(attrs)->type = (0x00000000UL); (attrs)->pValue = (& keyClass); (attrs)->ulValueLen = (sizeof(keyClass));; | |||
261 | attrs++; | |||
262 | PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType))(attrs)->type = (0x00000100UL); (attrs)->pValue = (& keyType); (attrs)->ulValueLen = (sizeof(keyType));; | |||
263 | attrs++; | |||
264 | PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, 1)(attrs)->type = (0x0000010CUL); (attrs)->pValue = (& cktrue); (attrs)->ulValueLen = (1);; | |||
265 | attrs++; | |||
266 | ||||
267 | crv = NSC_DeriveKey(session, pMech, *hKey, keyTemplate, 3, &newKey); | |||
268 | if (crv != CKR_OK0x00000000UL) { | |||
269 | printf("Derive Failed CK_RV=0x%x\n", (int)crv); | |||
270 | return SECFailure; | |||
271 | } | |||
272 | return SECSuccess; | |||
273 | } | |||
274 | ||||
275 | SECStatus | |||
276 | PKCS11_Sign(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *hKey, | |||
277 | SECItem *sig, SECItem *digest) | |||
278 | { | |||
279 | CK_RV crv; | |||
280 | CK_MECHANISM mech; | |||
281 | CK_ULONG sigLen = sig->len; | |||
282 | ||||
283 | mech.mechanism = CKM_ECDSA0x00001041UL; | |||
284 | mech.pParameter = NULL((void*)0); | |||
285 | mech.ulParameterLen = 0; | |||
286 | ||||
287 | crv = NSC_SignInit(session, &mech, *hKey); | |||
288 | if (crv != CKR_OK0x00000000UL) { | |||
289 | printf("Sign Failed CK_RV=0x%x\n", (int)crv); | |||
290 | return SECFailure; | |||
291 | } | |||
292 | crv = NSC_Sign(session, digest->data, digest->len, sig->data, &sigLen); | |||
293 | if (crv != CKR_OK0x00000000UL) { | |||
294 | printf("Sign Failed CK_RV=0x%x\n", (int)crv); | |||
295 | return SECFailure; | |||
296 | } | |||
297 | sig->len = (unsigned int)sigLen; | |||
298 | return SECSuccess; | |||
299 | } | |||
300 | ||||
301 | SECStatus | |||
302 | PKCS11_Verify(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *hKey, | |||
303 | SECItem *sig, SECItem *digest) | |||
304 | { | |||
305 | CK_RV crv; | |||
306 | CK_MECHANISM mech; | |||
307 | ||||
308 | mech.mechanism = CKM_ECDSA0x00001041UL; | |||
309 | mech.pParameter = NULL((void*)0); | |||
310 | mech.ulParameterLen = 0; | |||
311 | ||||
312 | crv = NSC_VerifyInit(session, &mech, *hKey); | |||
313 | if (crv != CKR_OK0x00000000UL) { | |||
314 | printf("Verify Failed CK_RV=0x%x\n", (int)crv); | |||
315 | return SECFailure; | |||
316 | } | |||
317 | crv = NSC_Verify(session, digest->data, digest->len, sig->data, sig->len); | |||
318 | if (crv != CKR_OK0x00000000UL) { | |||
319 | printf("Verify Failed CK_RV=0x%x\n", (int)crv); | |||
320 | return SECFailure; | |||
321 | } | |||
322 | return SECSuccess; | |||
323 | } | |||
324 | ||||
325 | /* Performs basic tests of elliptic curve cryptography over prime fields. | |||
326 | * If tests fail, then it prints an error message, aborts, and returns an | |||
327 | * error code. Otherwise, returns 0. */ | |||
328 | SECStatus | |||
329 | ectest_curve_pkcs11(ECCurveName curve, int iterations, int numThreads) | |||
330 | { | |||
331 | CK_OBJECT_HANDLE ecPriv; | |||
332 | CK_OBJECT_HANDLE ecPub; | |||
333 | CK_SESSION_HANDLE session; | |||
334 | SECItem sig; | |||
335 | SECItem digest; | |||
336 | SECKEYECParams ecParams; | |||
337 | CK_MECHANISM mech; | |||
338 | CK_ECDH1_DERIVE_PARAMS ecdh_params; | |||
339 | unsigned char sigData[256]; | |||
340 | unsigned char digestData[20]; | |||
341 | unsigned char pubKeyData[256]; | |||
342 | PRLock *lock = NULL((void*)0); | |||
343 | double signRate, deriveRate = 0; | |||
344 | CK_ATTRIBUTE template; | |||
345 | SECStatus rv; | |||
346 | CK_RV crv; | |||
347 | ||||
348 | ecParams.data = NULL((void*)0); | |||
349 | ecParams.len = 0; | |||
350 | rv = SECU_ecName2params(curve, &ecParams); | |||
351 | if (rv != SECSuccess) { | |||
352 | goto cleanup; | |||
353 | } | |||
354 | ||||
355 | crv = NSC_OpenSession(1, CKF_SERIAL_SESSION0x00000004UL, NULL((void*)0), 0, &session); | |||
356 | if (crv != CKR_OK0x00000000UL) { | |||
357 | printf("OpenSession Failed CK_RV=0x%x\n", (int)crv); | |||
358 | return SECFailure; | |||
359 | } | |||
360 | ||||
361 | PORT_Memsetmemset(digestData, 0xa5, sizeof(digestData)); | |||
362 | digest.data = digestData; | |||
363 | digest.len = sizeof(digestData); | |||
364 | sig.data = sigData; | |||
365 | sig.len = sizeof(sigData); | |||
366 | ||||
367 | template.type = CKA_EC_PARAMS0x00000180UL; | |||
368 | template.pValue = ecParams.data; | |||
369 | template.ulValueLen = ecParams.len; | |||
370 | mech.mechanism = CKM_EC_KEY_PAIR_GEN0x00001040UL; | |||
371 | mech.pParameter = NULL((void*)0); | |||
372 | mech.ulParameterLen = 0; | |||
373 | crv = NSC_GenerateKeyPair(session, &mech, | |||
374 | &template, 1, NULL((void*)0), 0, &ecPub, &ecPriv); | |||
375 | if (crv != CKR_OK0x00000000UL) { | |||
376 | printf("GenerateKeyPair Failed CK_RV=0x%x\n", (int)crv); | |||
377 | return SECFailure; | |||
378 | } | |||
379 | ||||
380 | template.type = CKA_EC_POINT0x00000181UL; | |||
381 | template.pValue = pubKeyData; | |||
382 | template.ulValueLen = sizeof(pubKeyData); | |||
383 | crv = NSC_GetAttributeValue(session, ecPub, &template, 1); | |||
384 | if (crv != CKR_OK0x00000000UL) { | |||
385 | printf("GenerateKeyPair Failed CK_RV=0x%x\n", (int)crv); | |||
386 | return SECFailure; | |||
387 | } | |||
388 | ||||
389 | ecdh_params.kdf = CKD_NULL0x00000001UL; | |||
390 | ecdh_params.ulSharedDataLen = 0; | |||
391 | ecdh_params.pSharedData = NULL((void*)0); | |||
392 | ecdh_params.ulPublicDataLen = template.ulValueLen; | |||
393 | ecdh_params.pPublicData = template.pValue; | |||
394 | ||||
395 | mech.mechanism = CKM_ECDH1_DERIVE0x00001050UL; | |||
396 | mech.pParameter = (void *)&ecdh_params; | |||
397 | mech.ulParameterLen = sizeof(ecdh_params); | |||
398 | ||||
399 | lock = PR_NewLock(); | |||
400 | ||||
401 | if (ecCurve_map[curve]->usage & KU_KEY_AGREEMENT(0x08)) { | |||
402 | rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Derive, "ECDH_Derive", | |||
403 | &ecPriv, &mech, NULL((void*)0), iterations, numThreads, | |||
404 | lock, session, 0, &deriveRate); | |||
405 | if (rv != SECSuccess) { | |||
406 | goto cleanup; | |||
407 | } | |||
408 | } | |||
409 | ||||
410 | if (ecCurve_map[curve]->usage & KU_DIGITAL_SIGNATURE(0x80)) { | |||
411 | rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Sign, "ECDSA_Sign", | |||
412 | (void *)&ecPriv, &sig, &digest, iterations, numThreads, | |||
413 | lock, session, 1, &signRate); | |||
414 | if (rv != SECSuccess) { | |||
415 | goto cleanup; | |||
416 | } | |||
417 | printf(" ECDHE max rate = %.2f\n", (deriveRate + signRate) / 4.0); | |||
418 | /* get a signature */ | |||
419 | rv = PKCS11_Sign(session, &ecPriv, &sig, &digest); | |||
420 | if (rv != SECSuccess) { | |||
421 | goto cleanup; | |||
422 | } | |||
423 | rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Verify, "ECDSA_Verify", | |||
424 | (void *)&ecPub, &sig, &digest, iterations, numThreads, | |||
425 | lock, session, 0, NULL((void*)0)); | |||
426 | if (rv != SECSuccess) { | |||
427 | goto cleanup; | |||
428 | } | |||
429 | } | |||
430 | ||||
431 | cleanup: | |||
432 | if (lock) { | |||
433 | PR_DestroyLock(lock); | |||
434 | } | |||
435 | return rv; | |||
436 | } | |||
437 | ||||
438 | SECStatus | |||
439 | ECDH_DeriveWrap(ECPrivateKey *priv, ECPublicKey *pub, int *dummy) | |||
440 | { | |||
441 | SECItem secret; | |||
442 | unsigned char secretData[256]; | |||
443 | SECStatus rv; | |||
444 | ||||
445 | secret.data = secretData; | |||
446 | secret.len = sizeof(secretData); | |||
447 | ||||
448 | rv = ECDH_Derive(&pub->publicValue, &pub->ecParams, | |||
449 | &priv->privateValue, 0, &secret); | |||
450 | SECITEM_FreeItemSECITEM_FreeItem_Util(&secret, PR_FALSE0); | |||
451 | return rv; | |||
452 | } | |||
453 | ||||
454 | /* Performs basic tests of elliptic curve cryptography over prime fields. | |||
455 | * If tests fail, then it prints an error message, aborts, and returns an | |||
456 | * error code. Otherwise, returns 0. */ | |||
457 | SECStatus | |||
458 | ectest_curve_freebl(ECCurveName curve, int iterations, int numThreads, | |||
459 | ECFieldType fieldType) | |||
460 | { | |||
461 | ECParams ecParams = { 0 }; | |||
462 | ECPrivateKey *ecPriv = NULL((void*)0); | |||
463 | ECPublicKey ecPub; | |||
464 | SECItem sig; | |||
465 | SECItem digest; | |||
466 | unsigned char sigData[256]; | |||
467 | unsigned char digestData[20]; | |||
468 | double signRate, deriveRate = 0; | |||
469 | SECStatus rv = SECFailure; | |||
470 | PLArenaPool *arena; | |||
471 | SECItem ecEncodedParams = { siBuffer, NULL((void*)0), 0 }; | |||
472 | ||||
473 | arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048)); | |||
474 | if (!arena) { | |||
475 | return SECFailure; | |||
476 | } | |||
477 | ||||
478 | if ((curve < ECCurve_noName) || (curve > ECCurve_pastLastCurve)) { | |||
479 | PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0); | |||
480 | return SECFailure; | |||
481 | } | |||
482 | ||||
483 | rv = SECU_ecName2params(curve, &ecEncodedParams); | |||
484 | if (rv != SECSuccess) { | |||
485 | goto cleanup; | |||
486 | } | |||
487 | EC_FillParams(arena, &ecEncodedParams, &ecParams); | |||
488 | ||||
489 | PORT_Memsetmemset(digestData, 0xa5, sizeof(digestData)); | |||
490 | digest.data = digestData; | |||
491 | digest.len = sizeof(digestData); | |||
492 | sig.data = sigData; | |||
493 | sig.len = sizeof(sigData); | |||
494 | ||||
495 | rv = EC_NewKey(&ecParams, &ecPriv); | |||
496 | if (rv != SECSuccess) { | |||
497 | goto cleanup; | |||
498 | } | |||
499 | ecPub.ecParams = ecParams; | |||
500 | ecPub.publicValue = ecPriv->publicValue; | |||
501 | ||||
502 | if (ecCurve_map[curve]->usage & KU_KEY_AGREEMENT(0x08)) { | |||
503 | rv = M_TimeOperation(genericThread, (op_func)ECDH_DeriveWrap, "ECDH_Derive", | |||
504 | ecPriv, &ecPub, NULL((void*)0), iterations, numThreads, 0, 0, 0, &deriveRate); | |||
505 | if (rv != SECSuccess) { | |||
506 | goto cleanup; | |||
507 | } | |||
508 | } | |||
509 | ||||
510 | if (ecCurve_map[curve]->usage & KU_DIGITAL_SIGNATURE(0x80)) { | |||
511 | rv = M_TimeOperation(genericThread, (op_func)ECDSA_SignDigest, "ECDSA_Sign", | |||
512 | ecPriv, &sig, &digest, iterations, numThreads, 0, 0, 1, &signRate); | |||
513 | if (rv != SECSuccess) | |||
514 | goto cleanup; | |||
515 | printf(" ECDHE max rate = %.2f\n", (deriveRate + signRate) / 4.0); | |||
516 | rv = ECDSA_SignDigest(ecPriv, &sig, &digest); | |||
517 | if (rv != SECSuccess) { | |||
518 | goto cleanup; | |||
519 | } | |||
520 | rv = M_TimeOperation(genericThread, (op_func)ECDSA_VerifyDigest, "ECDSA_Verify", | |||
521 | &ecPub, &sig, &digest, iterations, numThreads, 0, 0, 0, NULL((void*)0)); | |||
522 | if (rv != SECSuccess) { | |||
523 | goto cleanup; | |||
524 | } | |||
525 | } | |||
526 | ||||
527 | cleanup: | |||
528 | SECITEM_FreeItemSECITEM_FreeItem_Util(&ecEncodedParams, PR_FALSE0); | |||
529 | PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0); | |||
530 | if (ecPriv) { | |||
531 | PORT_FreeArenaPORT_FreeArena_Util(ecPriv->ecParams.arena, PR_FALSE0); | |||
532 | } | |||
533 | return rv; | |||
534 | } | |||
535 | ||||
536 | /* Prints help information. */ | |||
537 | void | |||
538 | printUsage(char *prog) | |||
539 | { | |||
540 | printf("Usage: %s [-i iterations] [-t threads ] [-ans] [-fp] [-Al]\n" | |||
541 | "-a: ansi\n-n: nist\n-s: secp\n-f: usefreebl\n-p: usepkcs11\n-A: all\n", | |||
542 | prog); | |||
543 | } | |||
544 | ||||
545 | /* Performs tests of elliptic curve cryptography over prime fields If | |||
546 | * tests fail, then it prints an error message, aborts, and returns an | |||
547 | * error code. Otherwise, returns 0. */ | |||
548 | int | |||
549 | main(int argv, char **argc) | |||
550 | { | |||
551 | int ansi = 0; | |||
552 | int nist = 0; | |||
553 | int secp = 0; | |||
554 | int usefreebl = 0; | |||
555 | int usepkcs11 = 0; | |||
556 | int i; | |||
557 | SECStatus rv = SECSuccess; | |||
558 | int iterations = 100; | |||
559 | int numThreads = 1; | |||
560 | ||||
561 | const CK_C_INITIALIZE_ARGS pk11args = { | |||
562 | NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), CKF_LIBRARY_CANT_CREATE_OS_THREADS0x00000001UL, | |||
563 | (void *)"flags=readOnly,noCertDB,noModDB", NULL((void*)0) | |||
564 | }; | |||
565 | ||||
566 | /* read command-line arguments */ | |||
567 | for (i = 1; i < argv; i++) { | |||
| ||||
568 | if (PL_strcasecmp(argc[i], "-i") == 0) { | |||
569 | i++; | |||
570 | iterations = atoi(argc[i]); | |||
571 | } else if (PL_strcasecmp(argc[i], "-t") == 0) { | |||
572 | i++; | |||
573 | numThreads = atoi(argc[i]); | |||
574 | } else if (PL_strcasecmp(argc[i], "-A") == 0) { | |||
575 | ansi = nist = secp = 1; | |||
576 | usepkcs11 = usefreebl = 1; | |||
577 | } else if (PL_strcasecmp(argc[i], "-a") == 0) { | |||
578 | ansi = 1; | |||
579 | } else if (PL_strcasecmp(argc[i], "-n") == 0) { | |||
580 | nist = 1; | |||
581 | } else if (PL_strcasecmp(argc[i], "-s") == 0) { | |||
582 | secp = 1; | |||
583 | } else if (PL_strcasecmp(argc[i], "-p") == 0) { | |||
584 | usepkcs11 = 1; | |||
585 | } else if (PL_strcasecmp(argc[i], "-f") == 0) { | |||
586 | usefreebl = 1; | |||
587 | } else { | |||
588 | printUsage(argc[0]); | |||
589 | return 0; | |||
590 | } | |||
591 | } | |||
592 | ||||
593 | if ((ansi | nist | secp) == 0) { | |||
594 | nist = 1; | |||
595 | } | |||
596 | if ((usepkcs11 | usefreebl) == 0) { | |||
597 | usefreebl = 1; | |||
598 | } | |||
599 | ||||
600 | rv = RNG_RNGInit(); | |||
601 | if (rv != SECSuccess) { | |||
602 | SECU_PrintError("Error:", "RNG_RNGInit"); | |||
603 | return -1; | |||
604 | } | |||
605 | RNG_SystemInfoForRNG(); | |||
606 | ||||
607 | rv = SECOID_Init(); | |||
608 | if (rv != SECSuccess) { | |||
609 | SECU_PrintError("Error:", "SECOID_Init"); | |||
610 | goto cleanup; | |||
611 | } | |||
612 | ||||
613 | if (usepkcs11
| |||
614 | CK_RV crv = NSC_Initialize((CK_VOID_PTR)&pk11args); | |||
615 | if (crv != CKR_OK0x00000000UL) { | |||
616 | fprintf(stderrstderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv); | |||
617 | return SECFailure; | |||
618 | } | |||
619 | } | |||
620 | ||||
621 | /* specific arithmetic tests */ | |||
622 | if (nist
| |||
623 | ECTEST_NAMED_GFP("NIST-P256", ECCurve_NIST_P256)if (usefreebl) { printf("Testing %s using freebl implementation...\n" , "NIST-P256"); rv = ectest_curve_freebl(ECCurve_NIST_P256, iterations , numThreads, ec_field_GFp); if (rv != SECSuccess) goto cleanup ; printf("... okay.\n"); } if (usepkcs11) { printf("Testing %s using pkcs11 implementation...\n" , "NIST-P256"); rv = ectest_curve_pkcs11(ECCurve_NIST_P256, iterations , numThreads); if (rv != SECSuccess) goto cleanup; printf("... okay.\n" ); }; | |||
624 | ECTEST_NAMED_GFP("NIST-P384", ECCurve_NIST_P384)if (usefreebl) { printf("Testing %s using freebl implementation...\n" , "NIST-P384"); rv = ectest_curve_freebl(ECCurve_NIST_P384, iterations , numThreads, ec_field_GFp); if (rv != SECSuccess) goto cleanup ; printf("... okay.\n"); } if (usepkcs11) { printf("Testing %s using pkcs11 implementation...\n" , "NIST-P384"); rv = ectest_curve_pkcs11(ECCurve_NIST_P384, iterations , numThreads); if (rv != SECSuccess) goto cleanup; printf("... okay.\n" ); }; | |||
625 | ECTEST_NAMED_GFP("NIST-P521", ECCurve_NIST_P521)if (usefreebl) { printf("Testing %s using freebl implementation...\n" , "NIST-P521"); rv = ectest_curve_freebl(ECCurve_NIST_P521, iterations , numThreads, ec_field_GFp); if (rv != SECSuccess) goto cleanup ; printf("... okay.\n"); } if (usepkcs11) { printf("Testing %s using pkcs11 implementation...\n" , "NIST-P521"); rv = ectest_curve_pkcs11(ECCurve_NIST_P521, iterations , numThreads); if (rv != SECSuccess) goto cleanup; printf("... okay.\n" ); }; | |||
626 | ECTEST_NAMED_CUSTOM("Curve25519", ECCurve25519)if (usefreebl) { printf("Testing %s using freebl implementation...\n" , "Curve25519"); rv = ectest_curve_freebl(ECCurve25519, iterations , numThreads, ec_field_plain); if (rv != SECSuccess) goto cleanup ; printf("... okay.\n"); } if (usepkcs11) { printf("Testing %s using pkcs11 implementation...\n" , "Curve25519"); rv = ectest_curve_pkcs11(ECCurve25519, iterations , numThreads); if (rv != SECSuccess) goto cleanup; printf("... okay.\n" ); }; | |||
627 | } | |||
628 | ||||
629 | cleanup: | |||
630 | rv |= SECOID_Shutdown(); | |||
631 | RNG_RNGShutdown(); | |||
632 | ||||
633 | if (rv != SECSuccess) { | |||
634 | printf("Error: exiting with error value\n"); | |||
635 | } | |||
636 | return rv; | |||
637 | } |