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