/src/openssl/crypto/x509/v3_genn.c
Line | Count | Source |
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 | 0 | } ASN1_SEQUENCE_END(OTHERNAME) |
21 | 0 |
|
22 | 0 | IMPLEMENT_ASN1_FUNCTIONS(OTHERNAME) |
23 | 0 |
|
24 | 0 | ASN1_SEQUENCE(EDIPARTYNAME) = { |
25 | 0 | /* DirectoryString is a CHOICE type so use explicit tagging */ |
26 | 0 | ASN1_EXP_OPT(EDIPARTYNAME, nameAssigner, DIRECTORYSTRING, 0), |
27 | 0 | ASN1_EXP(EDIPARTYNAME, partyName, DIRECTORYSTRING, 1) |
28 | 0 | } ASN1_SEQUENCE_END(EDIPARTYNAME) |
29 | 0 |
|
30 | 0 | IMPLEMENT_ASN1_FUNCTIONS(EDIPARTYNAME) |
31 | 0 |
|
32 | 0 | ASN1_CHOICE(GENERAL_NAME) = { |
33 | 0 | ASN1_IMP(GENERAL_NAME, d.otherName, OTHERNAME, GEN_OTHERNAME), |
34 | 0 | ASN1_IMP(GENERAL_NAME, d.rfc822Name, ASN1_IA5STRING, GEN_EMAIL), |
35 | 0 | ASN1_IMP(GENERAL_NAME, d.dNSName, ASN1_IA5STRING, GEN_DNS), |
36 | 0 | /* Don't decode this */ |
37 | 0 | ASN1_IMP(GENERAL_NAME, d.x400Address, ASN1_SEQUENCE, GEN_X400), |
38 | 0 | /* X509_NAME is a CHOICE type so use EXPLICIT */ |
39 | 0 | ASN1_EXP(GENERAL_NAME, d.directoryName, X509_NAME, GEN_DIRNAME), |
40 | 0 | ASN1_IMP(GENERAL_NAME, d.ediPartyName, EDIPARTYNAME, GEN_EDIPARTY), |
41 | 0 | ASN1_IMP(GENERAL_NAME, d.uniformResourceIdentifier, ASN1_IA5STRING, GEN_URI), |
42 | 0 | ASN1_IMP(GENERAL_NAME, d.iPAddress, ASN1_OCTET_STRING, GEN_IPADD), |
43 | 0 | ASN1_IMP(GENERAL_NAME, d.registeredID, ASN1_OBJECT, GEN_RID) |
44 | 0 | } ASN1_CHOICE_END(GENERAL_NAME) |
45 | 0 |
|
46 | 0 | IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAME) |
47 | 0 |
|
48 | 0 | ASN1_ITEM_TEMPLATE(GENERAL_NAMES) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, GENERAL_NAME) |
49 | 0 | 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 | 0 | { |
55 | 0 | return (GENERAL_NAME *)ASN1_dup((i2d_of_void *)i2d_GENERAL_NAME, |
56 | 0 | (d2i_of_void *)d2i_GENERAL_NAME, |
57 | 0 | (char *)a); |
58 | 0 | } |
59 | | |
60 | | int GENERAL_NAME_set1_X509_NAME(GENERAL_NAME **tgt, const X509_NAME *src) |
61 | 0 | { |
62 | 0 | GENERAL_NAME *name; |
63 | |
|
64 | 0 | if (tgt == NULL) { |
65 | 0 | ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NULL_ARGUMENT); |
66 | 0 | return 0; |
67 | 0 | } |
68 | | |
69 | 0 | if ((name = GENERAL_NAME_new()) == NULL) |
70 | 0 | return 0; |
71 | 0 | name->type = GEN_DIRNAME; |
72 | |
|
73 | 0 | if (src == NULL) { /* NULL-DN */ |
74 | 0 | if ((name->d.directoryName = X509_NAME_new()) == NULL) |
75 | 0 | goto err; |
76 | 0 | } else if (!X509_NAME_set(&name->d.directoryName, src)) { |
77 | 0 | goto err; |
78 | 0 | } |
79 | | |
80 | 0 | GENERAL_NAME_free(*tgt); |
81 | 0 | *tgt = name; |
82 | 0 | return 1; |
83 | | |
84 | 0 | err: |
85 | 0 | GENERAL_NAME_free(name); |
86 | 0 | return 0; |
87 | 0 | } |
88 | | |
89 | | static int edipartyname_cmp(const EDIPARTYNAME *a, const EDIPARTYNAME *b) |
90 | 0 | { |
91 | 0 | int res; |
92 | |
|
93 | 0 | 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 | 0 | return -1; |
99 | 0 | } |
100 | 0 | if (a->nameAssigner == NULL && b->nameAssigner != NULL) |
101 | 0 | return -1; |
102 | 0 | if (a->nameAssigner != NULL && b->nameAssigner == NULL) |
103 | 0 | return 1; |
104 | | /* If we get here then both have nameAssigner set, or both unset */ |
105 | 0 | if (a->nameAssigner != NULL) { |
106 | 0 | res = ASN1_STRING_cmp(a->nameAssigner, b->nameAssigner); |
107 | 0 | if (res != 0) |
108 | 0 | return res; |
109 | 0 | } |
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 | 0 | if (a->partyName == NULL || b->partyName == NULL) |
115 | 0 | return -1; |
116 | | |
117 | 0 | return ASN1_STRING_cmp(a->partyName, b->partyName); |
118 | 0 | } |
119 | | |
120 | | /* Returns 0 if they are equal, != 0 otherwise. */ |
121 | | int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b) |
122 | 0 | { |
123 | 0 | int result = -1; |
124 | |
|
125 | 0 | if (!a || !b || a->type != b->type) |
126 | 0 | return -1; |
127 | 0 | switch (a->type) { |
128 | 0 | case GEN_X400: |
129 | 0 | result = ASN1_STRING_cmp(a->d.x400Address, b->d.x400Address); |
130 | 0 | break; |
131 | | |
132 | 0 | case GEN_EDIPARTY: |
133 | 0 | result = edipartyname_cmp(a->d.ediPartyName, b->d.ediPartyName); |
134 | 0 | break; |
135 | | |
136 | 0 | case GEN_OTHERNAME: |
137 | 0 | result = OTHERNAME_cmp(a->d.otherName, b->d.otherName); |
138 | 0 | break; |
139 | | |
140 | 0 | case GEN_EMAIL: |
141 | 0 | case GEN_DNS: |
142 | 0 | case GEN_URI: |
143 | 0 | result = ASN1_STRING_cmp(a->d.ia5, b->d.ia5); |
144 | 0 | break; |
145 | | |
146 | 0 | case GEN_DIRNAME: |
147 | 0 | result = X509_NAME_cmp(a->d.dirn, b->d.dirn); |
148 | 0 | break; |
149 | | |
150 | 0 | case GEN_IPADD: |
151 | 0 | result = ASN1_OCTET_STRING_cmp(a->d.ip, b->d.ip); |
152 | 0 | break; |
153 | | |
154 | 0 | case GEN_RID: |
155 | 0 | result = OBJ_cmp(a->d.rid, b->d.rid); |
156 | 0 | break; |
157 | 0 | } |
158 | 0 | return result; |
159 | 0 | } |
160 | | |
161 | | /* Returns 0 if they are equal, != 0 otherwise. */ |
162 | | int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b) |
163 | 0 | { |
164 | 0 | int result = -1; |
165 | |
|
166 | 0 | if (!a || !b) |
167 | 0 | return -1; |
168 | | /* Check their type first. */ |
169 | 0 | if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0) |
170 | 0 | return result; |
171 | | /* Check the value. */ |
172 | 0 | result = ASN1_TYPE_cmp(a->value, b->value); |
173 | 0 | return result; |
174 | 0 | } |
175 | | |
176 | | void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value) |
177 | 0 | { |
178 | 0 | switch (type) { |
179 | 0 | case GEN_X400: |
180 | 0 | a->d.x400Address = value; |
181 | 0 | break; |
182 | | |
183 | 0 | case GEN_EDIPARTY: |
184 | 0 | a->d.ediPartyName = value; |
185 | 0 | break; |
186 | | |
187 | 0 | case GEN_OTHERNAME: |
188 | 0 | a->d.otherName = value; |
189 | 0 | break; |
190 | | |
191 | 0 | case GEN_EMAIL: |
192 | 0 | case GEN_DNS: |
193 | 0 | case GEN_URI: |
194 | 0 | a->d.ia5 = value; |
195 | 0 | break; |
196 | | |
197 | 0 | case GEN_DIRNAME: |
198 | 0 | a->d.dirn = value; |
199 | 0 | break; |
200 | | |
201 | 0 | case GEN_IPADD: |
202 | 0 | a->d.ip = value; |
203 | 0 | break; |
204 | | |
205 | 0 | case GEN_RID: |
206 | 0 | a->d.rid = value; |
207 | 0 | break; |
208 | 0 | } |
209 | 0 | a->type = type; |
210 | 0 | } |
211 | | |
212 | | void *GENERAL_NAME_get0_value(const GENERAL_NAME *a, int *ptype) |
213 | 0 | { |
214 | 0 | if (ptype) |
215 | 0 | *ptype = a->type; |
216 | 0 | switch (a->type) { |
217 | 0 | case GEN_X400: |
218 | 0 | return a->d.x400Address; |
219 | | |
220 | 0 | case GEN_EDIPARTY: |
221 | 0 | return a->d.ediPartyName; |
222 | | |
223 | 0 | case GEN_OTHERNAME: |
224 | 0 | return a->d.otherName; |
225 | | |
226 | 0 | case GEN_EMAIL: |
227 | 0 | case GEN_DNS: |
228 | 0 | case GEN_URI: |
229 | 0 | return a->d.ia5; |
230 | | |
231 | 0 | case GEN_DIRNAME: |
232 | 0 | return a->d.dirn; |
233 | | |
234 | 0 | case GEN_IPADD: |
235 | 0 | return a->d.ip; |
236 | | |
237 | 0 | case GEN_RID: |
238 | 0 | return a->d.rid; |
239 | | |
240 | 0 | default: |
241 | 0 | return NULL; |
242 | 0 | } |
243 | 0 | } |
244 | | |
245 | | int GENERAL_NAME_set0_othername(GENERAL_NAME *gen, |
246 | | ASN1_OBJECT *oid, ASN1_TYPE *value) |
247 | 0 | { |
248 | 0 | OTHERNAME *oth; |
249 | 0 | oth = OTHERNAME_new(); |
250 | 0 | if (oth == NULL) |
251 | 0 | return 0; |
252 | 0 | ASN1_TYPE_free(oth->value); |
253 | 0 | oth->type_id = oid; |
254 | 0 | oth->value = value; |
255 | 0 | GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth); |
256 | 0 | return 1; |
257 | 0 | } |
258 | | |
259 | | int GENERAL_NAME_get0_otherName(const GENERAL_NAME *gen, |
260 | | ASN1_OBJECT **poid, ASN1_TYPE **pvalue) |
261 | 0 | { |
262 | 0 | if (gen->type != GEN_OTHERNAME) |
263 | 0 | return 0; |
264 | 0 | if (poid) |
265 | 0 | *poid = gen->d.otherName->type_id; |
266 | 0 | if (pvalue) |
267 | 0 | *pvalue = gen->d.otherName->value; |
268 | 0 | return 1; |
269 | 0 | } |