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