rv = SECFailure;
PQG_VerifyParams(const PQGParams *params,                  const PQGVerify *vfy, SECStatus *result){    SECStatus rv = SECSuccess;    SECStatus passed;    unsigned int g, n, L, offset;    mp_int P, Q, G, P_, Q_, G_, r, h;    mp_err err = MP_OKAY;    int j;#define CHECKPARAM(cond)      \    if (!(cond)) {            \	rv = *result = SECFailure; \	goto cleanup;         \    }    if (!params || !vfy || !result) {	PORT_SetError(SEC_ERROR_INVALID_ARGS);	return SECFailure;    }    MP_DIGITS(&P) = 0;    MP_DIGITS(&Q) = 0;    MP_DIGITS(&G) = 0;    MP_DIGITS(&P_) = 0;    MP_DIGITS(&Q_) = 0;    MP_DIGITS(&G_) = 0;    MP_DIGITS(&r) = 0;    MP_DIGITS(&h) = 0;    CHECK_MPI_OK( mp_init(&P) );    CHECK_MPI_OK( mp_init(&Q) );    CHECK_MPI_OK( mp_init(&G) );    CHECK_MPI_OK( mp_init(&P_) );    CHECK_MPI_OK( mp_init(&Q_) );    CHECK_MPI_OK( mp_init(&G_) );    CHECK_MPI_OK( mp_init(&r) );    CHECK_MPI_OK( mp_init(&h) );    *result = SECSuccess;    SECITEM_TO_MPINT(params->prime,    &P);    SECITEM_TO_MPINT(params->subPrime, &Q);    SECITEM_TO_MPINT(params->base,     &G);    /* 1.  Q is 160 bits long. */    CHECKPARAM( params->subPrime.len == DSA_SUBPRIME_LEN &&                params->subPrime.data[0] & 0x80 );    /* 2.  P is one of the 9 valid lengths. */    L = params->prime.len * 8;    CHECKPARAM( params->prime.data[0] & 0x80 );    for (j=0; j<9; j++)	if (L == PQG_INDEX_TO_PBITS(j)) break;    CHECKPARAM( j < 9 );    /* 3.  G < P */    CHECKPARAM( mp_cmp(&G, &P) < 0 );    /* 4.  P % Q == 1 */    rv = mp_mod(&P, &Q, &r);    CHECKPARAM( mp_cmp_d(&r, 1) == 0 );    /* 5.  Q is prime */    CHECKPARAM( mpp_pprime(&Q, NUMITER) == MP_YES ); /* XXX rabin test */    /* 6.  P is prime */    CHECKPARAM( mpp_pprime(&P, NUMITER) == MP_YES ); /* XXX rabin test */    /* Steps 7-12 are done only if the optional PQGVerify is supplied. */    if (!vfy) goto cleanup;    /* 7.  counter < 4096 */    CHECKPARAM( vfy->counter < 4096 );    /* 8.  g >= 160 and g < 2048   (g is length of seed in bits) */    g = vfy->seed.len * 8;    CHECKPARAM( g >= 160 && g < 4096 );    /* 9.  Q generated from SEED matches Q in PQGParams. */    CHECK_SEC_OK( makeQfromSeed(g, &vfy->seed, &Q_) );    CHECKPARAM( mp_cmp(&Q, &Q_) == 0 );    /* 10. P generated from (L, counter, g, SEED, Q) matches P in PQGParams. */    n = (L - 1) / BITS_IN_Q;    offset = vfy->counter * (n + 1) + 2;    CHECK_SEC_OK( makePfromQandSeed(L, offset, g, &vfy->seed, &Q, &P_) );    CHECKPARAM( mp_cmp(&P, &P_) == 0 );    /* Next two are optional: if h == 0 ignore */    if (vfy->h.len == 0) return rv;    /* 11. 1 < h < P-1 */    SECITEM_TO_MPINT(vfy->h, &h);    CHECK_MPI_OK( mpl_set_bit(&P, 0, 0) ); /* P is prime, p-1 == zero 1st bit */    CHECKPARAM( mp_cmp_d(&h, 1) > 0 && mp_cmp(&h, &P) );    CHECK_MPI_OK( mpl_set_bit(&P, 0, 1) ); /* set it back */    /* 12. G generated from h matches G in PQGParams. */    CHECK_SEC_OK( makeGfromH(&P, &Q, &h, &G_, &passed) );    CHECKPARAM( passed && mp_cmp(&G, &G_) == 0 );cleanup:    mp_clear(&P);    mp_clear(&Q);    mp_clear(&G);    mp_clear(&P_);    mp_clear(&Q_);    mp_clear(&G_);    mp_clear(&r);    mp_clear(&h);    if (err) {	MP_TO_SEC_ERROR(err);    }    return rv;}