/security/nss/cmd/makepqg/makepqg.c

http://github.com/zpao/v8monkey · C · 363 lines · 274 code · 50 blank · 39 comment · 56 complexity · 413d153500c0e79f3f8845a4cbf362c6 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. *
  21. * Contributor(s):
  22. *
  23. * Alternatively, the contents of this file may be used under the terms of
  24. * either the GNU General Public License Version 2 or later (the "GPL"), or
  25. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  26. * in which case the provisions of the GPL or the LGPL are applicable instead
  27. * of those above. If you wish to allow use of your version of this file only
  28. * under the terms of either the GPL or the LGPL, and not to allow others to
  29. * use your version of this file under the terms of the MPL, indicate your
  30. * decision by deleting the provisions above and replace them with the notice
  31. * and other provisions required by the GPL or the LGPL. If you do not delete
  32. * the provisions above, a recipient may use your version of this file under
  33. * the terms of any one of the MPL, the GPL or the LGPL.
  34. *
  35. * ***** END LICENSE BLOCK ***** */
  36. #include "prtypes.h"
  37. #include "prtime.h"
  38. #include "prlong.h"
  39. #include "nss.h"
  40. #include "secutil.h"
  41. #include "secitem.h"
  42. #include "pk11func.h"
  43. #include "pk11pqg.h"
  44. #if defined(XP_UNIX)
  45. #include <unistd.h>
  46. #endif
  47. #include "plgetopt.h"
  48. #define BPB 8 /* bits per byte. */
  49. char *progName;
  50. const SEC_ASN1Template seckey_PQGParamsTemplate[] = {
  51. { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) },
  52. { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,prime) },
  53. { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,subPrime) },
  54. { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,base) },
  55. { 0, }
  56. };
  57. void
  58. Usage(void)
  59. {
  60. fprintf(stderr, "Usage: %s\n", progName);
  61. fprintf(stderr,
  62. "-a Output DER-encoded PQG params, BTOA encoded.\n"
  63. " -l prime-length Length of prime in bits (1024 is default)\n"
  64. " -o file Output to this file (default is stdout)\n"
  65. "-b Output DER-encoded PQG params in binary\n"
  66. " -l prime-length Length of prime in bits (1024 is default)\n"
  67. " -o file Output to this file (default is stdout)\n"
  68. "-r Output P, Q and G in ASCII hexadecimal. \n"
  69. " -l prime-length Length of prime in bits (1024 is default)\n"
  70. " -o file Output to this file (default is stdout)\n"
  71. "-g bits Generate SEED this many bits long.\n"
  72. );
  73. exit(-1);
  74. }
  75. SECStatus
  76. outputPQGParams(PQGParams * pqgParams, PRBool output_binary, PRBool output_raw,
  77. FILE * outFile)
  78. {
  79. PRArenaPool * arena = NULL;
  80. char * PQG;
  81. SECItem * pItem;
  82. int cc;
  83. SECStatus rv;
  84. SECItem encodedParams;
  85. if (output_raw) {
  86. SECItem item;
  87. rv = PK11_PQG_GetPrimeFromParams(pqgParams, &item);
  88. if (rv) {
  89. SECU_PrintError(progName, "PK11_PQG_GetPrimeFromParams");
  90. return rv;
  91. }
  92. SECU_PrintInteger(outFile, &item, "Prime", 1);
  93. SECITEM_FreeItem(&item, PR_FALSE);
  94. rv = PK11_PQG_GetSubPrimeFromParams(pqgParams, &item);
  95. if (rv) {
  96. SECU_PrintError(progName, "PK11_PQG_GetPrimeFromParams");
  97. return rv;
  98. }
  99. SECU_PrintInteger(outFile, &item, "Subprime", 1);
  100. SECITEM_FreeItem(&item, PR_FALSE);
  101. rv = PK11_PQG_GetBaseFromParams(pqgParams, &item);
  102. if (rv) {
  103. SECU_PrintError(progName, "PK11_PQG_GetPrimeFromParams");
  104. return rv;
  105. }
  106. SECU_PrintInteger(outFile, &item, "Base", 1);
  107. SECITEM_FreeItem(&item, PR_FALSE);
  108. fprintf(outFile, "\n");
  109. return SECSuccess;
  110. }
  111. encodedParams.data = NULL;
  112. encodedParams.len = 0;
  113. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  114. if (!arena) {
  115. SECU_PrintError(progName, "PORT_NewArena");
  116. return SECFailure;
  117. }
  118. pItem = SEC_ASN1EncodeItem(arena, &encodedParams, pqgParams,
  119. seckey_PQGParamsTemplate);
  120. if (!pItem) {
  121. SECU_PrintError(progName, "SEC_ASN1EncodeItem");
  122. PORT_FreeArena(arena, PR_FALSE);
  123. return SECFailure;
  124. }
  125. if (output_binary) {
  126. size_t len;
  127. len = fwrite(encodedParams.data, 1, encodedParams.len, outFile);
  128. PORT_FreeArena(arena, PR_FALSE);
  129. if (len != encodedParams.len) {
  130. fprintf(stderr, "%s: fwrite failed\n", progName);
  131. return SECFailure;
  132. }
  133. return SECSuccess;
  134. }
  135. /* must be output ASCII */
  136. PQG = BTOA_DataToAscii(encodedParams.data, encodedParams.len);
  137. PORT_FreeArena(arena, PR_FALSE);
  138. if (!PQG) {
  139. SECU_PrintError(progName, "BTOA_DataToAscii");
  140. return SECFailure;
  141. }
  142. cc = fprintf(outFile,"%s\n",PQG);
  143. PORT_Free(PQG);
  144. if (cc <= 0) {
  145. fprintf(stderr, "%s: fprintf failed\n", progName);
  146. return SECFailure;
  147. }
  148. return SECSuccess;
  149. }
  150. SECStatus
  151. outputPQGVerify(PQGVerify * pqgVerify, PRBool output_binary, PRBool output_raw,
  152. FILE * outFile)
  153. {
  154. SECStatus rv = SECSuccess;
  155. if (output_raw) {
  156. SECItem item;
  157. unsigned int counter;
  158. rv = PK11_PQG_GetHFromVerify(pqgVerify, &item);
  159. if (rv) {
  160. SECU_PrintError(progName, "PK11_PQG_GetHFromVerify");
  161. return rv;
  162. }
  163. SECU_PrintInteger(outFile, &item, "h", 1);
  164. SECITEM_FreeItem(&item, PR_FALSE);
  165. rv = PK11_PQG_GetSeedFromVerify(pqgVerify, &item);
  166. if (rv) {
  167. SECU_PrintError(progName, "PK11_PQG_GetSeedFromVerify");
  168. return rv;
  169. }
  170. SECU_PrintInteger(outFile, &item, "SEED", 1);
  171. fprintf(outFile, " g: %d\n", item.len * BPB);
  172. SECITEM_FreeItem(&item, PR_FALSE);
  173. counter = PK11_PQG_GetCounterFromVerify(pqgVerify);
  174. fprintf(outFile, " counter: %d\n", counter);
  175. fprintf(outFile, "\n");
  176. }
  177. return rv;
  178. }
  179. int
  180. main(int argc, char **argv)
  181. {
  182. FILE * outFile = NULL;
  183. char * outFileName = NULL;
  184. PQGParams * pqgParams = NULL;
  185. PQGVerify * pqgVerify = NULL;
  186. int keySizeInBits = 1024;
  187. int j;
  188. int g = 0;
  189. SECStatus rv = 0;
  190. SECStatus passed = 0;
  191. PRBool output_ascii = PR_FALSE;
  192. PRBool output_binary = PR_FALSE;
  193. PRBool output_raw = PR_FALSE;
  194. PLOptState *optstate;
  195. PLOptStatus status;
  196. progName = strrchr(argv[0], '/');
  197. if (!progName)
  198. progName = strrchr(argv[0], '\\');
  199. progName = progName ? progName+1 : argv[0];
  200. /* Parse command line arguments */
  201. optstate = PL_CreateOptState(argc, argv, "?abg:l:o:r" );
  202. while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
  203. switch (optstate->option) {
  204. case 'l':
  205. keySizeInBits = atoi(optstate->value);
  206. break;
  207. case 'a':
  208. output_ascii = PR_TRUE;
  209. break;
  210. case 'b':
  211. output_binary = PR_TRUE;
  212. break;
  213. case 'r':
  214. output_raw = PR_TRUE;
  215. break;
  216. case 'o':
  217. if (outFileName) {
  218. PORT_Free(outFileName);
  219. }
  220. outFileName = PORT_Strdup(optstate->value);
  221. if (!outFileName) {
  222. rv = -1;
  223. }
  224. break;
  225. case 'g':
  226. g = atoi(optstate->value);
  227. break;
  228. default:
  229. case '?':
  230. Usage();
  231. break;
  232. }
  233. }
  234. PL_DestroyOptState(optstate);
  235. if (status == PL_OPT_BAD) {
  236. Usage();
  237. }
  238. /* exactly 1 of these options must be set. */
  239. if (1 != ((output_ascii != PR_FALSE) +
  240. (output_binary != PR_FALSE) +
  241. (output_raw != PR_FALSE))) {
  242. Usage();
  243. }
  244. j = PQG_PBITS_TO_INDEX(keySizeInBits);
  245. if (j < 0) {
  246. fprintf(stderr, "%s: Illegal prime length, \n"
  247. "\tacceptable values are between 512 and 1024,\n"
  248. "\tand divisible by 64\n", progName);
  249. return 2;
  250. }
  251. if (g != 0 && (g < 160 || g >= 2048 || g % 8 != 0)) {
  252. fprintf(stderr, "%s: Illegal g bits, \n"
  253. "\tacceptable values are between 160 and 2040,\n"
  254. "\tand divisible by 8\n", progName);
  255. return 3;
  256. }
  257. if (!rv && outFileName) {
  258. outFile = fopen(outFileName, output_binary ? "wb" : "w");
  259. if (!outFile) {
  260. fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
  261. progName, outFileName);
  262. rv = -1;
  263. }
  264. }
  265. if (outFileName) {
  266. PORT_Free(outFileName);
  267. }
  268. if (rv != 0) {
  269. return 1;
  270. }
  271. if (outFile == NULL) {
  272. outFile = stdout;
  273. }
  274. NSS_NoDB_Init(NULL);
  275. if (g)
  276. rv = PK11_PQG_ParamGenSeedLen((unsigned)j, (unsigned)(g/8),
  277. &pqgParams, &pqgVerify);
  278. else
  279. rv = PK11_PQG_ParamGen((unsigned)j, &pqgParams, &pqgVerify);
  280. /* below here, must go to loser */
  281. if (rv != SECSuccess || pqgParams == NULL || pqgVerify == NULL) {
  282. SECU_PrintError(progName, "PQG parameter generation failed.\n");
  283. goto loser;
  284. }
  285. fprintf(stderr, "%s: PQG parameter generation completed.\n", progName);
  286. rv = outputPQGParams(pqgParams, output_binary, output_raw, outFile);
  287. if (rv) {
  288. fprintf(stderr, "%s: failed to output PQG params.\n", progName);
  289. goto loser;
  290. }
  291. rv = outputPQGVerify(pqgVerify, output_binary, output_raw, outFile);
  292. if (rv) {
  293. fprintf(stderr, "%s: failed to output PQG Verify.\n", progName);
  294. goto loser;
  295. }
  296. rv = PK11_PQG_VerifyParams(pqgParams, pqgVerify, &passed);
  297. if (rv != SECSuccess) {
  298. fprintf(stderr, "%s: PQG parameter verification aborted.\n", progName);
  299. goto loser;
  300. }
  301. if (passed != SECSuccess) {
  302. fprintf(stderr, "%s: PQG parameters failed verification.\n", progName);
  303. goto loser;
  304. }
  305. fprintf(stderr, "%s: PQG parameters passed verification.\n", progName);
  306. PK11_PQG_DestroyParams(pqgParams);
  307. PK11_PQG_DestroyVerify(pqgVerify);
  308. return 0;
  309. loser:
  310. PK11_PQG_DestroyParams(pqgParams);
  311. PK11_PQG_DestroyVerify(pqgVerify);
  312. return 1;
  313. }