1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <stdio.h> 11e1051a39Sopenharmony_ci#include <limits.h> 12e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 13e1051a39Sopenharmony_ci#include <openssl/evp.h> 14e1051a39Sopenharmony_ci#include "crypto/evp.h" 15e1051a39Sopenharmony_ci#include "evp_local.h" 16e1051a39Sopenharmony_ci 17e1051a39Sopenharmony_cistatic unsigned char conv_ascii2bin(unsigned char a, 18e1051a39Sopenharmony_ci const unsigned char *table); 19e1051a39Sopenharmony_cistatic int evp_encodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t, 20e1051a39Sopenharmony_ci const unsigned char *f, int dlen); 21e1051a39Sopenharmony_cistatic int evp_decodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t, 22e1051a39Sopenharmony_ci const unsigned char *f, int n); 23e1051a39Sopenharmony_ci 24e1051a39Sopenharmony_ci#ifndef CHARSET_EBCDIC 25e1051a39Sopenharmony_ci# define conv_bin2ascii(a, table) ((table)[(a)&0x3f]) 26e1051a39Sopenharmony_ci#else 27e1051a39Sopenharmony_ci/* 28e1051a39Sopenharmony_ci * We assume that PEM encoded files are EBCDIC files (i.e., printable text 29e1051a39Sopenharmony_ci * files). Convert them here while decoding. When encoding, output is EBCDIC 30e1051a39Sopenharmony_ci * (text) format again. (No need for conversion in the conv_bin2ascii macro, 31e1051a39Sopenharmony_ci * as the underlying textstring data_bin2ascii[] is already EBCDIC) 32e1051a39Sopenharmony_ci */ 33e1051a39Sopenharmony_ci# define conv_bin2ascii(a, table) ((table)[(a)&0x3f]) 34e1051a39Sopenharmony_ci#endif 35e1051a39Sopenharmony_ci 36e1051a39Sopenharmony_ci/*- 37e1051a39Sopenharmony_ci * 64 char lines 38e1051a39Sopenharmony_ci * pad input with 0 39e1051a39Sopenharmony_ci * left over chars are set to = 40e1051a39Sopenharmony_ci * 1 byte => xx== 41e1051a39Sopenharmony_ci * 2 bytes => xxx= 42e1051a39Sopenharmony_ci * 3 bytes => xxxx 43e1051a39Sopenharmony_ci */ 44e1051a39Sopenharmony_ci#define BIN_PER_LINE (64/4*3) 45e1051a39Sopenharmony_ci#define CHUNKS_PER_LINE (64/4) 46e1051a39Sopenharmony_ci#define CHAR_PER_LINE (64+1) 47e1051a39Sopenharmony_ci 48e1051a39Sopenharmony_cistatic const unsigned char data_bin2ascii[65] = 49e1051a39Sopenharmony_ci "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 50e1051a39Sopenharmony_ci 51e1051a39Sopenharmony_ci/* SRP uses a different base64 alphabet */ 52e1051a39Sopenharmony_cistatic const unsigned char srpdata_bin2ascii[65] = 53e1051a39Sopenharmony_ci "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./"; 54e1051a39Sopenharmony_ci 55e1051a39Sopenharmony_ci 56e1051a39Sopenharmony_ci/*- 57e1051a39Sopenharmony_ci * 0xF0 is a EOLN 58e1051a39Sopenharmony_ci * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing). 59e1051a39Sopenharmony_ci * 0xF2 is EOF 60e1051a39Sopenharmony_ci * 0xE0 is ignore at start of line. 61e1051a39Sopenharmony_ci * 0xFF is error 62e1051a39Sopenharmony_ci */ 63e1051a39Sopenharmony_ci 64e1051a39Sopenharmony_ci#define B64_EOLN 0xF0 65e1051a39Sopenharmony_ci#define B64_CR 0xF1 66e1051a39Sopenharmony_ci#define B64_EOF 0xF2 67e1051a39Sopenharmony_ci#define B64_WS 0xE0 68e1051a39Sopenharmony_ci#define B64_ERROR 0xFF 69e1051a39Sopenharmony_ci#define B64_NOT_BASE64(a) (((a)|0x13) == 0xF3) 70e1051a39Sopenharmony_ci#define B64_BASE64(a) (!B64_NOT_BASE64(a)) 71e1051a39Sopenharmony_ci 72e1051a39Sopenharmony_cistatic const unsigned char data_ascii2bin[128] = { 73e1051a39Sopenharmony_ci 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 74e1051a39Sopenharmony_ci 0xFF, 0xE0, 0xF0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, 75e1051a39Sopenharmony_ci 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 76e1051a39Sopenharmony_ci 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 77e1051a39Sopenharmony_ci 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 78e1051a39Sopenharmony_ci 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F, 79e1051a39Sopenharmony_ci 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 80e1051a39Sopenharmony_ci 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 81e1051a39Sopenharmony_ci 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 82e1051a39Sopenharmony_ci 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 83e1051a39Sopenharmony_ci 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 84e1051a39Sopenharmony_ci 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 85e1051a39Sopenharmony_ci 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 86e1051a39Sopenharmony_ci 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 87e1051a39Sopenharmony_ci 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 88e1051a39Sopenharmony_ci 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 89e1051a39Sopenharmony_ci}; 90e1051a39Sopenharmony_ci 91e1051a39Sopenharmony_cistatic const unsigned char srpdata_ascii2bin[128] = { 92e1051a39Sopenharmony_ci 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 93e1051a39Sopenharmony_ci 0xFF, 0xE0, 0xF0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, 94e1051a39Sopenharmony_ci 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 95e1051a39Sopenharmony_ci 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 96e1051a39Sopenharmony_ci 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 97e1051a39Sopenharmony_ci 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF2, 0x3E, 0x3F, 98e1051a39Sopenharmony_ci 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 99e1051a39Sopenharmony_ci 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 100e1051a39Sopenharmony_ci 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 101e1051a39Sopenharmony_ci 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 102e1051a39Sopenharmony_ci 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 103e1051a39Sopenharmony_ci 0x21, 0x22, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 104e1051a39Sopenharmony_ci 0xFF, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 105e1051a39Sopenharmony_ci 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 106e1051a39Sopenharmony_ci 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 107e1051a39Sopenharmony_ci 0x3B, 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 108e1051a39Sopenharmony_ci}; 109e1051a39Sopenharmony_ci 110e1051a39Sopenharmony_ci#ifndef CHARSET_EBCDIC 111e1051a39Sopenharmony_cistatic unsigned char conv_ascii2bin(unsigned char a, const unsigned char *table) 112e1051a39Sopenharmony_ci{ 113e1051a39Sopenharmony_ci if (a & 0x80) 114e1051a39Sopenharmony_ci return B64_ERROR; 115e1051a39Sopenharmony_ci return table[a]; 116e1051a39Sopenharmony_ci} 117e1051a39Sopenharmony_ci#else 118e1051a39Sopenharmony_cistatic unsigned char conv_ascii2bin(unsigned char a, const unsigned char *table) 119e1051a39Sopenharmony_ci{ 120e1051a39Sopenharmony_ci a = os_toascii[a]; 121e1051a39Sopenharmony_ci if (a & 0x80) 122e1051a39Sopenharmony_ci return B64_ERROR; 123e1051a39Sopenharmony_ci return table[a]; 124e1051a39Sopenharmony_ci} 125e1051a39Sopenharmony_ci#endif 126e1051a39Sopenharmony_ci 127e1051a39Sopenharmony_ciEVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void) 128e1051a39Sopenharmony_ci{ 129e1051a39Sopenharmony_ci return OPENSSL_zalloc(sizeof(EVP_ENCODE_CTX)); 130e1051a39Sopenharmony_ci} 131e1051a39Sopenharmony_ci 132e1051a39Sopenharmony_civoid EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx) 133e1051a39Sopenharmony_ci{ 134e1051a39Sopenharmony_ci OPENSSL_free(ctx); 135e1051a39Sopenharmony_ci} 136e1051a39Sopenharmony_ci 137e1051a39Sopenharmony_ciint EVP_ENCODE_CTX_copy(EVP_ENCODE_CTX *dctx, const EVP_ENCODE_CTX *sctx) 138e1051a39Sopenharmony_ci{ 139e1051a39Sopenharmony_ci memcpy(dctx, sctx, sizeof(EVP_ENCODE_CTX)); 140e1051a39Sopenharmony_ci 141e1051a39Sopenharmony_ci return 1; 142e1051a39Sopenharmony_ci} 143e1051a39Sopenharmony_ci 144e1051a39Sopenharmony_ciint EVP_ENCODE_CTX_num(EVP_ENCODE_CTX *ctx) 145e1051a39Sopenharmony_ci{ 146e1051a39Sopenharmony_ci return ctx->num; 147e1051a39Sopenharmony_ci} 148e1051a39Sopenharmony_ci 149e1051a39Sopenharmony_civoid evp_encode_ctx_set_flags(EVP_ENCODE_CTX *ctx, unsigned int flags) 150e1051a39Sopenharmony_ci{ 151e1051a39Sopenharmony_ci ctx->flags = flags; 152e1051a39Sopenharmony_ci} 153e1051a39Sopenharmony_ci 154e1051a39Sopenharmony_civoid EVP_EncodeInit(EVP_ENCODE_CTX *ctx) 155e1051a39Sopenharmony_ci{ 156e1051a39Sopenharmony_ci ctx->length = 48; 157e1051a39Sopenharmony_ci ctx->num = 0; 158e1051a39Sopenharmony_ci ctx->line_num = 0; 159e1051a39Sopenharmony_ci ctx->flags = 0; 160e1051a39Sopenharmony_ci} 161e1051a39Sopenharmony_ci 162e1051a39Sopenharmony_ciint EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, 163e1051a39Sopenharmony_ci const unsigned char *in, int inl) 164e1051a39Sopenharmony_ci{ 165e1051a39Sopenharmony_ci int i, j; 166e1051a39Sopenharmony_ci size_t total = 0; 167e1051a39Sopenharmony_ci 168e1051a39Sopenharmony_ci *outl = 0; 169e1051a39Sopenharmony_ci if (inl <= 0) 170e1051a39Sopenharmony_ci return 0; 171e1051a39Sopenharmony_ci OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data)); 172e1051a39Sopenharmony_ci if (ctx->length - ctx->num > inl) { 173e1051a39Sopenharmony_ci memcpy(&(ctx->enc_data[ctx->num]), in, inl); 174e1051a39Sopenharmony_ci ctx->num += inl; 175e1051a39Sopenharmony_ci return 1; 176e1051a39Sopenharmony_ci } 177e1051a39Sopenharmony_ci if (ctx->num != 0) { 178e1051a39Sopenharmony_ci i = ctx->length - ctx->num; 179e1051a39Sopenharmony_ci memcpy(&(ctx->enc_data[ctx->num]), in, i); 180e1051a39Sopenharmony_ci in += i; 181e1051a39Sopenharmony_ci inl -= i; 182e1051a39Sopenharmony_ci j = evp_encodeblock_int(ctx, out, ctx->enc_data, ctx->length); 183e1051a39Sopenharmony_ci ctx->num = 0; 184e1051a39Sopenharmony_ci out += j; 185e1051a39Sopenharmony_ci total = j; 186e1051a39Sopenharmony_ci if ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0) { 187e1051a39Sopenharmony_ci *(out++) = '\n'; 188e1051a39Sopenharmony_ci total++; 189e1051a39Sopenharmony_ci } 190e1051a39Sopenharmony_ci *out = '\0'; 191e1051a39Sopenharmony_ci } 192e1051a39Sopenharmony_ci while (inl >= ctx->length && total <= INT_MAX) { 193e1051a39Sopenharmony_ci j = evp_encodeblock_int(ctx, out, in, ctx->length); 194e1051a39Sopenharmony_ci in += ctx->length; 195e1051a39Sopenharmony_ci inl -= ctx->length; 196e1051a39Sopenharmony_ci out += j; 197e1051a39Sopenharmony_ci total += j; 198e1051a39Sopenharmony_ci if ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0) { 199e1051a39Sopenharmony_ci *(out++) = '\n'; 200e1051a39Sopenharmony_ci total++; 201e1051a39Sopenharmony_ci } 202e1051a39Sopenharmony_ci *out = '\0'; 203e1051a39Sopenharmony_ci } 204e1051a39Sopenharmony_ci if (total > INT_MAX) { 205e1051a39Sopenharmony_ci /* Too much output data! */ 206e1051a39Sopenharmony_ci *outl = 0; 207e1051a39Sopenharmony_ci return 0; 208e1051a39Sopenharmony_ci } 209e1051a39Sopenharmony_ci if (inl != 0) 210e1051a39Sopenharmony_ci memcpy(&(ctx->enc_data[0]), in, inl); 211e1051a39Sopenharmony_ci ctx->num = inl; 212e1051a39Sopenharmony_ci *outl = total; 213e1051a39Sopenharmony_ci 214e1051a39Sopenharmony_ci return 1; 215e1051a39Sopenharmony_ci} 216e1051a39Sopenharmony_ci 217e1051a39Sopenharmony_civoid EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl) 218e1051a39Sopenharmony_ci{ 219e1051a39Sopenharmony_ci unsigned int ret = 0; 220e1051a39Sopenharmony_ci 221e1051a39Sopenharmony_ci if (ctx->num != 0) { 222e1051a39Sopenharmony_ci ret = evp_encodeblock_int(ctx, out, ctx->enc_data, ctx->num); 223e1051a39Sopenharmony_ci if ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0) 224e1051a39Sopenharmony_ci out[ret++] = '\n'; 225e1051a39Sopenharmony_ci out[ret] = '\0'; 226e1051a39Sopenharmony_ci ctx->num = 0; 227e1051a39Sopenharmony_ci } 228e1051a39Sopenharmony_ci *outl = ret; 229e1051a39Sopenharmony_ci} 230e1051a39Sopenharmony_ci 231e1051a39Sopenharmony_cistatic int evp_encodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t, 232e1051a39Sopenharmony_ci const unsigned char *f, int dlen) 233e1051a39Sopenharmony_ci{ 234e1051a39Sopenharmony_ci int i, ret = 0; 235e1051a39Sopenharmony_ci unsigned long l; 236e1051a39Sopenharmony_ci const unsigned char *table; 237e1051a39Sopenharmony_ci 238e1051a39Sopenharmony_ci if (ctx != NULL && (ctx->flags & EVP_ENCODE_CTX_USE_SRP_ALPHABET) != 0) 239e1051a39Sopenharmony_ci table = srpdata_bin2ascii; 240e1051a39Sopenharmony_ci else 241e1051a39Sopenharmony_ci table = data_bin2ascii; 242e1051a39Sopenharmony_ci 243e1051a39Sopenharmony_ci for (i = dlen; i > 0; i -= 3) { 244e1051a39Sopenharmony_ci if (i >= 3) { 245e1051a39Sopenharmony_ci l = (((unsigned long)f[0]) << 16L) | 246e1051a39Sopenharmony_ci (((unsigned long)f[1]) << 8L) | f[2]; 247e1051a39Sopenharmony_ci *(t++) = conv_bin2ascii(l >> 18L, table); 248e1051a39Sopenharmony_ci *(t++) = conv_bin2ascii(l >> 12L, table); 249e1051a39Sopenharmony_ci *(t++) = conv_bin2ascii(l >> 6L, table); 250e1051a39Sopenharmony_ci *(t++) = conv_bin2ascii(l, table); 251e1051a39Sopenharmony_ci } else { 252e1051a39Sopenharmony_ci l = ((unsigned long)f[0]) << 16L; 253e1051a39Sopenharmony_ci if (i == 2) 254e1051a39Sopenharmony_ci l |= ((unsigned long)f[1] << 8L); 255e1051a39Sopenharmony_ci 256e1051a39Sopenharmony_ci *(t++) = conv_bin2ascii(l >> 18L, table); 257e1051a39Sopenharmony_ci *(t++) = conv_bin2ascii(l >> 12L, table); 258e1051a39Sopenharmony_ci *(t++) = (i == 1) ? '=' : conv_bin2ascii(l >> 6L, table); 259e1051a39Sopenharmony_ci *(t++) = '='; 260e1051a39Sopenharmony_ci } 261e1051a39Sopenharmony_ci ret += 4; 262e1051a39Sopenharmony_ci f += 3; 263e1051a39Sopenharmony_ci } 264e1051a39Sopenharmony_ci 265e1051a39Sopenharmony_ci *t = '\0'; 266e1051a39Sopenharmony_ci return ret; 267e1051a39Sopenharmony_ci} 268e1051a39Sopenharmony_ci 269e1051a39Sopenharmony_ciint EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen) 270e1051a39Sopenharmony_ci{ 271e1051a39Sopenharmony_ci return evp_encodeblock_int(NULL, t, f, dlen); 272e1051a39Sopenharmony_ci} 273e1051a39Sopenharmony_ci 274e1051a39Sopenharmony_civoid EVP_DecodeInit(EVP_ENCODE_CTX *ctx) 275e1051a39Sopenharmony_ci{ 276e1051a39Sopenharmony_ci /* Only ctx->num and ctx->flags are used during decoding. */ 277e1051a39Sopenharmony_ci ctx->num = 0; 278e1051a39Sopenharmony_ci ctx->length = 0; 279e1051a39Sopenharmony_ci ctx->line_num = 0; 280e1051a39Sopenharmony_ci ctx->flags = 0; 281e1051a39Sopenharmony_ci} 282e1051a39Sopenharmony_ci 283e1051a39Sopenharmony_ci/*- 284e1051a39Sopenharmony_ci * -1 for error 285e1051a39Sopenharmony_ci * 0 for last line 286e1051a39Sopenharmony_ci * 1 for full line 287e1051a39Sopenharmony_ci * 288e1051a39Sopenharmony_ci * Note: even though EVP_DecodeUpdate attempts to detect and report end of 289e1051a39Sopenharmony_ci * content, the context doesn't currently remember it and will accept more data 290e1051a39Sopenharmony_ci * in the next call. Therefore, the caller is responsible for checking and 291e1051a39Sopenharmony_ci * rejecting a 0 return value in the middle of content. 292e1051a39Sopenharmony_ci * 293e1051a39Sopenharmony_ci * Note: even though EVP_DecodeUpdate has historically tried to detect end of 294e1051a39Sopenharmony_ci * content based on line length, this has never worked properly. Therefore, 295e1051a39Sopenharmony_ci * we now return 0 when one of the following is true: 296e1051a39Sopenharmony_ci * - Padding or B64_EOF was detected and the last block is complete. 297e1051a39Sopenharmony_ci * - Input has zero-length. 298e1051a39Sopenharmony_ci * -1 is returned if: 299e1051a39Sopenharmony_ci * - Invalid characters are detected. 300e1051a39Sopenharmony_ci * - There is extra trailing padding, or data after padding. 301e1051a39Sopenharmony_ci * - B64_EOF is detected after an incomplete base64 block. 302e1051a39Sopenharmony_ci */ 303e1051a39Sopenharmony_ciint EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, 304e1051a39Sopenharmony_ci const unsigned char *in, int inl) 305e1051a39Sopenharmony_ci{ 306e1051a39Sopenharmony_ci int seof = 0, eof = 0, rv = -1, ret = 0, i, v, tmp, n, decoded_len; 307e1051a39Sopenharmony_ci unsigned char *d; 308e1051a39Sopenharmony_ci const unsigned char *table; 309e1051a39Sopenharmony_ci 310e1051a39Sopenharmony_ci n = ctx->num; 311e1051a39Sopenharmony_ci d = ctx->enc_data; 312e1051a39Sopenharmony_ci 313e1051a39Sopenharmony_ci if (n > 0 && d[n - 1] == '=') { 314e1051a39Sopenharmony_ci eof++; 315e1051a39Sopenharmony_ci if (n > 1 && d[n - 2] == '=') 316e1051a39Sopenharmony_ci eof++; 317e1051a39Sopenharmony_ci } 318e1051a39Sopenharmony_ci 319e1051a39Sopenharmony_ci /* Legacy behaviour: an empty input chunk signals end of input. */ 320e1051a39Sopenharmony_ci if (inl == 0) { 321e1051a39Sopenharmony_ci rv = 0; 322e1051a39Sopenharmony_ci goto end; 323e1051a39Sopenharmony_ci } 324e1051a39Sopenharmony_ci 325e1051a39Sopenharmony_ci if ((ctx->flags & EVP_ENCODE_CTX_USE_SRP_ALPHABET) != 0) 326e1051a39Sopenharmony_ci table = srpdata_ascii2bin; 327e1051a39Sopenharmony_ci else 328e1051a39Sopenharmony_ci table = data_ascii2bin; 329e1051a39Sopenharmony_ci 330e1051a39Sopenharmony_ci for (i = 0; i < inl; i++) { 331e1051a39Sopenharmony_ci tmp = *(in++); 332e1051a39Sopenharmony_ci v = conv_ascii2bin(tmp, table); 333e1051a39Sopenharmony_ci if (v == B64_ERROR) { 334e1051a39Sopenharmony_ci rv = -1; 335e1051a39Sopenharmony_ci goto end; 336e1051a39Sopenharmony_ci } 337e1051a39Sopenharmony_ci 338e1051a39Sopenharmony_ci if (tmp == '=') { 339e1051a39Sopenharmony_ci eof++; 340e1051a39Sopenharmony_ci } else if (eof > 0 && B64_BASE64(v)) { 341e1051a39Sopenharmony_ci /* More data after padding. */ 342e1051a39Sopenharmony_ci rv = -1; 343e1051a39Sopenharmony_ci goto end; 344e1051a39Sopenharmony_ci } 345e1051a39Sopenharmony_ci 346e1051a39Sopenharmony_ci if (eof > 2) { 347e1051a39Sopenharmony_ci rv = -1; 348e1051a39Sopenharmony_ci goto end; 349e1051a39Sopenharmony_ci } 350e1051a39Sopenharmony_ci 351e1051a39Sopenharmony_ci if (v == B64_EOF) { 352e1051a39Sopenharmony_ci seof = 1; 353e1051a39Sopenharmony_ci goto tail; 354e1051a39Sopenharmony_ci } 355e1051a39Sopenharmony_ci 356e1051a39Sopenharmony_ci /* Only save valid base64 characters. */ 357e1051a39Sopenharmony_ci if (B64_BASE64(v)) { 358e1051a39Sopenharmony_ci if (n >= 64) { 359e1051a39Sopenharmony_ci /* 360e1051a39Sopenharmony_ci * We increment n once per loop, and empty the buffer as soon as 361e1051a39Sopenharmony_ci * we reach 64 characters, so this can only happen if someone's 362e1051a39Sopenharmony_ci * manually messed with the ctx. Refuse to write any more data. 363e1051a39Sopenharmony_ci */ 364e1051a39Sopenharmony_ci rv = -1; 365e1051a39Sopenharmony_ci goto end; 366e1051a39Sopenharmony_ci } 367e1051a39Sopenharmony_ci OPENSSL_assert(n < (int)sizeof(ctx->enc_data)); 368e1051a39Sopenharmony_ci d[n++] = tmp; 369e1051a39Sopenharmony_ci } 370e1051a39Sopenharmony_ci 371e1051a39Sopenharmony_ci if (n == 64) { 372e1051a39Sopenharmony_ci decoded_len = evp_decodeblock_int(ctx, out, d, n); 373e1051a39Sopenharmony_ci n = 0; 374e1051a39Sopenharmony_ci if (decoded_len < 0 || eof > decoded_len) { 375e1051a39Sopenharmony_ci rv = -1; 376e1051a39Sopenharmony_ci goto end; 377e1051a39Sopenharmony_ci } 378e1051a39Sopenharmony_ci ret += decoded_len - eof; 379e1051a39Sopenharmony_ci out += decoded_len - eof; 380e1051a39Sopenharmony_ci } 381e1051a39Sopenharmony_ci } 382e1051a39Sopenharmony_ci 383e1051a39Sopenharmony_ci /* 384e1051a39Sopenharmony_ci * Legacy behaviour: if the current line is a full base64-block (i.e., has 385e1051a39Sopenharmony_ci * 0 mod 4 base64 characters), it is processed immediately. We keep this 386e1051a39Sopenharmony_ci * behaviour as applications may not be calling EVP_DecodeFinal properly. 387e1051a39Sopenharmony_ci */ 388e1051a39Sopenharmony_citail: 389e1051a39Sopenharmony_ci if (n > 0) { 390e1051a39Sopenharmony_ci if ((n & 3) == 0) { 391e1051a39Sopenharmony_ci decoded_len = evp_decodeblock_int(ctx, out, d, n); 392e1051a39Sopenharmony_ci n = 0; 393e1051a39Sopenharmony_ci if (decoded_len < 0 || eof > decoded_len) { 394e1051a39Sopenharmony_ci rv = -1; 395e1051a39Sopenharmony_ci goto end; 396e1051a39Sopenharmony_ci } 397e1051a39Sopenharmony_ci ret += (decoded_len - eof); 398e1051a39Sopenharmony_ci } else if (seof) { 399e1051a39Sopenharmony_ci /* EOF in the middle of a base64 block. */ 400e1051a39Sopenharmony_ci rv = -1; 401e1051a39Sopenharmony_ci goto end; 402e1051a39Sopenharmony_ci } 403e1051a39Sopenharmony_ci } 404e1051a39Sopenharmony_ci 405e1051a39Sopenharmony_ci rv = seof || (n == 0 && eof) ? 0 : 1; 406e1051a39Sopenharmony_ciend: 407e1051a39Sopenharmony_ci /* Legacy behaviour. This should probably rather be zeroed on error. */ 408e1051a39Sopenharmony_ci *outl = ret; 409e1051a39Sopenharmony_ci ctx->num = n; 410e1051a39Sopenharmony_ci return rv; 411e1051a39Sopenharmony_ci} 412e1051a39Sopenharmony_ci 413e1051a39Sopenharmony_cistatic int evp_decodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t, 414e1051a39Sopenharmony_ci const unsigned char *f, int n) 415e1051a39Sopenharmony_ci{ 416e1051a39Sopenharmony_ci int i, ret = 0, a, b, c, d; 417e1051a39Sopenharmony_ci unsigned long l; 418e1051a39Sopenharmony_ci const unsigned char *table; 419e1051a39Sopenharmony_ci 420e1051a39Sopenharmony_ci if (ctx != NULL && (ctx->flags & EVP_ENCODE_CTX_USE_SRP_ALPHABET) != 0) 421e1051a39Sopenharmony_ci table = srpdata_ascii2bin; 422e1051a39Sopenharmony_ci else 423e1051a39Sopenharmony_ci table = data_ascii2bin; 424e1051a39Sopenharmony_ci 425e1051a39Sopenharmony_ci /* trim whitespace from the start of the line. */ 426e1051a39Sopenharmony_ci while ((n > 0) && (conv_ascii2bin(*f, table) == B64_WS)) { 427e1051a39Sopenharmony_ci f++; 428e1051a39Sopenharmony_ci n--; 429e1051a39Sopenharmony_ci } 430e1051a39Sopenharmony_ci 431e1051a39Sopenharmony_ci /* 432e1051a39Sopenharmony_ci * strip off stuff at the end of the line ascii2bin values B64_WS, 433e1051a39Sopenharmony_ci * B64_EOLN, B64_EOLN and B64_EOF 434e1051a39Sopenharmony_ci */ 435e1051a39Sopenharmony_ci while ((n > 3) && (B64_NOT_BASE64(conv_ascii2bin(f[n - 1], table)))) 436e1051a39Sopenharmony_ci n--; 437e1051a39Sopenharmony_ci 438e1051a39Sopenharmony_ci if (n % 4 != 0) 439e1051a39Sopenharmony_ci return -1; 440e1051a39Sopenharmony_ci 441e1051a39Sopenharmony_ci for (i = 0; i < n; i += 4) { 442e1051a39Sopenharmony_ci a = conv_ascii2bin(*(f++), table); 443e1051a39Sopenharmony_ci b = conv_ascii2bin(*(f++), table); 444e1051a39Sopenharmony_ci c = conv_ascii2bin(*(f++), table); 445e1051a39Sopenharmony_ci d = conv_ascii2bin(*(f++), table); 446e1051a39Sopenharmony_ci if ((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80)) 447e1051a39Sopenharmony_ci return -1; 448e1051a39Sopenharmony_ci l = ((((unsigned long)a) << 18L) | 449e1051a39Sopenharmony_ci (((unsigned long)b) << 12L) | 450e1051a39Sopenharmony_ci (((unsigned long)c) << 6L) | (((unsigned long)d))); 451e1051a39Sopenharmony_ci *(t++) = (unsigned char)(l >> 16L) & 0xff; 452e1051a39Sopenharmony_ci *(t++) = (unsigned char)(l >> 8L) & 0xff; 453e1051a39Sopenharmony_ci *(t++) = (unsigned char)(l) & 0xff; 454e1051a39Sopenharmony_ci ret += 3; 455e1051a39Sopenharmony_ci } 456e1051a39Sopenharmony_ci return ret; 457e1051a39Sopenharmony_ci} 458e1051a39Sopenharmony_ci 459e1051a39Sopenharmony_ciint EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n) 460e1051a39Sopenharmony_ci{ 461e1051a39Sopenharmony_ci return evp_decodeblock_int(NULL, t, f, n); 462e1051a39Sopenharmony_ci} 463e1051a39Sopenharmony_ci 464e1051a39Sopenharmony_ciint EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl) 465e1051a39Sopenharmony_ci{ 466e1051a39Sopenharmony_ci int i; 467e1051a39Sopenharmony_ci 468e1051a39Sopenharmony_ci *outl = 0; 469e1051a39Sopenharmony_ci if (ctx->num != 0) { 470e1051a39Sopenharmony_ci i = evp_decodeblock_int(ctx, out, ctx->enc_data, ctx->num); 471e1051a39Sopenharmony_ci if (i < 0) 472e1051a39Sopenharmony_ci return -1; 473e1051a39Sopenharmony_ci ctx->num = 0; 474e1051a39Sopenharmony_ci *outl = i; 475e1051a39Sopenharmony_ci return 1; 476e1051a39Sopenharmony_ci } else 477e1051a39Sopenharmony_ci return 1; 478e1051a39Sopenharmony_ci} 479