Coverage Report

Created: 2023-03-26 07:33

/src/gnutls/lib/random.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2008-2012 Free Software Foundation, Inc.
3
 *
4
 * Author: Nikos Mavrogiannopoulos
5
 *
6
 * This file is part of GnuTLS.
7
 *
8
 * The GnuTLS is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public License
10
 * as published by the Free Software Foundation; either version 2.1 of
11
 * the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful, but
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
20
 *
21
 */
22
23
/* This file handles all the internal functions that cope with random data
24
 */
25
26
#include "gnutls_int.h"
27
#include "errors.h"
28
#include <random.h>
29
#include "locks.h"
30
#include <fips.h>
31
32
#include "gl_linkedhash_list.h"
33
#include "gl_list.h"
34
#include "glthread/tls.h"
35
#include "gthreads.h"
36
37
#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
38
extern gnutls_crypto_rnd_st _gnutls_fuzz_rnd_ops;
39
#endif
40
41
/* A global list of all allocated contexts.
42
 * A safety measure in case thread specific
43
 * context cannot be freed on thread exit
44
 */
45
GNUTLS_STATIC_MUTEX(gnutls_rnd_list_mutex);
46
static gl_list_t list;
47
48
/* Key used to locate and manage thread specific random generator context
49
 */
50
static gl_tls_key_t ctx_key;
51
52
/* Flag to indicate initialization
53
 */
54
static _Thread_local unsigned rnd_initialized = 0;
55
56
static void free_ctx(const void *ctx)
57
0
{
58
0
  if (ctx && _gnutls_rnd_ops.deinit)
59
0
    _gnutls_rnd_ops.deinit((void *)ctx);
60
0
}
61
62
static void delete_ctx(void *ctx)
63
0
{
64
0
  (void)gnutls_static_mutex_lock(&gnutls_rnd_list_mutex);
65
0
  gl_list_remove(list, ctx);
66
0
  gnutls_static_mutex_unlock(&gnutls_rnd_list_mutex);
67
0
}
68
69
static inline int _gnutls_rnd_init(void)
70
0
{
71
0
  int ret;
72
0
  void *ctx;
73
0
  gl_list_node_t node;
74
75
0
  if (likely(rnd_initialized))
76
0
    return 0;
77
78
0
  if (_gnutls_rnd_ops.init == NULL) {
79
0
    rnd_initialized = 1;
80
0
    return 0;
81
0
  }
82
83
0
  if (_gnutls_rnd_ops.init(&ctx) < 0)
84
0
    return gnutls_assert_val(GNUTLS_E_RANDOM_FAILED);
85
86
0
  if (glthread_tls_set(&ctx_key, ctx)) {
87
0
    _gnutls_rnd_ops.deinit(ctx);
88
0
    return gnutls_assert_val(GNUTLS_E_RANDOM_FAILED);
89
0
  }
90
91
0
  ret = gnutls_static_mutex_lock(&gnutls_rnd_list_mutex);
92
0
  if (ret < 0)
93
0
    return gnutls_assert_val(ret);
94
0
  node = gl_list_nx_add_last(list, ctx);
95
0
  gnutls_static_mutex_unlock(&gnutls_rnd_list_mutex);
96
0
  if (node == NULL) {
97
0
    _gnutls_rnd_ops.deinit(ctx);
98
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
99
0
  }
100
101
0
  rnd_initialized = 1;
102
0
  return 0;
103
0
}
104
105
int _gnutls_rnd_preinit(void)
106
2
{
107
2
  int ret;
108
109
#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
110
# warning Insecure PRNG is enabled
111
  ret = gnutls_crypto_rnd_register(100, &_gnutls_fuzz_rnd_ops);
112
  if (ret < 0)
113
    return ret;
114
115
#elif defined(ENABLE_FIPS140)
116
  /* The FIPS140 random generator is only enabled when we are compiled
117
   * with FIPS support, _and_ the system is in FIPS installed state.
118
   */
119
  if (_gnutls_fips_mode_enabled()) {
120
    ret = gnutls_crypto_rnd_register(100, &_gnutls_fips_rnd_ops);
121
    if (ret < 0)
122
      return ret;
123
  }
124
#endif
125
126
2
  ret = _rnd_system_entropy_init();
127
2
  if (ret < 0)
128
0
    return gnutls_assert_val(GNUTLS_E_RANDOM_FAILED);
129
130
2
  ret = glthread_tls_key_init(&ctx_key, delete_ctx);
131
2
  if (ret)
132
0
    return gnutls_assert_val(GNUTLS_E_RANDOM_FAILED);
133
134
2
  list =
135
2
      gl_list_nx_create_empty(GL_LINKEDHASH_LIST, NULL, NULL, free_ctx,
136
2
            false);
137
2
  if (list == NULL)
138
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
139
140
2
  return 0;
141
2
}
142
143
void _gnutls_rnd_deinit(void)
144
0
{
145
0
  gl_list_free(list);
146
0
  glthread_tls_key_destroy(&ctx_key);
147
0
  rnd_initialized = 0;
148
0
  _rnd_system_entropy_deinit();
149
0
}
150
151
/**
152
 * gnutls_rnd:
153
 * @level: a security level
154
 * @data: place to store random bytes
155
 * @len: The requested size
156
 *
157
 * This function will generate random data and store it to output
158
 * buffer. The value of @level should be one of %GNUTLS_RND_NONCE,
159
 * %GNUTLS_RND_RANDOM and %GNUTLS_RND_KEY. See the manual and
160
 * %gnutls_rnd_level_t for detailed information.
161
 *
162
 * This function is thread-safe and also fork-safe.
163
 *
164
 * Returns: Zero on success, or a negative error code on error.
165
 *
166
 * Since: 2.12.0
167
 **/
168
int gnutls_rnd(gnutls_rnd_level_t level, void *data, size_t len)
169
0
{
170
0
  int ret;
171
0
  FAIL_IF_LIB_ERROR;
172
173
0
  ret = _gnutls_rnd_init();
174
0
  if (unlikely(ret < 0))
175
0
    return gnutls_assert_val(ret);
176
177
0
  if (likely(len > 0))
178
0
    return _gnutls_rnd_ops.rnd(gl_tls_get(ctx_key), level, data,
179
0
             len);
180
181
0
  return 0;
182
0
}
183
184
/**
185
 * gnutls_rnd_refresh:
186
 *
187
 * This function refreshes the random generator state.
188
 * That is the current precise time, CPU usage, and
189
 * other values are input into its state.
190
 *
191
 * On a slower rate input from /dev/urandom is mixed too.
192
 *
193
 * Since: 3.1.7
194
 **/
195
void gnutls_rnd_refresh(void)
196
0
{
197
0
  if (rnd_initialized && _gnutls_rnd_ops.rnd_refresh)
198
0
    _gnutls_rnd_ops.rnd_refresh(gl_tls_get(ctx_key));
199
0
}