xref: /openbsd-src/lib/libcrypto/x509/x509_genn.c (revision 256a93a44f36679bee503f12e49566c2183f6181)
1 /* $OpenBSD: x509_genn.c,v 1.4 2023/02/07 15:46:58 tb Exp $ */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project 1999.
4  */
5 /* ====================================================================
6  * Copyright (c) 1999-2008 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58 
59 
60 #include <stdio.h>
61 
62 #include <openssl/asn1t.h>
63 #include <openssl/conf.h>
64 #include <openssl/x509v3.h>
65 
66 static const ASN1_TEMPLATE OTHERNAME_seq_tt[] = {
67 	{
68 		.flags = 0,
69 		.tag = 0,
70 		.offset = offsetof(OTHERNAME, type_id),
71 		.field_name = "type_id",
72 		.item = &ASN1_OBJECT_it,
73 	},
74 	/* Maybe have a true ANY DEFINED BY later */
75 	{
76 		.flags = ASN1_TFLG_EXPLICIT,
77 		.tag = 0,
78 		.offset = offsetof(OTHERNAME, value),
79 		.field_name = "value",
80 		.item = &ASN1_ANY_it,
81 	},
82 };
83 
84 const ASN1_ITEM OTHERNAME_it = {
85 	.itype = ASN1_ITYPE_SEQUENCE,
86 	.utype = V_ASN1_SEQUENCE,
87 	.templates = OTHERNAME_seq_tt,
88 	.tcount = sizeof(OTHERNAME_seq_tt) / sizeof(ASN1_TEMPLATE),
89 	.funcs = NULL,
90 	.size = sizeof(OTHERNAME),
91 	.sname = "OTHERNAME",
92 };
93 
94 
95 OTHERNAME *
96 d2i_OTHERNAME(OTHERNAME **a, const unsigned char **in, long len)
97 {
98 	return (OTHERNAME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
99 	    &OTHERNAME_it);
100 }
101 LCRYPTO_ALIAS(d2i_OTHERNAME)
102 
103 int
104 i2d_OTHERNAME(OTHERNAME *a, unsigned char **out)
105 {
106 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &OTHERNAME_it);
107 }
108 LCRYPTO_ALIAS(i2d_OTHERNAME)
109 
110 OTHERNAME *
111 OTHERNAME_new(void)
112 {
113 	return (OTHERNAME *)ASN1_item_new(&OTHERNAME_it);
114 }
115 LCRYPTO_ALIAS(OTHERNAME_new)
116 
117 void
118 OTHERNAME_free(OTHERNAME *a)
119 {
120 	ASN1_item_free((ASN1_VALUE *)a, &OTHERNAME_it);
121 }
122 LCRYPTO_ALIAS(OTHERNAME_free)
123 
124 /* Uses explicit tagging since DIRECTORYSTRING is a CHOICE type */
125 static const ASN1_TEMPLATE EDIPARTYNAME_seq_tt[] = {
126 	{
127 		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
128 		.tag = 0,
129 		.offset = offsetof(EDIPARTYNAME, nameAssigner),
130 		.field_name = "nameAssigner",
131 		.item = &DIRECTORYSTRING_it,
132 	},
133 	{
134 		.flags = ASN1_TFLG_EXPLICIT,
135 		.tag = 1,
136 		.offset = offsetof(EDIPARTYNAME, partyName),
137 		.field_name = "partyName",
138 		.item = &DIRECTORYSTRING_it,
139 	},
140 };
141 
142 const ASN1_ITEM EDIPARTYNAME_it = {
143 	.itype = ASN1_ITYPE_SEQUENCE,
144 	.utype = V_ASN1_SEQUENCE,
145 	.templates = EDIPARTYNAME_seq_tt,
146 	.tcount = sizeof(EDIPARTYNAME_seq_tt) / sizeof(ASN1_TEMPLATE),
147 	.funcs = NULL,
148 	.size = sizeof(EDIPARTYNAME),
149 	.sname = "EDIPARTYNAME",
150 };
151 
152 
153 EDIPARTYNAME *
154 d2i_EDIPARTYNAME(EDIPARTYNAME **a, const unsigned char **in, long len)
155 {
156 	return (EDIPARTYNAME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
157 	    &EDIPARTYNAME_it);
158 }
159 LCRYPTO_ALIAS(d2i_EDIPARTYNAME)
160 
161 int
162 i2d_EDIPARTYNAME(EDIPARTYNAME *a, unsigned char **out)
163 {
164 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &EDIPARTYNAME_it);
165 }
166 LCRYPTO_ALIAS(i2d_EDIPARTYNAME)
167 
168 EDIPARTYNAME *
169 EDIPARTYNAME_new(void)
170 {
171 	return (EDIPARTYNAME *)ASN1_item_new(&EDIPARTYNAME_it);
172 }
173 LCRYPTO_ALIAS(EDIPARTYNAME_new)
174 
175 void
176 EDIPARTYNAME_free(EDIPARTYNAME *a)
177 {
178 	ASN1_item_free((ASN1_VALUE *)a, &EDIPARTYNAME_it);
179 }
180 LCRYPTO_ALIAS(EDIPARTYNAME_free)
181 
182 static const ASN1_TEMPLATE GENERAL_NAME_ch_tt[] = {
183 	{
184 		.flags = ASN1_TFLG_IMPLICIT,
185 		.tag = GEN_OTHERNAME,
186 		.offset = offsetof(GENERAL_NAME, d.otherName),
187 		.field_name = "d.otherName",
188 		.item = &OTHERNAME_it,
189 	},
190 	{
191 		.flags = ASN1_TFLG_IMPLICIT,
192 		.tag = GEN_EMAIL,
193 		.offset = offsetof(GENERAL_NAME, d.rfc822Name),
194 		.field_name = "d.rfc822Name",
195 		.item = &ASN1_IA5STRING_it,
196 	},
197 	{
198 		.flags = ASN1_TFLG_IMPLICIT,
199 		.tag = GEN_DNS,
200 		.offset = offsetof(GENERAL_NAME, d.dNSName),
201 		.field_name = "d.dNSName",
202 		.item = &ASN1_IA5STRING_it,
203 	},
204 	/* Don't decode this */
205 	{
206 		.flags = ASN1_TFLG_IMPLICIT,
207 		.tag = GEN_X400,
208 		.offset = offsetof(GENERAL_NAME, d.x400Address),
209 		.field_name = "d.x400Address",
210 		.item = &ASN1_SEQUENCE_it,
211 	},
212 	/* X509_NAME is a CHOICE type so use EXPLICIT */
213 	{
214 		.flags = ASN1_TFLG_EXPLICIT,
215 		.tag = GEN_DIRNAME,
216 		.offset = offsetof(GENERAL_NAME, d.directoryName),
217 		.field_name = "d.directoryName",
218 		.item = &X509_NAME_it,
219 	},
220 	{
221 		.flags = ASN1_TFLG_IMPLICIT,
222 		.tag = GEN_EDIPARTY,
223 		.offset = offsetof(GENERAL_NAME, d.ediPartyName),
224 		.field_name = "d.ediPartyName",
225 		.item = &EDIPARTYNAME_it,
226 	},
227 	{
228 		.flags = ASN1_TFLG_IMPLICIT,
229 		.tag = GEN_URI,
230 		.offset = offsetof(GENERAL_NAME, d.uniformResourceIdentifier),
231 		.field_name = "d.uniformResourceIdentifier",
232 		.item = &ASN1_IA5STRING_it,
233 	},
234 	{
235 		.flags = ASN1_TFLG_IMPLICIT,
236 		.tag = GEN_IPADD,
237 		.offset = offsetof(GENERAL_NAME, d.iPAddress),
238 		.field_name = "d.iPAddress",
239 		.item = &ASN1_OCTET_STRING_it,
240 	},
241 	{
242 		.flags = ASN1_TFLG_IMPLICIT,
243 		.tag = GEN_RID,
244 		.offset = offsetof(GENERAL_NAME, d.registeredID),
245 		.field_name = "d.registeredID",
246 		.item = &ASN1_OBJECT_it,
247 	},
248 };
249 
250 const ASN1_ITEM GENERAL_NAME_it = {
251 	.itype = ASN1_ITYPE_CHOICE,
252 	.utype = offsetof(GENERAL_NAME, type),
253 	.templates = GENERAL_NAME_ch_tt,
254 	.tcount = sizeof(GENERAL_NAME_ch_tt) / sizeof(ASN1_TEMPLATE),
255 	.funcs = NULL,
256 	.size = sizeof(GENERAL_NAME),
257 	.sname = "GENERAL_NAME",
258 };
259 
260 
261 GENERAL_NAME *
262 d2i_GENERAL_NAME(GENERAL_NAME **a, const unsigned char **in, long len)
263 {
264 	return (GENERAL_NAME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
265 	    &GENERAL_NAME_it);
266 }
267 LCRYPTO_ALIAS(d2i_GENERAL_NAME)
268 
269 int
270 i2d_GENERAL_NAME(GENERAL_NAME *a, unsigned char **out)
271 {
272 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &GENERAL_NAME_it);
273 }
274 LCRYPTO_ALIAS(i2d_GENERAL_NAME)
275 
276 GENERAL_NAME *
277 GENERAL_NAME_new(void)
278 {
279 	return (GENERAL_NAME *)ASN1_item_new(&GENERAL_NAME_it);
280 }
281 LCRYPTO_ALIAS(GENERAL_NAME_new)
282 
283 void
284 GENERAL_NAME_free(GENERAL_NAME *a)
285 {
286 	ASN1_item_free((ASN1_VALUE *)a, &GENERAL_NAME_it);
287 }
288 LCRYPTO_ALIAS(GENERAL_NAME_free)
289 
290 static const ASN1_TEMPLATE GENERAL_NAMES_item_tt = {
291 	.flags = ASN1_TFLG_SEQUENCE_OF,
292 	.tag = 0,
293 	.offset = 0,
294 	.field_name = "GeneralNames",
295 	.item = &GENERAL_NAME_it,
296 };
297 
298 const ASN1_ITEM GENERAL_NAMES_it = {
299 	.itype = ASN1_ITYPE_PRIMITIVE,
300 	.utype = -1,
301 	.templates = &GENERAL_NAMES_item_tt,
302 	.tcount = 0,
303 	.funcs = NULL,
304 	.size = 0,
305 	.sname = "GENERAL_NAMES",
306 };
307 
308 
309 GENERAL_NAMES *
310 d2i_GENERAL_NAMES(GENERAL_NAMES **a, const unsigned char **in, long len)
311 {
312 	return (GENERAL_NAMES *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
313 	    &GENERAL_NAMES_it);
314 }
315 LCRYPTO_ALIAS(d2i_GENERAL_NAMES)
316 
317 int
318 i2d_GENERAL_NAMES(GENERAL_NAMES *a, unsigned char **out)
319 {
320 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &GENERAL_NAMES_it);
321 }
322 LCRYPTO_ALIAS(i2d_GENERAL_NAMES)
323 
324 GENERAL_NAMES *
325 GENERAL_NAMES_new(void)
326 {
327 	return (GENERAL_NAMES *)ASN1_item_new(&GENERAL_NAMES_it);
328 }
329 LCRYPTO_ALIAS(GENERAL_NAMES_new)
330 
331 void
332 GENERAL_NAMES_free(GENERAL_NAMES *a)
333 {
334 	ASN1_item_free((ASN1_VALUE *)a, &GENERAL_NAMES_it);
335 }
336 LCRYPTO_ALIAS(GENERAL_NAMES_free)
337 
338 GENERAL_NAME *
339 GENERAL_NAME_dup(GENERAL_NAME *a)
340 {
341 	return ASN1_item_dup(&GENERAL_NAME_it, a);
342 }
343 LCRYPTO_ALIAS(GENERAL_NAME_dup)
344 
345 static int
346 EDIPARTYNAME_cmp(const EDIPARTYNAME *a, const EDIPARTYNAME *b)
347 {
348 	int res;
349 
350 	/*
351 	 * Shouldn't be possible in a valid GENERAL_NAME, but we handle it
352 	 * anyway. OTHERNAME_cmp treats NULL != NULL, so we do the same here.
353 	 */
354 	if (a == NULL || b == NULL)
355 		return -1;
356 	if (a->nameAssigner == NULL && b->nameAssigner != NULL)
357 		return -1;
358 	if (a->nameAssigner != NULL && b->nameAssigner == NULL)
359 		return 1;
360 	/* If we get here, both have nameAssigner set or both unset. */
361 	if (a->nameAssigner != NULL) {
362 		res = ASN1_STRING_cmp(a->nameAssigner, b->nameAssigner);
363 		if (res != 0)
364 			return res;
365 	}
366 	/*
367 	 * partyName is required, so these should never be NULL. We treat it in
368 	 * the same way as the a == NULL || b == NULL case above.
369 	 */
370 	if (a->partyName == NULL || b->partyName == NULL)
371 		return -1;
372 
373 	return ASN1_STRING_cmp(a->partyName, b->partyName);
374 }
375 
376 /* Returns 0 if they are equal, != 0 otherwise. */
377 int
378 GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b)
379 {
380 	int result = -1;
381 
382 	if (!a || !b || a->type != b->type)
383 		return -1;
384 	switch (a->type) {
385 	case GEN_X400:
386 		result = ASN1_STRING_cmp((ASN1_STRING *)a->d.x400Address,
387 		    (ASN1_STRING *)b->d.x400Address);
388 		break;
389 
390 	case GEN_EDIPARTY:
391 		result = EDIPARTYNAME_cmp(a->d.ediPartyName, b->d.ediPartyName);
392 		break;
393 
394 	case GEN_OTHERNAME:
395 		result = OTHERNAME_cmp(a->d.otherName, b->d.otherName);
396 		break;
397 
398 	case GEN_EMAIL:
399 	case GEN_DNS:
400 	case GEN_URI:
401 		result = ASN1_STRING_cmp(a->d.ia5, b->d.ia5);
402 		break;
403 
404 	case GEN_DIRNAME:
405 		result = X509_NAME_cmp(a->d.dirn, b->d.dirn);
406 		break;
407 
408 	case GEN_IPADD:
409 		result = ASN1_OCTET_STRING_cmp(a->d.ip, b->d.ip);
410 		break;
411 
412 	case GEN_RID:
413 		result = OBJ_cmp(a->d.rid, b->d.rid);
414 		break;
415 	}
416 	return result;
417 }
418 LCRYPTO_ALIAS(GENERAL_NAME_cmp)
419 
420 /* Returns 0 if they are equal, != 0 otherwise. */
421 int
422 OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b)
423 {
424 	int result = -1;
425 
426 	if (!a || !b)
427 		return -1;
428 	/* Check their type first. */
429 	if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0)
430 		return result;
431 	/* Check the value. */
432 	result = ASN1_TYPE_cmp(a->value, b->value);
433 	return result;
434 }
435 LCRYPTO_ALIAS(OTHERNAME_cmp)
436 
437 void
438 GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value)
439 {
440 	switch (type) {
441 	case GEN_X400:
442 		a->d.x400Address = value;
443 		break;
444 
445 	case GEN_EDIPARTY:
446 		a->d.ediPartyName = value;
447 		break;
448 
449 	case GEN_OTHERNAME:
450 		a->d.otherName = value;
451 		break;
452 
453 	case GEN_EMAIL:
454 	case GEN_DNS:
455 	case GEN_URI:
456 		a->d.ia5 = value;
457 		break;
458 
459 	case GEN_DIRNAME:
460 		a->d.dirn = value;
461 		break;
462 
463 	case GEN_IPADD:
464 		a->d.ip = value;
465 		break;
466 
467 	case GEN_RID:
468 		a->d.rid = value;
469 		break;
470 	}
471 	a->type = type;
472 }
473 LCRYPTO_ALIAS(GENERAL_NAME_set0_value)
474 
475 void *
476 GENERAL_NAME_get0_value(GENERAL_NAME *a, int *ptype)
477 {
478 	if (ptype)
479 		*ptype = a->type;
480 	switch (a->type) {
481 	case GEN_X400:
482 		return a->d.x400Address;
483 
484 	case GEN_EDIPARTY:
485 		return a->d.ediPartyName;
486 
487 	case GEN_OTHERNAME:
488 		return a->d.otherName;
489 
490 	case GEN_EMAIL:
491 	case GEN_DNS:
492 	case GEN_URI:
493 		return a->d.ia5;
494 
495 	case GEN_DIRNAME:
496 		return a->d.dirn;
497 
498 	case GEN_IPADD:
499 		return a->d.ip;
500 
501 	case GEN_RID:
502 		return a->d.rid;
503 
504 	default:
505 		return NULL;
506 	}
507 }
508 LCRYPTO_ALIAS(GENERAL_NAME_get0_value)
509 
510 int
511 GENERAL_NAME_set0_othername(GENERAL_NAME *gen, ASN1_OBJECT *oid,
512     ASN1_TYPE *value)
513 {
514 	OTHERNAME *oth;
515 
516 	oth = OTHERNAME_new();
517 	if (!oth)
518 		return 0;
519 	oth->type_id = oid;
520 	oth->value = value;
521 	GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth);
522 	return 1;
523 }
524 LCRYPTO_ALIAS(GENERAL_NAME_set0_othername)
525 
526 int
527 GENERAL_NAME_get0_otherName(GENERAL_NAME *gen, ASN1_OBJECT **poid,
528     ASN1_TYPE **pvalue)
529 {
530 	if (gen->type != GEN_OTHERNAME)
531 		return 0;
532 	if (poid)
533 		*poid = gen->d.otherName->type_id;
534 	if (pvalue)
535 		*pvalue = gen->d.otherName->value;
536 	return 1;
537 }
538 LCRYPTO_ALIAS(GENERAL_NAME_get0_otherName)
539