Home | History | Annotate | Line # | Download | only in seeding
      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  */
    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 
    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 
    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 += prepare_item_list(JPI_item_data_64bit, OSSL_NELEM(JPI_item_data_64bit),
    371         JPI_items_64bit, &data.buffer[total_elems]);
    372     total_elems += prepare_item_list(RMI_item_data_64bit, OSSL_NELEM(RMI_item_data_64bit),
    373         RMI_items_64bit, &data.buffer[total_elems]);
    374     /* Now the 32-bit items */
    375     total_elems += prepare_item_list(DVI_item_data, OSSL_NELEM(DVI_item_data),
    376         DVI_items, &data.buffer[total_elems]);
    377     total_elems += prepare_item_list(JPI_item_data, OSSL_NELEM(JPI_item_data),
    378         JPI_items, &data.buffer[total_elems]);
    379     total_elems += prepare_item_list(RMI_item_data, OSSL_NELEM(RMI_item_data),
    380         RMI_items, &data.buffer[total_elems]);
    381     total_elems += prepare_item_list(SYI_item_data, OSSL_NELEM(SYI_item_data),
    382         SYI_items, &data.buffer[total_elems]);
    383     total_length = total_elems * sizeof(data.buffer[0]);
    384 
    385     /* Fill data.buffer with various info bits from this process */
    386     {
    387         uint32_t status;
    388         uint32_t efn;
    389         IOSB iosb;
    390         $DESCRIPTOR(SYSDEVICE, "SYS$SYSDEVICE:");
    391 
    392         if ((status = sys$getdviw(EFN$C_ENF, 0, &SYSDEVICE, DVI_items,
    393                  0, 0, 0, 0, 0))
    394             != 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     ossl_rand_pool_add(pool, (unsigned char *)data.buffer, total_length,
    473         8 * total_length / ENTROPY_FACTOR);
    474     return ossl_rand_pool_entropy_available(pool);
    475 }
    476 
    477 /*
    478  * SYS$GET_ENTROPY METHOD
    479  * ======================
    480  *
    481  * This is a high entropy method based on a new system service that is
    482  * based on getentropy() from FreeBSD 12.  It's only used if available,
    483  * and its availability is detected at run-time.
    484  *
    485  * We assume that this function provides full entropy random output.
    486  */
    487 #define PUBLIC_VECTORS "SYS$LIBRARY:SYS$PUBLIC_VECTORS.EXE"
    488 #define GET_ENTROPY "SYS$GET_ENTROPY"
    489 
    490 static int get_entropy_address_flag = 0;
    491 static int (*get_entropy_address)(void *buffer, size_t buffer_size) = NULL;
    492 static int init_get_entropy_address(void)
    493 {
    494     if (get_entropy_address_flag == 0)
    495         get_entropy_address = dlsym(dlopen(PUBLIC_VECTORS, 0), GET_ENTROPY);
    496     get_entropy_address_flag = 1;
    497     return get_entropy_address != NULL;
    498 }
    499 
    500 size_t get_entropy_method(RAND_POOL *pool)
    501 {
    502     /*
    503      * The documentation says that SYS$GET_ENTROPY will give a maximum of
    504      * 256 bytes of data.
    505      */
    506     unsigned char buffer[256];
    507     size_t bytes_needed;
    508     size_t bytes_to_get = 0;
    509     uint32_t status;
    510 
    511     for (bytes_needed = ossl_rand_pool_bytes_needed(pool, 1);
    512         bytes_needed > 0;
    513         bytes_needed -= bytes_to_get) {
    514         bytes_to_get = bytes_needed > sizeof(buffer) ? sizeof(buffer) : bytes_needed;
    515 
    516         status = get_entropy_address(buffer, bytes_to_get);
    517         if (status == SS$_RETRY) {
    518             /* Set to zero so the loop doesn't diminish |bytes_needed| */
    519             bytes_to_get = 0;
    520             /* Should sleep some amount of time */
    521             continue;
    522         }
    523 
    524         if (status != SS$_NORMAL) {
    525             lib$signal(status);
    526             return 0;
    527         }
    528 
    529         ossl_rand_pool_add(pool, buffer, bytes_to_get, 8 * bytes_to_get);
    530     }
    531 
    532     return ossl_rand_pool_entropy_available(pool);
    533 }
    534 
    535 /*
    536  * MAIN ENTROPY ACQUISITION FUNCTIONS
    537  * ==================================
    538  *
    539  * These functions are called by the RAND / DRBG functions
    540  */
    541 
    542 size_t ossl_pool_acquire_entropy(RAND_POOL *pool)
    543 {
    544     if (init_get_entropy_address())
    545         return get_entropy_method(pool);
    546     return data_collect_method(pool);
    547 }
    548 
    549 int ossl_pool_add_nonce_data(RAND_POOL *pool)
    550 {
    551     /*
    552      * Two variables to ensure that two nonces won't ever be the same
    553      */
    554     static unsigned __int64 last_time = 0;
    555     static unsigned __int32 last_seq = 0;
    556 
    557     struct {
    558         pid_t pid;
    559         CRYPTO_THREAD_ID tid;
    560         unsigned __int64 time;
    561         unsigned __int32 seq;
    562     } data;
    563 
    564     /* Erase the entire structure including any padding */
    565     memset(&data, 0, sizeof(data));
    566 
    567     /*
    568      * Add process id, thread id, a timestamp, and a sequence number in case
    569      * the same time stamp is repeated, to ensure that the nonce is unique
    570      * with high probability for different process instances.
    571      *
    572      * The normal OpenVMS time is specified to be high granularity (100ns),
    573      * but the time update granularity given by sys$gettim() may be lower.
    574      *
    575      * OpenVMS version 8.4 (which is the latest for Alpha and Itanium) and
    576      * on have sys$gettim_prec() as well, which is supposedly having a better
    577      * time update granularity, but tests on Itanium (and even Alpha) have
    578      * shown that compared with sys$gettim(), the difference is marginal,
    579      * so of very little significance in terms of entropy.
    580      * Given that, and that it's a high ask to expect everyone to have
    581      * upgraded to OpenVMS version 8.4, only sys$gettim() is used, and a
    582      * sequence number is added as well, in case sys$gettim() returns the
    583      * same time value more than once.
    584      *
    585      * This function is assumed to be called under thread lock, and does
    586      * therefore not take concurrency into account.
    587      */
    588     data.pid = getpid();
    589     data.tid = CRYPTO_THREAD_get_current_id();
    590     data.seq = 0;
    591     sys$gettim((void *)&data.time);
    592 
    593     if (data.time == last_time) {
    594         data.seq = ++last_seq;
    595     } else {
    596         last_time = data.time;
    597         last_seq = 0;
    598     }
    599 
    600     return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
    601 }
    602 
    603 int ossl_rand_pool_init(void)
    604 {
    605     return 1;
    606 }
    607 
    608 void ossl_rand_pool_cleanup(void)
    609 {
    610 }
    611 
    612 void ossl_rand_pool_keep_random_devices_open(int keep)
    613 {
    614 }
    615