xref: /openbsd-src/lib/libcrypto/bio/bio_lib.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /* crypto/bio/bio_lib.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  *
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  *
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  *
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  *
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58 
59 #include <stdio.h>
60 #include <errno.h>
61 #include <openssl/crypto.h>
62 #include "cryptlib.h"
63 #include <openssl/bio.h>
64 #include <openssl/stack.h>
65 
66 static STACK_OF(CRYPTO_EX_DATA_FUNCS) *bio_meth=NULL;
67 static int bio_meth_num=0;
68 
69 BIO *BIO_new(BIO_METHOD *method)
70 	{
71 	BIO *ret=NULL;
72 
73 	ret=(BIO *)OPENSSL_malloc(sizeof(BIO));
74 	if (ret == NULL)
75 		{
76 		BIOerr(BIO_F_BIO_NEW,ERR_R_MALLOC_FAILURE);
77 		return(NULL);
78 		}
79 	if (!BIO_set(ret,method))
80 		{
81 		OPENSSL_free(ret);
82 		ret=NULL;
83 		}
84 	return(ret);
85 	}
86 
87 int BIO_set(BIO *bio, BIO_METHOD *method)
88 	{
89 	bio->method=method;
90 	bio->callback=NULL;
91 	bio->cb_arg=NULL;
92 	bio->init=0;
93 	bio->shutdown=1;
94 	bio->flags=0;
95 	bio->retry_reason=0;
96 	bio->num=0;
97 	bio->ptr=NULL;
98 	bio->prev_bio=NULL;
99 	bio->next_bio=NULL;
100 	bio->references=1;
101 	bio->num_read=0L;
102 	bio->num_write=0L;
103 	CRYPTO_new_ex_data(bio_meth,bio,&bio->ex_data);
104 	if (method->create != NULL)
105 		if (!method->create(bio))
106 			return(0);
107 	return(1);
108 	}
109 
110 int BIO_free(BIO *a)
111 	{
112 	int ret=0,i;
113 
114 	if (a == NULL) return(0);
115 
116 	i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_BIO);
117 #ifdef REF_PRINT
118 	REF_PRINT("BIO",a);
119 #endif
120 	if (i > 0) return(1);
121 #ifdef REF_CHECK
122 	if (i < 0)
123 		{
124 		fprintf(stderr,"BIO_free, bad reference count\n");
125 		abort();
126 		}
127 #endif
128 	if ((a->callback != NULL) &&
129 		((i=(int)a->callback(a,BIO_CB_FREE,NULL,0,0L,1L)) <= 0))
130 			return(i);
131 
132 	CRYPTO_free_ex_data(bio_meth,a,&a->ex_data);
133 
134 	if ((a->method == NULL) || (a->method->destroy == NULL)) return(1);
135 	ret=a->method->destroy(a);
136 	OPENSSL_free(a);
137 	return(1);
138 	}
139 
140 void BIO_vfree(BIO *a)
141     { BIO_free(a); }
142 
143 int BIO_read(BIO *b, void *out, int outl)
144 	{
145 	int i;
146 	long (*cb)();
147 
148 	if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL))
149 		{
150 		BIOerr(BIO_F_BIO_READ,BIO_R_UNSUPPORTED_METHOD);
151 		return(-2);
152 		}
153 
154 	cb=b->callback;
155 	if ((cb != NULL) &&
156 		((i=(int)cb(b,BIO_CB_READ,out,outl,0L,1L)) <= 0))
157 			return(i);
158 
159 	if (!b->init)
160 		{
161 		BIOerr(BIO_F_BIO_READ,BIO_R_UNINITIALIZED);
162 		return(-2);
163 		}
164 
165 	i=b->method->bread(b,out,outl);
166 
167 	if (i > 0) b->num_read+=(unsigned long)i;
168 
169 	if (cb != NULL)
170 		i=(int)cb(b,BIO_CB_READ|BIO_CB_RETURN,out,outl,
171 			0L,(long)i);
172 	return(i);
173 	}
174 
175 int BIO_write(BIO *b, const void *in, int inl)
176 	{
177 	int i;
178 	long (*cb)();
179 
180 	if (b == NULL)
181 		return(0);
182 
183 	cb=b->callback;
184 	if ((b->method == NULL) || (b->method->bwrite == NULL))
185 		{
186 		BIOerr(BIO_F_BIO_WRITE,BIO_R_UNSUPPORTED_METHOD);
187 		return(-2);
188 		}
189 
190 	if ((cb != NULL) &&
191 		((i=(int)cb(b,BIO_CB_WRITE,in,inl,0L,1L)) <= 0))
192 			return(i);
193 
194 	if (!b->init)
195 		{
196 		BIOerr(BIO_F_BIO_WRITE,BIO_R_UNINITIALIZED);
197 		return(-2);
198 		}
199 
200 	i=b->method->bwrite(b,in,inl);
201 
202 	if (i > 0) b->num_write+=(unsigned long)i;
203 
204 	if (cb != NULL)
205 		i=(int)cb(b,BIO_CB_WRITE|BIO_CB_RETURN,in,inl,
206 			0L,(long)i);
207 	return(i);
208 	}
209 
210 int BIO_puts(BIO *b, const char *in)
211 	{
212 	int i;
213 	long (*cb)();
214 
215 	if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL))
216 		{
217 		BIOerr(BIO_F_BIO_PUTS,BIO_R_UNSUPPORTED_METHOD);
218 		return(-2);
219 		}
220 
221 	cb=b->callback;
222 
223 	if ((cb != NULL) &&
224 		((i=(int)cb(b,BIO_CB_PUTS,in,0,0L,1L)) <= 0))
225 			return(i);
226 
227 	if (!b->init)
228 		{
229 		BIOerr(BIO_F_BIO_PUTS,BIO_R_UNINITIALIZED);
230 		return(-2);
231 		}
232 
233 	i=b->method->bputs(b,in);
234 
235 	if (i > 0) b->num_write+=(unsigned long)i;
236 
237 	if (cb != NULL)
238 		i=(int)cb(b,BIO_CB_PUTS|BIO_CB_RETURN,in,0,
239 			0L,(long)i);
240 	return(i);
241 	}
242 
243 int BIO_gets(BIO *b, char *in, int inl)
244 	{
245 	int i;
246 	long (*cb)();
247 
248 	if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL))
249 		{
250 		BIOerr(BIO_F_BIO_GETS,BIO_R_UNSUPPORTED_METHOD);
251 		return(-2);
252 		}
253 
254 	cb=b->callback;
255 
256 	if ((cb != NULL) &&
257 		((i=(int)cb(b,BIO_CB_GETS,in,inl,0L,1L)) <= 0))
258 			return(i);
259 
260 	if (!b->init)
261 		{
262 		BIOerr(BIO_F_BIO_GETS,BIO_R_UNINITIALIZED);
263 		return(-2);
264 		}
265 
266 	i=b->method->bgets(b,in,inl);
267 
268 	if (cb != NULL)
269 		i=(int)cb(b,BIO_CB_GETS|BIO_CB_RETURN,in,inl,
270 			0L,(long)i);
271 	return(i);
272 	}
273 
274 long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
275 	{
276 	int i;
277 
278 	i=iarg;
279 	return(BIO_ctrl(b,cmd,larg,(char *)&i));
280 	}
281 
282 char *BIO_ptr_ctrl(BIO *b, int cmd, long larg)
283 	{
284 	char *p=NULL;
285 
286 	if (BIO_ctrl(b,cmd,larg,(char *)&p) <= 0)
287 		return(NULL);
288 	else
289 		return(p);
290 	}
291 
292 long BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
293 	{
294 	long ret;
295 	long (*cb)();
296 
297 	if (b == NULL) return(0);
298 
299 	if ((b->method == NULL) || (b->method->ctrl == NULL))
300 		{
301 		BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD);
302 		return(-2);
303 		}
304 
305 	cb=b->callback;
306 
307 	if ((cb != NULL) &&
308 		((ret=cb(b,BIO_CB_CTRL,parg,cmd,larg,1L)) <= 0))
309 		return(ret);
310 
311 	ret=b->method->ctrl(b,cmd,larg,parg);
312 
313 	if (cb != NULL)
314 		ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,parg,cmd,
315 			larg,ret);
316 	return(ret);
317 	}
318 
319 long BIO_callback_ctrl(BIO *b, int cmd, void (*fp)(struct bio_st *, int, const char *, int, long, long))
320 	{
321 	long ret;
322 	long (*cb)();
323 
324 	if (b == NULL) return(0);
325 
326 	if ((b->method == NULL) || (b->method->callback_ctrl == NULL))
327 		{
328 		BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD);
329 		return(-2);
330 		}
331 
332 	cb=b->callback;
333 
334 	if ((cb != NULL) &&
335 		((ret=cb(b,BIO_CB_CTRL,(void *)&fp,cmd,0,1L)) <= 0))
336 		return(ret);
337 
338 	ret=b->method->callback_ctrl(b,cmd,fp);
339 
340 	if (cb != NULL)
341 		ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,(void *)&fp,cmd,
342 			0,ret);
343 	return(ret);
344 	}
345 
346 /* It is unfortunate to duplicate in functions what the BIO_(w)pending macros
347  * do; but those macros have inappropriate return type, and for interfacing
348  * from other programming languages, C macros aren't much of a help anyway. */
349 size_t BIO_ctrl_pending(BIO *bio)
350 	{
351 	return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
352 	}
353 
354 size_t BIO_ctrl_wpending(BIO *bio)
355 	{
356 	return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
357 	}
358 
359 
360 /* put the 'bio' on the end of b's list of operators */
361 BIO *BIO_push(BIO *b, BIO *bio)
362 	{
363 	BIO *lb;
364 
365 	if (b == NULL) return(bio);
366 	lb=b;
367 	while (lb->next_bio != NULL)
368 		lb=lb->next_bio;
369 	lb->next_bio=bio;
370 	if (bio != NULL)
371 		bio->prev_bio=lb;
372 	/* called to do internal processing */
373 	BIO_ctrl(b,BIO_CTRL_PUSH,0,NULL);
374 	return(b);
375 	}
376 
377 /* Remove the first and return the rest */
378 BIO *BIO_pop(BIO *b)
379 	{
380 	BIO *ret;
381 
382 	if (b == NULL) return(NULL);
383 	ret=b->next_bio;
384 
385 	if (b->prev_bio != NULL)
386 		b->prev_bio->next_bio=b->next_bio;
387 	if (b->next_bio != NULL)
388 		b->next_bio->prev_bio=b->prev_bio;
389 
390 	b->next_bio=NULL;
391 	b->prev_bio=NULL;
392 	BIO_ctrl(b,BIO_CTRL_POP,0,NULL);
393 	return(ret);
394 	}
395 
396 BIO *BIO_get_retry_BIO(BIO *bio, int *reason)
397 	{
398 	BIO *b,*last;
399 
400 	b=last=bio;
401 	for (;;)
402 		{
403 		if (!BIO_should_retry(b)) break;
404 		last=b;
405 		b=b->next_bio;
406 		if (b == NULL) break;
407 		}
408 	if (reason != NULL) *reason=last->retry_reason;
409 	return(last);
410 	}
411 
412 int BIO_get_retry_reason(BIO *bio)
413 	{
414 	return(bio->retry_reason);
415 	}
416 
417 BIO *BIO_find_type(BIO *bio, int type)
418 	{
419 	int mt,mask;
420 
421 	if(!bio) return NULL;
422 	mask=type&0xff;
423 	do	{
424 		if (bio->method != NULL)
425 			{
426 			mt=bio->method->type;
427 
428 			if (!mask)
429 				{
430 				if (mt & type) return(bio);
431 				}
432 			else if (mt == type)
433 				return(bio);
434 			}
435 		bio=bio->next_bio;
436 		} while (bio != NULL);
437 	return(NULL);
438 	}
439 
440 BIO *BIO_next(BIO *b)
441 	{
442 	if(!b) return NULL;
443 	return b->next_bio;
444 	}
445 
446 void BIO_free_all(BIO *bio)
447 	{
448 	BIO *b;
449 	int ref;
450 
451 	while (bio != NULL)
452 		{
453 		b=bio;
454 		ref=b->references;
455 		bio=bio->next_bio;
456 		BIO_free(b);
457 		/* Since ref count > 1, don't free anyone else. */
458 		if (ref > 1) break;
459 		}
460 	}
461 
462 BIO *BIO_dup_chain(BIO *in)
463 	{
464 	BIO *ret=NULL,*eoc=NULL,*bio,*new;
465 
466 	for (bio=in; bio != NULL; bio=bio->next_bio)
467 		{
468 		if ((new=BIO_new(bio->method)) == NULL) goto err;
469 		new->callback=bio->callback;
470 		new->cb_arg=bio->cb_arg;
471 		new->init=bio->init;
472 		new->shutdown=bio->shutdown;
473 		new->flags=bio->flags;
474 
475 		/* This will let SSL_s_sock() work with stdin/stdout */
476 		new->num=bio->num;
477 
478 		if (!BIO_dup_state(bio,(char *)new))
479 			{
480 			BIO_free(new);
481 			goto err;
482 			}
483 
484 		/* copy app data */
485 		if (!CRYPTO_dup_ex_data(bio_meth,&new->ex_data,&bio->ex_data))
486 			goto err;
487 
488 		if (ret == NULL)
489 			{
490 			eoc=new;
491 			ret=eoc;
492 			}
493 		else
494 			{
495 			BIO_push(eoc,new);
496 			eoc=new;
497 			}
498 		}
499 	return(ret);
500 err:
501 	if (ret != NULL)
502 		BIO_free(ret);
503 	return(NULL);
504 	}
505 
506 void BIO_copy_next_retry(BIO *b)
507 	{
508 	BIO_set_flags(b,BIO_get_retry_flags(b->next_bio));
509 	b->retry_reason=b->next_bio->retry_reason;
510 	}
511 
512 int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
513 	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
514 	{
515 	bio_meth_num++;
516 	return(CRYPTO_get_ex_new_index(bio_meth_num-1,&bio_meth,
517 		argl,argp,new_func,dup_func,free_func));
518 	}
519 
520 int BIO_set_ex_data(BIO *bio, int idx, void *data)
521 	{
522 	return(CRYPTO_set_ex_data(&(bio->ex_data),idx,data));
523 	}
524 
525 void *BIO_get_ex_data(BIO *bio, int idx)
526 	{
527 	return(CRYPTO_get_ex_data(&(bio->ex_data),idx));
528 	}
529 
530 unsigned long BIO_number_read(BIO *bio)
531 {
532 	if(bio) return bio->num_read;
533 	return 0;
534 }
535 
536 unsigned long BIO_number_written(BIO *bio)
537 {
538 	if(bio) return bio->num_write;
539 	return 0;
540 }
541 
542 IMPLEMENT_STACK_OF(BIO)
543