155714Skris/* crypto/evp/encode.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 8296341Sdelphij * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15296341Sdelphij * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 22296341Sdelphij * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 37296341Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40296341Sdelphij * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 52296341Sdelphij * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 5855714Skris 5955714Skris#include <stdio.h> 60299068Sdelphij#include <limits.h> 6155714Skris#include "cryptlib.h" 6255714Skris#include <openssl/evp.h> 6355714Skris 6455714Skris#ifndef CHARSET_EBCDIC 65296341Sdelphij# define conv_bin2ascii(a) (data_bin2ascii[(a)&0x3f]) 66296341Sdelphij# define conv_ascii2bin(a) (data_ascii2bin[(a)&0x7f]) 6755714Skris#else 68296341Sdelphij/* 69296341Sdelphij * We assume that PEM encoded files are EBCDIC files (i.e., printable text 70296341Sdelphij * files). Convert them here while decoding. When encoding, output is EBCDIC 71296341Sdelphij * (text) format again. (No need for conversion in the conv_bin2ascii macro, 72296341Sdelphij * as the underlying textstring data_bin2ascii[] is already EBCDIC) 7355714Skris */ 74296341Sdelphij# define conv_bin2ascii(a) (data_bin2ascii[(a)&0x3f]) 75296341Sdelphij# define conv_ascii2bin(a) (data_ascii2bin[os_toascii[a]&0x7f]) 7655714Skris#endif 7755714Skris 78296341Sdelphij/*- 79296341Sdelphij * 64 char lines 8055714Skris * pad input with 0 8155714Skris * left over chars are set to = 8255714Skris * 1 byte => xx== 8355714Skris * 2 bytes => xxx= 8455714Skris * 3 bytes => xxxx 8555714Skris */ 8655714Skris#define BIN_PER_LINE (64/4*3) 8755714Skris#define CHUNKS_PER_LINE (64/4) 8855714Skris#define CHAR_PER_LINE (64+1) 8955714Skris 90296341Sdelphijstatic const unsigned char data_bin2ascii[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\ 9155714Skrisabcdefghijklmnopqrstuvwxyz0123456789+/"; 9255714Skris 93296341Sdelphij/*- 94296341Sdelphij * 0xF0 is a EOLN 9555714Skris * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing). 9655714Skris * 0xF2 is EOF 9755714Skris * 0xE0 is ignore at start of line. 9855714Skris * 0xFF is error 9955714Skris */ 10055714Skris 101296341Sdelphij#define B64_EOLN 0xF0 102296341Sdelphij#define B64_CR 0xF1 103296341Sdelphij#define B64_EOF 0xF2 104296341Sdelphij#define B64_WS 0xE0 105296341Sdelphij#define B64_ERROR 0xFF 106296341Sdelphij#define B64_NOT_BASE64(a) (((a)|0x13) == 0xF3) 10755714Skris 108296341Sdelphijstatic const unsigned char data_ascii2bin[128] = { 109296341Sdelphij 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 110296341Sdelphij 0xFF, 0xE0, 0xF0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, 111296341Sdelphij 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 112296341Sdelphij 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 113296341Sdelphij 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 114296341Sdelphij 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F, 115296341Sdelphij 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 116296341Sdelphij 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 117296341Sdelphij 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 118296341Sdelphij 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 119296341Sdelphij 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 120296341Sdelphij 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 121296341Sdelphij 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 122296341Sdelphij 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 123296341Sdelphij 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 124296341Sdelphij 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 125296341Sdelphij}; 12655714Skris 12755714Skrisvoid EVP_EncodeInit(EVP_ENCODE_CTX *ctx) 128296341Sdelphij{ 129296341Sdelphij ctx->length = 48; 130296341Sdelphij ctx->num = 0; 131296341Sdelphij ctx->line_num = 0; 132296341Sdelphij} 13355714Skris 13455714Skrisvoid EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, 135296341Sdelphij const unsigned char *in, int inl) 136296341Sdelphij{ 137296341Sdelphij int i, j; 138299068Sdelphij size_t total = 0; 13955714Skris 140296341Sdelphij *outl = 0; 141296341Sdelphij if (inl <= 0) 142296341Sdelphij return; 143296341Sdelphij OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data)); 144299068Sdelphij if (ctx->length - ctx->num > inl) { 145296341Sdelphij memcpy(&(ctx->enc_data[ctx->num]), in, inl); 146296341Sdelphij ctx->num += inl; 147296341Sdelphij return; 148296341Sdelphij } 149296341Sdelphij if (ctx->num != 0) { 150296341Sdelphij i = ctx->length - ctx->num; 151296341Sdelphij memcpy(&(ctx->enc_data[ctx->num]), in, i); 152296341Sdelphij in += i; 153296341Sdelphij inl -= i; 154296341Sdelphij j = EVP_EncodeBlock(out, ctx->enc_data, ctx->length); 155296341Sdelphij ctx->num = 0; 156296341Sdelphij out += j; 157296341Sdelphij *(out++) = '\n'; 158296341Sdelphij *out = '\0'; 159296341Sdelphij total = j + 1; 160296341Sdelphij } 161299068Sdelphij while (inl >= ctx->length && total <= INT_MAX) { 162296341Sdelphij j = EVP_EncodeBlock(out, in, ctx->length); 163296341Sdelphij in += ctx->length; 164296341Sdelphij inl -= ctx->length; 165296341Sdelphij out += j; 166296341Sdelphij *(out++) = '\n'; 167296341Sdelphij *out = '\0'; 168296341Sdelphij total += j + 1; 169296341Sdelphij } 170299068Sdelphij if (total > INT_MAX) { 171299068Sdelphij /* Too much output data! */ 172299068Sdelphij *outl = 0; 173299068Sdelphij return; 174299068Sdelphij } 175296341Sdelphij if (inl != 0) 176296341Sdelphij memcpy(&(ctx->enc_data[0]), in, inl); 177296341Sdelphij ctx->num = inl; 178296341Sdelphij *outl = total; 179296341Sdelphij} 18055714Skris 18155714Skrisvoid EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl) 182296341Sdelphij{ 183296341Sdelphij unsigned int ret = 0; 18455714Skris 185296341Sdelphij if (ctx->num != 0) { 186296341Sdelphij ret = EVP_EncodeBlock(out, ctx->enc_data, ctx->num); 187296341Sdelphij out[ret++] = '\n'; 188296341Sdelphij out[ret] = '\0'; 189296341Sdelphij ctx->num = 0; 190296341Sdelphij } 191296341Sdelphij *outl = ret; 192296341Sdelphij} 19355714Skris 19459191Skrisint EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen) 195296341Sdelphij{ 196296341Sdelphij int i, ret = 0; 197296341Sdelphij unsigned long l; 19855714Skris 199296341Sdelphij for (i = dlen; i > 0; i -= 3) { 200296341Sdelphij if (i >= 3) { 201296341Sdelphij l = (((unsigned long)f[0]) << 16L) | 202296341Sdelphij (((unsigned long)f[1]) << 8L) | f[2]; 203296341Sdelphij *(t++) = conv_bin2ascii(l >> 18L); 204296341Sdelphij *(t++) = conv_bin2ascii(l >> 12L); 205296341Sdelphij *(t++) = conv_bin2ascii(l >> 6L); 206296341Sdelphij *(t++) = conv_bin2ascii(l); 207296341Sdelphij } else { 208296341Sdelphij l = ((unsigned long)f[0]) << 16L; 209296341Sdelphij if (i == 2) 210296341Sdelphij l |= ((unsigned long)f[1] << 8L); 21155714Skris 212296341Sdelphij *(t++) = conv_bin2ascii(l >> 18L); 213296341Sdelphij *(t++) = conv_bin2ascii(l >> 12L); 214296341Sdelphij *(t++) = (i == 1) ? '=' : conv_bin2ascii(l >> 6L); 215296341Sdelphij *(t++) = '='; 216296341Sdelphij } 217296341Sdelphij ret += 4; 218296341Sdelphij f += 3; 219296341Sdelphij } 22055714Skris 221296341Sdelphij *t = '\0'; 222296341Sdelphij return (ret); 223296341Sdelphij} 22455714Skris 22555714Skrisvoid EVP_DecodeInit(EVP_ENCODE_CTX *ctx) 226296341Sdelphij{ 227296341Sdelphij ctx->length = 30; 228296341Sdelphij ctx->num = 0; 229296341Sdelphij ctx->line_num = 0; 230296341Sdelphij ctx->expect_nl = 0; 231296341Sdelphij} 23255714Skris 233296341Sdelphij/*- 234296341Sdelphij * -1 for error 23555714Skris * 0 for last line 23655714Skris * 1 for full line 23755714Skris */ 23855714Skrisint EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, 239296341Sdelphij const unsigned char *in, int inl) 240296341Sdelphij{ 241296341Sdelphij int seof = -1, eof = 0, rv = -1, ret = 0, i, v, tmp, n, ln, exp_nl; 242296341Sdelphij unsigned char *d; 24355714Skris 244296341Sdelphij n = ctx->num; 245296341Sdelphij d = ctx->enc_data; 246296341Sdelphij ln = ctx->line_num; 247296341Sdelphij exp_nl = ctx->expect_nl; 24855714Skris 249296341Sdelphij /* last line of input. */ 250296341Sdelphij if ((inl == 0) || ((n == 0) && (conv_ascii2bin(in[0]) == B64_EOF))) { 251296341Sdelphij rv = 0; 252296341Sdelphij goto end; 253296341Sdelphij } 25455714Skris 255296341Sdelphij /* We parse the input data */ 256296341Sdelphij for (i = 0; i < inl; i++) { 257296341Sdelphij /* If the current line is > 80 characters, scream alot */ 258296341Sdelphij if (ln >= 80) { 259296341Sdelphij rv = -1; 260296341Sdelphij goto end; 261296341Sdelphij } 26255714Skris 263296341Sdelphij /* Get char and put it into the buffer */ 264296341Sdelphij tmp = *(in++); 265296341Sdelphij v = conv_ascii2bin(tmp); 266296341Sdelphij /* only save the good data :-) */ 267296341Sdelphij if (!B64_NOT_BASE64(v)) { 268296341Sdelphij OPENSSL_assert(n < (int)sizeof(ctx->enc_data)); 269296341Sdelphij d[n++] = tmp; 270296341Sdelphij ln++; 271296341Sdelphij } else if (v == B64_ERROR) { 272296341Sdelphij rv = -1; 273296341Sdelphij goto end; 274296341Sdelphij } 27555714Skris 276296341Sdelphij /* 277296341Sdelphij * have we seen a '=' which is 'definitly' the last input line. seof 278296341Sdelphij * will point to the character that holds it. and eof will hold how 279296341Sdelphij * many characters to chop off. 280296341Sdelphij */ 281296341Sdelphij if (tmp == '=') { 282296341Sdelphij if (seof == -1) 283296341Sdelphij seof = n; 284296341Sdelphij eof++; 285296341Sdelphij } 286100928Snectar 287296341Sdelphij if (v == B64_CR) { 288296341Sdelphij ln = 0; 289296341Sdelphij if (exp_nl) 290296341Sdelphij continue; 291296341Sdelphij } 29255714Skris 293296341Sdelphij /* eoln */ 294296341Sdelphij if (v == B64_EOLN) { 295296341Sdelphij ln = 0; 296296341Sdelphij if (exp_nl) { 297296341Sdelphij exp_nl = 0; 298296341Sdelphij continue; 299296341Sdelphij } 300296341Sdelphij } 301296341Sdelphij exp_nl = 0; 30255714Skris 303296341Sdelphij /* 304296341Sdelphij * If we are at the end of input and it looks like a line, process 305296341Sdelphij * it. 306296341Sdelphij */ 307296341Sdelphij if (((i + 1) == inl) && (((n & 3) == 0) || eof)) { 308296341Sdelphij v = B64_EOF; 309296341Sdelphij /* 310296341Sdelphij * In case things were given us in really small records (so two 311296341Sdelphij * '=' were given in separate updates), eof may contain the 312296341Sdelphij * incorrect number of ending bytes to skip, so let's redo the 313296341Sdelphij * count 314296341Sdelphij */ 315296341Sdelphij eof = 0; 316296341Sdelphij if (d[n - 1] == '=') 317296341Sdelphij eof++; 318296341Sdelphij if (d[n - 2] == '=') 319296341Sdelphij eof++; 320296341Sdelphij /* There will never be more than two '=' */ 321296341Sdelphij } 32255714Skris 323296341Sdelphij if ((v == B64_EOF && (n & 3) == 0) || (n >= 64)) { 324296341Sdelphij /* 325296341Sdelphij * This is needed to work correctly on 64 byte input lines. We 326296341Sdelphij * process the line and then need to accept the '\n' 327296341Sdelphij */ 328296341Sdelphij if ((v != B64_EOF) && (n >= 64)) 329296341Sdelphij exp_nl = 1; 330296341Sdelphij if (n > 0) { 331296341Sdelphij v = EVP_DecodeBlock(out, d, n); 332296341Sdelphij n = 0; 333296341Sdelphij if (v < 0) { 334296341Sdelphij rv = 0; 335296341Sdelphij goto end; 336296341Sdelphij } 337296341Sdelphij if (eof > v) { 338296341Sdelphij rv = -1; 339296341Sdelphij goto end; 340296341Sdelphij } 341296341Sdelphij ret += (v - eof); 342296341Sdelphij } else { 343296341Sdelphij eof = 1; 344296341Sdelphij v = 0; 345296341Sdelphij } 34655714Skris 347296341Sdelphij /* 348296341Sdelphij * This is the case where we have had a short but valid input 349296341Sdelphij * line 350296341Sdelphij */ 351296341Sdelphij if ((v < ctx->length) && eof) { 352296341Sdelphij rv = 0; 353296341Sdelphij goto end; 354296341Sdelphij } else 355296341Sdelphij ctx->length = v; 35655714Skris 357296341Sdelphij if (seof >= 0) { 358296341Sdelphij rv = 0; 359296341Sdelphij goto end; 360296341Sdelphij } 361296341Sdelphij out += v; 362296341Sdelphij } 363296341Sdelphij } 364296341Sdelphij rv = 1; 365296341Sdelphij end: 366296341Sdelphij *outl = ret; 367296341Sdelphij ctx->num = n; 368296341Sdelphij ctx->line_num = ln; 369296341Sdelphij ctx->expect_nl = exp_nl; 370296341Sdelphij return (rv); 371296341Sdelphij} 372296341Sdelphij 37359191Skrisint EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n) 374296341Sdelphij{ 375296341Sdelphij int i, ret = 0, a, b, c, d; 376296341Sdelphij unsigned long l; 37755714Skris 378296341Sdelphij /* trim white space from the start of the line. */ 379296341Sdelphij while ((conv_ascii2bin(*f) == B64_WS) && (n > 0)) { 380296341Sdelphij f++; 381296341Sdelphij n--; 382296341Sdelphij } 38355714Skris 384296341Sdelphij /* 385296341Sdelphij * strip off stuff at the end of the line ascii2bin values B64_WS, 386296341Sdelphij * B64_EOLN, B64_EOLN and B64_EOF 387296341Sdelphij */ 388296341Sdelphij while ((n > 3) && (B64_NOT_BASE64(conv_ascii2bin(f[n - 1])))) 389296341Sdelphij n--; 39055714Skris 391296341Sdelphij if (n % 4 != 0) 392296341Sdelphij return (-1); 39355714Skris 394296341Sdelphij for (i = 0; i < n; i += 4) { 395296341Sdelphij a = conv_ascii2bin(*(f++)); 396296341Sdelphij b = conv_ascii2bin(*(f++)); 397296341Sdelphij c = conv_ascii2bin(*(f++)); 398296341Sdelphij d = conv_ascii2bin(*(f++)); 399296341Sdelphij if ((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80)) 400296341Sdelphij return (-1); 401296341Sdelphij l = ((((unsigned long)a) << 18L) | 402296341Sdelphij (((unsigned long)b) << 12L) | 403296341Sdelphij (((unsigned long)c) << 6L) | (((unsigned long)d))); 404296341Sdelphij *(t++) = (unsigned char)(l >> 16L) & 0xff; 405296341Sdelphij *(t++) = (unsigned char)(l >> 8L) & 0xff; 406296341Sdelphij *(t++) = (unsigned char)(l) & 0xff; 407296341Sdelphij ret += 3; 408296341Sdelphij } 409296341Sdelphij return (ret); 410296341Sdelphij} 41155714Skris 41255714Skrisint EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl) 413296341Sdelphij{ 414296341Sdelphij int i; 41555714Skris 416296341Sdelphij *outl = 0; 417296341Sdelphij if (ctx->num != 0) { 418296341Sdelphij i = EVP_DecodeBlock(out, ctx->enc_data, ctx->num); 419296341Sdelphij if (i < 0) 420296341Sdelphij return (-1); 421296341Sdelphij ctx->num = 0; 422296341Sdelphij *outl = i; 423296341Sdelphij return (1); 424296341Sdelphij } else 425296341Sdelphij return (1); 426296341Sdelphij} 42755714Skris 42855714Skris#ifdef undef 42955714Skrisint EVP_DecodeValid(unsigned char *buf, int len) 430296341Sdelphij{ 431296341Sdelphij int i, num = 0, bad = 0; 43255714Skris 433296341Sdelphij if (len == 0) 434296341Sdelphij return (-1); 435296341Sdelphij while (conv_ascii2bin(*buf) == B64_WS) { 436296341Sdelphij buf++; 437296341Sdelphij len--; 438296341Sdelphij if (len == 0) 439296341Sdelphij return (-1); 440296341Sdelphij } 44155714Skris 442296341Sdelphij for (i = len; i >= 4; i -= 4) { 443296341Sdelphij if ((conv_ascii2bin(buf[0]) >= 0x40) || 444296341Sdelphij (conv_ascii2bin(buf[1]) >= 0x40) || 445296341Sdelphij (conv_ascii2bin(buf[2]) >= 0x40) || 446296341Sdelphij (conv_ascii2bin(buf[3]) >= 0x40)) 447296341Sdelphij return (-1); 448296341Sdelphij buf += 4; 449296341Sdelphij num += 1 + (buf[2] != '=') + (buf[3] != '='); 450296341Sdelphij } 451296341Sdelphij if ((i == 1) && (conv_ascii2bin(buf[0]) == B64_EOLN)) 452296341Sdelphij return (num); 453296341Sdelphij if ((i == 2) && (conv_ascii2bin(buf[0]) == B64_EOLN) && 454296341Sdelphij (conv_ascii2bin(buf[0]) == B64_EOLN)) 455296341Sdelphij return (num); 456296341Sdelphij return (1); 457296341Sdelphij} 45855714Skris#endif 459