1 // Copyright 2020 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "ssl_lib.h"
16 #include "openssl/bio.h"
17 #include "ssl_dbg.h"
18 #include "openssl/err.h"
19 
20 #define DEFAULT_BIO_SIZE 1024
21 
BIO_new_mem_buf(void * buf,int len)22 BIO *BIO_new_mem_buf(void *buf, int len)
23 {
24     BIO_METHOD m = { .type = BIO_TYPE_MEM, .size = 0 };
25     BIO *b = BIO_new(&m);
26     if (b) {
27         b->dlen = len;
28         b->data = buf;
29     }
30     return b;
31 }
32 
33 /**
34  * @brief create a BIO object
35  */
BIO_new(BIO_METHOD * method)36 BIO *BIO_new(BIO_METHOD * method)
37 {
38     BIO *b = (BIO *)ssl_mem_zalloc(sizeof(BIO));
39     if (!b) {
40         OPENSSL_PUT_LIB_ERROR(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
41         goto err;
42     }
43     if (method) {
44         b->size = method->size;
45         b->type = method->type;
46     } else {
47         b->type = BIO_TYPE_NONE;
48     }
49     if ((b->type & BIO_TYPE_BIO) && b->size) {
50         b->data = ssl_mem_zalloc(b->size);
51         if (!b->data) {
52             OPENSSL_PUT_LIB_ERROR(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
53             goto err;
54         }
55     }
56     return b;
57 
58 err:
59     if (b && (b->type&BIO_TYPE_BIO)) {
60         ssl_mem_free(b->data);
61     }
62     ssl_mem_free(b);
63     return NULL;
64 }
65 
66 /**
67  * @brief free a BIO object
68  */
BIO_free(BIO * b)69 void BIO_free(BIO *b)
70 {
71     if (b && (b->type&BIO_TYPE_BIO)) {
72         ssl_mem_free(b->data);
73     }
74     ssl_mem_free(b);
75 }
76 
BIO_new_bio_pair(BIO ** out1,size_t writebuf1,BIO ** out2,size_t writebuf2)77 int BIO_new_bio_pair(BIO **out1, size_t writebuf1, BIO **out2, size_t writebuf2)
78 {
79     BIO *bio1 = NULL;
80     BIO *bio2 = NULL;
81     if (!writebuf1) {
82         writebuf1 = DEFAULT_BIO_SIZE;
83     }
84     if (!writebuf2) {
85         writebuf2 = DEFAULT_BIO_SIZE;
86     }
87     BIO_METHOD m1 = {
88             .size = writebuf1,
89             .type = BIO_TYPE_BIO,
90     };
91     BIO_METHOD m2 = {
92             .size = writebuf1,
93             .type = BIO_TYPE_BIO,
94     };
95     bio1 = BIO_new(&m1);
96     if (!bio1) {
97         goto err;
98     }
99     bio2 = BIO_new(&m2);
100     if (!bio2) {
101         goto err;
102     }
103     *out1 = bio1;
104     *out2 = bio2;
105     bio1->peer = bio2;
106     bio1->size = writebuf1;
107     bio2->peer = bio1;
108     bio2->size = writebuf2;
109     return 1;
110 
111 err:
112     if (bio1)
113     {
114         BIO_free(bio1);
115         *out1 = NULL;
116     }
117     if (bio2)
118     {
119         BIO_free(bio2);
120         *out2 = NULL;
121     }
122     return 0;
123 
124 }
125 
126 /**
127  * @brief get the memory BIO method function
128  */
BIO_s_mem(void)129 void *BIO_s_mem(void)
130 {
131     return NULL;
132 }
133 
BIO_method_type(const BIO * b)134 int BIO_method_type(const BIO *b)
135 {
136     SSL_ASSERT1(b);
137     return b->type;
138 }
139 
140 /**
141  * @brief load data into BIO.
142  *
143  */
BIO_write(BIO * b,const void * data,int dlen)144 int BIO_write(BIO *b, const void * data, int dlen)
145 {
146     SSL_ASSERT1(b);
147     int remaining = b->size - b->offset;
148     if (remaining <= 0) {
149         b->flags |= BIO_FLAGS_WRITE;
150         return -1;
151     }
152     int len_to_write = dlen > remaining?remaining:dlen;
153     memcpy(b->data + b->offset, data, len_to_write);
154     b->offset += len_to_write;
155     b->dlen = b->offset;
156     if (len_to_write == dlen) {
157         b->flags &= ~BIO_FLAGS_WRITE;
158     }
159     return len_to_write;
160 }
161 
162 /**
163  * @brief Read from BIO.
164  *
165  */
BIO_read(BIO * bio,void * data,int len)166 int BIO_read(BIO *bio, void *data, int len)
167 {
168     SSL_ASSERT1(bio);
169     BIO *peer = bio->peer;
170     int remaining = peer->dlen - peer->roffset;
171     if (remaining <= 0) {
172         bio->flags |= BIO_FLAGS_READ;
173         return -1;
174     }
175     int len_to_read = remaining > len ? len : remaining;
176     memcpy(data, peer->data + peer->roffset, len_to_read);
177     peer->roffset += len_to_read;
178     if (len_to_read == len) {
179         bio->flags &= ~BIO_FLAGS_READ;
180     }
181     if (peer->offset) {
182         // shift data back to the beginning of the buffer
183         memmove(peer->data, peer->data+peer->roffset, peer->offset - peer->roffset);
184         peer->offset -= peer->roffset;
185         peer->roffset = 0;
186         peer->dlen = peer->offset;
187     }
188     return len_to_read;
189 }
190 
BIO_wpending(const BIO * bio)191 size_t BIO_wpending(const BIO *bio)
192 {
193     return bio->dlen - bio->roffset;
194 }
195 
BIO_ctrl_pending(const BIO * bio)196 size_t BIO_ctrl_pending(const BIO *bio)
197 {
198     return bio->peer->dlen - bio->peer->roffset;
199 }
200 
BIO_ctrl_get_write_guarantee(BIO * b)201 size_t BIO_ctrl_get_write_guarantee(BIO *b)
202 {
203     return (long)b->size - b->dlen;
204 }
205 
BIO_test_flags(const BIO * b,int flags)206 int  BIO_test_flags(const BIO *b, int flags)
207 {
208     return (b->flags & flags);
209 }
210