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
62
63static 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
92static 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
106static uint8_t conv_ascii2bin(uint8_t a) {
107  if (a >= 128) {
108    return 0xFF;
109  }
110  return data_ascii2bin[a];
111}
112
113void EVP_EncodeInit(EVP_ENCODE_CTX *ctx) {
114  ctx->length = 48;
115  ctx->num = 0;
116  ctx->line_num = 0;
117}
118
119void 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
164void 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
176size_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
208int 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
216int 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
264void 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
271int 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
399end:
400  *out_len = ret;
401  ctx->num = n;
402  ctx->line_num = ln;
403  ctx->expect_nl = exp_nl;
404  return rv;
405}
406
407int 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
425int 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
457int 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