os/ossrv/ssl/libcrypto/src/crypto/rand/rand_egd.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/* crypto/rand/rand_egd.c */
sl@0
     2
/* Written by Ulf Moeller and Lutz Jaenicke for the OpenSSL project. */
sl@0
     3
/* ====================================================================
sl@0
     4
 * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
sl@0
     5
 *
sl@0
     6
 * Redistribution and use in source and binary forms, with or without
sl@0
     7
 * modification, are permitted provided that the following conditions
sl@0
     8
 * are met:
sl@0
     9
 *
sl@0
    10
 * 1. Redistributions of source code must retain the above copyright
sl@0
    11
 *    notice, this list of conditions and the following disclaimer. 
sl@0
    12
 *
sl@0
    13
 * 2. Redistributions in binary form must reproduce the above copyright
sl@0
    14
 *    notice, this list of conditions and the following disclaimer in
sl@0
    15
 *    the documentation and/or other materials provided with the
sl@0
    16
 *    distribution.
sl@0
    17
 *
sl@0
    18
 * 3. All advertising materials mentioning features or use of this
sl@0
    19
 *    software must display the following acknowledgment:
sl@0
    20
 *    "This product includes software developed by the OpenSSL Project
sl@0
    21
 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
sl@0
    22
 *
sl@0
    23
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
sl@0
    24
 *    endorse or promote products derived from this software without
sl@0
    25
 *    prior written permission. For written permission, please contact
sl@0
    26
 *    openssl-core@openssl.org.
sl@0
    27
 *
sl@0
    28
 * 5. Products derived from this software may not be called "OpenSSL"
sl@0
    29
 *    nor may "OpenSSL" appear in their names without prior written
sl@0
    30
 *    permission of the OpenSSL Project.
sl@0
    31
 *
sl@0
    32
 * 6. Redistributions of any form whatsoever must retain the following
sl@0
    33
 *    acknowledgment:
sl@0
    34
 *    "This product includes software developed by the OpenSSL Project
sl@0
    35
 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
sl@0
    36
 *
sl@0
    37
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
sl@0
    38
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
sl@0
    39
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
sl@0
    40
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
sl@0
    41
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
sl@0
    42
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
sl@0
    43
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
sl@0
    44
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
sl@0
    45
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
sl@0
    46
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
sl@0
    47
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
sl@0
    48
 * OF THE POSSIBILITY OF SUCH DAMAGE.
sl@0
    49
 * ====================================================================
sl@0
    50
 *
sl@0
    51
 * This product includes cryptographic software written by Eric Young
sl@0
    52
 * (eay@cryptsoft.com).  This product includes software written by Tim
sl@0
    53
 * Hudson (tjh@cryptsoft.com).
sl@0
    54
 *
sl@0
    55
 */
sl@0
    56
/*
sl@0
    57
 © Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
sl@0
    58
 */
sl@0
    59
#include <openssl/e_os2.h>
sl@0
    60
#include <openssl/rand.h>
sl@0
    61
#include <openssl/buffer.h>
sl@0
    62
sl@0
    63
/*
sl@0
    64
 * Query the EGD <URL: http://www.lothar.com/tech/crypto/>.
sl@0
    65
 *
sl@0
    66
 * This module supplies three routines:
sl@0
    67
 *
sl@0
    68
 * RAND_query_egd_bytes(path, buf, bytes)
sl@0
    69
 *   will actually query "bytes" bytes of entropy form the egd-socket located
sl@0
    70
 *   at path and will write them to buf (if supplied) or will directly feed
sl@0
    71
 *   it to RAND_seed() if buf==NULL.
sl@0
    72
 *   The number of bytes is not limited by the maximum chunk size of EGD,
sl@0
    73
 *   which is 255 bytes. If more than 255 bytes are wanted, several chunks
sl@0
    74
 *   of entropy bytes are requested. The connection is left open until the
sl@0
    75
 *   query is competed.
sl@0
    76
 *   RAND_query_egd_bytes() returns with
sl@0
    77
 *     -1  if an error occured during connection or communication.
sl@0
    78
 *     num the number of bytes read from the EGD socket. This number is either
sl@0
    79
 *         the number of bytes requested or smaller, if the EGD pool is
sl@0
    80
 *         drained and the daemon signals that the pool is empty.
sl@0
    81
 *   This routine does not touch any RAND_status(). This is necessary, since
sl@0
    82
 *   PRNG functions may call it during initialization.
sl@0
    83
 *
sl@0
    84
 * RAND_egd_bytes(path, bytes) will query "bytes" bytes and have them
sl@0
    85
 *   used to seed the PRNG.
sl@0
    86
 *   RAND_egd_bytes() is a wrapper for RAND_query_egd_bytes() with buf=NULL.
sl@0
    87
 *   Unlike RAND_query_egd_bytes(), RAND_status() is used to test the
sl@0
    88
 *   seed status so that the return value can reflect the seed state:
sl@0
    89
 *     -1  if an error occured during connection or communication _or_
sl@0
    90
 *         if the PRNG has still not received the required seeding.
sl@0
    91
 *     num the number of bytes read from the EGD socket. This number is either
sl@0
    92
 *         the number of bytes requested or smaller, if the EGD pool is
sl@0
    93
 *         drained and the daemon signals that the pool is empty.
sl@0
    94
 *
sl@0
    95
 * RAND_egd(path) will query 255 bytes and use the bytes retreived to seed
sl@0
    96
 *   the PRNG.
sl@0
    97
 *   RAND_egd() is a wrapper for RAND_egd_bytes() with numbytes=255.
sl@0
    98
 */
sl@0
    99
/*
sl@0
   100
 © Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
sl@0
   101
 */
sl@0
   102
sl@0
   103
#if defined(SYMBIAN)||defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_NETWARE) || defined(OPENSSL_SYS_VOS)
sl@0
   104
EXPORT_C int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
sl@0
   105
	{
sl@0
   106
	return(-1);
sl@0
   107
	}
sl@0
   108
EXPORT_C int RAND_egd(const char *path)
sl@0
   109
	{
sl@0
   110
	return(-1);
sl@0
   111
	}
sl@0
   112
sl@0
   113
EXPORT_C int RAND_egd_bytes(const char *path,int bytes)
sl@0
   114
	{
sl@0
   115
	return(-1);
sl@0
   116
	}
sl@0
   117
	
sl@0
   118
#else
sl@0
   119
#include <openssl/opensslconf.h>
sl@0
   120
#include OPENSSL_UNISTD
sl@0
   121
#include <sys/types.h>
sl@0
   122
#include <sys/socket.h>
sl@0
   123
#ifndef NO_SYS_UN_H
sl@0
   124
# ifdef OPENSSL_SYS_VXWORKS
sl@0
   125
#   include <streams/un.h>
sl@0
   126
# else
sl@0
   127
#   include <sys/un.h>
sl@0
   128
# endif
sl@0
   129
#else
sl@0
   130
struct	sockaddr_un {
sl@0
   131
	short	sun_family;		/* AF_UNIX */
sl@0
   132
	char	sun_path[108];		/* path name (gag) */
sl@0
   133
};
sl@0
   134
#endif /* NO_SYS_UN_H */
sl@0
   135
#include <string.h>
sl@0
   136
#include <errno.h>
sl@0
   137
sl@0
   138
#ifndef offsetof
sl@0
   139
#  define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
sl@0
   140
#endif
sl@0
   141
sl@0
   142
int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
sl@0
   143
	{
sl@0
   144
	int ret = 0;
sl@0
   145
	struct sockaddr_un addr;
sl@0
   146
	int len, num, numbytes;
sl@0
   147
	int fd = -1;
sl@0
   148
	int success;
sl@0
   149
	unsigned char egdbuf[2], tempbuf[255], *retrievebuf;
sl@0
   150
sl@0
   151
	memset(&addr, 0, sizeof(addr));
sl@0
   152
	addr.sun_family = AF_UNIX;
sl@0
   153
	if (strlen(path) >= sizeof(addr.sun_path))
sl@0
   154
		return (-1);
sl@0
   155
	BUF_strlcpy(addr.sun_path,path,sizeof addr.sun_path);
sl@0
   156
	len = offsetof(struct sockaddr_un, sun_path) + strlen(path);
sl@0
   157
	fd = socket(AF_UNIX, SOCK_STREAM, 0);
sl@0
   158
	if (fd == -1) return (-1);
sl@0
   159
	success = 0;
sl@0
   160
	while (!success)
sl@0
   161
	    {
sl@0
   162
	    if (connect(fd, (struct sockaddr *)&addr, len) == 0)
sl@0
   163
	       success = 1;
sl@0
   164
	    else
sl@0
   165
		{
sl@0
   166
		switch (errno)
sl@0
   167
		    {
sl@0
   168
#ifdef EINTR
sl@0
   169
		    case EINTR:
sl@0
   170
#endif
sl@0
   171
#ifdef EAGAIN
sl@0
   172
		    case EAGAIN:
sl@0
   173
#endif
sl@0
   174
#ifdef EINPROGRESS
sl@0
   175
		    case EINPROGRESS:
sl@0
   176
#endif
sl@0
   177
#ifdef EALREADY
sl@0
   178
		    case EALREADY:
sl@0
   179
#endif
sl@0
   180
			/* No error, try again */
sl@0
   181
			break;
sl@0
   182
#ifdef EISCONN
sl@0
   183
		    case EISCONN:
sl@0
   184
			success = 1;
sl@0
   185
			break;
sl@0
   186
#endif
sl@0
   187
		    default:
sl@0
   188
			goto err;	/* failure */
sl@0
   189
		    }
sl@0
   190
		}
sl@0
   191
	    }
sl@0
   192
sl@0
   193
	while(bytes > 0)
sl@0
   194
	    {
sl@0
   195
	    egdbuf[0] = 1;
sl@0
   196
	    egdbuf[1] = bytes < 255 ? bytes : 255;
sl@0
   197
	    numbytes = 0;
sl@0
   198
	    while (numbytes != 2)
sl@0
   199
		{
sl@0
   200
	        num = write(fd, egdbuf + numbytes, 2 - numbytes);
sl@0
   201
	        if (num >= 0)
sl@0
   202
		    numbytes += num;
sl@0
   203
	    	else
sl@0
   204
		    {
sl@0
   205
		    switch (errno)
sl@0
   206
		    	{
sl@0
   207
#ifdef EINTR
sl@0
   208
		    	case EINTR:
sl@0
   209
#endif
sl@0
   210
#ifdef EAGAIN
sl@0
   211
		    	case EAGAIN:
sl@0
   212
#endif
sl@0
   213
			    /* No error, try again */
sl@0
   214
			    break;
sl@0
   215
		    	default:
sl@0
   216
			    ret = -1;
sl@0
   217
			    goto err;	/* failure */
sl@0
   218
			}
sl@0
   219
		    }
sl@0
   220
		}
sl@0
   221
	    numbytes = 0;
sl@0
   222
	    while (numbytes != 1)
sl@0
   223
		{
sl@0
   224
	        num = read(fd, egdbuf, 1);
sl@0
   225
	        if (num == 0)
sl@0
   226
			goto err;	/* descriptor closed */
sl@0
   227
		else if (num > 0)
sl@0
   228
		    numbytes += num;
sl@0
   229
	    	else
sl@0
   230
		    {
sl@0
   231
		    switch (errno)
sl@0
   232
		    	{
sl@0
   233
#ifdef EINTR
sl@0
   234
		    	case EINTR:
sl@0
   235
#endif
sl@0
   236
#ifdef EAGAIN
sl@0
   237
		    	case EAGAIN:
sl@0
   238
#endif
sl@0
   239
			    /* No error, try again */
sl@0
   240
			    break;
sl@0
   241
		    	default:
sl@0
   242
			    ret = -1;
sl@0
   243
			    goto err;	/* failure */
sl@0
   244
			}
sl@0
   245
		    }
sl@0
   246
		}
sl@0
   247
	    if(egdbuf[0] == 0)
sl@0
   248
		goto err;
sl@0
   249
	    if (buf)
sl@0
   250
		retrievebuf = buf + ret;
sl@0
   251
	    else
sl@0
   252
		retrievebuf = tempbuf;
sl@0
   253
	    numbytes = 0;
sl@0
   254
	    while (numbytes != egdbuf[0])
sl@0
   255
		{
sl@0
   256
	        num = read(fd, retrievebuf + numbytes, egdbuf[0] - numbytes);
sl@0
   257
		if (num == 0)
sl@0
   258
			goto err;	/* descriptor closed */
sl@0
   259
	        else if (num > 0)
sl@0
   260
		    numbytes += num;
sl@0
   261
	    	else
sl@0
   262
		    {
sl@0
   263
		    switch (errno)
sl@0
   264
		    	{
sl@0
   265
#ifdef EINTR
sl@0
   266
		    	case EINTR:
sl@0
   267
#endif
sl@0
   268
#ifdef EAGAIN
sl@0
   269
		    	case EAGAIN:
sl@0
   270
#endif
sl@0
   271
			    /* No error, try again */
sl@0
   272
			    break;
sl@0
   273
		    	default:
sl@0
   274
			    ret = -1;
sl@0
   275
			    goto err;	/* failure */
sl@0
   276
			}
sl@0
   277
		    }
sl@0
   278
		}
sl@0
   279
	    ret += egdbuf[0];
sl@0
   280
	    bytes -= egdbuf[0];
sl@0
   281
	    if (!buf)
sl@0
   282
		RAND_seed(tempbuf, egdbuf[0]);
sl@0
   283
	    }
sl@0
   284
 err:
sl@0
   285
	if (fd != -1) close(fd);
sl@0
   286
	return(ret);
sl@0
   287
	}
sl@0
   288
sl@0
   289
sl@0
   290
int RAND_egd_bytes(const char *path, int bytes)
sl@0
   291
	{
sl@0
   292
	int num, ret = 0;
sl@0
   293
sl@0
   294
	num = RAND_query_egd_bytes(path, NULL, bytes);
sl@0
   295
	if (num < 1) goto err;
sl@0
   296
	if (RAND_status() == 1)
sl@0
   297
	    ret = num;
sl@0
   298
 err:
sl@0
   299
	return(ret);
sl@0
   300
	}
sl@0
   301
sl@0
   302
sl@0
   303
int RAND_egd(const char *path)
sl@0
   304
	{
sl@0
   305
	return (RAND_egd_bytes(path, 255));
sl@0
   306
	}
sl@0
   307
sl@0
   308
sl@0
   309
#endif