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