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