4a0fcdaa8f69c49d69d95e5d5f884278d7a272dc
[openssl.git] / crypto / bio / bss_mem.c
1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2  * All rights reserved.
3  *
4  * This package is an SSL implementation written
5  * by Eric Young (eay@cryptsoft.com).
6  * The implementation was written so as to conform with Netscapes SSL.
7  *
8  * This library is free for commercial and non-commercial use as long as
9  * the following conditions are aheared to.  The following conditions
10  * apply to all code found in this distribution, be it the RC4, RSA,
11  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12  * included with this distribution is covered by the same copyright terms
13  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14  *
15  * Copyright remains Eric Young's, and as such any Copyright notices in
16  * the code are not to be removed.
17  * If this package is used in a product, Eric Young should be given attribution
18  * as the author of the parts of the library used.
19  * This can be in the form of a textual message at program startup or
20  * in documentation (online or textual) provided with the package.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the copyright
26  *    notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *    notice, this list of conditions and the following disclaimer in the
29  *    documentation and/or other materials provided with the distribution.
30  * 3. All advertising materials mentioning features or use of this software
31  *    must display the following acknowledgement:
32  *    "This product includes cryptographic software written by
33  *     Eric Young (eay@cryptsoft.com)"
34  *    The word 'cryptographic' can be left out if the rouines from the library
35  *    being used are not cryptographic related :-).
36  * 4. If you include any Windows specific code (or a derivative thereof) from
37  *    the apps directory (application code) you must include an acknowledgement:
38  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  *
52  * The licence and distribution terms for any publically available version or
53  * derivative of this code cannot be changed.  i.e. this code cannot simply be
54  * copied and put under another distribution licence
55  * [including the GNU Public Licence.]
56  */
57
58 #include <stdio.h>
59 #include <errno.h>
60 #include "internal/cryptlib.h"
61 #include <openssl/bio.h>
62
63 static int mem_write(BIO *h, const char *buf, int num);
64 static int mem_read(BIO *h, char *buf, int size);
65 static int mem_puts(BIO *h, const char *str);
66 static int mem_gets(BIO *h, char *str, int size);
67 static long mem_ctrl(BIO *h, int cmd, long arg1, void *arg2);
68 static int mem_new(BIO *h);
69 static int secmem_new(BIO *h);
70 static int mem_free(BIO *data);
71 static BIO_METHOD mem_method = {
72     BIO_TYPE_MEM,
73     "memory buffer",
74     mem_write,
75     mem_read,
76     mem_puts,
77     mem_gets,
78     mem_ctrl,
79     mem_new,
80     mem_free,
81     NULL,
82 };
83 static BIO_METHOD secmem_method = {
84     BIO_TYPE_MEM,
85     "secure memory buffer",
86     mem_write,
87     mem_read,
88     mem_puts,
89     mem_gets,
90     mem_ctrl,
91     secmem_new,
92     mem_free,
93     NULL,
94 };
95
96 /*
97  * bio->num is used to hold the value to return on 'empty', if it is 0,
98  * should_retry is not set
99  */
100
101 BIO_METHOD *BIO_s_mem(void)
102 {
103     return (&mem_method);
104 }
105
106 BIO_METHOD *BIO_s_secmem(void)
107 {
108     return(&secmem_method);
109 }
110
111 BIO *BIO_new_mem_buf(void *buf, int len)
112 {
113     BIO *ret;
114     BUF_MEM *b;
115     size_t sz;
116
117     if (buf == NULL) {
118         BIOerr(BIO_F_BIO_NEW_MEM_BUF, BIO_R_NULL_PARAMETER);
119         return NULL;
120     }
121     sz = (len < 0) ? strlen(buf) : (size_t)len;
122     if ((ret = BIO_new(BIO_s_mem())) == NULL)
123         return NULL;
124     b = (BUF_MEM *)ret->ptr;
125     b->data = buf;
126     b->length = sz;
127     b->max = sz;
128     ret->flags |= BIO_FLAGS_MEM_RDONLY;
129     /* Since this is static data retrying wont help */
130     ret->num = 0;
131     return ret;
132 }
133
134 static int mem_init(BIO *bi, unsigned long flags)
135 {
136     BUF_MEM *b;
137
138     if ((b = BUF_MEM_new_ex(flags)) == NULL)
139         return(0);
140     bi->shutdown = 1;
141     bi->init = 1;
142     bi->num = -1;
143     bi->ptr = (char *)b;
144     return(1);
145 }
146
147 static int mem_new(BIO *bi)
148 {
149     return (mem_init(bi, 0L));
150 }
151
152 static int secmem_new(BIO *bi)
153 {
154     return (mem_init(bi, BUF_MEM_FLAG_SECURE));
155 }
156
157 static int mem_free(BIO *a)
158 {
159     if (a == NULL)
160         return (0);
161     if (a->shutdown) {
162         if ((a->init) && (a->ptr != NULL)) {
163             BUF_MEM *b;
164             b = (BUF_MEM *)a->ptr;
165             if (a->flags & BIO_FLAGS_MEM_RDONLY)
166                 b->data = NULL;
167             BUF_MEM_free(b);
168             a->ptr = NULL;
169         }
170     }
171     return (1);
172 }
173
174 static int mem_read(BIO *b, char *out, int outl)
175 {
176     int ret = -1;
177     BUF_MEM *bm;
178
179     bm = (BUF_MEM *)b->ptr;
180     BIO_clear_retry_flags(b);
181     ret = (outl >= 0 && (size_t)outl > bm->length) ? (int)bm->length : outl;
182     if ((out != NULL) && (ret > 0)) {
183         memcpy(out, bm->data, ret);
184         bm->length -= ret;
185         if (b->flags & BIO_FLAGS_MEM_RDONLY)
186             bm->data += ret;
187         else {
188             memmove(&(bm->data[0]), &(bm->data[ret]), bm->length);
189         }
190     } else if (bm->length == 0) {
191         ret = b->num;
192         if (ret != 0)
193             BIO_set_retry_read(b);
194     }
195     return (ret);
196 }
197
198 static int mem_write(BIO *b, const char *in, int inl)
199 {
200     int ret = -1;
201     int blen;
202     BUF_MEM *bm;
203
204     bm = (BUF_MEM *)b->ptr;
205     if (in == NULL) {
206         BIOerr(BIO_F_MEM_WRITE, BIO_R_NULL_PARAMETER);
207         goto end;
208     }
209
210     if (b->flags & BIO_FLAGS_MEM_RDONLY) {
211         BIOerr(BIO_F_MEM_WRITE, BIO_R_WRITE_TO_READ_ONLY_BIO);
212         goto end;
213     }
214
215     BIO_clear_retry_flags(b);
216     blen = bm->length;
217     if (BUF_MEM_grow_clean(bm, blen + inl) == 0)
218         goto end;
219     memcpy(&(bm->data[blen]), in, inl);
220     ret = inl;
221  end:
222     return (ret);
223 }
224
225 static long mem_ctrl(BIO *b, int cmd, long num, void *ptr)
226 {
227     long ret = 1;
228     char **pptr;
229
230     BUF_MEM *bm = (BUF_MEM *)b->ptr;
231
232     switch (cmd) {
233     case BIO_CTRL_RESET:
234         if (bm->data != NULL) {
235             /* For read only case reset to the start again */
236             if (b->flags & BIO_FLAGS_MEM_RDONLY) {
237                 bm->data -= bm->max - bm->length;
238                 bm->length = bm->max;
239             } else {
240                 memset(bm->data, 0, bm->max);
241                 bm->length = 0;
242             }
243         }
244         break;
245     case BIO_CTRL_EOF:
246         ret = (long)(bm->length == 0);
247         break;
248     case BIO_C_SET_BUF_MEM_EOF_RETURN:
249         b->num = (int)num;
250         break;
251     case BIO_CTRL_INFO:
252         ret = (long)bm->length;
253         if (ptr != NULL) {
254             pptr = (char **)ptr;
255             *pptr = (char *)&(bm->data[0]);
256         }
257         break;
258     case BIO_C_SET_BUF_MEM:
259         mem_free(b);
260         b->shutdown = (int)num;
261         b->ptr = ptr;
262         break;
263     case BIO_C_GET_BUF_MEM_PTR:
264         if (ptr != NULL) {
265             pptr = (char **)ptr;
266             *pptr = (char *)bm;
267         }
268         break;
269     case BIO_CTRL_GET_CLOSE:
270         ret = (long)b->shutdown;
271         break;
272     case BIO_CTRL_SET_CLOSE:
273         b->shutdown = (int)num;
274         break;
275
276     case BIO_CTRL_WPENDING:
277         ret = 0L;
278         break;
279     case BIO_CTRL_PENDING:
280         ret = (long)bm->length;
281         break;
282     case BIO_CTRL_DUP:
283     case BIO_CTRL_FLUSH:
284         ret = 1;
285         break;
286     case BIO_CTRL_PUSH:
287     case BIO_CTRL_POP:
288     default:
289         ret = 0;
290         break;
291     }
292     return (ret);
293 }
294
295 static int mem_gets(BIO *bp, char *buf, int size)
296 {
297     int i, j;
298     int ret = -1;
299     char *p;
300     BUF_MEM *bm = (BUF_MEM *)bp->ptr;
301
302     BIO_clear_retry_flags(bp);
303     j = bm->length;
304     if ((size - 1) < j)
305         j = size - 1;
306     if (j <= 0) {
307         *buf = '\0';
308         return 0;
309     }
310     p = bm->data;
311     for (i = 0; i < j; i++) {
312         if (p[i] == '\n') {
313             i++;
314             break;
315         }
316     }
317
318     /*
319      * i is now the max num of bytes to copy, either j or up to
320      * and including the first newline
321      */
322
323     i = mem_read(bp, buf, i);
324     if (i > 0)
325         buf[i] = '\0';
326     ret = i;
327     return (ret);
328 }
329
330 static int mem_puts(BIO *bp, const char *str)
331 {
332     int n, ret;
333
334     n = strlen(str);
335     ret = mem_write(bp, str, n);
336     /* memory semantics is that it will always work */
337     return (ret);
338 }