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