195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * All rights reserved.
395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This package is an SSL implementation written
595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * by Eric Young (eay@cryptsoft.com).
695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * The implementation was written so as to conform with Netscapes SSL.
795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This library is free for commercial and non-commercial use as long as
995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * the following conditions are aheared to.  The following conditions
1095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * apply to all code found in this distribution, be it the RC4, RSA,
1195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * included with this distribution is covered by the same copyright terms
1395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
1595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Copyright remains Eric Young's, and as such any Copyright notices in
1695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * the code are not to be removed.
1795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * If this package is used in a product, Eric Young should be given attribution
1895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * as the author of the parts of the library used.
1995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This can be in the form of a textual message at program startup or
2095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * in documentation (online or textual) provided with the package.
2195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
2295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Redistribution and use in source and binary forms, with or without
2395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * modification, are permitted provided that the following conditions
2495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * are met:
2595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 1. Redistributions of source code must retain the copyright
2695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    notice, this list of conditions and the following disclaimer.
2795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 2. Redistributions in binary form must reproduce the above copyright
2895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    notice, this list of conditions and the following disclaimer in the
2995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    documentation and/or other materials provided with the distribution.
3095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 3. All advertising materials mentioning features or use of this software
3195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    must display the following acknowledgement:
3295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    "This product includes cryptographic software written by
3395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *     Eric Young (eay@cryptsoft.com)"
3495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    The word 'cryptographic' can be left out if the rouines from the library
3595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    being used are not cryptographic related :-).
3695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 4. If you include any Windows specific code (or a derivative thereof) from
3795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    the apps directory (application code) you must include an acknowledgement:
3895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
3995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
4095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * SUCH DAMAGE.
5195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
5295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * The licence and distribution terms for any publically available version or
5395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * derivative of this code cannot be changed.  i.e. this code cannot simply be
5495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * copied and put under another distribution licence
5595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * [including the GNU Public Licence.] */
5695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
5795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/base64.h>
5895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
5995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <assert.h>
60ded93581f1674f81faa0dba4b15a842756066ab2Adam Langley#include <limits.h>
6195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic const unsigned char data_bin2ascii[65] =
6495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
6595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#define conv_bin2ascii(a) (data_bin2ascii[(a) & 0x3f])
6795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* 64 char lines
6995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * pad input with 0
7095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * left over chars are set to =
7195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 1 byte  => xx==
7295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 2 bytes => xxx=
7395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 3 bytes => xxxx
7495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
7595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#define BIN_PER_LINE    (64/4*3)
7695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#define CHUNKS_PER_LINE (64/4)
7795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#define CHAR_PER_LINE   (64+1)
7895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
7995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* 0xF0 is a EOLN
8095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing).
8195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 0xF2 is EOF
8295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 0xE0 is ignore at start of line.
8395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 0xFF is error */
8495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
8595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#define B64_EOLN 0xF0
8695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#define B64_CR 0xF1
8795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#define B64_EOF 0xF2
8895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#define B64_WS 0xE0
8995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#define B64_ERROR 0xFF
9095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#define B64_NOT_BASE64(a) (((a) | 0x13) == 0xF3)
9195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
92d698f322b58a50ee1acf21a734367d151c154dd1David Benjaminstatic const uint8_t data_ascii2bin[128] = {
9395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xF0, 0xFF,
9495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
9595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF,
9695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F,
9795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0xFF, 0xFF,
98d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
9995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
10095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
10195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
10295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
10395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
10495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley};
10595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
106d698f322b58a50ee1acf21a734367d151c154dd1David Benjaminstatic uint8_t conv_ascii2bin(uint8_t a) {
107d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin  if (a >= 128) {
108d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    return 0xFF;
109d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin  }
110d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin  return data_ascii2bin[a];
111d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin}
112d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin
11395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid EVP_EncodeInit(EVP_ENCODE_CTX *ctx) {
11495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ctx->length = 48;
11595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ctx->num = 0;
11695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ctx->line_num = 0;
11795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
11895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
11995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
12095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                      const uint8_t *in, size_t in_len) {
12195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  unsigned i, j;
12295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  unsigned total = 0;
12395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
12495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  *out_len = 0;
12595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (in_len == 0) {
12695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return;
12795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
12895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
12995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  assert(ctx->length <= sizeof(ctx->enc_data));
13095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
1318750fe58f4bd74a3dd1aeba47ace94907d0a7de5Adam Langley  if (ctx->num + in_len < ctx->length) {
13295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    memcpy(&ctx->enc_data[ctx->num], in, in_len);
13395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    ctx->num += in_len;
13495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return;
13595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
13695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (ctx->num != 0) {
13795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    i = ctx->length - ctx->num;
13895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    memcpy(&ctx->enc_data[ctx->num], in, i);
13995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    in += i;
14095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    in_len -= i;
14195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    j = EVP_EncodeBlock(out, ctx->enc_data, ctx->length);
14295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    ctx->num = 0;
14395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    out += j;
14495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    *(out++) = '\n';
14595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    *out = '\0';
14695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    total = j + 1;
14795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
14895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  while (in_len >= ctx->length) {
14995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    j = EVP_EncodeBlock(out, in, ctx->length);
15095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    in += ctx->length;
15195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    in_len -= ctx->length;
15295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    out += j;
15395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    *(out++) = '\n';
15495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    *out = '\0';
15595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    total += j + 1;
15695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
15795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (in_len != 0) {
15895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    memcpy(&ctx->enc_data[0], in, in_len);
15995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
16095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ctx->num = in_len;
16195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  *out_len = total;
16295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
16395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
16495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) {
16595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  unsigned ret = 0;
16695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
16795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (ctx->num != 0) {
16895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    ret = EVP_EncodeBlock(out, ctx->enc_data, ctx->num);
16995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    out[ret++] = '\n';
17095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    out[ret] = '\0';
17195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    ctx->num = 0;
17295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
17395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  *out_len = ret;
17495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
17595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
17695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleysize_t EVP_EncodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
1778750fe58f4bd74a3dd1aeba47ace94907d0a7de5Adam Langley  uint32_t l;
1788750fe58f4bd74a3dd1aeba47ace94907d0a7de5Adam Langley  size_t remaining = src_len, ret = 0;
17995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
1808750fe58f4bd74a3dd1aeba47ace94907d0a7de5Adam Langley  while (remaining) {
1818750fe58f4bd74a3dd1aeba47ace94907d0a7de5Adam Langley    if (remaining >= 3) {
1828750fe58f4bd74a3dd1aeba47ace94907d0a7de5Adam Langley      l = (((uint32_t)src[0]) << 16L) | (((uint32_t)src[1]) << 8L) | src[2];
18395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      *(dst++) = conv_bin2ascii(l >> 18L);
18495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      *(dst++) = conv_bin2ascii(l >> 12L);
18595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      *(dst++) = conv_bin2ascii(l >> 6L);
18695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      *(dst++) = conv_bin2ascii(l);
1878750fe58f4bd74a3dd1aeba47ace94907d0a7de5Adam Langley      remaining -= 3;
18895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    } else {
1898750fe58f4bd74a3dd1aeba47ace94907d0a7de5Adam Langley      l = ((uint32_t)src[0]) << 16L;
1908750fe58f4bd74a3dd1aeba47ace94907d0a7de5Adam Langley      if (remaining == 2) {
1918750fe58f4bd74a3dd1aeba47ace94907d0a7de5Adam Langley        l |= ((uint32_t)src[1] << 8L);
19295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
19395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
19495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      *(dst++) = conv_bin2ascii(l >> 18L);
19595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      *(dst++) = conv_bin2ascii(l >> 12L);
1968750fe58f4bd74a3dd1aeba47ace94907d0a7de5Adam Langley      *(dst++) = (remaining == 1) ? '=' : conv_bin2ascii(l >> 6L);
19795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      *(dst++) = '=';
1988750fe58f4bd74a3dd1aeba47ace94907d0a7de5Adam Langley      remaining = 0;
19995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
20095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    ret += 4;
20195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    src += 3;
20295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
20395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
20495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  *dst = '\0';
20595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return ret;
20695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
20795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
208d698f322b58a50ee1acf21a734367d151c154dd1David Benjaminint EVP_DecodedLength(size_t *out_len, size_t len) {
209d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin  if (len % 4 != 0) {
210d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    return 0;
211d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin  }
212d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin  *out_len = (len / 4) * 3;
213d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin  return 1;
214d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin}
215d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin
216d698f322b58a50ee1acf21a734367d151c154dd1David Benjaminint EVP_DecodeBase64(uint8_t *out, size_t *out_len, size_t max_out,
217d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin                     const uint8_t *in, size_t in_len) {
218d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin  uint8_t a, b, c, d;
219d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin  size_t pad_len = 0, len = 0, max_len, i;
220d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin  uint32_t l;
221d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin
222d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin  if (!EVP_DecodedLength(&max_len, in_len) || max_out < max_len) {
223d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    return 0;
224d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin  }
225d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin
226d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin  for (i = 0; i < in_len; i += 4) {
227d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    a = conv_ascii2bin(*(in++));
228d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    b = conv_ascii2bin(*(in++));
229d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    if (i + 4 == in_len && in[1] == '=') {
230d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin        if (in[0] == '=') {
231d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin          pad_len = 2;
232d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin        } else {
233d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin          pad_len = 1;
234d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin        }
235d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    }
236d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    if (pad_len < 2) {
237d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin      c = conv_ascii2bin(*(in++));
238d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    } else {
239d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin      c = 0;
240d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    }
241d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    if (pad_len < 1) {
242d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin      d = conv_ascii2bin(*(in++));
243d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    } else {
244d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin      d = 0;
245d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    }
246d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    if ((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80)) {
247d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin      return 0;
248d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    }
249d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    l = ((((uint32_t)a) << 18L) | (((uint32_t)b) << 12L) |
250d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin         (((uint32_t)c) << 6L) | (((uint32_t)d)));
251d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    *(out++) = (uint8_t)(l >> 16L) & 0xff;
252d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    if (pad_len < 2) {
253d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin      *(out++) = (uint8_t)(l >> 8L) & 0xff;
254d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    }
255d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    if (pad_len < 1) {
256d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin      *(out++) = (uint8_t)(l) & 0xff;
257d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    }
258d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    len += 3 - pad_len;
259d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin  }
260d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin  *out_len = len;
261d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin  return 1;
262d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin}
263d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin
26495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid EVP_DecodeInit(EVP_ENCODE_CTX *ctx) {
26595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ctx->length = 30;
26695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ctx->num = 0;
26795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ctx->line_num = 0;
26895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ctx->expect_nl = 0;
26995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
27095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
27195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
27295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                     const uint8_t *in, size_t in_len) {
27395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  int seof = -1, eof = 0, rv = -1, v, tmp, exp_nl;
27495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  uint8_t *d;
27595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  unsigned i, n, ln, ret = 0;
27695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
27795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  n = ctx->num;
27895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  d = ctx->enc_data;
27995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ln = ctx->line_num;
28095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  exp_nl = ctx->expect_nl;
28195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
28295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  /* last line of input. */
28395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (in_len == 0 || (n == 0 && conv_ascii2bin(in[0]) == B64_EOF)) {
28495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    rv = 0;
28595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    goto end;
28695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
28795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
28895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  /* We parse the input data */
28995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  for (i = 0; i < in_len; i++) {
29095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    /* If the current line is > 80 characters, scream alot */
29195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (ln >= 80) {
29295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      rv = -1;
29395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      goto end;
29495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
29595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
29695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    /* Get char and put it into the buffer */
29795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    tmp = *(in++);
29895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    v = conv_ascii2bin(tmp);
29995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    /* only save the good data :-) */
30095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (!B64_NOT_BASE64(v)) {
30195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      assert(n < sizeof(ctx->enc_data));
30295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      d[n++] = tmp;
30395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      ln++;
30495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    } else if (v == B64_ERROR) {
30595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      rv = -1;
30695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      goto end;
30795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
30895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
30995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    /* have we seen a '=' which is 'definitly' the last
31095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley     * input line.  seof will point to the character that
31195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley     * holds it. and eof will hold how many characters to
31295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley     * chop off. */
31395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (tmp == '=') {
31495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (seof == -1) {
31595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        seof = n;
31695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
31795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      eof++;
31864bda23cad8cb912a55328ee9a298ca4d9795477Adam Langley      if (eof > 2) {
31964bda23cad8cb912a55328ee9a298ca4d9795477Adam Langley        /* There are, at most, two equals signs at the end of base64 data. */
32064bda23cad8cb912a55328ee9a298ca4d9795477Adam Langley        rv = -1;
32164bda23cad8cb912a55328ee9a298ca4d9795477Adam Langley        goto end;
32264bda23cad8cb912a55328ee9a298ca4d9795477Adam Langley      }
32395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
32495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
32595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (v == B64_CR) {
32695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      ln = 0;
32795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (exp_nl) {
32895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        continue;
32995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
33095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
33195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
33295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    /* eoln */
33395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (v == B64_EOLN) {
33495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      ln = 0;
33595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (exp_nl) {
33695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        exp_nl = 0;
33795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        continue;
33895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
33995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
34095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    exp_nl = 0;
34195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
34295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    /* If we are at the end of input and it looks like a
34395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley     * line, process it. */
34495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if ((i + 1) == in_len && (((n & 3) == 0) || eof)) {
34595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      v = B64_EOF;
34695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      /* In case things were given us in really small
34795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley         records (so two '=' were given in separate
34895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley         updates), eof may contain the incorrect number
34995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley         of ending bytes to skip, so let's redo the count */
35095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      eof = 0;
35195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (d[n - 1] == '=') {
35295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        eof++;
35395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
35495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (d[n - 2] == '=') {
35595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        eof++;
35695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
35795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      /* There will never be more than two '=' */
35895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
35995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
36095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if ((v == B64_EOF && (n & 3) == 0) || n >= 64) {
36195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      /* This is needed to work correctly on 64 byte input
36295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley       * lines.  We process the line and then need to
36395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley       * accept the '\n' */
36495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (v != B64_EOF && n >= 64) {
36595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        exp_nl = 1;
36695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
36795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (n > 0) {
368d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin        /* TODO(davidben): Switch this to EVP_DecodeBase64. */
36995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        v = EVP_DecodeBlock(out, d, n);
37095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        n = 0;
37195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        if (v < 0) {
37295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley          rv = 0;
37395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley          goto end;
37495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        }
37595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        ret += (v - eof);
37695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      } else {
37795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        eof = 1;
37895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        v = 0;
37995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
38095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
38195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      /* This is the case where we have had a short
38295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley       * but valid input line */
38395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (v < (int)ctx->length && eof) {
38495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        rv = 0;
38595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        goto end;
38695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      } else {
38795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        ctx->length = v;
38895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
38995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
39095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (seof >= 0) {
39195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        rv = 0;
39295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        goto end;
39395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
39495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      out += v;
39595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
39695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
39795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  rv = 1;
39895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
39995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyend:
40095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  *out_len = ret;
40195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ctx->num = n;
40295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ctx->line_num = ln;
40395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ctx->expect_nl = exp_nl;
40495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return rv;
40595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
40695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
40795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *outl) {
40895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  int i;
40995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
41095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  *outl = 0;
41195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (ctx->num != 0) {
412d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    /* TODO(davidben): Switch this to EVP_DecodeBase64. */
41395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    i = EVP_DecodeBlock(out, ctx->enc_data, ctx->num);
41495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (i < 0) {
41595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return -1;
41695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
41795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    ctx->num = 0;
41895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    *outl = i;
41995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 1;
42095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  } else {
42195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 1;
42295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
42395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
42495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
425ded93581f1674f81faa0dba4b15a842756066ab2Adam Langleyint EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
426d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin  size_t dst_len;
42795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
42895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  /* trim white space from the start of the line. */
42995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  while (conv_ascii2bin(*src) == B64_WS && src_len > 0) {
43095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    src++;
43195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    src_len--;
43295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
43395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
43495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  /* strip off stuff at the end of the line
43595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley   * ascii2bin values B64_WS, B64_EOLN, B64_EOLN and B64_EOF */
43695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  while (src_len > 3 && B64_NOT_BASE64(conv_ascii2bin(src[src_len - 1]))) {
43795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    src_len--;
43895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
43995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
440d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin  if (!EVP_DecodedLength(&dst_len, src_len) || dst_len > INT_MAX) {
44195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return -1;
44295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
443d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin  if (!EVP_DecodeBase64(dst, &dst_len, dst_len, src, src_len)) {
444d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    return -1;
44595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
44695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
447d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin  /* EVP_DecodeBlock does not take padding into account, so put the
448d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin   * NULs back in... so the caller can strip them back out. */
449d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin  while (dst_len % 3 != 0) {
450d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin    dst[dst_len++] = '\0';
451ded93581f1674f81faa0dba4b15a842756066ab2Adam Langley  }
452d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin  assert(dst_len <= INT_MAX);
453ded93581f1674f81faa0dba4b15a842756066ab2Adam Langley
454d698f322b58a50ee1acf21a734367d151c154dd1David Benjamin  return dst_len;
45595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
456660140206ed32aa217ba3f299debae8d9ac472ecAdam Langley
457660140206ed32aa217ba3f299debae8d9ac472ecAdam Langleyint EVP_EncodedLength(size_t *out_len, size_t len) {
458660140206ed32aa217ba3f299debae8d9ac472ecAdam Langley  if (len + 2 < len) {
459660140206ed32aa217ba3f299debae8d9ac472ecAdam Langley    return 0;
460660140206ed32aa217ba3f299debae8d9ac472ecAdam Langley  }
461660140206ed32aa217ba3f299debae8d9ac472ecAdam Langley  len += 2;
462660140206ed32aa217ba3f299debae8d9ac472ecAdam Langley  len /= 3;
463660140206ed32aa217ba3f299debae8d9ac472ecAdam Langley  if (((len << 2) >> 2) != len) {
464660140206ed32aa217ba3f299debae8d9ac472ecAdam Langley    return 0;
465660140206ed32aa217ba3f299debae8d9ac472ecAdam Langley  }
466660140206ed32aa217ba3f299debae8d9ac472ecAdam Langley  len <<= 2;
467660140206ed32aa217ba3f299debae8d9ac472ecAdam Langley  if (len + 1 < len) {
468660140206ed32aa217ba3f299debae8d9ac472ecAdam Langley    return 0;
469660140206ed32aa217ba3f299debae8d9ac472ecAdam Langley  }
470660140206ed32aa217ba3f299debae8d9ac472ecAdam Langley  len++;
471660140206ed32aa217ba3f299debae8d9ac472ecAdam Langley  *out_len = len;
472660140206ed32aa217ba3f299debae8d9ac472ecAdam Langley  return 1;
473660140206ed32aa217ba3f299debae8d9ac472ecAdam Langley}
474