CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(pb, primeLen) ); CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(qb, primeLen) ); pb[0]          |= 0xC0;  pb[primeLen-1] |= 0x01;  qb[0]          |= 0xC0;  qb[primeLen-1] |= 0x01;  CHECK_MPI_OK( mp_read_unsigned_octets(&p, pb, primeLen) ); CHECK_MPI_OK( mp_read_unsigned_octets(&q, qb, primeLen) ); CHECK_MPI_OK( mpp_make_prime(&p, primeLen * 8, PR_FALSE, &counter) ); CHECK_MPI_OK( mpp_make_prime(&q, primeLen * 8, PR_FALSE, &counter) );
CHECK_SEC_OK( generate_prime(&p, primeLen) ); CHECK_SEC_OK( generate_prime(&q, primeLen) );
RSA_NewKey(int keySizeInBits, SECItem *publicExponent){    unsigned char *pb = NULL, *qb = NULL;    unsigned int primeLen;    unsigned long counter;    mp_int p, q, e;    mp_err   err = MP_OKAY;    SECStatus rv = SECSuccess;    int prerr = 0;    RSAPrivateKey *key = NULL;    PRArenaPool *arena = NULL;    /* Require key size to be a multiple of 16 bits. */    if (!publicExponent || keySizeInBits % 16 != 0) {	PORT_SetError(SEC_ERROR_INVALID_ARGS);	return NULL;    }    /* length of primes p and q (in bytes) */    primeLen = keySizeInBits / (2 * BITS_PER_BYTE);    MP_DIGITS(&p) = 0;    MP_DIGITS(&q) = 0;    MP_DIGITS(&e) = 0;    CHECK_MPI_OK( mp_init(&p) );    CHECK_MPI_OK( mp_init(&q) );    CHECK_MPI_OK( mp_init(&e) );    /* 1. Allocate arena & key */    arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);    if (!arena) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	return NULL;    }    key = (RSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(RSAPrivateKey));    if (!key) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	PORT_FreeArena(arena, PR_TRUE);	return NULL;    }    key->arena = arena;    /* 2.  Set the version number (PKCS1 v1.5 says it should be zero) */    SECITEM_AllocItem(arena, &key->version, 1);    key->version.data[0] = 0;    /* 3.  Set the public exponent */    SECITEM_CopyItem(arena, &key->publicExponent, publicExponent);    SECITEM_TO_MPINT(*publicExponent, &e);    /* 4.  Generate primes p and q */    pb = PORT_Alloc(primeLen);    qb = PORT_Alloc(primeLen);    if (!pb || !qb) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto cleanup;    }    do {	PORT_SetError(0);	CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(pb, primeLen) );	CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(qb, primeLen) );	pb[0]          |= 0xC0; /* set two high-order bits */	pb[primeLen-1] |= 0x01; /* set low-order bit       */	qb[0]          |= 0xC0; /* set two high-order bits */	qb[primeLen-1] |= 0x01; /* set low-order bit       */	CHECK_MPI_OK( mp_read_unsigned_octets(&p, pb, primeLen) );	CHECK_MPI_OK( mp_read_unsigned_octets(&q, qb, primeLen) );	CHECK_MPI_OK( mpp_make_prime(&p, primeLen * 8, PR_FALSE, &counter) );	CHECK_MPI_OK( mpp_make_prime(&q, primeLen * 8, PR_FALSE, &counter) );	if (mp_cmp(&p, &q) < 0)	    mp_exch(&p, &q);	rv = rsa_keygen_from_primes(&p, &q, &e, key, keySizeInBits);	if (rv == SECSuccess)	    break; /* generated two good primes */	prerr = PORT_GetError();    } while (prerr == SEC_ERROR_NEED_RANDOM); /* loop until have primes */    MPINT_TO_SECITEM(&p, &key->prime1, arena);    MPINT_TO_SECITEM(&q, &key->prime2, arena);cleanup:    mp_clear(&p);    mp_clear(&q);    mp_clear(&e);    if (pb)	PORT_ZFree(pb, primeLen);    if (qb)	PORT_ZFree(qb, primeLen);    if (err) {	MP_TO_SEC_ERROR(err);	rv = SECFailure;    }    if (rv && arena) {	PORT_FreeArena(arena, PR_TRUE);	key = NULL;    }    return key;}