summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/cryptlib.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/cryptlib.c')
-rw-r--r--src/lib/libcrypto/cryptlib.c201
1 files changed, 195 insertions, 6 deletions
diff --git a/src/lib/libcrypto/cryptlib.c b/src/lib/libcrypto/cryptlib.c
index a8f29f1e65..9de60fd528 100644
--- a/src/lib/libcrypto/cryptlib.c
+++ b/src/lib/libcrypto/cryptlib.c
@@ -60,11 +60,15 @@
60#include <string.h> 60#include <string.h>
61#include "cryptlib.h" 61#include "cryptlib.h"
62#include <openssl/crypto.h> 62#include <openssl/crypto.h>
63#include <openssl/safestack.h>
63 64
64#if defined(WIN32) || defined(WIN16) 65#if defined(WIN32) || defined(WIN16)
65static double SSLeay_MSVC5_hack=0.0; /* and for VC1.5 */ 66static double SSLeay_MSVC5_hack=0.0; /* and for VC1.5 */
66#endif 67#endif
67 68
69DECLARE_STACK_OF(CRYPTO_dynlock)
70IMPLEMENT_STACK_OF(CRYPTO_dynlock)
71
68/* real #defines in crypto.h, keep these upto date */ 72/* real #defines in crypto.h, keep these upto date */
69static const char* lock_names[CRYPTO_NUM_LOCKS] = 73static const char* lock_names[CRYPTO_NUM_LOCKS] =
70 { 74 {
@@ -94,18 +98,36 @@ static const char* lock_names[CRYPTO_NUM_LOCKS] =
94 "RSA_blinding", 98 "RSA_blinding",
95 "dh", 99 "dh",
96 "debug_malloc2", 100 "debug_malloc2",
97#if CRYPTO_NUM_LOCKS != 26 101 "dso",
102 "dynlock",
103 "engine",
104#if CRYPTO_NUM_LOCKS != 29
98# error "Inconsistency between crypto.h and cryptlib.c" 105# error "Inconsistency between crypto.h and cryptlib.c"
99#endif 106#endif
100 }; 107 };
101 108
109/* This is for applications to allocate new type names in the non-dynamic
110 array of lock names. These are numbered with positive numbers. */
102static STACK *app_locks=NULL; 111static STACK *app_locks=NULL;
103 112
113/* For applications that want a more dynamic way of handling threads, the
114 following stack is used. These are externally numbered with negative
115 numbers. */
116static STACK_OF(CRYPTO_dynlock) *dyn_locks=NULL;
117
118
104static void (MS_FAR *locking_callback)(int mode,int type, 119static void (MS_FAR *locking_callback)(int mode,int type,
105 const char *file,int line)=NULL; 120 const char *file,int line)=NULL;
106static int (MS_FAR *add_lock_callback)(int *pointer,int amount, 121static int (MS_FAR *add_lock_callback)(int *pointer,int amount,
107 int type,const char *file,int line)=NULL; 122 int type,const char *file,int line)=NULL;
108static unsigned long (MS_FAR *id_callback)(void)=NULL; 123static unsigned long (MS_FAR *id_callback)(void)=NULL;
124static struct CRYPTO_dynlock_value *(MS_FAR *dynlock_create_callback)
125 (const char *file,int line)=NULL;
126static void (MS_FAR *dynlock_lock_callback)(int mode,
127 struct CRYPTO_dynlock_value *l, const char *file,int line)=NULL;
128static void (MS_FAR *dynlock_destroy_callback)(struct CRYPTO_dynlock_value *l,
129 const char *file,int line)=NULL;
130
109int CRYPTO_get_new_lockid(char *name) 131int CRYPTO_get_new_lockid(char *name)
110 { 132 {
111 char *str; 133 char *str;
@@ -125,10 +147,13 @@ int CRYPTO_get_new_lockid(char *name)
125 return(0); 147 return(0);
126 } 148 }
127 if ((str=BUF_strdup(name)) == NULL) 149 if ((str=BUF_strdup(name)) == NULL)
150 {
151 CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID,ERR_R_MALLOC_FAILURE);
128 return(0); 152 return(0);
153 }
129 i=sk_push(app_locks,str); 154 i=sk_push(app_locks,str);
130 if (!i) 155 if (!i)
131 Free(str); 156 OPENSSL_free(str);
132 else 157 else
133 i+=CRYPTO_NUM_LOCKS; /* gap of one :-) */ 158 i+=CRYPTO_NUM_LOCKS; /* gap of one :-) */
134 return(i); 159 return(i);
@@ -139,6 +164,156 @@ int CRYPTO_num_locks(void)
139 return CRYPTO_NUM_LOCKS; 164 return CRYPTO_NUM_LOCKS;
140 } 165 }
141 166
167int CRYPTO_get_new_dynlockid(void)
168 {
169 int i = 0;
170 CRYPTO_dynlock *pointer = NULL;
171
172 if (dynlock_create_callback == NULL)
173 {
174 CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK);
175 return(0);
176 }
177 CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
178 if ((dyn_locks == NULL)
179 && ((dyn_locks=sk_CRYPTO_dynlock_new_null()) == NULL))
180 {
181 CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
182 CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,ERR_R_MALLOC_FAILURE);
183 return(0);
184 }
185 CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
186
187 pointer = (CRYPTO_dynlock *)OPENSSL_malloc(sizeof(CRYPTO_dynlock));
188 if (pointer == NULL)
189 {
190 CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,ERR_R_MALLOC_FAILURE);
191 return(0);
192 }
193 pointer->references = 1;
194 pointer->data = dynlock_create_callback(__FILE__,__LINE__);
195 if (pointer->data == NULL)
196 {
197 OPENSSL_free(pointer);
198 CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,ERR_R_MALLOC_FAILURE);
199 return(0);
200 }
201
202 CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
203 /* First, try to find an existing empty slot */
204 i=sk_CRYPTO_dynlock_find(dyn_locks,NULL);
205 /* If there was none, push, thereby creating a new one */
206 if (i == -1)
207 i=sk_CRYPTO_dynlock_push(dyn_locks,pointer);
208 CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
209
210 if (!i)
211 {
212 dynlock_destroy_callback(pointer->data,__FILE__,__LINE__);
213 OPENSSL_free(pointer);
214 }
215 else
216 i += 1; /* to avoid 0 */
217 return -i;
218 }
219
220void CRYPTO_destroy_dynlockid(int i)
221 {
222 CRYPTO_dynlock *pointer = NULL;
223 if (i)
224 i = -i-1;
225 if (dynlock_destroy_callback == NULL)
226 return;
227
228 CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
229
230 if (dyn_locks == NULL || i >= sk_CRYPTO_dynlock_num(dyn_locks))
231 return;
232 pointer = sk_CRYPTO_dynlock_value(dyn_locks, i);
233 if (pointer != NULL)
234 {
235 --pointer->references;
236#ifdef REF_CHECK
237 if (pointer->references < 0)
238 {
239 fprintf(stderr,"CRYPTO_destroy_dynlockid, bad reference count\n");
240 abort();
241 }
242 else
243#endif
244 if (--(pointer->references) <= 0)
245 {
246 sk_CRYPTO_dynlock_set(dyn_locks, i, NULL);
247 }
248 else
249 pointer = NULL;
250 }
251 CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
252
253 if (pointer)
254 {
255 dynlock_destroy_callback(pointer->data,__FILE__,__LINE__);
256 OPENSSL_free(pointer);
257 }
258 }
259
260struct CRYPTO_dynlock_value *CRYPTO_get_dynlock_value(int i)
261 {
262 CRYPTO_dynlock *pointer = NULL;
263 if (i)
264 i = -i-1;
265
266 CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
267
268 if (dyn_locks != NULL && i < sk_CRYPTO_dynlock_num(dyn_locks))
269 pointer = sk_CRYPTO_dynlock_value(dyn_locks, i);
270 if (pointer)
271 pointer->references++;
272
273 CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
274
275 if (pointer)
276 return pointer->data;
277 return NULL;
278 }
279
280struct CRYPTO_dynlock_value *(*CRYPTO_get_dynlock_create_callback(void))
281 (const char *file,int line)
282 {
283 return(dynlock_create_callback);
284 }
285
286void (*CRYPTO_get_dynlock_lock_callback(void))(int mode,
287 struct CRYPTO_dynlock_value *l, const char *file,int line)
288 {
289 return(dynlock_lock_callback);
290 }
291
292void (*CRYPTO_get_dynlock_destroy_callback(void))
293 (struct CRYPTO_dynlock_value *l, const char *file,int line)
294 {
295 return(dynlock_destroy_callback);
296 }
297
298void CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value *(*func)
299 (const char *file, int line))
300 {
301 dynlock_create_callback=func;
302 }
303
304void CRYPTO_set_dynlock_lock_callback(void (*func)(int mode,
305 struct CRYPTO_dynlock_value *l, const char *file, int line))
306 {
307 dynlock_lock_callback=func;
308 }
309
310void CRYPTO_set_dynlock_destroy_callback(void (*func)
311 (struct CRYPTO_dynlock_value *l, const char *file, int line))
312 {
313 dynlock_destroy_callback=func;
314 }
315
316
142void (*CRYPTO_get_locking_callback(void))(int mode,int type,const char *file, 317void (*CRYPTO_get_locking_callback(void))(int mode,int type,const char *file,
143 int line) 318 int line)
144 { 319 {
@@ -219,14 +394,28 @@ void CRYPTO_lock(int mode, int type, const char *file, int line)
219 CRYPTO_get_lock_name(type), file, line); 394 CRYPTO_get_lock_name(type), file, line);
220 } 395 }
221#endif 396#endif
222 if (locking_callback != NULL) 397 if (type < 0)
223 locking_callback(mode,type,file,line); 398 {
399 int i = -type - 1;
400 struct CRYPTO_dynlock_value *pointer
401 = CRYPTO_get_dynlock_value(i);
402
403 if (pointer)
404 {
405 dynlock_lock_callback(mode, pointer, file, line);
406 }
407
408 CRYPTO_destroy_dynlockid(i);
409 }
410 else
411 if (locking_callback != NULL)
412 locking_callback(mode,type,file,line);
224 } 413 }
225 414
226int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file, 415int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file,
227 int line) 416 int line)
228 { 417 {
229 int ret; 418 int ret = 0;
230 419
231 if (add_lock_callback != NULL) 420 if (add_lock_callback != NULL)
232 { 421 {
@@ -265,7 +454,7 @@ int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file,
265const char *CRYPTO_get_lock_name(int type) 454const char *CRYPTO_get_lock_name(int type)
266 { 455 {
267 if (type < 0) 456 if (type < 0)
268 return("ERROR"); 457 return("dynamic");
269 else if (type < CRYPTO_NUM_LOCKS) 458 else if (type < CRYPTO_NUM_LOCKS)
270 return(lock_names[type]); 459 return(lock_names[type]);
271 else if (type-CRYPTO_NUM_LOCKS >= sk_num(app_locks)) 460 else if (type-CRYPTO_NUM_LOCKS >= sk_num(app_locks))