~etc-pgh-launchpad/wildpockets/trunk

« back to all changes in this revision

Viewing changes to openssl-src/crypto/evp/encode.c

  • Committer: etc-pgh-launchpad at cmu
  • Date: 2010-11-30 20:56:30 UTC
  • Revision ID: etc-pgh-launchpad@lists.andrew.cmu.edu-20101130205630-0blbkcz28ovjl8wj
Committing the Wild Pockets code base to Launchpad.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 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 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
void EVP_EncodeInit(EVP_ENCODE_CTX *ctx)
 
125
        {
 
126
        ctx->length=48;
 
127
        ctx->num=0;
 
128
        ctx->line_num=0;
 
129
        }
 
130
 
 
131
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
        unsigned int total=0;
 
136
 
 
137
        *outl=0;
 
138
        if (inl == 0) return;
 
139
        OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data));
 
140
        if ((ctx->num+inl) < ctx->length)
 
141
                {
 
142
                memcpy(&(ctx->enc_data[ctx->num]),in,inl);
 
143
                ctx->num+=inl;
 
144
                return;
 
145
                }
 
146
        if (ctx->num != 0)
 
147
                {
 
148
                i=ctx->length-ctx->num;
 
149
                memcpy(&(ctx->enc_data[ctx->num]),in,i);
 
150
                in+=i;
 
151
                inl-=i;
 
152
                j=EVP_EncodeBlock(out,ctx->enc_data,ctx->length);
 
153
                ctx->num=0;
 
154
                out+=j;
 
155
                *(out++)='\n';
 
156
                *out='\0';
 
157
                total=j+1;
 
158
                }
 
159
        while (inl >= ctx->length)
 
160
                {
 
161
                j=EVP_EncodeBlock(out,in,ctx->length);
 
162
                in+=ctx->length;
 
163
                inl-=ctx->length;
 
164
                out+=j;
 
165
                *(out++)='\n';
 
166
                *out='\0';
 
167
                total+=j+1;
 
168
                }
 
169
        if (inl != 0)
 
170
                memcpy(&(ctx->enc_data[0]),in,inl);
 
171
        ctx->num=inl;
 
172
        *outl=total;
 
173
        }
 
174
 
 
175
void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
 
176
        {
 
177
        unsigned int ret=0;
 
178
 
 
179
        if (ctx->num != 0)
 
180
                {
 
181
                ret=EVP_EncodeBlock(out,ctx->enc_data,ctx->num);
 
182
                out[ret++]='\n';
 
183
                out[ret]='\0';
 
184
                ctx->num=0;
 
185
                }
 
186
        *outl=ret;
 
187
        }
 
188
 
 
189
int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen)
 
190
        {
 
191
        int i,ret=0;
 
192
        unsigned long l;
 
193
 
 
194
        for (i=dlen; i > 0; i-=3)
 
195
                {
 
196
                if (i >= 3)
 
197
                        {
 
198
                        l=      (((unsigned long)f[0])<<16L)|
 
199
                                (((unsigned long)f[1])<< 8L)|f[2];
 
200
                        *(t++)=conv_bin2ascii(l>>18L);
 
201
                        *(t++)=conv_bin2ascii(l>>12L);
 
202
                        *(t++)=conv_bin2ascii(l>> 6L);
 
203
                        *(t++)=conv_bin2ascii(l     );
 
204
                        }
 
205
                else
 
206
                        {
 
207
                        l=((unsigned long)f[0])<<16L;
 
208
                        if (i == 2) l|=((unsigned long)f[1]<<8L);
 
209
 
 
210
                        *(t++)=conv_bin2ascii(l>>18L);
 
211
                        *(t++)=conv_bin2ascii(l>>12L);
 
212
                        *(t++)=(i == 1)?'=':conv_bin2ascii(l>> 6L);
 
213
                        *(t++)='=';
 
214
                        }
 
215
                ret+=4;
 
216
                f+=3;
 
217
                }
 
218
 
 
219
        *t='\0';
 
220
        return(ret);
 
221
        }
 
222
 
 
223
void EVP_DecodeInit(EVP_ENCODE_CTX *ctx)
 
224
        {
 
225
        ctx->length=30;
 
226
        ctx->num=0;
 
227
        ctx->line_num=0;
 
228
        ctx->expect_nl=0;
 
229
        }
 
230
 
 
231
/* -1 for error
 
232
 *  0 for last line
 
233
 *  1 for full line
 
234
 */
 
235
int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
 
236
             const unsigned char *in, int inl)
 
237
        {
 
238
        int seof= -1,eof=0,rv= -1,ret=0,i,v,tmp,n,ln,tmp2,exp_nl;
 
239
        unsigned char *d;
 
240
 
 
241
        n=ctx->num;
 
242
        d=ctx->enc_data;
 
243
        ln=ctx->line_num;
 
244
        exp_nl=ctx->expect_nl;
 
245
 
 
246
        /* last line of input. */
 
247
        if ((inl == 0) || ((n == 0) && (conv_ascii2bin(in[0]) == B64_EOF)))
 
248
                { rv=0; goto end; }
 
249
                
 
250
        /* We parse the input data */
 
251
        for (i=0; i<inl; i++)
 
252
                {
 
253
                /* If the current line is > 80 characters, scream alot */
 
254
                if (ln >= 80) { rv= -1; goto end; }
 
255
 
 
256
                /* Get char and put it into the buffer */
 
257
                tmp= *(in++);
 
258
                v=conv_ascii2bin(tmp);
 
259
                /* only save the good data :-) */
 
260
                if (!B64_NOT_BASE64(v))
 
261
                        {
 
262
                        OPENSSL_assert(n < (int)sizeof(ctx->enc_data));
 
263
                        d[n++]=tmp;
 
264
                        ln++;
 
265
                        }
 
266
                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
                if (tmp == '=')
 
277
                        {
 
278
                        if (seof == -1) seof=n;
 
279
                        eof++;
 
280
                        }
 
281
 
 
282
                if (v == B64_CR)
 
283
                        {
 
284
                        ln = 0;
 
285
                        if (exp_nl)
 
286
                                continue;
 
287
                        }
 
288
 
 
289
                /* eoln */
 
290
                if (v == B64_EOLN)
 
291
                        {
 
292
                        ln=0;
 
293
                        if (exp_nl)
 
294
                                {
 
295
                                exp_nl=0;
 
296
                                continue;
 
297
                                }
 
298
                        }
 
299
                exp_nl=0;
 
300
 
 
301
                /* If we are at the end of input and it looks like a
 
302
                 * line, process it. */
 
303
                if (((i+1) == inl) && (((n&3) == 0) || eof))
 
304
                        {
 
305
                        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
                        eof = 0;
 
311
                        if (d[n-1] == '=') eof++;
 
312
                        if (d[n-2] == '=') eof++;
 
313
                        /* There will never be more than two '=' */
 
314
                        }
 
315
 
 
316
                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
                        if ((v != B64_EOF) && (n >= 64)) exp_nl=1;
 
322
                        tmp2=v;
 
323
                        if (n > 0)
 
324
                                {
 
325
                                v=EVP_DecodeBlock(out,d,n);
 
326
                                n=0;
 
327
                                if (v < 0) { rv=0; goto end; }
 
328
                                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
                        if ((v < ctx->length) && eof)
 
339
                                {
 
340
                                rv=0;
 
341
                                goto end;
 
342
                                }
 
343
                        else
 
344
                                ctx->length=v;
 
345
 
 
346
                        if (seof >= 0) { rv=0; goto end; }
 
347
                        out+=v;
 
348
                        }
 
349
                }
 
350
        rv=1;
 
351
end:
 
352
        *outl=ret;
 
353
        ctx->num=n;
 
354
        ctx->line_num=ln;
 
355
        ctx->expect_nl=exp_nl;
 
356
        return(rv);
 
357
        }
 
358
 
 
359
int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n)
 
360
        {
 
361
        int i,ret=0,a,b,c,d;
 
362
        unsigned long l;
 
363
 
 
364
        /* trim white space from the start of the line. */
 
365
        while ((conv_ascii2bin(*f) == B64_WS) && (n > 0))
 
366
                {
 
367
                f++;
 
368
                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
        while ((n > 3) && (B64_NOT_BASE64(conv_ascii2bin(f[n-1]))))
 
374
                n--;
 
375
 
 
376
        if (n%4 != 0) return(-1);
 
377
 
 
378
        for (i=0; i<n; i+=4)
 
379
                {
 
380
                a=conv_ascii2bin(*(f++));
 
381
                b=conv_ascii2bin(*(f++));
 
382
                c=conv_ascii2bin(*(f++));
 
383
                d=conv_ascii2bin(*(f++));
 
384
                if (    (a & 0x80) || (b & 0x80) ||
 
385
                        (c & 0x80) || (d & 0x80))
 
386
                        return(-1);
 
387
                l=(     (((unsigned long)a)<<18L)|
 
388
                        (((unsigned long)b)<<12L)|
 
389
                        (((unsigned long)c)<< 6L)|
 
390
                        (((unsigned long)d)     ));
 
391
                *(t++)=(unsigned char)(l>>16L)&0xff;
 
392
                *(t++)=(unsigned char)(l>> 8L)&0xff;
 
393
                *(t++)=(unsigned char)(l     )&0xff;
 
394
                ret+=3;
 
395
                }
 
396
        return(ret);
 
397
        }
 
398
 
 
399
int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
 
400
        {
 
401
        int i;
 
402
 
 
403
        *outl=0;
 
404
        if (ctx->num != 0)
 
405
                {
 
406
                i=EVP_DecodeBlock(out,ctx->enc_data,ctx->num);
 
407
                if (i < 0) return(-1);
 
408
                ctx->num=0;
 
409
                *outl=i;
 
410
                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