xref: /openssl/crypto/evp/encode.c (revision 7ed6de99)
1 /*
2  * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #include <stdio.h>
11 #include <limits.h>
12 #include "internal/cryptlib.h"
13 #include <openssl/evp.h>
14 #include "crypto/evp.h"
15 #include "evp_local.h"
16 
17 static unsigned char conv_ascii2bin(unsigned char a,
18                                     const unsigned char *table);
19 static int evp_encodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t,
20                                const unsigned char *f, int dlen);
21 static int evp_decodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t,
22                                const unsigned char *f, int n);
23 
24 #ifndef CHARSET_EBCDIC
25 # define conv_bin2ascii(a, table)       ((table)[(a)&0x3f])
26 #else
27 /*
28  * We assume that PEM encoded files are EBCDIC files (i.e., printable text
29  * files). Convert them here while decoding. When encoding, output is EBCDIC
30  * (text) format again. (No need for conversion in the conv_bin2ascii macro,
31  * as the underlying textstring data_bin2ascii[] is already EBCDIC)
32  */
33 # define conv_bin2ascii(a, table)       ((table)[(a)&0x3f])
34 #endif
35 
36 /*-
37  * 64 char lines
38  * pad input with 0
39  * left over chars are set to =
40  * 1 byte  => xx==
41  * 2 bytes => xxx=
42  * 3 bytes => xxxx
43  */
44 #define BIN_PER_LINE    (64/4*3)
45 #define CHUNKS_PER_LINE (64/4)
46 #define CHAR_PER_LINE   (64+1)
47 
48 static const unsigned char data_bin2ascii[65] =
49     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
50 
51 /* SRP uses a different base64 alphabet */
52 static const unsigned char srpdata_bin2ascii[65] =
53     "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./";
54 
55 
56 /*-
57  * 0xF0 is a EOLN
58  * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing).
59  * 0xF2 is EOF
60  * 0xE0 is ignore at start of line.
61  * 0xFF is error
62  */
63 
64 #define B64_EOLN                0xF0
65 #define B64_CR                  0xF1
66 #define B64_EOF                 0xF2
67 #define B64_WS                  0xE0
68 #define B64_ERROR               0xFF
69 #define B64_NOT_BASE64(a)       (((a)|0x13) == 0xF3)
70 #define B64_BASE64(a)           (!B64_NOT_BASE64(a))
71 
72 static const unsigned char data_ascii2bin[128] = {
73     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
74     0xFF, 0xE0, 0xF0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
75     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
76     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
77     0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
78     0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F,
79     0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
80     0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
81     0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
82     0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
83     0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
84     0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
85     0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
86     0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
87     0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
88     0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
89 };
90 
91 static const unsigned char srpdata_ascii2bin[128] = {
92     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
93     0xFF, 0xE0, 0xF0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
94     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
95     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
96     0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
97     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF2, 0x3E, 0x3F,
98     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
99     0x08, 0x09, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
100     0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
101     0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
102     0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
103     0x21, 0x22, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
104     0xFF, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,
105     0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
106     0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
107     0x3B, 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
108 };
109 
110 #ifndef CHARSET_EBCDIC
conv_ascii2bin(unsigned char a,const unsigned char * table)111 static unsigned char conv_ascii2bin(unsigned char a, const unsigned char *table)
112 {
113     if (a & 0x80)
114         return B64_ERROR;
115     return table[a];
116 }
117 #else
conv_ascii2bin(unsigned char a,const unsigned char * table)118 static unsigned char conv_ascii2bin(unsigned char a, const unsigned char *table)
119 {
120     a = os_toascii[a];
121     if (a & 0x80)
122         return B64_ERROR;
123     return table[a];
124 }
125 #endif
126 
EVP_ENCODE_CTX_new(void)127 EVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void)
128 {
129     return OPENSSL_zalloc(sizeof(EVP_ENCODE_CTX));
130 }
131 
EVP_ENCODE_CTX_free(EVP_ENCODE_CTX * ctx)132 void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx)
133 {
134     OPENSSL_free(ctx);
135 }
136 
EVP_ENCODE_CTX_copy(EVP_ENCODE_CTX * dctx,const EVP_ENCODE_CTX * sctx)137 int EVP_ENCODE_CTX_copy(EVP_ENCODE_CTX *dctx, const EVP_ENCODE_CTX *sctx)
138 {
139     memcpy(dctx, sctx, sizeof(EVP_ENCODE_CTX));
140 
141     return 1;
142 }
143 
EVP_ENCODE_CTX_num(EVP_ENCODE_CTX * ctx)144 int EVP_ENCODE_CTX_num(EVP_ENCODE_CTX *ctx)
145 {
146     return ctx->num;
147 }
148 
evp_encode_ctx_set_flags(EVP_ENCODE_CTX * ctx,unsigned int flags)149 void evp_encode_ctx_set_flags(EVP_ENCODE_CTX *ctx, unsigned int flags)
150 {
151     ctx->flags = flags;
152 }
153 
EVP_EncodeInit(EVP_ENCODE_CTX * ctx)154 void EVP_EncodeInit(EVP_ENCODE_CTX *ctx)
155 {
156     ctx->length = 48;
157     ctx->num = 0;
158     ctx->line_num = 0;
159     ctx->flags = 0;
160 }
161 
EVP_EncodeUpdate(EVP_ENCODE_CTX * ctx,unsigned char * out,int * outl,const unsigned char * in,int inl)162 int EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
163                       const unsigned char *in, int inl)
164 {
165     int i, j;
166     size_t total = 0;
167 
168     *outl = 0;
169     if (inl <= 0)
170         return 0;
171     OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data));
172     if (ctx->length - ctx->num > inl) {
173         memcpy(&(ctx->enc_data[ctx->num]), in, inl);
174         ctx->num += inl;
175         return 1;
176     }
177     if (ctx->num != 0) {
178         i = ctx->length - ctx->num;
179         memcpy(&(ctx->enc_data[ctx->num]), in, i);
180         in += i;
181         inl -= i;
182         j = evp_encodeblock_int(ctx, out, ctx->enc_data, ctx->length);
183         ctx->num = 0;
184         out += j;
185         total = j;
186         if ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0) {
187             *(out++) = '\n';
188             total++;
189         }
190         *out = '\0';
191     }
192     while (inl >= ctx->length && total <= INT_MAX) {
193         j = evp_encodeblock_int(ctx, out, in, ctx->length);
194         in += ctx->length;
195         inl -= ctx->length;
196         out += j;
197         total += j;
198         if ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0) {
199             *(out++) = '\n';
200             total++;
201         }
202         *out = '\0';
203     }
204     if (total > INT_MAX) {
205         /* Too much output data! */
206         *outl = 0;
207         return 0;
208     }
209     if (inl != 0)
210         memcpy(&(ctx->enc_data[0]), in, inl);
211     ctx->num = inl;
212     *outl = total;
213 
214     return 1;
215 }
216 
EVP_EncodeFinal(EVP_ENCODE_CTX * ctx,unsigned char * out,int * outl)217 void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
218 {
219     unsigned int ret = 0;
220 
221     if (ctx->num != 0) {
222         ret = evp_encodeblock_int(ctx, out, ctx->enc_data, ctx->num);
223         if ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0)
224             out[ret++] = '\n';
225         out[ret] = '\0';
226         ctx->num = 0;
227     }
228     *outl = ret;
229 }
230 
evp_encodeblock_int(EVP_ENCODE_CTX * ctx,unsigned char * t,const unsigned char * f,int dlen)231 static int evp_encodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t,
232                                const unsigned char *f, int dlen)
233 {
234     int i, ret = 0;
235     unsigned long l;
236     const unsigned char *table;
237 
238     if (ctx != NULL && (ctx->flags & EVP_ENCODE_CTX_USE_SRP_ALPHABET) != 0)
239         table = srpdata_bin2ascii;
240     else
241         table = data_bin2ascii;
242 
243     for (i = dlen; i > 0; i -= 3) {
244         if (i >= 3) {
245             l = (((unsigned long)f[0]) << 16L) |
246                 (((unsigned long)f[1]) << 8L) | f[2];
247             *(t++) = conv_bin2ascii(l >> 18L, table);
248             *(t++) = conv_bin2ascii(l >> 12L, table);
249             *(t++) = conv_bin2ascii(l >> 6L, table);
250             *(t++) = conv_bin2ascii(l, table);
251         } else {
252             l = ((unsigned long)f[0]) << 16L;
253             if (i == 2)
254                 l |= ((unsigned long)f[1] << 8L);
255 
256             *(t++) = conv_bin2ascii(l >> 18L, table);
257             *(t++) = conv_bin2ascii(l >> 12L, table);
258             *(t++) = (i == 1) ? '=' : conv_bin2ascii(l >> 6L, table);
259             *(t++) = '=';
260         }
261         ret += 4;
262         f += 3;
263     }
264 
265     *t = '\0';
266     return ret;
267 }
268 
EVP_EncodeBlock(unsigned char * t,const unsigned char * f,int dlen)269 int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen)
270 {
271     return evp_encodeblock_int(NULL, t, f, dlen);
272 }
273 
EVP_DecodeInit(EVP_ENCODE_CTX * ctx)274 void EVP_DecodeInit(EVP_ENCODE_CTX *ctx)
275 {
276     /* Only ctx->num and ctx->flags are used during decoding. */
277     ctx->num = 0;
278     ctx->length = 0;
279     ctx->line_num = 0;
280     ctx->flags = 0;
281 }
282 
283 /*-
284  * -1 for error
285  *  0 for last line
286  *  1 for full line
287  *
288  * Note: even though EVP_DecodeUpdate attempts to detect and report end of
289  * content, the context doesn't currently remember it and will accept more data
290  * in the next call. Therefore, the caller is responsible for checking and
291  * rejecting a 0 return value in the middle of content.
292  *
293  * Note: even though EVP_DecodeUpdate has historically tried to detect end of
294  * content based on line length, this has never worked properly. Therefore,
295  * we now return 0 when one of the following is true:
296  *   - Padding or B64_EOF was detected and the last block is complete.
297  *   - Input has zero-length.
298  * -1 is returned if:
299  *   - Invalid characters are detected.
300  *   - There is extra trailing padding, or data after padding.
301  *   - B64_EOF is detected after an incomplete base64 block.
302  */
EVP_DecodeUpdate(EVP_ENCODE_CTX * ctx,unsigned char * out,int * outl,const unsigned char * in,int inl)303 int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
304                      const unsigned char *in, int inl)
305 {
306     int seof = 0, eof = 0, rv = -1, ret = 0, i, v, tmp, n, decoded_len;
307     unsigned char *d;
308     const unsigned char *table;
309 
310     n = ctx->num;
311     d = ctx->enc_data;
312 
313     if (n > 0 && d[n - 1] == '=') {
314         eof++;
315         if (n > 1 && d[n - 2] == '=')
316             eof++;
317     }
318 
319      /* Legacy behaviour: an empty input chunk signals end of input. */
320     if (inl == 0) {
321         rv = 0;
322         goto end;
323     }
324 
325     if ((ctx->flags & EVP_ENCODE_CTX_USE_SRP_ALPHABET) != 0)
326         table = srpdata_ascii2bin;
327     else
328         table = data_ascii2bin;
329 
330     for (i = 0; i < inl; i++) {
331         tmp = *(in++);
332         v = conv_ascii2bin(tmp, table);
333         if (v == B64_ERROR) {
334             rv = -1;
335             goto end;
336         }
337 
338         if (tmp == '=') {
339             eof++;
340         } else if (eof > 0 && B64_BASE64(v)) {
341             /* More data after padding. */
342             rv = -1;
343             goto end;
344         }
345 
346         if (eof > 2) {
347             rv = -1;
348             goto end;
349         }
350 
351         if (v == B64_EOF) {
352             seof = 1;
353             goto tail;
354         }
355 
356         /* Only save valid base64 characters. */
357         if (B64_BASE64(v)) {
358             if (n >= 64) {
359                 /*
360                  * We increment n once per loop, and empty the buffer as soon as
361                  * we reach 64 characters, so this can only happen if someone's
362                  * manually messed with the ctx. Refuse to write any more data.
363                  */
364                 rv = -1;
365                 goto end;
366             }
367             OPENSSL_assert(n < (int)sizeof(ctx->enc_data));
368             d[n++] = tmp;
369         }
370 
371         if (n == 64) {
372             decoded_len = evp_decodeblock_int(ctx, out, d, n);
373             n = 0;
374             if (decoded_len < 0 || eof > decoded_len) {
375                 rv = -1;
376                 goto end;
377             }
378             ret += decoded_len - eof;
379             out += decoded_len - eof;
380         }
381     }
382 
383     /*
384      * Legacy behaviour: if the current line is a full base64-block (i.e., has
385      * 0 mod 4 base64 characters), it is processed immediately. We keep this
386      * behaviour as applications may not be calling EVP_DecodeFinal properly.
387      */
388 tail:
389     if (n > 0) {
390         if ((n & 3) == 0) {
391             decoded_len = evp_decodeblock_int(ctx, out, d, n);
392             n = 0;
393             if (decoded_len < 0 || eof > decoded_len) {
394                 rv = -1;
395                 goto end;
396             }
397             ret += (decoded_len - eof);
398         } else if (seof) {
399             /* EOF in the middle of a base64 block. */
400             rv = -1;
401             goto end;
402         }
403     }
404 
405     rv = seof || (n == 0 && eof) ? 0 : 1;
406 end:
407     /* Legacy behaviour. This should probably rather be zeroed on error. */
408     *outl = ret;
409     ctx->num = n;
410     return rv;
411 }
412 
evp_decodeblock_int(EVP_ENCODE_CTX * ctx,unsigned char * t,const unsigned char * f,int n)413 static int evp_decodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t,
414                                const unsigned char *f, int n)
415 {
416     int i, ret = 0, a, b, c, d;
417     unsigned long l;
418     const unsigned char *table;
419 
420     if (ctx != NULL && (ctx->flags & EVP_ENCODE_CTX_USE_SRP_ALPHABET) != 0)
421         table = srpdata_ascii2bin;
422     else
423         table = data_ascii2bin;
424 
425     /* trim whitespace from the start of the line. */
426     while ((n > 0) && (conv_ascii2bin(*f, table) == B64_WS)) {
427         f++;
428         n--;
429     }
430 
431     /*
432      * strip off stuff at the end of the line ascii2bin values B64_WS,
433      * B64_EOLN, B64_EOLN and B64_EOF
434      */
435     while ((n > 3) && (B64_NOT_BASE64(conv_ascii2bin(f[n - 1], table))))
436         n--;
437 
438     if (n % 4 != 0)
439         return -1;
440 
441     for (i = 0; i < n; i += 4) {
442         a = conv_ascii2bin(*(f++), table);
443         b = conv_ascii2bin(*(f++), table);
444         c = conv_ascii2bin(*(f++), table);
445         d = conv_ascii2bin(*(f++), table);
446         if ((a | b | c | d) & 0x80)
447             return -1;
448         l = ((((unsigned long)a) << 18L) |
449              (((unsigned long)b) << 12L) |
450              (((unsigned long)c) << 6L) | (((unsigned long)d)));
451         *(t++) = (unsigned char)(l >> 16L) & 0xff;
452         *(t++) = (unsigned char)(l >> 8L) & 0xff;
453         *(t++) = (unsigned char)(l) & 0xff;
454         ret += 3;
455     }
456     return ret;
457 }
458 
EVP_DecodeBlock(unsigned char * t,const unsigned char * f,int n)459 int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n)
460 {
461     return evp_decodeblock_int(NULL, t, f, n);
462 }
463 
EVP_DecodeFinal(EVP_ENCODE_CTX * ctx,unsigned char * out,int * outl)464 int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
465 {
466     int i;
467 
468     *outl = 0;
469     if (ctx->num != 0) {
470         i = evp_decodeblock_int(ctx, out, ctx->enc_data, ctx->num);
471         if (i < 0)
472             return -1;
473         ctx->num = 0;
474         *outl = i;
475         return 1;
476     } else
477         return 1;
478 }
479