xref: /openbsd/lib/libcrypto/x509/x509_genn.c (revision 7603ff28)
1 /* $OpenBSD: x509_genn.c,v 1.6 2023/04/25 15:51:04 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 *
d2i_OTHERNAME(OTHERNAME ** a,const unsigned char ** in,long len)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
i2d_OTHERNAME(OTHERNAME * a,unsigned char ** out)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 *
OTHERNAME_new(void)111 OTHERNAME_new(void)
112 {
113 	return (OTHERNAME *)ASN1_item_new(&OTHERNAME_it);
114 }
115 LCRYPTO_ALIAS(OTHERNAME_new);
116 
117 void
OTHERNAME_free(OTHERNAME * a)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 *
d2i_EDIPARTYNAME(EDIPARTYNAME ** a,const unsigned char ** in,long len)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
i2d_EDIPARTYNAME(EDIPARTYNAME * a,unsigned char ** out)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 *
EDIPARTYNAME_new(void)169 EDIPARTYNAME_new(void)
170 {
171 	return (EDIPARTYNAME *)ASN1_item_new(&EDIPARTYNAME_it);
172 }
173 LCRYPTO_ALIAS(EDIPARTYNAME_new);
174 
175 void
EDIPARTYNAME_free(EDIPARTYNAME * a)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 *
d2i_GENERAL_NAME(GENERAL_NAME ** a,const unsigned char ** in,long len)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
i2d_GENERAL_NAME(GENERAL_NAME * a,unsigned char ** out)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 *
GENERAL_NAME_new(void)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
GENERAL_NAME_free(GENERAL_NAME * a)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 *
d2i_GENERAL_NAMES(GENERAL_NAMES ** a,const unsigned char ** in,long len)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
i2d_GENERAL_NAMES(GENERAL_NAMES * a,unsigned char ** out)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 *
GENERAL_NAMES_new(void)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
GENERAL_NAMES_free(GENERAL_NAMES * a)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 *
GENERAL_NAME_dup(GENERAL_NAME * a)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
EDIPARTYNAME_cmp(const EDIPARTYNAME * a,const EDIPARTYNAME * b)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
GENERAL_NAME_cmp(GENERAL_NAME * a,GENERAL_NAME * b)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(a->d.x400Address, b->d.x400Address);
387 		break;
388 
389 	case GEN_EDIPARTY:
390 		result = EDIPARTYNAME_cmp(a->d.ediPartyName, b->d.ediPartyName);
391 		break;
392 
393 	case GEN_OTHERNAME:
394 		result = OTHERNAME_cmp(a->d.otherName, b->d.otherName);
395 		break;
396 
397 	case GEN_EMAIL:
398 	case GEN_DNS:
399 	case GEN_URI:
400 		result = ASN1_STRING_cmp(a->d.ia5, b->d.ia5);
401 		break;
402 
403 	case GEN_DIRNAME:
404 		result = X509_NAME_cmp(a->d.dirn, b->d.dirn);
405 		break;
406 
407 	case GEN_IPADD:
408 		result = ASN1_OCTET_STRING_cmp(a->d.ip, b->d.ip);
409 		break;
410 
411 	case GEN_RID:
412 		result = OBJ_cmp(a->d.rid, b->d.rid);
413 		break;
414 	}
415 	return result;
416 }
417 LCRYPTO_ALIAS(GENERAL_NAME_cmp);
418 
419 /* Returns 0 if they are equal, != 0 otherwise. */
420 int
OTHERNAME_cmp(OTHERNAME * a,OTHERNAME * b)421 OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b)
422 {
423 	int result = -1;
424 
425 	if (!a || !b)
426 		return -1;
427 	/* Check their type first. */
428 	if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0)
429 		return result;
430 	/* Check the value. */
431 	result = ASN1_TYPE_cmp(a->value, b->value);
432 	return result;
433 }
434 LCRYPTO_ALIAS(OTHERNAME_cmp);
435 
436 void
GENERAL_NAME_set0_value(GENERAL_NAME * a,int type,void * value)437 GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value)
438 {
439 	switch (type) {
440 	case GEN_X400:
441 		a->d.x400Address = value;
442 		break;
443 
444 	case GEN_EDIPARTY:
445 		a->d.ediPartyName = value;
446 		break;
447 
448 	case GEN_OTHERNAME:
449 		a->d.otherName = value;
450 		break;
451 
452 	case GEN_EMAIL:
453 	case GEN_DNS:
454 	case GEN_URI:
455 		a->d.ia5 = value;
456 		break;
457 
458 	case GEN_DIRNAME:
459 		a->d.dirn = value;
460 		break;
461 
462 	case GEN_IPADD:
463 		a->d.ip = value;
464 		break;
465 
466 	case GEN_RID:
467 		a->d.rid = value;
468 		break;
469 	}
470 	a->type = type;
471 }
472 LCRYPTO_ALIAS(GENERAL_NAME_set0_value);
473 
474 void *
GENERAL_NAME_get0_value(GENERAL_NAME * a,int * ptype)475 GENERAL_NAME_get0_value(GENERAL_NAME *a, int *ptype)
476 {
477 	if (ptype)
478 		*ptype = a->type;
479 	switch (a->type) {
480 	case GEN_X400:
481 		return a->d.x400Address;
482 
483 	case GEN_EDIPARTY:
484 		return a->d.ediPartyName;
485 
486 	case GEN_OTHERNAME:
487 		return a->d.otherName;
488 
489 	case GEN_EMAIL:
490 	case GEN_DNS:
491 	case GEN_URI:
492 		return a->d.ia5;
493 
494 	case GEN_DIRNAME:
495 		return a->d.dirn;
496 
497 	case GEN_IPADD:
498 		return a->d.ip;
499 
500 	case GEN_RID:
501 		return a->d.rid;
502 
503 	default:
504 		return NULL;
505 	}
506 }
507 LCRYPTO_ALIAS(GENERAL_NAME_get0_value);
508 
509 int
GENERAL_NAME_set0_othername(GENERAL_NAME * gen,ASN1_OBJECT * oid,ASN1_TYPE * value)510 GENERAL_NAME_set0_othername(GENERAL_NAME *gen, ASN1_OBJECT *oid,
511     ASN1_TYPE *value)
512 {
513 	OTHERNAME *oth;
514 
515 	oth = OTHERNAME_new();
516 	if (!oth)
517 		return 0;
518 	oth->type_id = oid;
519 	oth->value = value;
520 	GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth);
521 	return 1;
522 }
523 LCRYPTO_ALIAS(GENERAL_NAME_set0_othername);
524 
525 int
GENERAL_NAME_get0_otherName(GENERAL_NAME * gen,ASN1_OBJECT ** poid,ASN1_TYPE ** pvalue)526 GENERAL_NAME_get0_otherName(GENERAL_NAME *gen, ASN1_OBJECT **poid,
527     ASN1_TYPE **pvalue)
528 {
529 	if (gen->type != GEN_OTHERNAME)
530 		return 0;
531 	if (poid)
532 		*poid = gen->d.otherName->type_id;
533 	if (pvalue)
534 		*pvalue = gen->d.otherName->value;
535 	return 1;
536 }
537 LCRYPTO_ALIAS(GENERAL_NAME_get0_otherName);
538