Coverage Report

Created: 2026-10-28 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/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
0
{
23
0
    size_t ret = 0;
24
0
    size_t entropy_available;
25
0
    RAND_POOL *pool;
26
27
0
    pool = ossl_rand_pool_new(entropy, 1, min_len, max_len);
28
0
    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
0
    entropy_available = ossl_pool_acquire_entropy(pool);
35
36
0
    if (entropy_available > 0) {
37
0
        ret = ossl_rand_pool_length(pool);
38
0
        *pout = ossl_rand_pool_detach(pool);
39
0
    }
40
41
0
    ossl_rand_pool_free(pool);
42
0
    return ret;
43
0
}
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
0
{
55
0
    unsigned char *seed = NULL, *buf;
56
0
    size_t ret;
57
58
0
    ret = evp_rand_get_seed(rng, &seed, entropy, min_len, max_len,
59
0
        0, NULL, 0);
60
0
    if (ret == 0)
61
0
        return 0;
62
0
    buf = OPENSSL_secure_malloc(ret);
63
0
    if (buf != NULL)
64
0
        memcpy(buf, seed, ret);
65
0
    evp_rand_clear_seed(rng, seed, ret);
66
0
    if (buf == NULL)
67
0
        return 0;
68
0
    *pout = buf;
69
0
    return ret;
70
0
}
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
0
{
76
0
    EVP_RAND_CTX *rng;
77
78
0
    if (ossl_rand_seed_source_strict(ctx)) {
79
        /*
80
         * With strict seeding the configured seed source must be used,
81
         * even when the request arrives before anything instantiated it.
82
         */
83
0
        rng = ossl_rand_get0_seed(ctx);
84
0
        if (rng == NULL || !evp_rand_can_seed(rng)) {
85
0
            ERR_raise(ERR_LIB_RAND, RAND_R_ERROR_RETRIEVING_ENTROPY);
86
0
            return 0;
87
0
        }
88
0
    } else {
89
0
        rng = ossl_rand_get0_seed_noncreating(ctx);
90
0
        if (rng == NULL || !evp_rand_can_seed(rng))
91
0
            return ossl_rand_get_entropy(ctx, pout, entropy, min_len, max_len);
92
0
    }
93
0
    return rand_get_seed_copy(rng, pout, entropy, min_len, max_len);
94
0
}
95
96
void ossl_rand_cleanup_entropy(ossl_unused OSSL_LIB_CTX *ctx,
97
    unsigned char *buf, size_t len)
98
0
{
99
0
    OPENSSL_secure_clear_free(buf, len);
100
0
}
101
102
/* See rand_get_seed_copy() */
103
void ossl_rand_cleanup_user_entropy(OSSL_LIB_CTX *ctx,
104
    unsigned char *buf, size_t len)
105
0
{
106
0
    ossl_rand_cleanup_entropy(ctx, buf, len);
107
0
}
108
109
size_t ossl_rand_get_nonce(ossl_unused OSSL_LIB_CTX *ctx,
110
    unsigned char **pout,
111
    size_t min_len, ossl_unused size_t max_len,
112
    const void *salt, size_t salt_len)
113
0
{
114
0
    size_t ret = 0;
115
0
    RAND_POOL *pool;
116
117
0
    pool = ossl_rand_pool_new(0, 0, min_len, max_len);
118
0
    if (pool == NULL) {
119
0
        ERR_raise(ERR_LIB_RAND, ERR_R_RAND_LIB);
120
0
        return 0;
121
0
    }
122
123
0
    if (!ossl_pool_add_nonce_data(pool))
124
0
        goto err;
125
126
0
    if (salt != NULL && !ossl_rand_pool_add(pool, salt, salt_len, 0))
127
0
        goto err;
128
0
    ret = ossl_rand_pool_length(pool);
129
0
    *pout = ossl_rand_pool_detach(pool);
130
0
err:
131
0
    ossl_rand_pool_free(pool);
132
0
    return ret;
133
0
}
134
135
size_t ossl_rand_get_user_nonce(OSSL_LIB_CTX *ctx,
136
    unsigned char **pout,
137
    size_t min_len, size_t max_len,
138
    const void *salt, size_t salt_len)
139
0
{
140
0
    unsigned char *buf;
141
0
    EVP_RAND_CTX *rng;
142
143
0
    if (ossl_rand_seed_source_strict(ctx)) {
144
        /* See ossl_rand_get_user_entropy() */
145
0
        rng = ossl_rand_get0_seed(ctx);
146
0
        if (rng == NULL) {
147
0
            ERR_raise(ERR_LIB_RAND, RAND_R_ERROR_RETRIEVING_NONCE);
148
0
            return 0;
149
0
        }
150
0
    } else {
151
0
        rng = ossl_rand_get0_seed_noncreating(ctx);
152
0
        if (rng == NULL)
153
0
            return ossl_rand_get_nonce(ctx, pout, min_len, max_len,
154
0
                salt, salt_len);
155
0
    }
156
157
0
    if ((buf = OPENSSL_malloc(min_len)) == NULL)
158
0
        return 0;
159
160
0
    if (!EVP_RAND_generate(rng, buf, min_len, 0, 0, salt, salt_len)) {
161
0
        OPENSSL_free(buf);
162
0
        return 0;
163
0
    }
164
0
    *pout = buf;
165
0
    return min_len;
166
0
}
167
168
void ossl_rand_cleanup_nonce(ossl_unused OSSL_LIB_CTX *ctx,
169
    unsigned char *buf, size_t len)
170
0
{
171
0
    OPENSSL_clear_free(buf, len);
172
0
}
173
174
void ossl_rand_cleanup_user_nonce(ossl_unused OSSL_LIB_CTX *ctx,
175
    unsigned char *buf, size_t len)
176
0
{
177
0
    OPENSSL_clear_free(buf, len);
178
0
}