1 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com) 2 * All rights reserved. 3 * 4 * This package is an SSL implementation written 5 * by Eric Young (eay (at) cryptsoft.com). 6 * The implementation was written so as to conform with Netscapes SSL. 7 * 8 * This library is free for commercial and non-commercial use as long as 9 * the following conditions are aheared to. The following conditions 10 * apply to all code found in this distribution, be it the RC4, RSA, 11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 12 * included with this distribution is covered by the same copyright terms 13 * except that the holder is Tim Hudson (tjh (at) cryptsoft.com). 14 * 15 * Copyright remains Eric Young's, and as such any Copyright notices in 16 * the code are not to be removed. 17 * If this package is used in a product, Eric Young should be given attribution 18 * as the author of the parts of the library used. 19 * This can be in the form of a textual message at program startup or 20 * in documentation (online or textual) provided with the package. 21 * 22 * Redistribution and use in source and binary forms, with or without 23 * modification, are permitted provided that the following conditions 24 * are met: 25 * 1. Redistributions of source code must retain the copyright 26 * notice, this list of conditions and the following disclaimer. 27 * 2. Redistributions in binary form must reproduce the above copyright 28 * notice, this list of conditions and the following disclaimer in the 29 * documentation and/or other materials provided with the distribution. 30 * 3. All advertising materials mentioning features or use of this software 31 * must display the following acknowledgement: 32 * "This product includes cryptographic software written by 33 * Eric Young (eay (at) cryptsoft.com)" 34 * The word 'cryptographic' can be left out if the rouines from the library 35 * being used are not cryptographic related :-). 36 * 4. If you include any Windows specific code (or a derivative thereof) from 37 * the apps directory (application code) you must include an acknowledgement: 38 * "This product includes software written by Tim Hudson (tjh (at) cryptsoft.com)" 39 * 40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 50 * SUCH DAMAGE. 51 * 52 * The licence and distribution terms for any publically available version or 53 * derivative of this code cannot be changed. i.e. this code cannot simply be 54 * copied and put under another distribution licence 55 * [including the GNU Public Licence.] */ 56 57 #include <openssl/base64.h> 58 59 #include <assert.h> 60 #include <limits.h> 61 #include <string.h> 62 63 64 static const unsigned char data_bin2ascii[65] = 65 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 66 67 #define conv_bin2ascii(a) (data_bin2ascii[(a) & 0x3f]) 68 69 /* 64 char lines 70 * pad input with 0 71 * left over chars are set to = 72 * 1 byte => xx== 73 * 2 bytes => xxx= 74 * 3 bytes => xxxx 75 */ 76 #define BIN_PER_LINE (64/4*3) 77 #define CHUNKS_PER_LINE (64/4) 78 #define CHAR_PER_LINE (64+1) 79 80 /* 0xF0 is a EOLN 81 * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing). 82 * 0xF2 is EOF 83 * 0xE0 is ignore at start of line. 84 * 0xFF is error */ 85 86 #define B64_EOLN 0xF0 87 #define B64_CR 0xF1 88 #define B64_EOF 0xF2 89 #define B64_WS 0xE0 90 #define B64_ERROR 0xFF 91 #define B64_NOT_BASE64(a) (((a) | 0x13) == 0xF3) 92 93 static const uint8_t data_ascii2bin[128] = { 94 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xF0, 0xFF, 95 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 96 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 97 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F, 98 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0xFF, 0xFF, 99 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 100 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 101 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 102 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 103 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 104 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 105 }; 106 107 static uint8_t conv_ascii2bin(uint8_t a) { 108 if (a >= 128) { 109 return 0xFF; 110 } 111 return data_ascii2bin[a]; 112 } 113 114 void EVP_EncodeInit(EVP_ENCODE_CTX *ctx) { 115 ctx->length = 48; 116 ctx->num = 0; 117 ctx->line_num = 0; 118 } 119 120 void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len, 121 const uint8_t *in, size_t in_len) { 122 unsigned i, j; 123 unsigned total = 0; 124 125 *out_len = 0; 126 if (in_len == 0) { 127 return; 128 } 129 130 assert(ctx->length <= sizeof(ctx->enc_data)); 131 132 if (ctx->num + in_len < ctx->length) { 133 memcpy(&ctx->enc_data[ctx->num], in, in_len); 134 ctx->num += in_len; 135 return; 136 } 137 if (ctx->num != 0) { 138 i = ctx->length - ctx->num; 139 memcpy(&ctx->enc_data[ctx->num], in, i); 140 in += i; 141 in_len -= i; 142 j = EVP_EncodeBlock(out, ctx->enc_data, ctx->length); 143 ctx->num = 0; 144 out += j; 145 *(out++) = '\n'; 146 *out = '\0'; 147 total = j + 1; 148 } 149 while (in_len >= ctx->length) { 150 j = EVP_EncodeBlock(out, in, ctx->length); 151 in += ctx->length; 152 in_len -= ctx->length; 153 out += j; 154 *(out++) = '\n'; 155 *out = '\0'; 156 total += j + 1; 157 } 158 if (in_len != 0) { 159 memcpy(&ctx->enc_data[0], in, in_len); 160 } 161 ctx->num = in_len; 162 *out_len = total; 163 } 164 165 void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) { 166 unsigned ret = 0; 167 168 if (ctx->num != 0) { 169 ret = EVP_EncodeBlock(out, ctx->enc_data, ctx->num); 170 out[ret++] = '\n'; 171 out[ret] = '\0'; 172 ctx->num = 0; 173 } 174 *out_len = ret; 175 } 176 177 size_t EVP_EncodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) { 178 uint32_t l; 179 size_t remaining = src_len, ret = 0; 180 181 while (remaining) { 182 if (remaining >= 3) { 183 l = (((uint32_t)src[0]) << 16L) | (((uint32_t)src[1]) << 8L) | src[2]; 184 *(dst++) = conv_bin2ascii(l >> 18L); 185 *(dst++) = conv_bin2ascii(l >> 12L); 186 *(dst++) = conv_bin2ascii(l >> 6L); 187 *(dst++) = conv_bin2ascii(l); 188 remaining -= 3; 189 } else { 190 l = ((uint32_t)src[0]) << 16L; 191 if (remaining == 2) { 192 l |= ((uint32_t)src[1] << 8L); 193 } 194 195 *(dst++) = conv_bin2ascii(l >> 18L); 196 *(dst++) = conv_bin2ascii(l >> 12L); 197 *(dst++) = (remaining == 1) ? '=' : conv_bin2ascii(l >> 6L); 198 *(dst++) = '='; 199 remaining = 0; 200 } 201 ret += 4; 202 src += 3; 203 } 204 205 *dst = '\0'; 206 return ret; 207 } 208 209 int EVP_DecodedLength(size_t *out_len, size_t len) { 210 if (len % 4 != 0) { 211 return 0; 212 } 213 *out_len = (len / 4) * 3; 214 return 1; 215 } 216 217 int EVP_DecodeBase64(uint8_t *out, size_t *out_len, size_t max_out, 218 const uint8_t *in, size_t in_len) { 219 uint8_t a, b, c, d; 220 size_t pad_len = 0, len = 0, max_len, i; 221 uint32_t l; 222 223 if (!EVP_DecodedLength(&max_len, in_len) || max_out < max_len) { 224 return 0; 225 } 226 227 for (i = 0; i < in_len; i += 4) { 228 a = conv_ascii2bin(*(in++)); 229 b = conv_ascii2bin(*(in++)); 230 if (i + 4 == in_len && in[1] == '=') { 231 if (in[0] == '=') { 232 pad_len = 2; 233 } else { 234 pad_len = 1; 235 } 236 } 237 if (pad_len < 2) { 238 c = conv_ascii2bin(*(in++)); 239 } else { 240 c = 0; 241 } 242 if (pad_len < 1) { 243 d = conv_ascii2bin(*(in++)); 244 } else { 245 d = 0; 246 } 247 if ((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80)) { 248 return 0; 249 } 250 l = ((((uint32_t)a) << 18L) | (((uint32_t)b) << 12L) | 251 (((uint32_t)c) << 6L) | (((uint32_t)d))); 252 *(out++) = (uint8_t)(l >> 16L) & 0xff; 253 if (pad_len < 2) { 254 *(out++) = (uint8_t)(l >> 8L) & 0xff; 255 } 256 if (pad_len < 1) { 257 *(out++) = (uint8_t)(l) & 0xff; 258 } 259 len += 3 - pad_len; 260 } 261 *out_len = len; 262 return 1; 263 } 264 265 void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) { 266 ctx->length = 30; 267 ctx->num = 0; 268 ctx->line_num = 0; 269 ctx->expect_nl = 0; 270 } 271 272 int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len, 273 const uint8_t *in, size_t in_len) { 274 int seof = -1, eof = 0, rv = -1, v, tmp, exp_nl; 275 uint8_t *d; 276 unsigned i, n, ln, ret = 0; 277 278 n = ctx->num; 279 d = ctx->enc_data; 280 ln = ctx->line_num; 281 exp_nl = ctx->expect_nl; 282 283 /* last line of input. */ 284 if (in_len == 0 || (n == 0 && conv_ascii2bin(in[0]) == B64_EOF)) { 285 rv = 0; 286 goto end; 287 } 288 289 /* We parse the input data */ 290 for (i = 0; i < in_len; i++) { 291 /* If the current line is > 80 characters, scream alot */ 292 if (ln >= 80) { 293 rv = -1; 294 goto end; 295 } 296 297 /* Get char and put it into the buffer */ 298 tmp = *(in++); 299 v = conv_ascii2bin(tmp); 300 /* only save the good data :-) */ 301 if (!B64_NOT_BASE64(v)) { 302 assert(n < sizeof(ctx->enc_data)); 303 d[n++] = tmp; 304 ln++; 305 } else if (v == B64_ERROR) { 306 rv = -1; 307 goto end; 308 } 309 310 /* have we seen a '=' which is 'definitly' the last 311 * input line. seof will point to the character that 312 * holds it. and eof will hold how many characters to 313 * chop off. */ 314 if (tmp == '=') { 315 if (seof == -1) { 316 seof = n; 317 } 318 eof++; 319 if (eof > 2) { 320 /* There are, at most, two equals signs at the end of base64 data. */ 321 rv = -1; 322 goto end; 323 } 324 } 325 326 if (v == B64_CR) { 327 ln = 0; 328 if (exp_nl) { 329 continue; 330 } 331 } 332 333 /* eoln */ 334 if (v == B64_EOLN) { 335 ln = 0; 336 if (exp_nl) { 337 exp_nl = 0; 338 continue; 339 } 340 } 341 exp_nl = 0; 342 343 /* If we are at the end of input and it looks like a 344 * line, process it. */ 345 if ((i + 1) == in_len && (((n & 3) == 0) || eof)) { 346 v = B64_EOF; 347 /* In case things were given us in really small 348 records (so two '=' were given in separate 349 updates), eof may contain the incorrect number 350 of ending bytes to skip, so let's redo the count */ 351 eof = 0; 352 if (d[n - 1] == '=') { 353 eof++; 354 } 355 if (d[n - 2] == '=') { 356 eof++; 357 } 358 /* There will never be more than two '=' */ 359 } 360 361 if ((v == B64_EOF && (n & 3) == 0) || n >= 64) { 362 /* This is needed to work correctly on 64 byte input 363 * lines. We process the line and then need to 364 * accept the '\n' */ 365 if (v != B64_EOF && n >= 64) { 366 exp_nl = 1; 367 } 368 if (n > 0) { 369 /* TODO(davidben): Switch this to EVP_DecodeBase64. */ 370 v = EVP_DecodeBlock(out, d, n); 371 n = 0; 372 if (v < 0) { 373 rv = 0; 374 goto end; 375 } 376 if (eof > v) { 377 rv = -1; 378 goto end; 379 } 380 ret += (v - eof); 381 } else { 382 eof = 1; 383 v = 0; 384 } 385 386 /* This is the case where we have had a short 387 * but valid input line */ 388 if (v < (int)ctx->length && eof) { 389 rv = 0; 390 goto end; 391 } else { 392 ctx->length = v; 393 } 394 395 if (seof >= 0) { 396 rv = 0; 397 goto end; 398 } 399 out += v; 400 } 401 } 402 rv = 1; 403 404 end: 405 *out_len = ret; 406 ctx->num = n; 407 ctx->line_num = ln; 408 ctx->expect_nl = exp_nl; 409 return rv; 410 } 411 412 int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *outl) { 413 int i; 414 415 *outl = 0; 416 if (ctx->num != 0) { 417 /* TODO(davidben): Switch this to EVP_DecodeBase64. */ 418 i = EVP_DecodeBlock(out, ctx->enc_data, ctx->num); 419 if (i < 0) { 420 return -1; 421 } 422 ctx->num = 0; 423 *outl = i; 424 return 1; 425 } else { 426 return 1; 427 } 428 } 429 430 int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) { 431 size_t dst_len; 432 433 /* trim white space from the start of the line. */ 434 while (conv_ascii2bin(*src) == B64_WS && src_len > 0) { 435 src++; 436 src_len--; 437 } 438 439 /* strip off stuff at the end of the line 440 * ascii2bin values B64_WS, B64_EOLN, B64_EOLN and B64_EOF */ 441 while (src_len > 3 && B64_NOT_BASE64(conv_ascii2bin(src[src_len - 1]))) { 442 src_len--; 443 } 444 445 if (!EVP_DecodedLength(&dst_len, src_len) || dst_len > INT_MAX) { 446 return -1; 447 } 448 if (!EVP_DecodeBase64(dst, &dst_len, dst_len, src, src_len)) { 449 return -1; 450 } 451 452 /* EVP_DecodeBlock does not take padding into account, so put the 453 * NULs back in... so the caller can strip them back out. */ 454 while (dst_len % 3 != 0) { 455 dst[dst_len++] = '\0'; 456 } 457 assert(dst_len <= INT_MAX); 458 459 return dst_len; 460 } 461 462 int EVP_EncodedLength(size_t *out_len, size_t len) { 463 if (len + 2 < len) { 464 return 0; 465 } 466 len += 2; 467 len /= 3; 468 if (((len << 2) >> 2) != len) { 469 return 0; 470 } 471 len <<= 2; 472 if (len + 1 < len) { 473 return 0; 474 } 475 len++; 476 *out_len = len; 477 return 1; 478 } 479