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 *
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
102 int
i2d_OTHERNAME(OTHERNAME * a,unsigned char ** out)103 i2d_OTHERNAME(OTHERNAME *a, unsigned char **out)
104 {
105 return ASN1_item_i2d((ASN1_VALUE *)a, out, &OTHERNAME_it);
106 }
107
108 OTHERNAME *
OTHERNAME_new(void)109 OTHERNAME_new(void)
110 {
111 return (OTHERNAME *)ASN1_item_new(&OTHERNAME_it);
112 }
113
114 void
OTHERNAME_free(OTHERNAME * a)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 *
d2i_EDIPARTYNAME(EDIPARTYNAME ** a,const unsigned char ** in,long len)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
i2d_EDIPARTYNAME(EDIPARTYNAME * a,unsigned char ** out)157 i2d_EDIPARTYNAME(EDIPARTYNAME *a, unsigned char **out)
158 {
159 return ASN1_item_i2d((ASN1_VALUE *)a, out, &EDIPARTYNAME_it);
160 }
161
162 EDIPARTYNAME *
EDIPARTYNAME_new(void)163 EDIPARTYNAME_new(void)
164 {
165 return (EDIPARTYNAME *)ASN1_item_new(&EDIPARTYNAME_it);
166 }
167
168 void
EDIPARTYNAME_free(EDIPARTYNAME * a)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 *
d2i_GENERAL_NAME(GENERAL_NAME ** a,const unsigned char ** in,long len)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
i2d_GENERAL_NAME(GENERAL_NAME * a,unsigned char ** out)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 *
GENERAL_NAME_new(void)267 GENERAL_NAME_new(void)
268 {
269 return (GENERAL_NAME *)ASN1_item_new(&GENERAL_NAME_it);
270 }
271
272 void
GENERAL_NAME_free(GENERAL_NAME * a)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 *
d2i_GENERAL_NAMES(GENERAL_NAMES ** a,const unsigned char ** in,long len)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
i2d_GENERAL_NAMES(GENERAL_NAMES * a,unsigned char ** out)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 *
GENERAL_NAMES_new(void)311 GENERAL_NAMES_new(void)
312 {
313 return (GENERAL_NAMES *)ASN1_item_new(&GENERAL_NAMES_it);
314 }
315
316 void
GENERAL_NAMES_free(GENERAL_NAMES * a)317 GENERAL_NAMES_free(GENERAL_NAMES *a)
318 {
319 ASN1_item_free((ASN1_VALUE *)a, &GENERAL_NAMES_it);
320 }
321
322 GENERAL_NAME *
GENERAL_NAME_dup(GENERAL_NAME * a)323 GENERAL_NAME_dup(GENERAL_NAME *a)
324 {
325 return ASN1_item_dup(&GENERAL_NAME_it, a);
326 }
327
328 static int
EDIPARTYNAME_cmp(const EDIPARTYNAME * a,const EDIPARTYNAME * b)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
GENERAL_NAME_cmp(GENERAL_NAME * a,GENERAL_NAME * b)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
OTHERNAME_cmp(OTHERNAME * a,OTHERNAME * b)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
GENERAL_NAME_set0_value(GENERAL_NAME * a,int type,void * value)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 *
GENERAL_NAME_get0_value(GENERAL_NAME * a,int * ptype)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
GENERAL_NAME_set0_othername(GENERAL_NAME * gen,ASN1_OBJECT * oid,ASN1_TYPE * value)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
GENERAL_NAME_get0_otherName(GENERAL_NAME * gen,ASN1_OBJECT ** poid,ASN1_TYPE ** pvalue)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