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