1 /*
2 * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #include <stdio.h>
11 #include <errno.h>
12 #include "internal/cryptlib.h"
13 #include <openssl/buffer.h>
14 #include <openssl/evp.h>
15 #include "internal/bio.h"
16
17 static int b64_write(BIO *h, const char *buf, int num);
18 static int b64_read(BIO *h, char *buf, int size);
19 static int b64_puts(BIO *h, const char *str);
20 static long b64_ctrl(BIO *h, int cmd, long arg1, void *arg2);
21 static int b64_new(BIO *h);
22 static int b64_free(BIO *data);
23 static long b64_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
24 #define B64_BLOCK_SIZE 1024
25 #define B64_BLOCK_SIZE2 768
26 #define B64_NONE 0
27 #define B64_ENCODE 1
28 #define B64_DECODE 2
29
30 typedef struct b64_struct {
31 /*
32 * BIO *bio; moved to the BIO structure
33 */
34 int buf_len;
35 int buf_off;
36 int tmp_len; /* used to find the start when decoding */
37 int tmp_nl; /* If true, scan until '\n' */
38 int encode;
39 int start; /* have we started decoding yet? */
40 int cont; /* <= 0 when finished */
41 EVP_ENCODE_CTX *base64;
42 unsigned char buf[EVP_ENCODE_LENGTH(B64_BLOCK_SIZE) + 10];
43 unsigned char tmp[B64_BLOCK_SIZE];
44 } BIO_B64_CTX;
45
46 static const BIO_METHOD methods_b64 = {
47 BIO_TYPE_BASE64,
48 "base64 encoding",
49 bwrite_conv,
50 b64_write,
51 bread_conv,
52 b64_read,
53 b64_puts,
54 NULL, /* b64_gets, */
55 b64_ctrl,
56 b64_new,
57 b64_free,
58 b64_callback_ctrl,
59 };
60
BIO_f_base64(void)61 const BIO_METHOD *BIO_f_base64(void)
62 {
63 return &methods_b64;
64 }
65
b64_new(BIO * bi)66 static int b64_new(BIO *bi)
67 {
68 BIO_B64_CTX *ctx;
69
70 if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
71 ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
72 return 0;
73 }
74
75 ctx->cont = 1;
76 ctx->start = 1;
77 ctx->base64 = EVP_ENCODE_CTX_new();
78 if (ctx->base64 == NULL) {
79 OPENSSL_free(ctx);
80 return 0;
81 }
82
83 BIO_set_data(bi, ctx);
84 BIO_set_init(bi, 1);
85
86 return 1;
87 }
88
b64_free(BIO * a)89 static int b64_free(BIO *a)
90 {
91 BIO_B64_CTX *ctx;
92
93 if (a == NULL)
94 return 0;
95
96 ctx = BIO_get_data(a);
97 if (ctx == NULL)
98 return 0;
99
100 EVP_ENCODE_CTX_free(ctx->base64);
101 OPENSSL_free(ctx);
102 BIO_set_data(a, NULL);
103 BIO_set_init(a, 0);
104
105 return 1;
106 }
107
b64_read(BIO * b,char * out,int outl)108 static int b64_read(BIO *b, char *out, int outl)
109 {
110 int ret = 0, i, ii, j, k, x, n, num, ret_code = 0;
111 BIO_B64_CTX *ctx;
112 unsigned char *p, *q;
113 BIO *next;
114
115 if (out == NULL)
116 return 0;
117 ctx = (BIO_B64_CTX *)BIO_get_data(b);
118
119 next = BIO_next(b);
120 if (ctx == NULL || next == NULL)
121 return 0;
122
123 BIO_clear_retry_flags(b);
124
125 if (ctx->encode != B64_DECODE) {
126 ctx->encode = B64_DECODE;
127 ctx->buf_len = 0;
128 ctx->buf_off = 0;
129 ctx->tmp_len = 0;
130 EVP_DecodeInit(ctx->base64);
131 }
132
133 /* First check if there are bytes decoded/encoded */
134 if (ctx->buf_len > 0) {
135 OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
136 i = ctx->buf_len - ctx->buf_off;
137 if (i > outl)
138 i = outl;
139 OPENSSL_assert(ctx->buf_off + i < (int)sizeof(ctx->buf));
140 memcpy(out, &(ctx->buf[ctx->buf_off]), i);
141 ret = i;
142 out += i;
143 outl -= i;
144 ctx->buf_off += i;
145 if (ctx->buf_len == ctx->buf_off) {
146 ctx->buf_len = 0;
147 ctx->buf_off = 0;
148 }
149 }
150
151 /*
152 * At this point, we have room of outl bytes and an empty buffer, so we
153 * should read in some more.
154 */
155
156 ret_code = 0;
157 while (outl > 0) {
158 if (ctx->cont <= 0)
159 break;
160
161 i = BIO_read(next, &(ctx->tmp[ctx->tmp_len]),
162 B64_BLOCK_SIZE - ctx->tmp_len);
163
164 if (i <= 0) {
165 ret_code = i;
166
167 /* Should we continue next time we are called? */
168 if (!BIO_should_retry(next)) {
169 ctx->cont = i;
170 /* If buffer empty break */
171 if (ctx->tmp_len == 0)
172 break;
173 /* Fall through and process what we have */
174 else
175 i = 0;
176 }
177 /* else we retry and add more data to buffer */
178 else
179 break;
180 }
181 i += ctx->tmp_len;
182 ctx->tmp_len = i;
183
184 /*
185 * We need to scan, a line at a time until we have a valid line if we
186 * are starting.
187 */
188 if (ctx->start && (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) != 0) {
189 ctx->tmp_len = 0;
190 } else if (ctx->start) {
191 q = p = ctx->tmp;
192 num = 0;
193 for (j = 0; j < i; j++) {
194 if (*(q++) != '\n')
195 continue;
196
197 /*
198 * due to a previous very long line, we need to keep on
199 * scanning for a '\n' before we even start looking for
200 * base64 encoded stuff.
201 */
202 if (ctx->tmp_nl) {
203 p = q;
204 ctx->tmp_nl = 0;
205 continue;
206 }
207
208 k = EVP_DecodeUpdate(ctx->base64, ctx->buf, &num, p, q - p);
209 if (k <= 0 && num == 0 && ctx->start) {
210 EVP_DecodeInit(ctx->base64);
211 } else {
212 if (p != ctx->tmp) {
213 i -= p - ctx->tmp;
214 for (x = 0; x < i; x++)
215 ctx->tmp[x] = p[x];
216 }
217 EVP_DecodeInit(ctx->base64);
218 ctx->start = 0;
219 break;
220 }
221 p = q;
222 }
223
224 /* we fell off the end without starting */
225 if (j == i && num == 0) {
226 /*
227 * Is this is one long chunk?, if so, keep on reading until a
228 * new line.
229 */
230 if (p == ctx->tmp) {
231 /* Check buffer full */
232 if (i == B64_BLOCK_SIZE) {
233 ctx->tmp_nl = 1;
234 ctx->tmp_len = 0;
235 }
236 } else if (p != q) { /* finished on a '\n' */
237 n = q - p;
238 for (ii = 0; ii < n; ii++)
239 ctx->tmp[ii] = p[ii];
240 ctx->tmp_len = n;
241 }
242 /* else finished on a '\n' */
243 continue;
244 } else {
245 ctx->tmp_len = 0;
246 }
247 } else if (i < B64_BLOCK_SIZE && ctx->cont > 0) {
248 /*
249 * If buffer isn't full and we can retry then restart to read in
250 * more data.
251 */
252 continue;
253 }
254
255 if ((BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) != 0) {
256 int z, jj;
257
258 jj = i & ~3; /* process per 4 */
259 z = EVP_DecodeBlock(ctx->buf, ctx->tmp, jj);
260 if (jj > 2) {
261 if (ctx->tmp[jj - 1] == '=') {
262 z--;
263 if (ctx->tmp[jj - 2] == '=')
264 z--;
265 }
266 }
267 /*
268 * z is now number of output bytes and jj is the number consumed
269 */
270 if (jj != i) {
271 memmove(ctx->tmp, &ctx->tmp[jj], i - jj);
272 ctx->tmp_len = i - jj;
273 }
274 ctx->buf_len = 0;
275 if (z > 0) {
276 ctx->buf_len = z;
277 }
278 i = z;
279 } else {
280 i = EVP_DecodeUpdate(ctx->base64, ctx->buf, &ctx->buf_len,
281 ctx->tmp, i);
282 ctx->tmp_len = 0;
283 }
284 /*
285 * If eof or an error was signalled, then the condition
286 * 'ctx->cont <= 0' will prevent b64_read() from reading
287 * more data on subsequent calls. This assignment was
288 * deleted accidentally in commit 5562cfaca4f3.
289 */
290 ctx->cont = i;
291
292 ctx->buf_off = 0;
293 if (i < 0) {
294 ret_code = 0;
295 ctx->buf_len = 0;
296 break;
297 }
298
299 if (ctx->buf_len <= outl)
300 i = ctx->buf_len;
301 else
302 i = outl;
303
304 memcpy(out, ctx->buf, i);
305 ret += i;
306 ctx->buf_off = i;
307 if (ctx->buf_off == ctx->buf_len) {
308 ctx->buf_len = 0;
309 ctx->buf_off = 0;
310 }
311 outl -= i;
312 out += i;
313 }
314 /* BIO_clear_retry_flags(b); */
315 BIO_copy_next_retry(b);
316 return ret == 0 ? ret_code : ret;
317 }
318
b64_write(BIO * b,const char * in,int inl)319 static int b64_write(BIO *b, const char *in, int inl)
320 {
321 int ret = 0;
322 int n;
323 int i;
324 BIO_B64_CTX *ctx;
325 BIO *next;
326
327 ctx = (BIO_B64_CTX *)BIO_get_data(b);
328 next = BIO_next(b);
329 if (ctx == NULL || next == NULL)
330 return 0;
331
332 BIO_clear_retry_flags(b);
333
334 if (ctx->encode != B64_ENCODE) {
335 ctx->encode = B64_ENCODE;
336 ctx->buf_len = 0;
337 ctx->buf_off = 0;
338 ctx->tmp_len = 0;
339 EVP_EncodeInit(ctx->base64);
340 }
341
342 OPENSSL_assert(ctx->buf_off < (int)sizeof(ctx->buf));
343 OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
344 OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
345 n = ctx->buf_len - ctx->buf_off;
346 while (n > 0) {
347 i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n);
348 if (i <= 0) {
349 BIO_copy_next_retry(b);
350 return i;
351 }
352 OPENSSL_assert(i <= n);
353 ctx->buf_off += i;
354 OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf));
355 OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
356 n -= i;
357 }
358 /* at this point all pending data has been written */
359 ctx->buf_off = 0;
360 ctx->buf_len = 0;
361
362 if (in == NULL || inl <= 0)
363 return 0;
364
365 while (inl > 0) {
366 n = inl > B64_BLOCK_SIZE ? B64_BLOCK_SIZE : inl;
367
368 if ((BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) != 0) {
369 if (ctx->tmp_len > 0) {
370 OPENSSL_assert(ctx->tmp_len <= 3);
371 n = 3 - ctx->tmp_len;
372 /*
373 * There's a theoretical possibility for this
374 */
375 if (n > inl)
376 n = inl;
377 memcpy(&(ctx->tmp[ctx->tmp_len]), in, n);
378 ctx->tmp_len += n;
379 ret += n;
380 if (ctx->tmp_len < 3)
381 break;
382 ctx->buf_len =
383 EVP_EncodeBlock(ctx->buf, ctx->tmp, ctx->tmp_len);
384 OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
385 OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
386 /*
387 * Since we're now done using the temporary buffer, the
388 * length should be 0'd
389 */
390 ctx->tmp_len = 0;
391 } else {
392 if (n < 3) {
393 memcpy(ctx->tmp, in, n);
394 ctx->tmp_len = n;
395 ret += n;
396 break;
397 }
398 n -= n % 3;
399 ctx->buf_len =
400 EVP_EncodeBlock(ctx->buf, (unsigned char *)in, n);
401 OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
402 OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
403 ret += n;
404 }
405 } else {
406 if (!EVP_EncodeUpdate(ctx->base64, ctx->buf, &ctx->buf_len,
407 (unsigned char *)in, n))
408 return ret == 0 ? -1 : ret;
409 OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
410 OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
411 ret += n;
412 }
413 inl -= n;
414 in += n;
415
416 ctx->buf_off = 0;
417 n = ctx->buf_len;
418 while (n > 0) {
419 i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n);
420 if (i <= 0) {
421 BIO_copy_next_retry(b);
422 return ret == 0 ? i : ret;
423 }
424 OPENSSL_assert(i <= n);
425 n -= i;
426 ctx->buf_off += i;
427 OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf));
428 OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
429 }
430 ctx->buf_len = 0;
431 ctx->buf_off = 0;
432 }
433 return ret;
434 }
435
b64_ctrl(BIO * b,int cmd,long num,void * ptr)436 static long b64_ctrl(BIO *b, int cmd, long num, void *ptr)
437 {
438 BIO_B64_CTX *ctx;
439 long ret = 1;
440 int i;
441 BIO *next;
442
443 ctx = (BIO_B64_CTX *)BIO_get_data(b);
444 next = BIO_next(b);
445 if (ctx == NULL || next == NULL)
446 return 0;
447
448 switch (cmd) {
449 case BIO_CTRL_RESET:
450 ctx->cont = 1;
451 ctx->start = 1;
452 ctx->encode = B64_NONE;
453 ret = BIO_ctrl(next, cmd, num, ptr);
454 break;
455 case BIO_CTRL_EOF: /* More to read */
456 if (ctx->cont <= 0)
457 ret = 1;
458 else
459 ret = BIO_ctrl(next, cmd, num, ptr);
460 break;
461 case BIO_CTRL_WPENDING: /* More to write in buffer */
462 OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
463 ret = ctx->buf_len - ctx->buf_off;
464 if (ret == 0 && ctx->encode != B64_NONE
465 && EVP_ENCODE_CTX_num(ctx->base64) != 0)
466 ret = 1;
467 else if (ret <= 0)
468 ret = BIO_ctrl(next, cmd, num, ptr);
469 break;
470 case BIO_CTRL_PENDING: /* More to read in buffer */
471 OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
472 ret = ctx->buf_len - ctx->buf_off;
473 if (ret <= 0)
474 ret = BIO_ctrl(next, cmd, num, ptr);
475 break;
476 case BIO_CTRL_FLUSH:
477 /* do a final write */
478 again:
479 while (ctx->buf_len != ctx->buf_off) {
480 i = b64_write(b, NULL, 0);
481 if (i < 0)
482 return i;
483 }
484 if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) {
485 if (ctx->tmp_len != 0) {
486 ctx->buf_len = EVP_EncodeBlock(ctx->buf,
487 ctx->tmp, ctx->tmp_len);
488 ctx->buf_off = 0;
489 ctx->tmp_len = 0;
490 goto again;
491 }
492 } else if (ctx->encode != B64_NONE
493 && EVP_ENCODE_CTX_num(ctx->base64) != 0) {
494 ctx->buf_off = 0;
495 EVP_EncodeFinal(ctx->base64, ctx->buf, &(ctx->buf_len));
496 /* push out the bytes */
497 goto again;
498 }
499 /* Finally flush the underlying BIO */
500 ret = BIO_ctrl(next, cmd, num, ptr);
501 break;
502
503 case BIO_C_DO_STATE_MACHINE:
504 BIO_clear_retry_flags(b);
505 ret = BIO_ctrl(next, cmd, num, ptr);
506 BIO_copy_next_retry(b);
507 break;
508
509 case BIO_CTRL_DUP:
510 break;
511 case BIO_CTRL_INFO:
512 case BIO_CTRL_GET:
513 case BIO_CTRL_SET:
514 default:
515 ret = BIO_ctrl(next, cmd, num, ptr);
516 break;
517 }
518 return ret;
519 }
520
b64_callback_ctrl(BIO * b,int cmd,BIO_info_cb * fp)521 static long b64_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
522 {
523 BIO *next = BIO_next(b);
524
525 if (next == NULL)
526 return 0;
527
528 return BIO_callback_ctrl(next, cmd, fp);
529 }
530
b64_puts(BIO * b,const char * str)531 static int b64_puts(BIO *b, const char *str)
532 {
533 return b64_write(b, str, strlen(str));
534 }
535