Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* |
michael@0 | 2 | * rand_source.c |
michael@0 | 3 | * |
michael@0 | 4 | * implements a random source based on /dev/random |
michael@0 | 5 | * |
michael@0 | 6 | * David A. McGrew |
michael@0 | 7 | * Cisco Systems, Inc. |
michael@0 | 8 | */ |
michael@0 | 9 | /* |
michael@0 | 10 | * |
michael@0 | 11 | * Copyright(c) 2001-2006 Cisco Systems, Inc. |
michael@0 | 12 | * All rights reserved. |
michael@0 | 13 | * |
michael@0 | 14 | * Redistribution and use in source and binary forms, with or without |
michael@0 | 15 | * modification, are permitted provided that the following conditions |
michael@0 | 16 | * are met: |
michael@0 | 17 | * |
michael@0 | 18 | * Redistributions of source code must retain the above copyright |
michael@0 | 19 | * notice, this list of conditions and the following disclaimer. |
michael@0 | 20 | * |
michael@0 | 21 | * Redistributions in binary form must reproduce the above |
michael@0 | 22 | * copyright notice, this list of conditions and the following |
michael@0 | 23 | * disclaimer in the documentation and/or other materials provided |
michael@0 | 24 | * with the distribution. |
michael@0 | 25 | * |
michael@0 | 26 | * Neither the name of the Cisco Systems, Inc. nor the names of its |
michael@0 | 27 | * contributors may be used to endorse or promote products derived |
michael@0 | 28 | * from this software without specific prior written permission. |
michael@0 | 29 | * |
michael@0 | 30 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
michael@0 | 31 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
michael@0 | 32 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
michael@0 | 33 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
michael@0 | 34 | * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
michael@0 | 35 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
michael@0 | 36 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
michael@0 | 37 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
michael@0 | 38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
michael@0 | 39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
michael@0 | 40 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
michael@0 | 41 | * OF THE POSSIBILITY OF SUCH DAMAGE. |
michael@0 | 42 | * |
michael@0 | 43 | */ |
michael@0 | 44 | |
michael@0 | 45 | #include "config.h" |
michael@0 | 46 | |
michael@0 | 47 | #ifdef DEV_URANDOM |
michael@0 | 48 | # include <fcntl.h> /* for open() */ |
michael@0 | 49 | # include <unistd.h> /* for close() */ |
michael@0 | 50 | #elif defined(HAVE_RAND_S) |
michael@0 | 51 | # define _CRT_RAND_S |
michael@0 | 52 | # include <stdlib.h> |
michael@0 | 53 | #else |
michael@0 | 54 | # include <stdio.h> |
michael@0 | 55 | #endif |
michael@0 | 56 | |
michael@0 | 57 | #include "rand_source.h" |
michael@0 | 58 | |
michael@0 | 59 | |
michael@0 | 60 | /* |
michael@0 | 61 | * global dev_rand_fdes is file descriptor for /dev/random |
michael@0 | 62 | * |
michael@0 | 63 | * This variable is also used to indicate that the random source has |
michael@0 | 64 | * been initialized. When this variable is set to the value of the |
michael@0 | 65 | * #define RAND_SOURCE_NOT_READY, it indicates that the random source |
michael@0 | 66 | * is not ready to be used. The value of the #define |
michael@0 | 67 | * RAND_SOURCE_READY is for use whenever that variable is used as an |
michael@0 | 68 | * indicator of the state of the random source, but not as a file |
michael@0 | 69 | * descriptor. |
michael@0 | 70 | */ |
michael@0 | 71 | |
michael@0 | 72 | #define RAND_SOURCE_NOT_READY (-1) |
michael@0 | 73 | #define RAND_SOURCE_READY (17) |
michael@0 | 74 | |
michael@0 | 75 | static int dev_random_fdes = RAND_SOURCE_NOT_READY; |
michael@0 | 76 | |
michael@0 | 77 | |
michael@0 | 78 | err_status_t |
michael@0 | 79 | rand_source_init(void) { |
michael@0 | 80 | if (dev_random_fdes >= 0) { |
michael@0 | 81 | /* already open */ |
michael@0 | 82 | return err_status_ok; |
michael@0 | 83 | } |
michael@0 | 84 | #ifdef DEV_URANDOM |
michael@0 | 85 | /* open random source for reading */ |
michael@0 | 86 | dev_random_fdes = open(DEV_URANDOM, O_RDONLY); |
michael@0 | 87 | if (dev_random_fdes < 0) |
michael@0 | 88 | return err_status_init_fail; |
michael@0 | 89 | #elif defined(HAVE_RAND_S) |
michael@0 | 90 | dev_random_fdes = RAND_SOURCE_READY; |
michael@0 | 91 | #else |
michael@0 | 92 | /* no random source available; let the user know */ |
michael@0 | 93 | fprintf(stderr, "WARNING: no real random source present!\n"); |
michael@0 | 94 | dev_random_fdes = RAND_SOURCE_READY; |
michael@0 | 95 | #endif |
michael@0 | 96 | return err_status_ok; |
michael@0 | 97 | } |
michael@0 | 98 | |
michael@0 | 99 | err_status_t |
michael@0 | 100 | rand_source_get_octet_string(void *dest, uint32_t len) { |
michael@0 | 101 | |
michael@0 | 102 | /* |
michael@0 | 103 | * read len octets from /dev/random to dest, and |
michael@0 | 104 | * check return value to make sure enough octets were |
michael@0 | 105 | * written |
michael@0 | 106 | */ |
michael@0 | 107 | #ifdef DEV_URANDOM |
michael@0 | 108 | uint8_t *dst = (uint8_t *)dest; |
michael@0 | 109 | while (len) |
michael@0 | 110 | { |
michael@0 | 111 | ssize_t num_read = read(dev_random_fdes, dst, len); |
michael@0 | 112 | if (num_read <= 0 || num_read > len) |
michael@0 | 113 | return err_status_fail; |
michael@0 | 114 | len -= num_read; |
michael@0 | 115 | dst += num_read; |
michael@0 | 116 | } |
michael@0 | 117 | #elif defined(HAVE_RAND_S) |
michael@0 | 118 | uint8_t *dst = (uint8_t *)dest; |
michael@0 | 119 | while (len) |
michael@0 | 120 | { |
michael@0 | 121 | unsigned int val; |
michael@0 | 122 | errno_t err = rand_s(&val); |
michael@0 | 123 | |
michael@0 | 124 | if (err != 0) |
michael@0 | 125 | return err_status_fail; |
michael@0 | 126 | |
michael@0 | 127 | *dst++ = val & 0xff; |
michael@0 | 128 | len--; |
michael@0 | 129 | } |
michael@0 | 130 | #else |
michael@0 | 131 | /* Generic C-library (rand()) version */ |
michael@0 | 132 | /* This is a random source of last resort */ |
michael@0 | 133 | uint8_t *dst = (uint8_t *)dest; |
michael@0 | 134 | while (len) |
michael@0 | 135 | { |
michael@0 | 136 | int val = rand(); |
michael@0 | 137 | /* rand() returns 0-32767 (ugh) */ |
michael@0 | 138 | /* Is this a good enough way to get random bytes? |
michael@0 | 139 | It is if it passes FIPS-140... */ |
michael@0 | 140 | *dst++ = val & 0xff; |
michael@0 | 141 | len--; |
michael@0 | 142 | } |
michael@0 | 143 | #endif |
michael@0 | 144 | return err_status_ok; |
michael@0 | 145 | } |
michael@0 | 146 | |
michael@0 | 147 | err_status_t |
michael@0 | 148 | rand_source_deinit(void) { |
michael@0 | 149 | if (dev_random_fdes < 0) |
michael@0 | 150 | return err_status_dealloc_fail; /* well, we haven't really failed, * |
michael@0 | 151 | * but there is something wrong */ |
michael@0 | 152 | #ifdef DEV_URANDOM |
michael@0 | 153 | close(dev_random_fdes); |
michael@0 | 154 | #endif |
michael@0 | 155 | dev_random_fdes = RAND_SOURCE_NOT_READY; |
michael@0 | 156 | |
michael@0 | 157 | return err_status_ok; |
michael@0 | 158 | } |