encode.c revision 299068
1/* crypto/evp/encode.c */ 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay@cryptsoft.com). 7 * The implementation was written so as to conform with Netscapes SSL. 8 * 9 * This library is free for commercial and non-commercial use as long as 10 * the following conditions are aheared to. The following conditions 11 * apply to all code found in this distribution, be it the RC4, RSA, 12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13 * included with this distribution is covered by the same copyright terms 14 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15 * 16 * Copyright remains Eric Young's, and as such any Copyright notices in 17 * the code are not to be removed. 18 * If this package is used in a product, Eric Young should be given attribution 19 * as the author of the parts of the library used. 20 * This can be in the form of a textual message at program startup or 21 * in documentation (online or textual) provided with the package. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. All advertising materials mentioning features or use of this software 32 * must display the following acknowledgement: 33 * "This product includes cryptographic software written by 34 * Eric Young (eay@cryptsoft.com)" 35 * The word 'cryptographic' can be left out if the rouines from the library 36 * being used are not cryptographic related :-). 37 * 4. If you include any Windows specific code (or a derivative thereof) from 38 * the apps directory (application code) you must include an acknowledgement: 39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40 * 41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * The licence and distribution terms for any publically available version or 54 * derivative of this code cannot be changed. i.e. this code cannot simply be 55 * copied and put under another distribution licence 56 * [including the GNU Public Licence.] 57 */ 58 59#include <stdio.h> 60#include <limits.h> 61#include "cryptlib.h" 62#include <openssl/evp.h> 63 64#ifndef CHARSET_EBCDIC 65# define conv_bin2ascii(a) (data_bin2ascii[(a)&0x3f]) 66# define conv_ascii2bin(a) (data_ascii2bin[(a)&0x7f]) 67#else 68/* 69 * We assume that PEM encoded files are EBCDIC files (i.e., printable text 70 * files). Convert them here while decoding. When encoding, output is EBCDIC 71 * (text) format again. (No need for conversion in the conv_bin2ascii macro, 72 * as the underlying textstring data_bin2ascii[] is already EBCDIC) 73 */ 74# define conv_bin2ascii(a) (data_bin2ascii[(a)&0x3f]) 75# define conv_ascii2bin(a) (data_ascii2bin[os_toascii[a]&0x7f]) 76#endif 77 78/*- 79 * 64 char lines 80 * pad input with 0 81 * left over chars are set to = 82 * 1 byte => xx== 83 * 2 bytes => xxx= 84 * 3 bytes => xxxx 85 */ 86#define BIN_PER_LINE (64/4*3) 87#define CHUNKS_PER_LINE (64/4) 88#define CHAR_PER_LINE (64+1) 89 90static const unsigned char data_bin2ascii[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\ 91abcdefghijklmnopqrstuvwxyz0123456789+/"; 92 93/*- 94 * 0xF0 is a EOLN 95 * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing). 96 * 0xF2 is EOF 97 * 0xE0 is ignore at start of line. 98 * 0xFF is error 99 */ 100 101#define B64_EOLN 0xF0 102#define B64_CR 0xF1 103#define B64_EOF 0xF2 104#define B64_WS 0xE0 105#define B64_ERROR 0xFF 106#define B64_NOT_BASE64(a) (((a)|0x13) == 0xF3) 107 108static const unsigned char data_ascii2bin[128] = { 109 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 110 0xFF, 0xE0, 0xF0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, 111 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 112 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 113 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 114 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F, 115 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 116 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 117 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 118 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 119 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 120 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 121 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 122 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 123 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 124 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 125}; 126 127void EVP_EncodeInit(EVP_ENCODE_CTX *ctx) 128{ 129 ctx->length = 48; 130 ctx->num = 0; 131 ctx->line_num = 0; 132} 133 134void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, 135 const unsigned char *in, int inl) 136{ 137 int i, j; 138 size_t total = 0; 139 140 *outl = 0; 141 if (inl <= 0) 142 return; 143 OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data)); 144 if (ctx->length - ctx->num > inl) { 145 memcpy(&(ctx->enc_data[ctx->num]), in, inl); 146 ctx->num += inl; 147 return; 148 } 149 if (ctx->num != 0) { 150 i = ctx->length - ctx->num; 151 memcpy(&(ctx->enc_data[ctx->num]), in, i); 152 in += i; 153 inl -= i; 154 j = EVP_EncodeBlock(out, ctx->enc_data, ctx->length); 155 ctx->num = 0; 156 out += j; 157 *(out++) = '\n'; 158 *out = '\0'; 159 total = j + 1; 160 } 161 while (inl >= ctx->length && total <= INT_MAX) { 162 j = EVP_EncodeBlock(out, in, ctx->length); 163 in += ctx->length; 164 inl -= ctx->length; 165 out += j; 166 *(out++) = '\n'; 167 *out = '\0'; 168 total += j + 1; 169 } 170 if (total > INT_MAX) { 171 /* Too much output data! */ 172 *outl = 0; 173 return; 174 } 175 if (inl != 0) 176 memcpy(&(ctx->enc_data[0]), in, inl); 177 ctx->num = inl; 178 *outl = total; 179} 180 181void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl) 182{ 183 unsigned int ret = 0; 184 185 if (ctx->num != 0) { 186 ret = EVP_EncodeBlock(out, ctx->enc_data, ctx->num); 187 out[ret++] = '\n'; 188 out[ret] = '\0'; 189 ctx->num = 0; 190 } 191 *outl = ret; 192} 193 194int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen) 195{ 196 int i, ret = 0; 197 unsigned long l; 198 199 for (i = dlen; i > 0; i -= 3) { 200 if (i >= 3) { 201 l = (((unsigned long)f[0]) << 16L) | 202 (((unsigned long)f[1]) << 8L) | f[2]; 203 *(t++) = conv_bin2ascii(l >> 18L); 204 *(t++) = conv_bin2ascii(l >> 12L); 205 *(t++) = conv_bin2ascii(l >> 6L); 206 *(t++) = conv_bin2ascii(l); 207 } else { 208 l = ((unsigned long)f[0]) << 16L; 209 if (i == 2) 210 l |= ((unsigned long)f[1] << 8L); 211 212 *(t++) = conv_bin2ascii(l >> 18L); 213 *(t++) = conv_bin2ascii(l >> 12L); 214 *(t++) = (i == 1) ? '=' : conv_bin2ascii(l >> 6L); 215 *(t++) = '='; 216 } 217 ret += 4; 218 f += 3; 219 } 220 221 *t = '\0'; 222 return (ret); 223} 224 225void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) 226{ 227 ctx->length = 30; 228 ctx->num = 0; 229 ctx->line_num = 0; 230 ctx->expect_nl = 0; 231} 232 233/*- 234 * -1 for error 235 * 0 for last line 236 * 1 for full line 237 */ 238int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, 239 const unsigned char *in, int inl) 240{ 241 int seof = -1, eof = 0, rv = -1, ret = 0, i, v, tmp, n, ln, exp_nl; 242 unsigned char *d; 243 244 n = ctx->num; 245 d = ctx->enc_data; 246 ln = ctx->line_num; 247 exp_nl = ctx->expect_nl; 248 249 /* last line of input. */ 250 if ((inl == 0) || ((n == 0) && (conv_ascii2bin(in[0]) == B64_EOF))) { 251 rv = 0; 252 goto end; 253 } 254 255 /* We parse the input data */ 256 for (i = 0; i < inl; i++) { 257 /* If the current line is > 80 characters, scream alot */ 258 if (ln >= 80) { 259 rv = -1; 260 goto end; 261 } 262 263 /* Get char and put it into the buffer */ 264 tmp = *(in++); 265 v = conv_ascii2bin(tmp); 266 /* only save the good data :-) */ 267 if (!B64_NOT_BASE64(v)) { 268 OPENSSL_assert(n < (int)sizeof(ctx->enc_data)); 269 d[n++] = tmp; 270 ln++; 271 } else if (v == B64_ERROR) { 272 rv = -1; 273 goto end; 274 } 275 276 /* 277 * have we seen a '=' which is 'definitly' the last input line. seof 278 * will point to the character that holds it. and eof will hold how 279 * many characters to chop off. 280 */ 281 if (tmp == '=') { 282 if (seof == -1) 283 seof = n; 284 eof++; 285 } 286 287 if (v == B64_CR) { 288 ln = 0; 289 if (exp_nl) 290 continue; 291 } 292 293 /* eoln */ 294 if (v == B64_EOLN) { 295 ln = 0; 296 if (exp_nl) { 297 exp_nl = 0; 298 continue; 299 } 300 } 301 exp_nl = 0; 302 303 /* 304 * If we are at the end of input and it looks like a line, process 305 * it. 306 */ 307 if (((i + 1) == inl) && (((n & 3) == 0) || eof)) { 308 v = B64_EOF; 309 /* 310 * In case things were given us in really small records (so two 311 * '=' were given in separate updates), eof may contain the 312 * incorrect number of ending bytes to skip, so let's redo the 313 * count 314 */ 315 eof = 0; 316 if (d[n - 1] == '=') 317 eof++; 318 if (d[n - 2] == '=') 319 eof++; 320 /* There will never be more than two '=' */ 321 } 322 323 if ((v == B64_EOF && (n & 3) == 0) || (n >= 64)) { 324 /* 325 * This is needed to work correctly on 64 byte input lines. We 326 * process the line and then need to accept the '\n' 327 */ 328 if ((v != B64_EOF) && (n >= 64)) 329 exp_nl = 1; 330 if (n > 0) { 331 v = EVP_DecodeBlock(out, d, n); 332 n = 0; 333 if (v < 0) { 334 rv = 0; 335 goto end; 336 } 337 if (eof > v) { 338 rv = -1; 339 goto end; 340 } 341 ret += (v - eof); 342 } else { 343 eof = 1; 344 v = 0; 345 } 346 347 /* 348 * This is the case where we have had a short but valid input 349 * line 350 */ 351 if ((v < ctx->length) && eof) { 352 rv = 0; 353 goto end; 354 } else 355 ctx->length = v; 356 357 if (seof >= 0) { 358 rv = 0; 359 goto end; 360 } 361 out += v; 362 } 363 } 364 rv = 1; 365 end: 366 *outl = ret; 367 ctx->num = n; 368 ctx->line_num = ln; 369 ctx->expect_nl = exp_nl; 370 return (rv); 371} 372 373int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n) 374{ 375 int i, ret = 0, a, b, c, d; 376 unsigned long l; 377 378 /* trim white space from the start of the line. */ 379 while ((conv_ascii2bin(*f) == B64_WS) && (n > 0)) { 380 f++; 381 n--; 382 } 383 384 /* 385 * strip off stuff at the end of the line ascii2bin values B64_WS, 386 * B64_EOLN, B64_EOLN and B64_EOF 387 */ 388 while ((n > 3) && (B64_NOT_BASE64(conv_ascii2bin(f[n - 1])))) 389 n--; 390 391 if (n % 4 != 0) 392 return (-1); 393 394 for (i = 0; i < n; i += 4) { 395 a = conv_ascii2bin(*(f++)); 396 b = conv_ascii2bin(*(f++)); 397 c = conv_ascii2bin(*(f++)); 398 d = conv_ascii2bin(*(f++)); 399 if ((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80)) 400 return (-1); 401 l = ((((unsigned long)a) << 18L) | 402 (((unsigned long)b) << 12L) | 403 (((unsigned long)c) << 6L) | (((unsigned long)d))); 404 *(t++) = (unsigned char)(l >> 16L) & 0xff; 405 *(t++) = (unsigned char)(l >> 8L) & 0xff; 406 *(t++) = (unsigned char)(l) & 0xff; 407 ret += 3; 408 } 409 return (ret); 410} 411 412int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl) 413{ 414 int i; 415 416 *outl = 0; 417 if (ctx->num != 0) { 418 i = EVP_DecodeBlock(out, ctx->enc_data, ctx->num); 419 if (i < 0) 420 return (-1); 421 ctx->num = 0; 422 *outl = i; 423 return (1); 424 } else 425 return (1); 426} 427 428#ifdef undef 429int EVP_DecodeValid(unsigned char *buf, int len) 430{ 431 int i, num = 0, bad = 0; 432 433 if (len == 0) 434 return (-1); 435 while (conv_ascii2bin(*buf) == B64_WS) { 436 buf++; 437 len--; 438 if (len == 0) 439 return (-1); 440 } 441 442 for (i = len; i >= 4; i -= 4) { 443 if ((conv_ascii2bin(buf[0]) >= 0x40) || 444 (conv_ascii2bin(buf[1]) >= 0x40) || 445 (conv_ascii2bin(buf[2]) >= 0x40) || 446 (conv_ascii2bin(buf[3]) >= 0x40)) 447 return (-1); 448 buf += 4; 449 num += 1 + (buf[2] != '=') + (buf[3] != '='); 450 } 451 if ((i == 1) && (conv_ascii2bin(buf[0]) == B64_EOLN)) 452 return (num); 453 if ((i == 2) && (conv_ascii2bin(buf[0]) == B64_EOLN) && 454 (conv_ascii2bin(buf[0]) == B64_EOLN)) 455 return (num); 456 return (1); 457} 458#endif 459