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 62 63 static const unsigned char data_bin2ascii[65] = 64 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 65 66 #define conv_bin2ascii(a) (data_bin2ascii[(a) & 0x3f]) 67 68 /* 64 char lines 69 * pad input with 0 70 * left over chars are set to = 71 * 1 byte => xx== 72 * 2 bytes => xxx= 73 * 3 bytes => xxxx 74 */ 75 #define BIN_PER_LINE (64/4*3) 76 #define CHUNKS_PER_LINE (64/4) 77 #define CHAR_PER_LINE (64+1) 78 79 /* 0xF0 is a EOLN 80 * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing). 81 * 0xF2 is EOF 82 * 0xE0 is ignore at start of line. 83 * 0xFF is error */ 84 85 #define B64_EOLN 0xF0 86 #define B64_CR 0xF1 87 #define B64_EOF 0xF2 88 #define B64_WS 0xE0 89 #define B64_ERROR 0xFF 90 #define B64_NOT_BASE64(a) (((a) | 0x13) == 0xF3) 91 92 static const uint8_t data_ascii2bin[128] = { 93 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xF0, 0xFF, 94 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 95 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 96 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F, 97 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0xFF, 0xFF, 98 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 99 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 100 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 101 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 102 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 103 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 104 }; 105 106 static uint8_t conv_ascii2bin(uint8_t a) { 107 if (a >= 128) { 108 return 0xFF; 109 } 110 return data_ascii2bin[a]; 111 } 112 113 void EVP_EncodeInit(EVP_ENCODE_CTX *ctx) { 114 ctx->length = 48; 115 ctx->num = 0; 116 ctx->line_num = 0; 117 } 118 119 void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len, 120 const uint8_t *in, size_t in_len) { 121 unsigned i, j; 122 unsigned total = 0; 123 124 *out_len = 0; 125 if (in_len == 0) { 126 return; 127 } 128 129 assert(ctx->length <= sizeof(ctx->enc_data)); 130 131 if (ctx->num + in_len < ctx->length) { 132 memcpy(&ctx->enc_data[ctx->num], in, in_len); 133 ctx->num += in_len; 134 return; 135 } 136 if (ctx->num != 0) { 137 i = ctx->length - ctx->num; 138 memcpy(&ctx->enc_data[ctx->num], in, i); 139 in += i; 140 in_len -= i; 141 j = EVP_EncodeBlock(out, ctx->enc_data, ctx->length); 142 ctx->num = 0; 143 out += j; 144 *(out++) = '\n'; 145 *out = '\0'; 146 total = j + 1; 147 } 148 while (in_len >= ctx->length) { 149 j = EVP_EncodeBlock(out, in, ctx->length); 150 in += ctx->length; 151 in_len -= ctx->length; 152 out += j; 153 *(out++) = '\n'; 154 *out = '\0'; 155 total += j + 1; 156 } 157 if (in_len != 0) { 158 memcpy(&ctx->enc_data[0], in, in_len); 159 } 160 ctx->num = in_len; 161 *out_len = total; 162 } 163 164 void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) { 165 unsigned ret = 0; 166 167 if (ctx->num != 0) { 168 ret = EVP_EncodeBlock(out, ctx->enc_data, ctx->num); 169 out[ret++] = '\n'; 170 out[ret] = '\0'; 171 ctx->num = 0; 172 } 173 *out_len = ret; 174 } 175 176 size_t EVP_EncodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) { 177 uint32_t l; 178 size_t remaining = src_len, ret = 0; 179 180 while (remaining) { 181 if (remaining >= 3) { 182 l = (((uint32_t)src[0]) << 16L) | (((uint32_t)src[1]) << 8L) | src[2]; 183 *(dst++) = conv_bin2ascii(l >> 18L); 184 *(dst++) = conv_bin2ascii(l >> 12L); 185 *(dst++) = conv_bin2ascii(l >> 6L); 186 *(dst++) = conv_bin2ascii(l); 187 remaining -= 3; 188 } else { 189 l = ((uint32_t)src[0]) << 16L; 190 if (remaining == 2) { 191 l |= ((uint32_t)src[1] << 8L); 192 } 193 194 *(dst++) = conv_bin2ascii(l >> 18L); 195 *(dst++) = conv_bin2ascii(l >> 12L); 196 *(dst++) = (remaining == 1) ? '=' : conv_bin2ascii(l >> 6L); 197 *(dst++) = '='; 198 remaining = 0; 199 } 200 ret += 4; 201 src += 3; 202 } 203 204 *dst = '\0'; 205 return ret; 206 } 207 208 int EVP_DecodedLength(size_t *out_len, size_t len) { 209 if (len % 4 != 0) { 210 return 0; 211 } 212 *out_len = (len / 4) * 3; 213 return 1; 214 } 215 216 int EVP_DecodeBase64(uint8_t *out, size_t *out_len, size_t max_out, 217 const uint8_t *in, size_t in_len) { 218 uint8_t a, b, c, d; 219 size_t pad_len = 0, len = 0, max_len, i; 220 uint32_t l; 221 222 if (!EVP_DecodedLength(&max_len, in_len) || max_out < max_len) { 223 return 0; 224 } 225 226 for (i = 0; i < in_len; i += 4) { 227 a = conv_ascii2bin(*(in++)); 228 b = conv_ascii2bin(*(in++)); 229 if (i + 4 == in_len && in[1] == '=') { 230 if (in[0] == '=') { 231 pad_len = 2; 232 } else { 233 pad_len = 1; 234 } 235 } 236 if (pad_len < 2) { 237 c = conv_ascii2bin(*(in++)); 238 } else { 239 c = 0; 240 } 241 if (pad_len < 1) { 242 d = conv_ascii2bin(*(in++)); 243 } else { 244 d = 0; 245 } 246 if ((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80)) { 247 return 0; 248 } 249 l = ((((uint32_t)a) << 18L) | (((uint32_t)b) << 12L) | 250 (((uint32_t)c) << 6L) | (((uint32_t)d))); 251 *(out++) = (uint8_t)(l >> 16L) & 0xff; 252 if (pad_len < 2) { 253 *(out++) = (uint8_t)(l >> 8L) & 0xff; 254 } 255 if (pad_len < 1) { 256 *(out++) = (uint8_t)(l) & 0xff; 257 } 258 len += 3 - pad_len; 259 } 260 *out_len = len; 261 return 1; 262 } 263 264 void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) { 265 ctx->length = 30; 266 ctx->num = 0; 267 ctx->line_num = 0; 268 ctx->expect_nl = 0; 269 } 270 271 int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len, 272 const uint8_t *in, size_t in_len) { 273 int seof = -1, eof = 0, rv = -1, v, tmp, exp_nl; 274 uint8_t *d; 275 unsigned i, n, ln, ret = 0; 276 277 n = ctx->num; 278 d = ctx->enc_data; 279 ln = ctx->line_num; 280 exp_nl = ctx->expect_nl; 281 282 /* last line of input. */ 283 if (in_len == 0 || (n == 0 && conv_ascii2bin(in[0]) == B64_EOF)) { 284 rv = 0; 285 goto end; 286 } 287 288 /* We parse the input data */ 289 for (i = 0; i < in_len; i++) { 290 /* If the current line is > 80 characters, scream alot */ 291 if (ln >= 80) { 292 rv = -1; 293 goto end; 294 } 295 296 /* Get char and put it into the buffer */ 297 tmp = *(in++); 298 v = conv_ascii2bin(tmp); 299 /* only save the good data :-) */ 300 if (!B64_NOT_BASE64(v)) { 301 assert(n < sizeof(ctx->enc_data)); 302 d[n++] = tmp; 303 ln++; 304 } else if (v == B64_ERROR) { 305 rv = -1; 306 goto end; 307 } 308 309 /* have we seen a '=' which is 'definitly' the last 310 * input line. seof will point to the character that 311 * holds it. and eof will hold how many characters to 312 * chop off. */ 313 if (tmp == '=') { 314 if (seof == -1) { 315 seof = n; 316 } 317 eof++; 318 if (eof > 2) { 319 /* There are, at most, two equals signs at the end of base64 data. */ 320 rv = -1; 321 goto end; 322 } 323 } 324 325 if (v == B64_CR) { 326 ln = 0; 327 if (exp_nl) { 328 continue; 329 } 330 } 331 332 /* eoln */ 333 if (v == B64_EOLN) { 334 ln = 0; 335 if (exp_nl) { 336 exp_nl = 0; 337 continue; 338 } 339 } 340 exp_nl = 0; 341 342 /* If we are at the end of input and it looks like a 343 * line, process it. */ 344 if ((i + 1) == in_len && (((n & 3) == 0) || eof)) { 345 v = B64_EOF; 346 /* In case things were given us in really small 347 records (so two '=' were given in separate 348 updates), eof may contain the incorrect number 349 of ending bytes to skip, so let's redo the count */ 350 eof = 0; 351 if (d[n - 1] == '=') { 352 eof++; 353 } 354 if (d[n - 2] == '=') { 355 eof++; 356 } 357 /* There will never be more than two '=' */ 358 } 359 360 if ((v == B64_EOF && (n & 3) == 0) || n >= 64) { 361 /* This is needed to work correctly on 64 byte input 362 * lines. We process the line and then need to 363 * accept the '\n' */ 364 if (v != B64_EOF && n >= 64) { 365 exp_nl = 1; 366 } 367 if (n > 0) { 368 /* TODO(davidben): Switch this to EVP_DecodeBase64. */ 369 v = EVP_DecodeBlock(out, d, n); 370 n = 0; 371 if (v < 0) { 372 rv = 0; 373 goto end; 374 } 375 ret += (v - eof); 376 } else { 377 eof = 1; 378 v = 0; 379 } 380 381 /* This is the case where we have had a short 382 * but valid input line */ 383 if (v < (int)ctx->length && eof) { 384 rv = 0; 385 goto end; 386 } else { 387 ctx->length = v; 388 } 389 390 if (seof >= 0) { 391 rv = 0; 392 goto end; 393 } 394 out += v; 395 } 396 } 397 rv = 1; 398 399 end: 400 *out_len = ret; 401 ctx->num = n; 402 ctx->line_num = ln; 403 ctx->expect_nl = exp_nl; 404 return rv; 405 } 406 407 int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *outl) { 408 int i; 409 410 *outl = 0; 411 if (ctx->num != 0) { 412 /* TODO(davidben): Switch this to EVP_DecodeBase64. */ 413 i = EVP_DecodeBlock(out, ctx->enc_data, ctx->num); 414 if (i < 0) { 415 return -1; 416 } 417 ctx->num = 0; 418 *outl = i; 419 return 1; 420 } else { 421 return 1; 422 } 423 } 424 425 int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) { 426 size_t dst_len; 427 428 /* trim white space from the start of the line. */ 429 while (conv_ascii2bin(*src) == B64_WS && src_len > 0) { 430 src++; 431 src_len--; 432 } 433 434 /* strip off stuff at the end of the line 435 * ascii2bin values B64_WS, B64_EOLN, B64_EOLN and B64_EOF */ 436 while (src_len > 3 && B64_NOT_BASE64(conv_ascii2bin(src[src_len - 1]))) { 437 src_len--; 438 } 439 440 if (!EVP_DecodedLength(&dst_len, src_len) || dst_len > INT_MAX) { 441 return -1; 442 } 443 if (!EVP_DecodeBase64(dst, &dst_len, dst_len, src, src_len)) { 444 return -1; 445 } 446 447 /* EVP_DecodeBlock does not take padding into account, so put the 448 * NULs back in... so the caller can strip them back out. */ 449 while (dst_len % 3 != 0) { 450 dst[dst_len++] = '\0'; 451 } 452 assert(dst_len <= INT_MAX); 453 454 return dst_len; 455 } 456 457 int EVP_EncodedLength(size_t *out_len, size_t len) { 458 if (len + 2 < len) { 459 return 0; 460 } 461 len += 2; 462 len /= 3; 463 if (((len << 2) >> 2) != len) { 464 return 0; 465 } 466 len <<= 2; 467 if (len + 1 < len) { 468 return 0; 469 } 470 len++; 471 *out_len = len; 472 return 1; 473 } 474