PageRenderTime 53ms CodeModel.GetById 11ms app.highlight 36ms RepoModel.GetById 1ms app.codeStats 1ms

/security/nss/cmd/rsapoptst/rsapoptst.c

http://github.com/zpao/v8monkey
C | 550 lines | 449 code | 52 blank | 49 comment | 87 complexity | 33152c45f35a53577453f776a7ac9e53 MD5 | raw file
  1/* ***** BEGIN LICENSE BLOCK *****
  2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3 *
  4 * The contents of this file are subject to the Mozilla Public License Version
  5 * 1.1 (the "License"); you may not use this file except in compliance with
  6 * the License. You may obtain a copy of the License at
  7 * http://www.mozilla.org/MPL/
  8 *
  9 * Software distributed under the License is distributed on an "AS IS" basis,
 10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 11 * for the specific language governing rights and limitations under the
 12 * License.
 13 *
 14 * The Original Code is the Netscape security libraries.
 15 *
 16 * The Initial Developer of the Original Code is
 17 * Netscape Communications Corporation.
 18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
 19 * the Initial Developer. All Rights Reserved.
 20 * Portions created by the Red Hat, Inc. are Copyright (C) 2010
 21 * the Red Hat, Inc.. All Rights Reserved.
 22 *
 23 * Contributor(s):
 24 *
 25 * Alternatively, the contents of this file may be used under the terms of
 26 * either the GNU General Public License Version 2 or later (the "GPL"), or
 27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 28 * in which case the provisions of the GPL or the LGPL are applicable instead
 29 * of those above. If you wish to allow use of your version of this file only
 30 * under the terms of either the GPL or the LGPL, and not to allow others to
 31 * use your version of this file under the terms of the MPL, indicate your
 32 * decision by deleting the provisions above and replace them with the notice
 33 * and other provisions required by the GPL or the LGPL. If you do not delete
 34 * the provisions above, a recipient may use your version of this file under
 35 * the terms of any one of the MPL, the GPL or the LGPL.
 36 *
 37 * ***** END LICENSE BLOCK ***** */
 38
 39#include <stdio.h>
 40#include <stdlib.h>
 41#include "plgetopt.h"
 42#include "nss.h"
 43#include "secutil.h"
 44#include "pk11table.h"
 45#include "secmodt.h"
 46#include "pk11pub.h"
 47
 48
 49struct test_args {
 50    char *arg;
 51    int  mask_value;
 52    char *description;
 53};
 54
 55static const struct test_args test_array[] = {
 56    {"all",   0x1f, "run all the tests" },
 57    {"e_n_p", 0x01, "public exponent, modulus, prime1"},
 58    {"d_n_q", 0x02, "private exponent, modulus, prime2"},
 59    {"d_p_q", 0x04, "private exponent, prime1, prime2"},
 60    {"e_d_q", 0x08, "public exponent, private exponent, prime2"},
 61    {"e_d_n", 0x10, "public exponent, private exponent, moduls"}
 62};
 63static const int test_array_size = 
 64		(sizeof(test_array)/sizeof(struct test_args));
 65
 66static void Usage(char *progName)
 67{
 68    int i;
 69#define PRINTUSAGE(subject, option, predicate) \
 70    fprintf(stderr, "%10s %s\t%s\n", subject, option, predicate);
 71    fprintf(stderr, "%s [-k keysize] [-e exp] [-r rounds] [-t tests]\n "
 72            "Test creating RSA private keys from Partial components\n", 
 73	    progName);
 74    PRINTUSAGE("", "-k", "key size (in bit)");
 75    PRINTUSAGE("", "-e", "rsa public exponent");
 76    PRINTUSAGE("", "-r", "number times to repeat the test");
 77    PRINTUSAGE("", "-t", "run the specified tests");
 78    for (i=0; i < test_array_size; i++) {
 79	PRINTUSAGE("", test_array[i].arg, test_array[i].description);
 80    }
 81    fprintf(stderr,"\n");
 82}
 83
 84/*
 85 * Test the RSA populate command to see that it can really build
 86 * keys from it's components.
 87 */
 88
 89const static CK_ATTRIBUTE rsaTemplate[] = {
 90    {CKA_CLASS, NULL, 0 },
 91    {CKA_KEY_TYPE, NULL, 0 },
 92    {CKA_TOKEN, NULL, 0 },
 93    {CKA_SENSITIVE, NULL, 0 },
 94    {CKA_PRIVATE, NULL, 0 },
 95    {CKA_MODULUS, NULL, 0 },
 96    {CKA_PUBLIC_EXPONENT, NULL, 0 },
 97    {CKA_PRIVATE_EXPONENT, NULL, 0 },
 98    {CKA_PRIME_1, NULL, 0 },
 99    {CKA_PRIME_2, NULL, 0 },
100    {CKA_EXPONENT_1, NULL, 0 },
101    {CKA_EXPONENT_2, NULL, 0 },
102    {CKA_COEFFICIENT, NULL, 0 },
103};
104
105#define RSA_SIZE (sizeof(rsaTemplate))
106#define RSA_ATTRIBUTES (sizeof(rsaTemplate)/sizeof(CK_ATTRIBUTE))
107
108static void
109resetTemplate(CK_ATTRIBUTE *attribute, int start, int end)
110{
111    int i;
112    for (i=start; i < end; i++) {
113	if (attribute[i].pValue) {
114	    PORT_Free(attribute[i].pValue);
115	}
116	attribute[i].pValue = NULL;
117	attribute[i].ulValueLen = 0;
118    }
119}
120
121static SECStatus
122copyAttribute(PK11ObjectType objType, void *object, CK_ATTRIBUTE *template, 
123		int offset, CK_ATTRIBUTE_TYPE attrType)
124{
125    SECItem attributeItem = {0, 0, 0};
126    SECStatus rv;
127
128    rv = PK11_ReadRawAttribute(objType, object, attrType, &attributeItem);
129    if (rv != SECSuccess) {
130	return rv;
131    }
132    template[offset].type = attrType;
133    template[offset].pValue = attributeItem.data;
134    template[offset].ulValueLen = attributeItem.len;
135    return SECSuccess;
136}
137
138static SECStatus
139readKey(PK11ObjectType objType, void *object, CK_ATTRIBUTE *template,
140	int start, int end)
141{
142    int i;
143    SECStatus rv;
144
145    for (i=start; i < end; i++) {
146	rv = copyAttribute(objType, object, template, i, template[i].type);
147	if (rv != SECSuccess) {
148	     goto fail;
149	}
150    }
151    return SECSuccess;
152
153fail:
154    resetTemplate(template, start, i);
155    return rv;
156}
157
158#define ATTR_STRING(x) getNameFromAttribute(x)
159
160void
161dumpTemplate(CK_ATTRIBUTE *template, int start, int end)
162{
163    int i,j;
164    for (i=0; i < end; i++) {
165	unsigned char cval;
166	CK_ULONG ulval;
167	unsigned char *cpval;
168
169	fprintf(stderr, "%s:", ATTR_STRING(template[i].type));
170	switch (template[i].ulValueLen) {
171	case 1:
172	    cval =*(unsigned char *)template[i].pValue;
173	    switch(cval) {
174	    case 0: fprintf(stderr, " false"); break;
175	    case 1: fprintf(stderr, " true"); break;
176	    default: 
177		fprintf(stderr, " %d (=0x%02x,'%c')",cval,cval,cval);
178		 break;
179	    }
180	    break;
181	case sizeof(CK_ULONG):
182	    ulval = *(CK_ULONG *)template[i].pValue;
183	    fprintf(stderr," %ld (=0x%04lx)", ulval, ulval);
184	    break;
185	default:
186	    cpval = (unsigned char *)template[i].pValue;
187	    for (j=0; j < template[i].ulValueLen; j++) {
188	        if ((j % 16) == 0) fprintf(stderr, "\n ");
189		fprintf(stderr," %02x",cpval[j]);
190	    }
191	    break;
192	}
193	fprintf(stderr,"\n");
194    }
195}
196
197PRBool
198rsaKeysAreEqual(PK11ObjectType srcType, void *src, 
199		PK11ObjectType destType, void *dest)
200{
201
202    CK_ATTRIBUTE srcTemplate[RSA_ATTRIBUTES];
203    CK_ATTRIBUTE destTemplate[RSA_ATTRIBUTES];
204    PRBool areEqual = PR_TRUE;
205    SECStatus rv;
206    int i;
207
208    memcpy(srcTemplate, rsaTemplate, RSA_SIZE);
209    memcpy(destTemplate, rsaTemplate, RSA_SIZE);
210
211    rv = readKey(srcType, src, srcTemplate, 0, RSA_ATTRIBUTES);
212    if (rv != SECSuccess) {
213	printf("Could read source key\n");
214	return PR_FALSE;
215    }
216    readKey(destType, dest, destTemplate, 0, RSA_ATTRIBUTES);
217    if (rv != SECSuccess) {
218	printf("Could read dest key\n");
219	return PR_FALSE;
220    }
221
222    for (i=0; i < RSA_ATTRIBUTES; i++) {
223	if (srcTemplate[i].ulValueLen != destTemplate[i].ulValueLen) {
224	    printf("key->%s not equal src_len = %ld, dest_len=%ld\n",
225		    ATTR_STRING(srcTemplate[i].type), 
226		    srcTemplate[i].ulValueLen, destTemplate[i].ulValueLen);
227	    areEqual = 0;
228	} else if (memcmp(srcTemplate[i].pValue, destTemplate[i].pValue,
229			  destTemplate[i].ulValueLen) != 0) {
230	    printf("key->%s not equal.\n", ATTR_STRING(srcTemplate[i].type));
231	    areEqual = 0;
232	}
233    }
234    if (!areEqual) {
235	fprintf(stderr, "original key:\n");
236	dumpTemplate(srcTemplate,0, RSA_ATTRIBUTES);
237	fprintf(stderr, "created key:\n");
238	dumpTemplate(destTemplate,0, RSA_ATTRIBUTES);
239    }
240    return areEqual;
241}
242
243static int exp_exp_prime_fail_count = 0;
244   
245static int 
246doRSAPopulateTest(unsigned int keySize, unsigned long exponent, 
247	          int mask, void *pwarg)
248{
249    SECKEYPrivateKey *rsaPrivKey;
250    SECKEYPublicKey *rsaPubKey;
251    PK11GenericObject *tstPrivKey;
252    CK_ATTRIBUTE tstTemplate[RSA_ATTRIBUTES];
253    int tstHeaderCount;
254    PK11SlotInfo *slot = NULL;
255    PK11RSAGenParams rsaParams;
256    CK_OBJECT_CLASS obj_class = CKO_PRIVATE_KEY;
257    CK_KEY_TYPE key_type = CKK_RSA;
258    CK_BBOOL ck_false = CK_FALSE;
259    int failed = 0;
260
261    rsaParams.pe = exponent;
262    rsaParams.keySizeInBits = keySize;
263
264    slot = PK11_GetInternalSlot();
265    if (slot == NULL) {
266	fprintf(stderr, "Couldn't get the internal slot for the test \n");
267	return -1;
268    }
269
270    rsaPrivKey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, 
271				     &rsaParams, &rsaPubKey, PR_FALSE, 
272				     PR_FALSE, pwarg);
273    if (rsaPrivKey == NULL) {
274	fprintf(stderr, "RSA Key Gen failed");
275	PK11_FreeSlot(slot);
276	return -1;
277    }
278
279    memcpy(tstTemplate, rsaTemplate, RSA_SIZE);
280
281    tstTemplate[0].pValue = &obj_class;
282    tstTemplate[0].ulValueLen = sizeof(obj_class);
283    tstTemplate[1].pValue = &key_type;
284    tstTemplate[1].ulValueLen = sizeof(key_type);
285    tstTemplate[2].pValue = &ck_false;
286    tstTemplate[2].ulValueLen = sizeof(ck_false);
287    tstTemplate[3].pValue = &ck_false;
288    tstTemplate[3].ulValueLen = sizeof(ck_false);
289    tstTemplate[4].pValue = &ck_false;
290    tstTemplate[4].ulValueLen = sizeof(ck_false);
291    tstHeaderCount = 5;
292
293    if (mask & 1) {
294	printf("%s\n",test_array[1].description);
295	resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
296	copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 
297		  tstHeaderCount, CKA_PUBLIC_EXPONENT);
298	copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 
299		  tstHeaderCount+1, CKA_MODULUS);
300	copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 
301		  tstHeaderCount+2, CKA_PRIME_1);
302
303	tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate, 
304			tstHeaderCount+3, PR_FALSE);
305	if (tstPrivKey == NULL) {
306	    fprintf(stderr, "RSA Populate failed: pubExp mod p\n");
307	    failed = 1;
308	} else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey, 
309				PK11_TypeGeneric, tstPrivKey)) {
310	    fprintf(stderr, "RSA Populate key mismatch: pubExp mod p\n");
311	    failed = 1;
312	}
313	if (tstPrivKey) PK11_DestroyGenericObject(tstPrivKey);
314    }
315    if (mask & 2) {
316	printf("%s\n",test_array[2].description);
317	/* test the basic2 case, public exponent, modulus, prime2 */
318	resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
319	copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 
320	    	  tstHeaderCount, CKA_PUBLIC_EXPONENT);
321	copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 
322	    	  tstHeaderCount+1, CKA_MODULUS);
323	copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 
324	    	  tstHeaderCount+2, CKA_PRIME_2);
325	/* test with q in the prime1 position */
326	tstTemplate[tstHeaderCount+2].type = CKA_PRIME_1;
327
328	tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate, 
329	    		tstHeaderCount+3, PR_FALSE);
330	if (tstPrivKey == NULL) {
331	    fprintf(stderr, "RSA Populate failed: pubExp mod q\n");
332	    failed = 1;
333	} else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey, 
334	    			PK11_TypeGeneric, tstPrivKey)) {
335	    fprintf(stderr, "RSA Populate key mismatch: pubExp mod q\n");
336	    failed = 1;
337	}
338	if (tstPrivKey) PK11_DestroyGenericObject(tstPrivKey);
339    }
340    if (mask & 4) {
341	printf("%s\n",test_array[3].description);
342	/* test the medium case, private exponent, prime1, prime2 */
343	resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
344
345	copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 
346	    	  tstHeaderCount, CKA_PRIVATE_EXPONENT);
347	copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 
348	    	  tstHeaderCount+1, CKA_PRIME_1);
349	copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 
350	    	  tstHeaderCount+2, CKA_PRIME_2);
351	/* test with p & q swapped. Underlying code should swap these back */
352	tstTemplate[tstHeaderCount+2].type = CKA_PRIME_1;
353	tstTemplate[tstHeaderCount+1].type = CKA_PRIME_2;
354
355	tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate, 
356	    		tstHeaderCount+3, PR_FALSE);
357	if (tstPrivKey == NULL) {
358	    fprintf(stderr, "RSA Populate failed: privExp p q\n");
359	    failed = 1;
360	} else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey, 
361	    			PK11_TypeGeneric, tstPrivKey)) {
362	    fprintf(stderr, "RSA Populate key mismatch: privExp p q\n");
363	    failed = 1;
364	}
365	if (tstPrivKey) PK11_DestroyGenericObject(tstPrivKey);
366    }
367    if (mask & 8) {
368	printf("%s\n",test_array[4].description);
369	/* test the advanced case, public exponent, private exponent, prime2 */
370	resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
371	copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 
372	    	  tstHeaderCount, CKA_PRIVATE_EXPONENT);
373	copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 
374	    	  tstHeaderCount+1, CKA_PUBLIC_EXPONENT);
375	copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 
376	    	  tstHeaderCount+2, CKA_PRIME_2);
377
378	tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate, 
379	    		tstHeaderCount+3, PR_FALSE);
380	if (tstPrivKey == NULL) {
381	    fprintf(stderr, "RSA Populate failed: pubExp privExp q\n");
382	    fprintf(stderr, " this is expected periodically. It means we\n");
383	    fprintf(stderr, " had more than one key that meets the "
384			    "specification\n");
385	    exp_exp_prime_fail_count++;
386	} else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey, 
387	    			PK11_TypeGeneric, tstPrivKey)) {
388	    fprintf(stderr, "RSA Populate key mismatch: pubExp privExp q\n");
389	    failed = 1;
390	}
391	if (tstPrivKey) PK11_DestroyGenericObject(tstPrivKey);
392    }
393    if (mask & 16) {
394	printf("%s\n",test_array[5].description);
395	/* test the advanced case2, public exponent, private exponent, modulus 
396	 */
397	resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
398
399	copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 
400	    	  tstHeaderCount, CKA_PRIVATE_EXPONENT);
401	copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 
402	    	  tstHeaderCount+1, CKA_PUBLIC_EXPONENT);
403	copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 
404	    	  tstHeaderCount+2, CKA_MODULUS);
405
406	tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate, 
407	    		tstHeaderCount+3, PR_FALSE);
408	if (tstPrivKey == NULL) {
409	    fprintf(stderr, "RSA Populate failed: pubExp privExp mod\n");
410	    failed = 1;
411	} else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey, 
412	    			PK11_TypeGeneric, tstPrivKey)) {
413	    fprintf(stderr, "RSA Populate key mismatch: pubExp privExp mod\n");
414	    failed = 1;
415	}
416	if (tstPrivKey) PK11_DestroyGenericObject(tstPrivKey);
417    }
418
419
420    PK11_FreeSlot(slot);
421    return failed ? -1 : 0;
422}
423
424/* populate options */
425enum {
426    opt_Exponent = 0,
427    opt_KeySize,
428    opt_Repeat,
429    opt_Tests
430};
431
432static secuCommandFlag populate_options[] =
433{
434    { /* opt_Exponent	  */ 'e', PR_TRUE,  0, PR_FALSE },
435    { /* opt_KeySize	  */ 'k', PR_TRUE,  0, PR_FALSE },
436    { /* opt_Repeat	  */ 'r', PR_TRUE,  0, PR_FALSE },
437    { /* opt_Tests	  */ 't', PR_TRUE,  0, PR_FALSE },
438};
439
440int
441is_delimiter(char c)
442{
443    if ((c=='+') || (c==',') || (c=='|')) {
444	return 1;
445    }
446    return 0;
447}
448
449int 
450parse_tests(char *test_string)
451{
452    int mask = 0;
453    int i;
454
455    while (*test_string) {
456	if (is_delimiter(*test_string)) {
457	    test_string++;
458	}
459	for (i=0; i < test_array_size; i++) {
460	    char *arg = test_array[i].arg;
461	    int len = strlen(arg);
462	    if (strncmp(test_string,arg,len) == 0) {
463		test_string += len;
464		mask |= test_array[i].mask_value;
465		break;
466	    }
467	}
468	if (i == test_array_size) {
469	    break;
470	}
471    }
472    return mask;
473}
474
475int main(int argc, char **argv)
476{
477    unsigned int keySize = 1024;
478    unsigned long exponent = 65537;
479    int i, repeat = 1, ret = 0;
480    SECStatus rv = SECFailure;
481    secuCommand populateArgs;
482    char *progName;
483    int mask = 0xff;
484
485    populateArgs.numCommands = 0;
486    populateArgs.numOptions = sizeof(populate_options) / 
487			      sizeof(secuCommandFlag);
488    populateArgs.commands = NULL;
489    populateArgs.options = populate_options;
490
491    progName = strrchr(argv[0], '/');
492    if (!progName) 
493	progName = strrchr(argv[0], '\\');
494    progName = progName ? progName+1 : argv[0];
495
496    rv = NSS_NoDB_Init(NULL);
497    if (rv != SECSuccess) {
498    	SECU_PrintPRandOSError(progName);
499	return -1;
500    }
501
502    rv = SECU_ParseCommandLine(argc, argv, progName, &populateArgs);
503    if (rv == SECFailure) {
504        fprintf(stderr, "%s: command line parsing error!\n", progName);
505        Usage(progName);
506	return -1;
507    }
508    rv = SECFailure;
509
510	
511    if (populateArgs.options[opt_KeySize].activated) {
512	keySize = PORT_Atoi(populateArgs.options[opt_KeySize].arg);
513    }
514    if (populateArgs.options[opt_Repeat].activated) {
515	repeat = PORT_Atoi(populateArgs.options[opt_Repeat].arg);
516    }
517    if (populateArgs.options[opt_Exponent].activated) {
518	exponent = PORT_Atoi(populateArgs.options[opt_Exponent].arg);
519    }
520    if (populateArgs.options[opt_Tests].activated) {
521	char * test_string = populateArgs.options[opt_Tests].arg;
522	mask = PORT_Atoi(test_string);
523	if (mask == 0) {
524	    mask = parse_tests(test_string);
525	}
526	if (mask == 0) {
527	    Usage(progName);
528	    return -1;
529	}
530    }
531
532    exp_exp_prime_fail_count = 0;
533    for (i=0; i < repeat; i++) {
534	printf("Running RSA Populate test run %d\n",i);
535	ret = doRSAPopulateTest(keySize, exponent, mask, NULL);
536	if (ret != 0) {
537	    i++;
538	    break;
539	}
540    }
541    if (ret != 0) {
542	fprintf(stderr,"RSA Populate test round %d: FAILED\n",i);
543    }
544    if (repeat > 1) {
545	printf(" pub priv prime test:  %d failures out of %d runs (%f %%)\n",
546		exp_exp_prime_fail_count, i,
547		(((double)exp_exp_prime_fail_count) * 100.0)/(double) i);
548    }
549    return ret;
550}