1 | /* |
2 | * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. |
3 | * |
4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
5 | * this file except in compliance with the License. You can obtain a copy |
6 | * in the file LICENSE in the source distribution or at |
7 | * https://www.openssl.org/source/license.html |
8 | */ |
9 | |
10 | #include "e_os.h" |
11 | |
12 | #if defined(OPENSSL_SYS_VMS) |
13 | # define __NEW_STARLET 1 /* New starlet definitions since VMS 7.0 */ |
14 | # include <unistd.h> |
15 | # include "internal/cryptlib.h" |
16 | # include <openssl/rand.h> |
17 | # include "crypto/rand.h" |
18 | # include "rand_local.h" |
19 | # include <descrip.h> |
20 | # include <dvidef.h> |
21 | # include <jpidef.h> |
22 | # include <rmidef.h> |
23 | # include <syidef.h> |
24 | # include <ssdef.h> |
25 | # include <starlet.h> |
26 | # include <efndef.h> |
27 | # include <gen64def.h> |
28 | # include <iosbdef.h> |
29 | # include <iledef.h> |
30 | # include <lib$routines.h> |
31 | # ifdef __DECC |
32 | # pragma message disable DOLLARID |
33 | # endif |
34 | |
35 | # include <dlfcn.h> /* SYS$GET_ENTROPY presence */ |
36 | |
37 | # ifndef OPENSSL_RAND_SEED_OS |
38 | # error "Unsupported seeding method configured; must be os" |
39 | # endif |
40 | |
41 | /* |
42 | * DATA COLLECTION METHOD |
43 | * ====================== |
44 | * |
45 | * This is a method to get low quality entropy. |
46 | * It works by collecting all kinds of statistical data that |
47 | * VMS offers and using them as random seed. |
48 | */ |
49 | |
50 | /* We need to make sure we have the right size pointer in some cases */ |
51 | # if __INITIAL_POINTER_SIZE == 64 |
52 | # pragma pointer_size save |
53 | # pragma pointer_size 32 |
54 | # endif |
55 | typedef uint32_t *uint32_t__ptr32; |
56 | # if __INITIAL_POINTER_SIZE == 64 |
57 | # pragma pointer_size restore |
58 | # endif |
59 | |
60 | struct item_st { |
61 | short length, code; /* length is number of bytes */ |
62 | }; |
63 | |
64 | static const struct item_st DVI_item_data[] = { |
65 | {4, DVI$_ERRCNT}, |
66 | {4, DVI$_REFCNT}, |
67 | }; |
68 | |
69 | static const struct item_st JPI_item_data[] = { |
70 | {4, JPI$_BUFIO}, |
71 | {4, JPI$_CPUTIM}, |
72 | {4, JPI$_DIRIO}, |
73 | {4, JPI$_IMAGECOUNT}, |
74 | {4, JPI$_PAGEFLTS}, |
75 | {4, JPI$_PID}, |
76 | {4, JPI$_PPGCNT}, |
77 | {4, JPI$_WSPEAK}, |
78 | /* |
79 | * Note: the direct result is just a 32-bit address. However, it points |
80 | * to a list of 4 32-bit words, so we make extra space for them so we can |
81 | * do in-place replacement of values |
82 | */ |
83 | {16, JPI$_FINALEXC}, |
84 | }; |
85 | |
86 | static const struct item_st JPI_item_data_64bit[] = { |
87 | {8, JPI$_LAST_LOGIN_I}, |
88 | {8, JPI$_LOGINTIM}, |
89 | }; |
90 | |
91 | static const struct item_st RMI_item_data[] = { |
92 | {4, RMI$_COLPG}, |
93 | {4, RMI$_MWAIT}, |
94 | {4, RMI$_CEF}, |
95 | {4, RMI$_PFW}, |
96 | {4, RMI$_LEF}, |
97 | {4, RMI$_LEFO}, |
98 | {4, RMI$_HIB}, |
99 | {4, RMI$_HIBO}, |
100 | {4, RMI$_SUSP}, |
101 | {4, RMI$_SUSPO}, |
102 | {4, RMI$_FPG}, |
103 | {4, RMI$_COM}, |
104 | {4, RMI$_COMO}, |
105 | {4, RMI$_CUR}, |
106 | #if defined __alpha |
107 | {4, RMI$_FRLIST}, |
108 | {4, RMI$_MODLIST}, |
109 | #endif |
110 | {4, RMI$_FAULTS}, |
111 | {4, RMI$_PREADS}, |
112 | {4, RMI$_PWRITES}, |
113 | {4, RMI$_PWRITIO}, |
114 | {4, RMI$_PREADIO}, |
115 | {4, RMI$_GVALFLTS}, |
116 | {4, RMI$_WRTINPROG}, |
117 | {4, RMI$_FREFLTS}, |
118 | {4, RMI$_DZROFLTS}, |
119 | {4, RMI$_SYSFAULTS}, |
120 | {4, RMI$_ISWPCNT}, |
121 | {4, RMI$_DIRIO}, |
122 | {4, RMI$_BUFIO}, |
123 | {4, RMI$_MBREADS}, |
124 | {4, RMI$_MBWRITES}, |
125 | {4, RMI$_LOGNAM}, |
126 | {4, RMI$_FCPCALLS}, |
127 | {4, RMI$_FCPREAD}, |
128 | {4, RMI$_FCPWRITE}, |
129 | {4, RMI$_FCPCACHE}, |
130 | {4, RMI$_FCPCPU}, |
131 | {4, RMI$_FCPHIT}, |
132 | {4, RMI$_FCPSPLIT}, |
133 | {4, RMI$_FCPFAULT}, |
134 | {4, RMI$_ENQNEW}, |
135 | {4, RMI$_ENQCVT}, |
136 | {4, RMI$_DEQ}, |
137 | {4, RMI$_BLKAST}, |
138 | {4, RMI$_ENQWAIT}, |
139 | {4, RMI$_ENQNOTQD}, |
140 | {4, RMI$_DLCKSRCH}, |
141 | {4, RMI$_DLCKFND}, |
142 | {4, RMI$_NUMLOCKS}, |
143 | {4, RMI$_NUMRES}, |
144 | {4, RMI$_ARRLOCPK}, |
145 | {4, RMI$_DEPLOCPK}, |
146 | {4, RMI$_ARRTRAPK}, |
147 | {4, RMI$_TRCNGLOS}, |
148 | {4, RMI$_RCVBUFFL}, |
149 | {4, RMI$_ENQNEWLOC}, |
150 | {4, RMI$_ENQNEWIN}, |
151 | {4, RMI$_ENQNEWOUT}, |
152 | {4, RMI$_ENQCVTLOC}, |
153 | {4, RMI$_ENQCVTIN}, |
154 | {4, RMI$_ENQCVTOUT}, |
155 | {4, RMI$_DEQLOC}, |
156 | {4, RMI$_DEQIN}, |
157 | {4, RMI$_DEQOUT}, |
158 | {4, RMI$_BLKLOC}, |
159 | {4, RMI$_BLKIN}, |
160 | {4, RMI$_BLKOUT}, |
161 | {4, RMI$_DIRIN}, |
162 | {4, RMI$_DIROUT}, |
163 | /* We currently get a fault when trying these. TODO: To be figured out. */ |
164 | #if 0 |
165 | {140, RMI$_MSCP_EVERYTHING}, /* 35 32-bit words */ |
166 | {152, RMI$_DDTM_ALL}, /* 38 32-bit words */ |
167 | {80, RMI$_TMSCP_EVERYTHING} /* 20 32-bit words */ |
168 | #endif |
169 | {4, RMI$_LPZ_PAGCNT}, |
170 | {4, RMI$_LPZ_HITS}, |
171 | {4, RMI$_LPZ_MISSES}, |
172 | {4, RMI$_LPZ_EXPCNT}, |
173 | {4, RMI$_LPZ_ALLOCF}, |
174 | {4, RMI$_LPZ_ALLOC2}, |
175 | {4, RMI$_ACCESS}, |
176 | {4, RMI$_ALLOC}, |
177 | {4, RMI$_FCPCREATE}, |
178 | {4, RMI$_VOLWAIT}, |
179 | {4, RMI$_FCPTURN}, |
180 | {4, RMI$_FCPERASE}, |
181 | {4, RMI$_OPENS}, |
182 | {4, RMI$_FIDHIT}, |
183 | {4, RMI$_FIDMISS}, |
184 | {4, RMI$_FILHDR_HIT}, |
185 | {4, RMI$_DIRFCB_HIT}, |
186 | {4, RMI$_DIRFCB_MISS}, |
187 | {4, RMI$_DIRDATA_HIT}, |
188 | {4, RMI$_EXTHIT}, |
189 | {4, RMI$_EXTMISS}, |
190 | {4, RMI$_QUOHIT}, |
191 | {4, RMI$_QUOMISS}, |
192 | {4, RMI$_STORAGMAP_HIT}, |
193 | {4, RMI$_VOLLCK}, |
194 | {4, RMI$_SYNCHLCK}, |
195 | {4, RMI$_SYNCHWAIT}, |
196 | {4, RMI$_ACCLCK}, |
197 | {4, RMI$_XQPCACHEWAIT}, |
198 | {4, RMI$_DIRDATA_MISS}, |
199 | {4, RMI$_FILHDR_MISS}, |
200 | {4, RMI$_STORAGMAP_MISS}, |
201 | {4, RMI$_PROCCNTMAX}, |
202 | {4, RMI$_PROCBATCNT}, |
203 | {4, RMI$_PROCINTCNT}, |
204 | {4, RMI$_PROCNETCNT}, |
205 | {4, RMI$_PROCSWITCHCNT}, |
206 | {4, RMI$_PROCBALSETCNT}, |
207 | {4, RMI$_PROCLOADCNT}, |
208 | {4, RMI$_BADFLTS}, |
209 | {4, RMI$_EXEFAULTS}, |
210 | {4, RMI$_HDRINSWAPS}, |
211 | {4, RMI$_HDROUTSWAPS}, |
212 | {4, RMI$_IOPAGCNT}, |
213 | {4, RMI$_ISWPCNTPG}, |
214 | {4, RMI$_OSWPCNT}, |
215 | {4, RMI$_OSWPCNTPG}, |
216 | {4, RMI$_RDFAULTS}, |
217 | {4, RMI$_TRANSFLTS}, |
218 | {4, RMI$_WRTFAULTS}, |
219 | #if defined __alpha |
220 | {4, RMI$_USERPAGES}, |
221 | #endif |
222 | {4, RMI$_VMSPAGES}, |
223 | {4, RMI$_TTWRITES}, |
224 | {4, RMI$_BUFOBJPAG}, |
225 | {4, RMI$_BUFOBJPAGPEAK}, |
226 | {4, RMI$_BUFOBJPAGS01}, |
227 | {4, RMI$_BUFOBJPAGS2}, |
228 | {4, RMI$_BUFOBJPAGMAXS01}, |
229 | {4, RMI$_BUFOBJPAGMAXS2}, |
230 | {4, RMI$_BUFOBJPAGPEAKS01}, |
231 | {4, RMI$_BUFOBJPAGPEAKS2}, |
232 | {4, RMI$_BUFOBJPGLTMAXS01}, |
233 | {4, RMI$_BUFOBJPGLTMAXS2}, |
234 | {4, RMI$_DLCK_INCMPLT}, |
235 | {4, RMI$_DLCKMSGS_IN}, |
236 | {4, RMI$_DLCKMSGS_OUT}, |
237 | {4, RMI$_MCHKERRS}, |
238 | {4, RMI$_MEMERRS}, |
239 | }; |
240 | |
241 | static const struct item_st RMI_item_data_64bit[] = { |
242 | #if defined __ia64 |
243 | {8, RMI$_FRLIST}, |
244 | {8, RMI$_MODLIST}, |
245 | #endif |
246 | {8, RMI$_LCKMGR_REQCNT}, |
247 | {8, RMI$_LCKMGR_REQTIME}, |
248 | {8, RMI$_LCKMGR_SPINCNT}, |
249 | {8, RMI$_LCKMGR_SPINTIME}, |
250 | {8, RMI$_CPUINTSTK}, |
251 | {8, RMI$_CPUMPSYNCH}, |
252 | {8, RMI$_CPUKERNEL}, |
253 | {8, RMI$_CPUEXEC}, |
254 | {8, RMI$_CPUSUPER}, |
255 | {8, RMI$_CPUUSER}, |
256 | #if defined __ia64 |
257 | {8, RMI$_USERPAGES}, |
258 | #endif |
259 | {8, RMI$_TQETOTAL}, |
260 | {8, RMI$_TQESYSUB}, |
261 | {8, RMI$_TQEUSRTIMR}, |
262 | {8, RMI$_TQEUSRWAKE}, |
263 | }; |
264 | |
265 | static const struct item_st SYI_item_data[] = { |
266 | {4, SYI$_PAGEFILE_FREE}, |
267 | }; |
268 | |
269 | /* |
270 | * Input: |
271 | * items_data - an array of lengths and codes |
272 | * items_data_num - number of elements in that array |
273 | * |
274 | * Output: |
275 | * items - pre-allocated ILE3 array to be filled. |
276 | * It's assumed to have items_data_num elements plus |
277 | * one extra for the terminating NULL element |
278 | * databuffer - pre-allocated 32-bit word array. |
279 | * |
280 | * Returns the number of elements used in databuffer |
281 | */ |
282 | static size_t prepare_item_list(const struct item_st *items_input, |
283 | size_t items_input_num, |
284 | ILE3 *items, |
285 | uint32_t__ptr32 databuffer) |
286 | { |
287 | size_t data_sz = 0; |
288 | |
289 | for (; items_input_num-- > 0; items_input++, items++) { |
290 | |
291 | items->ile3$w_code = items_input->code; |
292 | /* Special treatment of JPI$_FINALEXC */ |
293 | if (items->ile3$w_code == JPI$_FINALEXC) |
294 | items->ile3$w_length = 4; |
295 | else |
296 | items->ile3$w_length = items_input->length; |
297 | |
298 | items->ile3$ps_bufaddr = databuffer; |
299 | items->ile3$ps_retlen_addr = 0; |
300 | |
301 | databuffer += items_input->length / sizeof(databuffer[0]); |
302 | data_sz += items_input->length; |
303 | } |
304 | /* Terminating NULL entry */ |
305 | items->ile3$w_length = items->ile3$w_code = 0; |
306 | items->ile3$ps_bufaddr = items->ile3$ps_retlen_addr = NULL; |
307 | |
308 | return data_sz / sizeof(databuffer[0]); |
309 | } |
310 | |
311 | static void massage_JPI(ILE3 *items) |
312 | { |
313 | /* |
314 | * Special treatment of JPI$_FINALEXC |
315 | * The result of that item's data buffer is a 32-bit address to a list of |
316 | * 4 32-bit words. |
317 | */ |
318 | for (; items->ile3$w_length != 0; items++) { |
319 | if (items->ile3$w_code == JPI$_FINALEXC) { |
320 | uint32_t *data = items->ile3$ps_bufaddr; |
321 | uint32_t *ptr = (uint32_t *)*data; |
322 | size_t j; |
323 | |
324 | /* |
325 | * We know we made space for 4 32-bit words, so we can do in-place |
326 | * replacement. |
327 | */ |
328 | for (j = 0; j < 4; j++) |
329 | data[j] = ptr[j]; |
330 | |
331 | break; |
332 | } |
333 | } |
334 | } |
335 | |
336 | /* |
337 | * This number expresses how many bits of data contain 1 bit of entropy. |
338 | * |
339 | * For the moment, we assume about 0.05 entropy bits per data bit, or 1 |
340 | * bit of entropy per 20 data bits. |
341 | */ |
342 | #define ENTROPY_FACTOR 20 |
343 | |
344 | size_t data_collect_method(RAND_POOL *pool) |
345 | { |
346 | ILE3 JPI_items_64bit[OSSL_NELEM(JPI_item_data_64bit) + 1]; |
347 | ILE3 RMI_items_64bit[OSSL_NELEM(RMI_item_data_64bit) + 1]; |
348 | ILE3 DVI_items[OSSL_NELEM(DVI_item_data) + 1]; |
349 | ILE3 JPI_items[OSSL_NELEM(JPI_item_data) + 1]; |
350 | ILE3 RMI_items[OSSL_NELEM(RMI_item_data) + 1]; |
351 | ILE3 SYI_items[OSSL_NELEM(SYI_item_data) + 1]; |
352 | union { |
353 | /* This ensures buffer starts at 64 bit boundary */ |
354 | uint64_t dummy; |
355 | uint32_t buffer[OSSL_NELEM(JPI_item_data_64bit) * 2 |
356 | + OSSL_NELEM(RMI_item_data_64bit) * 2 |
357 | + OSSL_NELEM(DVI_item_data) |
358 | + OSSL_NELEM(JPI_item_data) |
359 | + OSSL_NELEM(RMI_item_data) |
360 | + OSSL_NELEM(SYI_item_data) |
361 | + 4 /* For JPI$_FINALEXC */]; |
362 | } data; |
363 | size_t total_elems = 0; |
364 | size_t total_length = 0; |
365 | size_t bytes_needed = rand_pool_bytes_needed(pool, ENTROPY_FACTOR); |
366 | size_t bytes_remaining = rand_pool_bytes_remaining(pool); |
367 | |
368 | /* Take all the 64-bit items first, to ensure proper alignment of data */ |
369 | total_elems += |
370 | prepare_item_list(JPI_item_data_64bit, OSSL_NELEM(JPI_item_data_64bit), |
371 | JPI_items_64bit, &data.buffer[total_elems]); |
372 | total_elems += |
373 | prepare_item_list(RMI_item_data_64bit, OSSL_NELEM(RMI_item_data_64bit), |
374 | RMI_items_64bit, &data.buffer[total_elems]); |
375 | /* Now the 32-bit items */ |
376 | total_elems += prepare_item_list(DVI_item_data, OSSL_NELEM(DVI_item_data), |
377 | DVI_items, &data.buffer[total_elems]); |
378 | total_elems += prepare_item_list(JPI_item_data, OSSL_NELEM(JPI_item_data), |
379 | JPI_items, &data.buffer[total_elems]); |
380 | total_elems += prepare_item_list(RMI_item_data, OSSL_NELEM(RMI_item_data), |
381 | RMI_items, &data.buffer[total_elems]); |
382 | total_elems += prepare_item_list(SYI_item_data, OSSL_NELEM(SYI_item_data), |
383 | SYI_items, &data.buffer[total_elems]); |
384 | total_length = total_elems * sizeof(data.buffer[0]); |
385 | |
386 | /* Fill data.buffer with various info bits from this process */ |
387 | { |
388 | uint32_t status; |
389 | uint32_t efn; |
390 | IOSB iosb; |
391 | $DESCRIPTOR(SYSDEVICE,"SYS$SYSDEVICE:" ); |
392 | |
393 | if ((status = sys$getdviw(EFN$C_ENF, 0, &SYSDEVICE, DVI_items, |
394 | 0, 0, 0, 0, 0)) != SS$_NORMAL) { |
395 | lib$signal(status); |
396 | return 0; |
397 | } |
398 | if ((status = sys$getjpiw(EFN$C_ENF, 0, 0, JPI_items_64bit, 0, 0, 0)) |
399 | != SS$_NORMAL) { |
400 | lib$signal(status); |
401 | return 0; |
402 | } |
403 | if ((status = sys$getjpiw(EFN$C_ENF, 0, 0, JPI_items, 0, 0, 0)) |
404 | != SS$_NORMAL) { |
405 | lib$signal(status); |
406 | return 0; |
407 | } |
408 | if ((status = sys$getsyiw(EFN$C_ENF, 0, 0, SYI_items, 0, 0, 0)) |
409 | != SS$_NORMAL) { |
410 | lib$signal(status); |
411 | return 0; |
412 | } |
413 | /* |
414 | * The RMI service is a bit special, as there is no synchronous |
415 | * variant, so we MUST create an event flag to synchronise on. |
416 | */ |
417 | if ((status = lib$get_ef(&efn)) != SS$_NORMAL) { |
418 | lib$signal(status); |
419 | return 0; |
420 | } |
421 | if ((status = sys$getrmi(efn, 0, 0, RMI_items_64bit, &iosb, 0, 0)) |
422 | != SS$_NORMAL) { |
423 | lib$signal(status); |
424 | return 0; |
425 | } |
426 | if ((status = sys$synch(efn, &iosb)) != SS$_NORMAL) { |
427 | lib$signal(status); |
428 | return 0; |
429 | } |
430 | if (iosb.iosb$l_getxxi_status != SS$_NORMAL) { |
431 | lib$signal(iosb.iosb$l_getxxi_status); |
432 | return 0; |
433 | } |
434 | if ((status = sys$getrmi(efn, 0, 0, RMI_items, &iosb, 0, 0)) |
435 | != SS$_NORMAL) { |
436 | lib$signal(status); |
437 | return 0; |
438 | } |
439 | if ((status = sys$synch(efn, &iosb)) != SS$_NORMAL) { |
440 | lib$signal(status); |
441 | return 0; |
442 | } |
443 | if (iosb.iosb$l_getxxi_status != SS$_NORMAL) { |
444 | lib$signal(iosb.iosb$l_getxxi_status); |
445 | return 0; |
446 | } |
447 | if ((status = lib$free_ef(&efn)) != SS$_NORMAL) { |
448 | lib$signal(status); |
449 | return 0; |
450 | } |
451 | } |
452 | |
453 | massage_JPI(JPI_items); |
454 | |
455 | /* |
456 | * If we can't feed the requirements from the caller, we're in deep trouble. |
457 | */ |
458 | if (!ossl_assert(total_length >= bytes_needed)) { |
459 | ERR_raise_data(ERR_LIB_RAND, RAND_R_RANDOM_POOL_UNDERFLOW, |
460 | "Needed: %zu, Available: %zu" , |
461 | bytes_needed, total_length); |
462 | return 0; |
463 | } |
464 | |
465 | /* |
466 | * Try not to overfeed the pool |
467 | */ |
468 | if (total_length > bytes_remaining) |
469 | total_length = bytes_remaining; |
470 | |
471 | /* We give the pessimistic value for the amount of entropy */ |
472 | rand_pool_add(pool, (unsigned char *)data.buffer, total_length, |
473 | 8 * total_length / ENTROPY_FACTOR); |
474 | return rand_pool_entropy_available(pool); |
475 | } |
476 | |
477 | int rand_pool_add_nonce_data(RAND_POOL *pool) |
478 | { |
479 | struct { |
480 | pid_t pid; |
481 | CRYPTO_THREAD_ID tid; |
482 | uint64_t time; |
483 | } data; |
484 | |
485 | /* Erase the entire structure including any padding */ |
486 | memset(&data, 0, sizeof(data)); |
487 | |
488 | /* |
489 | * Add process id, thread id, and a high resolution timestamp |
490 | * (where available, which is OpenVMS v8.4 and up) to ensure that |
491 | * the nonce is unique with high probability for different process |
492 | * instances. |
493 | */ |
494 | data.pid = getpid(); |
495 | data.tid = CRYPTO_THREAD_get_current_id(); |
496 | #if __CRTL_VER >= 80400000 |
497 | sys$gettim_prec(&data.time); |
498 | #else |
499 | sys$gettim((void*)&data.time); |
500 | #endif |
501 | |
502 | return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); |
503 | } |
504 | |
505 | /* |
506 | * SYS$GET_ENTROPY METHOD |
507 | * ====================== |
508 | * |
509 | * This is a high entropy method based on a new system service that is |
510 | * based on getentropy() from FreeBSD 12. It's only used if available, |
511 | * and its availability is detected at run-time. |
512 | * |
513 | * We assume that this function provides full entropy random output. |
514 | */ |
515 | #define PUBLIC_VECTORS "SYS$LIBRARY:SYS$PUBLIC_VECTORS.EXE" |
516 | #define GET_ENTROPY "SYS$GET_ENTROPY" |
517 | |
518 | static int get_entropy_address_flag = 0; |
519 | static int (*get_entropy_address)(void *buffer, size_t buffer_size) = NULL; |
520 | static int init_get_entropy_address(void) |
521 | { |
522 | if (get_entropy_address_flag == 0) |
523 | get_entropy_address = dlsym(dlopen(PUBLIC_VECTORS, 0), GET_ENTROPY); |
524 | get_entropy_address_flag = 1; |
525 | return get_entropy_address != NULL; |
526 | } |
527 | |
528 | size_t get_entropy_method(RAND_POOL *pool) |
529 | { |
530 | /* |
531 | * The documentation says that SYS$GET_ENTROPY will give a maximum of |
532 | * 256 bytes of data. |
533 | */ |
534 | unsigned char buffer[256]; |
535 | size_t bytes_needed; |
536 | size_t bytes_to_get = 0; |
537 | uint32_t status; |
538 | |
539 | for (bytes_needed = rand_pool_bytes_needed(pool, 1); |
540 | bytes_needed > 0; |
541 | bytes_needed -= bytes_to_get) { |
542 | bytes_to_get = |
543 | bytes_needed > sizeof(buffer) ? sizeof(buffer) : bytes_needed; |
544 | |
545 | status = get_entropy_address(buffer, bytes_to_get); |
546 | if (status == SS$_RETRY) { |
547 | /* Set to zero so the loop doesn't diminish |bytes_needed| */ |
548 | bytes_to_get = 0; |
549 | /* Should sleep some amount of time */ |
550 | continue; |
551 | } |
552 | |
553 | if (status != SS$_NORMAL) { |
554 | lib$signal(status); |
555 | return 0; |
556 | } |
557 | |
558 | rand_pool_add(pool, buffer, bytes_to_get, 8 * bytes_to_get); |
559 | } |
560 | |
561 | return rand_pool_entropy_available(pool); |
562 | } |
563 | |
564 | /* |
565 | * MAIN ENTROPY ACQUISITION FUNCTIONS |
566 | * ================================== |
567 | * |
568 | * These functions are called by the RAND / DRBG functions |
569 | */ |
570 | |
571 | size_t rand_pool_acquire_entropy(RAND_POOL *pool) |
572 | { |
573 | if (init_get_entropy_address()) |
574 | return get_entropy_method(pool); |
575 | return data_collect_method(pool); |
576 | } |
577 | |
578 | |
579 | int rand_pool_add_additional_data(RAND_POOL *pool) |
580 | { |
581 | struct { |
582 | CRYPTO_THREAD_ID tid; |
583 | uint64_t time; |
584 | } data; |
585 | |
586 | /* Erase the entire structure including any padding */ |
587 | memset(&data, 0, sizeof(data)); |
588 | |
589 | /* |
590 | * Add some noise from the thread id and a high resolution timer. |
591 | * The thread id adds a little randomness if the drbg is accessed |
592 | * concurrently (which is the case for the <master> drbg). |
593 | */ |
594 | data.tid = CRYPTO_THREAD_get_current_id(); |
595 | #if __CRTL_VER >= 80400000 |
596 | sys$gettim_prec(&data.time); |
597 | #else |
598 | sys$gettim((void*)&data.time); |
599 | #endif |
600 | |
601 | return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); |
602 | } |
603 | |
604 | int rand_pool_init(void) |
605 | { |
606 | return 1; |
607 | } |
608 | |
609 | void rand_pool_cleanup(void) |
610 | { |
611 | } |
612 | |
613 | void rand_pool_keep_random_devices_open(int keep) |
614 | { |
615 | } |
616 | |
617 | #endif |
618 | |