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