📄 yarrow.c
字号:
if (y->seeded) { if (num_sources) { *num_sources = 0; } if (entropy_bits) { *entropy_bits = emax; } THROW( YARROW_OK ); } for (i = 0; i < y->num_sources; i++) { if (y->source[i].entropy[YARROW_SLOW_POOL] >= y->slow_thresh) { num--; } else if (y->source[i].entropy[YARROW_SLOW_POOL] > entropy) { source = i; entropy = y->source[i].entropy[YARROW_SLOW_POOL]; } } if (num_sources) { *num_sources = num; } if (source_id) { *source_id = source; } if (entropy_bits) { *entropy_bits = entropy; } THROW( YARROW_NOT_SEEDED ); CATCH: EXCEP_RET;}YARROW_DLLint Yarrow_Output( Yarrow_CTX* y, void* out, size_t size ){ EXCEP_DECL; int locked = 0; size_t left; char* outp; size_t use; if (!y || !out) { THROW( YARROW_BAD_ARG ); } TRY( Yarrow_detect_fork( y ) ); if (!y->seeded) { THROW( YARROW_NOT_SEEDED ); } left = size; outp = out; TRY( LOCK() ); if (y->out_left > 0) { use = min(left, y->out_left); mem_copy(outp, y->out + CIPHER_BLOCK_SIZE - y->out_left, use); left -= use; y->out_left -= use; outp += use; } for ( ; left >= CIPHER_BLOCK_SIZE; left -= CIPHER_BLOCK_SIZE, outp += CIPHER_BLOCK_SIZE) { TRY( Yarrow_Output_Block(y, outp) ); } if (left > 0) { TRY( Yarrow_Output_Block(y, y->out) ); mem_copy(outp, y->out, left); y->out_left = CIPHER_BLOCK_SIZE - left; } CATCH: if ( locked ) { TRY( UNLOCK() ); } EXCEP_RET;}int Yarrow_Gate(Yarrow_CTX* y){ EXCEP_DECL; byte new_K[CIPHER_KEY_SIZE]; if (!y) { THROW( YARROW_BAD_ARG ); } TRACE( printf( "GATE[" ); ); /* K <- Next k bits of PRNG output */ TRY( Yarrow_Output(y, new_K, CIPHER_KEY_SIZE) ); mem_copy(y->K, new_K, CIPHER_KEY_SIZE); /* need to resetup the key schedule as the key has changed */ CIPHER_Init(&y->cipher, y->K); CATCH: TRACE( printf( "]," ); ); mem_zero(new_K, sizeof(new_K)); EXCEP_RET;}#if defined( YARROW_SAVE_STATE )static int Yarrow_Load_State( Yarrow_CTX *y ){ EXCEP_DECL; Yarrow_STATE state; if ( !y ) { THROW( YARROW_BAD_ARG ); } if ( y->entropyfile ) { TRY( STATE_Load(y->entropyfile, &state) ); TRACE( printf( "LOAD STATE," ); );#if defined( YARROW_DEBUG ) hex_print( stderr, "state.load", state.seed, sizeof(state.seed));#endif /* what to do here is not defined by the Yarrow paper */ /* this is a place holder until we get some clarification */ HASH_Update( &y->pool[YARROW_FAST_POOL], state.seed, sizeof(state.seed) ); Yarrow_Make_Seeded( y ); TRY( Yarrow_Reseed(y, YARROW_FAST_POOL) ); } CATCH: mem_zero(state.seed, sizeof(state.seed)); EXCEP_RET;}static int Yarrow_Save_State( Yarrow_CTX *y ){ EXCEP_DECL; Yarrow_STATE state; if ( !y ) { THROW( YARROW_BAD_ARG ); } if ( y->entropyfile && y->seeded ) { TRACE( printf( "SAVE STATE[" ); ); TRY( Yarrow_Output( y, state.seed, sizeof(state.seed) ) ); TRY( STATE_Save(y->entropyfile, &state) ); } y->saved = 1;# if defined(YARROW_DEBUG) hex_print(stdout, "state.save", state.seed, sizeof(state.seed));# endif CATCH: TRACE( printf( "]," ); ); mem_zero(state.seed, sizeof(state.seed)); EXCEP_RET;}#endifint Yarrow_Reseed(Yarrow_CTX* y, int pool){ EXCEP_DECL; HASH_CTX* fast_pool = &y->pool[YARROW_FAST_POOL]; HASH_CTX* slow_pool = &y->pool[YARROW_SLOW_POOL]; byte digest[HASH_DIGEST_SIZE]; HASH_CTX hash; byte v_0[HASH_DIGEST_SIZE]; byte v_i[HASH_DIGEST_SIZE]; uint32 big_endian_int32; COUNTER i; if (!y) { THROW( YARROW_BAD_ARG ); } if( pool != YARROW_FAST_POOL && pool != YARROW_SLOW_POOL ) { THROW( YARROW_BAD_ARG ); } TRACE( printf( "%s RESEED,", pool == YARROW_SLOW_POOL ? "SLOW" : "FAST" ); ); if (pool == YARROW_SLOW_POOL) { /* SLOW RESEED */ /* feed hash of slow pool into the fast pool */ HASH_Final(slow_pool, digest); /* Each pool contains the running hash of all inputs fed into it * since it was last used to carry out a reseed -- this implies * that the pool must be reinitialized after a reseed */ HASH_Init(slow_pool); /* reinitialize slow pool */ HASH_Update(fast_pool, digest, sizeof(digest)); if (y->seeded == 0) { Yarrow_Make_Seeded( y ); } } /* step 1. v_0 <- hash of all inputs into fast pool */ HASH_Final(fast_pool, v_0); HASH_Init(fast_pool); /* reinitialize fast pool */ /* v_i <- v_0 */ mem_copy( v_i, v_0, sizeof(v_0) ); /* step 2. v_i = h(v_{i-1}|v_0|i) for i = 1,..,Pt */ /* note: this code has to work for Pt = 0 also */ for ( i = 0; i < y->Pt[pool]; i++ ) { HASH_Init(&hash); HASH_Update(&hash, v_i, sizeof(v_i)); HASH_Update(&hash, v_0, sizeof(v_0)); big_endian_int32 = make_big_endian32(i >> 32); /* MS word */ HASH_Update(&hash, &big_endian_int32, sizeof(uint32)); big_endian_int32 = make_big_endian32(i & 0xFFFFFFFF); /* LS word */ HASH_Update(&hash, &big_endian_int32, sizeof(uint32)); HASH_Final(&hash, v_i); } /* step3. K = h'(h(v_Pt|K)) */ /* t = h(v_Pt|K) */ HASH_Init(&hash); HASH_Update(&hash, v_i, sizeof(v_i)); HASH_Update(&hash, y->K, sizeof(y->K)); HASH_Final(&hash, v_i);#if defined(YARROW_DEBUG) hex_print(stdout, "old K", y->K, sizeof(y->K));#endif /* K <- h'(t) */ TRY( Yarrow_Stretch(v_i, HASH_DIGEST_SIZE, y->K, CIPHER_KEY_SIZE) ); /* need to resetup the key schedule as the key has changed */ CIPHER_Init(&y->cipher, y->K);#if defined(YARROW_DEBUG) hex_print(stdout, "new K", y->K, sizeof(y->K));#endif /* step 4. C <- E_k(0) */#if defined(YARROW_DEBUG) hex_print(stdout, "old C", y->C, sizeof(y->C));#endif CIPHER_Encrypt_Block(&y->cipher, zero_block, y->C);#if defined(YARROW_DEBUG) hex_print(stdout, "new C", y->C, sizeof(y->C));#endif /* discard part output from previous key */ y->out_left = 0; /* step 5. Reset all entropy estimate accumulators of the entropy * accumulator to zero */ for (i = 0; i < y->num_sources; i++) { y->source[i].entropy[pool] = 0; if (pool == YARROW_SLOW_POOL) { /* if this is a slow reseed, reset the fast pool entropy * accumulator also */ y->source[i].entropy[YARROW_FAST_POOL] = 0; y->source[i].reached_slow_thresh = 0; } } /* step 7. If a seed file is in use, the next 2k bits of output * are written to the seed file */#if defined( YARROW_SAVE_STATE ) if ( y->seeded && y->entropyfile ) { TRY( Yarrow_Save_State( y ) ); }#endif CATCH: /* step 6. Wipe the memory of all intermediate values * */ mem_zero( digest, sizeof(digest) ); mem_zero( &hash, sizeof(hash) ); mem_zero( v_0, sizeof(v_0) ); mem_zero( v_i, sizeof(v_i) ); EXCEP_RET;}int Yarrow_Stretch(const byte* m, size_t size, byte* out, size_t out_size){ EXCEP_DECL; const byte* s_i; byte* outp; int left, use; HASH_CTX hash, save; byte digest[HASH_DIGEST_SIZE]; if (m == NULL || size == 0 || out == NULL || out_size == 0) { THROW( YARROW_BAD_ARG ); } /* * s_0 = m * s_1 = h(s_0 | ... | s_{i-1}) * * h'(m, k) = first k bits of (s_0 | s_1 | ...) * */ outp = out; left = out_size; use = min(out_size, size); mem_copy(outp, m, use); /* get k bits or as many as available */ s_i = (const byte*)m; /* pointer to s0 = m */ outp += use; left -= use; HASH_Init(&hash); for ( ; left > 0; left -= HASH_DIGEST_SIZE) { HASH_Update(&hash, s_i, use); /* have to save hash state to one side as HASH_final changes state */ mem_copy(&save, &hash, sizeof(hash)); HASH_Final(&hash, digest); use = min(HASH_DIGEST_SIZE, left); mem_copy(outp, digest, use); /* put state back for next time */ mem_copy(&hash, &save, sizeof(hash)); s_i = outp; /* retain pointer to s_i */ outp += use; } CATCH: mem_zero(&hash, sizeof(hash)); mem_zero(digest, sizeof(digest)); EXCEP_RET;}static void block_increment(void* block, const int sz){ byte* b = block; int i; for (i = sz-1; (++b[i]) == 0 && i > 0; i--) { ; /* nothing */ }}YARROW_DLLint Yarrow_Final(Yarrow_CTX* y){ EXCEP_DECL; int locked = 0; if (!y) { THROW( YARROW_BAD_ARG ); } TRY( Yarrow_detect_fork(y) ); TRY( LOCK() ); locked = 1;#if defined( YARROW_SAVE_STATE ) if ( y->seeded && y->entropyfile ) { TRY( Yarrow_Save_State( y ) ); }#endif CATCH: if ( locked ) { TRY( UNLOCK() ); } mem_zero( y, sizeof(Yarrow_CTX) ); EXCEP_RET;}YARROW_DLLconst char* Yarrow_Str_Error( int err ){ err = 1-err; if ( err < 0 || err >= sizeof( yarrow_str_error ) / sizeof( char* ) ) { err = 1-YARROW_FAIL; } return yarrow_str_error[ err ];}#if defined(YARROW_DEBUG)static void hex_print(FILE* f, const char* var, void* data, size_t size){ const char* conv = "0123456789abcdef"; size_t i; char* p = (char*) data; char c, d; fprintf(f, var); fprintf(f, " = "); for (i = 0; i < size; i++) { c = conv[(p[i] >> 4) & 0xf]; d = conv[p[i] & 0xf]; fprintf(f, "%c%c", c, d); } fprintf(f, "\n");}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -