1 /*
2 * Copyright 2016-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 <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_cb_item_new(void)76 CRYPTO_RCU_CB_ITEM *ossl_rcu_cb_item_new(void)
77 {
78 return OPENSSL_zalloc(sizeof(CRYPTO_RCU_CB_ITEM));
79 }
80
ossl_rcu_cb_item_free(CRYPTO_RCU_CB_ITEM * item)81 void ossl_rcu_cb_item_free(CRYPTO_RCU_CB_ITEM *item)
82 {
83 OPENSSL_free(item);
84 }
85
ossl_rcu_call(CRYPTO_RCU_LOCK * lock,CRYPTO_RCU_CB_ITEM * item,rcu_cb_fn cb,void * data)86 void ossl_rcu_call(CRYPTO_RCU_LOCK *lock, CRYPTO_RCU_CB_ITEM *item,
87 rcu_cb_fn cb, void *data)
88 {
89 item->fn = cb;
90 item->data = data;
91 item->next = lock->cb_items;
92 lock->cb_items = item;
93 }
94
ossl_rcu_uptr_deref(void ** p)95 void *ossl_rcu_uptr_deref(void **p)
96 {
97 return (void *)*p;
98 }
99
ossl_rcu_assign_uptr(void ** p,void ** v)100 void ossl_rcu_assign_uptr(void **p, void **v)
101 {
102 *(void **)p = *(void **)v;
103 }
104
CRYPTO_THREAD_lock_new(void)105 CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void)
106 {
107 CRYPTO_RWLOCK *lock;
108
109 if ((lock = CRYPTO_zalloc(sizeof(unsigned int), NULL, 0)) == NULL)
110 /* Don't set error, to avoid recursion blowup. */
111 return NULL;
112
113 *(unsigned int *)lock = 1;
114
115 return lock;
116 }
117
CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK * lock)118 __owur int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock)
119 {
120 if (!ossl_assert(*(unsigned int *)lock == 1))
121 return 0;
122 return 1;
123 }
124
CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK * lock)125 __owur int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock)
126 {
127 if (!ossl_assert(*(unsigned int *)lock == 1))
128 return 0;
129 return 1;
130 }
131
CRYPTO_THREAD_unlock(CRYPTO_RWLOCK * lock)132 int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock)
133 {
134 if (!ossl_assert(*(unsigned int *)lock == 1))
135 return 0;
136 return 1;
137 }
138
CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK * lock)139 void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock)
140 {
141 if (lock == NULL)
142 return;
143
144 *(unsigned int *)lock = 0;
145 OPENSSL_free(lock);
146
147 return;
148 }
149
CRYPTO_THREAD_run_once(CRYPTO_ONCE * once,void (* init)(void))150 int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void))
151 {
152 if (*once != 0)
153 return 1;
154
155 init();
156 *once = 1;
157
158 return 1;
159 }
160
161 #define OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX 256
162
163 struct thread_local_storage_entry {
164 void *data;
165 uint8_t used;
166 };
167
168 static struct thread_local_storage_entry thread_local_storage[OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX];
169
ossl_thread_init_local(CRYPTO_THREAD_LOCAL * key,void (* cleanup)(void *))170 int ossl_thread_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *))
171 {
172 int entry_idx = 0;
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 1;
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