xref: /openbsd/lib/libcrypto/asn1/a_type.c (revision c9ae38aa)
1 /* $OpenBSD: a_type.c,v 1.27 2023/07/28 10:00:10 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 <string.h>
60 
61 #include <openssl/asn1t.h>
62 #include <openssl/err.h>
63 #include <openssl/objects.h>
64 
65 #include "asn1_local.h"
66 
67 typedef struct {
68 	ASN1_INTEGER *num;
69 	ASN1_OCTET_STRING *value;
70 } ASN1_int_octetstring;
71 
72 static const ASN1_TEMPLATE ASN1_INT_OCTETSTRING_seq_tt[] = {
73 	{
74 		.offset = offsetof(ASN1_int_octetstring, num),
75 		.field_name = "num",
76 		.item = &ASN1_INTEGER_it,
77 	},
78 	{
79 		.offset = offsetof(ASN1_int_octetstring, value),
80 		.field_name = "value",
81 		.item = &ASN1_OCTET_STRING_it,
82 	},
83 };
84 
85 const ASN1_ITEM ASN1_INT_OCTETSTRING_it = {
86 	.itype = ASN1_ITYPE_SEQUENCE,
87 	.utype = V_ASN1_SEQUENCE,
88 	.templates = ASN1_INT_OCTETSTRING_seq_tt,
89 	.tcount = sizeof(ASN1_INT_OCTETSTRING_seq_tt) / sizeof(ASN1_TEMPLATE),
90 	.size = sizeof(ASN1_int_octetstring),
91 	.sname = "ASN1_INT_OCTETSTRING",
92 };
93 
94 ASN1_TYPE *
ASN1_TYPE_new(void)95 ASN1_TYPE_new(void)
96 {
97 	return (ASN1_TYPE *)ASN1_item_new(&ASN1_ANY_it);
98 }
99 LCRYPTO_ALIAS(ASN1_TYPE_new);
100 
101 void
ASN1_TYPE_free(ASN1_TYPE * a)102 ASN1_TYPE_free(ASN1_TYPE *a)
103 {
104 	ASN1_item_free((ASN1_VALUE *)a, &ASN1_ANY_it);
105 }
106 LCRYPTO_ALIAS(ASN1_TYPE_free);
107 
108 int
ASN1_TYPE_get(const ASN1_TYPE * a)109 ASN1_TYPE_get(const ASN1_TYPE *a)
110 {
111 	/* Special non-pointer types. */
112 	if (a->type == V_ASN1_BOOLEAN || a->type == V_ASN1_NULL)
113 		return a->type;
114 
115 	if (a->value.ptr != NULL)
116 		return a->type;
117 
118 	return 0;
119 }
120 LCRYPTO_ALIAS(ASN1_TYPE_get);
121 
122 void
ASN1_TYPE_set(ASN1_TYPE * a,int type,void * value)123 ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value)
124 {
125 	if (a->value.ptr != NULL) {
126 		ASN1_TYPE **tmp_a = &a;
127 		ASN1_primitive_free((ASN1_VALUE **)tmp_a, NULL);
128 	}
129 	a->type = type;
130 	if (type == V_ASN1_BOOLEAN)
131 		a->value.boolean = value ? 0xff : 0;
132 	else
133 		a->value.ptr = value;
134 }
135 LCRYPTO_ALIAS(ASN1_TYPE_set);
136 
137 int
ASN1_TYPE_set1(ASN1_TYPE * a,int type,const void * value)138 ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value)
139 {
140 	if (!value || (type == V_ASN1_BOOLEAN)) {
141 		void *p = (void *)value;
142 		ASN1_TYPE_set(a, type, p);
143 	} else if (type == V_ASN1_OBJECT) {
144 		ASN1_OBJECT *odup;
145 		odup = OBJ_dup(value);
146 		if (!odup)
147 			return 0;
148 		ASN1_TYPE_set(a, type, odup);
149 	} else {
150 		ASN1_STRING *sdup;
151 		sdup = ASN1_STRING_dup(value);
152 		if (!sdup)
153 			return 0;
154 		ASN1_TYPE_set(a, type, sdup);
155 	}
156 	return 1;
157 }
158 LCRYPTO_ALIAS(ASN1_TYPE_set1);
159 
160 /* Returns 0 if they are equal, != 0 otherwise. */
161 int
ASN1_TYPE_cmp(const ASN1_TYPE * a,const ASN1_TYPE * b)162 ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b)
163 {
164 	int result = -1;
165 
166 	if (!a || !b || a->type != b->type)
167 		return -1;
168 
169 	switch (a->type) {
170 	case V_ASN1_OBJECT:
171 		result = OBJ_cmp(a->value.object, b->value.object);
172 		break;
173 	case V_ASN1_BOOLEAN:
174 		result = a->value.boolean - b->value.boolean;
175 		break;
176 	case V_ASN1_NULL:
177 		result = 0;	/* They do not have content. */
178 		break;
179 
180 	case V_ASN1_INTEGER:
181 	case V_ASN1_ENUMERATED:
182 	case V_ASN1_BIT_STRING:
183 	case V_ASN1_OCTET_STRING:
184 	case V_ASN1_SEQUENCE:
185 	case V_ASN1_SET:
186 	case V_ASN1_NUMERICSTRING:
187 	case V_ASN1_PRINTABLESTRING:
188 	case V_ASN1_T61STRING:
189 	case V_ASN1_VIDEOTEXSTRING:
190 	case V_ASN1_IA5STRING:
191 	case V_ASN1_UTCTIME:
192 	case V_ASN1_GENERALIZEDTIME:
193 	case V_ASN1_GRAPHICSTRING:
194 	case V_ASN1_VISIBLESTRING:
195 	case V_ASN1_GENERALSTRING:
196 	case V_ASN1_UNIVERSALSTRING:
197 	case V_ASN1_BMPSTRING:
198 	case V_ASN1_UTF8STRING:
199 	case V_ASN1_OTHER:
200 	default:
201 		result = ASN1_STRING_cmp((ASN1_STRING *)a->value.ptr,
202 		    (ASN1_STRING *)b->value.ptr);
203 		break;
204 	}
205 
206 	return result;
207 }
208 LCRYPTO_ALIAS(ASN1_TYPE_cmp);
209 
210 int
ASN1_TYPE_set_octetstring(ASN1_TYPE * a,const unsigned char * data,int len)211 ASN1_TYPE_set_octetstring(ASN1_TYPE *a, const unsigned char *data, int len)
212 {
213 	ASN1_STRING *os;
214 
215 	if ((os = ASN1_OCTET_STRING_new()) == NULL)
216 		return (0);
217 	if (!ASN1_STRING_set(os, data, len)) {
218 		ASN1_OCTET_STRING_free(os);
219 		return (0);
220 	}
221 	ASN1_TYPE_set(a, V_ASN1_OCTET_STRING, os);
222 	return (1);
223 }
224 LCRYPTO_ALIAS(ASN1_TYPE_set_octetstring);
225 
226 int
ASN1_TYPE_get_octetstring(const ASN1_TYPE * a,unsigned char * data,int max_len)227 ASN1_TYPE_get_octetstring(const ASN1_TYPE *a, unsigned char *data, int max_len)
228 {
229 	int ret, num;
230 	unsigned char *p;
231 
232 	if ((a->type != V_ASN1_OCTET_STRING) ||
233 	    (a->value.octet_string == NULL)) {
234 		ASN1error(ASN1_R_DATA_IS_WRONG);
235 		return (-1);
236 	}
237 	p = ASN1_STRING_data(a->value.octet_string);
238 	ret = ASN1_STRING_length(a->value.octet_string);
239 	if (ret < max_len)
240 		num = ret;
241 	else
242 		num = max_len;
243 	memcpy(data, p, num);
244 	return (ret);
245 }
246 LCRYPTO_ALIAS(ASN1_TYPE_get_octetstring);
247 
248 int
ASN1_TYPE_set_int_octetstring(ASN1_TYPE * at,long num,const unsigned char * data,int len)249 ASN1_TYPE_set_int_octetstring(ASN1_TYPE *at, long num, const unsigned char *data,
250     int len)
251 {
252 	ASN1_int_octetstring *ios;
253 	ASN1_STRING *sp = NULL;
254 	int ret = 0;
255 
256 	if ((ios = (ASN1_int_octetstring *)ASN1_item_new(
257 	    &ASN1_INT_OCTETSTRING_it)) == NULL)
258 		goto err;
259 	if (!ASN1_INTEGER_set(ios->num, num))
260 		goto err;
261 	if (!ASN1_OCTET_STRING_set(ios->value, data, len))
262 		goto err;
263 
264 	if ((sp = ASN1_item_pack(ios, &ASN1_INT_OCTETSTRING_it, NULL)) == NULL)
265 		goto err;
266 
267 	ASN1_TYPE_set(at, V_ASN1_SEQUENCE, sp);
268 	sp = NULL;
269 
270 	ret = 1;
271 
272  err:
273 	ASN1_item_free((ASN1_VALUE *)ios, &ASN1_INT_OCTETSTRING_it);
274 	ASN1_STRING_free(sp);
275 
276 	return ret;
277 }
278 LCRYPTO_ALIAS(ASN1_TYPE_set_int_octetstring);
279 
280 int
ASN1_TYPE_get_int_octetstring(const ASN1_TYPE * at,long * num,unsigned char * data,int max_len)281 ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *at, long *num, unsigned char *data,
282     int max_len)
283 {
284 	ASN1_STRING *sp = at->value.sequence;
285 	ASN1_int_octetstring *ios = NULL;
286 	int ret = -1;
287 	int len;
288 
289 	if (at->type != V_ASN1_SEQUENCE || sp == NULL)
290 		goto err;
291 
292 	if ((ios = ASN1_item_unpack(sp, &ASN1_INT_OCTETSTRING_it)) == NULL)
293 		goto err;
294 
295 	if (num != NULL)
296 		*num = ASN1_INTEGER_get(ios->num);
297 	if (data != NULL) {
298 		len = ASN1_STRING_length(ios->value);
299 		if (len > max_len)
300 			len = max_len;
301 		memcpy(data, ASN1_STRING_data(ios->value), len);
302 	}
303 
304 	ret = ASN1_STRING_length(ios->value);
305 
306  err:
307 	ASN1_item_free((ASN1_VALUE *)ios, &ASN1_INT_OCTETSTRING_it);
308 
309 	if (ret == -1)
310 		ASN1error(ASN1_R_DATA_IS_WRONG);
311 
312 	return ret;
313 }
314 LCRYPTO_ALIAS(ASN1_TYPE_get_int_octetstring);
315 
316 ASN1_TYPE *
ASN1_TYPE_pack_sequence(const ASN1_ITEM * it,void * s,ASN1_TYPE ** t)317 ASN1_TYPE_pack_sequence(const ASN1_ITEM *it, void *s, ASN1_TYPE **t)
318 {
319 	ASN1_OCTET_STRING *oct;
320 	ASN1_TYPE *rt;
321 
322 	if ((oct = ASN1_item_pack(s, it, NULL)) == NULL)
323 		return NULL;
324 
325 	if (t != NULL && *t != NULL) {
326 		rt = *t;
327 	} else {
328 		if ((rt = ASN1_TYPE_new()) == NULL) {
329 			ASN1_OCTET_STRING_free(oct);
330 			return NULL;
331 		}
332 		if (t != NULL)
333 			*t = rt;
334 	}
335 	ASN1_TYPE_set(rt, V_ASN1_SEQUENCE, oct);
336 	return rt;
337 }
338 
339 void *
ASN1_TYPE_unpack_sequence(const ASN1_ITEM * it,const ASN1_TYPE * t)340 ASN1_TYPE_unpack_sequence(const ASN1_ITEM *it, const ASN1_TYPE *t)
341 {
342 	if (t == NULL || t->type != V_ASN1_SEQUENCE || t->value.sequence == NULL)
343 		return NULL;
344 	return ASN1_item_unpack(t->value.sequence, it);
345 }
346 
347 int
i2d_ASN1_TYPE(ASN1_TYPE * a,unsigned char ** out)348 i2d_ASN1_TYPE(ASN1_TYPE *a, unsigned char **out)
349 {
350 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_ANY_it);
351 }
352 LCRYPTO_ALIAS(i2d_ASN1_TYPE);
353 
354 ASN1_TYPE *
d2i_ASN1_TYPE(ASN1_TYPE ** a,const unsigned char ** in,long len)355 d2i_ASN1_TYPE(ASN1_TYPE **a, const unsigned char **in, long len)
356 {
357 	return (ASN1_TYPE *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
358 	    &ASN1_ANY_it);
359 }
360 LCRYPTO_ALIAS(d2i_ASN1_TYPE);
361