diff options
Diffstat (limited to 'crypto/openssl/crypto/rand/rand_egd.c')
-rw-r--r-- | crypto/openssl/crypto/rand/rand_egd.c | 135 |
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 |