Coverage Report

Created: 2026-10-28 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl41/crypto/rand/prov_seed.c
Line
Count
Source
1
/*
2
 * Copyright 2020-2026 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (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 "rand_local.h"
11
#include "crypto/evp.h"
12
#include "crypto/rand.h"
13
#include "crypto/rand_pool.h"
14
#include "internal/core.h"
15
#include <openssl/core_dispatch.h>
16
#include <openssl/err.h>
17
#include <string.h>
18
19
size_t ossl_rand_get_entropy(ossl_unused OSSL_LIB_CTX *ctx,
20
    unsigned char **pout, int entropy,
21
    size_t min_len, size_t max_len)
22
1.30k
{
23
1.30k
    size_t ret = 0;
24
1.30k
    size_t entropy_available;
25
1.30k
    RAND_POOL *pool;
26
27
1.30k
    pool = ossl_rand_pool_new(entropy, 1, min_len, max_len);
28
1.30k
    if (pool == NULL) {
29
0
        ERR_raise(ERR_LIB_RAND, ERR_R_RAND_LIB);
30
0
        return 0;
31
0
    }
32
33
    /* Get entropy by polling system entropy sources. */
34
1.30k
    entropy_available = ossl_pool_acquire_entropy(pool);
35
36
1.30k
    if (entropy_available > 0) {
37
1.30k
        ret = ossl_rand_pool_length(pool);
38
1.30k
        *pout = ossl_rand_pool_detach(pool);
39
1.30k
    }
40
41
1.30k
    ossl_rand_pool_free(pool);
42
1.30k
    return ret;
43
1.30k
}
44
45
/*
46
 * Copy the seed into a buffer of our own and hand the original straight back
47
 * to the seed source. Otherwise ossl_rand_cleanup_user_entropy() would have
48
 * to work out who allocated |buf|, but a seed source may be created between
49
 * taking entropy from the operating system sources and cleaning it up, so
50
 * the seed source present at cleanup time does not tell.
51
 */
52
static size_t rand_get_seed_copy(EVP_RAND_CTX *rng, unsigned char **pout,
53
    int entropy, size_t min_len, size_t max_len)
54
238
{
55
238
    unsigned char *seed = NULL, *buf;
56
238
    size_t ret;
57
58
238
    ret = evp_rand_get_seed(rng, &seed, entropy, min_len, max_len,
59
238
        0, NULL, 0);
60
238
    if (ret == 0)
61
0
        return 0;
62
238
    buf = OPENSSL_secure_malloc(ret);
63
238
    if (buf != NULL)
64
238
        memcpy(buf, seed, ret);
65
238
    evp_rand_clear_seed(rng, seed, ret);
66
238
    if (buf == NULL)
67
0
        return 0;
68
238
    *pout = buf;
69
238
    return ret;
70
238
}
71
72
size_t ossl_rand_get_user_entropy(OSSL_LIB_CTX *ctx,
73
    unsigned char **pout, int entropy,
74
    size_t min_len, size_t max_len)
75
637
{
76
637
    EVP_RAND_CTX *rng;
77
78
637
    if (ossl_rand_seed_source_strict(ctx)) {
79
        /*
80
         * With strict seeding the seed source must be used, even when the
81
         * request arrives before anything instantiated it: create it now
82
         * and fail instead of silently substituting the operating system
83
         * entropy sources.
84
         */
85
0
        rng = ossl_rand_get0_seed(ctx);
86
0
        if (rng == NULL || !evp_rand_can_seed(rng)) {
87
0
            ERR_raise(ERR_LIB_RAND, RAND_R_ERROR_RETRIEVING_ENTROPY);
88
0
            return 0;
89
0
        }
90
637
    } else {
91
637
        rng = ossl_rand_get0_seed_noncreating(ctx);
92
637
        if (rng == NULL || !evp_rand_can_seed(rng))
93
399
            return ossl_rand_get_entropy(ctx, pout, entropy, min_len, max_len);
94
637
    }
95
238
    return rand_get_seed_copy(rng, pout, entropy, min_len, max_len);
96
637
}
97
98
void ossl_rand_cleanup_entropy(ossl_unused OSSL_LIB_CTX *ctx,
99
    unsigned char *buf, size_t len)
100
637
{
101
637
    OPENSSL_secure_clear_free(buf, len);
102
637
}
103
104
/* See rand_get_seed_copy() */
105
void ossl_rand_cleanup_user_entropy(OSSL_LIB_CTX *ctx,
106
    unsigned char *buf, size_t len)
107
637
{
108
637
    ossl_rand_cleanup_entropy(ctx, buf, len);
109
637
}
110
111
size_t ossl_rand_get_nonce(ossl_unused OSSL_LIB_CTX *ctx,
112
    unsigned char **pout,
113
    size_t min_len, ossl_unused size_t max_len,
114
    const void *salt, size_t salt_len)
115
629
{
116
629
    size_t ret = 0;
117
629
    RAND_POOL *pool;
118
119
629
    pool = ossl_rand_pool_new(0, 0, min_len, max_len);
120
629
    if (pool == NULL) {
121
0
        ERR_raise(ERR_LIB_RAND, ERR_R_RAND_LIB);
122
0
        return 0;
123
0
    }
124
125
629
    if (!ossl_pool_add_nonce_data(pool))
126
0
        goto err;
127
128
629
    if (salt != NULL && !ossl_rand_pool_add(pool, salt, salt_len, 0))
129
0
        goto err;
130
629
    ret = ossl_rand_pool_length(pool);
131
629
    *pout = ossl_rand_pool_detach(pool);
132
629
err:
133
629
    ossl_rand_pool_free(pool);
134
629
    return ret;
135
629
}
136
137
size_t ossl_rand_get_user_nonce(OSSL_LIB_CTX *ctx,
138
    unsigned char **pout,
139
    size_t min_len, size_t max_len,
140
    const void *salt, size_t salt_len)
141
306
{
142
306
    unsigned char *buf;
143
306
    EVP_RAND_CTX *rng;
144
145
306
    if (ossl_rand_seed_source_strict(ctx)) {
146
        /* See ossl_rand_get_user_entropy() */
147
0
        rng = ossl_rand_get0_seed(ctx);
148
0
        if (rng == NULL) {
149
0
            ERR_raise(ERR_LIB_RAND, RAND_R_ERROR_RETRIEVING_NONCE);
150
0
            return 0;
151
0
        }
152
306
    } else {
153
306
        rng = ossl_rand_get0_seed_noncreating(ctx);
154
306
        if (rng == NULL)
155
188
            return ossl_rand_get_nonce(ctx, pout, min_len, max_len,
156
188
                salt, salt_len);
157
306
    }
158
159
118
    if ((buf = OPENSSL_malloc(min_len)) == NULL)
160
0
        return 0;
161
162
118
    if (!EVP_RAND_generate(rng, buf, min_len, 0, 0, salt, salt_len)) {
163
0
        OPENSSL_free(buf);
164
0
        return 0;
165
0
    }
166
118
    *pout = buf;
167
118
    return min_len;
168
118
}
169
170
void ossl_rand_cleanup_nonce(ossl_unused OSSL_LIB_CTX *ctx,
171
    unsigned char *buf, size_t len)
172
0
{
173
0
    OPENSSL_clear_free(buf, len);
174
0
}
175
176
void ossl_rand_cleanup_user_nonce(ossl_unused OSSL_LIB_CTX *ctx,
177
    unsigned char *buf, size_t len)
178
763
{
179
763
    OPENSSL_clear_free(buf, len);
180
763
}