aboutsummaryrefslogtreecommitdiff
path: root/crypto/openssl/crypto/rand/rand_egd.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/openssl/crypto/rand/rand_egd.c')
-rw-r--r--crypto/openssl/crypto/rand/rand_egd.c135
1 files changed, 99 insertions, 36 deletions
diff --git a/crypto/openssl/crypto/rand/rand_egd.c b/crypto/openssl/crypto/rand/rand_egd.c
index da3017df3142..1699e7f38f0f 100644
--- a/crypto/openssl/crypto/rand/rand_egd.c
+++ b/crypto/openssl/crypto/rand/rand_egd.c
@@ -1,26 +1,23 @@
/*
- * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/opensslconf.h>
-#ifdef OPENSSL_NO_EGD
-NON_EMPTY_TRANSLATION_UNIT
-#else
-# include <openssl/crypto.h>
-# include <openssl/e_os2.h>
-# include <openssl/rand.h>
+#include <openssl/crypto.h>
+#include <openssl/e_os2.h>
+#include <openssl/rand.h>
/*
* Query an EGD
*/
-# if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_VOS) || defined(OPENSSL_SYS_UEFI)
+#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_VOS) || defined(OPENSSL_SYS_UEFI)
int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
{
return -1;
@@ -36,26 +33,78 @@ int RAND_egd_bytes(const char *path, int bytes)
return -1;
}
-# else
+#else
-# include OPENSSL_UNISTD
-# include <stddef.h>
-# include <sys/types.h>
-# include <sys/socket.h>
-# ifndef NO_SYS_UN_H
-# ifdef OPENSSL_SYS_VXWORKS
-# include <streams/un.h>
-# else
-# include <sys/un.h>
-# endif
-# else
+# include <unistd.h>
+# include <stddef.h>
+# include <sys/types.h>
+# include <sys/socket.h>
+# ifndef NO_SYS_UN_H
+# include <sys/un.h>
+# else
struct sockaddr_un {
short sun_family; /* AF_UNIX */
char sun_path[108]; /* path name (gag) */
};
-# endif /* NO_SYS_UN_H */
-# include <string.h>
-# include <errno.h>
+# endif /* NO_SYS_UN_H */
+# include <string.h>
+# include <errno.h>
+
+# if defined(OPENSSL_SYS_TANDEM)
+/*
+ * HPNS:
+ *
+ * This code forces the use of compatibility mode if required on HPE NonStop
+ * when coreutils PRNGD is used and then restores the previous mode
+ * after establishing the socket. This is not required on x86 where hardware
+ * randomization should be used instead of EGD available as of OpenSSL 3.0.
+ * Use --with-rand-seed=rdcpu when configuring x86 with 3.0 and above.
+ *
+ * Needs review:
+ *
+ * The better long-term solution is to either run two EGD's each in one of
+ * the two modes or revise the EGD code to listen on two different sockets
+ * (each in one of the two modes) or use the hardware randomizer.
+ */
+_variable
+int hpns_socket(int family,
+ int type,
+ int protocol,
+ char* transport)
+{
+ int socket_rc;
+ char current_transport[20];
+
+# define AF_UNIX_PORTABILITY "$ZAFN2"
+# define AF_UNIX_COMPATIBILITY "$ZPLS"
+
+ if (!_arg_present(transport) || transport == NULL || transport[0] == '\0')
+ return socket(family, type, protocol);
+
+ socket_transport_name_get(AF_UNIX, current_transport, 20);
+
+ if (strcmp(current_transport,transport) == 0)
+ return socket(family, type, protocol);
+
+ /* set the requested socket transport */
+ if (socket_transport_name_set(AF_UNIX, transport))
+ return -1;
+
+ socket_rc = socket(family,type,protocol);
+
+ /* set mode back to what it was */
+ if (socket_transport_name_set(AF_UNIX, current_transport))
+ return -1;
+
+ return socket_rc;
+}
+
+/*#define socket(a,b,c,...) hpns_socket(a,b,c,__VA_ARGS__) */
+
+static int hpns_connect_attempt = 0;
+
+# endif /* defined(OPENSSL_SYS_HPNS) */
+
int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
{
@@ -74,7 +123,11 @@ int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
return -1;
strcpy(addr.sun_path, path);
i = offsetof(struct sockaddr_un, sun_path) + strlen(path);
+#if defined(OPENSSL_SYS_TANDEM)
+ fd = hpns_socket(AF_UNIX, SOCK_STREAM, 0, AF_UNIX_COMPATIBILITY);
+#else
fd = socket(AF_UNIX, SOCK_STREAM, 0);
+#endif
if (fd == -1 || (fp = fdopen(fd, "r+")) == NULL)
return -1;
setbuf(fp, NULL);
@@ -83,26 +136,38 @@ int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
for ( ; ; ) {
if (connect(fd, (struct sockaddr *)&addr, i) == 0)
break;
-# ifdef EISCONN
+# ifdef EISCONN
if (errno == EISCONN)
break;
-# endif
+# endif
switch (errno) {
-# ifdef EINTR
+# ifdef EINTR
case EINTR:
-# endif
-# ifdef EAGAIN
+# endif
+# ifdef EAGAIN
case EAGAIN:
-# endif
-# ifdef EINPROGRESS
+# endif
+# ifdef EINPROGRESS
case EINPROGRESS:
-# endif
-# ifdef EALREADY
+# endif
+# ifdef EALREADY
case EALREADY:
-# endif
+# endif
/* No error, try again */
break;
default:
+# if defined(OPENSSL_SYS_TANDEM)
+ if (hpns_connect_attempt == 0) {
+ /* try the other kind of AF_UNIX socket */
+ close(fd);
+ fd = hpns_socket(AF_UNIX, SOCK_STREAM, 0, AF_UNIX_PORTABILITY);
+ if (fd == -1)
+ return -1;
+ ++hpns_connect_attempt;
+ break; /* try the connect again */
+ }
+# endif
+
ret = -1;
goto err;
}
@@ -153,6 +218,4 @@ int RAND_egd(const char *path)
return RAND_egd_bytes(path, 255);
}
-# endif
-
#endif