security/nss/cmd/rsapoptst/rsapoptst.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 <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 }

mercurial