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