2 * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
12 #if defined(OPENSSL_SYS_VMS)
13 # define __NEW_STARLET 1 /* New starlet definitions since VMS 7.0 */
15 # include "internal/cryptlib.h"
16 # include <openssl/rand.h>
17 # include "internal/rand_int.h"
18 # include "rand_lcl.h"
27 # include <gen64def.h>
30 # include <lib$routines.h>
32 # pragma message disable DOLLARID
35 # ifndef OPENSSL_RAND_SEED_OS
36 # error "Unsupported seeding method configured; must be os"
39 /* We need to make sure we have the right size pointer in some cases */
40 # if __INITIAL_POINTER_SIZE == 64
41 # pragma pointer_size save
42 # pragma pointer_size 32
44 typedef uint32_t *uint32_t__ptr32
;
45 # if __INITIAL_POINTER_SIZE == 64
46 # pragma pointer_size restore
49 static const struct item_st
{
50 short length
, code
; /* length is number of bytes */
56 {8, JPI$_LAST_LOGIN_I
},
63 * Note: the direct result is just a 32-bit address. However, it points
64 * to a list of 4 32-bit words, so we make extra space for them so we can
65 * do in-place replacement of values
72 * items_data - an array of lengths and codes
73 * items_data_num - number of elements in that array, minus one
74 * (caller MUST have space for one extra NULL element)
77 * items - pre-allocated ILE3 array to be filled.
78 * It's assume to have items_data_num elements.
79 * databuffer - pre-allocated 32-bit word array.
81 * Returns the number of bytes used in databuffer
83 static size_t prepare_item_list(const struct item_st
*items_input
,
84 size_t items_input_num
,
86 uint32_t__ptr32 databuffer
)
88 const struct item_st
*pitems_input
;
92 for (pitems_input
= items_input
, pitems
= items
;
93 items_input_num
-- > 0;
94 pitems_input
++, pitems
++) {
96 /* Special treatment of JPI$_FINALEXC */
97 if (pitems
->ile3$w_code
== JPI$_FINALEXC
)
98 pitems
->ile3$w_length
= 4;
100 pitems
->ile3$w_length
= pitems_input
->length
;
102 pitems
->ile3$w_code
= pitems_input
->code
;
103 pitems
->ile3$ps_bufaddr
= databuffer
;
104 pitems
->ile3$ps_retlen_addr
= 0;
106 databuffer
+= pitems_input
->length
/ sizeof(*databuffer
);
107 data_sz
+= pitems_input
->length
;
109 /* Terminating NULL entry */
110 pitems
->ile3$w_length
= pitems
->ile3$w_code
= 0;
115 static void massage_JPI(ILE3
*items
)
118 * Special treatment of JPI$_FINALEXC
119 * The result of that item's data buffer is a 32-bit address to a list of
122 for (; items
->ile3$w_length
!= 0; items
++) {
123 if (items
->ile3$w_code
== JPI$_FINALEXC
) {
124 uint32_t *data
= items
->ile3$ps_bufaddr
;
125 uint32_t *ptr
= (uint32_t *)*data
;
129 * We know we made space for 4 32-bit words, so we can do in-place
132 for (j
= 0; j
< 4; j
++)
141 * This number expresses how many bits of data contain 1 bit of entropy.
143 * For the moment, we assume about 0.5 entropy bits per data bit, or 1
144 * bit of entropy per 2 data bits.
146 #define ENTROPY_FACTOR 2
148 size_t rand_pool_acquire_entropy(RAND_POOL
*pool
)
150 ILE3 items
[OSSL_NELEM(item_data
) + 1];
152 * All items get 1 or 2 32-bit words of data, except JPI$_FINALEXC
153 * We make sure that we have ample space
155 uint32_t data_buffer
[(OSSL_NELEM(item_data
)) * 2 + 4];
156 size_t total_length
= 0;
157 size_t bytes_needed
= rand_pool_bytes_needed(pool
, ENTROPY_FACTOR
);
158 size_t bytes_remaining
= rand_pool_bytes_remaining(pool
);
160 total_length
+= prepare_item_list(item_data
, OSSL_NELEM(item_data
),
161 items
, &data_buffer
[total_length
]);
163 /* Fill data_buffer with various info bits from this process */
167 if ((status
= sys$
getjpiw(EFN$C_ENF
, 0, 0, items
, 0, 0, 0))
177 * If we can't feed the requirements from the caller, we're in deep trouble.
179 if (!ossl_assert(total_length
>= bytes_needed
)) {
181 char availablestr
[20];
183 BIO_snprintf(neededstr
, sizeof(neededstr
), "%zu", bytes_needed
);
184 BIO_snprintf(availablestr
, sizeof(availablestr
), "%zu", total_length
);
185 RANDerr(RAND_F_RAND_POOL_ACQUIRE_ENTROPY
,
186 RAND_R_RANDOM_POOL_UNDERFLOW
);
187 ERR_add_error_data(4, "Needed: ", neededstr
, ", Available: ",
193 * Try not to overfeed the pool
195 if (total_length
> bytes_remaining
)
196 total_length
= bytes_remaining
;
198 /* We give the pessimistic value for the amount of entropy */
199 rand_pool_add(pool
, (unsigned char *)data_buffer
, total_length
,
200 total_length
/ ENTROPY_FACTOR
);
201 return rand_pool_entropy_available(pool
);
204 int rand_pool_add_nonce_data(RAND_POOL
*pool
)
208 CRYPTO_THREAD_ID tid
;
213 * Add process id, thread id, and a high resolution timestamp to
214 * ensure that the nonce is unique whith high probability for
215 * different process instances.
218 data
.tid
= CRYPTO_THREAD_get_current_id();
219 sys$
gettim_prec(&data
.time
);
221 return rand_pool_add(pool
, (unsigned char *)&data
, sizeof(data
), 0);
224 int rand_pool_add_additional_data(RAND_POOL
*pool
)
227 CRYPTO_THREAD_ID tid
;
232 * Add some noise from the thread id and a high resolution timer.
233 * The thread id adds a little randomness if the drbg is accessed
234 * concurrently (which is the case for the <master> drbg).
236 data
.tid
= CRYPTO_THREAD_get_current_id();
237 sys$
gettim_prec(&data
.time
);
239 return rand_pool_add(pool
, (unsigned char *)&data
, sizeof(data
), 0);