base64.c
Go to the documentation of this file.
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.
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.
81  uint8_t max) {
82  a -= min;
83  return constant_time_lt_args_8(a, max - min + 1);
84 }
85 
86 // Encoding.
87 
89  // Since PEM is sometimes used to carry private keys, we encode base64 data
90  // itself in constant-time.
91  a &= 0x3f;
93  ret =
95  ret =
98  return ret;
99 }
100 
101 OPENSSL_STATIC_ASSERT(sizeof(((EVP_ENCODE_CTX *)(NULL))->data) % 3 == 0,
102  "data length must be a multiple of base64 chunk size");
103 
104 int 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 
127  if (ret == NULL) {
128  return NULL;
129  }
130  OPENSSL_memset(ret, 0, sizeof(EVP_ENCODE_CTX));
131  return ret;
132 }
133 
135  OPENSSL_free(ctx);
136 }
137 
139  OPENSSL_memset(ctx, 0, sizeof(EVP_ENCODE_CTX));
140 }
141 
143  const uint8_t *in, size_t in_len) {
144  size_t total = 0;
145 
146  *out_len = 0;
147  if (in_len == 0) {
148  return;
149  }
150 
151  assert(ctx->data_used < sizeof(ctx->data));
152 
153  if (sizeof(ctx->data) - ctx->data_used > in_len) {
154  OPENSSL_memcpy(&ctx->data[ctx->data_used], in, in_len);
155  ctx->data_used += (unsigned)in_len;
156  return;
157  }
158 
159  if (ctx->data_used != 0) {
160  const size_t todo = sizeof(ctx->data) - ctx->data_used;
161  OPENSSL_memcpy(&ctx->data[ctx->data_used], in, todo);
162  in += todo;
163  in_len -= todo;
164 
165  size_t encoded = EVP_EncodeBlock(out, ctx->data, sizeof(ctx->data));
166  ctx->data_used = 0;
167 
168  out += encoded;
169  *(out++) = '\n';
170  *out = '\0';
171 
172  total = encoded + 1;
173  }
174 
175  while (in_len >= sizeof(ctx->data)) {
176  size_t encoded = EVP_EncodeBlock(out, in, sizeof(ctx->data));
177  in += sizeof(ctx->data);
178  in_len -= sizeof(ctx->data);
179 
180  out += encoded;
181  *(out++) = '\n';
182  *out = '\0';
183 
184  if (total + encoded + 1 < total) {
185  *out_len = 0;
186  return;
187  }
188 
189  total += encoded + 1;
190  }
191 
192  if (in_len != 0) {
193  OPENSSL_memcpy(ctx->data, in, in_len);
194  }
195 
196  ctx->data_used = (unsigned)in_len;
197 
198  if (total > INT_MAX) {
199  // We cannot signal an error, but we can at least avoid making *out_len
200  // negative.
201  total = 0;
202  }
203  *out_len = (int)total;
204 }
205 
206 void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) {
207  if (ctx->data_used == 0) {
208  *out_len = 0;
209  return;
210  }
211 
212  size_t encoded = EVP_EncodeBlock(out, ctx->data, ctx->data_used);
213  out[encoded++] = '\n';
214  out[encoded] = '\0';
215  ctx->data_used = 0;
216 
217  // ctx->data_used is bounded by sizeof(ctx->data), so this does not
218  // overflow.
219  assert(encoded <= INT_MAX);
220  *out_len = (int)encoded;
221 }
222 
223 size_t EVP_EncodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
224  uint32_t l;
225  size_t remaining = src_len, ret = 0;
226 
227  while (remaining) {
228  if (remaining >= 3) {
229  l = (((uint32_t)src[0]) << 16L) | (((uint32_t)src[1]) << 8L) | src[2];
230  *(dst++) = conv_bin2ascii(l >> 18L);
231  *(dst++) = conv_bin2ascii(l >> 12L);
232  *(dst++) = conv_bin2ascii(l >> 6L);
233  *(dst++) = conv_bin2ascii(l);
234  remaining -= 3;
235  } else {
236  l = ((uint32_t)src[0]) << 16L;
237  if (remaining == 2) {
238  l |= ((uint32_t)src[1] << 8L);
239  }
240 
241  *(dst++) = conv_bin2ascii(l >> 18L);
242  *(dst++) = conv_bin2ascii(l >> 12L);
243  *(dst++) = (remaining == 1) ? '=' : conv_bin2ascii(l >> 6L);
244  *(dst++) = '=';
245  remaining = 0;
246  }
247  ret += 4;
248  src += 3;
249  }
250 
251  *dst = '\0';
252  return ret;
253 }
254 
255 
256 // Decoding.
257 
258 int EVP_DecodedLength(size_t *out_len, size_t len) {
259  if (len % 4 != 0) {
260  return 0;
261  }
262 
263  *out_len = (len / 4) * 3;
264  return 1;
265 }
266 
268  OPENSSL_memset(ctx, 0, sizeof(EVP_ENCODE_CTX));
269 }
270 
272  // Since PEM is sometimes used to carry private keys, we decode base64 data
273  // itself in constant-time.
274  const uint8_t is_upper = constant_time_in_range_8(a, 'A', 'Z');
275  const uint8_t is_lower = constant_time_in_range_8(a, 'a', 'z');
276  const uint8_t is_digit = constant_time_in_range_8(a, '0', '9');
277  const uint8_t is_plus = constant_time_eq_8(a, '+');
278  const uint8_t is_slash = constant_time_eq_8(a, '/');
279  const uint8_t is_equals = constant_time_eq_8(a, '=');
280 
281  uint8_t ret = 0;
282  ret |= is_upper & (a - 'A'); // [0,26)
283  ret |= is_lower & (a - 'a' + 26); // [26,52)
284  ret |= is_digit & (a - '0' + 52); // [52,62)
285  ret |= is_plus & 62;
286  ret |= is_slash & 63;
287  // Invalid inputs, 'A', and '=' have all been mapped to zero. Map invalid
288  // inputs to 0xff. Note '=' is padding and handled separately by the caller.
289  const uint8_t is_valid =
290  is_upper | is_lower | is_digit | is_plus | is_slash | is_equals;
291  ret |= ~is_valid;
292  return ret;
293 }
294 
295 // base64_decode_quad decodes a single “quad” (i.e. four characters) of base64
296 // data and writes up to three bytes to |out|. It sets |*out_num_bytes| to the
297 // number of bytes written, which will be less than three if the quad ended
298 // with padding. It returns one on success or zero on error.
299 static int base64_decode_quad(uint8_t *out, size_t *out_num_bytes,
300  const uint8_t *in) {
301  const uint8_t a = base64_ascii_to_bin(in[0]);
302  const uint8_t b = base64_ascii_to_bin(in[1]);
303  const uint8_t c = base64_ascii_to_bin(in[2]);
304  const uint8_t d = base64_ascii_to_bin(in[3]);
305  if (a == 0xff || b == 0xff || c == 0xff || d == 0xff) {
306  return 0;
307  }
308 
309  const uint32_t v = ((uint32_t)a) << 18 | ((uint32_t)b) << 12 |
310  ((uint32_t)c) << 6 | (uint32_t)d;
311 
312  const unsigned padding_pattern = (in[0] == '=') << 3 |
313  (in[1] == '=') << 2 |
314  (in[2] == '=') << 1 |
315  (in[3] == '=');
316 
317  switch (padding_pattern) {
318  case 0:
319  // The common case of no padding.
320  *out_num_bytes = 3;
321  out[0] = v >> 16;
322  out[1] = v >> 8;
323  out[2] = v;
324  break;
325 
326  case 1: // xxx=
327  *out_num_bytes = 2;
328  out[0] = v >> 16;
329  out[1] = v >> 8;
330  break;
331 
332  case 3: // xx==
333  *out_num_bytes = 1;
334  out[0] = v >> 16;
335  break;
336 
337  default:
338  return 0;
339  }
340 
341  return 1;
342 }
343 
345  const uint8_t *in, size_t in_len) {
346  *out_len = 0;
347 
348  if (ctx->error_encountered) {
349  return -1;
350  }
351 
352  size_t bytes_out = 0, i;
353  for (i = 0; i < in_len; i++) {
354  const char c = in[i];
355  switch (c) {
356  case ' ':
357  case '\t':
358  case '\r':
359  case '\n':
360  continue;
361  }
362 
363  if (ctx->eof_seen) {
364  ctx->error_encountered = 1;
365  return -1;
366  }
367 
368  ctx->data[ctx->data_used++] = c;
369  if (ctx->data_used == 4) {
370  size_t num_bytes_resulting;
371  if (!base64_decode_quad(out, &num_bytes_resulting, ctx->data)) {
372  ctx->error_encountered = 1;
373  return -1;
374  }
375 
376  ctx->data_used = 0;
377  bytes_out += num_bytes_resulting;
378  out += num_bytes_resulting;
379 
380  if (num_bytes_resulting < 3) {
381  ctx->eof_seen = 1;
382  }
383  }
384  }
385 
386  if (bytes_out > INT_MAX) {
387  ctx->error_encountered = 1;
388  *out_len = 0;
389  return -1;
390  }
391  *out_len = (int)bytes_out;
392 
393  if (ctx->eof_seen) {
394  return 0;
395  }
396 
397  return 1;
398 }
399 
401  *out_len = 0;
402  if (ctx->error_encountered || ctx->data_used != 0) {
403  return -1;
404  }
405 
406  return 1;
407 }
408 
409 int EVP_DecodeBase64(uint8_t *out, size_t *out_len, size_t max_out,
410  const uint8_t *in, size_t in_len) {
411  *out_len = 0;
412 
413  if (in_len % 4 != 0) {
414  return 0;
415  }
416 
417  size_t max_len;
418  if (!EVP_DecodedLength(&max_len, in_len) ||
419  max_out < max_len) {
420  return 0;
421  }
422 
423  size_t i, bytes_out = 0;
424  for (i = 0; i < in_len; i += 4) {
425  size_t num_bytes_resulting;
426 
427  if (!base64_decode_quad(out, &num_bytes_resulting, &in[i])) {
428  return 0;
429  }
430 
431  bytes_out += num_bytes_resulting;
432  out += num_bytes_resulting;
433  if (num_bytes_resulting != 3 && i != in_len - 4) {
434  return 0;
435  }
436  }
437 
438  *out_len = bytes_out;
439  return 1;
440 }
441 
442 int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
443  // Trim spaces and tabs from the beginning of the input.
444  while (src_len > 0) {
445  if (src[0] != ' ' && src[0] != '\t') {
446  break;
447  }
448 
449  src++;
450  src_len--;
451  }
452 
453  // Trim newlines, spaces and tabs from the end of the line.
454  while (src_len > 0) {
455  switch (src[src_len-1]) {
456  case ' ':
457  case '\t':
458  case '\r':
459  case '\n':
460  src_len--;
461  continue;
462  }
463 
464  break;
465  }
466 
467  size_t dst_len;
468  if (!EVP_DecodedLength(&dst_len, src_len) ||
469  dst_len > INT_MAX ||
470  !EVP_DecodeBase64(dst, &dst_len, dst_len, src, src_len)) {
471  return -1;
472  }
473 
474  // EVP_DecodeBlock does not take padding into account, so put the
475  // NULs back in... so the caller can strip them back out.
476  while (dst_len % 3 != 0) {
477  dst[dst_len++] = '\0';
478  }
479  assert(dst_len <= INT_MAX);
480 
481  return (int)dst_len;
482 }
base64_decode_quad
static int base64_decode_quad(uint8_t *out, size_t *out_num_bytes, const uint8_t *in)
Definition: base64.c:299
dst
static const char dst[]
Definition: test-fs-copyfile.c:37
gen_build_yaml.out
dictionary out
Definition: src/benchmark/gen_build_yaml.py:24
EVP_DecodeFinal
int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len)
Definition: base64.c:400
EVP_EncodeFinal
void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len)
Definition: base64.c:206
ctx
Definition: benchmark-async.c:30
constant_time_lt_args_8
static uint8_t constant_time_lt_args_8(uint8_t a, uint8_t b)
Definition: base64.c:70
EVP_DecodeInit
void EVP_DecodeInit(EVP_ENCODE_CTX *ctx)
Definition: base64.c:267
total
size_t total
Definition: cord_analysis.cc:59
string.h
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
base64_ascii_to_bin
static uint8_t base64_ascii_to_bin(uint8_t a)
Definition: base64.c:271
EVP_DecodedLength
int EVP_DecodedLength(size_t *out_len, size_t len)
Definition: base64.c:258
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
OPENSSL_memset
static void * OPENSSL_memset(void *dst, int c, size_t n)
Definition: third_party/boringssl-with-bazel/src/crypto/internal.h:835
EVP_DecodeBase64
int EVP_DecodeBase64(uint8_t *out, size_t *out_len, size_t max_out, const uint8_t *in, size_t in_len)
Definition: base64.c:409
EVP_EncodeBlock
size_t EVP_EncodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len)
Definition: base64.c:223
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
OPENSSL_malloc
#define OPENSSL_malloc
Definition: boringssl_prefix_symbols.h:1885
constant_time_msb_w
static crypto_word_t constant_time_msb_w(crypto_word_t a)
Definition: third_party/boringssl-with-bazel/src/crypto/internal.h:313
in
const char * in
Definition: third_party/abseil-cpp/absl/strings/internal/str_format/parser_test.cc:391
c
void c(T a)
Definition: miscompile_with_no_unique_address_test.cc:40
xds_interop_client.int
int
Definition: xds_interop_client.py:113
max
int max
Definition: bloaty/third_party/zlib/examples/enough.c:170
setup.v
v
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
EVP_DecodeUpdate
int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len, const uint8_t *in, size_t in_len)
Definition: base64.c:344
OPENSSL_memcpy
static void * OPENSSL_memcpy(void *dst, const void *src, size_t n)
Definition: third_party/boringssl-with-bazel/src/crypto/internal.h:819
base64.h
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
EVP_EncodeUpdate
void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len, const uint8_t *in, size_t in_len)
Definition: base64.c:142
min
#define min(a, b)
Definition: qsort.h:83
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
d
static const fe d
Definition: curve25519_tables.h:19
constant_time_eq_8
static uint8_t constant_time_eq_8(crypto_word_t a, crypto_word_t b)
Definition: third_party/boringssl-with-bazel/src/crypto/internal.h:401
evp_encode_ctx_st
Definition: base64.h:177
EVP_ENCODE_CTX_free
void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx)
Definition: base64.c:134
EVP_DecodeBlock
int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len)
Definition: base64.c:442
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
L
lua_State * L
Definition: upb/upb/bindings/lua/main.c:35
EVP_EncodeInit
void EVP_EncodeInit(EVP_ENCODE_CTX *ctx)
Definition: base64.c:138
constant_time_in_range_8
static uint8_t constant_time_in_range_8(uint8_t a, uint8_t min, uint8_t max)
Definition: base64.c:80
EVP_ENCODE_CTX_new
EVP_ENCODE_CTX * EVP_ENCODE_CTX_new(void)
Definition: base64.c:125
EVP_EncodedLength
int EVP_EncodedLength(size_t *out_len, size_t len)
Definition: base64.c:104
type_check.h
constant_time_select_8
static uint8_t constant_time_select_8(uint8_t mask, uint8_t a, uint8_t b)
Definition: third_party/boringssl-with-bazel/src/crypto/internal.h:434
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
run_grpclb_interop_tests.l
dictionary l
Definition: run_grpclb_interop_tests.py:410
conv_bin2ascii
static uint8_t conv_bin2ascii(uint8_t a)
Definition: base64.c:88
OPENSSL_free
#define OPENSSL_free
Definition: boringssl_prefix_symbols.h:1869
mkowners.todo
todo
Definition: mkowners.py:209
OPENSSL_STATIC_ASSERT
OPENSSL_STATIC_ASSERT(sizeof(((EVP_ENCODE_CTX *)(NULL)) ->data) % 3==0, "data length must be a multiple of base64 chunk size")
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230


grpc
Author(s):
autogenerated on Fri May 16 2025 02:57:45