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