xref: /freebsd/crypto/openssl/crypto/x509/v3_genn.c (revision f25b8c9fb4f58cf61adb47d7570abe7caa6d385d)
1 /*
2  * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #include <stdio.h>
11 #include "internal/cryptlib.h"
12 #include <openssl/asn1t.h>
13 #include <openssl/conf.h>
14 #include <openssl/x509v3.h>
15 
16 ASN1_SEQUENCE(OTHERNAME) = {
17     ASN1_SIMPLE(OTHERNAME, type_id, ASN1_OBJECT),
18     /* Maybe have a true ANY DEFINED BY later */
19     ASN1_EXP(OTHERNAME, value, ASN1_ANY, 0)
20 } ASN1_SEQUENCE_END(OTHERNAME)
21 
22 IMPLEMENT_ASN1_FUNCTIONS(OTHERNAME)
23 
24 ASN1_SEQUENCE(EDIPARTYNAME) = {
25     /* DirectoryString is a CHOICE type so use explicit tagging */
26     ASN1_EXP_OPT(EDIPARTYNAME, nameAssigner, DIRECTORYSTRING, 0),
27     ASN1_EXP(EDIPARTYNAME, partyName, DIRECTORYSTRING, 1)
28 } ASN1_SEQUENCE_END(EDIPARTYNAME)
29 
30 IMPLEMENT_ASN1_FUNCTIONS(EDIPARTYNAME)
31 
32 ASN1_CHOICE(GENERAL_NAME) = {
33     ASN1_IMP(GENERAL_NAME, d.otherName, OTHERNAME, GEN_OTHERNAME),
34     ASN1_IMP(GENERAL_NAME, d.rfc822Name, ASN1_IA5STRING, GEN_EMAIL),
35     ASN1_IMP(GENERAL_NAME, d.dNSName, ASN1_IA5STRING, GEN_DNS),
36     /* Don't decode this */
37     ASN1_IMP(GENERAL_NAME, d.x400Address, ASN1_SEQUENCE, GEN_X400),
38     /* X509_NAME is a CHOICE type so use EXPLICIT */
39     ASN1_EXP(GENERAL_NAME, d.directoryName, X509_NAME, GEN_DIRNAME),
40     ASN1_IMP(GENERAL_NAME, d.ediPartyName, EDIPARTYNAME, GEN_EDIPARTY),
41     ASN1_IMP(GENERAL_NAME, d.uniformResourceIdentifier, ASN1_IA5STRING, GEN_URI),
42     ASN1_IMP(GENERAL_NAME, d.iPAddress, ASN1_OCTET_STRING, GEN_IPADD),
43     ASN1_IMP(GENERAL_NAME, d.registeredID, ASN1_OBJECT, GEN_RID)
44 } ASN1_CHOICE_END(GENERAL_NAME)
45 
46 IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAME)
47 
48 ASN1_ITEM_TEMPLATE(GENERAL_NAMES) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, GENERAL_NAME)
49 ASN1_ITEM_TEMPLATE_END(GENERAL_NAMES)
50 
51 IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAMES)
52 
53 GENERAL_NAME *GENERAL_NAME_dup(const GENERAL_NAME *a)
54 {
55     return (GENERAL_NAME *)ASN1_dup((i2d_of_void *)i2d_GENERAL_NAME,
56         (d2i_of_void *)d2i_GENERAL_NAME,
57         (char *)a);
58 }
59 
GENERAL_NAME_set1_X509_NAME(GENERAL_NAME ** tgt,const X509_NAME * src)60 int GENERAL_NAME_set1_X509_NAME(GENERAL_NAME **tgt, const X509_NAME *src)
61 {
62     GENERAL_NAME *name;
63 
64     if (tgt == NULL) {
65         ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NULL_ARGUMENT);
66         return 0;
67     }
68 
69     if ((name = GENERAL_NAME_new()) == NULL)
70         return 0;
71     name->type = GEN_DIRNAME;
72 
73     if (src == NULL) { /* NULL-DN */
74         if ((name->d.directoryName = X509_NAME_new()) == NULL)
75             goto err;
76     } else if (!X509_NAME_set(&name->d.directoryName, src)) {
77         goto err;
78     }
79 
80     GENERAL_NAME_free(*tgt);
81     *tgt = name;
82     return 1;
83 
84 err:
85     GENERAL_NAME_free(name);
86     return 0;
87 }
88 
edipartyname_cmp(const EDIPARTYNAME * a,const EDIPARTYNAME * b)89 static int edipartyname_cmp(const EDIPARTYNAME *a, const EDIPARTYNAME *b)
90 {
91     int res;
92 
93     if (a == NULL || b == NULL) {
94         /*
95          * Shouldn't be possible in a valid GENERAL_NAME, but we handle it
96          * anyway. OTHERNAME_cmp treats NULL != NULL so we do the same here
97          */
98         return -1;
99     }
100     if (a->nameAssigner == NULL && b->nameAssigner != NULL)
101         return -1;
102     if (a->nameAssigner != NULL && b->nameAssigner == NULL)
103         return 1;
104     /* If we get here then both have nameAssigner set, or both unset */
105     if (a->nameAssigner != NULL) {
106         res = ASN1_STRING_cmp(a->nameAssigner, b->nameAssigner);
107         if (res != 0)
108             return res;
109     }
110     /*
111      * partyName is required, so these should never be NULL. We treat it in
112      * the same way as the a == NULL || b == NULL case above
113      */
114     if (a->partyName == NULL || b->partyName == NULL)
115         return -1;
116 
117     return ASN1_STRING_cmp(a->partyName, b->partyName);
118 }
119 
120 /* Returns 0 if they are equal, != 0 otherwise. */
GENERAL_NAME_cmp(GENERAL_NAME * a,GENERAL_NAME * b)121 int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b)
122 {
123     int result = -1;
124 
125     if (!a || !b || a->type != b->type)
126         return -1;
127     switch (a->type) {
128     case GEN_X400:
129         result = ASN1_STRING_cmp(a->d.x400Address, b->d.x400Address);
130         break;
131 
132     case GEN_EDIPARTY:
133         result = edipartyname_cmp(a->d.ediPartyName, b->d.ediPartyName);
134         break;
135 
136     case GEN_OTHERNAME:
137         result = OTHERNAME_cmp(a->d.otherName, b->d.otherName);
138         break;
139 
140     case GEN_EMAIL:
141     case GEN_DNS:
142     case GEN_URI:
143         result = ASN1_STRING_cmp(a->d.ia5, b->d.ia5);
144         break;
145 
146     case GEN_DIRNAME:
147         result = X509_NAME_cmp(a->d.dirn, b->d.dirn);
148         break;
149 
150     case GEN_IPADD:
151         result = ASN1_OCTET_STRING_cmp(a->d.ip, b->d.ip);
152         break;
153 
154     case GEN_RID:
155         result = OBJ_cmp(a->d.rid, b->d.rid);
156         break;
157     }
158     return result;
159 }
160 
161 /* Returns 0 if they are equal, != 0 otherwise. */
OTHERNAME_cmp(OTHERNAME * a,OTHERNAME * b)162 int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b)
163 {
164     int result = -1;
165 
166     if (!a || !b)
167         return -1;
168     /* Check their type first. */
169     if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0)
170         return result;
171     /* Check the value. */
172     result = ASN1_TYPE_cmp(a->value, b->value);
173     return result;
174 }
175 
GENERAL_NAME_set0_value(GENERAL_NAME * a,int type,void * value)176 void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value)
177 {
178     switch (type) {
179     case GEN_X400:
180         a->d.x400Address = value;
181         break;
182 
183     case GEN_EDIPARTY:
184         a->d.ediPartyName = value;
185         break;
186 
187     case GEN_OTHERNAME:
188         a->d.otherName = value;
189         break;
190 
191     case GEN_EMAIL:
192     case GEN_DNS:
193     case GEN_URI:
194         a->d.ia5 = value;
195         break;
196 
197     case GEN_DIRNAME:
198         a->d.dirn = value;
199         break;
200 
201     case GEN_IPADD:
202         a->d.ip = value;
203         break;
204 
205     case GEN_RID:
206         a->d.rid = value;
207         break;
208     }
209     a->type = type;
210 }
211 
GENERAL_NAME_get0_value(const GENERAL_NAME * a,int * ptype)212 void *GENERAL_NAME_get0_value(const GENERAL_NAME *a, int *ptype)
213 {
214     if (ptype)
215         *ptype = a->type;
216     switch (a->type) {
217     case GEN_X400:
218         return a->d.x400Address;
219 
220     case GEN_EDIPARTY:
221         return a->d.ediPartyName;
222 
223     case GEN_OTHERNAME:
224         return a->d.otherName;
225 
226     case GEN_EMAIL:
227     case GEN_DNS:
228     case GEN_URI:
229         return a->d.ia5;
230 
231     case GEN_DIRNAME:
232         return a->d.dirn;
233 
234     case GEN_IPADD:
235         return a->d.ip;
236 
237     case GEN_RID:
238         return a->d.rid;
239 
240     default:
241         return NULL;
242     }
243 }
244 
GENERAL_NAME_set0_othername(GENERAL_NAME * gen,ASN1_OBJECT * oid,ASN1_TYPE * value)245 int GENERAL_NAME_set0_othername(GENERAL_NAME *gen,
246     ASN1_OBJECT *oid, ASN1_TYPE *value)
247 {
248     OTHERNAME *oth;
249     oth = OTHERNAME_new();
250     if (oth == NULL)
251         return 0;
252     ASN1_TYPE_free(oth->value);
253     oth->type_id = oid;
254     oth->value = value;
255     GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth);
256     return 1;
257 }
258 
GENERAL_NAME_get0_otherName(const GENERAL_NAME * gen,ASN1_OBJECT ** poid,ASN1_TYPE ** pvalue)259 int GENERAL_NAME_get0_otherName(const GENERAL_NAME *gen,
260     ASN1_OBJECT **poid, ASN1_TYPE **pvalue)
261 {
262     if (gen->type != GEN_OTHERNAME)
263         return 0;
264     if (poid)
265         *poid = gen->d.otherName->type_id;
266     if (pvalue)
267         *pvalue = gen->d.otherName->value;
268     return 1;
269 }
270