]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/bio/bio_lib.c
Create BIO_write_ex() which handles size_t arguments
[thirdparty/openssl.git] / crypto / bio / bio_lib.c
CommitLineData
b1322259
RS
1/*
2 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
d02b48c6 3 *
b1322259
RS
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
d02b48c6
RE
8 */
9
10#include <stdio.h>
11#include <errno.h>
ec577822 12#include <openssl/crypto.h>
a146ae55 13#include "bio_lcl.h"
b39fc560 14#include "internal/cryptlib.h"
58964a49 15
04f6b0fd 16BIO *BIO_new(const BIO_METHOD *method)
0f113f3e 17{
9d7bfb14 18 BIO *bio = OPENSSL_zalloc(sizeof(*bio));
0f113f3e 19
9d7bfb14 20 if (bio == NULL) {
0f113f3e
MC
21 BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE);
22 return (NULL);
23 }
d02b48c6 24
0f113f3e 25 bio->method = method;
0f113f3e 26 bio->shutdown = 1;
0f113f3e 27 bio->references = 1;
9d7bfb14 28
25a807bc 29 if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data))
9d7bfb14 30 goto err;
fb46be03
AG
31
32 bio->lock = CRYPTO_THREAD_lock_new();
33 if (bio->lock == NULL) {
9d7bfb14 34 BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE);
fb46be03 35 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
9d7bfb14 36 goto err;
fb46be03
AG
37 }
38
9d7bfb14
F
39 if (method->create != NULL && !method->create(bio)) {
40 BIOerr(BIO_F_BIO_NEW, ERR_R_INIT_FAIL);
41 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
42 CRYPTO_THREAD_lock_free(bio->lock);
43 goto err;
fb46be03
AG
44 }
45
9d7bfb14
F
46 return bio;
47
48err:
49 OPENSSL_free(bio);
50 return NULL;
0f113f3e 51}
d02b48c6 52
6b691a5c 53int BIO_free(BIO *a)
0f113f3e
MC
54{
55 int i;
d02b48c6 56
0f113f3e 57 if (a == NULL)
fb46be03
AG
58 return 0;
59
60 if (CRYPTO_atomic_add(&a->references, -1, &i, a->lock) <= 0)
61 return 0;
d02b48c6 62
f3f1cf84 63 REF_PRINT_COUNT("BIO", a);
0f113f3e 64 if (i > 0)
fb46be03 65 return 1;
f3f1cf84 66 REF_ASSERT_ISNT(i < 0);
0f113f3e
MC
67 if ((a->callback != NULL) &&
68 ((i = (int)a->callback(a, BIO_CB_FREE, NULL, 0, 0L, 1L)) <= 0))
fb46be03 69 return i;
d02b48c6 70
a14a740d
F
71 if ((a->method != NULL) && (a->method->destroy != NULL))
72 a->method->destroy(a);
73
0f113f3e 74 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data);
58964a49 75
fb46be03
AG
76 CRYPTO_THREAD_lock_free(a->lock);
77
0f113f3e 78 OPENSSL_free(a);
fb46be03
AG
79
80 return 1;
0f113f3e 81}
d02b48c6 82
a146ae55
MC
83void BIO_set_data(BIO *a, void *ptr)
84{
85 a->ptr = ptr;
86}
87
88void *BIO_get_data(BIO *a)
89{
90 return a->ptr;
91}
92
93void BIO_set_init(BIO *a, int init)
94{
95 a->init = init;
96}
97
98int BIO_get_init(BIO *a)
99{
100 return a->init;
101}
102
103void BIO_set_shutdown(BIO *a, int shut)
104{
105 a->shutdown = shut;
106}
107
108int BIO_get_shutdown(BIO *a)
109{
110 return a->shutdown;
111}
112
371acb22 113void BIO_vfree(BIO *a)
0f113f3e
MC
114{
115 BIO_free(a);
116}
371acb22 117
fb46be03
AG
118int BIO_up_ref(BIO *a)
119{
120 int i;
121
122 if (CRYPTO_atomic_add(&a->references, 1, &i, a->lock) <= 0)
123 return 0;
124
125 REF_PRINT_COUNT("BIO", a);
126 REF_ASSERT_ISNT(i < 2);
127 return ((i > 1) ? 1 : 0);
128}
129
7806f3dd 130void BIO_clear_flags(BIO *b, int flags)
0f113f3e
MC
131{
132 b->flags &= ~flags;
133}
134
135int BIO_test_flags(const BIO *b, int flags)
136{
137 return (b->flags & flags);
138}
139
140void BIO_set_flags(BIO *b, int flags)
141{
142 b->flags |= flags;
143}
144
d07aee2c
MC
145BIO_callback_fn BIO_get_callback(const BIO *b)
146{
0f113f3e
MC
147 return b->callback;
148}
149
d07aee2c 150void BIO_set_callback(BIO *b, BIO_callback_fn cb)
0f113f3e
MC
151{
152 b->callback = cb;
153}
7806f3dd 154
d07aee2c
MC
155BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b)
156{
157 return b->callback_ex;
158}
159
160void BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex cb)
161{
162 b->callback_ex = cb;
163}
164
7806f3dd 165void BIO_set_callback_arg(BIO *b, char *arg)
0f113f3e
MC
166{
167 b->cb_arg = arg;
168}
7806f3dd 169
0f113f3e
MC
170char *BIO_get_callback_arg(const BIO *b)
171{
172 return b->cb_arg;
173}
7806f3dd 174
0f113f3e
MC
175const char *BIO_method_name(const BIO *b)
176{
177 return b->method->name;
178}
7806f3dd
NL
179
180int BIO_method_type(const BIO *b)
0f113f3e
MC
181{
182 return b->method->type;
183}
7806f3dd 184
d07aee2c
MC
185static int bio_call_callback(BIO *b, int oper, const char *argp, size_t len,
186 int argi, long argl, int inret, size_t *processed,
187 long *lret)
188{
189 long ret;
190 int bareoper;
191
192 if (b->callback_ex != NULL) {
193 return b->callback_ex(b, oper, argp, len, argi, argl, inret, processed,
194 lret);
195 }
196
197 /* Strip off the BIO_CB_RETURN flag */
198 bareoper = oper & ~BIO_CB_RETURN;
199 /*
200 * We have an old style callback, so we will have to do nasty casts and
201 * check for overflows.
202 */
203 if (bareoper == BIO_CB_READ || bareoper == BIO_CB_WRITE
204 || bareoper == BIO_CB_GETS) {
205 /* In this case |len| is set, and should be used instead of |argi| */
206 if (len > INT_MAX)
207 return 0;
208
209 argi = (int)len;
210
211 if (inret && (oper & BIO_CB_RETURN)) {
212 if (*processed > INT_MAX)
213 return 0;
214 inret = *processed;
215 }
216 }
217
218 ret = b->callback(b, oper, argp, argi, argl, inret);
219 if (bareoper == BIO_CB_CTRL)
220 return 1;
221
222 if (ret > INT_MAX || ret < INT_MIN)
223 return 0;
224
225 if (lret != NULL)
226 *lret = ret;
227
228 if (ret >= 0) {
229 *processed = (size_t)ret;
230 ret = 1;
231 }
232
233 return (int)ret;
234}
235
61f5b6f3 236int BIO_read(BIO *b, void *out, int outl)
0f113f3e 237{
d07aee2c
MC
238 size_t read;
239 int ret;
240
241 if (outl < 0)
242 return 0;
243
244 ret = BIO_read_ex(b, out, (size_t)outl, &read);
245
246 if (ret > 0) {
247 /* *read should always be <= outl */
248 ret = (int)read;
249 }
250
251 return ret;
252}
253
254int BIO_read_ex(BIO *b, void *out, size_t outl, size_t *read)
255{
256 int ret;
d02b48c6 257
0f113f3e 258 if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL)) {
d07aee2c 259 BIOerr(BIO_F_BIO_READ_EX, BIO_R_UNSUPPORTED_METHOD);
0f113f3e
MC
260 return (-2);
261 }
d02b48c6 262
d07aee2c
MC
263 if ((b->callback != NULL || b->callback_ex != NULL) &&
264 ((ret = bio_call_callback(b, BIO_CB_READ, out, outl, 0, 0L, 1L, read,
265 NULL)) <= 0))
266 return ret;
d02b48c6 267
0f113f3e 268 if (!b->init) {
d07aee2c
MC
269 BIOerr(BIO_F_BIO_READ_EX, BIO_R_UNINITIALIZED);
270 return -2;
0f113f3e 271 }
d02b48c6 272
d07aee2c 273 ret = b->method->bread(b, out, outl, read);
dfeab068 274
d07aee2c
MC
275 if (ret > 0)
276 b->num_read += (uint64_t)*read;
277
278 if (b->callback != NULL || b->callback_ex != NULL)
279 ret = bio_call_callback(b, BIO_CB_READ | BIO_CB_RETURN, out, outl, 0,
280 0L, ret, read, NULL);
d02b48c6 281
d07aee2c 282 return ret;
0f113f3e 283}
d02b48c6 284
6343829a 285int BIO_write(BIO *b, const void *in, int inl)
0f113f3e 286{
3befffa3
MC
287 size_t written;
288 int ret;
289
290 if (inl < 0)
291 return 0;
292
293 ret = BIO_write_ex(b, in, (size_t)inl, &written);
294
295 if (ret > 0) {
296 /* *written should always be <= inl */
297 ret = (int)written;
298 }
299
300 return ret;
301}
302
303int BIO_write_ex(BIO *b, const void *in, size_t inl, size_t *written)
304{
305 int ret;
58964a49 306
0f113f3e
MC
307 if (b == NULL)
308 return (0);
d02b48c6 309
0f113f3e 310 if ((b->method == NULL) || (b->method->bwrite == NULL)) {
3befffa3 311 BIOerr(BIO_F_BIO_WRITE_EX, BIO_R_UNSUPPORTED_METHOD);
0f113f3e
MC
312 return (-2);
313 }
d02b48c6 314
3befffa3
MC
315 if ((b->callback != NULL || b->callback_ex != NULL) &&
316 ((ret = bio_call_callback(b, BIO_CB_WRITE, in, inl, 0, 0L, 1L, written,
317 NULL)) <= 0))
318 return ret;
d02b48c6 319
0f113f3e 320 if (!b->init) {
3befffa3
MC
321 BIOerr(BIO_F_BIO_WRITE_EX, BIO_R_UNINITIALIZED);
322 return -2;
0f113f3e 323 }
d02b48c6 324
3befffa3 325 ret = b->method->bwrite(b, in, inl, written);
dfeab068 326
3befffa3
MC
327 if (ret > 0)
328 b->num_write += (uint64_t)*written;
d02b48c6 329
3befffa3
MC
330 if (b->callback != NULL || b->callback_ex != NULL)
331 ret = bio_call_callback(b, BIO_CB_WRITE | BIO_CB_RETURN, in, inl, 0,
332 0L, ret, written, NULL);
333
334 return ret;
0f113f3e 335}
d02b48c6 336
6b691a5c 337int BIO_puts(BIO *b, const char *in)
0f113f3e
MC
338{
339 int i;
340 long (*cb) (BIO *, int, const char *, int, long, long);
d02b48c6 341
0f113f3e
MC
342 if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) {
343 BIOerr(BIO_F_BIO_PUTS, BIO_R_UNSUPPORTED_METHOD);
344 return (-2);
345 }
d02b48c6 346
0f113f3e 347 cb = b->callback;
58964a49 348
0f113f3e
MC
349 if ((cb != NULL) && ((i = (int)cb(b, BIO_CB_PUTS, in, 0, 0L, 1L)) <= 0))
350 return (i);
d02b48c6 351
0f113f3e
MC
352 if (!b->init) {
353 BIOerr(BIO_F_BIO_PUTS, BIO_R_UNINITIALIZED);
354 return (-2);
355 }
d02b48c6 356
0f113f3e 357 i = b->method->bputs(b, in);
d02b48c6 358
0f113f3e 359 if (i > 0)
b8b12aad 360 b->num_write += (uint64_t)i;
7d95ff76 361
0f113f3e
MC
362 if (cb != NULL)
363 i = (int)cb(b, BIO_CB_PUTS | BIO_CB_RETURN, in, 0, 0L, (long)i);
364 return (i);
365}
d02b48c6 366
6b691a5c 367int BIO_gets(BIO *b, char *in, int inl)
0f113f3e
MC
368{
369 int i;
370 long (*cb) (BIO *, int, const char *, int, long, long);
371
372 if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) {
373 BIOerr(BIO_F_BIO_GETS, BIO_R_UNSUPPORTED_METHOD);
374 return (-2);
375 }
376
377 cb = b->callback;
378
379 if ((cb != NULL) && ((i = (int)cb(b, BIO_CB_GETS, in, inl, 0L, 1L)) <= 0))
380 return (i);
381
382 if (!b->init) {
383 BIOerr(BIO_F_BIO_GETS, BIO_R_UNINITIALIZED);
384 return (-2);
385 }
386
387 i = b->method->bgets(b, in, inl);
388
389 if (cb != NULL)
390 i = (int)cb(b, BIO_CB_GETS | BIO_CB_RETURN, in, inl, 0L, (long)i);
391 return (i);
392}
393
394int BIO_indent(BIO *b, int indent, int max)
395{
396 if (indent < 0)
397 indent = 0;
398 if (indent > max)
399 indent = max;
400 while (indent--)
401 if (BIO_puts(b, " ") != 1)
402 return 0;
403 return 1;
404}
54a656ef 405
6b691a5c 406long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
0f113f3e
MC
407{
408 int i;
d02b48c6 409
0f113f3e
MC
410 i = iarg;
411 return (BIO_ctrl(b, cmd, larg, (char *)&i));
412}
d02b48c6 413
417be660 414void *BIO_ptr_ctrl(BIO *b, int cmd, long larg)
0f113f3e 415{
417be660 416 void *p = NULL;
58964a49 417
0f113f3e
MC
418 if (BIO_ctrl(b, cmd, larg, (char *)&p) <= 0)
419 return (NULL);
420 else
421 return (p);
422}
58964a49 423
95d29597 424long BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
0f113f3e
MC
425{
426 long ret;
427 long (*cb) (BIO *, int, const char *, int, long, long);
d02b48c6 428
0f113f3e
MC
429 if (b == NULL)
430 return (0);
d02b48c6 431
0f113f3e
MC
432 if ((b->method == NULL) || (b->method->ctrl == NULL)) {
433 BIOerr(BIO_F_BIO_CTRL, BIO_R_UNSUPPORTED_METHOD);
434 return (-2);
435 }
d02b48c6 436
0f113f3e 437 cb = b->callback;
58964a49 438
0f113f3e
MC
439 if ((cb != NULL) &&
440 ((ret = cb(b, BIO_CB_CTRL, parg, cmd, larg, 1L)) <= 0))
441 return (ret);
d02b48c6 442
0f113f3e 443 ret = b->method->ctrl(b, cmd, larg, parg);
d02b48c6 444
0f113f3e
MC
445 if (cb != NULL)
446 ret = cb(b, BIO_CB_CTRL | BIO_CB_RETURN, parg, cmd, larg, ret);
447 return (ret);
448}
d02b48c6 449
0f113f3e
MC
450long BIO_callback_ctrl(BIO *b, int cmd,
451 void (*fp) (struct bio_st *, int, const char *, int,
452 long, long))
453{
454 long ret;
455 long (*cb) (BIO *, int, const char *, int, long, long);
d3442bc7 456
0f113f3e
MC
457 if (b == NULL)
458 return (0);
d3442bc7 459
0f113f3e
MC
460 if ((b->method == NULL) || (b->method->callback_ctrl == NULL)) {
461 BIOerr(BIO_F_BIO_CALLBACK_CTRL, BIO_R_UNSUPPORTED_METHOD);
462 return (-2);
463 }
d3442bc7 464
0f113f3e 465 cb = b->callback;
d3442bc7 466
0f113f3e
MC
467 if ((cb != NULL) &&
468 ((ret = cb(b, BIO_CB_CTRL, (void *)&fp, cmd, 0, 1L)) <= 0))
469 return (ret);
d3442bc7 470
0f113f3e 471 ret = b->method->callback_ctrl(b, cmd, fp);
d3442bc7 472
0f113f3e
MC
473 if (cb != NULL)
474 ret = cb(b, BIO_CB_CTRL | BIO_CB_RETURN, (void *)&fp, cmd, 0, ret);
475 return (ret);
476}
d3442bc7 477
0f113f3e
MC
478/*
479 * It is unfortunate to duplicate in functions what the BIO_(w)pending macros
95d29597 480 * do; but those macros have inappropriate return type, and for interfacing
0f113f3e
MC
481 * from other programming languages, C macros aren't much of a help anyway.
482 */
95d29597 483size_t BIO_ctrl_pending(BIO *bio)
0f113f3e
MC
484{
485 return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
486}
95d29597
BM
487
488size_t BIO_ctrl_wpending(BIO *bio)
0f113f3e
MC
489{
490 return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
491}
95d29597 492
d02b48c6 493/* put the 'bio' on the end of b's list of operators */
6b691a5c 494BIO *BIO_push(BIO *b, BIO *bio)
0f113f3e
MC
495{
496 BIO *lb;
497
498 if (b == NULL)
499 return (bio);
500 lb = b;
501 while (lb->next_bio != NULL)
502 lb = lb->next_bio;
503 lb->next_bio = bio;
504 if (bio != NULL)
505 bio->prev_bio = lb;
506 /* called to do internal processing */
507 BIO_ctrl(b, BIO_CTRL_PUSH, 0, lb);
508 return (b);
509}
d02b48c6
RE
510
511/* Remove the first and return the rest */
6b691a5c 512BIO *BIO_pop(BIO *b)
0f113f3e
MC
513{
514 BIO *ret;
d02b48c6 515
0f113f3e
MC
516 if (b == NULL)
517 return (NULL);
518 ret = b->next_bio;
d02b48c6 519
0f113f3e 520 BIO_ctrl(b, BIO_CTRL_POP, 0, b);
5d780bab 521
0f113f3e
MC
522 if (b->prev_bio != NULL)
523 b->prev_bio->next_bio = b->next_bio;
524 if (b->next_bio != NULL)
525 b->next_bio->prev_bio = b->prev_bio;
d02b48c6 526
0f113f3e
MC
527 b->next_bio = NULL;
528 b->prev_bio = NULL;
529 return (ret);
530}
d02b48c6 531
6b691a5c 532BIO *BIO_get_retry_BIO(BIO *bio, int *reason)
0f113f3e
MC
533{
534 BIO *b, *last;
535
536 b = last = bio;
537 for (;;) {
538 if (!BIO_should_retry(b))
539 break;
540 last = b;
541 b = b->next_bio;
542 if (b == NULL)
543 break;
544 }
545 if (reason != NULL)
546 *reason = last->retry_reason;
547 return (last);
548}
d02b48c6 549
6b691a5c 550int BIO_get_retry_reason(BIO *bio)
0f113f3e
MC
551{
552 return (bio->retry_reason);
553}
d02b48c6 554
a146ae55
MC
555void BIO_set_retry_reason(BIO *bio, int reason)
556{
557 bio->retry_reason = reason;
558}
559
6b691a5c 560BIO *BIO_find_type(BIO *bio, int type)
0f113f3e
MC
561{
562 int mt, mask;
563
cc99bfa7 564 if (bio == NULL)
0f113f3e
MC
565 return NULL;
566 mask = type & 0xff;
567 do {
568 if (bio->method != NULL) {
569 mt = bio->method->type;
570
571 if (!mask) {
572 if (mt & type)
573 return (bio);
574 } else if (mt == type)
575 return (bio);
576 }
577 bio = bio->next_bio;
578 } while (bio != NULL);
579 return (NULL);
580}
d02b48c6 581
cfd3bb17 582BIO *BIO_next(BIO *b)
0f113f3e 583{
cc99bfa7 584 if (b == NULL)
0f113f3e
MC
585 return NULL;
586 return b->next_bio;
587}
cfd3bb17 588
a146ae55
MC
589void BIO_set_next(BIO *b, BIO *next)
590{
591 b->next_bio = next;
592}
593
6b691a5c 594void BIO_free_all(BIO *bio)
0f113f3e
MC
595{
596 BIO *b;
597 int ref;
598
599 while (bio != NULL) {
600 b = bio;
601 ref = b->references;
602 bio = bio->next_bio;
603 BIO_free(b);
604 /* Since ref count > 1, don't free anyone else. */
605 if (ref > 1)
606 break;
607 }
608}
d02b48c6 609
6b691a5c 610BIO *BIO_dup_chain(BIO *in)
0f113f3e
MC
611{
612 BIO *ret = NULL, *eoc = NULL, *bio, *new_bio;
613
614 for (bio = in; bio != NULL; bio = bio->next_bio) {
615 if ((new_bio = BIO_new(bio->method)) == NULL)
616 goto err;
617 new_bio->callback = bio->callback;
618 new_bio->cb_arg = bio->cb_arg;
619 new_bio->init = bio->init;
620 new_bio->shutdown = bio->shutdown;
621 new_bio->flags = bio->flags;
622
623 /* This will let SSL_s_sock() work with stdin/stdout */
624 new_bio->num = bio->num;
625
626 if (!BIO_dup_state(bio, (char *)new_bio)) {
627 BIO_free(new_bio);
628 goto err;
629 }
630
631 /* copy app data */
632 if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new_bio->ex_data,
aec54108
MC
633 &bio->ex_data)) {
634 BIO_free(new_bio);
0f113f3e 635 goto err;
aec54108 636 }
0f113f3e
MC
637
638 if (ret == NULL) {
639 eoc = new_bio;
640 ret = eoc;
641 } else {
642 BIO_push(eoc, new_bio);
643 eoc = new_bio;
644 }
645 }
646 return (ret);
647 err:
aec54108
MC
648 BIO_free_all(ret);
649
0f113f3e
MC
650 return (NULL);
651}
d02b48c6 652
6b691a5c 653void BIO_copy_next_retry(BIO *b)
0f113f3e
MC
654{
655 BIO_set_flags(b, BIO_get_retry_flags(b->next_bio));
656 b->retry_reason = b->next_bio->retry_reason;
657}
d02b48c6 658
dd9d233e 659int BIO_set_ex_data(BIO *bio, int idx, void *data)
0f113f3e
MC
660{
661 return (CRYPTO_set_ex_data(&(bio->ex_data), idx, data));
662}
58964a49 663
dd9d233e 664void *BIO_get_ex_data(BIO *bio, int idx)
0f113f3e
MC
665{
666 return (CRYPTO_get_ex_data(&(bio->ex_data), idx));
667}
58964a49 668
b8b12aad 669uint64_t BIO_number_read(BIO *bio)
c3ed3b6e 670{
0f113f3e
MC
671 if (bio)
672 return bio->num_read;
673 return 0;
c3ed3b6e
DSH
674}
675
b8b12aad 676uint64_t BIO_number_written(BIO *bio)
c3ed3b6e 677{
0f113f3e
MC
678 if (bio)
679 return bio->num_write;
680 return 0;
c3ed3b6e 681}
ff234405 682
1ee7b8b9
MC
683void bio_free_ex_data(BIO *bio)
684{
685 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
686}
ff234405
MC
687
688void bio_cleanup(void)
689{
690#ifndef OPENSSL_NO_SOCK
691 bio_sock_cleanup_int();
692 CRYPTO_THREAD_lock_free(bio_lookup_lock);
693 bio_lookup_lock = NULL;
5a7ad1f0 694#endif
8b8d963d
RS
695 CRYPTO_THREAD_lock_free(bio_type_lock);
696 bio_type_lock = NULL;
ff234405 697}