xref: /openbsd/lib/libcrypto/x509/x509_genn.c (revision c0ebdaf2)
1 /* $OpenBSD: x509_genn.c,v 1.7 2024/07/08 14:47:44 beck 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 LCRYPTO_ALIAS(OTHERNAME_it);
94 
95 
96 OTHERNAME *
d2i_OTHERNAME(OTHERNAME ** a,const unsigned char ** in,long len)97 d2i_OTHERNAME(OTHERNAME **a, const unsigned char **in, long len)
98 {
99 	return (OTHERNAME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
100 	    &OTHERNAME_it);
101 }
102 LCRYPTO_ALIAS(d2i_OTHERNAME);
103 
104 int
i2d_OTHERNAME(OTHERNAME * a,unsigned char ** out)105 i2d_OTHERNAME(OTHERNAME *a, unsigned char **out)
106 {
107 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &OTHERNAME_it);
108 }
109 LCRYPTO_ALIAS(i2d_OTHERNAME);
110 
111 OTHERNAME *
OTHERNAME_new(void)112 OTHERNAME_new(void)
113 {
114 	return (OTHERNAME *)ASN1_item_new(&OTHERNAME_it);
115 }
116 LCRYPTO_ALIAS(OTHERNAME_new);
117 
118 void
OTHERNAME_free(OTHERNAME * a)119 OTHERNAME_free(OTHERNAME *a)
120 {
121 	ASN1_item_free((ASN1_VALUE *)a, &OTHERNAME_it);
122 }
123 LCRYPTO_ALIAS(OTHERNAME_free);
124 
125 /* Uses explicit tagging since DIRECTORYSTRING is a CHOICE type */
126 static const ASN1_TEMPLATE EDIPARTYNAME_seq_tt[] = {
127 	{
128 		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
129 		.tag = 0,
130 		.offset = offsetof(EDIPARTYNAME, nameAssigner),
131 		.field_name = "nameAssigner",
132 		.item = &DIRECTORYSTRING_it,
133 	},
134 	{
135 		.flags = ASN1_TFLG_EXPLICIT,
136 		.tag = 1,
137 		.offset = offsetof(EDIPARTYNAME, partyName),
138 		.field_name = "partyName",
139 		.item = &DIRECTORYSTRING_it,
140 	},
141 };
142 
143 const ASN1_ITEM EDIPARTYNAME_it = {
144 	.itype = ASN1_ITYPE_SEQUENCE,
145 	.utype = V_ASN1_SEQUENCE,
146 	.templates = EDIPARTYNAME_seq_tt,
147 	.tcount = sizeof(EDIPARTYNAME_seq_tt) / sizeof(ASN1_TEMPLATE),
148 	.funcs = NULL,
149 	.size = sizeof(EDIPARTYNAME),
150 	.sname = "EDIPARTYNAME",
151 };
152 LCRYPTO_ALIAS(EDIPARTYNAME_it);
153 
154 
155 EDIPARTYNAME *
d2i_EDIPARTYNAME(EDIPARTYNAME ** a,const unsigned char ** in,long len)156 d2i_EDIPARTYNAME(EDIPARTYNAME **a, const unsigned char **in, long len)
157 {
158 	return (EDIPARTYNAME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
159 	    &EDIPARTYNAME_it);
160 }
161 LCRYPTO_ALIAS(d2i_EDIPARTYNAME);
162 
163 int
i2d_EDIPARTYNAME(EDIPARTYNAME * a,unsigned char ** out)164 i2d_EDIPARTYNAME(EDIPARTYNAME *a, unsigned char **out)
165 {
166 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &EDIPARTYNAME_it);
167 }
168 LCRYPTO_ALIAS(i2d_EDIPARTYNAME);
169 
170 EDIPARTYNAME *
EDIPARTYNAME_new(void)171 EDIPARTYNAME_new(void)
172 {
173 	return (EDIPARTYNAME *)ASN1_item_new(&EDIPARTYNAME_it);
174 }
175 LCRYPTO_ALIAS(EDIPARTYNAME_new);
176 
177 void
EDIPARTYNAME_free(EDIPARTYNAME * a)178 EDIPARTYNAME_free(EDIPARTYNAME *a)
179 {
180 	ASN1_item_free((ASN1_VALUE *)a, &EDIPARTYNAME_it);
181 }
182 LCRYPTO_ALIAS(EDIPARTYNAME_free);
183 
184 static const ASN1_TEMPLATE GENERAL_NAME_ch_tt[] = {
185 	{
186 		.flags = ASN1_TFLG_IMPLICIT,
187 		.tag = GEN_OTHERNAME,
188 		.offset = offsetof(GENERAL_NAME, d.otherName),
189 		.field_name = "d.otherName",
190 		.item = &OTHERNAME_it,
191 	},
192 	{
193 		.flags = ASN1_TFLG_IMPLICIT,
194 		.tag = GEN_EMAIL,
195 		.offset = offsetof(GENERAL_NAME, d.rfc822Name),
196 		.field_name = "d.rfc822Name",
197 		.item = &ASN1_IA5STRING_it,
198 	},
199 	{
200 		.flags = ASN1_TFLG_IMPLICIT,
201 		.tag = GEN_DNS,
202 		.offset = offsetof(GENERAL_NAME, d.dNSName),
203 		.field_name = "d.dNSName",
204 		.item = &ASN1_IA5STRING_it,
205 	},
206 	/* Don't decode this */
207 	{
208 		.flags = ASN1_TFLG_IMPLICIT,
209 		.tag = GEN_X400,
210 		.offset = offsetof(GENERAL_NAME, d.x400Address),
211 		.field_name = "d.x400Address",
212 		.item = &ASN1_SEQUENCE_it,
213 	},
214 	/* X509_NAME is a CHOICE type so use EXPLICIT */
215 	{
216 		.flags = ASN1_TFLG_EXPLICIT,
217 		.tag = GEN_DIRNAME,
218 		.offset = offsetof(GENERAL_NAME, d.directoryName),
219 		.field_name = "d.directoryName",
220 		.item = &X509_NAME_it,
221 	},
222 	{
223 		.flags = ASN1_TFLG_IMPLICIT,
224 		.tag = GEN_EDIPARTY,
225 		.offset = offsetof(GENERAL_NAME, d.ediPartyName),
226 		.field_name = "d.ediPartyName",
227 		.item = &EDIPARTYNAME_it,
228 	},
229 	{
230 		.flags = ASN1_TFLG_IMPLICIT,
231 		.tag = GEN_URI,
232 		.offset = offsetof(GENERAL_NAME, d.uniformResourceIdentifier),
233 		.field_name = "d.uniformResourceIdentifier",
234 		.item = &ASN1_IA5STRING_it,
235 	},
236 	{
237 		.flags = ASN1_TFLG_IMPLICIT,
238 		.tag = GEN_IPADD,
239 		.offset = offsetof(GENERAL_NAME, d.iPAddress),
240 		.field_name = "d.iPAddress",
241 		.item = &ASN1_OCTET_STRING_it,
242 	},
243 	{
244 		.flags = ASN1_TFLG_IMPLICIT,
245 		.tag = GEN_RID,
246 		.offset = offsetof(GENERAL_NAME, d.registeredID),
247 		.field_name = "d.registeredID",
248 		.item = &ASN1_OBJECT_it,
249 	},
250 };
251 
252 const ASN1_ITEM GENERAL_NAME_it = {
253 	.itype = ASN1_ITYPE_CHOICE,
254 	.utype = offsetof(GENERAL_NAME, type),
255 	.templates = GENERAL_NAME_ch_tt,
256 	.tcount = sizeof(GENERAL_NAME_ch_tt) / sizeof(ASN1_TEMPLATE),
257 	.funcs = NULL,
258 	.size = sizeof(GENERAL_NAME),
259 	.sname = "GENERAL_NAME",
260 };
261 LCRYPTO_ALIAS(GENERAL_NAME_it);
262 
263 
264 GENERAL_NAME *
d2i_GENERAL_NAME(GENERAL_NAME ** a,const unsigned char ** in,long len)265 d2i_GENERAL_NAME(GENERAL_NAME **a, const unsigned char **in, long len)
266 {
267 	return (GENERAL_NAME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
268 	    &GENERAL_NAME_it);
269 }
270 LCRYPTO_ALIAS(d2i_GENERAL_NAME);
271 
272 int
i2d_GENERAL_NAME(GENERAL_NAME * a,unsigned char ** out)273 i2d_GENERAL_NAME(GENERAL_NAME *a, unsigned char **out)
274 {
275 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &GENERAL_NAME_it);
276 }
277 LCRYPTO_ALIAS(i2d_GENERAL_NAME);
278 
279 GENERAL_NAME *
GENERAL_NAME_new(void)280 GENERAL_NAME_new(void)
281 {
282 	return (GENERAL_NAME *)ASN1_item_new(&GENERAL_NAME_it);
283 }
284 LCRYPTO_ALIAS(GENERAL_NAME_new);
285 
286 void
GENERAL_NAME_free(GENERAL_NAME * a)287 GENERAL_NAME_free(GENERAL_NAME *a)
288 {
289 	ASN1_item_free((ASN1_VALUE *)a, &GENERAL_NAME_it);
290 }
291 LCRYPTO_ALIAS(GENERAL_NAME_free);
292 
293 static const ASN1_TEMPLATE GENERAL_NAMES_item_tt = {
294 	.flags = ASN1_TFLG_SEQUENCE_OF,
295 	.tag = 0,
296 	.offset = 0,
297 	.field_name = "GeneralNames",
298 	.item = &GENERAL_NAME_it,
299 };
300 
301 const ASN1_ITEM GENERAL_NAMES_it = {
302 	.itype = ASN1_ITYPE_PRIMITIVE,
303 	.utype = -1,
304 	.templates = &GENERAL_NAMES_item_tt,
305 	.tcount = 0,
306 	.funcs = NULL,
307 	.size = 0,
308 	.sname = "GENERAL_NAMES",
309 };
310 LCRYPTO_ALIAS(GENERAL_NAMES_it);
311 
312 
313 GENERAL_NAMES *
d2i_GENERAL_NAMES(GENERAL_NAMES ** a,const unsigned char ** in,long len)314 d2i_GENERAL_NAMES(GENERAL_NAMES **a, const unsigned char **in, long len)
315 {
316 	return (GENERAL_NAMES *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
317 	    &GENERAL_NAMES_it);
318 }
319 LCRYPTO_ALIAS(d2i_GENERAL_NAMES);
320 
321 int
i2d_GENERAL_NAMES(GENERAL_NAMES * a,unsigned char ** out)322 i2d_GENERAL_NAMES(GENERAL_NAMES *a, unsigned char **out)
323 {
324 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &GENERAL_NAMES_it);
325 }
326 LCRYPTO_ALIAS(i2d_GENERAL_NAMES);
327 
328 GENERAL_NAMES *
GENERAL_NAMES_new(void)329 GENERAL_NAMES_new(void)
330 {
331 	return (GENERAL_NAMES *)ASN1_item_new(&GENERAL_NAMES_it);
332 }
333 LCRYPTO_ALIAS(GENERAL_NAMES_new);
334 
335 void
GENERAL_NAMES_free(GENERAL_NAMES * a)336 GENERAL_NAMES_free(GENERAL_NAMES *a)
337 {
338 	ASN1_item_free((ASN1_VALUE *)a, &GENERAL_NAMES_it);
339 }
340 LCRYPTO_ALIAS(GENERAL_NAMES_free);
341 
342 GENERAL_NAME *
GENERAL_NAME_dup(GENERAL_NAME * a)343 GENERAL_NAME_dup(GENERAL_NAME *a)
344 {
345 	return ASN1_item_dup(&GENERAL_NAME_it, a);
346 }
347 LCRYPTO_ALIAS(GENERAL_NAME_dup);
348 
349 static int
EDIPARTYNAME_cmp(const EDIPARTYNAME * a,const EDIPARTYNAME * b)350 EDIPARTYNAME_cmp(const EDIPARTYNAME *a, const EDIPARTYNAME *b)
351 {
352 	int res;
353 
354 	/*
355 	 * Shouldn't be possible in a valid GENERAL_NAME, but we handle it
356 	 * anyway. OTHERNAME_cmp treats NULL != NULL, so we do the same here.
357 	 */
358 	if (a == NULL || b == NULL)
359 		return -1;
360 	if (a->nameAssigner == NULL && b->nameAssigner != NULL)
361 		return -1;
362 	if (a->nameAssigner != NULL && b->nameAssigner == NULL)
363 		return 1;
364 	/* If we get here, both have nameAssigner set or both unset. */
365 	if (a->nameAssigner != NULL) {
366 		res = ASN1_STRING_cmp(a->nameAssigner, b->nameAssigner);
367 		if (res != 0)
368 			return res;
369 	}
370 	/*
371 	 * partyName is required, so these should never be NULL. We treat it in
372 	 * the same way as the a == NULL || b == NULL case above.
373 	 */
374 	if (a->partyName == NULL || b->partyName == NULL)
375 		return -1;
376 
377 	return ASN1_STRING_cmp(a->partyName, b->partyName);
378 }
379 
380 /* Returns 0 if they are equal, != 0 otherwise. */
381 int
GENERAL_NAME_cmp(GENERAL_NAME * a,GENERAL_NAME * b)382 GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b)
383 {
384 	int result = -1;
385 
386 	if (!a || !b || a->type != b->type)
387 		return -1;
388 	switch (a->type) {
389 	case GEN_X400:
390 		result = ASN1_STRING_cmp(a->d.x400Address, b->d.x400Address);
391 		break;
392 
393 	case GEN_EDIPARTY:
394 		result = EDIPARTYNAME_cmp(a->d.ediPartyName, b->d.ediPartyName);
395 		break;
396 
397 	case GEN_OTHERNAME:
398 		result = OTHERNAME_cmp(a->d.otherName, b->d.otherName);
399 		break;
400 
401 	case GEN_EMAIL:
402 	case GEN_DNS:
403 	case GEN_URI:
404 		result = ASN1_STRING_cmp(a->d.ia5, b->d.ia5);
405 		break;
406 
407 	case GEN_DIRNAME:
408 		result = X509_NAME_cmp(a->d.dirn, b->d.dirn);
409 		break;
410 
411 	case GEN_IPADD:
412 		result = ASN1_OCTET_STRING_cmp(a->d.ip, b->d.ip);
413 		break;
414 
415 	case GEN_RID:
416 		result = OBJ_cmp(a->d.rid, b->d.rid);
417 		break;
418 	}
419 	return result;
420 }
421 LCRYPTO_ALIAS(GENERAL_NAME_cmp);
422 
423 /* Returns 0 if they are equal, != 0 otherwise. */
424 int
OTHERNAME_cmp(OTHERNAME * a,OTHERNAME * b)425 OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b)
426 {
427 	int result = -1;
428 
429 	if (!a || !b)
430 		return -1;
431 	/* Check their type first. */
432 	if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0)
433 		return result;
434 	/* Check the value. */
435 	result = ASN1_TYPE_cmp(a->value, b->value);
436 	return result;
437 }
438 LCRYPTO_ALIAS(OTHERNAME_cmp);
439 
440 void
GENERAL_NAME_set0_value(GENERAL_NAME * a,int type,void * value)441 GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value)
442 {
443 	switch (type) {
444 	case GEN_X400:
445 		a->d.x400Address = value;
446 		break;
447 
448 	case GEN_EDIPARTY:
449 		a->d.ediPartyName = value;
450 		break;
451 
452 	case GEN_OTHERNAME:
453 		a->d.otherName = value;
454 		break;
455 
456 	case GEN_EMAIL:
457 	case GEN_DNS:
458 	case GEN_URI:
459 		a->d.ia5 = value;
460 		break;
461 
462 	case GEN_DIRNAME:
463 		a->d.dirn = value;
464 		break;
465 
466 	case GEN_IPADD:
467 		a->d.ip = value;
468 		break;
469 
470 	case GEN_RID:
471 		a->d.rid = value;
472 		break;
473 	}
474 	a->type = type;
475 }
476 LCRYPTO_ALIAS(GENERAL_NAME_set0_value);
477 
478 void *
GENERAL_NAME_get0_value(GENERAL_NAME * a,int * ptype)479 GENERAL_NAME_get0_value(GENERAL_NAME *a, int *ptype)
480 {
481 	if (ptype)
482 		*ptype = a->type;
483 	switch (a->type) {
484 	case GEN_X400:
485 		return a->d.x400Address;
486 
487 	case GEN_EDIPARTY:
488 		return a->d.ediPartyName;
489 
490 	case GEN_OTHERNAME:
491 		return a->d.otherName;
492 
493 	case GEN_EMAIL:
494 	case GEN_DNS:
495 	case GEN_URI:
496 		return a->d.ia5;
497 
498 	case GEN_DIRNAME:
499 		return a->d.dirn;
500 
501 	case GEN_IPADD:
502 		return a->d.ip;
503 
504 	case GEN_RID:
505 		return a->d.rid;
506 
507 	default:
508 		return NULL;
509 	}
510 }
511 LCRYPTO_ALIAS(GENERAL_NAME_get0_value);
512 
513 int
GENERAL_NAME_set0_othername(GENERAL_NAME * gen,ASN1_OBJECT * oid,ASN1_TYPE * value)514 GENERAL_NAME_set0_othername(GENERAL_NAME *gen, ASN1_OBJECT *oid,
515     ASN1_TYPE *value)
516 {
517 	OTHERNAME *oth;
518 
519 	oth = OTHERNAME_new();
520 	if (!oth)
521 		return 0;
522 	oth->type_id = oid;
523 	oth->value = value;
524 	GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth);
525 	return 1;
526 }
527 LCRYPTO_ALIAS(GENERAL_NAME_set0_othername);
528 
529 int
GENERAL_NAME_get0_otherName(GENERAL_NAME * gen,ASN1_OBJECT ** poid,ASN1_TYPE ** pvalue)530 GENERAL_NAME_get0_otherName(GENERAL_NAME *gen, ASN1_OBJECT **poid,
531     ASN1_TYPE **pvalue)
532 {
533 	if (gen->type != GEN_OTHERNAME)
534 		return 0;
535 	if (poid)
536 		*poid = gen->d.otherName->type_id;
537 	if (pvalue)
538 		*pvalue = gen->d.otherName->value;
539 	return 1;
540 }
541 LCRYPTO_ALIAS(GENERAL_NAME_get0_otherName);
542