Wed, 31 Dec 2014 07:16:47 +0100
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 <stdio.h>
6 #include <stdlib.h>
7 #include "plgetopt.h"
8 #include "nss.h"
9 #include "secutil.h"
10 #include "pk11table.h"
11 #include "secmodt.h"
12 #include "pk11pub.h"
15 struct test_args {
16 char *arg;
17 int mask_value;
18 char *description;
19 };
21 static const struct test_args test_array[] = {
22 {"all", 0x1f, "run all the tests" },
23 {"e_n_p", 0x01, "public exponent, modulus, prime1"},
24 {"d_n_q", 0x02, "private exponent, modulus, prime2"},
25 {"d_p_q", 0x04, "private exponent, prime1, prime2"},
26 {"e_d_q", 0x08, "public exponent, private exponent, prime2"},
27 {"e_d_n", 0x10, "public exponent, private exponent, moduls"}
28 };
29 static const int test_array_size =
30 (sizeof(test_array)/sizeof(struct test_args));
32 static void Usage(char *progName)
33 {
34 int i;
35 #define PRINTUSAGE(subject, option, predicate) \
36 fprintf(stderr, "%10s %s\t%s\n", subject, option, predicate);
37 fprintf(stderr, "%s [-k keysize] [-e exp] [-r rounds] [-t tests]\n "
38 "Test creating RSA private keys from Partial components\n",
39 progName);
40 PRINTUSAGE("", "-k", "key size (in bit)");
41 PRINTUSAGE("", "-e", "rsa public exponent");
42 PRINTUSAGE("", "-r", "number times to repeat the test");
43 PRINTUSAGE("", "-t", "run the specified tests");
44 for (i=0; i < test_array_size; i++) {
45 PRINTUSAGE("", test_array[i].arg, test_array[i].description);
46 }
47 fprintf(stderr,"\n");
48 }
50 /*
51 * Test the RSA populate command to see that it can really build
52 * keys from it's components.
53 */
55 const static CK_ATTRIBUTE rsaTemplate[] = {
56 {CKA_CLASS, NULL, 0 },
57 {CKA_KEY_TYPE, NULL, 0 },
58 {CKA_TOKEN, NULL, 0 },
59 {CKA_SENSITIVE, NULL, 0 },
60 {CKA_PRIVATE, NULL, 0 },
61 {CKA_MODULUS, NULL, 0 },
62 {CKA_PUBLIC_EXPONENT, NULL, 0 },
63 {CKA_PRIVATE_EXPONENT, NULL, 0 },
64 {CKA_PRIME_1, NULL, 0 },
65 {CKA_PRIME_2, NULL, 0 },
66 {CKA_EXPONENT_1, NULL, 0 },
67 {CKA_EXPONENT_2, NULL, 0 },
68 {CKA_COEFFICIENT, NULL, 0 },
69 };
71 #define RSA_SIZE (sizeof(rsaTemplate))
72 #define RSA_ATTRIBUTES (sizeof(rsaTemplate)/sizeof(CK_ATTRIBUTE))
74 static void
75 resetTemplate(CK_ATTRIBUTE *attribute, int start, int end)
76 {
77 int i;
78 for (i=start; i < end; i++) {
79 if (attribute[i].pValue) {
80 PORT_Free(attribute[i].pValue);
81 }
82 attribute[i].pValue = NULL;
83 attribute[i].ulValueLen = 0;
84 }
85 }
87 static SECStatus
88 copyAttribute(PK11ObjectType objType, void *object, CK_ATTRIBUTE *template,
89 int offset, CK_ATTRIBUTE_TYPE attrType)
90 {
91 SECItem attributeItem = {0, 0, 0};
92 SECStatus rv;
94 rv = PK11_ReadRawAttribute(objType, object, attrType, &attributeItem);
95 if (rv != SECSuccess) {
96 return rv;
97 }
98 template[offset].type = attrType;
99 template[offset].pValue = attributeItem.data;
100 template[offset].ulValueLen = attributeItem.len;
101 return SECSuccess;
102 }
104 static SECStatus
105 readKey(PK11ObjectType objType, void *object, CK_ATTRIBUTE *template,
106 int start, int end)
107 {
108 int i;
109 SECStatus rv;
111 for (i=start; i < end; i++) {
112 rv = copyAttribute(objType, object, template, i, template[i].type);
113 if (rv != SECSuccess) {
114 goto fail;
115 }
116 }
117 return SECSuccess;
119 fail:
120 resetTemplate(template, start, i);
121 return rv;
122 }
124 #define ATTR_STRING(x) getNameFromAttribute(x)
126 void
127 dumpTemplate(CK_ATTRIBUTE *template, int start, int end)
128 {
129 int i,j;
130 for (i=0; i < end; i++) {
131 unsigned char cval;
132 CK_ULONG ulval;
133 unsigned char *cpval;
135 fprintf(stderr, "%s:", ATTR_STRING(template[i].type));
136 switch (template[i].ulValueLen) {
137 case 1:
138 cval =*(unsigned char *)template[i].pValue;
139 switch(cval) {
140 case 0: fprintf(stderr, " false"); break;
141 case 1: fprintf(stderr, " true"); break;
142 default:
143 fprintf(stderr, " %d (=0x%02x,'%c')",cval,cval,cval);
144 break;
145 }
146 break;
147 case sizeof(CK_ULONG):
148 ulval = *(CK_ULONG *)template[i].pValue;
149 fprintf(stderr," %ld (=0x%04lx)", ulval, ulval);
150 break;
151 default:
152 cpval = (unsigned char *)template[i].pValue;
153 for (j=0; j < template[i].ulValueLen; j++) {
154 if ((j % 16) == 0) fprintf(stderr, "\n ");
155 fprintf(stderr," %02x",cpval[j]);
156 }
157 break;
158 }
159 fprintf(stderr,"\n");
160 }
161 }
163 PRBool
164 rsaKeysAreEqual(PK11ObjectType srcType, void *src,
165 PK11ObjectType destType, void *dest)
166 {
168 CK_ATTRIBUTE srcTemplate[RSA_ATTRIBUTES];
169 CK_ATTRIBUTE destTemplate[RSA_ATTRIBUTES];
170 PRBool areEqual = PR_TRUE;
171 SECStatus rv;
172 int i;
174 memcpy(srcTemplate, rsaTemplate, RSA_SIZE);
175 memcpy(destTemplate, rsaTemplate, RSA_SIZE);
177 rv = readKey(srcType, src, srcTemplate, 0, RSA_ATTRIBUTES);
178 if (rv != SECSuccess) {
179 printf("Could read source key\n");
180 return PR_FALSE;
181 }
182 readKey(destType, dest, destTemplate, 0, RSA_ATTRIBUTES);
183 if (rv != SECSuccess) {
184 printf("Could read dest key\n");
185 return PR_FALSE;
186 }
188 for (i=0; i < RSA_ATTRIBUTES; i++) {
189 if (srcTemplate[i].ulValueLen != destTemplate[i].ulValueLen) {
190 printf("key->%s not equal src_len = %ld, dest_len=%ld\n",
191 ATTR_STRING(srcTemplate[i].type),
192 srcTemplate[i].ulValueLen, destTemplate[i].ulValueLen);
193 areEqual = 0;
194 } else if (memcmp(srcTemplate[i].pValue, destTemplate[i].pValue,
195 destTemplate[i].ulValueLen) != 0) {
196 printf("key->%s not equal.\n", ATTR_STRING(srcTemplate[i].type));
197 areEqual = 0;
198 }
199 }
200 if (!areEqual) {
201 fprintf(stderr, "original key:\n");
202 dumpTemplate(srcTemplate,0, RSA_ATTRIBUTES);
203 fprintf(stderr, "created key:\n");
204 dumpTemplate(destTemplate,0, RSA_ATTRIBUTES);
205 }
206 return areEqual;
207 }
209 static int exp_exp_prime_fail_count = 0;
211 static int
212 doRSAPopulateTest(unsigned int keySize, unsigned long exponent,
213 int mask, void *pwarg)
214 {
215 SECKEYPrivateKey *rsaPrivKey;
216 SECKEYPublicKey *rsaPubKey;
217 PK11GenericObject *tstPrivKey;
218 CK_ATTRIBUTE tstTemplate[RSA_ATTRIBUTES];
219 int tstHeaderCount;
220 PK11SlotInfo *slot = NULL;
221 PK11RSAGenParams rsaParams;
222 CK_OBJECT_CLASS obj_class = CKO_PRIVATE_KEY;
223 CK_KEY_TYPE key_type = CKK_RSA;
224 CK_BBOOL ck_false = CK_FALSE;
225 int failed = 0;
227 rsaParams.pe = exponent;
228 rsaParams.keySizeInBits = keySize;
230 slot = PK11_GetInternalSlot();
231 if (slot == NULL) {
232 fprintf(stderr, "Couldn't get the internal slot for the test \n");
233 return -1;
234 }
236 rsaPrivKey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN,
237 &rsaParams, &rsaPubKey, PR_FALSE,
238 PR_FALSE, pwarg);
239 if (rsaPrivKey == NULL) {
240 fprintf(stderr, "RSA Key Gen failed");
241 PK11_FreeSlot(slot);
242 return -1;
243 }
245 memcpy(tstTemplate, rsaTemplate, RSA_SIZE);
247 tstTemplate[0].pValue = &obj_class;
248 tstTemplate[0].ulValueLen = sizeof(obj_class);
249 tstTemplate[1].pValue = &key_type;
250 tstTemplate[1].ulValueLen = sizeof(key_type);
251 tstTemplate[2].pValue = &ck_false;
252 tstTemplate[2].ulValueLen = sizeof(ck_false);
253 tstTemplate[3].pValue = &ck_false;
254 tstTemplate[3].ulValueLen = sizeof(ck_false);
255 tstTemplate[4].pValue = &ck_false;
256 tstTemplate[4].ulValueLen = sizeof(ck_false);
257 tstHeaderCount = 5;
259 if (mask & 1) {
260 printf("%s\n",test_array[1].description);
261 resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
262 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
263 tstHeaderCount, CKA_PUBLIC_EXPONENT);
264 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
265 tstHeaderCount+1, CKA_MODULUS);
266 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
267 tstHeaderCount+2, CKA_PRIME_1);
269 tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate,
270 tstHeaderCount+3, PR_FALSE);
271 if (tstPrivKey == NULL) {
272 fprintf(stderr, "RSA Populate failed: pubExp mod p\n");
273 failed = 1;
274 } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey,
275 PK11_TypeGeneric, tstPrivKey)) {
276 fprintf(stderr, "RSA Populate key mismatch: pubExp mod p\n");
277 failed = 1;
278 }
279 if (tstPrivKey) PK11_DestroyGenericObject(tstPrivKey);
280 }
281 if (mask & 2) {
282 printf("%s\n",test_array[2].description);
283 /* test the basic2 case, public exponent, modulus, prime2 */
284 resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
285 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
286 tstHeaderCount, CKA_PUBLIC_EXPONENT);
287 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
288 tstHeaderCount+1, CKA_MODULUS);
289 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
290 tstHeaderCount+2, CKA_PRIME_2);
291 /* test with q in the prime1 position */
292 tstTemplate[tstHeaderCount+2].type = CKA_PRIME_1;
294 tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate,
295 tstHeaderCount+3, PR_FALSE);
296 if (tstPrivKey == NULL) {
297 fprintf(stderr, "RSA Populate failed: pubExp mod q\n");
298 failed = 1;
299 } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey,
300 PK11_TypeGeneric, tstPrivKey)) {
301 fprintf(stderr, "RSA Populate key mismatch: pubExp mod q\n");
302 failed = 1;
303 }
304 if (tstPrivKey) PK11_DestroyGenericObject(tstPrivKey);
305 }
306 if (mask & 4) {
307 printf("%s\n",test_array[3].description);
308 /* test the medium case, private exponent, prime1, prime2 */
309 resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
311 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
312 tstHeaderCount, CKA_PRIVATE_EXPONENT);
313 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
314 tstHeaderCount+1, CKA_PRIME_1);
315 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
316 tstHeaderCount+2, CKA_PRIME_2);
317 /* test with p & q swapped. Underlying code should swap these back */
318 tstTemplate[tstHeaderCount+2].type = CKA_PRIME_1;
319 tstTemplate[tstHeaderCount+1].type = CKA_PRIME_2;
321 tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate,
322 tstHeaderCount+3, PR_FALSE);
323 if (tstPrivKey == NULL) {
324 fprintf(stderr, "RSA Populate failed: privExp p q\n");
325 failed = 1;
326 } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey,
327 PK11_TypeGeneric, tstPrivKey)) {
328 fprintf(stderr, "RSA Populate key mismatch: privExp p q\n");
329 failed = 1;
330 }
331 if (tstPrivKey) PK11_DestroyGenericObject(tstPrivKey);
332 }
333 if (mask & 8) {
334 printf("%s\n",test_array[4].description);
335 /* test the advanced case, public exponent, private exponent, prime2 */
336 resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
337 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
338 tstHeaderCount, CKA_PRIVATE_EXPONENT);
339 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
340 tstHeaderCount+1, CKA_PUBLIC_EXPONENT);
341 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
342 tstHeaderCount+2, CKA_PRIME_2);
344 tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate,
345 tstHeaderCount+3, PR_FALSE);
346 if (tstPrivKey == NULL) {
347 fprintf(stderr, "RSA Populate failed: pubExp privExp q\n");
348 fprintf(stderr, " this is expected periodically. It means we\n");
349 fprintf(stderr, " had more than one key that meets the "
350 "specification\n");
351 exp_exp_prime_fail_count++;
352 } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey,
353 PK11_TypeGeneric, tstPrivKey)) {
354 fprintf(stderr, "RSA Populate key mismatch: pubExp privExp q\n");
355 failed = 1;
356 }
357 if (tstPrivKey) PK11_DestroyGenericObject(tstPrivKey);
358 }
359 if (mask & 16) {
360 printf("%s\n",test_array[5].description);
361 /* test the advanced case2, public exponent, private exponent, modulus
362 */
363 resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
365 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
366 tstHeaderCount, CKA_PRIVATE_EXPONENT);
367 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
368 tstHeaderCount+1, CKA_PUBLIC_EXPONENT);
369 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
370 tstHeaderCount+2, CKA_MODULUS);
372 tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate,
373 tstHeaderCount+3, PR_FALSE);
374 if (tstPrivKey == NULL) {
375 fprintf(stderr, "RSA Populate failed: pubExp privExp mod\n");
376 failed = 1;
377 } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey,
378 PK11_TypeGeneric, tstPrivKey)) {
379 fprintf(stderr, "RSA Populate key mismatch: pubExp privExp mod\n");
380 failed = 1;
381 }
382 if (tstPrivKey) PK11_DestroyGenericObject(tstPrivKey);
383 }
386 PK11_FreeSlot(slot);
387 return failed ? -1 : 0;
388 }
390 /* populate options */
391 enum {
392 opt_Exponent = 0,
393 opt_KeySize,
394 opt_Repeat,
395 opt_Tests
396 };
398 static secuCommandFlag populate_options[] =
399 {
400 { /* opt_Exponent */ 'e', PR_TRUE, 0, PR_FALSE },
401 { /* opt_KeySize */ 'k', PR_TRUE, 0, PR_FALSE },
402 { /* opt_Repeat */ 'r', PR_TRUE, 0, PR_FALSE },
403 { /* opt_Tests */ 't', PR_TRUE, 0, PR_FALSE },
404 };
406 int
407 is_delimiter(char c)
408 {
409 if ((c=='+') || (c==',') || (c=='|')) {
410 return 1;
411 }
412 return 0;
413 }
415 int
416 parse_tests(char *test_string)
417 {
418 int mask = 0;
419 int i;
421 while (*test_string) {
422 if (is_delimiter(*test_string)) {
423 test_string++;
424 }
425 for (i=0; i < test_array_size; i++) {
426 char *arg = test_array[i].arg;
427 int len = strlen(arg);
428 if (strncmp(test_string,arg,len) == 0) {
429 test_string += len;
430 mask |= test_array[i].mask_value;
431 break;
432 }
433 }
434 if (i == test_array_size) {
435 break;
436 }
437 }
438 return mask;
439 }
441 int main(int argc, char **argv)
442 {
443 unsigned int keySize = 1024;
444 unsigned long exponent = 65537;
445 int i, repeat = 1, ret = 0;
446 SECStatus rv = SECFailure;
447 secuCommand populateArgs;
448 char *progName;
449 int mask = 0xff;
451 populateArgs.numCommands = 0;
452 populateArgs.numOptions = sizeof(populate_options) /
453 sizeof(secuCommandFlag);
454 populateArgs.commands = NULL;
455 populateArgs.options = populate_options;
457 progName = strrchr(argv[0], '/');
458 if (!progName)
459 progName = strrchr(argv[0], '\\');
460 progName = progName ? progName+1 : argv[0];
462 rv = NSS_NoDB_Init(NULL);
463 if (rv != SECSuccess) {
464 SECU_PrintPRandOSError(progName);
465 return -1;
466 }
468 rv = SECU_ParseCommandLine(argc, argv, progName, &populateArgs);
469 if (rv == SECFailure) {
470 fprintf(stderr, "%s: command line parsing error!\n", progName);
471 Usage(progName);
472 return -1;
473 }
474 rv = SECFailure;
477 if (populateArgs.options[opt_KeySize].activated) {
478 keySize = PORT_Atoi(populateArgs.options[opt_KeySize].arg);
479 }
480 if (populateArgs.options[opt_Repeat].activated) {
481 repeat = PORT_Atoi(populateArgs.options[opt_Repeat].arg);
482 }
483 if (populateArgs.options[opt_Exponent].activated) {
484 exponent = PORT_Atoi(populateArgs.options[opt_Exponent].arg);
485 }
486 if (populateArgs.options[opt_Tests].activated) {
487 char * test_string = populateArgs.options[opt_Tests].arg;
488 mask = PORT_Atoi(test_string);
489 if (mask == 0) {
490 mask = parse_tests(test_string);
491 }
492 if (mask == 0) {
493 Usage(progName);
494 return -1;
495 }
496 }
498 exp_exp_prime_fail_count = 0;
499 for (i=0; i < repeat; i++) {
500 printf("Running RSA Populate test run %d\n",i);
501 ret = doRSAPopulateTest(keySize, exponent, mask, NULL);
502 if (ret != 0) {
503 i++;
504 break;
505 }
506 }
507 if (ret != 0) {
508 fprintf(stderr,"RSA Populate test round %d: FAILED\n",i);
509 }
510 if (repeat > 1) {
511 printf(" pub priv prime test: %d failures out of %d runs (%f %%)\n",
512 exp_exp_prime_fail_count, i,
513 (((double)exp_exp_prime_fail_count) * 100.0)/(double) i);
514 }
515 return ret;
516 }