1 /* 2 * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. 3 * 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 8 */ 9 10 #include <openssl/opensslconf.h> 11 #ifdef OPENSSL_NO_EGD 12 NON_EMPTY_TRANSLATION_UNIT 13 #else 14 15 # include <openssl/crypto.h> 16 # include <openssl/e_os2.h> 17 # include <openssl/rand.h> 18 19 /* 20 * Query an EGD 21 */ 22 23 # 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) 24 int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes) 25 { 26 return -1; 27 } 28 29 int RAND_egd(const char *path) 30 { 31 return -1; 32 } 33 34 int RAND_egd_bytes(const char *path, int bytes) 35 { 36 return -1; 37 } 38 39 # else 40 41 # include OPENSSL_UNISTD 42 # include <stddef.h> 43 # include <sys/types.h> 44 # include <sys/socket.h> 45 # ifndef NO_SYS_UN_H 46 # ifdef OPENSSL_SYS_VXWORKS 47 # include <streams/un.h> 48 # else 49 # include <sys/un.h> 50 # endif 51 # else 52 struct sockaddr_un { 53 short sun_family; /* AF_UNIX */ 54 char sun_path[108]; /* path name (gag) */ 55 }; 56 # endif /* NO_SYS_UN_H */ 57 # include <string.h> 58 # include <errno.h> 59 60 int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes) 61 { 62 FILE *fp = NULL; 63 struct sockaddr_un addr; 64 int mybuffer, ret = -1, i, numbytes, fd; 65 unsigned char tempbuf[255]; 66 67 if (bytes > (int)sizeof(tempbuf)) 68 return -1; 69 70 /* Make socket. */ 71 memset(&addr, 0, sizeof(addr)); 72 addr.sun_family = AF_UNIX; 73 if (strlen(path) >= sizeof(addr.sun_path)) 74 return -1; 75 strcpy(addr.sun_path, path); 76 i = offsetof(struct sockaddr_un, sun_path) + strlen(path); 77 fd = socket(AF_UNIX, SOCK_STREAM, 0); 78 if (fd == -1 || (fp = fdopen(fd, "r+")) == NULL) 79 return -1; 80 setbuf(fp, NULL); 81 82 /* Try to connect */ 83 for ( ; ; ) { 84 if (connect(fd, (struct sockaddr *)&addr, i) == 0) 85 break; 86 # ifdef EISCONN 87 if (errno == EISCONN) 88 break; 89 # endif 90 switch (errno) { 91 # ifdef EINTR 92 case EINTR: 93 # endif 94 # ifdef EAGAIN 95 case EAGAIN: 96 # endif 97 # ifdef EINPROGRESS 98 case EINPROGRESS: 99 # endif 100 # ifdef EALREADY 101 case EALREADY: 102 # endif 103 /* No error, try again */ 104 break; 105 default: 106 ret = -1; 107 goto err; 108 } 109 } 110 111 /* Make request, see how many bytes we can get back. */ 112 tempbuf[0] = 1; 113 tempbuf[1] = bytes; 114 if (fwrite(tempbuf, sizeof(char), 2, fp) != 2 || fflush(fp) == EOF) 115 goto err; 116 if (fread(tempbuf, sizeof(char), 1, fp) != 1 || tempbuf[0] == 0) 117 goto err; 118 numbytes = tempbuf[0]; 119 120 /* Which buffer are we using? */ 121 mybuffer = buf == NULL; 122 if (mybuffer) 123 buf = tempbuf; 124 125 /* Read bytes. */ 126 i = fread(buf, sizeof(char), numbytes, fp); 127 if (i < numbytes) 128 goto err; 129 ret = numbytes; 130 if (mybuffer) 131 RAND_add(tempbuf, i, i); 132 133 err: 134 if (fp != NULL) 135 fclose(fp); 136 return ret; 137 } 138 139 int RAND_egd_bytes(const char *path, int bytes) 140 { 141 int num; 142 143 num = RAND_query_egd_bytes(path, NULL, bytes); 144 if (num < 0) 145 return -1; 146 if (RAND_status() != 1) 147 return -1; 148 return num; 149 } 150 151 int RAND_egd(const char *path) 152 { 153 return RAND_egd_bytes(path, 255); 154 } 155 156 # endif 157 158 #endif 159