/** Add entropy to the PRNG state @param in The data to add @param inlen Length of the data to add @param prng PRNG state to update @return CRYPT_OK if successful */ int sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) { struct sober128_prng *c; ulong32 i, k; LTC_ARGCHK(in != NULL); LTC_ARGCHK(prng != NULL); c = &(prng->sober128); if (c->flag == 1) { /* this is the first call to the add_entropy so this input is the key */ /* inlen must be multiple of 4 bytes */ if ((inlen & 3) != 0) { return CRYPT_INVALID_KEYSIZE; } for (i = 0; i < inlen; i += 4) { k = BYTE2WORD((unsigned char *)&in[i]); ADDKEY(k); cycle(c->R); XORNL(nltap(c)); } /* also fold in the length of the key */ ADDKEY(inlen); /* now diffuse */ s128_diffuse(c); s128_genkonst(c); s128_savestate(c); c->nbuf = 0; c->flag = 0; c->set = 1; } else { /* ok we are adding an IV then... */ s128_reloadstate(c); /* inlen must be multiple of 4 bytes */ if ((inlen & 3) != 0) { return CRYPT_INVALID_KEYSIZE; } for (i = 0; i < inlen; i += 4) { k = BYTE2WORD((unsigned char *)&in[i]); ADDKEY(k); cycle(c->R); XORNL(nltap(c)); } /* also fold in the length of the key */ ADDKEY(inlen); /* now diffuse */ s128_diffuse(c); c->nbuf = 0; } return CRYPT_OK; }
int sober128_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng) { struct sober128_prng *c; ulong32 i, k; c = &(prng->sober128); if (c->flag == 1) { /* this is the first call to the add_entropy so this input is the key */ /* len must be multiple of 4 bytes */ assert ((len & 3) == 0); for (i = 0; i < len; i += 4) { k = BYTE2WORD(&buf[i]); ADDKEY(k); cycle(c->R); XORNL(nltap(c)); } /* also fold in the length of the key */ ADDKEY(len); /* now diffuse */ s128_diffuse(c); s128_genkonst(c); s128_savestate(c); c->nbuf = 0; c->flag = 0; c->set = 1; } else { /* ok we are adding an IV then... */ s128_reloadstate(c); /* len must be multiple of 4 bytes */ assert ((len & 3) == 0); for (i = 0; i < len; i += 4) { k = BYTE2WORD(&buf[i]); ADDKEY(k); cycle(c->R); XORNL(nltap(c)); } /* also fold in the length of the key */ ADDKEY(len); /* now diffuse */ s128_diffuse(c); c->nbuf = 0; } return CRYPT_OK; }
uint32_t SIZE_OPTIMIZATION WaitEEWriteToFinish(PFLASH_SSD_CONFIG pSSDConfig, uint32_t* dest,\ uint32_t* size, uint8_t** pData, uint8_t step) { uint32_t ret; /* return code variable */ uint32_t temp; /* temporary variable */ if (0x01U == step) { WRITE8(*dest, READ8(*pData)); } if (0x02U == step) { #if(BIG_ENDIAN == ENDIANNESS) temp = (uint32_t)READ8(*pData) << 8; temp |= (uint32_t)(READ8(*pData + 1)); #else temp = (uint32_t)READ8(*pData + 1) << 8; temp |= (uint32_t)(READ8(*pData)); #endif WRITE16(BYTE2WORD(*dest), (uint16_t)temp); } if (0x04U == step) { #if(BIG_ENDIAN == ENDIANNESS) temp = (uint32_t)READ8(*pData) << 24; temp |= (uint32_t)(READ8(*pData + 1)) << 16; temp |= (uint32_t)(READ8(*pData + 2)) << 8; temp |= (uint32_t)(READ8(*pData + 3)); #else temp = (uint32_t)READ8(*pData + 3) << 24; temp |= (uint32_t)(READ8(*pData + 2)) << 16; temp |= (uint32_t)(READ8(*pData + 1)) << 8; temp |= (uint32_t)READ8(*pData); #endif WRITE32(BYTE2WORD(*dest), (uint32_t)temp); } temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCNFG_OFFSET; while(0x0U == REG_BIT_GET(temp, FTFx_SSD_FCNFG_EEERDY)) { /* wait till EEERDY bit is set */ } /* Check for protection violation error */ temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FSTAT_OFFSET; ret = (uint32_t)REG_READ(temp) & FTFx_SSD_FSTAT_FPVIOL; *dest += step; *size -= step; *pData += step; return ret; }
/** Set IV to the Sober128 state @param c The Sober12820 state @param iv The IV data to add @param ivlen The length of the IV (must be 12) @return CRYPT_OK on success */ int sober128_stream_setiv(sober128_state *c, const unsigned char *iv, unsigned long ivlen) { ulong32 i, k; LTC_ARGCHK(c != NULL); LTC_ARGCHK(iv != NULL); LTC_ARGCHK(ivlen > 0); /* ok we are adding an IV then... */ s128_reloadstate(c); /* ivlen must be multiple of 4 bytes */ if ((ivlen & 3) != 0) { return CRYPT_INVALID_KEYSIZE; } for (i = 0; i < ivlen; i += 4) { k = BYTE2WORD((unsigned char *)&iv[i]); ADDKEY(k); cycle(c->R); XORNL(nltap(c)); } /* also fold in the length of the key */ ADDKEY(ivlen); /* now diffuse */ s128_diffuse(c); c->nbuf = 0; return CRYPT_OK; }
/* Reseed the PRNG given by randomStruct. * It requires previous calls to RandomUpdate. If there is no (enough) * entropy stored returns PRNG_NO_DATA_TO_RESEED. Use GetRandomBytesNeeded * to find out how much (random) input is still needed. */ u32 RandomReseed (RANDOM_STRUCT *randStruct) { u8 auxbuff[PRNG_MOD_BLEN]; if (randStruct == NULL) return PRNG_NOT_INIT; if (randStruct->bytesPool) { /* reseed from pool; new_state = H(previous_state || pool) */ /* transform zstate to byte string */ WORD2BYTE (auxbuff, randStruct->zstate, PRNG_MOD_BLEN); /* compute hash */ SHA1Init (&(randStruct->hashCtx)); SHA1Update (&(randStruct->hashCtx), auxbuff, PRNG_MOD_BLEN); SHA1Update (&(randStruct->hashCtx), randStruct->pool, PRNG_MOD_BLEN); SHA1Final (randStruct->pool, &(randStruct->hashCtx)); /* transform new pool to mpz number (zstate, the new prng state) */ BYTE2WORD (randStruct->zstate, randStruct->pool, PRNG_MOD_BLEN); return PRNG_NO_ERROR; } else /* no input has been fed since last reseed! */ return PRNG_NO_DATA_TO_RESEED; }
void s128_decrypt(s128_ctx *c, UCHAR *buf, int nbytes) { UCHAR *endbuf; WORD t = 0; if ((nbytes & 3) != 0) abort(); endbuf = &buf[nbytes]; /* do small or odd size buffers the slow way, at least at first */ while ((nbytes % (N*4)) != 0) { cycle(c->R); t = nltap(c); t ^= BYTE2WORD(buf); macfunc(c, t); WORD2BYTE(t, buf); nbytes -= 4; buf += 4; } /* now do lots at a time, if there's any left */ while (buf < endbuf) { DROUND(0); DROUND(1); DROUND(2); DROUND(3); DROUND(4); DROUND(5); DROUND(6); DROUND(7); DROUND(8); DROUND(9); DROUND(10); DROUND(11); DROUND(12); DROUND(13); DROUND(14); DROUND(15); DROUND(16); buf += 4*17; } }
SECStatus rijndael_encryptBlock(AESContext *cx, unsigned char *output, const unsigned char *input) { return SECFailure; #ifdef rijndael_large_blocks_fixed unsigned int j, r, Nb; unsigned int c2=0, c3=0; PRUint32 *roundkeyw; PRUint8 clone[RIJNDAEL_MAX_STATE_SIZE]; Nb = cx->Nb; roundkeyw = cx->expandedKey; /* Step 1: Add Round Key 0 to initial state */ for (j=0; j<4*Nb; j+=4) { COLUMN(clone, j) = COLUMN(input, j) ^ *roundkeyw++; } /* Step 2: Loop over rounds [1..NR-1] */ for (r=1; r<cx->Nr; ++r) { for (j=0; j<Nb; ++j) { COLUMN(output, j) = T0(STATE_BYTE(4* j )) ^ T1(STATE_BYTE(4*((j+ 1)%Nb)+1)) ^ T2(STATE_BYTE(4*((j+c2)%Nb)+2)) ^ T3(STATE_BYTE(4*((j+c3)%Nb)+3)); } for (j=0; j<4*Nb; j+=4) { COLUMN(clone, j) = COLUMN(output, j) ^ *roundkeyw++; } } /* Step 3: Do the last round */ /* Final round does not employ MixColumn */ for (j=0; j<Nb; ++j) { COLUMN(output, j) = ((BYTE0WORD(T2(STATE_BYTE(4* j )))) | (BYTE1WORD(T3(STATE_BYTE(4*(j+ 1)%Nb)+1))) | (BYTE2WORD(T0(STATE_BYTE(4*(j+c2)%Nb)+2))) | (BYTE3WORD(T1(STATE_BYTE(4*(j+c3)%Nb)+3)))) ^ *roundkeyw++; } return SECSuccess; #endif }
/** Initialize an Sober128 context (only the key) @param c [out] The destination of the Sober128 state @param key The secret key @param keylen The length of the secret key (octets) @return CRYPT_OK if successful */ int sober128_stream_setup(sober128_state *c, const unsigned char *key, unsigned long keylen) { ulong32 i, k; LTC_ARGCHK(c != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(keylen > 0); /* keylen must be multiple of 4 bytes */ if ((keylen & 3) != 0) { return CRYPT_INVALID_KEYSIZE; } /* Register initialised to Fibonacci numbers */ c->R[0] = 1; c->R[1] = 1; for (i = 2; i < N; ++i) { c->R[i] = c->R[i-1] + c->R[i-2]; } c->konst = INITKONST; for (i = 0; i < keylen; i += 4) { k = BYTE2WORD((unsigned char *)&key[i]); ADDKEY(k); cycle(c->R); XORNL(nltap(c)); } /* also fold in the length of the key */ ADDKEY(keylen); /* now diffuse */ s128_diffuse(c); s128_genkonst(c); s128_savestate(c); c->nbuf = 0; return CRYPT_OK; }
static void s128_loadkey(s128_ctx *c, UCHAR key[], int keylen) { int i; WORD k; /* start folding in key, reject odd sized keys */ if ((keylen & 3) != 0) abort(); for (i = 0; i < keylen; i += 4) { k = BYTE2WORD(&key[i]); ADDKEY(k); cycle(c->R); XORNL(nltap(c)); } /* also fold in the length of the key */ ADDKEY(keylen); /* now diffuse */ s128_diffuse(c); }
static SECStatus rijndael_encryptBlock128(AESContext *cx, unsigned char *output, const unsigned char *input) { unsigned int r; PRUint32 *roundkeyw; rijndael_state state; PRUint32 C0, C1, C2, C3; #if defined(NSS_X86_OR_X64) #define pIn input #define pOut output #else unsigned char *pIn, *pOut; PRUint32 inBuf[4], outBuf[4]; if ((ptrdiff_t)input & 0x3) { memcpy(inBuf, input, sizeof inBuf); pIn = (unsigned char *)inBuf; } else { pIn = (unsigned char *)input; } if ((ptrdiff_t)output & 0x3) { pOut = (unsigned char *)outBuf; } else { pOut = (unsigned char *)output; } #endif roundkeyw = cx->expandedKey; /* Step 1: Add Round Key 0 to initial state */ COLUMN_0(state) = *((PRUint32 *)(pIn )) ^ *roundkeyw++; COLUMN_1(state) = *((PRUint32 *)(pIn + 4 )) ^ *roundkeyw++; COLUMN_2(state) = *((PRUint32 *)(pIn + 8 )) ^ *roundkeyw++; COLUMN_3(state) = *((PRUint32 *)(pIn + 12)) ^ *roundkeyw++; /* Step 2: Loop over rounds [1..NR-1] */ for (r=1; r<cx->Nr; ++r) { /* Do ShiftRow, ByteSub, and MixColumn all at once */ C0 = T0(STATE_BYTE(0)) ^ T1(STATE_BYTE(5)) ^ T2(STATE_BYTE(10)) ^ T3(STATE_BYTE(15)); C1 = T0(STATE_BYTE(4)) ^ T1(STATE_BYTE(9)) ^ T2(STATE_BYTE(14)) ^ T3(STATE_BYTE(3)); C2 = T0(STATE_BYTE(8)) ^ T1(STATE_BYTE(13)) ^ T2(STATE_BYTE(2)) ^ T3(STATE_BYTE(7)); C3 = T0(STATE_BYTE(12)) ^ T1(STATE_BYTE(1)) ^ T2(STATE_BYTE(6)) ^ T3(STATE_BYTE(11)); /* Round key addition */ COLUMN_0(state) = C0 ^ *roundkeyw++; COLUMN_1(state) = C1 ^ *roundkeyw++; COLUMN_2(state) = C2 ^ *roundkeyw++; COLUMN_3(state) = C3 ^ *roundkeyw++; } /* Step 3: Do the last round */ /* Final round does not employ MixColumn */ C0 = ((BYTE0WORD(T2(STATE_BYTE(0)))) | (BYTE1WORD(T3(STATE_BYTE(5)))) | (BYTE2WORD(T0(STATE_BYTE(10)))) | (BYTE3WORD(T1(STATE_BYTE(15))))) ^ *roundkeyw++; C1 = ((BYTE0WORD(T2(STATE_BYTE(4)))) | (BYTE1WORD(T3(STATE_BYTE(9)))) | (BYTE2WORD(T0(STATE_BYTE(14)))) | (BYTE3WORD(T1(STATE_BYTE(3))))) ^ *roundkeyw++; C2 = ((BYTE0WORD(T2(STATE_BYTE(8)))) | (BYTE1WORD(T3(STATE_BYTE(13)))) | (BYTE2WORD(T0(STATE_BYTE(2)))) | (BYTE3WORD(T1(STATE_BYTE(7))))) ^ *roundkeyw++; C3 = ((BYTE0WORD(T2(STATE_BYTE(12)))) | (BYTE1WORD(T3(STATE_BYTE(1)))) | (BYTE2WORD(T0(STATE_BYTE(6)))) | (BYTE3WORD(T1(STATE_BYTE(11))))) ^ *roundkeyw++; *((PRUint32 *) pOut ) = C0; *((PRUint32 *)(pOut + 4)) = C1; *((PRUint32 *)(pOut + 8)) = C2; *((PRUint32 *)(pOut + 12)) = C3; #if defined(NSS_X86_OR_X64) #undef pIn #undef pOut #else if ((ptrdiff_t)output & 0x3) { memcpy(output, outBuf, sizeof outBuf); } #endif return SECSuccess; }
/* PSEC-KEM key encapsulation mechanism Return: TRUE if succeed; otherwise FALSE */ u8 PSEC_KEM_KEM( PSEC_KEM_PUB_KEY *publicKey, /* PSEC_KEM public key */ PSEC_KEM_KEY_ENCAPSULATION *keyEncapsulation, /* returned keyEncapsulation */ PSEC_KEM_KEY_MATERIAL *keyMaterial, /* returned key material */ EC_PARAM *E, PSEC_KEM_EC_ENCODING_FORMAT format ) { mpz_t s, u, res, v; u8 *s_raw, *u_raw, *t_raw, *mgf_arg_1, *mgf_arg_2, *res_raw, *v_raw, *PEH_raw; u8 *EG_raw; s32 i; u32 hoLen, uoLen, EGoLen, PEHoLen, qoLen; EC_POINT h_tilde, g_tilde; mpz_init(s); mpz_init(u); mpz_init(res); mpz_init(v); hoLen = (publicKey->hLen) >> 3; uoLen = (u32)ceil(E->pLen/8.0) + 16; keyMaterial->KoLen = (publicKey->outputKeyLen) >> 3; qoLen = (u32)ceil(E->qLen/8.0); if (format == COMPRESSED) { EGoLen = 1 + qoLen; PEHoLen = 1 + qoLen; } else { EGoLen = 1 + 2*qoLen; PEHoLen = 1 + 2*qoLen; } if ((publicKey->pk).inf_id == EC_O) PEHoLen = 1; if ((E->P).inf_id == EC_O) EGoLen = 1; #ifdef DEBUG printf("hoLen = %u\n", hoLen); printf("uoLen = %u\n", uoLen); printf("keyMaterial->KoLen = %u\n", keyMaterial->KoLen); printf("EGoLen = %u\n", EGoLen); printf("PEHoLen = %u\n", PEHoLen); #endif EC_initPoint ( &h_tilde ); EC_initPoint ( &g_tilde); s_raw = (BYTE *) malloc (hoLen); u_raw = (BYTE *) malloc (uoLen); t_raw = (BYTE *) malloc (uoLen + keyMaterial->KoLen); mgf_arg_1 = (u8 *) malloc (4 + hoLen); mgf_arg_2 = (u8 *) malloc (4 + EGoLen + PEHoLen); res_raw = (u8 *) malloc (hoLen); v_raw = (u8 *) malloc (hoLen); PEH_raw = (u8 *) malloc (PEHoLen); EG_raw = (u8 *) malloc (EGoLen); /* generate s */ GenerateBytes(s_raw, hoLen, global_prng); BYTE2WORD (s, s_raw, hoLen); #ifdef DEBUG printf("s = 0x%s\n", mpz_get_str(NULL, 16, s)); printf("\n"); fflush(stdout); #endif /* compute t = MGF1(0 || s) */ U32TO8_BIG(mgf_arg_1, 0L); memcpy(mgf_arg_1+4, s_raw, hoLen); MGF1( t_raw, 8 * (uoLen + keyMaterial->KoLen), mgf_arg_1, 4 + hoLen); #ifdef DEBUG printf("t = "); printAsHex(t_raw, uoLen+keyMaterial->KoLen); printf("\n"); fflush(stdout); #endif /* parse t as t = u || K */ memcpy( u_raw, t_raw, uoLen ); BYTE2WORD( u, u_raw, uoLen ); memcpy( keyMaterial->K_raw, t_raw+uoLen, keyMaterial->KoLen ); #ifdef DEBUG printf("u = 0x%s\n", mpz_get_str(NULL, 16, u)); printf("keyMaterial = "); printAsHex(keyMaterial->K_raw, keyMaterial->KoLen); printf("\n"); fflush(stdout); #endif /* compute h_tilde = u * publicKey->pk */ EC_Mult( &h_tilde, u, &(publicKey->pk), E ); ec2os (PEH_raw, &h_tilde, E, format); #ifdef DEBUG printf("h_tilde.x = 0x%s\n", mpz_get_str(NULL, 16, h_tilde.x)); printf("h_tilde.y = 0x%s\n", mpz_get_str(NULL, 16, h_tilde.y)); printf("PEH = "); printAsHex(PEH_raw, PEHoLen); printf("\n"); fflush(stdout); #endif /* compute g_tilde = u * E->P */ EC_Mult( &g_tilde, u, &(E->P), E ); #ifdef DEBUG printf("g_tilde.x = 0x%s\n", mpz_get_str(NULL, 16, g_tilde.x)); printf("g_tilde.y = 0x%s\n", mpz_get_str(NULL, 16, g_tilde.y)); printf("g_tilde.inf_id = %u\n", g_tilde.inf_id); #endif /* convert g_tilde's EC point to an octet string according to P1363 E.2.3.2 */ ec2os( EG_raw, &g_tilde, E, format); #ifdef DEBUG printf("EG = "); printAsHex(EG_raw, EGoLen); printf("\n"); fflush(stdout); #endif /* compute res = MGF1( 1 || EG || PEH ) */ U32TO8_BIG ( mgf_arg_2, 1L ); memcpy( mgf_arg_2 + 4, EG_raw, EGoLen ); memcpy( mgf_arg_2 + 4 + EGoLen, PEH_raw, PEHoLen ); MGF1( res_raw, publicKey->hLen, mgf_arg_2, 4 + EGoLen + PEHoLen); BYTE2WORD( res, res_raw, hoLen); #ifdef DEBUG printf("res = 0x%s\n", mpz_get_str(NULL, 16, res)); printf("\n"); fflush(stdout); #endif /* compute v = s \xor res */ mpz_xor(v, s, res); WORD2BYTE(v_raw, v, hoLen); #ifdef DEBUG printf("v = 0x%s\n", mpz_get_str(NULL, 16, v)); printf("\n"); fflush(stdout); #endif /* output C0 = EG || v */ memcpy( keyEncapsulation->C0, EG_raw, EGoLen); memcpy( keyEncapsulation->C0 + EGoLen, v_raw, hoLen); #ifdef DEBUG printf("C0 = "); printAsHex(keyEncapsulation->C0, keyEncapsulation->C0oLen); printf("\n"); fflush(stdout); #endif /* clean up */ mpz_clear(s); mpz_clear(u); mpz_clear(res); mpz_clear(v); memset(s_raw, 0, hoLen); memset(u_raw, 0, uoLen); memset(t_raw, 0, uoLen + keyMaterial->KoLen); memset(mgf_arg_1, 0, 4+hoLen); memset(mgf_arg_2, 0, 4 + EGoLen + PEHoLen); memset(res_raw, 0, hoLen); memset(v_raw, 0, hoLen); memset(PEH_raw, 0, PEHoLen); memset(EG_raw, 0, EGoLen); free(s_raw); free(u_raw); free(t_raw); free(mgf_arg_1); free(mgf_arg_2); free(res_raw); free(v_raw); free(PEH_raw); free(EG_raw); EC_clearPoint ( &h_tilde ); EC_clearPoint ( &g_tilde ); return TRUE; }
/* * Update PRNG state with new input */ u32 RandomUpdate ( RANDOM_STRUCT *randStruct, /* prng context */ u8 *block, /* input */ u32 blockLen /* input length */ ) { u8 auxbuff[SHA1_DIGESTSIZE]; u8 *blockptr; u32 blen; if (randStruct == NULL) return PRNG_NOT_INIT; blockptr = block; blen = blockLen; if (blen == 0) return PRNG_NO_ERROR; /* nothing happens */ if (randStruct->bytesNeeded > 0) { /* Initial seeding is not complete */ if (blen < randStruct->bytesNeeded) { /* not enough seed, save it for later */ memcpy ( (u8 *)(randStruct->seedbuf+RANDOM_BYTES_NEEDED-randStruct->bytesNeeded), blockptr, blen); randStruct->bytesNeeded -= blen; return PRNG_NO_ERROR; } /* complete the seed buffer */ memcpy ( (u8 *)(randStruct->seedbuf+RANDOM_BYTES_NEEDED-randStruct->bytesNeeded), blockptr, randStruct->bytesNeeded); blockptr += randStruct->bytesNeeded; blen -= randStruct->bytesNeeded; /* compute initial state as state = H( seedbuf ) */ SHA1Init (&(randStruct->hashCtx)); SHA1Update (&(randStruct->hashCtx), randStruct->seedbuf, RANDOM_BYTES_NEEDED); SHA1Final (auxbuff, &(randStruct->hashCtx)); /* transform seed buffer into mpz number (the PRNG state) */ BYTE2WORD (randStruct->zstate, auxbuff, PRNG_MOD_BLEN); randStruct->bytesNeeded = 0; /* if there is more input use it for state update; otw return */ if (blen == 0) return PRNG_NO_ERROR; } /* Bulk input processing * * Design note: The update operation is no more than hashing down * the current pool (state) concatenated with the new input. * Namely: new_pool = H(previous_pool || input) */ SHA1Init (&(randStruct->hashCtx)); SHA1Update (&(randStruct->hashCtx), randStruct->pool, PRNG_MOD_BLEN); SHA1Update (&(randStruct->hashCtx), blockptr, blen); SHA1Final (randStruct->pool, &(randStruct->hashCtx)); randStruct->bytesPool += blen; /* Zeroize sensitive information */ memset (auxbuff, 0, SHA1_DIGESTSIZE); blen = 0; return PRNG_NO_ERROR; }
u32 GenerateBytes ( u8 *block, u32 blockLen, RANDOM_STRUCT *randStruct ) { u32 available; u8 auxbuff[PRNG_MOD_BLEN]; mpz_t zaux; u32 return_code = PRNG_NO_ERROR; if (randStruct == NULL) return PRNG_NOT_INIT; /* Is the prng seeded? */ if (randStruct->bytesNeeded) return PRNG_NOT_SEEDED; /* Initializations */ mpz_init_set_ui (zaux, 0L); if (!randStruct->maxNoOutputBlocks) { /* max no. of output blocks exceeded; we need to reseed */ return_code = RandomReseed (randStruct); /* If return_code is PRNG_NO_DATA_TO_RESEED, return output anyway * but forward return code */ } else randStruct->maxNoOutputBlocks--; /* There may be output available from previous output generation */ available = randStruct->outputAvailable; /* Generate and copy prng output */ while (blockLen > available) { /* copy prng output (if any) to user buffer */ memcpy ((u8 *)block, (u8 *)&randStruct->output[SHA1_DIGESTSIZE-available], available); block += available; blockLen -= available; /* * generate new output */ /* In FIPS 186 apdx 3.1, prng output is G(state + optional_user_input) * Here, optional_user_input = 0. * To avoid Blaichenbacher's attack, there is NO reduction modulo q * on the output. */ /* transform prng state (zstate) into byte array */ WORD2BYTE (auxbuff, randStruct->zstate, PRNG_MOD_BLEN); /* Compute randStruct->output = G(state); */ sha1G (randStruct, auxbuff); /* randStruct->output now contains the PRNG output */ available = SHA1_DIGESTSIZE; /* * update prng state */ /* transform output into mpz_t number */ BYTE2WORD (zaux, randStruct->output, SHA1_DIGESTSIZE); /* update state: new state S_{i+1} = H(Si+ti) + S_i + 1 */ mpz_add (zaux, zaux, randStruct->zstate); mpz_add (randStruct->zstate, zaux, one); mpz_mod (randStruct->zstate, randStruct->zstate, two2pow); } /* copy last chunk of prng output to user buffer */ memcpy ((u8 *)block, (u8 *)&randStruct->output[SHA1_DIGESTSIZE-available], blockLen); randStruct->outputAvailable = available - blockLen; /* Zeroize sensitive information */ memset (auxbuff, 0, PRNG_MOD_BLEN); mpz_clear (zaux); available = 0; return (return_code); }