Bumping gaia.json for 4 gaia revision(s) a=gaia-bump
[gecko.git] / security / nss / cmd / makepqg / makepqg.c
blob36e2aab5cdb920c0f67d3fbf12cb6b78d52ec2e2
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, }
36 void
37 Usage(void)
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"
49 exit(-1);
53 SECStatus
54 outputPQGParams(PQGParams * pqgParams, PRBool output_binary, PRBool output_raw,
55 FILE * outFile)
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;
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;
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;
88 SECU_PrintInteger(outFile, &item, "Base", 1);
89 SECITEM_FreeItem(&item, PR_FALSE);
91 fprintf(outFile, "\n");
92 return SECSuccess;
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;
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;
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;
117 return SECSuccess;
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;
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;
134 return SECSuccess;
137 SECStatus
138 outputPQGVerify(PQGVerify * pqgVerify, PRBool output_binary, PRBool output_raw,
139 FILE * outFile)
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;
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;
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");
167 return rv;
171 main(int argc, char **argv)
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);
225 outFileName = PORT_Strdup(optstate->value);
226 if (!outFileName) {
227 rv = -1;
229 break;
231 case 'g':
232 g = atoi(optstate->value);
233 break;
236 default:
237 case '?':
238 Usage();
239 break;
243 PL_DestroyOptState(optstate);
245 if (status == PL_OPT_BAD) {
246 Usage();
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();
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;
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;
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.
277 qSizeInBits = 0;
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;
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;
294 if (outFileName) {
295 PORT_Free(outFileName);
297 if (rv != 0) {
298 return 1;
301 if (outFile == NULL) {
302 outFile = stdout;
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);
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;
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;
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;
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;
341 if (passed != SECSuccess) {
342 fprintf(stderr, "%s: PQG parameters failed verification.\n", progName);
343 goto loser;
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;