xref: /dragonfly/crypto/libressl/crypto/x509/x509_genn.c (revision 961e30ea7dc61d1112b778ea4981eac68129fb86)
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