summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/evp/bio_b64.c
diff options
context:
space:
mode:
authorryker <>1998-10-05 20:13:14 +0000
committerryker <>1998-10-05 20:13:14 +0000
commitaeeae06a79815dc190061534d47236cec09f9e32 (patch)
tree851692b9c2f9c04f077666855641900f19fdb217 /src/lib/libcrypto/evp/bio_b64.c
parenta4f79641824cbf9f60ca9d1168d1fcc46717a82a (diff)
downloadopenbsd-aeeae06a79815dc190061534d47236cec09f9e32.tar.gz
openbsd-aeeae06a79815dc190061534d47236cec09f9e32.tar.bz2
openbsd-aeeae06a79815dc190061534d47236cec09f9e32.zip
Import of SSLeay-0.9.0b with RSA and IDEA stubbed + OpenBSD build
functionality for shared libs. Note that routines such as sslv2_init and friends that use RSA will not work due to lack of RSA in this library. Needs documentation and help from ports for easy upgrade to full functionality where legally possible.
Diffstat (limited to 'src/lib/libcrypto/evp/bio_b64.c')
-rw-r--r--src/lib/libcrypto/evp/bio_b64.c547
1 files changed, 547 insertions, 0 deletions
diff --git a/src/lib/libcrypto/evp/bio_b64.c b/src/lib/libcrypto/evp/bio_b64.c
new file mode 100644
index 0000000000..73172b9a07
--- /dev/null
+++ b/src/lib/libcrypto/evp/bio_b64.c
@@ -0,0 +1,547 @@
1/* crypto/evp/bio_b64.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 "cryptlib.h"
62#include "buffer.h"
63#include "evp.h"
64
65#ifndef NOPROTO
66static int b64_write(BIO *h,char *buf,int num);
67static int b64_read(BIO *h,char *buf,int size);
68/*static int b64_puts(BIO *h,char *str); */
69/*static int b64_gets(BIO *h,char *str,int size); */
70static long b64_ctrl(BIO *h,int cmd,long arg1,char *arg2);
71static int b64_new(BIO *h);
72static int b64_free(BIO *data);
73#else
74static int b64_write();
75static int b64_read();
76/*static int b64_puts(); */
77/*static int b64_gets(); */
78static long b64_ctrl();
79static int b64_new();
80static int b64_free();
81#endif
82
83#define B64_BLOCK_SIZE 1024
84#define B64_BLOCK_SIZE2 768
85#define B64_NONE 0
86#define B64_ENCODE 1
87#define B64_DECODE 2
88
89typedef struct b64_struct
90 {
91 /*BIO *bio; moved to the BIO structure */
92 int buf_len;
93 int buf_off;
94 int tmp_len; /* used to find the start when decoding */
95 int tmp_nl; /* If true, scan until '\n' */
96 int encode;
97 int start; /* have we started decoding yet? */
98 int cont; /* <= 0 when finished */
99 EVP_ENCODE_CTX base64;
100 char buf[EVP_ENCODE_LENGTH(B64_BLOCK_SIZE)+10];
101 char tmp[B64_BLOCK_SIZE];
102 } BIO_B64_CTX;
103
104static BIO_METHOD methods_b64=
105 {
106 BIO_TYPE_BASE64,"base64 encoding",
107 b64_write,
108 b64_read,
109 NULL, /* b64_puts, */
110 NULL, /* b64_gets, */
111 b64_ctrl,
112 b64_new,
113 b64_free,
114 };
115
116BIO_METHOD *BIO_f_base64()
117 {
118 return(&methods_b64);
119 }
120
121static int b64_new(bi)
122BIO *bi;
123 {
124 BIO_B64_CTX *ctx;
125
126 ctx=(BIO_B64_CTX *)Malloc(sizeof(BIO_B64_CTX));
127 if (ctx == NULL) return(0);
128
129 ctx->buf_len=0;
130 ctx->tmp_len=0;
131 ctx->tmp_nl=0;
132 ctx->buf_off=0;
133 ctx->cont=1;
134 ctx->start=1;
135 ctx->encode=0;
136
137 bi->init=1;
138 bi->ptr=(char *)ctx;
139 bi->flags=0;
140 return(1);
141 }
142
143static int b64_free(a)
144BIO *a;
145 {
146 if (a == NULL) return(0);
147 Free(a->ptr);
148 a->ptr=NULL;
149 a->init=0;
150 a->flags=0;
151 return(1);
152 }
153
154static int b64_read(b,out,outl)
155BIO *b;
156char *out;
157int outl;
158 {
159 int ret=0,i,ii,j,k,x,n,num,ret_code=0;
160 BIO_B64_CTX *ctx;
161 unsigned char *p,*q;
162
163 if (out == NULL) return(0);
164 ctx=(BIO_B64_CTX *)b->ptr;
165
166 if ((ctx == NULL) || (b->next_bio == NULL)) return(0);
167
168 if (ctx->encode != B64_DECODE)
169 {
170 ctx->encode=B64_DECODE;
171 ctx->buf_len=0;
172 ctx->buf_off=0;
173 ctx->tmp_len=0;
174 EVP_DecodeInit(&(ctx->base64));
175 }
176
177 /* First check if there are bytes decoded/encoded */
178 if (ctx->buf_len > 0)
179 {
180 i=ctx->buf_len-ctx->buf_off;
181 if (i > outl) i=outl;
182 memcpy(out,&(ctx->buf[ctx->buf_off]),i);
183 ret=i;
184 out+=i;
185 outl-=i;
186 ctx->buf_off+=i;
187 if (ctx->buf_len == ctx->buf_off)
188 {
189 ctx->buf_len=0;
190 ctx->buf_off=0;
191 }
192 }
193
194 /* At this point, we have room of outl bytes and an empty
195 * buffer, so we should read in some more. */
196
197 ret_code=0;
198 while (outl > 0)
199 {
200 if (ctx->cont <= 0) break;
201
202 i=BIO_read(b->next_bio,&(ctx->tmp[ctx->tmp_len]),
203 B64_BLOCK_SIZE-ctx->tmp_len);
204
205 if (i <= 0)
206 {
207 ret_code=i;
208
209 /* Should be continue next time we are called? */
210 if (!BIO_should_retry(b->next_bio))
211 ctx->cont=i;
212 /* else we should continue when called again */
213 break;
214 }
215 i+=ctx->tmp_len;
216
217 /* We need to scan, a line at a time until we
218 * have a valid line if we are starting. */
219 if (ctx->start && (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL))
220 {
221 /* ctx->start=1; */
222 ctx->tmp_len=0;
223 }
224 else if (ctx->start)
225 {
226 q=p=(unsigned char *)ctx->tmp;
227 for (j=0; j<i; j++)
228 {
229 if (*(q++) != '\n') continue;
230
231 /* due to a previous very long line,
232 * we need to keep on scanning for a '\n'
233 * before we even start looking for
234 * base64 encoded stuff. */
235 if (ctx->tmp_nl)
236 {
237 p=q;
238 ctx->tmp_nl=0;
239 continue;
240 }
241
242 k=EVP_DecodeUpdate(&(ctx->base64),
243 (unsigned char *)ctx->buf,
244 &num,p,q-p);
245 if ((k <= 0) && (num == 0) && (ctx->start))
246 EVP_DecodeInit(&ctx->base64);
247 else
248 {
249 if (p != (unsigned char *)
250 &(ctx->tmp[0]))
251 {
252 i-=(p- (unsigned char *)
253 &(ctx->tmp[0]));
254 for (x=0; x < i; x++)
255 ctx->tmp[x]=p[x];
256 EVP_DecodeInit(&ctx->base64);
257 }
258 ctx->start=0;
259 break;
260 }
261 p=q;
262 }
263
264 /* we fell off the end without starting */
265 if (j == i)
266 {
267 /* Is this is one long chunk?, if so, keep on
268 * reading until a new line. */
269 if (p == (unsigned char *)&(ctx->tmp[0]))
270 {
271 ctx->tmp_nl=1;
272 ctx->tmp_len=0;
273 }
274 else if (p != q) /* finished on a '\n' */
275 {
276 n=q-p;
277 for (ii=0; ii<n; ii++)
278 ctx->tmp[ii]=p[ii];
279 ctx->tmp_len=n;
280 }
281 /* else finished on a '\n' */
282 continue;
283 }
284 else
285 ctx->tmp_len=0;
286 }
287
288 if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)
289 {
290 int z,jj;
291
292 jj=(i>>2)<<2;
293 z=EVP_DecodeBlock((unsigned char *)ctx->buf,
294 (unsigned char *)ctx->tmp,jj);
295 if (jj > 2)
296 {
297 if (ctx->tmp[jj-1] == '=')
298 {
299 z--;
300 if (ctx->tmp[jj-2] == '=')
301 z--;
302 }
303 }
304 /* z is now number of output bytes and jj is the
305 * number consumed */
306 if (jj != i)
307 {
308 memcpy((unsigned char *)ctx->tmp,
309 (unsigned char *)&(ctx->tmp[jj]),i-jj);
310 ctx->tmp_len=i-jj;
311 }
312 ctx->buf_len=0;
313 if (z > 0)
314 {
315 ctx->buf_len=z;
316 i=1;
317 }
318 else
319 i=z;
320 }
321 else
322 {
323 i=EVP_DecodeUpdate(&(ctx->base64),
324 (unsigned char *)ctx->buf,&ctx->buf_len,
325 (unsigned char *)ctx->tmp,i);
326 }
327 ctx->cont=i;
328 ctx->buf_off=0;
329 if (i < 0)
330 {
331 ret_code=0;
332 ctx->buf_len=0;
333 break;
334 }
335
336 if (ctx->buf_len <= outl)
337 i=ctx->buf_len;
338 else
339 i=outl;
340
341 memcpy(out,ctx->buf,i);
342 ret+=i;
343 ctx->buf_off=i;
344 if (ctx->buf_off == ctx->buf_len)
345 {
346 ctx->buf_len=0;
347 ctx->buf_off=0;
348 }
349 outl-=i;
350 out+=i;
351 }
352 BIO_clear_retry_flags(b);
353 BIO_copy_next_retry(b);
354 return((ret == 0)?ret_code:ret);
355 }
356
357static int b64_write(b,in,inl)
358BIO *b;
359char *in;
360int inl;
361 {
362 int ret=inl,n,i;
363 BIO_B64_CTX *ctx;
364
365 ctx=(BIO_B64_CTX *)b->ptr;
366 BIO_clear_retry_flags(b);
367
368 if (ctx->encode != B64_ENCODE)
369 {
370 ctx->encode=B64_ENCODE;
371 ctx->buf_len=0;
372 ctx->buf_off=0;
373 ctx->tmp_len=0;
374 EVP_EncodeInit(&(ctx->base64));
375 }
376
377 n=ctx->buf_len-ctx->buf_off;
378 while (n > 0)
379 {
380 i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n);
381 if (i <= 0)
382 {
383 BIO_copy_next_retry(b);
384 return(i);
385 }
386 ctx->buf_off+=i;
387 n-=i;
388 }
389 /* at this point all pending data has been written */
390
391 if ((in == NULL) || (inl <= 0)) return(0);
392
393 ctx->buf_off=0;
394 while (inl > 0)
395 {
396 n=(inl > B64_BLOCK_SIZE)?B64_BLOCK_SIZE:inl;
397
398 if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)
399 {
400 if (ctx->tmp_len > 0)
401 {
402 n=3-ctx->tmp_len;
403 memcpy(&(ctx->tmp[ctx->tmp_len]),in,n);
404 ctx->tmp_len+=n;
405 n=ctx->tmp_len;
406 if (n < 3)
407 break;
408 ctx->buf_len=EVP_EncodeBlock(
409 (unsigned char *)ctx->buf,
410 (unsigned char *)ctx->tmp,n);
411 }
412 else
413 {
414 if (n < 3)
415 {
416 memcpy(&(ctx->tmp[0]),in,n);
417 ctx->tmp_len=n;
418 break;
419 }
420 n-=n%3;
421 ctx->buf_len=EVP_EncodeBlock(
422 (unsigned char *)ctx->buf,
423 (unsigned char *)in,n);
424 }
425 }
426 else
427 {
428 EVP_EncodeUpdate(&(ctx->base64),
429 (unsigned char *)ctx->buf,&ctx->buf_len,
430 (unsigned char *)in,n);
431 }
432 inl-=n;
433 in+=n;
434
435 ctx->buf_off=0;
436 n=ctx->buf_len;
437 while (n > 0)
438 {
439 i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n);
440 if (i <= 0)
441 {
442 BIO_copy_next_retry(b);
443 return((ret == 0)?i:ret);
444 }
445 n-=i;
446 ctx->buf_off+=i;
447 }
448 ctx->buf_len=0;
449 ctx->buf_off=0;
450 }
451 return(ret);
452 }
453
454static long b64_ctrl(b,cmd,num,ptr)
455BIO *b;
456int cmd;
457long num;
458char *ptr;
459 {
460 BIO_B64_CTX *ctx;
461 long ret=1;
462 int i;
463
464 ctx=(BIO_B64_CTX *)b->ptr;
465
466 switch (cmd)
467 {
468 case BIO_CTRL_RESET:
469 ctx->cont=1;
470 ctx->start=1;
471 ctx->encode=B64_NONE;
472 ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
473 break;
474 case BIO_CTRL_EOF: /* More to read */
475 if (ctx->cont <= 0)
476 ret=1;
477 else
478 ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
479 break;
480 case BIO_CTRL_WPENDING: /* More to write in buffer */
481 ret=ctx->buf_len-ctx->buf_off;
482 if ((ret == 0) && (ctx->base64.num != 0))
483 ret=1;
484 else if (ret <= 0)
485 ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
486 break;
487 case BIO_CTRL_PENDING: /* More to read in buffer */
488 ret=ctx->buf_len-ctx->buf_off;
489 if (ret <= 0)
490 ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
491 break;
492 case BIO_CTRL_FLUSH:
493 /* do a final write */
494again:
495 while (ctx->buf_len != ctx->buf_off)
496 {
497 i=b64_write(b,NULL,0);
498 if (i < 0)
499 {
500 ret=i;
501 break;
502 }
503 }
504 if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)
505 {
506 if (ctx->tmp_len != 0)
507 {
508 ctx->buf_len=EVP_EncodeBlock(
509 (unsigned char *)ctx->buf,
510 (unsigned char *)ctx->tmp,
511 ctx->tmp_len);
512 ctx->buf_off=0;
513 ctx->tmp_len=0;
514 goto again;
515 }
516 }
517 else if (ctx->base64.num != 0)
518 {
519 ctx->buf_off=0;
520 EVP_EncodeFinal(&(ctx->base64),
521 (unsigned char *)ctx->buf,
522 &(ctx->buf_len));
523 /* push out the bytes */
524 goto again;
525 }
526 /* Finally flush the underlying BIO */
527 ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
528 break;
529
530 case BIO_C_DO_STATE_MACHINE:
531 BIO_clear_retry_flags(b);
532 ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
533 BIO_copy_next_retry(b);
534 break;
535
536 case BIO_CTRL_DUP:
537 break;
538 case BIO_CTRL_INFO:
539 case BIO_CTRL_GET:
540 case BIO_CTRL_SET:
541 default:
542 ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
543 break;
544 }
545 return(ret);
546 }
547