mp_err err;
mp_err err   = MP_OKAY;
dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,               const unsigned char *kb){    mp_int p, q, g;  /* PQG parameters */    mp_int x, k;     /* private key & pseudo-random integer */    mp_int r, s;     /* tuple (r, s) is signature) */    mp_err err;    SECStatus rv = SECSuccess;    /* FIPS-compliance dictates that digest is a SHA1 hash. */    /* Check args. */    if (!key || !signature || !digest ||        (signature->len != DSA_SIGNATURE_LEN) ||	(digest->len != SHA1_LENGTH)) {	PORT_SetError(SEC_ERROR_INVALID_ARGS);	return SECFailure;    }    /* Initialize MPI integers. */    MP_DIGITS(&p) = 0;    MP_DIGITS(&q) = 0;    MP_DIGITS(&g) = 0;    MP_DIGITS(&x) = 0;    MP_DIGITS(&k) = 0;    MP_DIGITS(&r) = 0;    MP_DIGITS(&s) = 0;    CHECKOK( mp_init(&p) );    CHECKOK( mp_init(&q) );    CHECKOK( mp_init(&g) );    CHECKOK( mp_init(&x) );    CHECKOK( mp_init(&k) );    CHECKOK( mp_init(&r) );    CHECKOK( mp_init(&s) );    /*    ** Convert stored PQG and private key into MPI integers.    */    SECITEM_TO_MPINT(key->params.prime,    &p);    SECITEM_TO_MPINT(key->params.subPrime, &q);    SECITEM_TO_MPINT(key->params.base,     &g);    SECITEM_TO_MPINT(key->privateValue,    &x);    CHECKOK( mp_read_unsigned_octets(&k, kb, DSA_SUBPRIME_LEN) );    /*    ** FIPS 186-1, Section 5, Step 1    **    ** r = (g**k mod p) mod q    */    CHECKOK( mp_exptmod(&g, &k, &p, &r) ); /* r = g**k mod p */    CHECKOK(     mp_mod(&r, &q, &r) );     /* r = r mod q    */    /*                                      ** FIPS 186-1, Section 5, Step 2    **    ** s = (k**-1 * (SHA1(M) + x*r)) mod q    */    SECITEM_TO_MPINT(*digest, &s);         /* s = SHA1(M)     */    CHECKOK( mp_invmod(&k, &q, &k) );      /* k = k**-1 mod q */    CHECKOK( mp_mulmod(&x, &r, &q, &x) );  /* x = x * r mod q */    CHECKOK( mp_addmod(&s, &x, &q, &s) );  /* s = s + x mod q */    CHECKOK( mp_mulmod(&s, &k, &q, &s) );  /* s = s * k mod q */    /*    ** verify r != 0 and s != 0    ** mentioned as optional in FIPS 186-1.    */    if (mp_cmp_z(&r) == 0 || mp_cmp_z(&s) == 0) {	PORT_SetError(SEC_ERROR_NEED_RANDOM);	rv = SECFailure;	goto cleanup;    }    /*    ** Step 4    **    ** Signature is tuple (r, s)    */    err = mp_to_fixlen_octets(&r, signature->data, DSA_SUBPRIME_LEN);    if (err < 0) goto cleanup;     err = mp_to_fixlen_octets(&s, signature->data + DSA_SUBPRIME_LEN,                                   DSA_SUBPRIME_LEN);    if (err < 0) goto cleanup;     err = MP_OKAY;cleanup:    mp_clear(&p);    mp_clear(&q);    mp_clear(&g);    mp_clear(&x);    mp_clear(&k);    mp_clear(&r);    mp_clear(&s);    if (err) {	translate_mpi_error(err);	rv = SECFailure;    }    return rv;}