Line data Source code
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 "cryptlib.h"
61 : #include <openssl/evp.h>
62 :
63 : #ifndef CHARSET_EBCDIC
64 : # define conv_bin2ascii(a) (data_bin2ascii[(a)&0x3f])
65 : # define conv_ascii2bin(a) (data_ascii2bin[(a)&0x7f])
66 : #else
67 : /*
68 : * We assume that PEM encoded files are EBCDIC files (i.e., printable text
69 : * files). Convert them here while decoding. When encoding, output is EBCDIC
70 : * (text) format again. (No need for conversion in the conv_bin2ascii macro,
71 : * as the underlying textstring data_bin2ascii[] is already EBCDIC)
72 : */
73 : # define conv_bin2ascii(a) (data_bin2ascii[(a)&0x3f])
74 : # define conv_ascii2bin(a) (data_ascii2bin[os_toascii[a]&0x7f])
75 : #endif
76 :
77 : /*-
78 : * 64 char lines
79 : * pad input with 0
80 : * left over chars are set to =
81 : * 1 byte => xx==
82 : * 2 bytes => xxx=
83 : * 3 bytes => xxxx
84 : */
85 : #define BIN_PER_LINE (64/4*3)
86 : #define CHUNKS_PER_LINE (64/4)
87 : #define CHAR_PER_LINE (64+1)
88 :
89 : static const unsigned char data_bin2ascii[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\
90 : abcdefghijklmnopqrstuvwxyz0123456789+/";
91 :
92 : /*-
93 : * 0xF0 is a EOLN
94 : * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing).
95 : * 0xF2 is EOF
96 : * 0xE0 is ignore at start of line.
97 : * 0xFF is error
98 : */
99 :
100 : #define B64_EOLN 0xF0
101 : #define B64_CR 0xF1
102 : #define B64_EOF 0xF2
103 : #define B64_WS 0xE0
104 : #define B64_ERROR 0xFF
105 : #define B64_NOT_BASE64(a) (((a)|0x13) == 0xF3)
106 :
107 : static const unsigned char data_ascii2bin[128] = {
108 : 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
109 : 0xFF, 0xE0, 0xF0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
110 : 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
111 : 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
112 : 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
113 : 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F,
114 : 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
115 : 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
116 : 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
117 : 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
118 : 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
119 : 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
120 : 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
121 : 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
122 : 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
123 : 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
124 : };
125 :
126 0 : void EVP_EncodeInit(EVP_ENCODE_CTX *ctx)
127 : {
128 0 : ctx->length = 48;
129 0 : ctx->num = 0;
130 0 : ctx->line_num = 0;
131 0 : }
132 :
133 0 : void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
134 : const unsigned char *in, int inl)
135 : {
136 : int i, j;
137 : unsigned int total = 0;
138 :
139 0 : *outl = 0;
140 0 : if (inl <= 0)
141 : return;
142 0 : OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data));
143 0 : if ((ctx->num + inl) < ctx->length) {
144 0 : memcpy(&(ctx->enc_data[ctx->num]), in, inl);
145 0 : ctx->num += inl;
146 0 : return;
147 : }
148 0 : if (ctx->num != 0) {
149 0 : i = ctx->length - ctx->num;
150 0 : memcpy(&(ctx->enc_data[ctx->num]), in, i);
151 0 : in += i;
152 0 : inl -= i;
153 0 : j = EVP_EncodeBlock(out, ctx->enc_data, ctx->length);
154 0 : ctx->num = 0;
155 0 : out += j;
156 0 : *(out++) = '\n';
157 0 : *out = '\0';
158 0 : total = j + 1;
159 : }
160 0 : while (inl >= ctx->length) {
161 0 : j = EVP_EncodeBlock(out, in, ctx->length);
162 0 : in += ctx->length;
163 0 : inl -= ctx->length;
164 0 : out += j;
165 0 : *(out++) = '\n';
166 0 : *out = '\0';
167 0 : total += j + 1;
168 : }
169 0 : if (inl != 0)
170 0 : memcpy(&(ctx->enc_data[0]), in, inl);
171 0 : ctx->num = inl;
172 0 : *outl = total;
173 : }
174 :
175 0 : void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
176 : {
177 : unsigned int ret = 0;
178 :
179 0 : if (ctx->num != 0) {
180 0 : ret = EVP_EncodeBlock(out, ctx->enc_data, ctx->num);
181 0 : out[ret++] = '\n';
182 0 : out[ret] = '\0';
183 0 : ctx->num = 0;
184 : }
185 0 : *outl = ret;
186 0 : }
187 :
188 0 : int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen)
189 : {
190 : int i, ret = 0;
191 : unsigned long l;
192 :
193 0 : for (i = dlen; i > 0; i -= 3) {
194 0 : if (i >= 3) {
195 0 : l = (((unsigned long)f[0]) << 16L) |
196 0 : (((unsigned long)f[1]) << 8L) | f[2];
197 0 : *(t++) = conv_bin2ascii(l >> 18L);
198 0 : *(t++) = conv_bin2ascii(l >> 12L);
199 0 : *(t++) = conv_bin2ascii(l >> 6L);
200 0 : *(t++) = conv_bin2ascii(l);
201 : } else {
202 0 : l = ((unsigned long)f[0]) << 16L;
203 0 : if (i == 2)
204 0 : l |= ((unsigned long)f[1] << 8L);
205 :
206 0 : *(t++) = conv_bin2ascii(l >> 18L);
207 0 : *(t++) = conv_bin2ascii(l >> 12L);
208 0 : *(t++) = (i == 1) ? '=' : conv_bin2ascii(l >> 6L);
209 0 : *(t++) = '=';
210 : }
211 0 : ret += 4;
212 0 : f += 3;
213 : }
214 :
215 0 : *t = '\0';
216 0 : return (ret);
217 : }
218 :
219 1761 : void EVP_DecodeInit(EVP_ENCODE_CTX *ctx)
220 : {
221 1761 : ctx->length = 30;
222 1761 : ctx->num = 0;
223 1761 : ctx->line_num = 0;
224 1761 : ctx->expect_nl = 0;
225 1761 : }
226 :
227 : /*-
228 : * -1 for error
229 : * 0 for last line
230 : * 1 for full line
231 : */
232 1761 : int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
233 : const unsigned char *in, int inl)
234 : {
235 : int seof = -1, eof = 0, rv = -1, ret = 0, i, v, tmp, n, ln, exp_nl;
236 : unsigned char *d;
237 :
238 1761 : n = ctx->num;
239 1761 : d = ctx->enc_data;
240 1761 : ln = ctx->line_num;
241 1761 : exp_nl = ctx->expect_nl;
242 :
243 : /* last line of input. */
244 1761 : if ((inl == 0) || ((n == 0) && (conv_ascii2bin(in[0]) == B64_EOF))) {
245 : rv = 0;
246 : goto end;
247 : }
248 :
249 : /* We parse the input data */
250 1491564 : for (i = 0; i < inl; i++) {
251 : /* If the current line is > 80 characters, scream a lot */
252 1493313 : if (ln >= 80) {
253 : rv = -1;
254 : goto end;
255 : }
256 :
257 : /* Get char and put it into the buffer */
258 1493313 : tmp = *(in++);
259 1493313 : v = conv_ascii2bin(tmp);
260 : /* only save the good data :-) */
261 1493313 : if (!B64_NOT_BASE64(v)) {
262 1470844 : OPENSSL_assert(n < (int)sizeof(ctx->enc_data));
263 1470844 : d[n++] = tmp;
264 1470844 : ln++;
265 22469 : } else if (v == B64_ERROR) {
266 : rv = -1;
267 : goto end;
268 : }
269 :
270 : /*
271 : * have we seen a '=' which is 'definitly' the last input line. seof
272 : * will point to the character that holds it. and eof will hold how
273 : * many characters to chop off.
274 : */
275 1493313 : if (tmp == '=') {
276 2188 : if (seof == -1)
277 : seof = n;
278 2188 : eof++;
279 : }
280 :
281 1493313 : if (v == B64_CR) {
282 : ln = 0;
283 0 : if (exp_nl)
284 0 : continue;
285 : }
286 :
287 : /* eoln */
288 1493313 : if (v == B64_EOLN) {
289 : ln = 0;
290 22469 : if (exp_nl) {
291 : exp_nl = 0;
292 21584 : continue;
293 : }
294 : }
295 : exp_nl = 0;
296 :
297 : /*
298 : * If we are at the end of input and it looks like a line, process
299 : * it.
300 : */
301 1471729 : if (((i + 1) == inl) && (((n & 3) == 0) || eof)) {
302 : v = B64_EOF;
303 : /*
304 : * In case things were given us in really small records (so two
305 : * '=' were given in separate updates), eof may contain the
306 : * incorrect number of ending bytes to skip, so let's redo the
307 : * count
308 : */
309 : eof = 0;
310 885 : if (d[n - 1] == '=')
311 : eof++;
312 885 : if (d[n - 2] == '=')
313 439 : eof++;
314 : /* There will never be more than two '=' */
315 : }
316 :
317 1471729 : if ((v == B64_EOF && (n & 3) == 0) || (n >= 64)) {
318 : /*
319 : * This is needed to work correctly on 64 byte input lines. We
320 : * process the line and then need to accept the '\n'
321 : */
322 23345 : if ((v != B64_EOF) && (n >= 64))
323 : exp_nl = 1;
324 23345 : if (n > 0) {
325 23345 : v = EVP_DecodeBlock(out, d, n);
326 : n = 0;
327 23345 : if (v < 0) {
328 : rv = 0;
329 : goto end;
330 : }
331 23345 : if (eof > v) {
332 : rv = -1;
333 : goto end;
334 : }
335 23345 : ret += (v - eof);
336 : } else {
337 : eof = 1;
338 : v = 0;
339 : }
340 :
341 : /*
342 : * This is the case where we have had a short but valid input
343 : * line
344 : */
345 23345 : if ((v < ctx->length) && eof) {
346 : rv = 0;
347 : goto end;
348 : } else
349 22472 : ctx->length = v;
350 :
351 22472 : if (seof >= 0) {
352 : rv = 0;
353 : goto end;
354 : }
355 21596 : out += v;
356 : }
357 : }
358 : rv = 1;
359 : end:
360 1761 : *outl = ret;
361 1761 : ctx->num = n;
362 1761 : ctx->line_num = ln;
363 1761 : ctx->expect_nl = exp_nl;
364 1761 : return (rv);
365 : }
366 :
367 23345 : int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n)
368 : {
369 : int i, ret = 0, a, b, c, d;
370 : unsigned long l;
371 :
372 : /* trim white space from the start of the line. */
373 46690 : while ((conv_ascii2bin(*f) == B64_WS) && (n > 0)) {
374 0 : f++;
375 0 : n--;
376 : }
377 :
378 : /*
379 : * strip off stuff at the end of the line ascii2bin values B64_WS,
380 : * B64_EOLN, B64_EOLN and B64_EOF
381 : */
382 23345 : while ((n > 3) && (B64_NOT_BASE64(conv_ascii2bin(f[n - 1]))))
383 0 : n--;
384 :
385 23345 : if (n % 4 != 0)
386 : return (-1);
387 :
388 367711 : for (i = 0; i < n; i += 4) {
389 367711 : a = conv_ascii2bin(*(f++));
390 367711 : b = conv_ascii2bin(*(f++));
391 367711 : c = conv_ascii2bin(*(f++));
392 367711 : d = conv_ascii2bin(*(f++));
393 367711 : if ((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80))
394 : return (-1);
395 1103133 : l = ((((unsigned long)a) << 18L) |
396 735422 : (((unsigned long)b) << 12L) |
397 735422 : (((unsigned long)c) << 6L) | (((unsigned long)d)));
398 367711 : *(t++) = (unsigned char)(l >> 16L) & 0xff;
399 367711 : *(t++) = (unsigned char)(l >> 8L) & 0xff;
400 367711 : *(t++) = (unsigned char)(l) & 0xff;
401 367711 : ret += 3;
402 : }
403 : return (ret);
404 : }
405 :
406 1761 : int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
407 : {
408 : int i;
409 :
410 1761 : *outl = 0;
411 1761 : if (ctx->num != 0) {
412 0 : i = EVP_DecodeBlock(out, ctx->enc_data, ctx->num);
413 0 : if (i < 0)
414 : return (-1);
415 0 : ctx->num = 0;
416 0 : *outl = i;
417 0 : return (1);
418 : } else
419 : return (1);
420 : }
421 :
422 : #ifdef undef
423 : int EVP_DecodeValid(unsigned char *buf, int len)
424 : {
425 : int i, num = 0, bad = 0;
426 :
427 : if (len == 0)
428 : return (-1);
429 : while (conv_ascii2bin(*buf) == B64_WS) {
430 : buf++;
431 : len--;
432 : if (len == 0)
433 : return (-1);
434 : }
435 :
436 : for (i = len; i >= 4; i -= 4) {
437 : if ((conv_ascii2bin(buf[0]) >= 0x40) ||
438 : (conv_ascii2bin(buf[1]) >= 0x40) ||
439 : (conv_ascii2bin(buf[2]) >= 0x40) ||
440 : (conv_ascii2bin(buf[3]) >= 0x40))
441 : return (-1);
442 : buf += 4;
443 : num += 1 + (buf[2] != '=') + (buf[3] != '=');
444 : }
445 : if ((i == 1) && (conv_ascii2bin(buf[0]) == B64_EOLN))
446 : return (num);
447 : if ((i == 2) && (conv_ascii2bin(buf[0]) == B64_EOLN) &&
448 : (conv_ascii2bin(buf[0]) == B64_EOLN))
449 : return (num);
450 : return (1);
451 : }
452 : #endif
|