security/nss/cmd/makepqg/makepqg.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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 "prtypes.h"
     6 #include "prtime.h"
     7 #include "prlong.h"
     9 #include "nss.h"
    10 #include "secutil.h"
    11 #include "secitem.h"
    12 #include "pk11func.h"
    13 #include "pk11pqg.h"
    15 #if defined(XP_UNIX)
    16 #include <unistd.h>
    17 #endif
    19 #include "plgetopt.h"
    21 #define BPB 8 /* bits per byte. */
    23 char  *progName;
    26 const SEC_ASN1Template seckey_PQGParamsTemplate[] = {
    27     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) },
    28     { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,prime) },
    29     { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,subPrime) },
    30     { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,base) },
    31     { 0, }
    32 };
    36 void
    37 Usage(void)
    38 {
    39     fprintf(stderr, "Usage:  %s\n", progName);
    40     fprintf(stderr, 
    41 "-a   Output DER-encoded PQG params, BTOA encoded.\n"
    42 "-b   Output DER-encoded PQG params in binary\n"
    43 "-r   Output P, Q and G in ASCII hexadecimal. \n"
    44 "  -l prime-length       Length of prime in bits (1024 is default)\n"
    45 "  -n subprime-length    Length of subprime in bits\n"
    46 "  -o file               Output to this file (default is stdout)\n"
    47 "  -g bits               Generate SEED this many bits long.\n"
    48 );
    49     exit(-1);
    51 }
    53 SECStatus
    54 outputPQGParams(PQGParams * pqgParams, PRBool output_binary, PRBool output_raw,
    55                 FILE * outFile)
    56 {
    57     PLArenaPool   * arena 		= NULL;
    58     char          * PQG;
    59     SECItem       * pItem;
    60     int             cc;
    61     SECStatus       rv;
    62     SECItem         encodedParams;
    64     if (output_raw) {
    65     	SECItem item;
    67 	rv = PK11_PQG_GetPrimeFromParams(pqgParams, &item);
    68 	if (rv) {
    69 	    SECU_PrintError(progName, "PK11_PQG_GetPrimeFromParams");
    70 	    return rv;
    71 	}
    72 	SECU_PrintInteger(outFile, &item,    "Prime",    1);
    73 	SECITEM_FreeItem(&item, PR_FALSE);
    75 	rv = PK11_PQG_GetSubPrimeFromParams(pqgParams, &item);
    76 	if (rv) {
    77 	    SECU_PrintError(progName, "PK11_PQG_GetPrimeFromParams");
    78 	    return rv;
    79 	}
    80 	SECU_PrintInteger(outFile, &item, "Subprime", 1);
    81 	SECITEM_FreeItem(&item, PR_FALSE);
    83 	rv = PK11_PQG_GetBaseFromParams(pqgParams, &item);
    84 	if (rv) {
    85 	    SECU_PrintError(progName, "PK11_PQG_GetPrimeFromParams");
    86 	    return rv;
    87 	}
    88 	SECU_PrintInteger(outFile, &item,     "Base",     1);
    89 	SECITEM_FreeItem(&item, PR_FALSE);
    91 	fprintf(outFile, "\n");
    92 	return SECSuccess;
    93     }
    95     encodedParams.data = NULL;
    96     encodedParams.len  = 0;
    97     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    98     if (!arena) {
    99     	SECU_PrintError(progName, "PORT_NewArena");
   100 	return SECFailure;
   101     }
   102     pItem = SEC_ASN1EncodeItem(arena, &encodedParams, pqgParams,
   103 			       seckey_PQGParamsTemplate);
   104     if (!pItem) {
   105     	SECU_PrintError(progName, "SEC_ASN1EncodeItem");
   106 	PORT_FreeArena(arena, PR_FALSE);
   107     	return SECFailure;
   108     }
   109     if (output_binary) {
   110 	size_t len;
   111 	len = fwrite(encodedParams.data, 1, encodedParams.len, outFile);
   112 	PORT_FreeArena(arena, PR_FALSE);
   113 	if (len != encodedParams.len) {
   114 	     fprintf(stderr, "%s: fwrite failed\n", progName);
   115 	     return SECFailure;
   116 	}
   117 	return SECSuccess;
   118     }
   120     /* must be output ASCII */
   121     PQG = BTOA_DataToAscii(encodedParams.data, encodedParams.len);    
   122     PORT_FreeArena(arena, PR_FALSE);
   123     if (!PQG) {
   124     	SECU_PrintError(progName, "BTOA_DataToAscii");
   125 	return SECFailure;
   126     }
   128     cc = fprintf(outFile,"%s\n",PQG);
   129     PORT_Free(PQG);
   130     if (cc <= 0) {
   131 	 fprintf(stderr, "%s: fprintf failed\n", progName);
   132 	 return SECFailure;
   133     }
   134     return SECSuccess;
   135 }
   137 SECStatus
   138 outputPQGVerify(PQGVerify * pqgVerify, PRBool output_binary, PRBool output_raw,
   139                 FILE * outFile)
   140 {
   141     SECStatus rv = SECSuccess;
   142     if (output_raw) {
   143     	SECItem item;
   144 	unsigned int counter;
   146 	rv = PK11_PQG_GetHFromVerify(pqgVerify, &item);
   147 	if (rv) {
   148 	    SECU_PrintError(progName, "PK11_PQG_GetHFromVerify");
   149 	    return rv;
   150 	}
   151 	SECU_PrintInteger(outFile, &item,        "h",        1);
   152 	SECITEM_FreeItem(&item, PR_FALSE);
   154 	rv = PK11_PQG_GetSeedFromVerify(pqgVerify, &item);
   155 	if (rv) {
   156 	    SECU_PrintError(progName, "PK11_PQG_GetSeedFromVerify");
   157 	    return rv;
   158 	}
   159 	SECU_PrintInteger(outFile, &item,     "SEED",     1);
   160 	fprintf(outFile, "    g:       %d\n", item.len * BPB);
   161 	SECITEM_FreeItem(&item, PR_FALSE);
   163 	counter = PK11_PQG_GetCounterFromVerify(pqgVerify);
   164 	fprintf(outFile, "    counter: %d\n", counter);
   165 	fprintf(outFile, "\n");
   166     }
   167     return rv;
   168 }
   170 int
   171 main(int argc, char **argv)
   172 {
   173     FILE          * outFile 		= NULL;
   174     char          * outFileName         = NULL;
   175     PQGParams     * pqgParams 		= NULL;
   176     PQGVerify     * pqgVerify           = NULL;
   177     int             keySizeInBits	= 1024;
   178     int             j                   = 8;
   179     int             g                   = 0;
   180     int             gMax                = 0;
   181     int             qSizeInBits         = 0;
   182     SECStatus       rv 			= 0;
   183     SECStatus       passed 		= 0;
   184     PRBool          output_ascii	= PR_FALSE;
   185     PRBool          output_binary	= PR_FALSE;
   186     PRBool          output_raw		= PR_FALSE;
   187     PLOptState *optstate;
   188     PLOptStatus status;
   191     progName = strrchr(argv[0], '/');
   192     if (!progName)
   193 	progName = strrchr(argv[0], '\\');
   194     progName = progName ? progName+1 : argv[0];
   196     /* Parse command line arguments */
   197     optstate = PL_CreateOptState(argc, argv, "?abg:l:n:o:r" );
   198     while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
   199 	switch (optstate->option) {
   201 	  case 'l':
   202 	    keySizeInBits = atoi(optstate->value);
   203 	    break;
   205 	  case 'n':
   206 	    qSizeInBits = atoi(optstate->value);
   207 	    break;
   209 	  case 'a':
   210 	    output_ascii = PR_TRUE;  
   211 	    break;
   213 	  case 'b':
   214 	    output_binary = PR_TRUE;
   215 	    break;
   217 	  case 'r':
   218 	    output_raw = PR_TRUE;
   219 	    break;
   221 	  case 'o':
   222 	    if (outFileName) {
   223 	    	PORT_Free(outFileName);
   224 	    }
   225 	    outFileName = PORT_Strdup(optstate->value);
   226 	    if (!outFileName) {
   227 		rv = -1;
   228 	    }
   229 	    break;
   231 	  case 'g':
   232 	    g = atoi(optstate->value);
   233 	    break;
   236 	  default:
   237 	  case '?':
   238 	    Usage();
   239 	    break;
   241 	}
   242     }
   243     PL_DestroyOptState(optstate);
   245     if (status == PL_OPT_BAD) {
   246         Usage();
   247     }
   249     /* exactly 1 of these options must be set. */
   250     if (1 != ((output_ascii  != PR_FALSE) + 
   251 	      (output_binary != PR_FALSE) +
   252 	      (output_raw    != PR_FALSE))) {
   253 	Usage();
   254     }
   256     gMax = 2*keySizeInBits;
   257     if (keySizeInBits < 1024) {
   258 	j = PQG_PBITS_TO_INDEX(keySizeInBits);
   259 	if (j < 0) {
   260 	    fprintf(stderr, "%s: Illegal prime length, \n"
   261 			    "\tacceptable values are between 512 and 1024,\n"
   262 			    "\tand divisible by 64, or 2048 or 3072\n",
   263 			    progName);
   264 	    return 2;
   265 	}
   266 	gMax =2048;
   267 	if ((qSizeInBits != 0) && (qSizeInBits != 160)) {
   268 	    fprintf(stderr, "%s: Illegal subprime length, \n"
   269 			    "\tonly 160 is acceptible for primes <= 1024\n",
   270 			    progName);
   271 	    return 2;
   272 	}
   273 	/* this forces keysizes less than 1024 into the DSA1 generation
   274 	 * code. Whether 1024 uses DSA2 or not is triggered by qSizeInBits
   275 	 * being non-zero. All larger keysizes will use DSA2.
   276 	 */
   277 	qSizeInBits = 0; 
   278     } 
   279     if (g != 0 && (g < 160 || g >= gMax || g % 8 != 0)) {
   280 	fprintf(stderr, "%s: Illegal g bits, \n"
   281 			"\tacceptable values are between 160 and %d,\n"
   282 			"\tand divisible by 8\n", progName, gMax);
   283 	return 3;
   284     }
   286     if (!rv && outFileName) {
   287 	outFile = fopen(outFileName, output_binary ? "wb" : "w");
   288 	if (!outFile) {
   289 	    fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
   290 		    progName, outFileName);
   291 	    rv = -1;
   292 	}
   293     }
   294     if (outFileName) {
   295 	PORT_Free(outFileName);
   296     }
   297     if (rv != 0) {
   298 	return 1;
   299     }
   301     if (outFile == NULL) {
   302 	outFile = stdout;
   303     }
   306     NSS_NoDB_Init(NULL);
   308     if (keySizeInBits > 1024 || qSizeInBits != 0) {
   309 	rv = PK11_PQG_ParamGenV2((unsigned)keySizeInBits, 
   310 	   (unsigned) qSizeInBits, (unsigned)(g/8), &pqgParams, &pqgVerify);
   311     } else if (g) {
   312 	rv = PK11_PQG_ParamGenSeedLen((unsigned)j, (unsigned)(g/8), 
   313 	                         &pqgParams, &pqgVerify);
   314     } else  {
   315 	rv = PK11_PQG_ParamGen((unsigned)j, &pqgParams, &pqgVerify);
   316     }
   317     /* below here, must go to loser */
   319     if (rv != SECSuccess || pqgParams == NULL || pqgVerify == NULL) {
   320 	SECU_PrintError(progName, "PQG parameter generation failed.\n");
   321 	goto loser;
   322     } 
   323     fprintf(stderr, "%s: PQG parameter generation completed.\n", progName);
   325     rv = outputPQGParams(pqgParams, output_binary, output_raw, outFile);
   326     if (rv) {
   327     	fprintf(stderr, "%s: failed to output PQG params.\n", progName);
   328 	goto loser;
   329     }
   330     rv = outputPQGVerify(pqgVerify, output_binary, output_raw, outFile);
   331     if (rv) {
   332     	fprintf(stderr, "%s: failed to output PQG Verify.\n", progName);
   333 	goto loser;
   334     }
   336     rv = PK11_PQG_VerifyParams(pqgParams, pqgVerify, &passed);
   337     if (rv != SECSuccess) {
   338 	fprintf(stderr, "%s: PQG parameter verification aborted.\n", progName);
   339 	goto loser;
   340     }
   341     if (passed != SECSuccess) {
   342 	fprintf(stderr, "%s: PQG parameters failed verification.\n", progName);
   343 	goto loser;
   344     } 
   345     fprintf(stderr, "%s: PQG parameters passed verification.\n", progName);
   347     PK11_PQG_DestroyParams(pqgParams);
   348     PK11_PQG_DestroyVerify(pqgVerify);
   349     return 0;
   351 loser:
   352     PK11_PQG_DestroyParams(pqgParams);
   353     PK11_PQG_DestroyVerify(pqgVerify);
   354     return 1;
   355 }

mercurial