1 /* crypto/evp/bio_b64.c */ 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 <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 num = 0; 230 for (j=0; j<i; j++) 231 { 232 if (*(q++) != '\n') continue; 233 234 /* due to a previous very long line, 235 * we need to keep on scanning for a '\n' 236 * before we even start looking for 237 * base64 encoded stuff. */ 238 if (ctx->tmp_nl) 239 { 240 p=q; 241 ctx->tmp_nl=0; 242 continue; 243 } 244 245 k=EVP_DecodeUpdate(&(ctx->base64), 246 (unsigned char *)ctx->buf, 247 &num,p,q-p); 248 if ((k <= 0) && (num == 0) && (ctx->start)) 249 EVP_DecodeInit(&ctx->base64); 250 else 251 { 252 if (p != (unsigned char *) 253 &(ctx->tmp[0])) 254 { 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 271 * reading until a new line. */ 272 if (p == (unsigned char *)&(ctx->tmp[0])) 273 { 274 /* Check buffer full */ 275 if (i == B64_BLOCK_SIZE) 276 { 277 ctx->tmp_nl=1; 278 ctx->tmp_len=0; 279 } 280 } 281 else if (p != q) /* finished on a '\n' */ 282 { 283 n=q-p; 284 for (ii=0; ii<n; ii++) 285 ctx->tmp[ii]=p[ii]; 286 ctx->tmp_len=n; 287 } 288 /* else finished on a '\n' */ 289 continue; 290 } 291 else 292 { 293 ctx->tmp_len=0; 294 } 295 } 296 else if ((i < B64_BLOCK_SIZE) && (ctx->cont > 0)) 297 { 298 /* If buffer isn't full and we can retry then 299 * restart to read in more data. 300 */ 301 continue; 302 } 303 304 if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) 305 { 306 int z,jj; 307 308 #if 0 309 jj=(i>>2)<<2; 310 #else 311 jj = i & ~3; /* process per 4 */ 312 #endif 313 z=EVP_DecodeBlock((unsigned char *)ctx->buf, 314 (unsigned char *)ctx->tmp,jj); 315 if (jj > 2) 316 { 317 if (ctx->tmp[jj-1] == '=') 318 { 319 z--; 320 if (ctx->tmp[jj-2] == '=') 321 z--; 322 } 323 } 324 /* z is now number of output bytes and jj is the 325 * number consumed */ 326 if (jj != i) 327 { 328 memmove(ctx->tmp, &ctx->tmp[jj], i-jj); 329 ctx->tmp_len=i-jj; 330 } 331 ctx->buf_len=0; 332 if (z > 0) 333 { 334 ctx->buf_len=z; 335 } 336 i=z; 337 } 338 else 339 { 340 i=EVP_DecodeUpdate(&(ctx->base64), 341 (unsigned char *)ctx->buf,&ctx->buf_len, 342 (unsigned char *)ctx->tmp,i); 343 ctx->tmp_len = 0; 344 } 345 ctx->buf_off=0; 346 if (i < 0) 347 { 348 ret_code=0; 349 ctx->buf_len=0; 350 break; 351 } 352 353 if (ctx->buf_len <= outl) 354 i=ctx->buf_len; 355 else 356 i=outl; 357 358 memcpy(out,ctx->buf,i); 359 ret+=i; 360 ctx->buf_off=i; 361 if (ctx->buf_off == ctx->buf_len) 362 { 363 ctx->buf_len=0; 364 ctx->buf_off=0; 365 } 366 outl-=i; 367 out+=i; 368 } 369 /* BIO_clear_retry_flags(b); */ 370 BIO_copy_next_retry(b); 371 return((ret == 0)?ret_code:ret); 372 } 373 374 static int b64_write(BIO *b, const char *in, int inl) 375 { 376 int ret=0; 377 int n; 378 int i; 379 BIO_B64_CTX *ctx; 380 381 ctx=(BIO_B64_CTX *)b->ptr; 382 BIO_clear_retry_flags(b); 383 384 if (ctx->encode != B64_ENCODE) 385 { 386 ctx->encode=B64_ENCODE; 387 ctx->buf_len=0; 388 ctx->buf_off=0; 389 ctx->tmp_len=0; 390 EVP_EncodeInit(&(ctx->base64)); 391 } 392 393 OPENSSL_assert(ctx->buf_off < (int)sizeof(ctx->buf)); 394 OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf)); 395 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 396 n=ctx->buf_len-ctx->buf_off; 397 while (n > 0) 398 { 399 i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n); 400 if (i <= 0) 401 { 402 BIO_copy_next_retry(b); 403 return(i); 404 } 405 OPENSSL_assert(i <= n); 406 ctx->buf_off+=i; 407 OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf)); 408 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 409 n-=i; 410 } 411 /* at this point all pending data has been written */ 412 ctx->buf_off=0; 413 ctx->buf_len=0; 414 415 if ((in == NULL) || (inl <= 0)) return(0); 416 417 while (inl > 0) 418 { 419 n=(inl > B64_BLOCK_SIZE)?B64_BLOCK_SIZE:inl; 420 421 if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) 422 { 423 if (ctx->tmp_len > 0) 424 { 425 OPENSSL_assert(ctx->tmp_len <= 3); 426 n=3-ctx->tmp_len; 427 /* There's a theoretical possibility for this */ 428 if (n > inl) 429 n=inl; 430 memcpy(&(ctx->tmp[ctx->tmp_len]),in,n); 431 ctx->tmp_len+=n; 432 ret += n; 433 if (ctx->tmp_len < 3) 434 break; 435 ctx->buf_len=EVP_EncodeBlock((unsigned char *)ctx->buf,(unsigned char *)ctx->tmp,ctx->tmp_len); 436 OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf)); 437 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 438 /* Since we're now done using the temporary 439 buffer, the length should be 0'd */ 440 ctx->tmp_len=0; 441 } 442 else 443 { 444 if (n < 3) 445 { 446 memcpy(ctx->tmp,in,n); 447 ctx->tmp_len=n; 448 ret += n; 449 break; 450 } 451 n-=n%3; 452 ctx->buf_len=EVP_EncodeBlock((unsigned char *)ctx->buf,(const unsigned char *)in,n); 453 OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf)); 454 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 455 ret += n; 456 } 457 } 458 else 459 { 460 EVP_EncodeUpdate(&(ctx->base64), 461 (unsigned char *)ctx->buf,&ctx->buf_len, 462 (unsigned char *)in,n); 463 OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf)); 464 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 465 ret += n; 466 } 467 inl-=n; 468 in+=n; 469 470 ctx->buf_off=0; 471 n=ctx->buf_len; 472 while (n > 0) 473 { 474 i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n); 475 if (i <= 0) 476 { 477 BIO_copy_next_retry(b); 478 return((ret == 0)?i:ret); 479 } 480 OPENSSL_assert(i <= n); 481 n-=i; 482 ctx->buf_off+=i; 483 OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf)); 484 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 485 } 486 ctx->buf_len=0; 487 ctx->buf_off=0; 488 } 489 return(ret); 490 } 491 492 static long b64_ctrl(BIO *b, int cmd, long num, void *ptr) 493 { 494 BIO_B64_CTX *ctx; 495 long ret=1; 496 int i; 497 498 ctx=(BIO_B64_CTX *)b->ptr; 499 500 switch (cmd) 501 { 502 case BIO_CTRL_RESET: 503 ctx->cont=1; 504 ctx->start=1; 505 ctx->encode=B64_NONE; 506 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 507 break; 508 case BIO_CTRL_EOF: /* More to read */ 509 if (ctx->cont <= 0) 510 ret=1; 511 else 512 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 513 break; 514 case BIO_CTRL_WPENDING: /* More to write in buffer */ 515 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 516 ret=ctx->buf_len-ctx->buf_off; 517 if ((ret == 0) && (ctx->encode != B64_NONE) 518 && (ctx->base64.num != 0)) 519 ret=1; 520 else if (ret <= 0) 521 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 522 break; 523 case BIO_CTRL_PENDING: /* More to read in buffer */ 524 OPENSSL_assert(ctx->buf_len >= ctx->buf_off); 525 ret=ctx->buf_len-ctx->buf_off; 526 if (ret <= 0) 527 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 528 break; 529 case BIO_CTRL_FLUSH: 530 /* do a final write */ 531 again: 532 while (ctx->buf_len != ctx->buf_off) 533 { 534 i=b64_write(b,NULL,0); 535 if (i < 0) 536 return i; 537 } 538 if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) 539 { 540 if (ctx->tmp_len != 0) 541 { 542 ctx->buf_len=EVP_EncodeBlock( 543 (unsigned char *)ctx->buf, 544 (unsigned char *)ctx->tmp, 545 ctx->tmp_len); 546 ctx->buf_off=0; 547 ctx->tmp_len=0; 548 goto again; 549 } 550 } 551 else if (ctx->encode != B64_NONE && ctx->base64.num != 0) 552 { 553 ctx->buf_off=0; 554 EVP_EncodeFinal(&(ctx->base64), 555 (unsigned char *)ctx->buf, 556 &(ctx->buf_len)); 557 /* push out the bytes */ 558 goto again; 559 } 560 /* Finally flush the underlying BIO */ 561 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 562 break; 563 564 case BIO_C_DO_STATE_MACHINE: 565 BIO_clear_retry_flags(b); 566 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 567 BIO_copy_next_retry(b); 568 break; 569 570 case BIO_CTRL_DUP: 571 break; 572 case BIO_CTRL_INFO: 573 case BIO_CTRL_GET: 574 case BIO_CTRL_SET: 575 default: 576 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 577 break; 578 } 579 return(ret); 580 } 581 582 static long b64_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) 583 { 584 long ret=1; 585 586 if (b->next_bio == NULL) return(0); 587 switch (cmd) 588 { 589 default: 590 ret=BIO_callback_ctrl(b->next_bio,cmd,fp); 591 break; 592 } 593 return(ret); 594 } 595 596 static int b64_puts(BIO *b, const char *str) 597 { 598 return b64_write(b,str,strlen(str)); 599 }