rand_unix.c 5.4 KB
Newer Older
R
Rich Salz 已提交
1
/*
R
Rich Salz 已提交
2
 * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
3
 *
R
Rich Salz 已提交
4 5 6 7
 * Licensed under the OpenSSL license (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
8
 */
R
Rich Salz 已提交
9

R
Richard Levitte 已提交
10
#include <stdio.h>
11

12
#include "e_os.h"
13
#include "internal/cryptlib.h"
14 15
#include <openssl/rand.h>
#include "rand_lcl.h"
R
Rich Salz 已提交
16
#include <stdio.h>
17

R
Rich Salz 已提交
18
#if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI))
19

R
Rich Salz 已提交
20 21 22
# if (defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI)) && \
        !defined(OPENSSL_RAND_SEED_NONE)
#  error "UEFI and VXWorks only support seeding NONE"
23 24 25 26
# endif

# if defined(OPENSSL_SYS_VOS)

R
Rich Salz 已提交
27 28 29 30 31 32 33 34 35 36 37
#  ifndef OPENSSL_RAND_SEED_OS
#   error "Unsupported seeding method configured; must be os"
#  endif

#  if defined(OPENSSL_SYS_VOS_HPPA) && defined(OPENSSL_SYS_VOS_IA32)
#   error "Unsupported HP-PA and IA32 at the same time."
#  endif
#  if !defined(OPENSSL_SYS_VOS_HPPA) && !defined(OPENSSL_SYS_VOS_IA32)
#   error "Must have one of HP-PA or IA32"
#  endif

38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
/*
 * The following algorithm repeatedly samples the real-time clock (RTC) to
 * generate a sequence of unpredictable data.  The algorithm relies upon the
 * uneven execution speed of the code (due to factors such as cache misses,
 * interrupts, bus activity, and scheduling) and upon the rather large
 * relative difference between the speed of the clock and the rate at which
 * it can be read.
 *
 * If this code is ported to an environment where execution speed is more
 * constant or where the RTC ticks at a much slower rate, or the clock can be
 * read with fewer instructions, it is likely that the results would be far
 * more predictable.
 *
 * As a precaution, we generate 4 times the minimum required amount of seed
 * data.
 */
D
Dr. Stephen Henson 已提交
54 55
int RAND_poll(void)
{
56 57 58 59 60 61 62 63 64 65 66 67 68
    short int code;
    gid_t curr_gid;
    pid_t curr_pid;
    uid_t curr_uid;
    int i, k;
    struct timespec ts;
    unsigned char v;
#  ifdef OPENSSL_SYS_VOS_HPPA
    long duration;
    extern void s$sleep(long *_duration, short int *_code);
#  else
    long long duration;
    extern void s$sleep2(long long *_duration, short int *_code);
R
Rich Salz 已提交
69
#  endif
70 71 72 73 74 75

    /*
     * Seed with the gid, pid, and uid, to ensure *some* variation between
     * different processes.
     */
    curr_gid = getgid();
R
Rich Salz 已提交
76
    RAND_add(&curr_gid, sizeof curr_gid, 0);
77
    curr_pid = getpid();
R
Rich Salz 已提交
78
    RAND_add(&curr_pid, sizeof curr_pid, 0);
79
    curr_uid = getuid();
R
Rich Salz 已提交
80
    RAND_add(&curr_uid, sizeof curr_uid, 0);
81

R
Rich Salz 已提交
82
    for (i = 0; i < (RANDOMNESS_NEEDED * 4); i++) {
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
        /*
         * burn some cpu; hope for interrupts, cache collisions, bus
         * interference, etc.
         */
        for (k = 0; k < 99; k++)
            ts.tv_nsec = random();

#  ifdef OPENSSL_SYS_VOS_HPPA
        /* sleep for 1/1024 of a second (976 us).  */
        duration = 1;
        s$sleep(&duration, &code);
#  else
        /* sleep for 1/65536 of a second (15 us).  */
        duration = 1;
        s$sleep2(&duration, &code);
R
Rich Salz 已提交
98
#  endif
99

R
Rich Salz 已提交
100
        /* Get wall clock time, take 8 bits. */
101
        clock_gettime(CLOCK_REALTIME, &ts);
R
Rich Salz 已提交
102
        v = (unsigned char)(ts.tv_nsec & 0xFF);
103 104 105
        RAND_add(&v, sizeof v, 1);
    }
    return 1;
D
Dr. Stephen Henson 已提交
106
}
R
Rich Salz 已提交
107

R
Rich Salz 已提交
108
# else
R
Rich Salz 已提交
109 110 111 112

#  if defined(OPENSSL_RAND_SEED_EGD) && \
        (defined(OPENSSL_NO_EGD) || !defined(DEVRANDOM_EGD))
#   error "Seeding uses EGD but EGD is turned off or no device given"
113 114
#  endif

R
Rich Salz 已提交
115 116 117
#  if defined(OPENSSL_RAND_SEED_DEVRANDOM) && !defined(DEVRANDOM)
#   error "Seeding uses urandom but DEVRANDOM is not configured"
#  endif
118

R
Rich Salz 已提交
119 120 121 122 123
#  if defined(OPENSSL_RAND_SEED_OS)
#   if defined(DEVRANDOM)
#    define OPENSSL_RAND_SEED_DEVRANDOM
#   else
#    error "OS seeding requires DEVRANDOM to be configured"
124
#   endif
R
Rich Salz 已提交
125
#  endif
126

R
Rich Salz 已提交
127 128 129
#  if defined(OPENSSL_RAND_SEED_LIBRANDOM)
#   error "librandom not (yet) supported"
#  endif
130

R
Rich Salz 已提交
131 132 133 134 135 136 137 138
int RAND_poll(void)
{
#  ifdef OPENSSL_RAND_SEED_NONE
    return 0;
#  else
    int ok = 0;
    char temp[RANDOMNESS_NEEDED];
#   define TEMPSIZE (int)sizeof(temp)
139

R
Rich Salz 已提交
140 141 142
#   ifdef OPENSSL_RAND_SEED_RDTSC
    rand_rdtsc();
#   endif
143

R
Rich Salz 已提交
144 145 146
#   ifdef OPENSSL_RAND_SEED_RDCPU
    if (rand_rdcpu())
        ok++;
147 148
#   endif

R
Rich Salz 已提交
149 150 151 152
#   ifdef OPENSSL_RAND_SEED_EGD
    {
        static const char *paths[] = { DEVRANDOM_EGD, NULL };
        int i;
153

R
Rich Salz 已提交
154 155 156 157 158
        for (i = 0; paths[i] != NULL; i++) {
            if (RAND_query_egd_bytes(paths[i], temp, TEMPSIZE) == TEMPSIZE) {
                RAND_add(temp, TEMPSIZE, TEMPSIZE);
                ok++;
                break;
159 160 161
            }
        }
    }
R
Rich Salz 已提交
162
#   endif
163

R
Rich Salz 已提交
164 165 166 167 168
#   ifdef OPENSSL_RAND_SEED_DEVRANDOM
    {
        static const char *paths[] = { DEVRANDOM, NULL };
        FILE *fp;
        int i;
169

R
Rich Salz 已提交
170 171 172 173 174 175 176 177 178 179 180
        for (i = 0; paths[i] != NULL; i++) {
            if ((fp = fopen(paths[i], "rb")) == NULL)
                continue;
            setbuf(fp, NULL);
            if (fread(temp, 1, TEMPSIZE, fp) == TEMPSIZE) {
                RAND_add(temp, TEMPSIZE, TEMPSIZE);
                ok++;
                fclose(fp);
                break;
            }
        }
181
    }
R
Rich Salz 已提交
182
#   endif
183

R
Rich Salz 已提交
184 185 186
#   ifdef OPENSSL_RAND_SEED_GETRANDOM
    {
        int i = getrandom(temp, TEMPSIZE, 0);
187

R
Rich Salz 已提交
188 189 190 191 192 193 194
        if (i >= 0) {
            RAND_add(temp, i, i);
            if (i == TEMPSIZE)
                ok++;
        }
    }
#   endif
195

R
Rich Salz 已提交
196 197
    OPENSSL_cleanse(temp, TEMPSIZE);
    return ok > 0 ? 1 : 0;
198
#  endif
199
}
R
Rich Salz 已提交
200
# endif
201

202
#endif