1/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2 * All rights reserved. 3 * 4 * This package is an SSL implementation written 5 * by Eric Young (eay@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@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@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@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#include <openssl/type_check.h> 64 65#include "../internal.h" 66 67 68// constant_time_lt_args_8 behaves like |constant_time_lt_8| but takes |uint8_t| 69// arguments for a slightly simpler implementation. 70static inline uint8_t constant_time_lt_args_8(uint8_t a, uint8_t b) { 71 crypto_word_t aw = a; 72 crypto_word_t bw = b; 73 // |crypto_word_t| is larger than |uint8_t|, so |aw| and |bw| have the same 74 // MSB. |aw| < |bw| iff MSB(|aw| - |bw|) is 1. 75 return constant_time_msb_w(aw - bw); 76} 77 78// constant_time_in_range_8 returns |CONSTTIME_TRUE_8| if |min| <= |a| <= |max| 79// and |CONSTTIME_FALSE_8| otherwise. 80static inline uint8_t constant_time_in_range_8(uint8_t a, uint8_t min, 81 uint8_t max) { 82 a -= min; 83 return constant_time_lt_args_8(a, max - min + 1); 84} 85 86// Encoding. 87 88static uint8_t conv_bin2ascii(uint8_t a) { 89 // Since PEM is sometimes used to carry private keys, we encode base64 data 90 // itself in constant-time. 91 a &= 0x3f; 92 uint8_t ret = constant_time_select_8(constant_time_eq_8(a, 62), '+', '/'); 93 ret = 94 constant_time_select_8(constant_time_lt_args_8(a, 62), a - 52 + '0', ret); 95 ret = 96 constant_time_select_8(constant_time_lt_args_8(a, 52), a - 26 + 'a', ret); 97 ret = constant_time_select_8(constant_time_lt_args_8(a, 26), a + 'A', ret); 98 return ret; 99} 100 101OPENSSL_COMPILE_ASSERT(sizeof(((EVP_ENCODE_CTX *)(NULL))->data) % 3 == 0, 102 data_length_must_be_multiple_of_base64_chunk_size); 103 104int EVP_EncodedLength(size_t *out_len, size_t len) { 105 if (len + 2 < len) { 106 return 0; 107 } 108 len += 2; 109 len /= 3; 110 111 if (((len << 2) >> 2) != len) { 112 return 0; 113 } 114 len <<= 2; 115 116 if (len + 1 < len) { 117 return 0; 118 } 119 len++; 120 121 *out_len = len; 122 return 1; 123} 124 125void EVP_EncodeInit(EVP_ENCODE_CTX *ctx) { 126 OPENSSL_memset(ctx, 0, sizeof(EVP_ENCODE_CTX)); 127} 128 129void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len, 130 const uint8_t *in, size_t in_len) { 131 size_t total = 0; 132 133 *out_len = 0; 134 if (in_len == 0) { 135 return; 136 } 137 138 assert(ctx->data_used < sizeof(ctx->data)); 139 140 if (sizeof(ctx->data) - ctx->data_used > in_len) { 141 OPENSSL_memcpy(&ctx->data[ctx->data_used], in, in_len); 142 ctx->data_used += (unsigned)in_len; 143 return; 144 } 145 146 if (ctx->data_used != 0) { 147 const size_t todo = sizeof(ctx->data) - ctx->data_used; 148 OPENSSL_memcpy(&ctx->data[ctx->data_used], in, todo); 149 in += todo; 150 in_len -= todo; 151 152 size_t encoded = EVP_EncodeBlock(out, ctx->data, sizeof(ctx->data)); 153 ctx->data_used = 0; 154 155 out += encoded; 156 *(out++) = '\n'; 157 *out = '\0'; 158 159 total = encoded + 1; 160 } 161 162 while (in_len >= sizeof(ctx->data)) { 163 size_t encoded = EVP_EncodeBlock(out, in, sizeof(ctx->data)); 164 in += sizeof(ctx->data); 165 in_len -= sizeof(ctx->data); 166 167 out += encoded; 168 *(out++) = '\n'; 169 *out = '\0'; 170 171 if (total + encoded + 1 < total) { 172 *out_len = 0; 173 return; 174 } 175 176 total += encoded + 1; 177 } 178 179 if (in_len != 0) { 180 OPENSSL_memcpy(ctx->data, in, in_len); 181 } 182 183 ctx->data_used = (unsigned)in_len; 184 185 if (total > INT_MAX) { 186 // We cannot signal an error, but we can at least avoid making *out_len 187 // negative. 188 total = 0; 189 } 190 *out_len = (int)total; 191} 192 193void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) { 194 if (ctx->data_used == 0) { 195 *out_len = 0; 196 return; 197 } 198 199 size_t encoded = EVP_EncodeBlock(out, ctx->data, ctx->data_used); 200 out[encoded++] = '\n'; 201 out[encoded] = '\0'; 202 ctx->data_used = 0; 203 204 // ctx->data_used is bounded by sizeof(ctx->data), so this does not 205 // overflow. 206 assert(encoded <= INT_MAX); 207 *out_len = (int)encoded; 208} 209 210size_t EVP_EncodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) { 211 uint32_t l; 212 size_t remaining = src_len, ret = 0; 213 214 while (remaining) { 215 if (remaining >= 3) { 216 l = (((uint32_t)src[0]) << 16L) | (((uint32_t)src[1]) << 8L) | src[2]; 217 *(dst++) = conv_bin2ascii(l >> 18L); 218 *(dst++) = conv_bin2ascii(l >> 12L); 219 *(dst++) = conv_bin2ascii(l >> 6L); 220 *(dst++) = conv_bin2ascii(l); 221 remaining -= 3; 222 } else { 223 l = ((uint32_t)src[0]) << 16L; 224 if (remaining == 2) { 225 l |= ((uint32_t)src[1] << 8L); 226 } 227 228 *(dst++) = conv_bin2ascii(l >> 18L); 229 *(dst++) = conv_bin2ascii(l >> 12L); 230 *(dst++) = (remaining == 1) ? '=' : conv_bin2ascii(l >> 6L); 231 *(dst++) = '='; 232 remaining = 0; 233 } 234 ret += 4; 235 src += 3; 236 } 237 238 *dst = '\0'; 239 return ret; 240} 241 242 243// Decoding. 244 245int EVP_DecodedLength(size_t *out_len, size_t len) { 246 if (len % 4 != 0) { 247 return 0; 248 } 249 250 *out_len = (len / 4) * 3; 251 return 1; 252} 253 254void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) { 255 OPENSSL_memset(ctx, 0, sizeof(EVP_ENCODE_CTX)); 256} 257 258static uint8_t base64_ascii_to_bin(uint8_t a) { 259 // Since PEM is sometimes used to carry private keys, we decode base64 data 260 // itself in constant-time. 261 const uint8_t is_upper = constant_time_in_range_8(a, 'A', 'Z'); 262 const uint8_t is_lower = constant_time_in_range_8(a, 'a', 'z'); 263 const uint8_t is_digit = constant_time_in_range_8(a, '0', '9'); 264 const uint8_t is_plus = constant_time_eq_8(a, '+'); 265 const uint8_t is_slash = constant_time_eq_8(a, '/'); 266 const uint8_t is_equals = constant_time_eq_8(a, '='); 267 268 uint8_t ret = 0xff; // 0xff signals invalid. 269 ret = constant_time_select_8(is_upper, a - 'A', ret); // [0,26) 270 ret = constant_time_select_8(is_lower, a - 'a' + 26, ret); // [26,52) 271 ret = constant_time_select_8(is_digit, a - '0' + 52, ret); // [52,62) 272 ret = constant_time_select_8(is_plus, 62, ret); 273 ret = constant_time_select_8(is_slash, 63, ret); 274 // Padding maps to zero, to be further handled by the caller. 275 ret = constant_time_select_8(is_equals, 0, ret); 276 return ret; 277} 278 279// base64_decode_quad decodes a single “quad” (i.e. four characters) of base64 280// data and writes up to three bytes to |out|. It sets |*out_num_bytes| to the 281// number of bytes written, which will be less than three if the quad ended 282// with padding. It returns one on success or zero on error. 283static int base64_decode_quad(uint8_t *out, size_t *out_num_bytes, 284 const uint8_t *in) { 285 const uint8_t a = base64_ascii_to_bin(in[0]); 286 const uint8_t b = base64_ascii_to_bin(in[1]); 287 const uint8_t c = base64_ascii_to_bin(in[2]); 288 const uint8_t d = base64_ascii_to_bin(in[3]); 289 if (a == 0xff || b == 0xff || c == 0xff || d == 0xff) { 290 return 0; 291 } 292 293 const uint32_t v = ((uint32_t)a) << 18 | ((uint32_t)b) << 12 | 294 ((uint32_t)c) << 6 | (uint32_t)d; 295 296 const unsigned padding_pattern = (in[0] == '=') << 3 | 297 (in[1] == '=') << 2 | 298 (in[2] == '=') << 1 | 299 (in[3] == '='); 300 301 switch (padding_pattern) { 302 case 0: 303 // The common case of no padding. 304 *out_num_bytes = 3; 305 out[0] = v >> 16; 306 out[1] = v >> 8; 307 out[2] = v; 308 break; 309 310 case 1: // xxx= 311 *out_num_bytes = 2; 312 out[0] = v >> 16; 313 out[1] = v >> 8; 314 break; 315 316 case 3: // xx== 317 *out_num_bytes = 1; 318 out[0] = v >> 16; 319 break; 320 321 default: 322 return 0; 323 } 324 325 return 1; 326} 327 328int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len, 329 const uint8_t *in, size_t in_len) { 330 *out_len = 0; 331 332 if (ctx->error_encountered) { 333 return -1; 334 } 335 336 size_t bytes_out = 0, i; 337 for (i = 0; i < in_len; i++) { 338 const char c = in[i]; 339 switch (c) { 340 case ' ': 341 case '\t': 342 case '\r': 343 case '\n': 344 continue; 345 } 346 347 if (ctx->eof_seen) { 348 ctx->error_encountered = 1; 349 return -1; 350 } 351 352 ctx->data[ctx->data_used++] = c; 353 if (ctx->data_used == 4) { 354 size_t num_bytes_resulting; 355 if (!base64_decode_quad(out, &num_bytes_resulting, ctx->data)) { 356 ctx->error_encountered = 1; 357 return -1; 358 } 359 360 ctx->data_used = 0; 361 bytes_out += num_bytes_resulting; 362 out += num_bytes_resulting; 363 364 if (num_bytes_resulting < 3) { 365 ctx->eof_seen = 1; 366 } 367 } 368 } 369 370 if (bytes_out > INT_MAX) { 371 ctx->error_encountered = 1; 372 *out_len = 0; 373 return -1; 374 } 375 *out_len = (int)bytes_out; 376 377 if (ctx->eof_seen) { 378 return 0; 379 } 380 381 return 1; 382} 383 384int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) { 385 *out_len = 0; 386 if (ctx->error_encountered || ctx->data_used != 0) { 387 return -1; 388 } 389 390 return 1; 391} 392 393int EVP_DecodeBase64(uint8_t *out, size_t *out_len, size_t max_out, 394 const uint8_t *in, size_t in_len) { 395 *out_len = 0; 396 397 if (in_len % 4 != 0) { 398 return 0; 399 } 400 401 size_t max_len; 402 if (!EVP_DecodedLength(&max_len, in_len) || 403 max_out < max_len) { 404 return 0; 405 } 406 407 size_t i, bytes_out = 0; 408 for (i = 0; i < in_len; i += 4) { 409 size_t num_bytes_resulting; 410 411 if (!base64_decode_quad(out, &num_bytes_resulting, &in[i])) { 412 return 0; 413 } 414 415 bytes_out += num_bytes_resulting; 416 out += num_bytes_resulting; 417 if (num_bytes_resulting != 3 && i != in_len - 4) { 418 return 0; 419 } 420 } 421 422 *out_len = bytes_out; 423 return 1; 424} 425 426int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) { 427 // Trim spaces and tabs from the beginning of the input. 428 while (src_len > 0) { 429 if (src[0] != ' ' && src[0] != '\t') { 430 break; 431 } 432 433 src++; 434 src_len--; 435 } 436 437 // Trim newlines, spaces and tabs from the end of the line. 438 while (src_len > 0) { 439 switch (src[src_len-1]) { 440 case ' ': 441 case '\t': 442 case '\r': 443 case '\n': 444 src_len--; 445 continue; 446 } 447 448 break; 449 } 450 451 size_t dst_len; 452 if (!EVP_DecodedLength(&dst_len, src_len) || 453 dst_len > INT_MAX || 454 !EVP_DecodeBase64(dst, &dst_len, dst_len, src, src_len)) { 455 return -1; 456 } 457 458 // EVP_DecodeBlock does not take padding into account, so put the 459 // NULs back in... so the caller can strip them back out. 460 while (dst_len % 3 != 0) { 461 dst[dst_len++] = '\0'; 462 } 463 assert(dst_len <= INT_MAX); 464 465 return (int)dst_len; 466} 467