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