1 /* $OpenBSD: bio_b64.c,v 1.19 2014/07/11 12:04:46 miod Exp $ */ 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 <errno.h> 60 #include <stdio.h> 61 #include <string.h> 62 63 #include <openssl/buffer.h> 64 #include <openssl/evp.h> 65 66 static int b64_write(BIO *h, const char *buf, int num); 67 static int b64_read(BIO *h, char *buf, int size); 68 static int b64_puts(BIO *h, const char *str); 69 /*static int b64_gets(BIO *h, char *str, int size); */ 70 static long b64_ctrl(BIO *h, int cmd, long arg1, void *arg2); 71 static int b64_new(BIO *h); 72 static int b64_free(BIO *data); 73 static long b64_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); 74 #define B64_BLOCK_SIZE 1024 75 #define B64_BLOCK_SIZE2 768 76 #define B64_NONE 0 77 #define B64_ENCODE 1 78 #define B64_DECODE 2 79 80 typedef struct b64_struct { 81 /*BIO *bio; moved to the BIO structure */ 82 int buf_len; 83 int buf_off; 84 int tmp_len; /* used to find the start when decoding */ 85 int tmp_nl; /* If true, scan until '\n' */ 86 int encode; 87 int start; /* have we started decoding yet? */ 88 int cont; /* <= 0 when finished */ 89 EVP_ENCODE_CTX base64; 90 char buf[EVP_ENCODE_LENGTH(B64_BLOCK_SIZE) + 10]; 91 char tmp[B64_BLOCK_SIZE]; 92 } BIO_B64_CTX; 93 94 static BIO_METHOD methods_b64 = { 95 .type = BIO_TYPE_BASE64, 96 .name = "base64 encoding", 97 .bwrite = b64_write, 98 .bread = b64_read, 99 .bputs = b64_puts, 100 .ctrl = b64_ctrl, 101 .create = b64_new, 102 .destroy = b64_free, 103 .callback_ctrl = b64_callback_ctrl 104 }; 105 106 BIO_METHOD * 107 BIO_f_base64(void) 108 { 109 return (&methods_b64); 110 } 111 112 static int 113 b64_new(BIO *bi) 114 { 115 BIO_B64_CTX *ctx; 116 117 ctx = malloc(sizeof(BIO_B64_CTX)); 118 if (ctx == NULL) 119 return (0); 120 121 ctx->buf_len = 0; 122 ctx->tmp_len = 0; 123 ctx->tmp_nl = 0; 124 ctx->buf_off = 0; 125 ctx->cont = 1; 126 ctx->start = 1; 127 ctx->encode = 0; 128 129 bi->init = 1; 130 bi->ptr = (char *)ctx; 131 bi->flags = 0; 132 bi->num = 0; 133 return (1); 134 } 135 136 static int 137 b64_free(BIO *a) 138 { 139 if (a == NULL) 140 return (0); 141 free(a->ptr); 142 a->ptr = NULL; 143 a->init = 0; 144 a->flags = 0; 145 return (1); 146 } 147 148 static int 149 b64_read(BIO *b, char *out, int outl) 150 { 151 int ret = 0, i, ii, j, k, x, n, num, ret_code = 0; 152 BIO_B64_CTX *ctx; 153 unsigned char *p, *q; 154 155 if (out == NULL) 156 return (0); 157 ctx = (BIO_B64_CTX *)b->ptr; 158 159 if ((ctx == NULL) || (b->next_bio == NULL)) 160 return (0); 161 162 BIO_clear_retry_flags(b); 163 164 if (ctx->encode != B64_DECODE) { 165 ctx->encode = B64_DECODE; 166 ctx->buf_len = 0; 167 ctx->buf_off = 0; 168 ctx->tmp_len = 0; 169 EVP_DecodeInit(&(ctx->base64)); 170 } 171 172 /* First check if there are bytes decoded/encoded */ 173 if (ctx->buf_len > 0) { 174 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 175 i = ctx->buf_len - ctx->buf_off; 176 if (i > outl) 177 i = outl; 178 OPENSSL_assert(ctx->buf_off + i < (int)sizeof(ctx->buf)); 179 memcpy(out, &(ctx->buf[ctx->buf_off]), i); 180 ret = i; 181 out += i; 182 outl -= i; 183 ctx->buf_off += i; 184 if (ctx->buf_len == ctx->buf_off) { 185 ctx->buf_len = 0; 186 ctx->buf_off = 0; 187 } 188 } 189 190 /* At this point, we have room of outl bytes and an empty 191 * buffer, so we should read in some more. */ 192 193 ret_code = 0; 194 while (outl > 0) { 195 if (ctx->cont <= 0) 196 break; 197 198 i = BIO_read(b->next_bio, &(ctx->tmp[ctx->tmp_len]), 199 B64_BLOCK_SIZE - ctx->tmp_len); 200 201 if (i <= 0) { 202 ret_code = i; 203 204 /* Should we continue next time we are called? */ 205 if (!BIO_should_retry(b->next_bio)) { 206 ctx->cont = i; 207 /* If buffer empty break */ 208 if (ctx->tmp_len == 0) 209 break; 210 /* Fall through and process what we have */ 211 else 212 i = 0; 213 } 214 /* else we retry and add more data to buffer */ 215 else 216 break; 217 } 218 i += ctx->tmp_len; 219 ctx->tmp_len = i; 220 221 /* We need to scan, a line at a time until we 222 * have a valid line if we are starting. */ 223 if (ctx->start && (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)) { 224 /* ctx->start=1; */ 225 ctx->tmp_len = 0; 226 } else if (ctx->start) { 227 q = p =(unsigned char *)ctx->tmp; 228 num = 0; 229 for (j = 0; j < i; j++) { 230 if (*(q++) != '\n') 231 continue; 232 233 /* due to a previous very long line, 234 * we need to keep on scanning for a '\n' 235 * before we even start looking for 236 * base64 encoded stuff. */ 237 if (ctx->tmp_nl) { 238 p = q; 239 ctx->tmp_nl = 0; 240 continue; 241 } 242 243 k = EVP_DecodeUpdate(&(ctx->base64), 244 (unsigned char *)ctx->buf, 245 &num, p, q - p); 246 if ((k <= 0) && (num == 0) && (ctx->start)) 247 EVP_DecodeInit(&ctx->base64); 248 else { 249 if (p != (unsigned char *) 250 &(ctx->tmp[0])) { 251 i -= (p - (unsigned char *) 252 &(ctx->tmp[0])); 253 for (x = 0; x < i; x++) 254 ctx->tmp[x] = p[x]; 255 } 256 EVP_DecodeInit(&ctx->base64); 257 ctx->start = 0; 258 break; 259 } 260 p = q; 261 } 262 263 /* we fell off the end without starting */ 264 if ((j == i) && (num == 0)) { 265 /* Is this is one long chunk?, if so, keep on 266 * reading until a new line. */ 267 if (p == (unsigned char *)&(ctx->tmp[0])) { 268 /* Check buffer full */ 269 if (i == B64_BLOCK_SIZE) { 270 ctx->tmp_nl = 1; 271 ctx->tmp_len = 0; 272 } 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 } else { 284 ctx->tmp_len = 0; 285 } 286 } else if ((i < B64_BLOCK_SIZE) && (ctx->cont > 0)) { 287 /* If buffer isn't full and we can retry then 288 * restart to read in more data. 289 */ 290 continue; 291 } 292 293 if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) { 294 int z, jj; 295 296 #if 0 297 jj = (i >> 2) << 2; 298 #else 299 jj = i & ~3; /* process per 4 */ 300 #endif 301 z = EVP_DecodeBlock((unsigned char *)ctx->buf, 302 (unsigned char *)ctx->tmp, jj); 303 if (jj > 2) { 304 if (ctx->tmp[jj-1] == '=') { 305 z--; 306 if (ctx->tmp[jj-2] == '=') 307 z--; 308 } 309 } 310 /* z is now number of output bytes and jj is the 311 * number consumed */ 312 if (jj != i) { 313 memmove(ctx->tmp, &ctx->tmp[jj], i - jj); 314 ctx->tmp_len = i - jj; 315 } 316 ctx->buf_len = 0; 317 if (z > 0) { 318 ctx->buf_len = z; 319 } 320 i = z; 321 } else { 322 i = EVP_DecodeUpdate(&(ctx->base64), 323 (unsigned char *)ctx->buf, &ctx->buf_len, 324 (unsigned char *)ctx->tmp, i); 325 ctx->tmp_len = 0; 326 } 327 ctx->buf_off = 0; 328 if (i < 0) { 329 ret_code = 0; 330 ctx->buf_len = 0; 331 break; 332 } 333 334 if (ctx->buf_len <= outl) 335 i = ctx->buf_len; 336 else 337 i = outl; 338 339 memcpy(out, ctx->buf, i); 340 ret += i; 341 ctx->buf_off = i; 342 if (ctx->buf_off == ctx->buf_len) { 343 ctx->buf_len = 0; 344 ctx->buf_off = 0; 345 } 346 outl -= i; 347 out += i; 348 } 349 /* BIO_clear_retry_flags(b); */ 350 BIO_copy_next_retry(b); 351 return ((ret == 0) ? ret_code : ret); 352 } 353 354 static int 355 b64_write(BIO *b, const char *in, int inl) 356 { 357 int ret = 0; 358 int n; 359 int i; 360 BIO_B64_CTX *ctx; 361 362 ctx = (BIO_B64_CTX *)b->ptr; 363 BIO_clear_retry_flags(b); 364 365 if (ctx->encode != B64_ENCODE) { 366 ctx->encode = B64_ENCODE; 367 ctx->buf_len = 0; 368 ctx->buf_off = 0; 369 ctx->tmp_len = 0; 370 EVP_EncodeInit(&(ctx->base64)); 371 } 372 373 OPENSSL_assert(ctx->buf_off < (int)sizeof(ctx->buf)); 374 OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf)); 375 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 376 n = ctx->buf_len - ctx->buf_off; 377 while (n > 0) { 378 i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n); 379 if (i <= 0) { 380 BIO_copy_next_retry(b); 381 return (i); 382 } 383 OPENSSL_assert(i <= n); 384 ctx->buf_off += i; 385 OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf)); 386 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 387 n -= i; 388 } 389 /* at this point all pending data has been written */ 390 ctx->buf_off = 0; 391 ctx->buf_len = 0; 392 393 if ((in == NULL) || (inl <= 0)) 394 return (0); 395 396 while (inl > 0) { 397 n = (inl > B64_BLOCK_SIZE) ? B64_BLOCK_SIZE : inl; 398 399 if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) { 400 if (ctx->tmp_len > 0) { 401 OPENSSL_assert(ctx->tmp_len <= 3); 402 n = 3 - ctx->tmp_len; 403 /* There's a theoretical possibility for this */ 404 if (n > inl) 405 n = inl; 406 memcpy(&(ctx->tmp[ctx->tmp_len]), in, n); 407 ctx->tmp_len += n; 408 ret += n; 409 if (ctx->tmp_len < 3) 410 break; 411 ctx->buf_len = EVP_EncodeBlock( 412 (unsigned char *)ctx->buf, 413 (unsigned char *)ctx->tmp, ctx->tmp_len); 414 OPENSSL_assert(ctx->buf_len <= 415 (int)sizeof(ctx->buf)); 416 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 417 /* Since we're now done using the temporary 418 buffer, the length should be 0'd */ 419 ctx->tmp_len = 0; 420 } else { 421 if (n < 3) { 422 memcpy(ctx->tmp, in, n); 423 ctx->tmp_len = n; 424 ret += n; 425 break; 426 } 427 n -= n % 3; 428 ctx->buf_len = EVP_EncodeBlock( 429 (unsigned char *)ctx->buf, 430 (const unsigned char *)in, n); 431 OPENSSL_assert(ctx->buf_len <= 432 (int)sizeof(ctx->buf)); 433 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 434 ret += n; 435 } 436 } else { 437 EVP_EncodeUpdate(&(ctx->base64), 438 (unsigned char *)ctx->buf, &ctx->buf_len, 439 (unsigned char *)in, n); 440 OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf)); 441 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 442 ret += n; 443 } 444 inl -= n; 445 in += n; 446 447 ctx->buf_off = 0; 448 n = ctx->buf_len; 449 while (n > 0) { 450 i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n); 451 if (i <= 0) { 452 BIO_copy_next_retry(b); 453 return ((ret == 0) ? i : ret); 454 } 455 OPENSSL_assert(i <= n); 456 n -= i; 457 ctx->buf_off += i; 458 OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf)); 459 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 460 } 461 ctx->buf_len = 0; 462 ctx->buf_off = 0; 463 } 464 return (ret); 465 } 466 467 static long 468 b64_ctrl(BIO *b, int cmd, long num, void *ptr) 469 { 470 BIO_B64_CTX *ctx; 471 long ret = 1; 472 int i; 473 474 ctx = (BIO_B64_CTX *)b->ptr; 475 476 switch (cmd) { 477 case BIO_CTRL_RESET: 478 ctx->cont = 1; 479 ctx->start = 1; 480 ctx->encode = B64_NONE; 481 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 482 break; 483 case BIO_CTRL_EOF: /* More to read */ 484 if (ctx->cont <= 0) 485 ret = 1; 486 else 487 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 488 break; 489 case BIO_CTRL_WPENDING: /* More to write in buffer */ 490 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 491 ret = ctx->buf_len - ctx->buf_off; 492 if ((ret == 0) && (ctx->encode != B64_NONE) && 493 (ctx->base64.num != 0)) 494 ret = 1; 495 else if (ret <= 0) 496 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 497 break; 498 case BIO_CTRL_PENDING: /* More to read in buffer */ 499 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 500 ret = ctx->buf_len - ctx->buf_off; 501 if (ret <= 0) 502 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 503 break; 504 case BIO_CTRL_FLUSH: 505 /* do a final write */ 506 again: 507 while (ctx->buf_len != ctx->buf_off) { 508 i = b64_write(b, NULL, 0); 509 if (i < 0) 510 return i; 511 } 512 if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) { 513 if (ctx->tmp_len != 0) { 514 ctx->buf_len = EVP_EncodeBlock( 515 (unsigned char *)ctx->buf, 516 (unsigned char *)ctx->tmp, 517 ctx->tmp_len); 518 ctx->buf_off = 0; 519 ctx->tmp_len = 0; 520 goto again; 521 } 522 } else if (ctx->encode != B64_NONE && ctx->base64.num != 0) { 523 ctx->buf_off = 0; 524 EVP_EncodeFinal(&(ctx->base64), 525 (unsigned char *)ctx->buf, 526 &(ctx->buf_len)); 527 /* push out the bytes */ 528 goto again; 529 } 530 /* Finally flush the underlying BIO */ 531 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 532 break; 533 534 case BIO_C_DO_STATE_MACHINE: 535 BIO_clear_retry_flags(b); 536 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 537 BIO_copy_next_retry(b); 538 break; 539 540 case BIO_CTRL_DUP: 541 break; 542 case BIO_CTRL_INFO: 543 case BIO_CTRL_GET: 544 case BIO_CTRL_SET: 545 default: 546 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 547 break; 548 } 549 return (ret); 550 } 551 552 static long 553 b64_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) 554 { 555 long ret = 1; 556 557 if (b->next_bio == NULL) 558 return (0); 559 switch (cmd) { 560 default: 561 ret = BIO_callback_ctrl(b->next_bio, cmd, fp); 562 break; 563 } 564 return (ret); 565 } 566 567 static int 568 b64_puts(BIO *b, const char *str) 569 { 570 return b64_write(b, str, strlen(str)); 571 } 572