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