rand_vms.c 19 KB

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