pqg.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:22k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is the Netscape security libraries.
  13.  * 
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation. Portions created by Netscape are 
  16.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s):
  20.  * 
  21.  * Alternatively, the contents of this file may be used under the
  22.  * terms of the GNU General Public License Version 2 or later (the
  23.  * "GPL"), in which case the provisions of the GPL are applicable 
  24.  * instead of those above. If you wish to allow use of your 
  25.  * version of this file only under the terms of the GPL and not to
  26.  * allow others to use your version of this file under the MPL,
  27.  * indicate your decision by deleting the provisions above and
  28.  * replace them with the notice and other provisions required by
  29.  * the GPL.  If you do not delete the provisions above, a recipient
  30.  * may use your version of this file under either the MPL or the
  31.  * GPL.
  32.  */
  33. /*
  34.  * PQG parameter generation/verification.  Based on FIPS 186-1.
  35.  *
  36.  * $Id: pqg.c,v 1.5 2000/09/29 04:03:34 nelsonb%netscape.com Exp $
  37.  */
  38. #include "prerr.h"
  39. #include "secerr.h"
  40. #include "prtypes.h"
  41. #include "blapi.h"
  42. #include "secitem.h"
  43. #include "mpi.h"
  44. #include "mpprime.h"
  45. #include "mplogic.h"
  46. #include "secmpi.h"
  47. #define MAX_ITERATIONS 5  /* Maximum number of iterations of primegen */
  48. #define NUMITER        40 /* Number iterations for primality tests    */
  49.  /* XXX to be replaced by define in blapit.h */
  50. #define BITS_IN_Q 160
  51. /* For FIPS-compliance testing.
  52. ** The following array holds the seed defined in FIPS 186-1 appendix 5.
  53. ** This seed is used to generate P and Q according to appendix 2; use of
  54. ** this seed will exactly generate the PQG specified in appendix 2.
  55. */
  56. #ifdef FIPS_186_1_A5_TEST
  57. static const unsigned char fips_186_1_a5_pqseed[] = {
  58.     0xd5, 0x01, 0x4e, 0x4b, 0x60, 0xef, 0x2b, 0xa8,
  59.     0xb6, 0x21, 0x1b, 0x40, 0x62, 0xba, 0x32, 0x24,
  60.     0xe0, 0x42, 0x7d, 0xd3
  61. };
  62. #endif
  63. /* Get a seed for generating P and Q.  If in testing mode, copy in the
  64. ** seed from FIPS 186-1 appendix 5.  Otherwise, obtain bytes from the
  65. ** global random number generator.
  66. */
  67. static SECStatus
  68. getPQseed(SECItem *seed)
  69. {
  70.     if (seed->data) {
  71.         PORT_Free(seed->data);
  72.         seed->data = NULL;
  73.     }
  74.     seed->data = (unsigned char*)PORT_ZAlloc(seed->len);
  75.     if (!seed->data) {
  76. PORT_SetError(SEC_ERROR_NO_MEMORY);
  77. return SECFailure;
  78.     }
  79. #ifdef FIPS_186_1_A5_TEST
  80.     memcpy(seed->data, fips_186_1_a5_pqseed, seed->len);
  81.     return SECSuccess;
  82. #else
  83.     return RNG_GenerateGlobalRandomBytes(seed->data, seed->len);
  84. #endif
  85. }
  86. /* Generate a candidate h value.  If in testing mode, use the h value
  87. ** specified in FIPS 186-1 appendix 5, h = 2.  Otherwise, obtain bytes
  88. ** from the global random number generator.
  89. */
  90. static SECStatus
  91. generate_h_candidate(SECItem *hit, mp_int *H)
  92. {
  93.     SECStatus rv = SECSuccess;
  94.     mp_err   err = MP_OKAY;
  95. #ifdef FIPS_186_1_A5_TEST
  96.     memset(hit->data, 0, hit->len);
  97.     hit->data[hit->len-1] = 0x02;
  98. #else
  99.     rv = RNG_GenerateGlobalRandomBytes(hit->data, hit->len);
  100. #endif
  101.     if (rv)
  102. return SECFailure;
  103.     err = mp_read_unsigned_octets(H, hit->data, hit->len);
  104.     if (err) {
  105. MP_TO_SEC_ERROR(err);
  106. return SECFailure;
  107.     }
  108.     return SECSuccess;
  109. }
  110. /* Compute SHA[(SEED + addend) mod 2**g]
  111. ** Result is placed in shaOutBuf.
  112. ** This computation is used in steps 2 and 7 of FIPS 186 Appendix 2.2 .
  113. */
  114. static SECStatus
  115. addToSeedThenSHA(const SECItem * seed,
  116.                  unsigned long   addend,
  117.                  int             g,
  118.                  unsigned char * shaOutBuf)
  119. {
  120.     SECItem str = { 0, 0, 0 };
  121.     mp_int s, sum, modulus, tmp;
  122.     mp_err    err = MP_OKAY;
  123.     SECStatus rv  = SECSuccess;
  124.     MP_DIGITS(&s)       = 0;
  125.     MP_DIGITS(&sum)     = 0;
  126.     MP_DIGITS(&modulus) = 0;
  127.     MP_DIGITS(&tmp)     = 0;
  128.     CHECK_MPI_OK( mp_init(&s) );
  129.     CHECK_MPI_OK( mp_init(&sum) );
  130.     CHECK_MPI_OK( mp_init(&modulus) );
  131.     SECITEM_TO_MPINT(*seed, &s); /* s = seed */
  132.     /* seed += addend */
  133.     if (addend < MP_DIGIT_MAX) {
  134. CHECK_MPI_OK( mp_add_d(&s, (mp_digit)addend, &s) );
  135.     } else {
  136. CHECK_MPI_OK( mp_init(&tmp) );
  137. CHECK_MPI_OK( mp_set_ulong(&tmp, addend) );
  138. CHECK_MPI_OK( mp_add(&s, &tmp, &s) );
  139.     }
  140.     CHECK_MPI_OK( mp_div_2d(&s, (mp_digit)g, NULL, &sum) );/*sum = s mod 2**g */
  141.     MPINT_TO_SECITEM(&sum, &str, NULL);
  142.     rv = SHA1_HashBuf(shaOutBuf, str.data, str.len); /* SHA1 hash result */
  143. cleanup:
  144.     mp_clear(&s);
  145.     mp_clear(&sum);
  146.     mp_clear(&modulus);
  147.     mp_clear(&tmp);
  148.     if (str.data)
  149. SECITEM_ZfreeItem(&str, PR_FALSE);
  150.     if (err) {
  151. MP_TO_SEC_ERROR(err);
  152. return SECFailure;
  153.     }
  154.     return rv;
  155. }
  156. /*
  157. **  Perform steps 2 and 3 of FIPS 186, appendix 2.2.
  158. **  Generate Q from seed.
  159. */
  160. static SECStatus
  161. makeQfromSeed(
  162.       unsigned int  g,          /* input.  Length of seed in bits. */
  163. const SECItem   *   seed,       /* input.  */
  164.       mp_int    *   Q)          /* output. */
  165. {
  166.     unsigned char sha1[SHA1_LENGTH];
  167.     unsigned char sha2[SHA1_LENGTH];
  168.     unsigned char U[SHA1_LENGTH];
  169.     SECStatus rv  = SECSuccess;
  170.     mp_err    err = MP_OKAY;
  171.     int i;
  172.     /* ******************************************************************
  173.     ** Step 2.
  174.     ** "Compute U = SHA[SEED] XOR SHA[(SEED+1) mod 2**g]."
  175.     **/
  176.     CHECK_SEC_OK( SHA1_HashBuf(sha1, seed->data, seed->len) );
  177.     CHECK_SEC_OK( addToSeedThenSHA(seed, 1, g, sha2) );
  178.     for (i=0; i<SHA1_LENGTH; ++i) 
  179. U[i] = sha1[i] ^ sha2[i];
  180.     /* ******************************************************************
  181.     ** Step 3.
  182.     ** "Form Q from U by setting the most signficant bit (the 2**159 bit)
  183.     **  and the least signficant bit to 1.  In terms of boolean operations,
  184.     **  Q = U OR 2**159 OR 1.  Note that 2**159 < Q < 2**160."
  185.     */
  186.     U[0]             |= 0x80;  /* U is MSB first */
  187.     U[SHA1_LENGTH-1] |= 0x01;
  188.     err = mp_read_unsigned_octets(Q, U, SHA1_LENGTH);
  189. cleanup:
  190.      memset(U, 0, SHA1_LENGTH);
  191.      memset(sha1, 0, SHA1_LENGTH);
  192.      memset(sha2, 0, SHA1_LENGTH);
  193.      if (err) {
  194. MP_TO_SEC_ERROR(err);
  195. return SECFailure;
  196.      }
  197.      return rv;
  198. }
  199. /*  Perform steps 7, 8 and 9 of FIPS 186, appendix 2.2.
  200. **  Generate P from Q, seed, L, and offset.
  201. */
  202. static SECStatus
  203. makePfromQandSeed(
  204.       unsigned int  L,          /* Length of P in bits.  Per FIPS 186. */
  205.       unsigned int  offset,     /* Per FIPS 186, appendix 2.2. */
  206.       unsigned int  g,          /* input.  Length of seed in bits. */
  207. const SECItem   *   seed,       /* input.  */
  208. const mp_int    *   Q,          /* input.  */
  209.       mp_int    *   P)          /* output. */
  210. {
  211.     unsigned int  k;            /* Per FIPS 186, appendix 2.2. */
  212.     unsigned int  n;            /* Per FIPS 186, appendix 2.2. */
  213.     mp_digit      b;            /* Per FIPS 186, appendix 2.2. */
  214.     unsigned char V_k[SHA1_LENGTH];
  215.     mp_int        W, X, c, twoQ, V_n, tmp;
  216.     mp_err    err = MP_OKAY;
  217.     SECStatus rv  = SECSuccess;
  218.     /* Initialize bignums */
  219.     MP_DIGITS(&W)     = 0;
  220.     MP_DIGITS(&X)     = 0;
  221.     MP_DIGITS(&c)     = 0;
  222.     MP_DIGITS(&twoQ)  = 0;
  223.     MP_DIGITS(&V_n)   = 0;
  224.     MP_DIGITS(&tmp)   = 0;
  225.     CHECK_MPI_OK( mp_init(&W)    );
  226.     CHECK_MPI_OK( mp_init(&X)    );
  227.     CHECK_MPI_OK( mp_init(&c)    );
  228.     CHECK_MPI_OK( mp_init(&twoQ) );
  229.     CHECK_MPI_OK( mp_init(&tmp)  );
  230.     CHECK_MPI_OK( mp_init(&V_n)  );
  231.     /* L - 1 = n*160 + b */
  232.     n = (L - 1) / BITS_IN_Q;
  233.     b = (L - 1) % BITS_IN_Q;
  234.     /* ******************************************************************
  235.     ** Step 7.
  236.     **  "for k = 0 ... n let
  237.     **           V_k = SHA[(SEED + offset + k) mod 2**g]."
  238.     **
  239.     ** Step 8.
  240.     **  "Let W be the integer 
  241.     **    W = V_0 + (V_1 * 2**160) + ... + (V_n-1 * 2**((n-1)*160)) 
  242.     **         + ((V_n mod 2**b) * 2**(n*160))
  243.     */
  244.     for (k=0; k<n; ++k) { /* Do the first n terms of V_k */
  245. /* Do step 7 for iteration k.
  246. ** V_k = SHA[(seed + offset + k) mod 2**g]
  247. */
  248. CHECK_SEC_OK( addToSeedThenSHA(seed, offset + k, g, V_k) );
  249. /* Do step 8 for iteration k.
  250. ** W += V_k * 2**(k*160)
  251. */
  252. OCTETS_TO_MPINT(V_k, &tmp, SHA1_LENGTH);      /* get bignum V_k     */
  253. CHECK_MPI_OK( mpl_lsh(&tmp, &tmp, k*160) );   /* tmp = V_k << k*160 */
  254. CHECK_MPI_OK( mp_add(&W, &tmp, &W) );         /* W += tmp           */
  255.     }
  256.     /* Step 8, continued.
  257.     **   [W += ((V_n mod 2**b) * 2**(n*160))] 
  258.     */
  259.     CHECK_SEC_OK( addToSeedThenSHA(seed, offset + n, g, V_k) );
  260.     OCTETS_TO_MPINT(V_k, &V_n, SHA1_LENGTH);          /* get bignum V_n     */
  261.     CHECK_MPI_OK( mp_div_2d(&V_n, b, NULL, &tmp) );   /* tmp = V_n mod 2**b */
  262.     CHECK_MPI_OK( mpl_lsh(&tmp, &tmp, n*160) );       /* tmp = tmp << n*160 */
  263.     CHECK_MPI_OK( mp_add(&W, &tmp, &W) );             /* W += tmp           */
  264.     /* Step 8, continued.
  265.     ** "and let X = W + 2**(L-1).
  266.     **  Note that 0 <= W < 2**(L-1) and hence 2**(L-1) <= X < 2**L."
  267.     */
  268.     CHECK_MPI_OK( mpl_set_bit(&X, (mp_size)(L-1), 1) );    /* X = 2**(L-1) */
  269.     CHECK_MPI_OK( mp_add(&X, &W, &X) );                    /* X += W       */
  270.     /*************************************************************
  271.     ** Step 9.
  272.     ** "Let c = X mod 2q  and set p = X - (c - 1).
  273.     **  Note that p is congruent to 1 mod 2q."
  274.     */
  275.     CHECK_MPI_OK( mp_mul_2(Q, &twoQ) );                    /* 2q           */
  276.     CHECK_MPI_OK( mp_mod(&X, &twoQ, &c) );                 /* c = X mod 2q */
  277.     CHECK_MPI_OK( mp_sub_d(&c, 1, &c) );                   /* c -= 1       */
  278.     CHECK_MPI_OK( mp_sub(&X, &c, P) );                     /* P = X - c    */
  279. cleanup:
  280.     mp_clear(&W);
  281.     mp_clear(&X);
  282.     mp_clear(&c);
  283.     mp_clear(&twoQ);
  284.     mp_clear(&V_n);
  285.     mp_clear(&tmp);
  286.     if (err) {
  287. MP_TO_SEC_ERROR(err);
  288. return SECFailure;
  289.     }
  290.     return rv;
  291. }
  292. /*
  293. ** Generate G from h, P, and Q.
  294. */
  295. static SECStatus
  296. makeGfromH(const mp_int *P,     /* input.  */
  297.            const mp_int *Q,     /* input.  */
  298.                  mp_int *H,     /* input and output. */
  299.                  mp_int *G,     /* output. */
  300.                  PRBool *passed)
  301. {
  302.     mp_int exp, pm1;
  303.     mp_err err = MP_OKAY;
  304.     SECStatus rv = SECSuccess;
  305.     *passed = PR_FALSE;
  306.     MP_DIGITS(&exp) = 0;
  307.     MP_DIGITS(&pm1) = 0;
  308.     CHECK_MPI_OK( mp_init(&exp) );
  309.     CHECK_MPI_OK( mp_init(&pm1) );
  310.     CHECK_MPI_OK( mp_sub_d(P, 1, &pm1) );        /* P - 1            */
  311.     if ( mp_cmp(H, &pm1) > 0)                   /* H = H mod (P-1)  */
  312. CHECK_MPI_OK( mp_sub(H, &pm1, H) );
  313.     /* Let b = 2**n (smallest power of 2 greater than P).
  314.     ** Since P-1 >= b/2, and H < b, quotient(H/(P-1)) = 0 or 1
  315.     ** so the above operation safely computes H mod (P-1)
  316.     */
  317.     /* Check for H = to 0 or 1.  Regen H if so.  (Regen means return error). */
  318.     if (mp_cmp_d(H, 1) <= 0) {
  319. rv = SECFailure;
  320. goto cleanup;
  321.     }
  322.     /* Compute G, according to the equation  G = (H ** ((P-1)/Q)) mod P */
  323.     CHECK_MPI_OK( mp_div(&pm1, Q, &exp, NULL) );  /* exp = (P-1)/Q      */
  324.     CHECK_MPI_OK( mp_exptmod(H, &exp, P, G) );    /* G = H ** exp mod P */
  325.     /* Check for G == 0 or G == 1, return error if so. */
  326.     if (mp_cmp_d(G, 1) <= 0) {
  327. rv = SECFailure;
  328. goto cleanup;
  329.     }
  330.     *passed = PR_TRUE;
  331. cleanup:
  332.     mp_clear(&exp);
  333.     mp_clear(&pm1);
  334.     if (err) {
  335. MP_TO_SEC_ERROR(err);
  336. rv = SECFailure;
  337.     }
  338.     return rv;
  339. }
  340. SECStatus
  341. PQG_ParamGen(unsigned int j, PQGParams **pParams, PQGVerify **pVfy)
  342. {
  343.     unsigned int L;            /* Length of P in bits.  Per FIPS 186. */
  344.     unsigned int seedBytes;
  345.     if (j > 8 || !pParams || !pVfy) {
  346. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  347.         return SECFailure;
  348.     }
  349.     L = 512 + (j * 64);         /* bits in P */
  350.     seedBytes = L/8;
  351.     return PQG_ParamGenSeedLen(j, seedBytes, pParams, pVfy);
  352. }
  353. /* This code uses labels and gotos, so that it can follow the numbered
  354. ** steps in the algorithms from FIPS 186 appendix 2.2 very closely,
  355. ** and so that the correctness of this code can be easily verified.
  356. ** So, please forgive the ugly c code.
  357. **/
  358. SECStatus
  359. PQG_ParamGenSeedLen(unsigned int j, unsigned int seedBytes,
  360.                     PQGParams **pParams, PQGVerify **pVfy)
  361. {
  362.     unsigned int  L;        /* Length of P in bits.  Per FIPS 186. */
  363.     unsigned int  n;        /* Per FIPS 186, appendix 2.2. */
  364.     unsigned int  b;        /* Per FIPS 186, appendix 2.2. */
  365.     unsigned int  g;        /* Per FIPS 186, appendix 2.2. */
  366.     unsigned int  counter;  /* Per FIPS 186, appendix 2.2. */
  367.     unsigned int  offset;   /* Per FIPS 186, appendix 2.2. */
  368.     SECItem      *seed;     /* Per FIPS 186, appendix 2.2. */
  369.     PRArenaPool  *arena  = NULL;
  370.     PQGParams    *params = NULL;
  371.     PQGVerify    *verify = NULL;
  372.     PRBool passed;
  373.     SECItem hit = { 0, 0, 0 };
  374.     mp_int P, Q, G, H, l;
  375.     mp_err    err = MP_OKAY;
  376.     SECStatus rv  = SECFailure;
  377.     int iterations = 0;
  378.     if (j > 8 || !pParams || !pVfy) {
  379. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  380. return SECFailure;
  381.     }
  382.     /* Initialize an arena for the params. */
  383.     arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
  384.     if (!arena) {
  385. PORT_SetError(SEC_ERROR_NO_MEMORY);
  386. return SECFailure;
  387.     }
  388.     params = (PQGParams *)PORT_ArenaZAlloc(arena, sizeof(PQGParams));
  389.     if (!params) {
  390. PORT_SetError(SEC_ERROR_NO_MEMORY);
  391. PORT_FreeArena(arena, PR_TRUE);
  392. return SECFailure;
  393.     }
  394.     params->arena = arena;
  395.     /* Initialize an arena for the verify. */
  396.     arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
  397.     if (!arena) {
  398. PORT_SetError(SEC_ERROR_NO_MEMORY);
  399. return SECFailure;
  400.     }
  401.     verify = (PQGVerify *)PORT_ArenaZAlloc(arena, sizeof(PQGVerify));
  402.     if (!verify) {
  403. PORT_SetError(SEC_ERROR_NO_MEMORY);
  404. PORT_FreeArena(arena, PR_TRUE);
  405. PORT_FreeArena(params->arena, PR_TRUE);
  406. return SECFailure;
  407.     }
  408.     verify->arena = arena;
  409.     seed = &verify->seed;
  410.     arena = NULL;
  411.     /* Initialize bignums */
  412.     MP_DIGITS(&P) = 0;
  413.     MP_DIGITS(&Q) = 0;
  414.     MP_DIGITS(&G) = 0;
  415.     MP_DIGITS(&H) = 0;
  416.     MP_DIGITS(&l) = 0;
  417.     CHECK_MPI_OK( mp_init(&P) );
  418.     CHECK_MPI_OK( mp_init(&Q) );
  419.     CHECK_MPI_OK( mp_init(&G) );
  420.     CHECK_MPI_OK( mp_init(&H) );
  421.     CHECK_MPI_OK( mp_init(&l) );
  422.     /* Compute lengths. */
  423.     L = 512 + (j * 64);               /* bits in P */
  424.     n = (L - 1) / BITS_IN_Q;          /* BITS_IN_Q is 160 */  
  425.     b = (L - 1) % BITS_IN_Q;
  426.     g = seedBytes * BITS_PER_BYTE;    /* bits in seed, NOT G of PQG. */
  427. step_1:
  428.     /* ******************************************************************
  429.     ** Step 1.
  430.     ** "Choose an abitrary sequence of at least 160 bits and call it SEED.
  431.     **  Let g be the length of SEED in bits."
  432.     */
  433.     if (++iterations > MAX_ITERATIONS) {        /* give up after a while */
  434.         PORT_SetError(SEC_ERROR_NEED_RANDOM);
  435.         goto cleanup;
  436.     }
  437.     seed->len = seedBytes;
  438.     CHECK_SEC_OK( getPQseed(seed) );
  439.     /* ******************************************************************
  440.     ** Step 2.
  441.     ** "Compute U = SHA[SEED] XOR SHA[(SEED+1) mod 2**g]."
  442.     **
  443.     ** Step 3.
  444.     ** "Form Q from U by setting the most signficant bit (the 2**159 bit) 
  445.     **  and the least signficant bit to 1.  In terms of boolean operations,
  446.     **  Q = U OR 2**159 OR 1.  Note that 2**159 < Q < 2**160."
  447.     */
  448.     CHECK_SEC_OK( makeQfromSeed(g, seed, &Q) );
  449.     /* ******************************************************************
  450.     ** Step 4.
  451.     ** "Use a robust primality testing algorithm to test whether q is prime."
  452.     **
  453.     ** Appendix 2.1 states that a Rabin test with at least 50 iterations
  454.     ** "will give an acceptable probability of error."
  455.     */
  456.     /*CHECK_SEC_OK( prm_RabinTest(&Q, &passed) );*/
  457.     err = mpp_pprime(&Q, 40);
  458.     passed = (err == MP_YES) ? SECSuccess : SECFailure;
  459.     /* ******************************************************************
  460.     ** Step 5. "If q is not prime, goto step 1."
  461.     */
  462.     if (passed != SECSuccess)
  463.         goto step_1;
  464.     /* ******************************************************************
  465.     ** Step 6. "Let counter = 0 and offset = 2."
  466.     */
  467.     counter = 0;
  468.     offset  = 2;
  469. step_7:
  470.     /* ******************************************************************
  471.     ** Step 7.
  472.     ** "for k = 0 ... n let
  473.     **          V_k = SHA[(SEED + offset + k) mod 2**g]."
  474.     **
  475.     ** Step 8.
  476.     ** "Let W be the sum of  (V_k * 2**(k*160)) for k = 0 ... n
  477.     **  and let X = W + 2**(L-1).
  478.     **  Note that 0 <= W < 2**(L-1) and hence 2**(L-1) <= X < 2**L."
  479.     **
  480.     ** Step 9.
  481.     ** "Let c = X mod 2q  and set p = X - (c - 1).
  482.     **  Note that p is congruent to 1 mod 2q."
  483.     */
  484.     CHECK_SEC_OK( makePfromQandSeed(L, offset, g, seed, &Q, &P) );
  485.     /*************************************************************
  486.     ** Step 10.
  487.     ** "if p < 2**(L-1), then goto step 13."
  488.     */
  489.     CHECK_MPI_OK( mpl_set_bit(&l, (mp_size)(L-1), 1) ); /* l = 2**(L-1) */
  490.     if (mp_cmp(&P, &l) < 0)
  491.         goto step_13;
  492.     /************************************************************
  493.     ** Step 11.
  494.     ** "Perform a robust primality test on p."
  495.     */
  496.     /*CHECK_SEC_OK( prm_RabinTest(&P, &passed) );*/
  497.     err = mpp_pprime(&P, 40);
  498.     passed = (err == MP_YES) ? SECSuccess : SECFailure;
  499.     /* ******************************************************************
  500.     ** Step 12. "If p passes the test performed in step 11, go to step 15."
  501.     */
  502.     if (passed == SECSuccess)
  503.         goto step_15;
  504. step_13:
  505.     /* ******************************************************************
  506.     ** Step 13.  "Let counter = counter + 1 and offset = offset + n + 1."
  507.     */
  508.     counter++;
  509.     offset += n + 1;
  510.     /* ******************************************************************
  511.     ** Step 14.  "If counter >= 4096 goto step 1, otherwise go to step 7."
  512.     */
  513.     if (counter >= 4096)
  514.         goto step_1;
  515.     goto step_7;
  516. step_15:
  517.     /* ******************************************************************
  518.     ** Step 15.  
  519.     ** "Save the value of SEED and the value of counter for use
  520.     **  in certifying the proper generation of p and q."
  521.     */
  522.     /* Generate h. */
  523.     SECITEM_AllocItem(NULL, &hit, seedBytes); /* h is no longer than p */
  524.     if (!hit.data) goto cleanup;
  525.     do {
  526. /* loop generate h until 1<h<p-1 and (h**[(p-1)/q])mod p > 1 */
  527. CHECK_SEC_OK( generate_h_candidate(&hit, &H) );
  528.         CHECK_SEC_OK( makeGfromH(&P, &Q, &H, &G, &passed) );
  529.     } while (passed != PR_TRUE);
  530.     /* All generation is done.  Now, save the PQG params.  */
  531.     MPINT_TO_SECITEM(&P, &params->prime,    params->arena);
  532.     MPINT_TO_SECITEM(&Q, &params->subPrime, params->arena);
  533.     MPINT_TO_SECITEM(&G, &params->base,     params->arena);
  534.     MPINT_TO_SECITEM(&H, &verify->h,        verify->arena);
  535.     verify->counter = counter;
  536.     *pParams = params;
  537.     *pVfy = verify;
  538. cleanup:
  539.     mp_clear(&P);
  540.     mp_clear(&Q);
  541.     mp_clear(&G);
  542.     mp_clear(&H);
  543.     mp_clear(&l);
  544.     if (err) {
  545. MP_TO_SEC_ERROR(err);
  546. rv = SECFailure;
  547.     }
  548.     if (rv) {
  549. PORT_FreeArena(params->arena, PR_TRUE);
  550. PORT_FreeArena(verify->arena, PR_TRUE);
  551.     }
  552.     return rv;
  553. }
  554. SECStatus   
  555. PQG_VerifyParams(const PQGParams *params, 
  556.                  const PQGVerify *vfy, SECStatus *result)
  557. {
  558.     SECStatus rv = SECSuccess;
  559.     int passed;
  560.     unsigned int g, n, L, offset;
  561.     mp_int P, Q, G, P_, Q_, G_, r, h;
  562.     mp_err err = MP_OKAY;
  563.     int j;
  564. #define CHECKPARAM(cond)      
  565.     if (!(cond)) {            
  566. *result = SECFailure; 
  567. goto cleanup;         
  568.     }
  569.     if (!params || !vfy || !result) {
  570. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  571. return SECFailure;
  572.     }
  573.     MP_DIGITS(&P) = 0;
  574.     MP_DIGITS(&Q) = 0;
  575.     MP_DIGITS(&G) = 0;
  576.     MP_DIGITS(&P_) = 0;
  577.     MP_DIGITS(&Q_) = 0;
  578.     MP_DIGITS(&G_) = 0;
  579.     MP_DIGITS(&r) = 0;
  580.     MP_DIGITS(&h) = 0;
  581.     CHECK_MPI_OK( mp_init(&P) );
  582.     CHECK_MPI_OK( mp_init(&Q) );
  583.     CHECK_MPI_OK( mp_init(&G) );
  584.     CHECK_MPI_OK( mp_init(&P_) );
  585.     CHECK_MPI_OK( mp_init(&Q_) );
  586.     CHECK_MPI_OK( mp_init(&G_) );
  587.     CHECK_MPI_OK( mp_init(&r) );
  588.     CHECK_MPI_OK( mp_init(&h) );
  589.     *result = SECSuccess;
  590.     SECITEM_TO_MPINT(params->prime,    &P);
  591.     SECITEM_TO_MPINT(params->subPrime, &Q);
  592.     SECITEM_TO_MPINT(params->base,     &G);
  593.     /* 1.  Q is 160 bits long. */
  594.     CHECKPARAM( mpl_significant_bits(&Q) == 160 );
  595.     /* 2.  P is one of the 9 valid lengths. */
  596.     L = mpl_significant_bits(&P);
  597.     j = PQG_PBITS_TO_INDEX(L);
  598.     CHECKPARAM( j >= 0 && j <= 8 );
  599.     /* 3.  G < P */
  600.     CHECKPARAM( mp_cmp(&G, &P) < 0 );
  601.     /* 4.  P % Q == 1 */
  602.     CHECK_MPI_OK( mp_mod(&P, &Q, &r) );
  603.     CHECKPARAM( mp_cmp_d(&r, 1) == 0 );
  604.     /* 5.  Q is prime */
  605.     CHECKPARAM( mpp_pprime(&Q, NUMITER) == MP_YES );
  606.     /* 6.  P is prime */
  607.     CHECKPARAM( mpp_pprime(&P, NUMITER) == MP_YES );
  608.     /* Steps 7-12 are done only if the optional PQGVerify is supplied. */
  609.     if (!vfy) goto cleanup;
  610.     /* 7.  counter < 4096 */
  611.     CHECKPARAM( vfy->counter < 4096 );
  612.     /* 8.  g >= 160 and g < 2048   (g is length of seed in bits) */
  613.     g = vfy->seed.len * 8;
  614.     CHECKPARAM( g >= 160 && g < 2048 );
  615.     /* 9.  Q generated from SEED matches Q in PQGParams. */
  616.     CHECK_SEC_OK( makeQfromSeed(g, &vfy->seed, &Q_) );
  617.     CHECKPARAM( mp_cmp(&Q, &Q_) == 0 );
  618.     /* 10. P generated from (L, counter, g, SEED, Q) matches P in PQGParams. */
  619.     n = (L - 1) / BITS_IN_Q;
  620.     offset = vfy->counter * (n + 1) + 2;
  621.     CHECK_SEC_OK( makePfromQandSeed(L, offset, g, &vfy->seed, &Q, &P_) );
  622.     CHECKPARAM( mp_cmp(&P, &P_) == 0 );
  623.     /* Next two are optional: if h == 0 ignore */
  624.     if (vfy->h.len == 0) goto cleanup;
  625.     /* 11. 1 < h < P-1 */
  626.     SECITEM_TO_MPINT(vfy->h, &h);
  627.     CHECK_MPI_OK( mpl_set_bit(&P, 0, 0) ); /* P is prime, p-1 == zero 1st bit */
  628.     CHECKPARAM( mp_cmp_d(&h, 1) > 0 && mp_cmp(&h, &P) );
  629.     CHECK_MPI_OK( mpl_set_bit(&P, 0, 1) ); /* set it back */
  630.     /* 12. G generated from h matches G in PQGParams. */
  631.     CHECK_SEC_OK( makeGfromH(&P, &Q, &h, &G_, &passed) );
  632.     CHECKPARAM( passed && mp_cmp(&G, &G_) == 0 );
  633. cleanup:
  634.     mp_clear(&P);
  635.     mp_clear(&Q);
  636.     mp_clear(&G);
  637.     mp_clear(&P_);
  638.     mp_clear(&Q_);
  639.     mp_clear(&G_);
  640.     mp_clear(&r);
  641.     mp_clear(&h);
  642.     if (err) {
  643. MP_TO_SEC_ERROR(err);
  644. rv = SECFailure;
  645.     }
  646.     return rv;
  647. }