rand_vms.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. /*
  2. * Copyright 2001-2018 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 "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/rand.h>
  15. # include "internal/rand_int.h"
  16. # include "rand_lcl.h"
  17. # include <descrip.h>
  18. # include <dvidef.h>
  19. # include <jpidef.h>
  20. # include <rmidef.h>
  21. # include <syidef.h>
  22. # include <ssdef.h>
  23. # include <starlet.h>
  24. # include <efndef.h>
  25. # include <gen64def.h>
  26. # include <iosbdef.h>
  27. # include <iledef.h>
  28. # include <lib$routines.h>
  29. # ifdef __DECC
  30. # pragma message disable DOLLARID
  31. # endif
  32. # ifndef OPENSSL_RAND_SEED_OS
  33. # error "Unsupported seeding method configured; must be os"
  34. # endif
  35. /* We need to make sure we have the right size pointer in some cases */
  36. # if __INITIAL_POINTER_SIZE == 64
  37. # pragma pointer_size save
  38. # pragma pointer_size 32
  39. # endif
  40. typedef uint32_t *uint32_t__ptr32;
  41. # if __INITIAL_POINTER_SIZE == 64
  42. # pragma pointer_size restore
  43. # endif
  44. struct item_st {
  45. short length, code; /* length is number of bytes */
  46. };
  47. static const struct item_st DVI_item_data[] = {
  48. {4, DVI$_ERRCNT},
  49. {4, DVI$_REFCNT},
  50. };
  51. static const struct item_st JPI_item_data[] = {
  52. {4, JPI$_BUFIO},
  53. {4, JPI$_CPUTIM},
  54. {4, JPI$_DIRIO},
  55. {4, JPI$_IMAGECOUNT},
  56. {4, JPI$_PAGEFLTS},
  57. {4, JPI$_PID},
  58. {4, JPI$_PPGCNT},
  59. {4, JPI$_WSPEAK},
  60. /*
  61. * Note: the direct result is just a 32-bit address. However, it points
  62. * to a list of 4 32-bit words, so we make extra space for them so we can
  63. * do in-place replacement of values
  64. */
  65. {16, JPI$_FINALEXC},
  66. };
  67. static const struct item_st JPI_item_data_64bit[] = {
  68. {8, JPI$_LAST_LOGIN_I},
  69. {8, JPI$_LOGINTIM},
  70. };
  71. static const struct item_st RMI_item_data[] = {
  72. {4, RMI$_COLPG},
  73. {4, RMI$_MWAIT},
  74. {4, RMI$_CEF},
  75. {4, RMI$_PFW},
  76. {4, RMI$_LEF},
  77. {4, RMI$_LEFO},
  78. {4, RMI$_HIB},
  79. {4, RMI$_HIBO},
  80. {4, RMI$_SUSP},
  81. {4, RMI$_SUSPO},
  82. {4, RMI$_FPG},
  83. {4, RMI$_COM},
  84. {4, RMI$_COMO},
  85. {4, RMI$_CUR},
  86. #if defined __alpha
  87. {4, RMI$_FRLIST},
  88. {4, RMI$_MODLIST},
  89. #endif
  90. {4, RMI$_FAULTS},
  91. {4, RMI$_PREADS},
  92. {4, RMI$_PWRITES},
  93. {4, RMI$_PWRITIO},
  94. {4, RMI$_PREADIO},
  95. {4, RMI$_GVALFLTS},
  96. {4, RMI$_WRTINPROG},
  97. {4, RMI$_FREFLTS},
  98. {4, RMI$_DZROFLTS},
  99. {4, RMI$_SYSFAULTS},
  100. {4, RMI$_ISWPCNT},
  101. {4, RMI$_DIRIO},
  102. {4, RMI$_BUFIO},
  103. {4, RMI$_MBREADS},
  104. {4, RMI$_MBWRITES},
  105. {4, RMI$_LOGNAM},
  106. {4, RMI$_FCPCALLS},
  107. {4, RMI$_FCPREAD},
  108. {4, RMI$_FCPWRITE},
  109. {4, RMI$_FCPCACHE},
  110. {4, RMI$_FCPCPU},
  111. {4, RMI$_FCPHIT},
  112. {4, RMI$_FCPSPLIT},
  113. {4, RMI$_FCPFAULT},
  114. {4, RMI$_ENQNEW},
  115. {4, RMI$_ENQCVT},
  116. {4, RMI$_DEQ},
  117. {4, RMI$_BLKAST},
  118. {4, RMI$_ENQWAIT},
  119. {4, RMI$_ENQNOTQD},
  120. {4, RMI$_DLCKSRCH},
  121. {4, RMI$_DLCKFND},
  122. {4, RMI$_NUMLOCKS},
  123. {4, RMI$_NUMRES},
  124. {4, RMI$_ARRLOCPK},
  125. {4, RMI$_DEPLOCPK},
  126. {4, RMI$_ARRTRAPK},
  127. {4, RMI$_TRCNGLOS},
  128. {4, RMI$_RCVBUFFL},
  129. {4, RMI$_ENQNEWLOC},
  130. {4, RMI$_ENQNEWIN},
  131. {4, RMI$_ENQNEWOUT},
  132. {4, RMI$_ENQCVTLOC},
  133. {4, RMI$_ENQCVTIN},
  134. {4, RMI$_ENQCVTOUT},
  135. {4, RMI$_DEQLOC},
  136. {4, RMI$_DEQIN},
  137. {4, RMI$_DEQOUT},
  138. {4, RMI$_BLKLOC},
  139. {4, RMI$_BLKIN},
  140. {4, RMI$_BLKOUT},
  141. {4, RMI$_DIRIN},
  142. {4, RMI$_DIROUT},
  143. /* We currently get a fault when trying these. TODO: To be figured out. */
  144. #if 0
  145. {140, RMI$_MSCP_EVERYTHING}, /* 35 32-bit words */
  146. {152, RMI$_DDTM_ALL}, /* 38 32-bit words */
  147. {80, RMI$_TMSCP_EVERYTHING} /* 20 32-bit words */
  148. #endif
  149. {4, RMI$_LPZ_PAGCNT},
  150. {4, RMI$_LPZ_HITS},
  151. {4, RMI$_LPZ_MISSES},
  152. {4, RMI$_LPZ_EXPCNT},
  153. {4, RMI$_LPZ_ALLOCF},
  154. {4, RMI$_LPZ_ALLOC2},
  155. {4, RMI$_ACCESS},
  156. {4, RMI$_ALLOC},
  157. {4, RMI$_FCPCREATE},
  158. {4, RMI$_VOLWAIT},
  159. {4, RMI$_FCPTURN},
  160. {4, RMI$_FCPERASE},
  161. {4, RMI$_OPENS},
  162. {4, RMI$_FIDHIT},
  163. {4, RMI$_FIDMISS},
  164. {4, RMI$_FILHDR_HIT},
  165. {4, RMI$_DIRFCB_HIT},
  166. {4, RMI$_DIRFCB_MISS},
  167. {4, RMI$_DIRDATA_HIT},
  168. {4, RMI$_EXTHIT},
  169. {4, RMI$_EXTMISS},
  170. {4, RMI$_QUOHIT},
  171. {4, RMI$_QUOMISS},
  172. {4, RMI$_STORAGMAP_HIT},
  173. {4, RMI$_VOLLCK},
  174. {4, RMI$_SYNCHLCK},
  175. {4, RMI$_SYNCHWAIT},
  176. {4, RMI$_ACCLCK},
  177. {4, RMI$_XQPCACHEWAIT},
  178. {4, RMI$_DIRDATA_MISS},
  179. {4, RMI$_FILHDR_MISS},
  180. {4, RMI$_STORAGMAP_MISS},
  181. {4, RMI$_PROCCNTMAX},
  182. {4, RMI$_PROCBATCNT},
  183. {4, RMI$_PROCINTCNT},
  184. {4, RMI$_PROCNETCNT},
  185. {4, RMI$_PROCSWITCHCNT},
  186. {4, RMI$_PROCBALSETCNT},
  187. {4, RMI$_PROCLOADCNT},
  188. {4, RMI$_BADFLTS},
  189. {4, RMI$_EXEFAULTS},
  190. {4, RMI$_HDRINSWAPS},
  191. {4, RMI$_HDROUTSWAPS},
  192. {4, RMI$_IOPAGCNT},
  193. {4, RMI$_ISWPCNTPG},
  194. {4, RMI$_OSWPCNT},
  195. {4, RMI$_OSWPCNTPG},
  196. {4, RMI$_RDFAULTS},
  197. {4, RMI$_TRANSFLTS},
  198. {4, RMI$_WRTFAULTS},
  199. #if defined __alpha
  200. {4, RMI$_USERPAGES},
  201. #endif
  202. {4, RMI$_VMSPAGES},
  203. {4, RMI$_TTWRITES},
  204. {4, RMI$_BUFOBJPAG},
  205. {4, RMI$_BUFOBJPAGPEAK},
  206. {4, RMI$_BUFOBJPAGS01},
  207. {4, RMI$_BUFOBJPAGS2},
  208. {4, RMI$_BUFOBJPAGMAXS01},
  209. {4, RMI$_BUFOBJPAGMAXS2},
  210. {4, RMI$_BUFOBJPAGPEAKS01},
  211. {4, RMI$_BUFOBJPAGPEAKS2},
  212. {4, RMI$_BUFOBJPGLTMAXS01},
  213. {4, RMI$_BUFOBJPGLTMAXS2},
  214. {4, RMI$_DLCK_INCMPLT},
  215. {4, RMI$_DLCKMSGS_IN},
  216. {4, RMI$_DLCKMSGS_OUT},
  217. {4, RMI$_MCHKERRS},
  218. {4, RMI$_MEMERRS},
  219. };
  220. static const struct item_st RMI_item_data_64bit[] = {
  221. #if defined __ia64
  222. {8, RMI$_FRLIST},
  223. {8, RMI$_MODLIST},
  224. #endif
  225. {8, RMI$_LCKMGR_REQCNT},
  226. {8, RMI$_LCKMGR_REQTIME},
  227. {8, RMI$_LCKMGR_SPINCNT},
  228. {8, RMI$_LCKMGR_SPINTIME},
  229. {8, RMI$_CPUINTSTK},
  230. {8, RMI$_CPUMPSYNCH},
  231. {8, RMI$_CPUKERNEL},
  232. {8, RMI$_CPUEXEC},
  233. {8, RMI$_CPUSUPER},
  234. {8, RMI$_CPUUSER},
  235. #if defined __ia64
  236. {8, RMI$_USERPAGES},
  237. #endif
  238. {8, RMI$_TQETOTAL},
  239. {8, RMI$_TQESYSUB},
  240. {8, RMI$_TQEUSRTIMR},
  241. {8, RMI$_TQEUSRWAKE},
  242. };
  243. static const struct item_st SYI_item_data[] = {
  244. {4, SYI$_PAGEFILE_FREE},
  245. };
  246. /*
  247. * Input:
  248. * items_data - an array of lengths and codes
  249. * items_data_num - number of elements in that array
  250. *
  251. * Output:
  252. * items - pre-allocated ILE3 array to be filled.
  253. * It's assumed to have items_data_num elements plus
  254. * one extra for the terminating NULL element
  255. * databuffer - pre-allocated 32-bit word array.
  256. *
  257. * Returns the number of elements used in databuffer
  258. */
  259. static size_t prepare_item_list(const struct item_st *items_input,
  260. size_t items_input_num,
  261. ILE3 *items,
  262. uint32_t__ptr32 databuffer)
  263. {
  264. size_t data_sz = 0;
  265. for (; items_input_num-- > 0; items_input++, items++) {
  266. items->ile3$w_code = items_input->code;
  267. /* Special treatment of JPI$_FINALEXC */
  268. if (items->ile3$w_code == JPI$_FINALEXC)
  269. items->ile3$w_length = 4;
  270. else
  271. items->ile3$w_length = items_input->length;
  272. items->ile3$ps_bufaddr = databuffer;
  273. items->ile3$ps_retlen_addr = 0;
  274. databuffer += items_input->length / sizeof(databuffer[0]);
  275. data_sz += items_input->length;
  276. }
  277. /* Terminating NULL entry */
  278. items->ile3$w_length = items->ile3$w_code = 0;
  279. items->ile3$ps_bufaddr = items->ile3$ps_retlen_addr = NULL;
  280. return data_sz / sizeof(databuffer[0]);
  281. }
  282. static void massage_JPI(ILE3 *items)
  283. {
  284. /*
  285. * Special treatment of JPI$_FINALEXC
  286. * The result of that item's data buffer is a 32-bit address to a list of
  287. * 4 32-bit words.
  288. */
  289. for (; items->ile3$w_length != 0; items++) {
  290. if (items->ile3$w_code == JPI$_FINALEXC) {
  291. uint32_t *data = items->ile3$ps_bufaddr;
  292. uint32_t *ptr = (uint32_t *)*data;
  293. size_t j;
  294. /*
  295. * We know we made space for 4 32-bit words, so we can do in-place
  296. * replacement.
  297. */
  298. for (j = 0; j < 4; j++)
  299. data[j] = ptr[j];
  300. break;
  301. }
  302. }
  303. }
  304. /*
  305. * This number expresses how many bits of data contain 1 bit of entropy.
  306. *
  307. * For the moment, we assume about 0.05 entropy bits per data bit, or 1
  308. * bit of entropy per 20 data bits.
  309. */
  310. #define ENTROPY_FACTOR 20
  311. size_t rand_pool_acquire_entropy(RAND_POOL *pool)
  312. {
  313. ILE3 JPI_items_64bit[OSSL_NELEM(JPI_item_data_64bit) + 1];
  314. ILE3 RMI_items_64bit[OSSL_NELEM(RMI_item_data_64bit) + 1];
  315. ILE3 DVI_items[OSSL_NELEM(DVI_item_data) + 1];
  316. ILE3 JPI_items[OSSL_NELEM(JPI_item_data) + 1];
  317. ILE3 RMI_items[OSSL_NELEM(RMI_item_data) + 1];
  318. ILE3 SYI_items[OSSL_NELEM(SYI_item_data) + 1];
  319. union {
  320. /* This ensures buffer starts at 64 bit boundary */
  321. uint64_t dummy;
  322. uint32_t buffer[OSSL_NELEM(JPI_item_data_64bit) * 2
  323. + OSSL_NELEM(RMI_item_data_64bit) * 2
  324. + OSSL_NELEM(DVI_item_data)
  325. + OSSL_NELEM(JPI_item_data)
  326. + OSSL_NELEM(RMI_item_data)
  327. + OSSL_NELEM(SYI_item_data)
  328. + 4 /* For JPI$_FINALEXC */];
  329. } data;
  330. size_t total_elems = 0;
  331. size_t total_length = 0;
  332. size_t bytes_needed = rand_pool_bytes_needed(pool, ENTROPY_FACTOR);
  333. size_t bytes_remaining = rand_pool_bytes_remaining(pool);
  334. /* Take all the 64-bit items first, to ensure proper alignment of data */
  335. total_elems +=
  336. prepare_item_list(JPI_item_data_64bit, OSSL_NELEM(JPI_item_data_64bit),
  337. JPI_items_64bit, &data.buffer[total_elems]);
  338. total_elems +=
  339. prepare_item_list(RMI_item_data_64bit, OSSL_NELEM(RMI_item_data_64bit),
  340. RMI_items_64bit, &data.buffer[total_elems]);
  341. /* Now the 32-bit items */
  342. total_elems += prepare_item_list(DVI_item_data, OSSL_NELEM(DVI_item_data),
  343. DVI_items, &data.buffer[total_elems]);
  344. total_elems += prepare_item_list(JPI_item_data, OSSL_NELEM(JPI_item_data),
  345. JPI_items, &data.buffer[total_elems]);
  346. total_elems += prepare_item_list(RMI_item_data, OSSL_NELEM(RMI_item_data),
  347. RMI_items, &data.buffer[total_elems]);
  348. total_elems += prepare_item_list(SYI_item_data, OSSL_NELEM(SYI_item_data),
  349. SYI_items, &data.buffer[total_elems]);
  350. total_length = total_elems * sizeof(data.buffer[0]);
  351. /* Fill data.buffer with various info bits from this process */
  352. {
  353. uint32_t status;
  354. uint32_t efn;
  355. IOSB iosb;
  356. $DESCRIPTOR(SYSDEVICE,"SYS$SYSDEVICE:");
  357. if ((status = sys$getdviw(EFN$C_ENF, 0, &SYSDEVICE, DVI_items,
  358. 0, 0, 0, 0, 0)) != SS$_NORMAL) {
  359. lib$signal(status);
  360. return 0;
  361. }
  362. if ((status = sys$getjpiw(EFN$C_ENF, 0, 0, JPI_items_64bit, 0, 0, 0))
  363. != SS$_NORMAL) {
  364. lib$signal(status);
  365. return 0;
  366. }
  367. if ((status = sys$getjpiw(EFN$C_ENF, 0, 0, JPI_items, 0, 0, 0))
  368. != SS$_NORMAL) {
  369. lib$signal(status);
  370. return 0;
  371. }
  372. if ((status = sys$getsyiw(EFN$C_ENF, 0, 0, SYI_items, 0, 0, 0))
  373. != SS$_NORMAL) {
  374. lib$signal(status);
  375. return 0;
  376. }
  377. /*
  378. * The RMI service is a bit special, as there is no synchronous
  379. * variant, so we MUST create an event flag to synchronise on.
  380. */
  381. if ((status = lib$get_ef(&efn)) != SS$_NORMAL) {
  382. lib$signal(status);
  383. return 0;
  384. }
  385. if ((status = sys$getrmi(efn, 0, 0, RMI_items_64bit, &iosb, 0, 0))
  386. != SS$_NORMAL) {
  387. lib$signal(status);
  388. return 0;
  389. }
  390. if ((status = sys$synch(efn, &iosb)) != SS$_NORMAL) {
  391. lib$signal(status);
  392. return 0;
  393. }
  394. if (iosb.iosb$l_getxxi_status != SS$_NORMAL) {
  395. lib$signal(iosb.iosb$l_getxxi_status);
  396. return 0;
  397. }
  398. if ((status = sys$getrmi(efn, 0, 0, RMI_items, &iosb, 0, 0))
  399. != SS$_NORMAL) {
  400. lib$signal(status);
  401. return 0;
  402. }
  403. if ((status = sys$synch(efn, &iosb)) != SS$_NORMAL) {
  404. lib$signal(status);
  405. return 0;
  406. }
  407. if (iosb.iosb$l_getxxi_status != SS$_NORMAL) {
  408. lib$signal(iosb.iosb$l_getxxi_status);
  409. return 0;
  410. }
  411. if ((status = lib$free_ef(&efn)) != SS$_NORMAL) {
  412. lib$signal(status);
  413. return 0;
  414. }
  415. }
  416. massage_JPI(JPI_items);
  417. /*
  418. * If we can't feed the requirements from the caller, we're in deep trouble.
  419. */
  420. if (!ossl_assert(total_length >= bytes_needed)) {
  421. char neededstr[20];
  422. char availablestr[20];
  423. BIO_snprintf(neededstr, sizeof(neededstr), "%zu", bytes_needed);
  424. BIO_snprintf(availablestr, sizeof(availablestr), "%zu", total_length);
  425. RANDerr(RAND_F_RAND_POOL_ACQUIRE_ENTROPY,
  426. RAND_R_RANDOM_POOL_UNDERFLOW);
  427. ERR_add_error_data(4, "Needed: ", neededstr, ", Available: ",
  428. availablestr);
  429. return 0;
  430. }
  431. /*
  432. * Try not to overfeed the pool
  433. */
  434. if (total_length > bytes_remaining)
  435. total_length = bytes_remaining;
  436. /* We give the pessimistic value for the amount of entropy */
  437. rand_pool_add(pool, (unsigned char *)data.buffer, total_length,
  438. 8 * total_length / ENTROPY_FACTOR);
  439. return rand_pool_entropy_available(pool);
  440. }
  441. int rand_pool_add_nonce_data(RAND_POOL *pool)
  442. {
  443. struct {
  444. pid_t pid;
  445. CRYPTO_THREAD_ID tid;
  446. uint64_t time;
  447. } data;
  448. /* Erase the entire structure including any padding */
  449. memset(&data, 0, sizeof(data));
  450. /*
  451. * Add process id, thread id, and a high resolution timestamp
  452. * (where available, which is OpenVMS v8.4 and up) to ensure that
  453. * the nonce is unique whith high probability for different process
  454. * instances.
  455. */
  456. data.pid = getpid();
  457. data.tid = CRYPTO_THREAD_get_current_id();
  458. #if __CRTL_VER >= 80400000
  459. sys$gettim_prec(&data.time);
  460. #else
  461. sys$gettim((void*)&data.time);
  462. #endif
  463. return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
  464. }
  465. int rand_pool_add_additional_data(RAND_POOL *pool)
  466. {
  467. struct {
  468. CRYPTO_THREAD_ID tid;
  469. uint64_t time;
  470. } data;
  471. /* Erase the entire structure including any padding */
  472. memset(&data, 0, sizeof(data));
  473. /*
  474. * Add some noise from the thread id and a high resolution timer.
  475. * The thread id adds a little randomness if the drbg is accessed
  476. * concurrently (which is the case for the <master> drbg).
  477. */
  478. data.tid = CRYPTO_THREAD_get_current_id();
  479. #if __CRTL_VER >= 80400000
  480. sys$gettim_prec(&data.time);
  481. #else
  482. sys$gettim((void*)&data.time);
  483. #endif
  484. return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
  485. }
  486. int rand_pool_init(void)
  487. {
  488. return 1;
  489. }
  490. void rand_pool_cleanup(void)
  491. {
  492. }
  493. void rand_pool_keep_random_devices_open(int keep)
  494. {
  495. }
  496. #endif