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