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 __RCSID("$MirOS: src/lib/libssl/src/crypto/evp/encode.c,v 1.2 2014/06/05 13:26:38 tg Exp $");
64
65 #ifndef CHARSET_EBCDIC
66 #define conv_bin2ascii(a) (data_bin2ascii[(a)&0x3f])
67 #define conv_ascii2bin(a) (data_ascii2bin[(a)&0x7f])
68 #else
69 /* We assume that PEM encoded files are EBCDIC files
70 * (i.e., printable text files). Convert them here while decoding.
71 * When encoding, output is EBCDIC (text) format again.
72 * (No need for conversion in the conv_bin2ascii macro, as the
73 * underlying textstring data_bin2ascii[] is already EBCDIC)
74 */
75 #define conv_bin2ascii(a) (data_bin2ascii[(a)&0x3f])
76 #define conv_ascii2bin(a) (data_ascii2bin[os_toascii[a]&0x7f])
77 #endif
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
90 static unsigned char data_bin2ascii[65]="ABCDEFGHIJKLMNOPQRSTUVWXYZ\
91 abcdefghijklmnopqrstuvwxyz0123456789+/";
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 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
EVP_EncodeInit(EVP_ENCODE_CTX * ctx)126 void EVP_EncodeInit(EVP_ENCODE_CTX *ctx)
127 {
128 ctx->length=48;
129 ctx->num=0;
130 ctx->line_num=0;
131 }
132
EVP_EncodeUpdate(EVP_ENCODE_CTX * ctx,unsigned char * out,int * outl,unsigned char * in,int inl)133 void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
134 unsigned char *in, int inl)
135 {
136 int i,j;
137 unsigned int total=0;
138
139 *outl=0;
140 if (inl == 0) return;
141 OPENSSL_assert(ctx->length <= sizeof ctx->enc_data);
142 if ((ctx->num+inl) < ctx->length)
143 {
144 memcpy(&(ctx->enc_data[ctx->num]),in,inl);
145 ctx->num+=inl;
146 return;
147 }
148 if (ctx->num != 0)
149 {
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)
162 {
163 j=EVP_EncodeBlock(out,in,ctx->length);
164 in+=ctx->length;
165 inl-=ctx->length;
166 out+=j;
167 *(out++)='\n';
168 *out='\0';
169 total+=j+1;
170 }
171 if (inl != 0)
172 memcpy(&(ctx->enc_data[0]),in,inl);
173 ctx->num=inl;
174 *outl=total;
175 }
176
EVP_EncodeFinal(EVP_ENCODE_CTX * ctx,unsigned char * out,int * outl)177 void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
178 {
179 unsigned int ret=0;
180
181 if (ctx->num != 0)
182 {
183 ret=EVP_EncodeBlock(out,ctx->enc_data,ctx->num);
184 out[ret++]='\n';
185 out[ret]='\0';
186 ctx->num=0;
187 }
188 *outl=ret;
189 }
190
EVP_EncodeBlock(unsigned char * t,const unsigned char * f,int dlen)191 int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen)
192 {
193 int i,ret=0;
194 unsigned long l;
195
196 for (i=dlen; i > 0; i-=3)
197 {
198 if (i >= 3)
199 {
200 l= (((unsigned long)f[0])<<16L)|
201 (((unsigned long)f[1])<< 8L)|f[2];
202 *(t++)=conv_bin2ascii(l>>18L);
203 *(t++)=conv_bin2ascii(l>>12L);
204 *(t++)=conv_bin2ascii(l>> 6L);
205 *(t++)=conv_bin2ascii(l );
206 }
207 else
208 {
209 l=((unsigned long)f[0])<<16L;
210 if (i == 2) 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
EVP_DecodeInit(EVP_ENCODE_CTX * ctx)225 void 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 /* -1 for error
234 * 0 for last line
235 * 1 for full line
236 */
EVP_DecodeUpdate(EVP_ENCODE_CTX * ctx,unsigned char * out,int * outl,unsigned char * in,int inl)237 int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
238 unsigned char *in, int inl)
239 {
240 int seof= -1,eof=0,rv= -1,ret=0,i,v,tmp,n,ln,tmp2,exp_nl;
241 unsigned char *d;
242
243 n=ctx->num;
244 d=ctx->enc_data;
245 ln=ctx->line_num;
246 exp_nl=ctx->expect_nl;
247
248 /* last line of input. */
249 if ((inl == 0) || ((n == 0) && (conv_ascii2bin(in[0]) == B64_EOF)))
250 { rv=0; goto end; }
251
252 /* We parse the input data */
253 for (i=0; i<inl; i++)
254 {
255 /* If the current line is > 80 characters, scream alot */
256 if (ln >= 80) { rv= -1; goto end; }
257
258 /* Get char and put it into the buffer */
259 tmp= *(in++);
260 v=conv_ascii2bin(tmp);
261 /* only save the good data :-) */
262 if (!B64_NOT_BASE64(v))
263 {
264 OPENSSL_assert(n < sizeof ctx->enc_data);
265 d[n++]=tmp;
266 ln++;
267 }
268 else if (v == B64_ERROR)
269 {
270 rv= -1;
271 goto end;
272 }
273
274 /* have we seen a '=' which is 'definitly' the last
275 * input line. seof will point to the character that
276 * holds it. and eof will hold how many characters to
277 * chop off. */
278 if (tmp == '=')
279 {
280 if (seof == -1) seof=n;
281 eof++;
282 }
283
284 if (v == B64_CR)
285 {
286 ln = 0;
287 if (exp_nl)
288 continue;
289 }
290
291 /* eoln */
292 if (v == B64_EOLN)
293 {
294 ln=0;
295 if (exp_nl)
296 {
297 exp_nl=0;
298 continue;
299 }
300 }
301 exp_nl=0;
302
303 /* If we are at the end of input and it looks like a
304 * line, process it. */
305 if (((i+1) == inl) && (((n&3) == 0) || eof))
306 {
307 v=B64_EOF;
308 /* In case things were given us in really small
309 records (so two '=' were given in separate
310 updates), eof may contain the incorrect number
311 of ending bytes to skip, so let's redo the count */
312 eof = 0;
313 if (d[n-1] == '=') eof++;
314 if (d[n-2] == '=') eof++;
315 /* There will never be more than two '=' */
316 }
317
318 if ((v == B64_EOF && (n&3) == 0) || (n >= 64))
319 {
320 /* This is needed to work correctly on 64 byte input
321 * lines. We process the line and then need to
322 * accept the '\n' */
323 if ((v != B64_EOF) && (n >= 64)) exp_nl=1;
324 tmp2=v;
325 if (n > 0)
326 {
327 v=EVP_DecodeBlock(out,d,n);
328 if (v < 0) { rv=0; goto end; }
329 if (eof > v) { rv=-1; goto end; }
330 n=0;
331 ret+=(v-eof);
332 }
333 else
334 {
335 eof=1;
336 v=0;
337 }
338
339 /* This is the case where we have had a short
340 * but valid input line */
341 if ((v < ctx->length) && eof)
342 {
343 rv=0;
344 goto end;
345 }
346 else
347 ctx->length=v;
348
349 if (seof >= 0) { rv=0; goto end; }
350 out+=v;
351 }
352 }
353 rv=1;
354 end:
355 *outl=ret;
356 ctx->num=n;
357 ctx->line_num=ln;
358 ctx->expect_nl=exp_nl;
359 return(rv);
360 }
361
EVP_DecodeBlock(unsigned char * t,const unsigned char * f,int n)362 int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n)
363 {
364 int i,ret=0,a,b,c,d;
365 unsigned long l;
366
367 /* trim white space from the start of the line. */
368 while ((conv_ascii2bin(*f) == B64_WS) && (n > 0))
369 {
370 f++;
371 n--;
372 }
373
374 /* strip off stuff at the end of the line
375 * ascii2bin values B64_WS, B64_EOLN, B64_EOLN and B64_EOF */
376 while ((n > 3) && (B64_NOT_BASE64(conv_ascii2bin(f[n-1]))))
377 n--;
378
379 if (n%4 != 0) return(-1);
380
381 for (i=0; i<n; i+=4)
382 {
383 a=conv_ascii2bin(*(f++));
384 b=conv_ascii2bin(*(f++));
385 c=conv_ascii2bin(*(f++));
386 d=conv_ascii2bin(*(f++));
387 if ( (a & 0x80) || (b & 0x80) ||
388 (c & 0x80) || (d & 0x80))
389 return(-1);
390 l=( (((unsigned long)a)<<18L)|
391 (((unsigned long)b)<<12L)|
392 (((unsigned long)c)<< 6L)|
393 (((unsigned long)d) ));
394 *(t++)=(unsigned char)(l>>16L)&0xff;
395 *(t++)=(unsigned char)(l>> 8L)&0xff;
396 *(t++)=(unsigned char)(l )&0xff;
397 ret+=3;
398 }
399 return(ret);
400 }
401
EVP_DecodeFinal(EVP_ENCODE_CTX * ctx,unsigned char * out,int * outl)402 int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
403 {
404 int i;
405
406 *outl=0;
407 if (ctx->num != 0)
408 {
409 i=EVP_DecodeBlock(out,ctx->enc_data,ctx->num);
410 if (i < 0) return(-1);
411 ctx->num=0;
412 *outl=i;
413 return(1);
414 }
415 else
416 return(1);
417 }
418
419 #ifdef undef
EVP_DecodeValid(unsigned char * buf,int len)420 int EVP_DecodeValid(unsigned char *buf, int len)
421 {
422 int i,num=0,bad=0;
423
424 if (len == 0) return(-1);
425 while (conv_ascii2bin(*buf) == B64_WS)
426 {
427 buf++;
428 len--;
429 if (len == 0) return(-1);
430 }
431
432 for (i=len; i >= 4; i-=4)
433 {
434 if ( (conv_ascii2bin(buf[0]) >= 0x40) ||
435 (conv_ascii2bin(buf[1]) >= 0x40) ||
436 (conv_ascii2bin(buf[2]) >= 0x40) ||
437 (conv_ascii2bin(buf[3]) >= 0x40))
438 return(-1);
439 buf+=4;
440 num+=1+(buf[2] != '=')+(buf[3] != '=');
441 }
442 if ((i == 1) && (conv_ascii2bin(buf[0]) == B64_EOLN))
443 return(num);
444 if ((i == 2) && (conv_ascii2bin(buf[0]) == B64_EOLN) &&
445 (conv_ascii2bin(buf[0]) == B64_EOLN))
446 return(num);
447 return(1);
448 }
449 #endif
450