1 /*
2 * Copyright 2016-2025 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 <openssl/crypto.h>
11 #include "internal/cryptlib.h"
12 #include "internal/rcu.h"
13 #include "crypto/cryptlib.h"
14 #include "rcu_internal.h"
15
16 #if !defined(OPENSSL_THREADS) || defined(CRYPTO_TDEBUG)
17
18 #if defined(OPENSSL_SYS_UNIX)
19 #include <sys/types.h>
20 #include <unistd.h>
21 #endif
22
23 struct rcu_lock_st {
24 struct rcu_cb_item *cb_items;
25 };
26
ossl_rcu_lock_new(int num_writers,ossl_unused OSSL_LIB_CTX * ctx)27 CRYPTO_RCU_LOCK *ossl_rcu_lock_new(int num_writers,
28 ossl_unused OSSL_LIB_CTX *ctx)
29 {
30 struct rcu_lock_st *lock;
31
32 lock = OPENSSL_zalloc(sizeof(*lock));
33 return lock;
34 }
35
ossl_rcu_lock_free(CRYPTO_RCU_LOCK * lock)36 void ossl_rcu_lock_free(CRYPTO_RCU_LOCK *lock)
37 {
38 OPENSSL_free(lock);
39 }
40
ossl_rcu_read_lock(CRYPTO_RCU_LOCK * lock)41 void ossl_rcu_read_lock(CRYPTO_RCU_LOCK *lock)
42 {
43 return;
44 }
45
ossl_rcu_write_lock(CRYPTO_RCU_LOCK * lock)46 void ossl_rcu_write_lock(CRYPTO_RCU_LOCK *lock)
47 {
48 return;
49 }
50
ossl_rcu_write_unlock(CRYPTO_RCU_LOCK * lock)51 void ossl_rcu_write_unlock(CRYPTO_RCU_LOCK *lock)
52 {
53 return;
54 }
55
ossl_rcu_read_unlock(CRYPTO_RCU_LOCK * lock)56 void ossl_rcu_read_unlock(CRYPTO_RCU_LOCK *lock)
57 {
58 return;
59 }
60
ossl_synchronize_rcu(CRYPTO_RCU_LOCK * lock)61 void ossl_synchronize_rcu(CRYPTO_RCU_LOCK *lock)
62 {
63 struct rcu_cb_item *items = lock->cb_items;
64 struct rcu_cb_item *tmp;
65
66 lock->cb_items = NULL;
67
68 while (items != NULL) {
69 tmp = items->next;
70 items->fn(items->data);
71 OPENSSL_free(items);
72 items = tmp;
73 }
74 }
75
ossl_rcu_call(CRYPTO_RCU_LOCK * lock,rcu_cb_fn cb,void * data)76 int ossl_rcu_call(CRYPTO_RCU_LOCK *lock, rcu_cb_fn cb, void *data)
77 {
78 struct rcu_cb_item *new = OPENSSL_zalloc(sizeof(*new));
79
80 if (new == NULL)
81 return 0;
82
83 new->fn = cb;
84 new->data = data;
85 new->next = lock->cb_items;
86 lock->cb_items = new;
87 return 1;
88 }
89
ossl_rcu_uptr_deref(void ** p)90 void *ossl_rcu_uptr_deref(void **p)
91 {
92 return (void *)*p;
93 }
94
ossl_rcu_assign_uptr(void ** p,void ** v)95 void ossl_rcu_assign_uptr(void **p, void **v)
96 {
97 *(void **)p = *(void **)v;
98 }
99
CRYPTO_THREAD_lock_new(void)100 CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void)
101 {
102 CRYPTO_RWLOCK *lock;
103
104 if ((lock = CRYPTO_zalloc(sizeof(unsigned int), NULL, 0)) == NULL)
105 /* Don't set error, to avoid recursion blowup. */
106 return NULL;
107
108 *(unsigned int *)lock = 1;
109
110 return lock;
111 }
112
CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK * lock)113 __owur int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock)
114 {
115 if (!ossl_assert(*(unsigned int *)lock == 1))
116 return 0;
117 return 1;
118 }
119
CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK * lock)120 __owur int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock)
121 {
122 if (!ossl_assert(*(unsigned int *)lock == 1))
123 return 0;
124 return 1;
125 }
126
CRYPTO_THREAD_unlock(CRYPTO_RWLOCK * lock)127 int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock)
128 {
129 if (!ossl_assert(*(unsigned int *)lock == 1))
130 return 0;
131 return 1;
132 }
133
CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK * lock)134 void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock)
135 {
136 if (lock == NULL)
137 return;
138
139 *(unsigned int *)lock = 0;
140 OPENSSL_free(lock);
141
142 return;
143 }
144
CRYPTO_THREAD_run_once(CRYPTO_ONCE * once,void (* init)(void))145 int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void))
146 {
147 if (*once != 0)
148 return 1;
149
150 init();
151 *once = 1;
152
153 return 1;
154 }
155
156 #define OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX 256
157
158 struct thread_local_storage_entry {
159 void *data;
160 uint8_t used;
161 };
162
163 static struct thread_local_storage_entry thread_local_storage[OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX];
164
CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL * key,void (* cleanup)(void *))165 int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *))
166 {
167 int entry_idx = 0;
168
169 #ifndef FIPS_MODULE
170 if (!ossl_init_thread())
171 return 0;
172 #endif
173
174 for (entry_idx = 0; entry_idx < OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX; entry_idx++) {
175 if (!thread_local_storage[entry_idx].used)
176 break;
177 }
178
179 if (entry_idx == OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX)
180 return 0;
181
182 *key = entry_idx;
183 thread_local_storage[*key].used = 1;
184 thread_local_storage[*key].data = NULL;
185
186 return 1;
187 }
188
CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL * key)189 void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key)
190 {
191 if (*key >= OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX)
192 return NULL;
193
194 return thread_local_storage[*key].data;
195 }
196
CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL * key,void * val)197 int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val)
198 {
199 if (*key >= OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX)
200 return 0;
201
202 thread_local_storage[*key].data = val;
203
204 return 1;
205 }
206
CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL * key)207 int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key)
208 {
209 if (*key >= OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX)
210 return 0;
211
212 thread_local_storage[*key].used = 0;
213 thread_local_storage[*key].data = NULL;
214 *key = OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX + 1;
215 return 1;
216 }
217
CRYPTO_THREAD_get_current_id(void)218 CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void)
219 {
220 return 0;
221 }
222
CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a,CRYPTO_THREAD_ID b)223 int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b)
224 {
225 return (a == b);
226 }
227
CRYPTO_atomic_add(int * val,int amount,int * ret,CRYPTO_RWLOCK * lock)228 int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock)
229 {
230 *val += amount;
231 *ret = *val;
232
233 return 1;
234 }
235
CRYPTO_atomic_add64(uint64_t * val,uint64_t op,uint64_t * ret,CRYPTO_RWLOCK * lock)236 int CRYPTO_atomic_add64(uint64_t *val, uint64_t op, uint64_t *ret,
237 CRYPTO_RWLOCK *lock)
238 {
239 *val += op;
240 *ret = *val;
241
242 return 1;
243 }
244
CRYPTO_atomic_and(uint64_t * val,uint64_t op,uint64_t * ret,CRYPTO_RWLOCK * lock)245 int CRYPTO_atomic_and(uint64_t *val, uint64_t op, uint64_t *ret,
246 CRYPTO_RWLOCK *lock)
247 {
248 *val &= op;
249 *ret = *val;
250
251 return 1;
252 }
253
CRYPTO_atomic_or(uint64_t * val,uint64_t op,uint64_t * ret,CRYPTO_RWLOCK * lock)254 int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret,
255 CRYPTO_RWLOCK *lock)
256 {
257 *val |= op;
258 *ret = *val;
259
260 return 1;
261 }
262
CRYPTO_atomic_load(uint64_t * val,uint64_t * ret,CRYPTO_RWLOCK * lock)263 int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock)
264 {
265 *ret = *val;
266
267 return 1;
268 }
269
CRYPTO_atomic_store(uint64_t * dst,uint64_t val,CRYPTO_RWLOCK * lock)270 int CRYPTO_atomic_store(uint64_t *dst, uint64_t val, CRYPTO_RWLOCK *lock)
271 {
272 *dst = val;
273
274 return 1;
275 }
276
CRYPTO_atomic_load_int(int * val,int * ret,CRYPTO_RWLOCK * lock)277 int CRYPTO_atomic_load_int(int *val, int *ret, CRYPTO_RWLOCK *lock)
278 {
279 *ret = *val;
280
281 return 1;
282 }
283
openssl_init_fork_handlers(void)284 int openssl_init_fork_handlers(void)
285 {
286 return 0;
287 }
288
openssl_get_fork_id(void)289 int openssl_get_fork_id(void)
290 {
291 #if defined(OPENSSL_SYS_UNIX)
292 return getpid();
293 #else
294 return 0;
295 #endif
296 }
297 #endif
298