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