/src/libressl/crypto/asn1/a_string.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* $OpenBSD: a_string.c,v 1.11 2022/05/20 08:04:21 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 <stdlib.h> |
61 | | #include <string.h> |
62 | | |
63 | | #include <openssl/asn1.h> |
64 | | #include <openssl/err.h> |
65 | | |
66 | | #include "asn1_locl.h" |
67 | | |
68 | | ASN1_STRING * |
69 | | ASN1_STRING_new(void) |
70 | 0 | { |
71 | 0 | return ASN1_STRING_type_new(V_ASN1_OCTET_STRING); |
72 | 0 | } |
73 | | |
74 | | ASN1_STRING * |
75 | | ASN1_STRING_type_new(int type) |
76 | 0 | { |
77 | 0 | ASN1_STRING *astr; |
78 | |
|
79 | 0 | if ((astr = calloc(1, sizeof(ASN1_STRING))) == NULL) { |
80 | 0 | ASN1error(ERR_R_MALLOC_FAILURE); |
81 | 0 | return NULL; |
82 | 0 | } |
83 | 0 | astr->type = type; |
84 | |
|
85 | 0 | return astr; |
86 | 0 | } |
87 | | |
88 | | static void |
89 | | ASN1_STRING_clear(ASN1_STRING *astr) |
90 | 0 | { |
91 | 0 | if (!(astr->flags & ASN1_STRING_FLAG_NDEF)) |
92 | 0 | freezero(astr->data, astr->length); |
93 | |
|
94 | 0 | astr->flags &= ~ASN1_STRING_FLAG_NDEF; |
95 | 0 | astr->data = NULL; |
96 | 0 | astr->length = 0; |
97 | 0 | } |
98 | | |
99 | | void |
100 | | ASN1_STRING_free(ASN1_STRING *astr) |
101 | 0 | { |
102 | 0 | if (astr == NULL) |
103 | 0 | return; |
104 | | |
105 | 0 | ASN1_STRING_clear(astr); |
106 | |
|
107 | 0 | free(astr); |
108 | 0 | } |
109 | | |
110 | | int |
111 | | ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b) |
112 | 0 | { |
113 | 0 | int cmp; |
114 | |
|
115 | 0 | if (a == NULL || b == NULL) |
116 | 0 | return -1; |
117 | 0 | if ((cmp = (a->length - b->length)) != 0) |
118 | 0 | return cmp; |
119 | 0 | if ((cmp = memcmp(a->data, b->data, a->length)) != 0) |
120 | 0 | return cmp; |
121 | | |
122 | 0 | return (a->type - b->type); |
123 | 0 | } |
124 | | |
125 | | int |
126 | | ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *src) |
127 | 0 | { |
128 | 0 | if (src == NULL) |
129 | 0 | return 0; |
130 | | |
131 | 0 | if (!ASN1_STRING_set(dst, src->data, src->length)) |
132 | 0 | return 0; |
133 | | |
134 | 0 | dst->type = src->type; |
135 | 0 | dst->flags = src->flags & ~ASN1_STRING_FLAG_NDEF; |
136 | |
|
137 | 0 | return 1; |
138 | 0 | } |
139 | | |
140 | | ASN1_STRING * |
141 | | ASN1_STRING_dup(const ASN1_STRING *src) |
142 | 0 | { |
143 | 0 | ASN1_STRING *astr; |
144 | |
|
145 | 0 | if (src == NULL) |
146 | 0 | return NULL; |
147 | | |
148 | 0 | if ((astr = ASN1_STRING_new()) == NULL) |
149 | 0 | return NULL; |
150 | 0 | if (!ASN1_STRING_copy(astr, src)) { |
151 | 0 | ASN1_STRING_free(astr); |
152 | 0 | return NULL; |
153 | 0 | } |
154 | 0 | return astr; |
155 | 0 | } |
156 | | |
157 | | int |
158 | | ASN1_STRING_set(ASN1_STRING *astr, const void *_data, int len) |
159 | 0 | { |
160 | 0 | const char *data = _data; |
161 | |
|
162 | 0 | if (len == -1) { |
163 | 0 | size_t slen; |
164 | |
|
165 | 0 | if (data == NULL) |
166 | 0 | return 0; |
167 | | |
168 | 0 | if ((slen = strlen(data)) > INT_MAX) |
169 | 0 | return 0; |
170 | | |
171 | 0 | len = (int)slen; |
172 | 0 | } |
173 | | |
174 | 0 | ASN1_STRING_clear(astr); |
175 | |
|
176 | 0 | if (len < 0 || len >= INT_MAX) |
177 | 0 | return 0; |
178 | | |
179 | 0 | if ((astr->data = calloc(1, len + 1)) == NULL) { |
180 | 0 | ASN1error(ERR_R_MALLOC_FAILURE); |
181 | 0 | return (0); |
182 | 0 | } |
183 | 0 | astr->length = len; |
184 | |
|
185 | 0 | if (data != NULL) { |
186 | 0 | memcpy(astr->data, data, len); |
187 | 0 | astr->data[len] = '\0'; |
188 | 0 | } |
189 | |
|
190 | 0 | return 1; |
191 | 0 | } |
192 | | |
193 | | void |
194 | | ASN1_STRING_set0(ASN1_STRING *astr, void *data, int len) |
195 | 0 | { |
196 | 0 | ASN1_STRING_clear(astr); |
197 | |
|
198 | 0 | astr->data = data; |
199 | 0 | astr->length = len; |
200 | 0 | } |
201 | | |
202 | | void |
203 | | asn1_add_error(const unsigned char *address, int offset) |
204 | 0 | { |
205 | 0 | ERR_asprintf_error_data("offset=%d", offset); |
206 | 0 | } |
207 | | |
208 | | int |
209 | | ASN1_STRING_length(const ASN1_STRING *astr) |
210 | 0 | { |
211 | 0 | return astr->length; |
212 | 0 | } |
213 | | |
214 | | void |
215 | | ASN1_STRING_length_set(ASN1_STRING *astr, int len) |
216 | 0 | { |
217 | | /* This is dangerous and unfixable. */ |
218 | 0 | astr->length = len; |
219 | 0 | } |
220 | | |
221 | | int |
222 | | ASN1_STRING_type(const ASN1_STRING *astr) |
223 | 0 | { |
224 | 0 | return astr->type; |
225 | 0 | } |
226 | | |
227 | | unsigned char * |
228 | | ASN1_STRING_data(ASN1_STRING *astr) |
229 | 0 | { |
230 | 0 | return astr->data; |
231 | 0 | } |
232 | | |
233 | | const unsigned char * |
234 | | ASN1_STRING_get0_data(const ASN1_STRING *astr) |
235 | 0 | { |
236 | 0 | return astr->data; |
237 | 0 | } |
238 | | |
239 | | int |
240 | | ASN1_STRING_print(BIO *bp, const ASN1_STRING *astr) |
241 | 0 | { |
242 | 0 | int i, n; |
243 | 0 | char buf[80]; |
244 | 0 | const char *p; |
245 | |
|
246 | 0 | if (astr == NULL) |
247 | 0 | return 0; |
248 | | |
249 | 0 | n = 0; |
250 | 0 | p = (const char *)astr->data; |
251 | 0 | for (i = 0; i < astr->length; i++) { |
252 | 0 | if ((p[i] > '~') || ((p[i] < ' ') && |
253 | 0 | (p[i] != '\n') && (p[i] != '\r'))) |
254 | 0 | buf[n] = '.'; |
255 | 0 | else |
256 | 0 | buf[n] = p[i]; |
257 | 0 | n++; |
258 | 0 | if (n >= 80) { |
259 | 0 | if (BIO_write(bp, buf, n) <= 0) |
260 | 0 | return 0; |
261 | 0 | n = 0; |
262 | 0 | } |
263 | 0 | } |
264 | 0 | if (n > 0) { |
265 | 0 | if (BIO_write(bp, buf, n) <= 0) |
266 | 0 | return 0; |
267 | 0 | } |
268 | | |
269 | 0 | return 1; |
270 | 0 | } |
271 | | |
272 | | /* |
273 | | * Utility function: convert any string type to UTF8, returns number of bytes |
274 | | * in output string or a negative error code |
275 | | */ |
276 | | int |
277 | | ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in) |
278 | 0 | { |
279 | 0 | ASN1_STRING *astr = NULL; |
280 | 0 | int mbflag; |
281 | 0 | int ret = -1; |
282 | | |
283 | | /* |
284 | | * XXX We can't fail on *out != NULL here since things like haproxy and |
285 | | * grpc pass in a pointer to an uninitialized pointer on the stack. |
286 | | */ |
287 | 0 | if (out == NULL) |
288 | 0 | goto err; |
289 | | |
290 | 0 | if (in == NULL) |
291 | 0 | goto err; |
292 | | |
293 | 0 | if ((mbflag = asn1_tag2charwidth(in->type)) == -1) |
294 | 0 | goto err; |
295 | | |
296 | 0 | mbflag |= MBSTRING_FLAG; |
297 | |
|
298 | 0 | if ((ret = ASN1_mbstring_copy(&astr, in->data, in->length, mbflag, |
299 | 0 | B_ASN1_UTF8STRING)) < 0) |
300 | 0 | goto err; |
301 | | |
302 | 0 | *out = astr->data; |
303 | 0 | ret = astr->length; |
304 | |
|
305 | 0 | astr->data = NULL; |
306 | 0 | astr->length = 0; |
307 | |
|
308 | 0 | err: |
309 | 0 | ASN1_STRING_free(astr); |
310 | |
|
311 | 0 | return ret; |
312 | 0 | } |
313 | | |
314 | | int |
315 | | i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *astr, int type) |
316 | 0 | { |
317 | 0 | int i, n = 0; |
318 | 0 | static const char h[] = "0123456789ABCDEF"; |
319 | 0 | char buf[2]; |
320 | |
|
321 | 0 | if (astr == NULL) |
322 | 0 | return 0; |
323 | | |
324 | 0 | if (astr->length == 0) { |
325 | 0 | if (BIO_write(bp, "0", 1) != 1) |
326 | 0 | goto err; |
327 | 0 | n = 1; |
328 | 0 | } else { |
329 | 0 | for (i = 0; i < astr->length; i++) { |
330 | 0 | if ((i != 0) && (i % 35 == 0)) { |
331 | 0 | if (BIO_write(bp, "\\\n", 2) != 2) |
332 | 0 | goto err; |
333 | 0 | n += 2; |
334 | 0 | } |
335 | 0 | buf[0] = h[((unsigned char)astr->data[i] >> 4) & 0x0f]; |
336 | 0 | buf[1] = h[((unsigned char)astr->data[i]) & 0x0f]; |
337 | 0 | if (BIO_write(bp, buf, 2) != 2) |
338 | 0 | goto err; |
339 | 0 | n += 2; |
340 | 0 | } |
341 | 0 | } |
342 | 0 | return n; |
343 | | |
344 | 0 | err: |
345 | 0 | return -1; |
346 | 0 | } |
347 | | |
348 | | int |
349 | | a2i_ASN1_STRING(BIO *bp, ASN1_STRING *astr, char *buf, int size) |
350 | 0 | { |
351 | 0 | int ret = 0; |
352 | 0 | int i, j, k, m, n, again, bufsize; |
353 | 0 | unsigned char *s = NULL, *sp; |
354 | 0 | unsigned char *bufp; |
355 | 0 | int first = 1; |
356 | 0 | size_t num = 0, slen = 0; |
357 | |
|
358 | 0 | bufsize = BIO_gets(bp, buf, size); |
359 | 0 | for (;;) { |
360 | 0 | if (bufsize < 1) { |
361 | 0 | if (first) |
362 | 0 | break; |
363 | 0 | else |
364 | 0 | goto err_sl; |
365 | 0 | } |
366 | 0 | first = 0; |
367 | |
|
368 | 0 | i = bufsize; |
369 | 0 | if (buf[i-1] == '\n') |
370 | 0 | buf[--i] = '\0'; |
371 | 0 | if (i == 0) |
372 | 0 | goto err_sl; |
373 | 0 | if (buf[i-1] == '\r') |
374 | 0 | buf[--i] = '\0'; |
375 | 0 | if (i == 0) |
376 | 0 | goto err_sl; |
377 | 0 | if (buf[i - 1] == '\\') { |
378 | 0 | i--; |
379 | 0 | again = 1; |
380 | 0 | } else |
381 | 0 | again = 0; |
382 | 0 | buf[i] = '\0'; |
383 | 0 | if (i < 2) |
384 | 0 | goto err_sl; |
385 | | |
386 | 0 | bufp = (unsigned char *)buf; |
387 | |
|
388 | 0 | k = 0; |
389 | 0 | if (i % 2 != 0) { |
390 | 0 | ASN1error(ASN1_R_ODD_NUMBER_OF_CHARS); |
391 | 0 | goto err; |
392 | 0 | } |
393 | 0 | i /= 2; |
394 | 0 | if (num + i > slen) { |
395 | 0 | sp = realloc(s, num + i); |
396 | 0 | if (sp == NULL) { |
397 | 0 | ASN1error(ERR_R_MALLOC_FAILURE); |
398 | 0 | goto err; |
399 | 0 | } |
400 | 0 | s = sp; |
401 | 0 | slen = num + i; |
402 | 0 | } |
403 | 0 | for (j = 0; j < i; j++, k += 2) { |
404 | 0 | for (n = 0; n < 2; n++) { |
405 | 0 | m = bufp[k + n]; |
406 | 0 | if ((m >= '0') && (m <= '9')) |
407 | 0 | m -= '0'; |
408 | 0 | else if ((m >= 'a') && (m <= 'f')) |
409 | 0 | m = m - 'a' + 10; |
410 | 0 | else if ((m >= 'A') && (m <= 'F')) |
411 | 0 | m = m - 'A' + 10; |
412 | 0 | else { |
413 | 0 | ASN1error(ASN1_R_NON_HEX_CHARACTERS); |
414 | 0 | goto err; |
415 | 0 | } |
416 | 0 | s[num + j] <<= 4; |
417 | 0 | s[num + j] |= m; |
418 | 0 | } |
419 | 0 | } |
420 | 0 | num += i; |
421 | 0 | if (again) |
422 | 0 | bufsize = BIO_gets(bp, buf, size); |
423 | 0 | else |
424 | 0 | break; |
425 | 0 | } |
426 | 0 | astr->length = num; |
427 | 0 | astr->data = s; |
428 | |
|
429 | 0 | return 1; |
430 | | |
431 | 0 | err_sl: |
432 | 0 | ASN1error(ASN1_R_SHORT_LINE); |
433 | 0 | err: |
434 | 0 | free(s); |
435 | |
|
436 | 0 | return ret; |
437 | 0 | } |