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