📄 scrandom.c
字号:
/* * $Id: scrandom.c,v 1.10 2003/09/03 18:18:57 aet Exp $ * * Copyright (C) 2002 * Antti Tapaninen <aet@cc.hut.fi> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#ifdef HAVE_CONFIG_H#include <config.h>#endif#ifndef _WIN32#include <stdio.h>#include <stdlib.h>#include <string.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <errno.h>#include <sys/un.h>#include <sys/socket.h>#include <netinet/in.h>#if !defined(RANDOM_POOL) && !defined(PRNGD_PORT) && !defined(PRNGD_SOCKET)#define USE_SRANDOM#include <time.h>#endif#include "scrandom.h"#if defined(PRNGD_SOCKET) || defined(PRNGD_PORT)#include <signal.h>#ifndef offsetof#define offsetof(type, member) ((size_t) &((type *)0)->member)#endiftypedef void (*mysig_t) (int);static mysig_t mysignal(int sig, mysig_t act){#ifdef HAVE_SIGACTION struct sigaction sa, osa; if (sigaction(sig, NULL, &osa) == -1) { return (mysig_t) - 1; } if (osa.sa_handler != act) { memset(&sa, 0, sizeof(sa)); sigemptyset(&sa.sa_mask); sa.sa_flags = 0;#if defined(SA_INTERRUPT) if (sig == SIGALRM) { sa.sa_flags |= SA_INTERRUPT; }#endif sa.sa_handler = act; if (sigaction(sig, &sa, NULL) == -1) { return (mysig_t) - 1; } } return osa.sa_handler;#else return signal(sig, act);#endif}#endif#if !defined(USE_SRANDOM)static ssize_t atomicio(ssize_t(*f) (int fd, void *_s, size_t n), int fd, void *_s, size_t n){ char *s = (char *) _s; size_t pos = 0; ssize_t res; while (n > pos) { res = (f) (fd, s + pos, n - pos); switch (res) { case -1: if (errno == EINTR || errno == EAGAIN) { continue; } case 0: return res; default: pos += res; } } return pos;}/* Get entropy from: * /dev/[u]random or pipe * PRNGD/EGD (socket) * PRNGD/EGD (port) */static int scrandom_get_bytes(unsigned char *buf, int len){ int fd;#if defined(RANDOM_POOL) fd = open(RANDOM_POOL, O_RDONLY); if (fd == -1) { fprintf(stderr, "Couldn't open random pool \"%s\": %s\n", RANDOM_POOL, strerror(errno)); return 0; } if (atomicio(read, fd, buf, len) != len) { fprintf(stderr, "Couldn't read from random pool \"%s\": %s\n", RANDOM_POOL, strerror(errno)); close(fd); return 0; } close(fd); return 1;#elif defined(PRNGD_SOCKET) int addr_len, rval, errors; struct sockaddr_un addr; mysig_t old_sigpipe; char msg[2]; memset(&addr, 0, sizeof(addr)); if (sizeof(PRNGD_SOCKET) > sizeof(addr.sun_path)) { fprintf(stderr, "Random pool path is too long"); return 0; } if (len > 255) { fprintf(stderr, "Too many bytes to read from PRNGD"); return 0; } addr.sun_family = AF_UNIX; strncpy(addr.sun_path, PRNGD_SOCKET, sizeof(addr.sun_path)); addr_len = offsetof(struct sockaddr_un, sun_path) + sizeof(PRNGD_SOCKET); old_sigpipe = mysignal(SIGPIPE, SIG_IGN); errors = rval = 0; reopen: fd = socket(addr.sun_family, SOCK_STREAM, 0); if (fd == -1) { fprintf(stderr, "Couldn't create AF_UNIX socket: %s\n", strerror(errno)); goto done; } if (connect(fd, (struct sockaddr *) &addr, addr_len) == -1) { fprintf(stderr, "Couldn't connect to PRNGD socket \"%s\": %s\n", addr.sun_path, strerror(errno)); goto done; } /* Send blocking read request to PRNGD */ msg[0] = 0x02; msg[1] = len; if (atomicio(write, fd, msg, sizeof(msg)) != sizeof(msg)) { if (errno == EPIPE && errors < 10) { close(fd); errors++; goto reopen; } fprintf(stderr, "Couldn't write to PRNGD socket: %s\n", strerror(errno)); goto done; } if (atomicio(read, fd, buf, len) != len) { if (errno == EPIPE && errors < 10) { close(fd); errors++; goto reopen; } fprintf(stderr, "Couldn't read from PRNGD socket: %s\n", strerror(errno)); goto done; } rval = 1; done: mysignal(SIGPIPE, old_sigpipe); if (fd != -1) { close(fd); } return rval;#elif defined(PRNGD_PORT) int addr_len, rval, errors; struct sockaddr_in addr; mysig_t old_sigpipe; char msg[2]; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); addr.sin_port = htons(PRNGD_PORT); addr_len = sizeof(struct sockaddr_in); old_sigpipe = mysignal(SIGPIPE, SIG_IGN); errors = rval = 0; reopen: fd = socket(addr.sin_family, SOCK_STREAM, 0); if (fd == -1) { fprintf(stderr, "Couldn't create AF_INET socket: %s\n", strerror(errno)); goto done; } if (connect(fd, (struct sockaddr *) &addr, addr_len) == -1) { fprintf(stderr, "Couldn't connect to PRNGD port %d: %s\n", PRNGD_PORT, strerror(errno)); goto done; } /* Send blocking read request to PRNGD */ msg[0] = 0x02; msg[1] = len; if (atomicio(write, fd, msg, sizeof(msg)) != sizeof(msg)) { if (errno == EPIPE && errors < 10) { close(fd); errors++; goto reopen; } fprintf(stderr, "Couldn't write to PRNGD socket: %s\n", strerror(errno)); goto done; } if (atomicio(read, fd, buf, len) != len) { if (errno == EPIPE && errors < 10) { close(fd); errors++; goto reopen; } fprintf(stderr, "Couldn't read from PRNGD socket: %s\n", strerror(errno)); goto done; } rval = 1; done: mysignal(SIGPIPE, old_sigpipe); if (fd != -1) { close(fd); } return rval;#endif return 0;}#endif/* Read random data from random data source */int scrandom_get_data(unsigned char *buf, unsigned int len){#define BLOCK_SIZE 255 int rv = -1;#if !defined(USE_SRANDOM) unsigned int div, mod, i, bytes; unsigned char *p;#endif if (!buf || !len) { return -1; }#if !defined(USE_SRANDOM) div = len / BLOCK_SIZE; mod = len % BLOCK_SIZE; p = buf; for (i = 0; i <= div; i++) { bytes = 0; if (div == i) { bytes = mod; } else { bytes = BLOCK_SIZE; } if (bytes) { if (!scrandom_get_bytes(p, bytes)) { rv = -1; } else { if (rv < 0) rv = 0; rv += bytes; p += bytes; } if (rv < 0) { break; } } }#else /* Well, this is only for testing/porting purposes anyway */ /* FIXME: We could add something like Mersenne Twister - pseudorandom number generator, although that won't either fit into cryptography purposes. So why bother? */ srandom((len + (unsigned int) time(NULL))); for (rv = 0; rv < len; rv++) { buf[rv] = (unsigned char) random(); } rv = len;#endif return rv;#undef BLOCK_SIZE}#else/* Since the above is very *nix specific, we use Window's CryptoAPI * random generation instead. */#include "scrandom.h"#include <wincrypt.h>int scrandom_get_data(unsigned char *buf, unsigned int len){ HCRYPTPROV hProv = 0; if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) return GetLastError(); if(!CryptGenRandom(hProv, len, buf)) return GetLastError(); CryptReleaseContext(hProv, 0); return 0;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -