SCA hardening for mod. field inversion in EC_GROUP
[openssl.git] / crypto / threads_pthread.c
1 /*
2  * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (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
12 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) && !defined(OPENSSL_SYS_WINDOWS)
13
14 # ifdef PTHREAD_RWLOCK_INITIALIZER
15 #  define USE_RWLOCK
16 # endif
17
18 CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void)
19 {
20 # ifdef USE_RWLOCK
21     CRYPTO_RWLOCK *lock = OPENSSL_zalloc(sizeof(pthread_rwlock_t));
22     if (lock == NULL)
23         return NULL;
24
25     if (pthread_rwlock_init(lock, NULL) != 0) {
26         OPENSSL_free(lock);
27         return NULL;
28     }
29 # else
30     pthread_mutexattr_t attr;
31     CRYPTO_RWLOCK *lock = OPENSSL_zalloc(sizeof(pthread_mutex_t));
32     if (lock == NULL)
33         return NULL;
34
35     pthread_mutexattr_init(&attr);
36     pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
37
38     if (pthread_mutex_init(lock, &attr) != 0) {
39         pthread_mutexattr_destroy(&attr);
40         OPENSSL_free(lock);
41         return NULL;
42     }
43
44     pthread_mutexattr_destroy(&attr);
45 # endif
46
47     return lock;
48 }
49
50 int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock)
51 {
52 # ifdef USE_RWLOCK
53     if (pthread_rwlock_rdlock(lock) != 0)
54         return 0;
55 # else
56     if (pthread_mutex_lock(lock) != 0)
57         return 0;
58 # endif
59
60     return 1;
61 }
62
63 int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock)
64 {
65 # ifdef USE_RWLOCK
66     if (pthread_rwlock_wrlock(lock) != 0)
67         return 0;
68 # else
69     if (pthread_mutex_lock(lock) != 0)
70         return 0;
71 # endif
72
73     return 1;
74 }
75
76 int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock)
77 {
78 # ifdef USE_RWLOCK
79     if (pthread_rwlock_unlock(lock) != 0)
80         return 0;
81 # else
82     if (pthread_mutex_unlock(lock) != 0)
83         return 0;
84 # endif
85
86     return 1;
87 }
88
89 void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock)
90 {
91     if (lock == NULL)
92         return;
93
94 # ifdef USE_RWLOCK
95     pthread_rwlock_destroy(lock);
96 # else
97     pthread_mutex_destroy(lock);
98 # endif
99     OPENSSL_free(lock);
100
101     return;
102 }
103
104 int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void))
105 {
106     if (pthread_once(once, init) != 0)
107         return 0;
108
109     return 1;
110 }
111
112 int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *))
113 {
114     if (pthread_key_create(key, cleanup) != 0)
115         return 0;
116
117     return 1;
118 }
119
120 void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key)
121 {
122     return pthread_getspecific(*key);
123 }
124
125 int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val)
126 {
127     if (pthread_setspecific(*key, val) != 0)
128         return 0;
129
130     return 1;
131 }
132
133 int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key)
134 {
135     if (pthread_key_delete(*key) != 0)
136         return 0;
137
138     return 1;
139 }
140
141 CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void)
142 {
143     return pthread_self();
144 }
145
146 int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b)
147 {
148     return pthread_equal(a, b);
149 }
150
151 int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock)
152 {
153 # if defined(__GNUC__) && defined(__ATOMIC_ACQ_REL)
154     if (__atomic_is_lock_free(sizeof(*val), val)) {
155         *ret = __atomic_add_fetch(val, amount, __ATOMIC_ACQ_REL);
156         return 1;
157     }
158 # endif
159     if (!CRYPTO_THREAD_write_lock(lock))
160         return 0;
161
162     *val += amount;
163     *ret  = *val;
164
165     if (!CRYPTO_THREAD_unlock(lock))
166         return 0;
167
168     return 1;
169 }
170
171 #endif