@@ -30,6 +30,11 @@ static int osrandom_init(ENGINE *e) {
30
30
PROV_RSA_FULL , CRYPT_VERIFYCONTEXT )) {
31
31
return 1 ;
32
32
} else {
33
+ ERR_Cryptography_OSRandom_error (
34
+ CRYPTOGRAPHY_OSRANDOM_F_INIT ,
35
+ CRYPTOGRAPHY_OSRANDOM_R_CRYPTACQUIRECONTEXT ,
36
+ __FILE__ , __LINE__
37
+ );
33
38
return 0 ;
34
39
}
35
40
}
@@ -40,8 +45,11 @@ static int osrandom_rand_bytes(unsigned char *buffer, int size) {
40
45
}
41
46
42
47
if (!CryptGenRandom (hCryptProv , (DWORD )size , buffer )) {
43
- CRYPTOGRAPHY_OSRANDOM_put_error (
44
- "osrandom_engine.py:CryptGenRandom()" );
48
+ ERR_Cryptography_OSRandom_error (
49
+ CRYPTOGRAPHY_OSRANDOM_F_RAND_BYTES ,
50
+ CRYPTOGRAPHY_OSRANDOM_R_CRYPTGENRANDOM ,
51
+ __FILE__ , __LINE__
52
+ );
45
53
return 0 ;
46
54
}
47
55
return 1 ;
@@ -52,6 +60,11 @@ static int osrandom_finish(ENGINE *e) {
52
60
hCryptProv = 0 ;
53
61
return 1 ;
54
62
} else {
63
+ ERR_Cryptography_OSRandom_error (
64
+ CRYPTOGRAPHY_OSRANDOM_F_FINISH ,
65
+ CRYPTOGRAPHY_OSRANDOM_R_CRYPTRELEASECONTEXT ,
66
+ __FILE__ , __LINE__
67
+ );
55
68
return 0 ;
56
69
}
57
70
}
@@ -83,8 +96,11 @@ static int osrandom_rand_bytes(unsigned char *buffer, int size) {
83
96
len = size > 256 ? 256 : size ;
84
97
res = getentropy (buffer , len );
85
98
if (res < 0 ) {
86
- CRYPTOGRAPHY_OSRANDOM_put_error (
87
- "osrandom_engine.py:getentropy()" );
99
+ ERR_Cryptography_OSRandom_error (
100
+ CRYPTOGRAPHY_OSRANDOM_F_RAND_BYTES ,
101
+ CRYPTOGRAPHY_OSRANDOM_R_GETENTROPY_FAILED ,
102
+ __FILE__ , __LINE__
103
+ );
88
104
return 0 ;
89
105
}
90
106
buffer += len ;
@@ -166,8 +182,11 @@ static int dev_urandom_fd(void) {
166
182
n = close (fd );
167
183
} while (n < 0 && errno == EINTR );
168
184
}
169
- CRYPTOGRAPHY_OSRANDOM_put_error (
170
- "osrandom_engine.py:dev_urandom_fd()" );
185
+ ERR_Cryptography_OSRandom_error (
186
+ CRYPTOGRAPHY_OSRANDOM_F_DEV_URANDOM_FD ,
187
+ CRYPTOGRAPHY_OSRANDOM_R_DEV_URANDOM_OPEN_FAILED ,
188
+ __FILE__ , __LINE__
189
+ );
171
190
return -1 ;
172
191
}
173
192
@@ -186,8 +205,11 @@ static int dev_urandom_read(unsigned char *buffer, int size) {
186
205
} while (n < 0 && errno == EINTR );
187
206
188
207
if (n <= 0 ) {
189
- CRYPTOGRAPHY_OSRANDOM_put_error (
190
- "osrandom_engine.py:dev_urandom_read()" );
208
+ ERR_Cryptography_OSRandom_error (
209
+ CRYPTOGRAPHY_OSRANDOM_F_DEV_URANDOM_READ ,
210
+ CRYPTOGRAPHY_OSRANDOM_R_DEV_URANDOM_READ_FAILED ,
211
+ __FILE__ , __LINE__
212
+ );
191
213
return 0 ;
192
214
}
193
215
buffer += n ;
@@ -221,28 +243,51 @@ static void dev_urandom_close(void) {
221
243
#if CRYPTOGRAPHY_OSRANDOM_ENGINE == CRYPTOGRAPHY_OSRANDOM_ENGINE_GETRANDOM
222
244
static const char * Cryptography_osrandom_engine_name = "osrandom_engine getrandom()" ;
223
245
224
- static int getrandom_works = -1 ;
246
+ static int getrandom_works = CRYPTOGRAPHY_OSRANDOM_GETRANDOM_NOT_INIT ;
225
247
226
248
static int osrandom_init (ENGINE * e ) {
227
249
/* We try to detect working getrandom until we succeed. */
228
- if (getrandom_works != 1 ) {
250
+ if (getrandom_works != CRYPTOGRAPHY_OSRANDOM_GETRANDOM_WORKS ) {
229
251
long n ;
230
252
char dest [1 ];
231
253
n = syscall (SYS_getrandom , dest , sizeof (dest ), GRND_NONBLOCK );
232
- if (n < 0 ) {
233
- /* Can fail with:
234
- * - ENOSYS: Kernel does not support the syscall.
235
- * - ENOPERM: seccomp prevents syscall.
236
- * - EAGAIN: Kernel CRPNG has not been seeded yet.
237
- * EINTR cannot occur for buflen < 256.
238
- */
239
- getrandom_works = 0 ;
254
+ if (n == sizeof (dest )) {
255
+ getrandom_works = CRYPTOGRAPHY_OSRANDOM_GETRANDOM_WORKS ;
240
256
} else {
241
- getrandom_works = 1 ;
257
+ int e = errno ;
258
+ switch (e ) {
259
+ case ENOSYS :
260
+ /* Fallback: Kernel does not support the syscall. */
261
+ getrandom_works = CRYPTOGRAPHY_OSRANDOM_GETRANDOM_FALLBACK ;
262
+ break ;
263
+ case EPERM :
264
+ /* Fallback: seccomp prevents syscall */
265
+ getrandom_works = CRYPTOGRAPHY_OSRANDOM_GETRANDOM_FALLBACK ;
266
+ break ;
267
+ case EAGAIN :
268
+ /* Failure: Kernel CRPNG has not been seeded yet */
269
+ ERR_Cryptography_OSRandom_error (
270
+ CRYPTOGRAPHY_OSRANDOM_F_INIT ,
271
+ CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_INIT_FAILED_EAGAIN ,
272
+ __FILE__ , __LINE__
273
+ );
274
+ getrandom_works = CRYPTOGRAPHY_OSRANDOM_GETRANDOM_INIT_FAILED ;
275
+ break ;
276
+ default :
277
+ /* EINTR cannot occur for buflen < 256. */
278
+ ERR_Cryptography_OSRandom_error (
279
+ CRYPTOGRAPHY_OSRANDOM_F_INIT ,
280
+ CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_INIT_FAILED_UNEXPECTED ,
281
+ "errno" , e
282
+ );
283
+ getrandom_works = CRYPTOGRAPHY_OSRANDOM_GETRANDOM_INIT_FAILED ;
284
+ break ;
285
+ }
242
286
}
243
287
}
288
+
244
289
/* fallback to dev urandom */
245
- if (getrandom_works == 0 ) {
290
+ if (getrandom_works == CRYPTOGRAPHY_OSRANDOM_GETRANDOM_FALLBACK ) {
246
291
int fd = dev_urandom_fd ();
247
292
if (fd < 0 ) {
248
293
return 0 ;
@@ -252,25 +297,45 @@ static int osrandom_init(ENGINE *e) {
252
297
}
253
298
254
299
static int osrandom_rand_bytes (unsigned char * buffer , int size ) {
255
- if (getrandom_works == 1 ) {
256
- long n ;
300
+ long n ;
301
+
302
+ switch (getrandom_works ) {
303
+ case CRYPTOGRAPHY_OSRANDOM_GETRANDOM_INIT_FAILED :
304
+ ERR_Cryptography_OSRandom_error (
305
+ CRYPTOGRAPHY_OSRANDOM_F_RAND_BYTES ,
306
+ CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_INIT_FAILED ,
307
+ __FILE__ , __LINE__
308
+ );
309
+ return 0 ;
310
+ case CRYPTOGRAPHY_OSRANDOM_GETRANDOM_NOT_INIT :
311
+ ERR_Cryptography_OSRandom_error (
312
+ CRYPTOGRAPHY_OSRANDOM_F_RAND_BYTES ,
313
+ CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_NOT_INIT ,
314
+ __FILE__ , __LINE__
315
+ );
316
+ return 0 ;
317
+ case CRYPTOGRAPHY_OSRANDOM_GETRANDOM_FALLBACK :
318
+ return dev_urandom_read (buffer , size );
319
+ case CRYPTOGRAPHY_OSRANDOM_GETRANDOM_WORKS :
257
320
while (size > 0 ) {
258
321
do {
259
322
n = syscall (SYS_getrandom , buffer , size , GRND_NONBLOCK );
260
323
} while (n < 0 && errno == EINTR );
261
324
262
325
if (n <= 0 ) {
263
- CRYPTOGRAPHY_OSRANDOM_put_error (
264
- "osrandom_engine.py:SYS_getrandom" );
326
+ ERR_Cryptography_OSRandom_error (
327
+ CRYPTOGRAPHY_OSRANDOM_F_RAND_BYTES ,
328
+ CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_FAILED ,
329
+ __FILE__ , __LINE__
330
+ );
265
331
return 0 ;
266
332
}
267
333
buffer += n ;
268
334
size -= n ;
269
335
}
270
336
return 1 ;
271
- } else {
272
- return dev_urandom_read (buffer , size );
273
337
}
338
+ return 0 ; /* unreachable */
274
339
}
275
340
276
341
static int osrandom_finish (ENGINE * e ) {
@@ -279,17 +344,31 @@ static int osrandom_finish(ENGINE *e) {
279
344
}
280
345
281
346
static int osrandom_rand_status (void ) {
282
- if ((getrandom_works != 1 ) && (urandom_cache .fd < 0 )) {
347
+ switch (getrandom_works ) {
348
+ case CRYPTOGRAPHY_OSRANDOM_GETRANDOM_INIT_FAILED :
349
+ return 0 ;
350
+ case CRYPTOGRAPHY_OSRANDOM_GETRANDOM_NOT_INIT :
283
351
return 0 ;
352
+ case CRYPTOGRAPHY_OSRANDOM_GETRANDOM_FALLBACK :
353
+ return urandom_cache .fd >= 0 ;
354
+ case CRYPTOGRAPHY_OSRANDOM_GETRANDOM_WORKS :
355
+ return 1 ;
284
356
}
285
- return 1 ;
357
+ return 0 ; /* unreachable */
286
358
}
287
359
288
360
static const char * osurandom_get_implementation (void ) {
289
- if (getrandom_works == 1 ) {
361
+ switch (getrandom_works ) {
362
+ case CRYPTOGRAPHY_OSRANDOM_GETRANDOM_INIT_FAILED :
363
+ return "<failed>" ;
364
+ case CRYPTOGRAPHY_OSRANDOM_GETRANDOM_NOT_INIT :
365
+ return "<not initialized>" ;
366
+ case CRYPTOGRAPHY_OSRANDOM_GETRANDOM_FALLBACK :
367
+ return "/dev/urandom" ;
368
+ case CRYPTOGRAPHY_OSRANDOM_GETRANDOM_WORKS :
290
369
return "getrandom" ;
291
370
}
292
- return "/dev/urandom" ;
371
+ return "<invalid>" ; /* unreachable */
293
372
}
294
373
#endif /* CRYPTOGRAPHY_OSRANDOM_ENGINE_GETRANDOM */
295
374
@@ -384,10 +463,85 @@ static int osrandom_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
384
463
}
385
464
}
386
465
466
+ /* error reporting */
467
+ #define ERR_FUNC (func ) ERR_PACK(0, func, 0)
468
+ #define ERR_REASON (reason ) ERR_PACK(0, 0, reason)
469
+
470
+ static ERR_STRING_DATA CRYPTOGRAPHY_OSRANDOM_lib_name [] = {
471
+ {0 , "osrandom_engine" },
472
+ {0 , NULL }
473
+ };
474
+
475
+ static ERR_STRING_DATA CRYPTOGRAPHY_OSRANDOM_str_funcs [] = {
476
+ {ERR_FUNC (CRYPTOGRAPHY_OSRANDOM_F_INIT ),
477
+ "osrandom_init" },
478
+ {ERR_FUNC (CRYPTOGRAPHY_OSRANDOM_F_RAND_BYTES ),
479
+ "osrandom_rand_bytes" },
480
+ {ERR_FUNC (CRYPTOGRAPHY_OSRANDOM_F_FINISH ),
481
+ "osrandom_finish" },
482
+ {ERR_FUNC (CRYPTOGRAPHY_OSRANDOM_F_DEV_URANDOM_FD ),
483
+ "dev_urandom_fd" },
484
+ {ERR_FUNC (CRYPTOGRAPHY_OSRANDOM_F_DEV_URANDOM_READ ),
485
+ "dev_urandom_read" },
486
+ {0 , NULL }
487
+ };
488
+
489
+ static ERR_STRING_DATA CRYPTOGRAPHY_OSRANDOM_str_reasons [] = {
490
+ {ERR_REASON (CRYPTOGRAPHY_OSRANDOM_R_CRYPTACQUIRECONTEXT ),
491
+ "CryptAcquireContext() failed." },
492
+ {ERR_REASON (CRYPTOGRAPHY_OSRANDOM_R_CRYPTGENRANDOM ),
493
+ "CryptGenRandom() failed." },
494
+ {ERR_REASON (CRYPTOGRAPHY_OSRANDOM_R_CRYPTRELEASECONTEXT ),
495
+ "CryptReleaseContext() failed." },
496
+ {ERR_REASON (CRYPTOGRAPHY_OSRANDOM_R_GETENTROPY_FAILED ),
497
+ "getentropy() failed" },
498
+ {ERR_REASON (CRYPTOGRAPHY_OSRANDOM_R_DEV_URANDOM_OPEN_FAILED ),
499
+ "open('/dev/urandom') failed." },
500
+ {ERR_REASON (CRYPTOGRAPHY_OSRANDOM_R_DEV_URANDOM_READ_FAILED ),
501
+ "Reading from /dev/urandom fd failed." },
502
+ {ERR_REASON (CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_INIT_FAILED ),
503
+ "getrandom() initialization failed." },
504
+ {ERR_REASON (CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_INIT_FAILED_EAGAIN ),
505
+ "getrandom() initialization failed with EAGAIN. Most likely Kernel "
506
+ "CPRNG is not seeded yet." },
507
+ {ERR_REASON (CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_INIT_FAILED_UNEXPECTED ),
508
+ "getrandom() initialization failed with unexpected errno." },
509
+ {ERR_REASON (CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_FAILED ),
510
+ "getrandom() syscall failed." },
511
+ {ERR_REASON (CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_NOT_INIT ),
512
+ "getrandom() engine was not properly initialized." },
513
+ {0 , NULL }
514
+ };
515
+
516
+ static int Cryptography_OSRandom_lib_error_code = 0 ;
517
+
518
+ static void ERR_load_Cryptography_OSRandom_strings (void )
519
+ {
520
+ if (Cryptography_OSRandom_lib_error_code == 0 ) {
521
+ Cryptography_OSRandom_lib_error_code = ERR_get_next_error_library ();
522
+ ERR_load_strings (Cryptography_OSRandom_lib_error_code ,
523
+ CRYPTOGRAPHY_OSRANDOM_lib_name );
524
+ ERR_load_strings (Cryptography_OSRandom_lib_error_code ,
525
+ CRYPTOGRAPHY_OSRANDOM_str_funcs );
526
+ ERR_load_strings (Cryptography_OSRandom_lib_error_code ,
527
+ CRYPTOGRAPHY_OSRANDOM_str_reasons );
528
+ }
529
+ }
530
+
531
+ static void ERR_Cryptography_OSRandom_error (int function , int reason ,
532
+ char * file , int line )
533
+ {
534
+ ERR_PUT_error (Cryptography_OSRandom_lib_error_code , function , reason ,
535
+ file , line );
536
+ }
537
+
387
538
/* Returns 1 if successfully added, 2 if engine has previously been added,
388
539
and 0 for error. */
389
540
int Cryptography_add_osrandom_engine (void ) {
390
541
ENGINE * e ;
542
+
543
+ ERR_load_Cryptography_OSRandom_strings ();
544
+
391
545
e = ENGINE_by_id (Cryptography_osrandom_engine_id );
392
546
if (e != NULL ) {
393
547
ENGINE_free (e );
0 commit comments