BeRTOS
|
00001 00038 #include "randpool.h" 00039 #include "md2.h" 00040 00041 #include <cfg/compiler.h> 00042 #include <cfg/debug.h> //ASSERT() 00043 #include <cfg/macros.h> //MIN(), ROUND_UP(); 00044 00045 #include <stdio.h> //sprintf(); 00046 #include <string.h> //memset(), memcpy(); 00047 00048 #if CONFIG_RANDPOOL_TIMER 00049 #include <drv/timer.h> //timer_clock(); 00050 #endif 00051 00052 00053 00054 /* 00055 * Insert bytes in entropy pool, making a XOR of bytes present 00056 * in entropy pool. 00057 */ 00058 static void randpool_push(EntropyPool *pool, void *_byte, size_t n_byte) 00059 { 00060 size_t i = pool->pos_add; // Current number of byte insert in entropy pool. 00061 uint8_t *byte; 00062 00063 byte = (uint8_t *)_byte; 00064 00065 /* 00066 * Insert a bytes in entropy pool. 00067 */ 00068 for(size_t j = 0; j < n_byte; j++) 00069 { 00070 pool->pool_entropy[i] = pool->pool_entropy[i] ^ byte[j]; 00071 i++; 00072 i = i % CONFIG_SIZE_ENTROPY_POOL; 00073 } 00074 00075 pool->pos_add = i; // Update a insert bytes. 00076 } 00077 00078 00079 /* 00080 * This function stir entropy pool with MD2 function hash. 00081 * 00082 */ 00083 static void randpool_stir(EntropyPool *pool) 00084 { 00085 size_t entropy = pool->entropy; //Save current calue of entropy. 00086 Md2Context context; 00087 uint8_t tmp_buf[((sizeof(size_t) * 2) + sizeof(int)) * 2 + 1]; //Temporary buffer. 00088 00089 md2_init(&context); //Init MD2 algorithm. 00090 00091 randpool_add(pool, NULL, 0); 00092 00093 for (int i = 0; i < (CONFIG_SIZE_ENTROPY_POOL / MD2_DIGEST_LEN); i++) 00094 { 00095 sprintf((char *)tmp_buf, "%0x%0x%0x", pool->counter, i, pool->pos_add); 00096 00097 /* 00098 * Hash with MD2 algorithm the entropy pool. 00099 */ 00100 md2_update(&context, pool->pool_entropy, CONFIG_SIZE_ENTROPY_POOL); 00101 00102 md2_update(&context, tmp_buf, sizeof(tmp_buf) - 1); 00103 00104 /*Insert a message digest in entropy pool.*/ 00105 randpool_push(pool, md2_end(&context), MD2_DIGEST_LEN); 00106 00107 pool->counter = pool->counter + 1; 00108 00109 } 00110 00111 /*Insert in pool the difference between a two call of this function (see above).*/ 00112 randpool_add(pool, NULL, 0); 00113 00114 pool->entropy = entropy; //Restore old value of entropy. We haven't add entropy. 00115 } 00116 00120 void randpool_add(EntropyPool *pool, void *data, size_t entropy) 00121 { 00122 uint8_t sep[] = "\xaa\xaa\xaa\xaa"; // ?? 00123 size_t data_len = ROUND_UP(entropy, 8) / 8; //Number of entropy byte in input. 00124 00125 randpool_push(pool, data, data_len); //Insert data to entropy pool. 00126 00127 #if CONFIG_RANDPOOL_TIMER 00128 00129 ticks_t event = timer_clock(); 00130 ticks_t delta; 00131 00132 /*Difference of time between a two accese to entropy pool.*/ 00133 delta = event - pool->last_counter; 00134 00135 randpool_push(pool, &event, sizeof(ticks_t)); 00136 randpool_push(pool, sep, sizeof(sep) - 1); // ?? 00137 randpool_push(pool, &delta, sizeof(delta)); 00138 00139 /* 00140 * Count of number entropy bit add with delta. 00141 */ 00142 delta = delta & 0xff; 00143 while(delta) 00144 { 00145 delta >>= 1; 00146 entropy++; 00147 } 00148 00149 pool->last_counter = event; 00150 00151 #endif 00152 00153 pool->entropy += entropy; //Update a entropy of the pool. 00154 } 00155 00161 void randpool_init(EntropyPool *pool, void *_data, size_t len) 00162 { 00163 uint8_t *data; 00164 00165 data = (uint8_t *)_data; 00166 00167 memset(pool, 0, sizeof(EntropyPool)); 00168 pool->pos_get = MD2_DIGEST_LEN; 00169 00170 #if CONFIG_RANDPOOL_TIMER 00171 pool->last_counter = timer_clock(); 00172 #endif 00173 00174 if(data) 00175 { 00176 /* 00177 * Initialize a entropy pool with a 00178 * previous pool, and assume all pool as 00179 * entropy. 00180 */ 00181 len = MIN(len,(size_t)CONFIG_SIZE_ENTROPY_POOL); 00182 memcpy(pool->pool_entropy, data, len); 00183 pool->entropy = len; 00184 } 00185 00186 } 00187 00191 size_t randpool_size(EntropyPool *pool) 00192 { 00193 return pool->entropy; 00194 } 00195 00205 void randpool_get(EntropyPool *pool, void *_data, size_t n_byte) 00206 { 00207 Md2Context context; 00208 size_t i = pool->pos_get; 00209 size_t n = n_byte; 00210 size_t pos_write = 0; //Number of block has been written in data. 00211 size_t len = MIN((size_t)MD2_DIGEST_LEN, n_byte); 00212 uint8_t *data; 00213 00214 data = (uint8_t *)_data; 00215 00216 /* Test if i + CONFIG_MD2_BLOCK_LEN is inside of entropy pool.*/ 00217 ASSERT((MD2_DIGEST_LEN + i) <= CONFIG_SIZE_ENTROPY_POOL); 00218 00219 md2_init(&context); 00220 00221 while(n > 0) 00222 { 00223 00224 /*Hash previous state of pool*/ 00225 md2_update(&context, &pool->pool_entropy[i], MD2_DIGEST_LEN); 00226 00227 memcpy(&data[pos_write], md2_end(&context), len); 00228 00229 pos_write += len; //Update number of block has been written in data. 00230 n -= len; //Number of byte copied in data. 00231 00232 len = MIN(n,(size_t)MD2_DIGEST_LEN); 00233 00234 i = (i + MD2_DIGEST_LEN) % CONFIG_SIZE_ENTROPY_POOL; 00235 00236 /* If we haven't more entropy pool to hash, we stir it.*/ 00237 if(i < MD2_DIGEST_LEN) 00238 { 00239 randpool_stir(pool); 00240 i = pool->pos_get; 00241 } 00242 00243 } 00244 00245 pool->pos_get = i; //Current number of byte we get from pool. 00246 pool->entropy -= n_byte; //Update a entropy. 00247 00248 } 00249 00253 uint8_t *randpool_pool(EntropyPool *pool) 00254 { 00255 return pool->pool_entropy; 00256 } 00257