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 jj = i & ~3; /* process per 4 */ 297 z = EVP_DecodeBlock((unsigned char *)ctx->buf, 298 (unsigned char *)ctx->tmp, jj); 299 if (jj > 2) { 300 if (ctx->tmp[jj-1] == '=') { 301 z--; 302 if (ctx->tmp[jj-2] == '=') 303 z--; 304 } 305 } 306 /* z is now number of output bytes and jj is the 307 * number consumed */ 308 if (jj != i) { 309 memmove(ctx->tmp, &ctx->tmp[jj], i - jj); 310 ctx->tmp_len = i - jj; 311 } 312 ctx->buf_len = 0; 313 if (z > 0) { 314 ctx->buf_len = z; 315 } 316 i = z; 317 } else { 318 i = EVP_DecodeUpdate(&(ctx->base64), 319 (unsigned char *)ctx->buf, &ctx->buf_len, 320 (unsigned char *)ctx->tmp, i); 321 ctx->tmp_len = 0; 322 } 323 ctx->buf_off = 0; 324 if (i < 0) { 325 ret_code = 0; 326 ctx->buf_len = 0; 327 break; 328 } 329 330 if (ctx->buf_len <= outl) 331 i = ctx->buf_len; 332 else 333 i = outl; 334 335 memcpy(out, ctx->buf, i); 336 ret += i; 337 ctx->buf_off = i; 338 if (ctx->buf_off == ctx->buf_len) { 339 ctx->buf_len = 0; 340 ctx->buf_off = 0; 341 } 342 outl -= i; 343 out += i; 344 } 345 /* BIO_clear_retry_flags(b); */ 346 BIO_copy_next_retry(b); 347 return ((ret == 0) ? ret_code : ret); 348 } 349 350 static int 351 b64_write(BIO *b, const char *in, int inl) 352 { 353 int ret = 0; 354 int n; 355 int i; 356 BIO_B64_CTX *ctx; 357 358 ctx = (BIO_B64_CTX *)b->ptr; 359 BIO_clear_retry_flags(b); 360 361 if (ctx->encode != B64_ENCODE) { 362 ctx->encode = B64_ENCODE; 363 ctx->buf_len = 0; 364 ctx->buf_off = 0; 365 ctx->tmp_len = 0; 366 EVP_EncodeInit(&(ctx->base64)); 367 } 368 369 OPENSSL_assert(ctx->buf_off < (int)sizeof(ctx->buf)); 370 OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf)); 371 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 372 n = ctx->buf_len - ctx->buf_off; 373 while (n > 0) { 374 i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n); 375 if (i <= 0) { 376 BIO_copy_next_retry(b); 377 return (i); 378 } 379 OPENSSL_assert(i <= n); 380 ctx->buf_off += i; 381 OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf)); 382 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 383 n -= i; 384 } 385 /* at this point all pending data has been written */ 386 ctx->buf_off = 0; 387 ctx->buf_len = 0; 388 389 if ((in == NULL) || (inl <= 0)) 390 return (0); 391 392 while (inl > 0) { 393 n = (inl > B64_BLOCK_SIZE) ? B64_BLOCK_SIZE : inl; 394 395 if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) { 396 if (ctx->tmp_len > 0) { 397 OPENSSL_assert(ctx->tmp_len <= 3); 398 n = 3 - ctx->tmp_len; 399 /* There's a theoretical possibility for this */ 400 if (n > inl) 401 n = inl; 402 memcpy(&(ctx->tmp[ctx->tmp_len]), in, n); 403 ctx->tmp_len += n; 404 ret += n; 405 if (ctx->tmp_len < 3) 406 break; 407 ctx->buf_len = EVP_EncodeBlock( 408 (unsigned char *)ctx->buf, 409 (unsigned char *)ctx->tmp, ctx->tmp_len); 410 OPENSSL_assert(ctx->buf_len <= 411 (int)sizeof(ctx->buf)); 412 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 413 /* Since we're now done using the temporary 414 buffer, the length should be 0'd */ 415 ctx->tmp_len = 0; 416 } else { 417 if (n < 3) { 418 memcpy(ctx->tmp, in, n); 419 ctx->tmp_len = n; 420 ret += n; 421 break; 422 } 423 n -= n % 3; 424 ctx->buf_len = EVP_EncodeBlock( 425 (unsigned char *)ctx->buf, 426 (const unsigned char *)in, n); 427 OPENSSL_assert(ctx->buf_len <= 428 (int)sizeof(ctx->buf)); 429 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 430 ret += n; 431 } 432 } else { 433 EVP_EncodeUpdate(&(ctx->base64), 434 (unsigned char *)ctx->buf, &ctx->buf_len, 435 (unsigned char *)in, n); 436 OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf)); 437 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 438 ret += n; 439 } 440 inl -= n; 441 in += n; 442 443 ctx->buf_off = 0; 444 n = ctx->buf_len; 445 while (n > 0) { 446 i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n); 447 if (i <= 0) { 448 BIO_copy_next_retry(b); 449 return ((ret == 0) ? i : ret); 450 } 451 OPENSSL_assert(i <= n); 452 n -= i; 453 ctx->buf_off += i; 454 OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf)); 455 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 456 } 457 ctx->buf_len = 0; 458 ctx->buf_off = 0; 459 } 460 return (ret); 461 } 462 463 static long 464 b64_ctrl(BIO *b, int cmd, long num, void *ptr) 465 { 466 BIO_B64_CTX *ctx; 467 long ret = 1; 468 int i; 469 470 ctx = (BIO_B64_CTX *)b->ptr; 471 472 switch (cmd) { 473 case BIO_CTRL_RESET: 474 ctx->cont = 1; 475 ctx->start = 1; 476 ctx->encode = B64_NONE; 477 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 478 break; 479 case BIO_CTRL_EOF: /* More to read */ 480 if (ctx->cont <= 0) 481 ret = 1; 482 else 483 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 484 break; 485 case BIO_CTRL_WPENDING: /* More to write in buffer */ 486 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 487 ret = ctx->buf_len - ctx->buf_off; 488 if ((ret == 0) && (ctx->encode != B64_NONE) && 489 (ctx->base64.num != 0)) 490 ret = 1; 491 else if (ret <= 0) 492 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 493 break; 494 case BIO_CTRL_PENDING: /* More to read in buffer */ 495 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 496 ret = ctx->buf_len - ctx->buf_off; 497 if (ret <= 0) 498 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 499 break; 500 case BIO_CTRL_FLUSH: 501 /* do a final write */ 502 again: 503 while (ctx->buf_len != ctx->buf_off) { 504 i = b64_write(b, NULL, 0); 505 if (i < 0) 506 return i; 507 } 508 if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) { 509 if (ctx->tmp_len != 0) { 510 ctx->buf_len = EVP_EncodeBlock( 511 (unsigned char *)ctx->buf, 512 (unsigned char *)ctx->tmp, 513 ctx->tmp_len); 514 ctx->buf_off = 0; 515 ctx->tmp_len = 0; 516 goto again; 517 } 518 } else if (ctx->encode != B64_NONE && ctx->base64.num != 0) { 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 548 static long 549 b64_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) 550 { 551 long ret = 1; 552 553 if (b->next_bio == NULL) 554 return (0); 555 switch (cmd) { 556 default: 557 ret = BIO_callback_ctrl(b->next_bio, cmd, fp); 558 break; 559 } 560 return (ret); 561 } 562 563 static int 564 b64_puts(BIO *b, const char *str) 565 { 566 return b64_write(b, str, strlen(str)); 567 } 568