PageRenderTime 67ms CodeModel.GetById 9ms app.highlight 51ms RepoModel.GetById 1ms app.codeStats 0ms

/security/nss/lib/freebl/pqg.c

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