1*acf64401Sbeck /* $OpenBSD: bf_nbio.c,v 1.23 2023/07/05 21:23:37 beck Exp $ */
25b37fcf3Sryker /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
35b37fcf3Sryker * All rights reserved.
45b37fcf3Sryker *
55b37fcf3Sryker * This package is an SSL implementation written
65b37fcf3Sryker * by Eric Young (eay@cryptsoft.com).
75b37fcf3Sryker * The implementation was written so as to conform with Netscapes SSL.
85b37fcf3Sryker *
95b37fcf3Sryker * This library is free for commercial and non-commercial use as long as
105b37fcf3Sryker * the following conditions are aheared to. The following conditions
115b37fcf3Sryker * apply to all code found in this distribution, be it the RC4, RSA,
125b37fcf3Sryker * lhash, DES, etc., code; not just the SSL code. The SSL documentation
135b37fcf3Sryker * included with this distribution is covered by the same copyright terms
145b37fcf3Sryker * except that the holder is Tim Hudson (tjh@cryptsoft.com).
155b37fcf3Sryker *
165b37fcf3Sryker * Copyright remains Eric Young's, and as such any Copyright notices in
175b37fcf3Sryker * the code are not to be removed.
185b37fcf3Sryker * If this package is used in a product, Eric Young should be given attribution
195b37fcf3Sryker * as the author of the parts of the library used.
205b37fcf3Sryker * This can be in the form of a textual message at program startup or
215b37fcf3Sryker * in documentation (online or textual) provided with the package.
225b37fcf3Sryker *
235b37fcf3Sryker * Redistribution and use in source and binary forms, with or without
245b37fcf3Sryker * modification, are permitted provided that the following conditions
255b37fcf3Sryker * are met:
265b37fcf3Sryker * 1. Redistributions of source code must retain the copyright
275b37fcf3Sryker * notice, this list of conditions and the following disclaimer.
285b37fcf3Sryker * 2. Redistributions in binary form must reproduce the above copyright
295b37fcf3Sryker * notice, this list of conditions and the following disclaimer in the
305b37fcf3Sryker * documentation and/or other materials provided with the distribution.
315b37fcf3Sryker * 3. All advertising materials mentioning features or use of this software
325b37fcf3Sryker * must display the following acknowledgement:
335b37fcf3Sryker * "This product includes cryptographic software written by
345b37fcf3Sryker * Eric Young (eay@cryptsoft.com)"
355b37fcf3Sryker * The word 'cryptographic' can be left out if the rouines from the library
365b37fcf3Sryker * being used are not cryptographic related :-).
375b37fcf3Sryker * 4. If you include any Windows specific code (or a derivative thereof) from
385b37fcf3Sryker * the apps directory (application code) you must include an acknowledgement:
395b37fcf3Sryker * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
405b37fcf3Sryker *
415b37fcf3Sryker * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
425b37fcf3Sryker * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
435b37fcf3Sryker * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
445b37fcf3Sryker * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
455b37fcf3Sryker * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
465b37fcf3Sryker * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
475b37fcf3Sryker * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
485b37fcf3Sryker * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
495b37fcf3Sryker * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
505b37fcf3Sryker * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
515b37fcf3Sryker * SUCH DAMAGE.
525b37fcf3Sryker *
535b37fcf3Sryker * The licence and distribution terms for any publically available version or
545b37fcf3Sryker * derivative of this code cannot be changed. i.e. this code cannot simply be
555b37fcf3Sryker * copied and put under another distribution licence
565b37fcf3Sryker * [including the GNU Public Licence.]
575b37fcf3Sryker */
585b37fcf3Sryker
595b37fcf3Sryker #include <errno.h>
60b6ab114eSjsing #include <stdio.h>
61ef624301Sjsing #include <stdlib.h>
62b6ab114eSjsing
63913ec974Sbeck #include <openssl/bio.h>
645b37fcf3Sryker
6594b1984eStb #include "bio_local.h"
6694b1984eStb
675b37fcf3Sryker /* BIO_put and BIO_get both add to the digest,
685b37fcf3Sryker * BIO_gets returns the digest */
695b37fcf3Sryker
70c109e398Sbeck static int nbiof_write(BIO *h, const char *buf, int num);
715b37fcf3Sryker static int nbiof_read(BIO *h, char *buf, int size);
72c109e398Sbeck static int nbiof_puts(BIO *h, const char *str);
735b37fcf3Sryker static int nbiof_gets(BIO *h, char *str, int size);
74c109e398Sbeck static long nbiof_ctrl(BIO *h, int cmd, long arg1, void *arg2);
755b37fcf3Sryker static int nbiof_new(BIO *h);
765b37fcf3Sryker static int nbiof_free(BIO *data);
77818427c5Stb static long nbiof_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
78c3d505beSjsing
79c3d505beSjsing typedef struct nbio_test_st {
805b37fcf3Sryker /* only set if we sent a 'should retry' error */
815b37fcf3Sryker int lrn;
825b37fcf3Sryker int lwn;
835b37fcf3Sryker } NBIO_TEST;
845b37fcf3Sryker
856dc76777Stb static const BIO_METHOD methods_nbiof = {
86e402ce74Smiod .type = BIO_TYPE_NBIO_TEST,
87e402ce74Smiod .name = "non-blocking IO test filter",
88e402ce74Smiod .bwrite = nbiof_write,
89e402ce74Smiod .bread = nbiof_read,
90e402ce74Smiod .bputs = nbiof_puts,
91e402ce74Smiod .bgets = nbiof_gets,
92e402ce74Smiod .ctrl = nbiof_ctrl,
93e402ce74Smiod .create = nbiof_new,
94e402ce74Smiod .destroy = nbiof_free,
95e402ce74Smiod .callback_ctrl = nbiof_callback_ctrl
965b37fcf3Sryker };
975b37fcf3Sryker
986dc76777Stb const BIO_METHOD *
BIO_f_nbio_test(void)99ae7f143bSderaadt BIO_f_nbio_test(void)
1005b37fcf3Sryker {
1015b37fcf3Sryker return (&methods_nbiof);
1025b37fcf3Sryker }
103*acf64401Sbeck LCRYPTO_ALIAS(BIO_f_nbio_test);
1045b37fcf3Sryker
105c3d505beSjsing static int
nbiof_new(BIO * bi)106c3d505beSjsing nbiof_new(BIO *bi)
1075b37fcf3Sryker {
1085b37fcf3Sryker NBIO_TEST *nt;
1095b37fcf3Sryker
1103c6fe066Sderaadt if (!(nt = malloc(sizeof(NBIO_TEST))))
111c3d505beSjsing return (0);
1125b37fcf3Sryker nt->lrn = -1;
1135b37fcf3Sryker nt->lwn = -1;
1145b37fcf3Sryker bi->ptr = (char *)nt;
1155b37fcf3Sryker bi->init = 1;
1165b37fcf3Sryker bi->flags = 0;
1175b37fcf3Sryker return (1);
1185b37fcf3Sryker }
1195b37fcf3Sryker
120c3d505beSjsing static int
nbiof_free(BIO * a)121c3d505beSjsing nbiof_free(BIO *a)
1225b37fcf3Sryker {
123c3d505beSjsing if (a == NULL)
124c3d505beSjsing return (0);
1256f3a6cb1Sbeck free(a->ptr);
1265b37fcf3Sryker a->ptr = NULL;
1275b37fcf3Sryker a->init = 0;
1285b37fcf3Sryker a->flags = 0;
1295b37fcf3Sryker return (1);
1305b37fcf3Sryker }
1315b37fcf3Sryker
132c3d505beSjsing static int
nbiof_read(BIO * b,char * out,int outl)133c3d505beSjsing nbiof_read(BIO *b, char *out, int outl)
1345b37fcf3Sryker {
1355b37fcf3Sryker int ret = 0;
1365b37fcf3Sryker int num;
1375b37fcf3Sryker unsigned char n;
1385b37fcf3Sryker
139c3d505beSjsing if (out == NULL)
140c3d505beSjsing return (0);
141c3d505beSjsing if (b->next_bio == NULL)
142c3d505beSjsing return (0);
1435b37fcf3Sryker
1445b37fcf3Sryker BIO_clear_retry_flags(b);
145700744f6Sdoug
146ef624301Sjsing arc4random_buf(&n, 1);
1475b37fcf3Sryker num = (n & 0x07);
1485b37fcf3Sryker
149c3d505beSjsing if (outl > num)
150c3d505beSjsing outl = num;
1515b37fcf3Sryker
152c3d505beSjsing if (num == 0) {
1535b37fcf3Sryker ret = -1;
1545b37fcf3Sryker BIO_set_retry_read(b);
155700744f6Sdoug } else {
1565b37fcf3Sryker ret = BIO_read(b->next_bio, out, outl);
1575b37fcf3Sryker if (ret < 0)
1585b37fcf3Sryker BIO_copy_next_retry(b);
1595b37fcf3Sryker }
1605b37fcf3Sryker return (ret);
1615b37fcf3Sryker }
1625b37fcf3Sryker
163c3d505beSjsing static int
nbiof_write(BIO * b,const char * in,int inl)164c3d505beSjsing nbiof_write(BIO *b, const char *in, int inl)
1655b37fcf3Sryker {
1665b37fcf3Sryker NBIO_TEST *nt;
1675b37fcf3Sryker int ret = 0;
1685b37fcf3Sryker int num;
1695b37fcf3Sryker unsigned char n;
1705b37fcf3Sryker
171c3d505beSjsing if ((in == NULL) || (inl <= 0))
172c3d505beSjsing return (0);
173c3d505beSjsing if (b->next_bio == NULL)
174c3d505beSjsing return (0);
1755b37fcf3Sryker nt = (NBIO_TEST *)b->ptr;
1765b37fcf3Sryker
1775b37fcf3Sryker BIO_clear_retry_flags(b);
1785b37fcf3Sryker
179c3d505beSjsing if (nt->lwn > 0) {
1805b37fcf3Sryker num = nt->lwn;
1815b37fcf3Sryker nt->lwn = 0;
182c3d505beSjsing } else {
183ef624301Sjsing arc4random_buf(&n, 1);
1845b37fcf3Sryker num = (n&7);
1855b37fcf3Sryker }
1865b37fcf3Sryker
187c3d505beSjsing if (inl > num)
188c3d505beSjsing inl = num;
1895b37fcf3Sryker
190c3d505beSjsing if (num == 0) {
1915b37fcf3Sryker ret = -1;
1925b37fcf3Sryker BIO_set_retry_write(b);
193700744f6Sdoug } else {
1945b37fcf3Sryker ret = BIO_write(b->next_bio, in, inl);
195c3d505beSjsing if (ret < 0) {
1965b37fcf3Sryker BIO_copy_next_retry(b);
1975b37fcf3Sryker nt->lwn = inl;
1985b37fcf3Sryker }
1995b37fcf3Sryker }
2005b37fcf3Sryker return (ret);
2015b37fcf3Sryker }
2025b37fcf3Sryker
203c3d505beSjsing static long
nbiof_ctrl(BIO * b,int cmd,long num,void * ptr)204c3d505beSjsing nbiof_ctrl(BIO *b, int cmd, long num, void *ptr)
2055b37fcf3Sryker {
2065b37fcf3Sryker long ret;
2075b37fcf3Sryker
208c3d505beSjsing if (b->next_bio == NULL)
209c3d505beSjsing return (0);
210c3d505beSjsing switch (cmd) {
2115b37fcf3Sryker case BIO_C_DO_STATE_MACHINE:
2125b37fcf3Sryker BIO_clear_retry_flags(b);
2135b37fcf3Sryker ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
2145b37fcf3Sryker BIO_copy_next_retry(b);
2155b37fcf3Sryker break;
2165b37fcf3Sryker case BIO_CTRL_DUP:
2175b37fcf3Sryker ret = 0L;
2185b37fcf3Sryker break;
2195b37fcf3Sryker default:
2205b37fcf3Sryker ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
2215b37fcf3Sryker break;
2225b37fcf3Sryker }
2235b37fcf3Sryker return (ret);
2245b37fcf3Sryker }
2255b37fcf3Sryker
226c3d505beSjsing static long
nbiof_callback_ctrl(BIO * b,int cmd,BIO_info_cb * fp)227818427c5Stb nbiof_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
228ba5406e9Sbeck {
229ba5406e9Sbeck long ret = 1;
230ba5406e9Sbeck
231c3d505beSjsing if (b->next_bio == NULL)
232c3d505beSjsing return (0);
233c3d505beSjsing switch (cmd) {
234ba5406e9Sbeck default:
235ba5406e9Sbeck ret = BIO_callback_ctrl(b->next_bio, cmd, fp);
236ba5406e9Sbeck break;
237ba5406e9Sbeck }
238ba5406e9Sbeck return (ret);
239ba5406e9Sbeck }
240ba5406e9Sbeck
241c3d505beSjsing static int
nbiof_gets(BIO * bp,char * buf,int size)242c3d505beSjsing nbiof_gets(BIO *bp, char *buf, int size)
2435b37fcf3Sryker {
244c3d505beSjsing if (bp->next_bio == NULL)
245c3d505beSjsing return (0);
2465b37fcf3Sryker return (BIO_gets(bp->next_bio, buf, size));
2475b37fcf3Sryker }
2485b37fcf3Sryker
249c3d505beSjsing static int
nbiof_puts(BIO * bp,const char * str)250c3d505beSjsing nbiof_puts(BIO *bp, const char *str)
2515b37fcf3Sryker {
252c3d505beSjsing if (bp->next_bio == NULL)
253c3d505beSjsing return (0);
2545b37fcf3Sryker return (BIO_puts(bp->next_bio, str));
2555b37fcf3Sryker }
256