xref: /dragonfly/crypto/libressl/crypto/evp/encode.c (revision 961e30ea7dc61d1112b778ea4981eac68129fb86)
1 /* $OpenBSD: encode.c,v 1.29 2021/12/12 21:30:13 tb Exp $ */
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 <limits.h>
60 #include <stdio.h>
61 #include <string.h>
62 
63 #include <openssl/evp.h>
64 
65 #include "evp_locl.h"
66 
67 static unsigned char conv_ascii2bin(unsigned char a);
68 #define conv_bin2ascii(a)     (data_bin2ascii[(a)&0x3f])
69 
70 /* 64 char lines
71  * pad input with 0
72  * left over chars are set to =
73  * 1 byte  => xx==
74  * 2 bytes => xxx=
75  * 3 bytes => xxxx
76  */
77 #define BIN_PER_LINE    (64/4*3)
78 #define CHUNKS_PER_LINE (64/4)
79 #define CHAR_PER_LINE   (64+1)
80 
81 static const unsigned char data_bin2ascii[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\
82 abcdefghijklmnopqrstuvwxyz0123456789+/";
83 
84 /* 0xF0 is a EOLN
85  * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing).
86  * 0xF2 is EOF
87  * 0xE0 is ignore at start of line.
88  * 0xFF is error
89  */
90 
91 #define B64_EOLN              0xF0
92 #define B64_CR                          0xF1
93 #define B64_EOF                         0xF2
94 #define B64_WS                          0xE0
95 #define B64_ERROR             0xFF
96 #define B64_NOT_BASE64(a)     (((a)|0x13) == 0xF3)
97 #define B64_BASE64(a)                   !B64_NOT_BASE64(a)
98 
99 static const unsigned char data_ascii2bin[128] = {
100           0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
101           0xFF, 0xE0, 0xF0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
102           0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
103           0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
104           0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
105           0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F,
106           0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
107           0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
108           0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
109           0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
110           0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
111           0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
112           0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
113           0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
114           0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
115           0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
116 };
117 
118 static unsigned char
conv_ascii2bin(unsigned char a)119 conv_ascii2bin(unsigned char a)
120 {
121           if (a & 0x80)
122                     return B64_ERROR;
123           return data_ascii2bin[a];
124 }
125 
126 EVP_ENCODE_CTX *
EVP_ENCODE_CTX_new(void)127 EVP_ENCODE_CTX_new(void)
128 {
129           return calloc(1, sizeof(EVP_ENCODE_CTX));
130 }
131 
132 void
EVP_ENCODE_CTX_free(EVP_ENCODE_CTX * ctx)133 EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx)
134 {
135           free(ctx);
136 }
137 
138 void
EVP_EncodeInit(EVP_ENCODE_CTX * ctx)139 EVP_EncodeInit(EVP_ENCODE_CTX *ctx)
140 {
141           ctx->length = 48;
142           ctx->num = 0;
143           ctx->line_num = 0;
144 }
145 
146 int
EVP_EncodeUpdate(EVP_ENCODE_CTX * ctx,unsigned char * out,int * outl,const unsigned char * in,int inl)147 EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
148     const unsigned char *in, int inl)
149 {
150           int i, j;
151           size_t total = 0;
152 
153           *outl = 0;
154           if (inl <= 0)
155                     return 0;
156           OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data));
157           if (ctx->length - ctx->num > inl) {
158                     memcpy(&(ctx->enc_data[ctx->num]), in, inl);
159                     ctx->num += inl;
160                     return 1;
161           }
162           if (ctx->num != 0) {
163                     i = ctx->length - ctx->num;
164                     memcpy(&(ctx->enc_data[ctx->num]), in, i);
165                     in += i;
166                     inl -= i;
167                     j = EVP_EncodeBlock(out, ctx->enc_data, ctx->length);
168                     ctx->num = 0;
169                     out += j;
170                     *(out++) = '\n';
171                     *out = '\0';
172                     total = j + 1;
173           }
174           while (inl >= ctx->length && total <= INT_MAX) {
175                     j = EVP_EncodeBlock(out, in, ctx->length);
176                     in += ctx->length;
177                     inl -= ctx->length;
178                     out += j;
179                     *(out++) = '\n';
180                     *out = '\0';
181                     total += j + 1;
182           }
183           if (total > INT_MAX) {
184                     /* Too much output data! */
185                     *outl = 0;
186                     return 0;
187           }
188           if (inl != 0)
189                     memcpy(&(ctx->enc_data[0]), in, inl);
190           ctx->num = inl;
191           *outl = total;
192 
193           return 1;
194 }
195 
196 void
EVP_EncodeFinal(EVP_ENCODE_CTX * ctx,unsigned char * out,int * outl)197 EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
198 {
199           unsigned int ret = 0;
200 
201           if (ctx->num != 0) {
202                     ret = EVP_EncodeBlock(out, ctx->enc_data, ctx->num);
203                     out[ret++] = '\n';
204                     out[ret] = '\0';
205                     ctx->num = 0;
206           }
207           *outl = ret;
208 }
209 
210 int
EVP_EncodeBlock(unsigned char * t,const unsigned char * f,int dlen)211 EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen)
212 {
213           int i, ret = 0;
214           unsigned long l;
215 
216           for (i = dlen; i > 0; i -= 3) {
217                     if (i >= 3) {
218                               l = (((unsigned long)f[0]) << 16L) |
219                                   (((unsigned long)f[1]) << 8L) | f[2];
220                               *(t++) = conv_bin2ascii(l >> 18L);
221                               *(t++) = conv_bin2ascii(l >> 12L);
222                               *(t++) = conv_bin2ascii(l >> 6L);
223                               *(t++) = conv_bin2ascii(l     );
224                     } else {
225                               l = ((unsigned long)f[0]) << 16L;
226                               if (i == 2)
227                                         l |= ((unsigned long)f[1] << 8L);
228 
229                               *(t++) = conv_bin2ascii(l >> 18L);
230                               *(t++) = conv_bin2ascii(l >> 12L);
231                               *(t++) = (i == 1) ? '=' : conv_bin2ascii(l >> 6L);
232                               *(t++) = '=';
233                     }
234                     ret += 4;
235                     f += 3;
236           }
237 
238           *t = '\0';
239           return (ret);
240 }
241 
242 void
EVP_DecodeInit(EVP_ENCODE_CTX * ctx)243 EVP_DecodeInit(EVP_ENCODE_CTX *ctx)
244 {
245           ctx->num = 0;
246           ctx->length = 0;
247           ctx->line_num = 0;
248           ctx->expect_nl = 0;
249 }
250 
251 int
EVP_DecodeUpdate(EVP_ENCODE_CTX * ctx,unsigned char * out,int * outl,const unsigned char * in,int inl)252 EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
253     const unsigned char *in, int inl)
254 {
255           int seof = 0, eof = 0, rv = -1, ret = 0, i, v, tmp, n, decoded_len;
256           unsigned char *d;
257 
258           n = ctx->num;
259           d = ctx->enc_data;
260 
261           if (n > 0 && d[n - 1] == '=') {
262                     eof++;
263                     if (n > 1 && d[n - 2] == '=')
264                               eof++;
265           }
266 
267           /* Legacy behaviour: an empty input chunk signals end of input. */
268           if (inl == 0) {
269                     rv = 0;
270                     goto end;
271           }
272 
273           for (i = 0; i < inl; i++) {
274                     tmp = *(in++);
275                     v = conv_ascii2bin(tmp);
276                     if (v == B64_ERROR) {
277                               rv = -1;
278                               goto end;
279                     }
280 
281                     if (tmp == '=') {
282                               eof++;
283                     } else if (eof > 0 && B64_BASE64(v)) {
284                               /* More data after padding. */
285                               rv = -1;
286                               goto end;
287                     }
288 
289                     if (eof > 2) {
290                               rv = -1;
291                               goto end;
292                     }
293 
294                     if (v == B64_EOF) {
295                               seof = 1;
296                               goto tail;
297                     }
298 
299                     /* Only save valid base64 characters. */
300                     if (B64_BASE64(v)) {
301                               if (n >= 64) {
302                                         /*
303                                          * We increment n once per loop, and empty the
304                                          * buffer as soon as we reach 64 characters, so
305                                          * this can only happen if someone's manually
306                                          * messed with the ctx. Refuse to write any
307                                          * more data.
308                                          */
309                                         rv = -1;
310                                         goto end;
311                               }
312                               OPENSSL_assert(n < (int)sizeof(ctx->enc_data));
313                               d[n++] = tmp;
314                     }
315 
316                     if (n == 64) {
317                               decoded_len = EVP_DecodeBlock(out, d, n);
318                               n = 0;
319                               if (decoded_len < 0 || eof > decoded_len) {
320                                         rv = -1;
321                                         goto end;
322                               }
323                               ret += decoded_len - eof;
324                               out += decoded_len - eof;
325                     }
326           }
327 
328           /*
329            * Legacy behaviour: if the current line is a full base64-block (i.e.,
330            * has 0 mod 4 base64 characters), it is processed immediately. We keep
331            * this behaviour as applications may not be calling EVP_DecodeFinal
332            * properly.
333            */
334  tail:
335           if (n > 0) {
336                     if ((n & 3) == 0) {
337                               decoded_len = EVP_DecodeBlock(out, d, n);
338                               n = 0;
339                               if (decoded_len < 0 || eof > decoded_len) {
340                                         rv = -1;
341                                         goto end;
342                               }
343                               ret += (decoded_len - eof);
344                     } else if (seof) {
345                               /* EOF in the middle of a base64 block. */
346                               rv = -1;
347                               goto end;
348                     }
349           }
350 
351           rv = seof || (n == 0 && eof) ? 0 : 1;
352  end:
353           /* Legacy behaviour. This should probably rather be zeroed on error. */
354           *outl = ret;
355           ctx->num = n;
356           return (rv);
357 }
358 
359 int
EVP_DecodeBlock(unsigned char * t,const unsigned char * f,int n)360 EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n)
361 {
362           int i, ret = 0, a, b, c, d;
363           unsigned long l;
364 
365           /* trim white space from the start of the line. */
366           while ((conv_ascii2bin(*f) == B64_WS) && (n > 0)) {
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)
377                     return (-1);
378 
379           for (i = 0; i < n; i += 4) {
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 EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
401 {
402           int i;
403 
404           *outl = 0;
405           if (ctx->num != 0) {
406                     i = EVP_DecodeBlock(out, ctx->enc_data, ctx->num);
407                     if (i < 0)
408                               return (-1);
409                     ctx->num = 0;
410                     *outl = i;
411                     return (1);
412           } else
413                     return (1);
414 }
415