comparison dbrandom.c @ 1916:3f4cdf839a1a

Make SHA1 optional, implement SHA256 fingerprints SHA256 is always compiled and only enable SHA1 when needed. Fingerprints are always SHA256: base64 format, md5 and sha1 are removed. dbrandom now uses sha256 its hash function.
author Matt Johnston <matt@ucc.asn.au>
date Wed, 30 Mar 2022 11:44:04 +0800
parents 833bf9947603
children
comparison
equal deleted inserted replaced
1915:13cb8cc1b0e4 1916:3f4cdf839a1a
32 /* this is used to generate unique output from the same hashpool */ 32 /* this is used to generate unique output from the same hashpool */
33 static uint32_t counter = 0; 33 static uint32_t counter = 0;
34 /* the max value for the counter, so it won't integer overflow */ 34 /* the max value for the counter, so it won't integer overflow */
35 #define MAX_COUNTER (1<<30) 35 #define MAX_COUNTER (1<<30)
36 36
37 static unsigned char hashpool[SHA1_HASH_SIZE] = {0}; 37 static unsigned char hashpool[SHA256_HASH_SIZE] = {0};
38 static int donerandinit = 0; 38 static int donerandinit = 0;
39 39
40 #define INIT_SEED_SIZE 32 /* 256 bits */ 40 #define INIT_SEED_SIZE 32 /* 256 bits */
41 41
42 /* The basic setup is we read some data from /dev/(u)random or prngd and hash it 42 /* The basic setup is we read some data from /dev/(u)random or prngd and hash it
98 /* whole file was read as requested */ 98 /* whole file was read as requested */
99 break; 99 break;
100 } 100 }
101 goto out; 101 goto out;
102 } 102 }
103 sha1_process(hs, readbuf, readlen); 103 sha256_process(hs, readbuf, readlen);
104 readcount += readlen; 104 readcount += readlen;
105 } 105 }
106 ret = DROPBEAR_SUCCESS; 106 ret = DROPBEAR_SUCCESS;
107 out: 107 out:
108 close(readfd); 108 close(readfd);
118 return; 118 return;
119 } 119 }
120 #endif 120 #endif
121 121
122 /* hash in the new seed data */ 122 /* hash in the new seed data */
123 sha1_init(&hs); 123 sha256_init(&hs);
124 /* existing state (zeroes on startup) */ 124 /* existing state (zeroes on startup) */
125 sha1_process(&hs, (void*)hashpool, sizeof(hashpool)); 125 sha256_process(&hs, (void*)hashpool, sizeof(hashpool));
126 126
127 /* new */ 127 /* new */
128 sha1_process(&hs, buf, len); 128 sha256_process(&hs, buf, len);
129 sha1_done(&hs, hashpool); 129 sha256_done(&hs, hashpool);
130 } 130 }
131 131
132 static void write_urandom() 132 static void write_urandom()
133 { 133 {
134 #if DROPBEAR_FUZZ 134 #if DROPBEAR_FUZZ
150 } 150 }
151 151
152 #if DROPBEAR_FUZZ 152 #if DROPBEAR_FUZZ
153 void fuzz_seed(const unsigned char* dat, unsigned int len) { 153 void fuzz_seed(const unsigned char* dat, unsigned int len) {
154 hash_state hs; 154 hash_state hs;
155 sha1_init(&hs); 155 sha256_init(&hs);
156 sha1_process(&hs, "fuzzfuzzfuzz", strlen("fuzzfuzzfuzz")); 156 sha256_process(&hs, "fuzzfuzzfuzz", strlen("fuzzfuzzfuzz"));
157 sha1_process(&hs, dat, len); 157 sha256_process(&hs, dat, len);
158 sha1_done(&hs, hashpool); 158 sha256_done(&hs, hashpool);
159 counter = 0; 159 counter = 0;
160 donerandinit = 1; 160 donerandinit = 1;
161 } 161 }
162 #endif 162 #endif
163 163
207 break; 207 break;
208 } 208 }
209 209
210 if (ret == sizeof(buf)) { 210 if (ret == sizeof(buf)) {
211 /* Success, stir in the entropy */ 211 /* Success, stir in the entropy */
212 sha1_process(hs, (void*)buf, sizeof(buf)); 212 sha256_process(hs, (void*)buf, sizeof(buf));
213 return DROPBEAR_SUCCESS; 213 return DROPBEAR_SUCCESS;
214 } 214 }
215 215
216 return DROPBEAR_FAILURE; 216 return DROPBEAR_FAILURE;
217 217
219 #endif /* HAVE_GETRANDOM */ 219 #endif /* HAVE_GETRANDOM */
220 220
221 /* Initialise the prng from /dev/urandom or prngd. This function can 221 /* Initialise the prng from /dev/urandom or prngd. This function can
222 * be called multiple times */ 222 * be called multiple times */
223 void seedrandom() { 223 void seedrandom() {
224
225 hash_state hs; 224 hash_state hs;
226 225
227 pid_t pid; 226 pid_t pid;
228 struct timeval tv; 227 struct timeval tv;
229 clock_t clockval; 228 clock_t clockval;
234 return; 233 return;
235 } 234 }
236 #endif 235 #endif
237 236
238 /* hash in the new seed data */ 237 /* hash in the new seed data */
239 sha1_init(&hs); 238 sha256_init(&hs);
240 239
241 /* existing state */ 240 /* existing state */
242 sha1_process(&hs, (void*)hashpool, sizeof(hashpool)); 241 sha256_process(&hs, (void*)hashpool, sizeof(hashpool));
243 242
244 #ifdef HAVE_GETRANDOM 243 #ifdef HAVE_GETRANDOM
245 if (process_getrandom(&hs) == DROPBEAR_SUCCESS) { 244 if (process_getrandom(&hs) == DROPBEAR_SUCCESS) {
246 urandom_seeded = 1; 245 urandom_seeded = 1;
247 } 246 }
287 process_file(&hs, "/proc/net/rt_cache", 4096, 0); 286 process_file(&hs, "/proc/net/rt_cache", 4096, 0);
288 process_file(&hs, "/proc/vmstat", 0, 0); 287 process_file(&hs, "/proc/vmstat", 0, 0);
289 #endif 288 #endif
290 289
291 pid = getpid(); 290 pid = getpid();
292 sha1_process(&hs, (void*)&pid, sizeof(pid)); 291 sha256_process(&hs, (void*)&pid, sizeof(pid));
293 292
294 /* gettimeofday() doesn't completely fill out struct timeval on 293 /* gettimeofday() doesn't completely fill out struct timeval on
295 OS X (10.8.3), avoid valgrind warnings by clearing it first */ 294 OS X (10.8.3), avoid valgrind warnings by clearing it first */
296 memset(&tv, 0x0, sizeof(tv)); 295 memset(&tv, 0x0, sizeof(tv));
297 gettimeofday(&tv, NULL); 296 gettimeofday(&tv, NULL);
298 sha1_process(&hs, (void*)&tv, sizeof(tv)); 297 sha256_process(&hs, (void*)&tv, sizeof(tv));
299 298
300 clockval = clock(); 299 clockval = clock();
301 sha1_process(&hs, (void*)&clockval, sizeof(clockval)); 300 sha256_process(&hs, (void*)&clockval, sizeof(clockval));
302 301
303 /* When a private key is read by the client or server it will 302 /* When a private key is read by the client or server it will
304 * be added to the hashpool - see runopts.c */ 303 * be added to the hashpool - see runopts.c */
305 304
306 sha1_done(&hs, hashpool); 305 sha256_done(&hs, hashpool);
307 306
308 counter = 0; 307 counter = 0;
309 donerandinit = 1; 308 donerandinit = 1;
310 309
311 /* Feed it all back into /dev/urandom - this might help if Dropbear 310 /* Feed it all back into /dev/urandom - this might help if Dropbear
315 314
316 /* return len bytes of pseudo-random data */ 315 /* return len bytes of pseudo-random data */
317 void genrandom(unsigned char* buf, unsigned int len) { 316 void genrandom(unsigned char* buf, unsigned int len) {
318 317
319 hash_state hs; 318 hash_state hs;
320 unsigned char hash[SHA1_HASH_SIZE]; 319 unsigned char hash[SHA256_HASH_SIZE];
321 unsigned int copylen; 320 unsigned int copylen;
322 321
323 if (!donerandinit) { 322 if (!donerandinit) {
324 dropbear_exit("seedrandom not done"); 323 dropbear_exit("seedrandom not done");
325 } 324 }
326 325
327 while (len > 0) { 326 while (len > 0) {
328 sha1_init(&hs); 327 sha256_init(&hs);
329 sha1_process(&hs, (void*)hashpool, sizeof(hashpool)); 328 sha256_process(&hs, (void*)hashpool, sizeof(hashpool));
330 sha1_process(&hs, (void*)&counter, sizeof(counter)); 329 sha256_process(&hs, (void*)&counter, sizeof(counter));
331 sha1_done(&hs, hash); 330 sha256_done(&hs, hash);
332 331
333 counter++; 332 counter++;
334 if (counter > MAX_COUNTER) { 333 if (counter > MAX_COUNTER) {
335 seedrandom(); 334 seedrandom();
336 } 335 }
337 336
338 copylen = MIN(len, SHA1_HASH_SIZE); 337 copylen = MIN(len, SHA256_HASH_SIZE);
339 memcpy(buf, hash, copylen); 338 memcpy(buf, hash, copylen);
340 len -= copylen; 339 len -= copylen;
341 buf += copylen; 340 buf += copylen;
342 } 341 }
343 m_burn(hash, sizeof(hash)); 342 m_burn(hash, sizeof(hash));