bio_b64.c revision 280304
12061Sjkh/* crypto/evp/bio_b64.c */ 250479Speter/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 32061Sjkh * All rights reserved. 438666Sjb * 532427Sjb * This package is an SSL implementation written 638666Sjb * by Eric Young (eay@cryptsoft.com). 738666Sjb * The implementation was written so as to conform with Netscapes SSL. 838666Sjb * 938666Sjb * This library is free for commercial and non-commercial use as long as 1038666Sjb * the following conditions are aheared to. The following conditions 1144918Sjkh * apply to all code found in this distribution, be it the RC4, RSA, 1238666Sjb * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1338666Sjb * included with this distribution is covered by the same copyright terms 1438666Sjb * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1538666Sjb * 1638666Sjb * Copyright remains Eric Young's, and as such any Copyright notices in 1738666Sjb * the code are not to be removed. 1838666Sjb * If this package is used in a product, Eric Young should be given attribution 1938978Sjb * as the author of the parts of the library used. 2038978Sjb * This can be in the form of a textual message at program startup or 2132427Sjb * in documentation (online or textual) provided with the package. 2238666Sjb * 2338666Sjb * Redistribution and use in source and binary forms, with or without 2438666Sjb * modification, are permitted provided that the following conditions 2538666Sjb * are met: 2638666Sjb * 1. Redistributions of source code must retain the copyright 2738666Sjb * notice, this list of conditions and the following disclaimer. 2817308Speter * 2. Redistributions in binary form must reproduce the above copyright 2938666Sjb * notice, this list of conditions and the following disclaimer in the 3038666Sjb * documentation and/or other materials provided with the distribution. 3138666Sjb * 3. All advertising materials mentioning features or use of this software 3219175Sbde * must display the following acknowledgement: 3338666Sjb * "This product includes cryptographic software written by 3438666Sjb * Eric Young (eay@cryptsoft.com)" 3538042Sbde * The word 'cryptographic' can be left out if the rouines from the library 3639726Sjb * being used are not cryptographic related :-). 3738666Sjb * 4. If you include any Windows specific code (or a derivative thereof) from 3838666Sjb * the apps directory (application code) you must include an acknowledgement: 3938042Sbde * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4038666Sjb * 4149315Shoek * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4217308Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4338666Sjb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4438666Sjb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4538666Sjb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4638666Sjb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4717308Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4845108Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4942128Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5042128Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5138666Sjb * SUCH DAMAGE. 5251361Sjb * 5338666Sjb * The licence and distribution terms for any publically available version or 5417308Speter * derivative of this code cannot be changed. i.e. this code cannot simply be 5538666Sjb * copied and put under another distribution licence 5617308Speter * [including the GNU Public Licence.] 5738666Sjb */ 5817308Speter 5927910Sasami#include <stdio.h> 6043226Sjkh#include <errno.h> 6143226Sjkh#include "cryptlib.h" 6243226Sjkh#include <openssl/buffer.h> 6338666Sjb#include <openssl/evp.h> 6427910Sasami 6538666Sjbstatic int b64_write(BIO *h, const char *buf, int num); 6638666Sjbstatic int b64_read(BIO *h, char *buf, int size); 6738666Sjbstatic int b64_puts(BIO *h, const char *str); 6827910Sasami/* 6938666Sjb * static int b64_gets(BIO *h, char *str, int size); 7038666Sjb */ 7143226Sjkhstatic long b64_ctrl(BIO *h, int cmd, long arg1, void *arg2); 7243226Sjkhstatic int b64_new(BIO *h); 7327910Sasamistatic int b64_free(BIO *data); 7438666Sjbstatic long b64_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); 7538666Sjb#define B64_BLOCK_SIZE 1024 7627910Sasami#define B64_BLOCK_SIZE2 768 7738666Sjb#define B64_NONE 0 7827910Sasami#define B64_ENCODE 1 7917308Speter#define B64_DECODE 2 8038666Sjb 8138666Sjbtypedef struct b64_struct { 8217308Speter /* 8355678Smarcel * BIO *bio; moved to the BIO structure 8455678Smarcel */ 8555678Smarcel int buf_len; 8655678Smarcel int buf_off; 872061Sjkh int tmp_len; /* used to find the start when decoding */ 8855026Smarcel int tmp_nl; /* If true, scan until '\n' */ 8955026Smarcel int encode; 9054324Smarcel int start; /* have we started decoding yet? */ 9117308Speter int cont; /* <= 0 when finished */ 9238666Sjb EVP_ENCODE_CTX base64; 9317308Speter char buf[EVP_ENCODE_LENGTH(B64_BLOCK_SIZE) + 10]; 9455678Smarcel char tmp[B64_BLOCK_SIZE]; 9538666Sjb} BIO_B64_CTX; 9654324Smarcel 972302Spaulstatic BIO_METHOD methods_b64 = { 9839206Sjkh BIO_TYPE_BASE64, "base64 encoding", 9939206Sjkh b64_write, 10039206Sjkh b64_read, 10154324Smarcel b64_puts, 10217308Speter NULL, /* b64_gets, */ 10354324Smarcel b64_ctrl, 10454324Smarcel b64_new, 10554324Smarcel b64_free, 10654324Smarcel b64_callback_ctrl, 10754324Smarcel}; 10854324Smarcel 10954324SmarcelBIO_METHOD *BIO_f_base64(void) 11054324Smarcel{ 11154324Smarcel return (&methods_b64); 11254324Smarcel} 11354324Smarcel 11454324Smarcelstatic int b64_new(BIO *bi) 11554324Smarcel{ 11654324Smarcel BIO_B64_CTX *ctx; 11754324Smarcel 11854324Smarcel ctx = (BIO_B64_CTX *)OPENSSL_malloc(sizeof(BIO_B64_CTX)); 11954324Smarcel if (ctx == NULL) 12054324Smarcel return (0); 12154324Smarcel 12254324Smarcel ctx->buf_len = 0; 12354324Smarcel ctx->tmp_len = 0; 12454324Smarcel ctx->tmp_nl = 0; 12554324Smarcel ctx->buf_off = 0; 12654324Smarcel ctx->cont = 1; 12754324Smarcel ctx->start = 1; 12854324Smarcel ctx->encode = 0; 12954324Smarcel 13054324Smarcel bi->init = 1; 13154324Smarcel bi->ptr = (char *)ctx; 13254324Smarcel bi->flags = 0; 13354324Smarcel bi->num = 0; 13454324Smarcel return (1); 13538666Sjb} 13638666Sjb 13717308Speterstatic int b64_free(BIO *a) 13838666Sjb{ 13938666Sjb if (a == NULL) 14038666Sjb return (0); 14117308Speter OPENSSL_free(a->ptr); 14255678Smarcel a->ptr = NULL; 14355678Smarcel a->init = 0; 14455678Smarcel a->flags = 0; 14555678Smarcel return (1); 14655678Smarcel} 1472061Sjkh 14817308Speterstatic int b64_read(BIO *b, char *out, int outl) 14938666Sjb{ 15038666Sjb int ret = 0, i, ii, j, k, x, n, num, ret_code = 0; 15117308Speter BIO_B64_CTX *ctx; 15255678Smarcel unsigned char *p, *q; 1533626Swollman 15417308Speter if (out == NULL) 15555678Smarcel return (0); 15655678Smarcel ctx = (BIO_B64_CTX *)b->ptr; 15755678Smarcel 15855678Smarcel if ((ctx == NULL) || (b->next_bio == NULL)) 15955678Smarcel return (0); 16055678Smarcel 16155678Smarcel BIO_clear_retry_flags(b); 16255678Smarcel 16355678Smarcel if (ctx->encode != B64_DECODE) { 16455678Smarcel ctx->encode = B64_DECODE; 16555678Smarcel ctx->buf_len = 0; 16655678Smarcel ctx->buf_off = 0; 16755678Smarcel ctx->tmp_len = 0; 16838666Sjb EVP_DecodeInit(&(ctx->base64)); 16938666Sjb } 17017308Speter 17155678Smarcel /* First check if there are bytes decoded/encoded */ 17238978Sjb if (ctx->buf_len > 0) { 1733626Swollman OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 17417308Speter i = ctx->buf_len - ctx->buf_off; 17538666Sjb if (i > outl) 17617308Speter i = outl; 17743226Sjkh OPENSSL_assert(ctx->buf_off + i < (int)sizeof(ctx->buf)); 17843226Sjkh memcpy(out, &(ctx->buf[ctx->buf_off]), i); 17943226Sjkh ret = i; 18038666Sjb out += i; 18138666Sjb outl -= i; 18244103Smsmith ctx->buf_off += i; 183 if (ctx->buf_len == ctx->buf_off) { 184 ctx->buf_len = 0; 185 ctx->buf_off = 0; 186 } 187 } 188 189 /* 190 * At this point, we have room of outl bytes and an empty buffer, so we 191 * should read in some more. 192 */ 193 194 ret_code = 0; 195 while (outl > 0) { 196 if (ctx->cont <= 0) 197 break; 198 199 i = BIO_read(b->next_bio, &(ctx->tmp[ctx->tmp_len]), 200 B64_BLOCK_SIZE - ctx->tmp_len); 201 202 if (i <= 0) { 203 ret_code = i; 204 205 /* Should we continue next time we are called? */ 206 if (!BIO_should_retry(b->next_bio)) { 207 ctx->cont = i; 208 /* If buffer empty break */ 209 if (ctx->tmp_len == 0) 210 break; 211 /* Fall through and process what we have */ 212 else 213 i = 0; 214 } 215 /* else we retry and add more data to buffer */ 216 else 217 break; 218 } 219 i += ctx->tmp_len; 220 ctx->tmp_len = i; 221 222 /* 223 * We need to scan, a line at a time until we have a valid line if we 224 * are starting. 225 */ 226 if (ctx->start && (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)) { 227 /* ctx->start=1; */ 228 ctx->tmp_len = 0; 229 } else if (ctx->start) { 230 q = p = (unsigned char *)ctx->tmp; 231 num = 0; 232 for (j = 0; j < i; j++) { 233 if (*(q++) != '\n') 234 continue; 235 236 /* 237 * due to a previous very long line, we need to keep on 238 * scanning for a '\n' before we even start looking for 239 * base64 encoded stuff. 240 */ 241 if (ctx->tmp_nl) { 242 p = q; 243 ctx->tmp_nl = 0; 244 continue; 245 } 246 247 k = EVP_DecodeUpdate(&(ctx->base64), 248 (unsigned char *)ctx->buf, 249 &num, p, q - p); 250 if ((k <= 0) && (num == 0) && (ctx->start)) 251 EVP_DecodeInit(&ctx->base64); 252 else { 253 if (p != (unsigned char *) 254 &(ctx->tmp[0])) { 255 i -= (p - (unsigned char *) 256 &(ctx->tmp[0])); 257 for (x = 0; x < i; x++) 258 ctx->tmp[x] = p[x]; 259 } 260 EVP_DecodeInit(&ctx->base64); 261 ctx->start = 0; 262 break; 263 } 264 p = q; 265 } 266 267 /* we fell off the end without starting */ 268 if ((j == i) && (num == 0)) { 269 /* 270 * Is this is one long chunk?, if so, keep on reading until a 271 * new line. 272 */ 273 if (p == (unsigned char *)&(ctx->tmp[0])) { 274 /* Check buffer full */ 275 if (i == B64_BLOCK_SIZE) { 276 ctx->tmp_nl = 1; 277 ctx->tmp_len = 0; 278 } 279 } else if (p != q) { /* finished on a '\n' */ 280 n = q - p; 281 for (ii = 0; ii < n; ii++) 282 ctx->tmp[ii] = p[ii]; 283 ctx->tmp_len = n; 284 } 285 /* else finished on a '\n' */ 286 continue; 287 } else { 288 ctx->tmp_len = 0; 289 } 290 } else if ((i < B64_BLOCK_SIZE) && (ctx->cont > 0)) { 291 /* 292 * If buffer isn't full and we can retry then restart to read in 293 * more data. 294 */ 295 continue; 296 } 297 298 if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) { 299 int z, jj; 300 301#if 0 302 jj = (i >> 2) << 2; 303#else 304 jj = i & ~3; /* process per 4 */ 305#endif 306 z = EVP_DecodeBlock((unsigned char *)ctx->buf, 307 (unsigned char *)ctx->tmp, jj); 308 if (jj > 2) { 309 if (ctx->tmp[jj - 1] == '=') { 310 z--; 311 if (ctx->tmp[jj - 2] == '=') 312 z--; 313 } 314 } 315 /* 316 * z is now number of output bytes and jj is the number consumed 317 */ 318 if (jj != i) { 319 memmove(ctx->tmp, &ctx->tmp[jj], i - jj); 320 ctx->tmp_len = i - jj; 321 } 322 ctx->buf_len = 0; 323 if (z > 0) { 324 ctx->buf_len = z; 325 } 326 i = z; 327 } else { 328 i = EVP_DecodeUpdate(&(ctx->base64), 329 (unsigned char *)ctx->buf, &ctx->buf_len, 330 (unsigned char *)ctx->tmp, i); 331 ctx->tmp_len = 0; 332 } 333 ctx->buf_off = 0; 334 if (i < 0) { 335 ret_code = 0; 336 ctx->buf_len = 0; 337 break; 338 } 339 340 if (ctx->buf_len <= outl) 341 i = ctx->buf_len; 342 else 343 i = outl; 344 345 memcpy(out, ctx->buf, i); 346 ret += i; 347 ctx->buf_off = i; 348 if (ctx->buf_off == ctx->buf_len) { 349 ctx->buf_len = 0; 350 ctx->buf_off = 0; 351 } 352 outl -= i; 353 out += i; 354 } 355 /* BIO_clear_retry_flags(b); */ 356 BIO_copy_next_retry(b); 357 return ((ret == 0) ? ret_code : ret); 358} 359 360static int b64_write(BIO *b, const char *in, int inl) 361{ 362 int ret = 0; 363 int n; 364 int i; 365 BIO_B64_CTX *ctx; 366 367 ctx = (BIO_B64_CTX *)b->ptr; 368 BIO_clear_retry_flags(b); 369 370 if (ctx->encode != B64_ENCODE) { 371 ctx->encode = B64_ENCODE; 372 ctx->buf_len = 0; 373 ctx->buf_off = 0; 374 ctx->tmp_len = 0; 375 EVP_EncodeInit(&(ctx->base64)); 376 } 377 378 OPENSSL_assert(ctx->buf_off < (int)sizeof(ctx->buf)); 379 OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf)); 380 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 381 n = ctx->buf_len - ctx->buf_off; 382 while (n > 0) { 383 i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n); 384 if (i <= 0) { 385 BIO_copy_next_retry(b); 386 return (i); 387 } 388 OPENSSL_assert(i <= n); 389 ctx->buf_off += i; 390 OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf)); 391 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 392 n -= i; 393 } 394 /* at this point all pending data has been written */ 395 ctx->buf_off = 0; 396 ctx->buf_len = 0; 397 398 if ((in == NULL) || (inl <= 0)) 399 return (0); 400 401 while (inl > 0) { 402 n = (inl > B64_BLOCK_SIZE) ? B64_BLOCK_SIZE : inl; 403 404 if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) { 405 if (ctx->tmp_len > 0) { 406 OPENSSL_assert(ctx->tmp_len <= 3); 407 n = 3 - ctx->tmp_len; 408 /* 409 * There's a theoretical possibility for this 410 */ 411 if (n > inl) 412 n = inl; 413 memcpy(&(ctx->tmp[ctx->tmp_len]), in, n); 414 ctx->tmp_len += n; 415 ret += n; 416 if (ctx->tmp_len < 3) 417 break; 418 ctx->buf_len = 419 EVP_EncodeBlock((unsigned char *)ctx->buf, 420 (unsigned char *)ctx->tmp, ctx->tmp_len); 421 OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf)); 422 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 423 /* 424 * Since we're now done using the temporary buffer, the 425 * length should be 0'd 426 */ 427 ctx->tmp_len = 0; 428 } else { 429 if (n < 3) { 430 memcpy(ctx->tmp, in, n); 431 ctx->tmp_len = n; 432 ret += n; 433 break; 434 } 435 n -= n % 3; 436 ctx->buf_len = 437 EVP_EncodeBlock((unsigned char *)ctx->buf, 438 (const unsigned char *)in, n); 439 OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf)); 440 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 441 ret += n; 442 } 443 } else { 444 EVP_EncodeUpdate(&(ctx->base64), 445 (unsigned char *)ctx->buf, &ctx->buf_len, 446 (unsigned char *)in, n); 447 OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf)); 448 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 449 ret += n; 450 } 451 inl -= n; 452 in += n; 453 454 ctx->buf_off = 0; 455 n = ctx->buf_len; 456 while (n > 0) { 457 i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n); 458 if (i <= 0) { 459 BIO_copy_next_retry(b); 460 return ((ret == 0) ? i : ret); 461 } 462 OPENSSL_assert(i <= n); 463 n -= i; 464 ctx->buf_off += i; 465 OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf)); 466 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 467 } 468 ctx->buf_len = 0; 469 ctx->buf_off = 0; 470 } 471 return (ret); 472} 473 474static long b64_ctrl(BIO *b, int cmd, long num, void *ptr) 475{ 476 BIO_B64_CTX *ctx; 477 long ret = 1; 478 int i; 479 480 ctx = (BIO_B64_CTX *)b->ptr; 481 482 switch (cmd) { 483 case BIO_CTRL_RESET: 484 ctx->cont = 1; 485 ctx->start = 1; 486 ctx->encode = B64_NONE; 487 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 488 break; 489 case BIO_CTRL_EOF: /* More to read */ 490 if (ctx->cont <= 0) 491 ret = 1; 492 else 493 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 494 break; 495 case BIO_CTRL_WPENDING: /* More to write in buffer */ 496 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 497 ret = ctx->buf_len - ctx->buf_off; 498 if ((ret == 0) && (ctx->encode != B64_NONE) 499 && (ctx->base64.num != 0)) 500 ret = 1; 501 else if (ret <= 0) 502 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 503 break; 504 case BIO_CTRL_PENDING: /* More to read in buffer */ 505 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 506 ret = ctx->buf_len - ctx->buf_off; 507 if (ret <= 0) 508 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 509 break; 510 case BIO_CTRL_FLUSH: 511 /* do a final write */ 512 again: 513 while (ctx->buf_len != ctx->buf_off) { 514 i = b64_write(b, NULL, 0); 515 if (i < 0) 516 return i; 517 } 518 if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) { 519 if (ctx->tmp_len != 0) { 520 ctx->buf_len = EVP_EncodeBlock((unsigned char *)ctx->buf, 521 (unsigned char *)ctx->tmp, 522 ctx->tmp_len); 523 ctx->buf_off = 0; 524 ctx->tmp_len = 0; 525 goto again; 526 } 527 } else if (ctx->encode != B64_NONE && ctx->base64.num != 0) { 528 ctx->buf_off = 0; 529 EVP_EncodeFinal(&(ctx->base64), 530 (unsigned char *)ctx->buf, &(ctx->buf_len)); 531 /* push out the bytes */ 532 goto again; 533 } 534 /* Finally flush the underlying BIO */ 535 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 536 break; 537 538 case BIO_C_DO_STATE_MACHINE: 539 BIO_clear_retry_flags(b); 540 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 541 BIO_copy_next_retry(b); 542 break; 543 544 case BIO_CTRL_DUP: 545 break; 546 case BIO_CTRL_INFO: 547 case BIO_CTRL_GET: 548 case BIO_CTRL_SET: 549 default: 550 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 551 break; 552 } 553 return (ret); 554} 555 556static long b64_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) 557{ 558 long ret = 1; 559 560 if (b->next_bio == NULL) 561 return (0); 562 switch (cmd) { 563 default: 564 ret = BIO_callback_ctrl(b->next_bio, cmd, fp); 565 break; 566 } 567 return (ret); 568} 569 570static int b64_puts(BIO *b, const char *str) 571{ 572 return b64_write(b, str, strlen(str)); 573} 574