xref: /dragonfly/crypto/libressl/crypto/bio/bf_nbio.c (revision de0e0e4d)
1*de0e0e4dSAntonio Huete Jimenez /* $OpenBSD: bf_nbio.c,v 1.22 2022/01/14 08:40:57 tb Exp $ */
2f5b1c8a1SJohn Marino /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3f5b1c8a1SJohn Marino  * All rights reserved.
4f5b1c8a1SJohn Marino  *
5f5b1c8a1SJohn Marino  * This package is an SSL implementation written
6f5b1c8a1SJohn Marino  * by Eric Young (eay@cryptsoft.com).
7f5b1c8a1SJohn Marino  * The implementation was written so as to conform with Netscapes SSL.
8f5b1c8a1SJohn Marino  *
9f5b1c8a1SJohn Marino  * This library is free for commercial and non-commercial use as long as
10f5b1c8a1SJohn Marino  * the following conditions are aheared to.  The following conditions
11f5b1c8a1SJohn Marino  * apply to all code found in this distribution, be it the RC4, RSA,
12f5b1c8a1SJohn Marino  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13f5b1c8a1SJohn Marino  * included with this distribution is covered by the same copyright terms
14f5b1c8a1SJohn Marino  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15f5b1c8a1SJohn Marino  *
16f5b1c8a1SJohn Marino  * Copyright remains Eric Young's, and as such any Copyright notices in
17f5b1c8a1SJohn Marino  * the code are not to be removed.
18f5b1c8a1SJohn Marino  * If this package is used in a product, Eric Young should be given attribution
19f5b1c8a1SJohn Marino  * as the author of the parts of the library used.
20f5b1c8a1SJohn Marino  * This can be in the form of a textual message at program startup or
21f5b1c8a1SJohn Marino  * in documentation (online or textual) provided with the package.
22f5b1c8a1SJohn Marino  *
23f5b1c8a1SJohn Marino  * Redistribution and use in source and binary forms, with or without
24f5b1c8a1SJohn Marino  * modification, are permitted provided that the following conditions
25f5b1c8a1SJohn Marino  * are met:
26f5b1c8a1SJohn Marino  * 1. Redistributions of source code must retain the copyright
27f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer.
28f5b1c8a1SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
29f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
30f5b1c8a1SJohn Marino  *    documentation and/or other materials provided with the distribution.
31f5b1c8a1SJohn Marino  * 3. All advertising materials mentioning features or use of this software
32f5b1c8a1SJohn Marino  *    must display the following acknowledgement:
33f5b1c8a1SJohn Marino  *    "This product includes cryptographic software written by
34f5b1c8a1SJohn Marino  *     Eric Young (eay@cryptsoft.com)"
35f5b1c8a1SJohn Marino  *    The word 'cryptographic' can be left out if the rouines from the library
36f5b1c8a1SJohn Marino  *    being used are not cryptographic related :-).
37f5b1c8a1SJohn Marino  * 4. If you include any Windows specific code (or a derivative thereof) from
38f5b1c8a1SJohn Marino  *    the apps directory (application code) you must include an acknowledgement:
39f5b1c8a1SJohn Marino  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40f5b1c8a1SJohn Marino  *
41f5b1c8a1SJohn Marino  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42f5b1c8a1SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43f5b1c8a1SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44f5b1c8a1SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45f5b1c8a1SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46f5b1c8a1SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47f5b1c8a1SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48f5b1c8a1SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49f5b1c8a1SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50f5b1c8a1SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51f5b1c8a1SJohn Marino  * SUCH DAMAGE.
52f5b1c8a1SJohn Marino  *
53f5b1c8a1SJohn Marino  * The licence and distribution terms for any publically available version or
54f5b1c8a1SJohn Marino  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55f5b1c8a1SJohn Marino  * copied and put under another distribution licence
56f5b1c8a1SJohn Marino  * [including the GNU Public Licence.]
57f5b1c8a1SJohn Marino  */
58f5b1c8a1SJohn Marino 
59f5b1c8a1SJohn Marino #include <errno.h>
60f5b1c8a1SJohn Marino #include <stdio.h>
61f5b1c8a1SJohn Marino #include <stdlib.h>
62f5b1c8a1SJohn Marino 
63f5b1c8a1SJohn Marino #include <openssl/bio.h>
64f5b1c8a1SJohn Marino 
65*de0e0e4dSAntonio Huete Jimenez #include "bio_local.h"
66*de0e0e4dSAntonio Huete Jimenez 
67f5b1c8a1SJohn Marino /* BIO_put and BIO_get both add to the digest,
68f5b1c8a1SJohn Marino  * BIO_gets returns the digest */
69f5b1c8a1SJohn Marino 
70f5b1c8a1SJohn Marino static int nbiof_write(BIO *h, const char *buf, int num);
71f5b1c8a1SJohn Marino static int nbiof_read(BIO *h, char *buf, int size);
72f5b1c8a1SJohn Marino static int nbiof_puts(BIO *h, const char *str);
73f5b1c8a1SJohn Marino static int nbiof_gets(BIO *h, char *str, int size);
74f5b1c8a1SJohn Marino static long nbiof_ctrl(BIO *h, int cmd, long arg1, void *arg2);
75f5b1c8a1SJohn Marino static int nbiof_new(BIO *h);
76f5b1c8a1SJohn Marino static int nbiof_free(BIO *data);
77*de0e0e4dSAntonio Huete Jimenez static long nbiof_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
78f5b1c8a1SJohn Marino 
79f5b1c8a1SJohn Marino typedef struct nbio_test_st {
80f5b1c8a1SJohn Marino 	/* only set if we sent a 'should retry' error */
81f5b1c8a1SJohn Marino 	int lrn;
82f5b1c8a1SJohn Marino 	int lwn;
83f5b1c8a1SJohn Marino } NBIO_TEST;
84f5b1c8a1SJohn Marino 
8572c33676SMaxim Ag static const BIO_METHOD methods_nbiof = {
86f5b1c8a1SJohn Marino 	.type = BIO_TYPE_NBIO_TEST,
87f5b1c8a1SJohn Marino 	.name = "non-blocking IO test filter",
88f5b1c8a1SJohn Marino 	.bwrite = nbiof_write,
89f5b1c8a1SJohn Marino 	.bread = nbiof_read,
90f5b1c8a1SJohn Marino 	.bputs = nbiof_puts,
91f5b1c8a1SJohn Marino 	.bgets = nbiof_gets,
92f5b1c8a1SJohn Marino 	.ctrl = nbiof_ctrl,
93f5b1c8a1SJohn Marino 	.create = nbiof_new,
94f5b1c8a1SJohn Marino 	.destroy = nbiof_free,
95f5b1c8a1SJohn Marino 	.callback_ctrl = nbiof_callback_ctrl
96f5b1c8a1SJohn Marino };
97f5b1c8a1SJohn Marino 
9872c33676SMaxim Ag const BIO_METHOD *
BIO_f_nbio_test(void)99f5b1c8a1SJohn Marino BIO_f_nbio_test(void)
100f5b1c8a1SJohn Marino {
101f5b1c8a1SJohn Marino 	return (&methods_nbiof);
102f5b1c8a1SJohn Marino }
103f5b1c8a1SJohn Marino 
104f5b1c8a1SJohn Marino static int
nbiof_new(BIO * bi)105f5b1c8a1SJohn Marino nbiof_new(BIO *bi)
106f5b1c8a1SJohn Marino {
107f5b1c8a1SJohn Marino 	NBIO_TEST *nt;
108f5b1c8a1SJohn Marino 
109f5b1c8a1SJohn Marino 	if (!(nt = malloc(sizeof(NBIO_TEST))))
110f5b1c8a1SJohn Marino 		return (0);
111f5b1c8a1SJohn Marino 	nt->lrn = -1;
112f5b1c8a1SJohn Marino 	nt->lwn = -1;
113f5b1c8a1SJohn Marino 	bi->ptr = (char *)nt;
114f5b1c8a1SJohn Marino 	bi->init = 1;
115f5b1c8a1SJohn Marino 	bi->flags = 0;
116f5b1c8a1SJohn Marino 	return (1);
117f5b1c8a1SJohn Marino }
118f5b1c8a1SJohn Marino 
119f5b1c8a1SJohn Marino static int
nbiof_free(BIO * a)120f5b1c8a1SJohn Marino nbiof_free(BIO *a)
121f5b1c8a1SJohn Marino {
122f5b1c8a1SJohn Marino 	if (a == NULL)
123f5b1c8a1SJohn Marino 		return (0);
124f5b1c8a1SJohn Marino 	free(a->ptr);
125f5b1c8a1SJohn Marino 	a->ptr = NULL;
126f5b1c8a1SJohn Marino 	a->init = 0;
127f5b1c8a1SJohn Marino 	a->flags = 0;
128f5b1c8a1SJohn Marino 	return (1);
129f5b1c8a1SJohn Marino }
130f5b1c8a1SJohn Marino 
131f5b1c8a1SJohn Marino static int
nbiof_read(BIO * b,char * out,int outl)132f5b1c8a1SJohn Marino nbiof_read(BIO *b, char *out, int outl)
133f5b1c8a1SJohn Marino {
134f5b1c8a1SJohn Marino 	int ret = 0;
135f5b1c8a1SJohn Marino 	int num;
136f5b1c8a1SJohn Marino 	unsigned char n;
137f5b1c8a1SJohn Marino 
138f5b1c8a1SJohn Marino 	if (out == NULL)
139f5b1c8a1SJohn Marino 		return (0);
140f5b1c8a1SJohn Marino 	if (b->next_bio == NULL)
141f5b1c8a1SJohn Marino 		return (0);
142f5b1c8a1SJohn Marino 
143f5b1c8a1SJohn Marino 	BIO_clear_retry_flags(b);
144f5b1c8a1SJohn Marino 
145f5b1c8a1SJohn Marino 	arc4random_buf(&n, 1);
146f5b1c8a1SJohn Marino 	num = (n & 0x07);
147f5b1c8a1SJohn Marino 
148f5b1c8a1SJohn Marino 	if (outl > num)
149f5b1c8a1SJohn Marino 		outl = num;
150f5b1c8a1SJohn Marino 
151f5b1c8a1SJohn Marino 	if (num == 0) {
152f5b1c8a1SJohn Marino 		ret = -1;
153f5b1c8a1SJohn Marino 		BIO_set_retry_read(b);
154f5b1c8a1SJohn Marino 	} else {
155f5b1c8a1SJohn Marino 		ret = BIO_read(b->next_bio, out, outl);
156f5b1c8a1SJohn Marino 		if (ret < 0)
157f5b1c8a1SJohn Marino 			BIO_copy_next_retry(b);
158f5b1c8a1SJohn Marino 	}
159f5b1c8a1SJohn Marino 	return (ret);
160f5b1c8a1SJohn Marino }
161f5b1c8a1SJohn Marino 
162f5b1c8a1SJohn Marino static int
nbiof_write(BIO * b,const char * in,int inl)163f5b1c8a1SJohn Marino nbiof_write(BIO *b, const char *in, int inl)
164f5b1c8a1SJohn Marino {
165f5b1c8a1SJohn Marino 	NBIO_TEST *nt;
166f5b1c8a1SJohn Marino 	int ret = 0;
167f5b1c8a1SJohn Marino 	int num;
168f5b1c8a1SJohn Marino 	unsigned char n;
169f5b1c8a1SJohn Marino 
170f5b1c8a1SJohn Marino 	if ((in == NULL) || (inl <= 0))
171f5b1c8a1SJohn Marino 		return (0);
172f5b1c8a1SJohn Marino 	if (b->next_bio == NULL)
173f5b1c8a1SJohn Marino 		return (0);
174f5b1c8a1SJohn Marino 	nt = (NBIO_TEST *)b->ptr;
175f5b1c8a1SJohn Marino 
176f5b1c8a1SJohn Marino 	BIO_clear_retry_flags(b);
177f5b1c8a1SJohn Marino 
178f5b1c8a1SJohn Marino 	if (nt->lwn > 0) {
179f5b1c8a1SJohn Marino 		num = nt->lwn;
180f5b1c8a1SJohn Marino 		nt->lwn = 0;
181f5b1c8a1SJohn Marino 	} else {
182f5b1c8a1SJohn Marino 		arc4random_buf(&n, 1);
183f5b1c8a1SJohn Marino 		num = (n&7);
184f5b1c8a1SJohn Marino 	}
185f5b1c8a1SJohn Marino 
186f5b1c8a1SJohn Marino 	if (inl > num)
187f5b1c8a1SJohn Marino 		inl = num;
188f5b1c8a1SJohn Marino 
189f5b1c8a1SJohn Marino 	if (num == 0) {
190f5b1c8a1SJohn Marino 		ret = -1;
191f5b1c8a1SJohn Marino 		BIO_set_retry_write(b);
192f5b1c8a1SJohn Marino 	} else {
193f5b1c8a1SJohn Marino 		ret = BIO_write(b->next_bio, in, inl);
194f5b1c8a1SJohn Marino 		if (ret < 0) {
195f5b1c8a1SJohn Marino 			BIO_copy_next_retry(b);
196f5b1c8a1SJohn Marino 			nt->lwn = inl;
197f5b1c8a1SJohn Marino 		}
198f5b1c8a1SJohn Marino 	}
199f5b1c8a1SJohn Marino 	return (ret);
200f5b1c8a1SJohn Marino }
201f5b1c8a1SJohn Marino 
202f5b1c8a1SJohn Marino static long
nbiof_ctrl(BIO * b,int cmd,long num,void * ptr)203f5b1c8a1SJohn Marino nbiof_ctrl(BIO *b, int cmd, long num, void *ptr)
204f5b1c8a1SJohn Marino {
205f5b1c8a1SJohn Marino 	long ret;
206f5b1c8a1SJohn Marino 
207f5b1c8a1SJohn Marino 	if (b->next_bio == NULL)
208f5b1c8a1SJohn Marino 		return (0);
209f5b1c8a1SJohn Marino 	switch (cmd) {
210f5b1c8a1SJohn Marino 	case BIO_C_DO_STATE_MACHINE:
211f5b1c8a1SJohn Marino 		BIO_clear_retry_flags(b);
212f5b1c8a1SJohn Marino 		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
213f5b1c8a1SJohn Marino 		BIO_copy_next_retry(b);
214f5b1c8a1SJohn Marino 		break;
215f5b1c8a1SJohn Marino 	case BIO_CTRL_DUP:
216f5b1c8a1SJohn Marino 		ret = 0L;
217f5b1c8a1SJohn Marino 		break;
218f5b1c8a1SJohn Marino 	default:
219f5b1c8a1SJohn Marino 		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
220f5b1c8a1SJohn Marino 		break;
221f5b1c8a1SJohn Marino 	}
222f5b1c8a1SJohn Marino 	return (ret);
223f5b1c8a1SJohn Marino }
224f5b1c8a1SJohn Marino 
225f5b1c8a1SJohn Marino static long
nbiof_callback_ctrl(BIO * b,int cmd,BIO_info_cb * fp)226*de0e0e4dSAntonio Huete Jimenez nbiof_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
227f5b1c8a1SJohn Marino {
228f5b1c8a1SJohn Marino 	long ret = 1;
229f5b1c8a1SJohn Marino 
230f5b1c8a1SJohn Marino 	if (b->next_bio == NULL)
231f5b1c8a1SJohn Marino 		return (0);
232f5b1c8a1SJohn Marino 	switch (cmd) {
233f5b1c8a1SJohn Marino 	default:
234f5b1c8a1SJohn Marino 		ret = BIO_callback_ctrl(b->next_bio, cmd, fp);
235f5b1c8a1SJohn Marino 		break;
236f5b1c8a1SJohn Marino 	}
237f5b1c8a1SJohn Marino 	return (ret);
238f5b1c8a1SJohn Marino }
239f5b1c8a1SJohn Marino 
240f5b1c8a1SJohn Marino static int
nbiof_gets(BIO * bp,char * buf,int size)241f5b1c8a1SJohn Marino nbiof_gets(BIO *bp, char *buf, int size)
242f5b1c8a1SJohn Marino {
243f5b1c8a1SJohn Marino 	if (bp->next_bio == NULL)
244f5b1c8a1SJohn Marino 		return (0);
245f5b1c8a1SJohn Marino 	return (BIO_gets(bp->next_bio, buf, size));
246f5b1c8a1SJohn Marino }
247f5b1c8a1SJohn Marino 
248f5b1c8a1SJohn Marino static int
nbiof_puts(BIO * bp,const char * str)249f5b1c8a1SJohn Marino nbiof_puts(BIO *bp, const char *str)
250f5b1c8a1SJohn Marino {
251f5b1c8a1SJohn Marino 	if (bp->next_bio == NULL)
252f5b1c8a1SJohn Marino 		return (0);
253f5b1c8a1SJohn Marino 	return (BIO_puts(bp->next_bio, str));
254f5b1c8a1SJohn Marino }
255