#include "internal/e_os.h"
#define __NEW_STARLET 1
#include <unistd.h>
#include "internal/cryptlib.h"
#include "internal/nelem.h"
#include <openssl/rand.h>
#include "crypto/rand.h"
#include "crypto/rand_pool.h"
#include "prov/seeding.h"
#include <descrip.h>
#include <dvidef.h>
#include <jpidef.h>
#include <rmidef.h>
#include <syidef.h>
#include <ssdef.h>
#include <starlet.h>
#include <efndef.h>
#include <gen64def.h>
#include <iosbdef.h>
#include <iledef.h>
#include <lib$routines.h>
#ifdef __DECC
#pragma message disable DOLLARID
#endif
#include <dlfcn.h>
#ifndef OPENSSL_RAND_SEED_OS
#error "Unsupported seeding method configured; must be os"
#endif
#if __INITIAL_POINTER_SIZE == 64
#pragma pointer_size save
#pragma pointer_size 32
#endif
typedef uint32_t *uint32_t__ptr32;
#if __INITIAL_POINTER_SIZE == 64
#pragma pointer_size restore
#endif
struct item_st {
short length, code;
};
static const struct item_st DVI_item_data[] = {
{ 4, DVI$_ERRCNT },
{ 4, DVI$_REFCNT },
};
static const struct item_st JPI_item_data[] = {
{ 4, JPI$_BUFIO },
{ 4, JPI$_CPUTIM },
{ 4, JPI$_DIRIO },
{ 4, JPI$_IMAGECOUNT },
{ 4, JPI$_PAGEFLTS },
{ 4, JPI$_PID },
{ 4, JPI$_PPGCNT },
{ 4, JPI$_WSPEAK },
{ 16, JPI$_FINALEXC },
};
static const struct item_st JPI_item_data_64bit[] = {
{ 8, JPI$_LAST_LOGIN_I },
{ 8, JPI$_LOGINTIM },
};
static const struct item_st RMI_item_data[] = {
{ 4, RMI$_COLPG },
{ 4, RMI$_MWAIT },
{ 4, RMI$_CEF },
{ 4, RMI$_PFW },
{ 4, RMI$_LEF },
{ 4, RMI$_LEFO },
{ 4, RMI$_HIB },
{ 4, RMI$_HIBO },
{ 4, RMI$_SUSP },
{ 4, RMI$_SUSPO },
{ 4, RMI$_FPG },
{ 4, RMI$_COM },
{ 4, RMI$_COMO },
{ 4, RMI$_CUR },
#if defined __alpha
{ 4, RMI$_FRLIST },
{ 4, RMI$_MODLIST },
#endif
{ 4, RMI$_FAULTS },
{ 4, RMI$_PREADS },
{ 4, RMI$_PWRITES },
{ 4, RMI$_PWRITIO },
{ 4, RMI$_PREADIO },
{ 4, RMI$_GVALFLTS },
{ 4, RMI$_WRTINPROG },
{ 4, RMI$_FREFLTS },
{ 4, RMI$_DZROFLTS },
{ 4, RMI$_SYSFAULTS },
{ 4, RMI$_ISWPCNT },
{ 4, RMI$_DIRIO },
{ 4, RMI$_BUFIO },
{ 4, RMI$_MBREADS },
{ 4, RMI$_MBWRITES },
{ 4, RMI$_LOGNAM },
{ 4, RMI$_FCPCALLS },
{ 4, RMI$_FCPREAD },
{ 4, RMI$_FCPWRITE },
{ 4, RMI$_FCPCACHE },
{ 4, RMI$_FCPCPU },
{ 4, RMI$_FCPHIT },
{ 4, RMI$_FCPSPLIT },
{ 4, RMI$_FCPFAULT },
{ 4, RMI$_ENQNEW },
{ 4, RMI$_ENQCVT },
{ 4, RMI$_DEQ },
{ 4, RMI$_BLKAST },
{ 4, RMI$_ENQWAIT },
{ 4, RMI$_ENQNOTQD },
{ 4, RMI$_DLCKSRCH },
{ 4, RMI$_DLCKFND },
{ 4, RMI$_NUMLOCKS },
{ 4, RMI$_NUMRES },
{ 4, RMI$_ARRLOCPK },
{ 4, RMI$_DEPLOCPK },
{ 4, RMI$_ARRTRAPK },
{ 4, RMI$_TRCNGLOS },
{ 4, RMI$_RCVBUFFL },
{ 4, RMI$_ENQNEWLOC },
{ 4, RMI$_ENQNEWIN },
{ 4, RMI$_ENQNEWOUT },
{ 4, RMI$_ENQCVTLOC },
{ 4, RMI$_ENQCVTIN },
{ 4, RMI$_ENQCVTOUT },
{ 4, RMI$_DEQLOC },
{ 4, RMI$_DEQIN },
{ 4, RMI$_DEQOUT },
{ 4, RMI$_BLKLOC },
{ 4, RMI$_BLKIN },
{ 4, RMI$_BLKOUT },
{ 4, RMI$_DIRIN },
{ 4, RMI$_DIROUT },
#if 0
{140, RMI$_MSCP_EVERYTHING},
{152, RMI$_DDTM_ALL},
{80, RMI$_TMSCP_EVERYTHING}
#endif
{ 4, RMI$_LPZ_PAGCNT },
{ 4, RMI$_LPZ_HITS },
{ 4, RMI$_LPZ_MISSES },
{ 4, RMI$_LPZ_EXPCNT },
{ 4, RMI$_LPZ_ALLOCF },
{ 4, RMI$_LPZ_ALLOC2 },
{ 4, RMI$_ACCESS },
{ 4, RMI$_ALLOC },
{ 4, RMI$_FCPCREATE },
{ 4, RMI$_VOLWAIT },
{ 4, RMI$_FCPTURN },
{ 4, RMI$_FCPERASE },
{ 4, RMI$_OPENS },
{ 4, RMI$_FIDHIT },
{ 4, RMI$_FIDMISS },
{ 4, RMI$_FILHDR_HIT },
{ 4, RMI$_DIRFCB_HIT },
{ 4, RMI$_DIRFCB_MISS },
{ 4, RMI$_DIRDATA_HIT },
{ 4, RMI$_EXTHIT },
{ 4, RMI$_EXTMISS },
{ 4, RMI$_QUOHIT },
{ 4, RMI$_QUOMISS },
{ 4, RMI$_STORAGMAP_HIT },
{ 4, RMI$_VOLLCK },
{ 4, RMI$_SYNCHLCK },
{ 4, RMI$_SYNCHWAIT },
{ 4, RMI$_ACCLCK },
{ 4, RMI$_XQPCACHEWAIT },
{ 4, RMI$_DIRDATA_MISS },
{ 4, RMI$_FILHDR_MISS },
{ 4, RMI$_STORAGMAP_MISS },
{ 4, RMI$_PROCCNTMAX },
{ 4, RMI$_PROCBATCNT },
{ 4, RMI$_PROCINTCNT },
{ 4, RMI$_PROCNETCNT },
{ 4, RMI$_PROCSWITCHCNT },
{ 4, RMI$_PROCBALSETCNT },
{ 4, RMI$_PROCLOADCNT },
{ 4, RMI$_BADFLTS },
{ 4, RMI$_EXEFAULTS },
{ 4, RMI$_HDRINSWAPS },
{ 4, RMI$_HDROUTSWAPS },
{ 4, RMI$_IOPAGCNT },
{ 4, RMI$_ISWPCNTPG },
{ 4, RMI$_OSWPCNT },
{ 4, RMI$_OSWPCNTPG },
{ 4, RMI$_RDFAULTS },
{ 4, RMI$_TRANSFLTS },
{ 4, RMI$_WRTFAULTS },
#if defined __alpha
{ 4, RMI$_USERPAGES },
#endif
{ 4, RMI$_VMSPAGES },
{ 4, RMI$_TTWRITES },
{ 4, RMI$_BUFOBJPAG },
{ 4, RMI$_BUFOBJPAGPEAK },
{ 4, RMI$_BUFOBJPAGS01 },
{ 4, RMI$_BUFOBJPAGS2 },
{ 4, RMI$_BUFOBJPAGMAXS01 },
{ 4, RMI$_BUFOBJPAGMAXS2 },
{ 4, RMI$_BUFOBJPAGPEAKS01 },
{ 4, RMI$_BUFOBJPAGPEAKS2 },
{ 4, RMI$_BUFOBJPGLTMAXS01 },
{ 4, RMI$_BUFOBJPGLTMAXS2 },
{ 4, RMI$_DLCK_INCMPLT },
{ 4, RMI$_DLCKMSGS_IN },
{ 4, RMI$_DLCKMSGS_OUT },
{ 4, RMI$_MCHKERRS },
{ 4, RMI$_MEMERRS },
};
static const struct item_st RMI_item_data_64bit[] = {
#if defined __ia64
{ 8, RMI$_FRLIST },
{ 8, RMI$_MODLIST },
#endif
{ 8, RMI$_LCKMGR_REQCNT },
{ 8, RMI$_LCKMGR_REQTIME },
{ 8, RMI$_LCKMGR_SPINCNT },
{ 8, RMI$_LCKMGR_SPINTIME },
{ 8, RMI$_CPUINTSTK },
{ 8, RMI$_CPUMPSYNCH },
{ 8, RMI$_CPUKERNEL },
{ 8, RMI$_CPUEXEC },
{ 8, RMI$_CPUSUPER },
{ 8, RMI$_CPUUSER },
#if defined __ia64
{ 8, RMI$_USERPAGES },
#endif
{ 8, RMI$_TQETOTAL },
{ 8, RMI$_TQESYSUB },
{ 8, RMI$_TQEUSRTIMR },
{ 8, RMI$_TQEUSRWAKE },
};
static const struct item_st SYI_item_data[] = {
{ 4, SYI$_PAGEFILE_FREE },
};
static size_t prepare_item_list(const struct item_st *items_input,
size_t items_input_num,
ILE3 *items,
uint32_t__ptr32 databuffer)
{
size_t data_sz = 0;
for (; items_input_num-- > 0; items_input++, items++) {
items->ile3$w_code = items_input->code;
if (items->ile3$w_code == JPI$_FINALEXC)
items->ile3$w_length = 4;
else
items->ile3$w_length = items_input->length;
items->ile3$ps_bufaddr = databuffer;
items->ile3$ps_retlen_addr = 0;
databuffer += items_input->length / sizeof(databuffer[0]);
data_sz += items_input->length;
}
items->ile3$w_length = items->ile3$w_code = 0;
items->ile3$ps_bufaddr = items->ile3$ps_retlen_addr = NULL;
return data_sz / sizeof(databuffer[0]);
}
static void massage_JPI(ILE3 *items)
{
for (; items->ile3$w_length != 0; items++) {
if (items->ile3$w_code == JPI$_FINALEXC) {
uint32_t *data = items->ile3$ps_bufaddr;
uint32_t *ptr = (uint32_t *)*data;
size_t j;
for (j = 0; j < 4; j++)
data[j] = ptr[j];
break;
}
}
}
#define ENTROPY_FACTOR 20
size_t data_collect_method(RAND_POOL *pool)
{
ILE3 JPI_items_64bit[OSSL_NELEM(JPI_item_data_64bit) + 1];
ILE3 RMI_items_64bit[OSSL_NELEM(RMI_item_data_64bit) + 1];
ILE3 DVI_items[OSSL_NELEM(DVI_item_data) + 1];
ILE3 JPI_items[OSSL_NELEM(JPI_item_data) + 1];
ILE3 RMI_items[OSSL_NELEM(RMI_item_data) + 1];
ILE3 SYI_items[OSSL_NELEM(SYI_item_data) + 1];
union {
uint64_t dummy;
uint32_t buffer[OSSL_NELEM(JPI_item_data_64bit) * 2
+ OSSL_NELEM(RMI_item_data_64bit) * 2
+ OSSL_NELEM(DVI_item_data)
+ OSSL_NELEM(JPI_item_data)
+ OSSL_NELEM(RMI_item_data)
+ OSSL_NELEM(SYI_item_data)
+ 4 ];
} data;
size_t total_elems = 0;
size_t total_length = 0;
size_t bytes_needed = ossl_rand_pool_bytes_needed(pool, ENTROPY_FACTOR);
size_t bytes_remaining = ossl_rand_pool_bytes_remaining(pool);
total_elems += prepare_item_list(JPI_item_data_64bit, OSSL_NELEM(JPI_item_data_64bit),
JPI_items_64bit, &data.buffer[total_elems]);
total_elems += prepare_item_list(RMI_item_data_64bit, OSSL_NELEM(RMI_item_data_64bit),
RMI_items_64bit, &data.buffer[total_elems]);
total_elems += prepare_item_list(DVI_item_data, OSSL_NELEM(DVI_item_data),
DVI_items, &data.buffer[total_elems]);
total_elems += prepare_item_list(JPI_item_data, OSSL_NELEM(JPI_item_data),
JPI_items, &data.buffer[total_elems]);
total_elems += prepare_item_list(RMI_item_data, OSSL_NELEM(RMI_item_data),
RMI_items, &data.buffer[total_elems]);
total_elems += prepare_item_list(SYI_item_data, OSSL_NELEM(SYI_item_data),
SYI_items, &data.buffer[total_elems]);
total_length = total_elems * sizeof(data.buffer[0]);
{
uint32_t status;
uint32_t efn;
IOSB iosb;
$DESCRIPTOR(SYSDEVICE, "SYS$SYSDEVICE:");
if ((status = sys$getdviw(EFN$C_ENF, 0, &SYSDEVICE, DVI_items,
0, 0, 0, 0, 0))
!= SS$_NORMAL) {
lib$signal(status);
return 0;
}
if ((status = sys$getjpiw(EFN$C_ENF, 0, 0, JPI_items_64bit, 0, 0, 0))
!= SS$_NORMAL) {
lib$signal(status);
return 0;
}
if ((status = sys$getjpiw(EFN$C_ENF, 0, 0, JPI_items, 0, 0, 0))
!= SS$_NORMAL) {
lib$signal(status);
return 0;
}
if ((status = sys$getsyiw(EFN$C_ENF, 0, 0, SYI_items, 0, 0, 0))
!= SS$_NORMAL) {
lib$signal(status);
return 0;
}
if ((status = lib$get_ef(&efn)) != SS$_NORMAL) {
lib$signal(status);
return 0;
}
if ((status = sys$getrmi(efn, 0, 0, RMI_items_64bit, &iosb, 0, 0))
!= SS$_NORMAL) {
lib$signal(status);
return 0;
}
if ((status = sys$synch(efn, &iosb)) != SS$_NORMAL) {
lib$signal(status);
return 0;
}
if (iosb.iosb$l_getxxi_status != SS$_NORMAL) {
lib$signal(iosb.iosb$l_getxxi_status);
return 0;
}
if ((status = sys$getrmi(efn, 0, 0, RMI_items, &iosb, 0, 0))
!= SS$_NORMAL) {
lib$signal(status);
return 0;
}
if ((status = sys$synch(efn, &iosb)) != SS$_NORMAL) {
lib$signal(status);
return 0;
}
if (iosb.iosb$l_getxxi_status != SS$_NORMAL) {
lib$signal(iosb.iosb$l_getxxi_status);
return 0;
}
if ((status = lib$free_ef(&efn)) != SS$_NORMAL) {
lib$signal(status);
return 0;
}
}
massage_JPI(JPI_items);
if (!ossl_assert(total_length >= bytes_needed)) {
ERR_raise_data(ERR_LIB_RAND, RAND_R_RANDOM_POOL_UNDERFLOW,
"Needed: %zu, Available: %zu",
bytes_needed, total_length);
return 0;
}
if (total_length > bytes_remaining)
total_length = bytes_remaining;
ossl_rand_pool_add(pool, (unsigned char *)data.buffer, total_length,
8 * total_length / ENTROPY_FACTOR);
return ossl_rand_pool_entropy_available(pool);
}
#define PUBLIC_VECTORS "SYS$LIBRARY:SYS$PUBLIC_VECTORS.EXE"
#define GET_ENTROPY "SYS$GET_ENTROPY"
static int get_entropy_address_flag = 0;
static int (*get_entropy_address)(void *buffer, size_t buffer_size) = NULL;
static int init_get_entropy_address(void)
{
if (get_entropy_address_flag == 0)
get_entropy_address = dlsym(dlopen(PUBLIC_VECTORS, 0), GET_ENTROPY);
get_entropy_address_flag = 1;
return get_entropy_address != NULL;
}
size_t get_entropy_method(RAND_POOL *pool)
{
unsigned char buffer[256];
size_t bytes_needed;
size_t bytes_to_get = 0;
uint32_t status;
for (bytes_needed = ossl_rand_pool_bytes_needed(pool, 1);
bytes_needed > 0;
bytes_needed -= bytes_to_get) {
bytes_to_get = bytes_needed > sizeof(buffer) ? sizeof(buffer) : bytes_needed;
status = get_entropy_address(buffer, bytes_to_get);
if (status == SS$_RETRY) {
bytes_to_get = 0;
continue;
}
if (status != SS$_NORMAL) {
lib$signal(status);
return 0;
}
ossl_rand_pool_add(pool, buffer, bytes_to_get, 8 * bytes_to_get);
}
return ossl_rand_pool_entropy_available(pool);
}
size_t ossl_pool_acquire_entropy(RAND_POOL *pool)
{
if (init_get_entropy_address())
return get_entropy_method(pool);
return data_collect_method(pool);
}
int ossl_pool_add_nonce_data(RAND_POOL *pool)
{
static unsigned __int64 last_time = 0;
static unsigned __int32 last_seq = 0;
struct {
pid_t pid;
CRYPTO_THREAD_ID tid;
unsigned __int64 time;
unsigned __int32 seq;
} data;
memset(&data, 0, sizeof(data));
data.pid = getpid();
data.tid = CRYPTO_THREAD_get_current_id();
data.seq = 0;
sys$gettim((void *)&data.time);
if (data.time == last_time) {
data.seq = ++last_seq;
} else {
last_time = data.time;
last_seq = 0;
}
return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
}
int ossl_rand_pool_init(void)
{
return 1;
}
void ossl_rand_pool_cleanup(void)
{
}
void ossl_rand_pool_keep_random_devices_open(int keep)
{
}