rand_vms.c 18 KB

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