]>
Commit | Line | Data |
---|---|---|
b1322259 | 1 | /* |
33388b44 | 2 | * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. |
d02b48c6 | 3 | * |
3e4b43b9 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
b1322259 RS |
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 | |
d02b48c6 RE |
8 | */ |
9 | ||
10 | #include <stdio.h> | |
b39fc560 | 11 | #include "internal/cryptlib.h" |
1f5e0f92 | 12 | #include <openssl/safestack.h> |
ec577822 BM |
13 | #include <openssl/asn1.h> |
14 | #include <openssl/objects.h> | |
15 | #include <openssl/evp.h> | |
16 | #include <openssl/x509.h> | |
25f2138b | 17 | #include "crypto/x509.h" |
d02b48c6 | 18 | |
852c2ed2 RS |
19 | DEFINE_STACK_OF(X509_NAME_ENTRY) |
20 | ||
8cc86b81 DDO |
21 | int X509_NAME_get_text_by_NID(const X509_NAME *name, int nid, |
22 | char *buf, int len) | |
0f113f3e MC |
23 | { |
24 | ASN1_OBJECT *obj; | |
d02b48c6 | 25 | |
0f113f3e MC |
26 | obj = OBJ_nid2obj(nid); |
27 | if (obj == NULL) | |
26a7d938 K |
28 | return -1; |
29 | return X509_NAME_get_text_by_OBJ(name, obj, buf, len); | |
0f113f3e | 30 | } |
d02b48c6 | 31 | |
8cc86b81 | 32 | int X509_NAME_get_text_by_OBJ(const X509_NAME *name, const ASN1_OBJECT *obj, |
28ad7318 | 33 | char *buf, int len) |
0f113f3e MC |
34 | { |
35 | int i; | |
9f5466b9 | 36 | const ASN1_STRING *data; |
0f113f3e MC |
37 | |
38 | i = X509_NAME_get_index_by_OBJ(name, obj, -1); | |
39 | if (i < 0) | |
26a7d938 | 40 | return -1; |
0f113f3e | 41 | data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i)); |
0f113f3e | 42 | if (buf == NULL) |
26a7d938 | 43 | return data->length; |
28ad7318 AP |
44 | if (len <= 0) |
45 | return 0; | |
46 | i = (data->length > (len - 1)) ? (len - 1) : data->length; | |
0f113f3e MC |
47 | memcpy(buf, data->data, i); |
48 | buf[i] = '\0'; | |
26a7d938 | 49 | return i; |
0f113f3e | 50 | } |
d02b48c6 | 51 | |
333ed02c | 52 | int X509_NAME_entry_count(const X509_NAME *name) |
0f113f3e MC |
53 | { |
54 | if (name == NULL) | |
26a7d938 K |
55 | return 0; |
56 | return sk_X509_NAME_ENTRY_num(name->entries); | |
0f113f3e | 57 | } |
d02b48c6 | 58 | |
8cc86b81 | 59 | int X509_NAME_get_index_by_NID(const X509_NAME *name, int nid, int lastpos) |
0f113f3e MC |
60 | { |
61 | ASN1_OBJECT *obj; | |
d02b48c6 | 62 | |
0f113f3e MC |
63 | obj = OBJ_nid2obj(nid); |
64 | if (obj == NULL) | |
26a7d938 K |
65 | return -2; |
66 | return X509_NAME_get_index_by_OBJ(name, obj, lastpos); | |
0f113f3e | 67 | } |
d02b48c6 | 68 | |
0d4fb843 | 69 | /* NOTE: you should be passing -1, not 0 as lastpos */ |
8cc86b81 DDO |
70 | int X509_NAME_get_index_by_OBJ(const X509_NAME *name, const ASN1_OBJECT *obj, |
71 | int lastpos) | |
0f113f3e MC |
72 | { |
73 | int n; | |
74 | X509_NAME_ENTRY *ne; | |
75 | STACK_OF(X509_NAME_ENTRY) *sk; | |
76 | ||
77 | if (name == NULL) | |
26a7d938 | 78 | return -1; |
0f113f3e MC |
79 | if (lastpos < 0) |
80 | lastpos = -1; | |
81 | sk = name->entries; | |
82 | n = sk_X509_NAME_ENTRY_num(sk); | |
83 | for (lastpos++; lastpos < n; lastpos++) { | |
84 | ne = sk_X509_NAME_ENTRY_value(sk, lastpos); | |
85 | if (OBJ_cmp(ne->object, obj) == 0) | |
26a7d938 | 86 | return lastpos; |
0f113f3e | 87 | } |
26a7d938 | 88 | return -1; |
0f113f3e | 89 | } |
d02b48c6 | 90 | |
0fe91236 | 91 | X509_NAME_ENTRY *X509_NAME_get_entry(const X509_NAME *name, int loc) |
0f113f3e MC |
92 | { |
93 | if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc | |
94 | || loc < 0) | |
d2a56999 F |
95 | return NULL; |
96 | ||
97 | return sk_X509_NAME_ENTRY_value(name->entries, loc); | |
0f113f3e | 98 | } |
d02b48c6 | 99 | |
6b691a5c | 100 | X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc) |
0f113f3e MC |
101 | { |
102 | X509_NAME_ENTRY *ret; | |
103 | int i, n, set_prev, set_next; | |
104 | STACK_OF(X509_NAME_ENTRY) *sk; | |
105 | ||
106 | if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc | |
107 | || loc < 0) | |
d2a56999 F |
108 | return NULL; |
109 | ||
0f113f3e MC |
110 | sk = name->entries; |
111 | ret = sk_X509_NAME_ENTRY_delete(sk, loc); | |
112 | n = sk_X509_NAME_ENTRY_num(sk); | |
113 | name->modified = 1; | |
114 | if (loc == n) | |
d2a56999 | 115 | return ret; |
0f113f3e MC |
116 | |
117 | /* else we need to fixup the set field */ | |
118 | if (loc != 0) | |
119 | set_prev = (sk_X509_NAME_ENTRY_value(sk, loc - 1))->set; | |
120 | else | |
121 | set_prev = ret->set - 1; | |
122 | set_next = sk_X509_NAME_ENTRY_value(sk, loc)->set; | |
123 | ||
35a1cc90 MC |
124 | /*- |
125 | * set_prev is the previous set | |
126 | * set is the current set | |
127 | * set_next is the following | |
128 | * prev 1 1 1 1 1 1 1 1 | |
129 | * set 1 1 2 2 | |
130 | * next 1 1 2 2 2 2 3 2 | |
131 | * so basically only if prev and next differ by 2, then | |
132 | * re-number down by 1 | |
133 | */ | |
0f113f3e MC |
134 | if (set_prev + 1 < set_next) |
135 | for (i = loc; i < n; i++) | |
136 | sk_X509_NAME_ENTRY_value(sk, i)->set--; | |
d2a56999 | 137 | return ret; |
0f113f3e | 138 | } |
d02b48c6 | 139 | |
333ed02c | 140 | int X509_NAME_add_entry_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int type, |
924212a6 | 141 | const unsigned char *bytes, int len, int loc, |
0f113f3e | 142 | int set) |
74400f73 | 143 | { |
0f113f3e MC |
144 | X509_NAME_ENTRY *ne; |
145 | int ret; | |
d2a56999 | 146 | |
0f113f3e MC |
147 | ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len); |
148 | if (!ne) | |
149 | return 0; | |
150 | ret = X509_NAME_add_entry(name, ne, loc, set); | |
151 | X509_NAME_ENTRY_free(ne); | |
152 | return ret; | |
74400f73 DSH |
153 | } |
154 | ||
155 | int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type, | |
924212a6 | 156 | const unsigned char *bytes, int len, int loc, |
0f113f3e | 157 | int set) |
74400f73 | 158 | { |
0f113f3e MC |
159 | X509_NAME_ENTRY *ne; |
160 | int ret; | |
161 | ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len); | |
162 | if (!ne) | |
163 | return 0; | |
164 | ret = X509_NAME_add_entry(name, ne, loc, set); | |
165 | X509_NAME_ENTRY_free(ne); | |
166 | return ret; | |
74400f73 DSH |
167 | } |
168 | ||
0821bcd4 | 169 | int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type, |
0f113f3e MC |
170 | const unsigned char *bytes, int len, int loc, |
171 | int set) | |
74400f73 | 172 | { |
0f113f3e MC |
173 | X509_NAME_ENTRY *ne; |
174 | int ret; | |
175 | ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len); | |
176 | if (!ne) | |
177 | return 0; | |
178 | ret = X509_NAME_add_entry(name, ne, loc, set); | |
179 | X509_NAME_ENTRY_free(ne); | |
180 | return ret; | |
74400f73 DSH |
181 | } |
182 | ||
0f113f3e MC |
183 | /* |
184 | * if set is -1, append to previous set, 0 'a new one', and 1, prepend to the | |
185 | * guy we are about to stomp on. | |
186 | */ | |
9f5466b9 | 187 | int X509_NAME_add_entry(X509_NAME *name, const X509_NAME_ENTRY *ne, int loc, |
0f113f3e MC |
188 | int set) |
189 | { | |
190 | X509_NAME_ENTRY *new_name = NULL; | |
191 | int n, i, inc; | |
192 | STACK_OF(X509_NAME_ENTRY) *sk; | |
193 | ||
194 | if (name == NULL) | |
26a7d938 | 195 | return 0; |
0f113f3e MC |
196 | sk = name->entries; |
197 | n = sk_X509_NAME_ENTRY_num(sk); | |
198 | if (loc > n) | |
199 | loc = n; | |
200 | else if (loc < 0) | |
201 | loc = n; | |
bbf27cd5 | 202 | inc = (set == 0); |
0f113f3e MC |
203 | name->modified = 1; |
204 | ||
205 | if (set == -1) { | |
206 | if (loc == 0) { | |
207 | set = 0; | |
208 | inc = 1; | |
209 | } else { | |
210 | set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set; | |
0f113f3e MC |
211 | } |
212 | } else { /* if (set >= 0) */ | |
213 | ||
214 | if (loc >= n) { | |
215 | if (loc != 0) | |
216 | set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set + 1; | |
217 | else | |
218 | set = 0; | |
219 | } else | |
220 | set = sk_X509_NAME_ENTRY_value(sk, loc)->set; | |
0f113f3e MC |
221 | } |
222 | ||
8cc86b81 | 223 | if ((new_name = X509_NAME_ENTRY_dup(ne)) == NULL) |
0f113f3e MC |
224 | goto err; |
225 | new_name->set = set; | |
226 | if (!sk_X509_NAME_ENTRY_insert(sk, new_name, loc)) { | |
227 | X509err(X509_F_X509_NAME_ADD_ENTRY, ERR_R_MALLOC_FAILURE); | |
228 | goto err; | |
229 | } | |
230 | if (inc) { | |
231 | n = sk_X509_NAME_ENTRY_num(sk); | |
232 | for (i = loc + 1; i < n; i++) | |
bbf27cd5 | 233 | sk_X509_NAME_ENTRY_value(sk, i)->set += 1; |
0f113f3e | 234 | } |
208fb891 | 235 | return 1; |
0f113f3e | 236 | err: |
222561fe | 237 | X509_NAME_ENTRY_free(new_name); |
26a7d938 | 238 | return 0; |
0f113f3e | 239 | } |
d02b48c6 | 240 | |
74400f73 | 241 | X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne, |
0f113f3e MC |
242 | const char *field, int type, |
243 | const unsigned char *bytes, | |
244 | int len) | |
245 | { | |
246 | ASN1_OBJECT *obj; | |
247 | X509_NAME_ENTRY *nentry; | |
248 | ||
249 | obj = OBJ_txt2obj(field, 0); | |
250 | if (obj == NULL) { | |
251 | X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_TXT, | |
252 | X509_R_INVALID_FIELD_NAME); | |
253 | ERR_add_error_data(2, "name=", field); | |
26a7d938 | 254 | return NULL; |
0f113f3e MC |
255 | } |
256 | nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len); | |
257 | ASN1_OBJECT_free(obj); | |
258 | return nentry; | |
259 | } | |
74400f73 | 260 | |
6b691a5c | 261 | X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid, |
924212a6 F |
262 | int type, |
263 | const unsigned char *bytes, | |
0f113f3e MC |
264 | int len) |
265 | { | |
266 | ASN1_OBJECT *obj; | |
267 | X509_NAME_ENTRY *nentry; | |
268 | ||
269 | obj = OBJ_nid2obj(nid); | |
270 | if (obj == NULL) { | |
271 | X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_NID, X509_R_UNKNOWN_NID); | |
26a7d938 | 272 | return NULL; |
0f113f3e MC |
273 | } |
274 | nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len); | |
275 | ASN1_OBJECT_free(obj); | |
276 | return nentry; | |
277 | } | |
d02b48c6 | 278 | |
6b691a5c | 279 | X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne, |
333ed02c | 280 | const ASN1_OBJECT *obj, int type, |
0f113f3e MC |
281 | const unsigned char *bytes, |
282 | int len) | |
283 | { | |
284 | X509_NAME_ENTRY *ret; | |
285 | ||
286 | if ((ne == NULL) || (*ne == NULL)) { | |
287 | if ((ret = X509_NAME_ENTRY_new()) == NULL) | |
26a7d938 | 288 | return NULL; |
0f113f3e MC |
289 | } else |
290 | ret = *ne; | |
291 | ||
292 | if (!X509_NAME_ENTRY_set_object(ret, obj)) | |
293 | goto err; | |
294 | if (!X509_NAME_ENTRY_set_data(ret, type, bytes, len)) | |
295 | goto err; | |
296 | ||
297 | if ((ne != NULL) && (*ne == NULL)) | |
298 | *ne = ret; | |
26a7d938 | 299 | return ret; |
0f113f3e MC |
300 | err: |
301 | if ((ne == NULL) || (ret != *ne)) | |
302 | X509_NAME_ENTRY_free(ret); | |
26a7d938 | 303 | return NULL; |
0f113f3e | 304 | } |
d02b48c6 | 305 | |
333ed02c | 306 | int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, const ASN1_OBJECT *obj) |
0f113f3e MC |
307 | { |
308 | if ((ne == NULL) || (obj == NULL)) { | |
309 | X509err(X509_F_X509_NAME_ENTRY_SET_OBJECT, | |
310 | ERR_R_PASSED_NULL_PARAMETER); | |
26a7d938 | 311 | return 0; |
0f113f3e MC |
312 | } |
313 | ASN1_OBJECT_free(ne->object); | |
314 | ne->object = OBJ_dup(obj); | |
315 | return ((ne->object == NULL) ? 0 : 1); | |
316 | } | |
d02b48c6 | 317 | |
6b691a5c | 318 | int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type, |
0f113f3e MC |
319 | const unsigned char *bytes, int len) |
320 | { | |
321 | int i; | |
322 | ||
323 | if ((ne == NULL) || ((bytes == NULL) && (len != 0))) | |
26a7d938 | 324 | return 0; |
0f113f3e MC |
325 | if ((type > 0) && (type & MBSTRING_FLAG)) |
326 | return ASN1_STRING_set_by_NID(&ne->value, bytes, | |
327 | len, type, | |
328 | OBJ_obj2nid(ne->object)) ? 1 : 0; | |
329 | if (len < 0) | |
330 | len = strlen((const char *)bytes); | |
331 | i = ASN1_STRING_set(ne->value, bytes, len); | |
332 | if (!i) | |
26a7d938 | 333 | return 0; |
0f113f3e MC |
334 | if (type != V_ASN1_UNDEF) { |
335 | if (type == V_ASN1_APP_CHOOSE) | |
336 | ne->value->type = ASN1_PRINTABLE_type(bytes, len); | |
337 | else | |
338 | ne->value->type = type; | |
339 | } | |
208fb891 | 340 | return 1; |
0f113f3e | 341 | } |
d02b48c6 | 342 | |
9f5466b9 | 343 | ASN1_OBJECT *X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY *ne) |
0f113f3e MC |
344 | { |
345 | if (ne == NULL) | |
26a7d938 K |
346 | return NULL; |
347 | return ne->object; | |
0f113f3e | 348 | } |
d02b48c6 | 349 | |
9f5466b9 | 350 | ASN1_STRING *X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne) |
0f113f3e MC |
351 | { |
352 | if (ne == NULL) | |
26a7d938 K |
353 | return NULL; |
354 | return ne->value; | |
0f113f3e | 355 | } |
2743e38c DSH |
356 | |
357 | int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne) | |
358 | { | |
359 | return ne->set; | |
360 | } |