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