1 /* Copyright (C) 1995-1998 Eric Young ([email protected])
2 * All rights reserved.
3 *
4 * This package is an SSL implementation written
5 * by Eric Young ([email protected]).
6 * The implementation was written so as to conform with Netscapes SSL.
7 *
8 * This library is free for commercial and non-commercial use as long as
9 * the following conditions are aheared to. The following conditions
10 * apply to all code found in this distribution, be it the RC4, RSA,
11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
12 * included with this distribution is covered by the same copyright terms
13 * except that the holder is Tim Hudson ([email protected]).
14 *
15 * Copyright remains Eric Young's, and as such any Copyright notices in
16 * the code are not to be removed.
17 * If this package is used in a product, Eric Young should be given attribution
18 * as the author of the parts of the library used.
19 * This can be in the form of a textual message at program startup or
20 * in documentation (online or textual) provided with the package.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
25 * 1. Redistributions of source code must retain the copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution.
30 * 3. All advertising materials mentioning features or use of this software
31 * must display the following acknowledgement:
32 * "This product includes cryptographic software written by
33 * Eric Young ([email protected])"
34 * The word 'cryptographic' can be left out if the rouines from the library
35 * being used are not cryptographic related :-).
36 * 4. If you include any Windows specific code (or a derivative thereof) from
37 * the apps directory (application code) you must include an acknowledgement:
38 * "This product includes software written by Tim Hudson ([email protected])"
39 *
40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * SUCH DAMAGE.
51 *
52 * The licence and distribution terms for any publically available version or
53 * derivative of this code cannot be changed. i.e. this code cannot simply be
54 * copied and put under another distribution licence
55 * [including the GNU Public Licence.] */
56
57 #include <string.h>
58
59 #include <openssl/asn1.h>
60 #include <openssl/bytestring.h>
61 #include <openssl/err.h>
62 #include <openssl/evp.h>
63 #include <openssl/obj.h>
64 #include <openssl/stack.h>
65 #include <openssl/x509.h>
66
67 #include "../internal.h"
68 #include "internal.h"
69
70
X509_NAME_get_text_by_NID(const X509_NAME * name,int nid,char * buf,int len)71 int X509_NAME_get_text_by_NID(const X509_NAME *name, int nid, char *buf,
72 int len) {
73 const ASN1_OBJECT *obj;
74
75 obj = OBJ_nid2obj(nid);
76 if (obj == NULL) {
77 return -1;
78 }
79 return (X509_NAME_get_text_by_OBJ(name, obj, buf, len));
80 }
81
X509_NAME_get_text_by_OBJ(const X509_NAME * name,const ASN1_OBJECT * obj,char * buf,int len)82 int X509_NAME_get_text_by_OBJ(const X509_NAME *name, const ASN1_OBJECT *obj,
83 char *buf, int len) {
84 int i = X509_NAME_get_index_by_OBJ(name, obj, -1);
85 if (i < 0) {
86 return -1;
87 }
88 const ASN1_STRING *data =
89 X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
90 unsigned char *text = NULL;
91 int ret = -1;
92 int text_len = ASN1_STRING_to_UTF8(&text, data);
93 // Fail if we could not encode as UTF-8.
94 if (text_len < 0) {
95 goto out;
96 }
97 CBS cbs;
98 CBS_init(&cbs, text, text_len);
99 // Fail if the UTF-8 encoding constains a 0 byte because this is
100 // returned as a C string and callers very often do not check.
101 if (CBS_contains_zero_byte(&cbs)) {
102 goto out;
103 }
104 // We still support the "pass NULL to find out how much" API
105 if (buf != NULL) {
106 if (text_len >= len || len <= 0 ||
107 !CBS_copy_bytes(&cbs, (uint8_t *)buf, text_len)) {
108 goto out;
109 }
110 // It must be a C string
111 buf[text_len] = '\0';
112 }
113 ret = text_len;
114
115 out:
116 OPENSSL_free(text);
117 return ret;
118 }
119
X509_NAME_entry_count(const X509_NAME * name)120 int X509_NAME_entry_count(const X509_NAME *name) {
121 if (name == NULL) {
122 return 0;
123 }
124 return (int)sk_X509_NAME_ENTRY_num(name->entries);
125 }
126
X509_NAME_get_index_by_NID(const X509_NAME * name,int nid,int lastpos)127 int X509_NAME_get_index_by_NID(const X509_NAME *name, int nid, int lastpos) {
128 const ASN1_OBJECT *obj;
129
130 obj = OBJ_nid2obj(nid);
131 if (obj == NULL) {
132 return -2;
133 }
134 return X509_NAME_get_index_by_OBJ(name, obj, lastpos);
135 }
136
137 // NOTE: you should be passsing -1, not 0 as lastpos
X509_NAME_get_index_by_OBJ(const X509_NAME * name,const ASN1_OBJECT * obj,int lastpos)138 int X509_NAME_get_index_by_OBJ(const X509_NAME *name, const ASN1_OBJECT *obj,
139 int lastpos) {
140 if (name == NULL) {
141 return -1;
142 }
143 if (lastpos < 0) {
144 lastpos = -1;
145 }
146 const STACK_OF(X509_NAME_ENTRY) *sk = name->entries;
147 int n = (int)sk_X509_NAME_ENTRY_num(sk);
148 for (lastpos++; lastpos < n; lastpos++) {
149 const X509_NAME_ENTRY *ne = sk_X509_NAME_ENTRY_value(sk, lastpos);
150 if (OBJ_cmp(ne->object, obj) == 0) {
151 return lastpos;
152 }
153 }
154 return -1;
155 }
156
X509_NAME_get_entry(const X509_NAME * name,int loc)157 X509_NAME_ENTRY *X509_NAME_get_entry(const X509_NAME *name, int loc) {
158 if (name == NULL || loc < 0 ||
159 sk_X509_NAME_ENTRY_num(name->entries) <= (size_t)loc) {
160 return NULL;
161 } else {
162 return (sk_X509_NAME_ENTRY_value(name->entries, loc));
163 }
164 }
165
X509_NAME_delete_entry(X509_NAME * name,int loc)166 X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc) {
167 if (name == NULL || loc < 0 ||
168 sk_X509_NAME_ENTRY_num(name->entries) <= (size_t)loc) {
169 return NULL;
170 }
171
172 STACK_OF(X509_NAME_ENTRY) *sk = name->entries;
173 X509_NAME_ENTRY *ret = sk_X509_NAME_ENTRY_delete(sk, loc);
174 size_t n = sk_X509_NAME_ENTRY_num(sk);
175 name->modified = 1;
176 if ((size_t)loc == n) {
177 return ret;
178 }
179
180 int set_prev;
181 if (loc != 0) {
182 set_prev = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set;
183 } else {
184 set_prev = ret->set - 1;
185 }
186 int set_next = sk_X509_NAME_ENTRY_value(sk, loc)->set;
187
188 // If we removed a singleton RDN, update the RDN indices so they are
189 // consecutive again.
190 if (set_prev + 1 < set_next) {
191 for (size_t i = loc; i < n; i++) {
192 sk_X509_NAME_ENTRY_value(sk, i)->set--;
193 }
194 }
195 return ret;
196 }
197
X509_NAME_add_entry_by_OBJ(X509_NAME * name,const ASN1_OBJECT * obj,int type,const unsigned char * bytes,ossl_ssize_t len,int loc,int set)198 int X509_NAME_add_entry_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj,
199 int type, const unsigned char *bytes,
200 ossl_ssize_t len, int loc, int set) {
201 X509_NAME_ENTRY *ne =
202 X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len);
203 if (!ne) {
204 return 0;
205 }
206 int ret = X509_NAME_add_entry(name, ne, loc, set);
207 X509_NAME_ENTRY_free(ne);
208 return ret;
209 }
210
X509_NAME_add_entry_by_NID(X509_NAME * name,int nid,int type,const unsigned char * bytes,ossl_ssize_t len,int loc,int set)211 int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
212 const unsigned char *bytes, ossl_ssize_t len,
213 int loc, int set) {
214 X509_NAME_ENTRY *ne =
215 X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len);
216 if (!ne) {
217 return 0;
218 }
219 int ret = X509_NAME_add_entry(name, ne, loc, set);
220 X509_NAME_ENTRY_free(ne);
221 return ret;
222 }
223
X509_NAME_add_entry_by_txt(X509_NAME * name,const char * field,int type,const unsigned char * bytes,ossl_ssize_t len,int loc,int set)224 int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type,
225 const unsigned char *bytes, ossl_ssize_t len,
226 int loc, int set) {
227 X509_NAME_ENTRY *ne =
228 X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len);
229 if (!ne) {
230 return 0;
231 }
232 int ret = X509_NAME_add_entry(name, ne, loc, set);
233 X509_NAME_ENTRY_free(ne);
234 return ret;
235 }
236
237 // if set is -1, append to previous set, 0 'a new one', and 1, prepend to the
238 // guy we are about to stomp on.
X509_NAME_add_entry(X509_NAME * name,const X509_NAME_ENTRY * entry,int loc,int set)239 int X509_NAME_add_entry(X509_NAME *name, const X509_NAME_ENTRY *entry, int loc,
240 int set) {
241 X509_NAME_ENTRY *new_name = NULL;
242 int i, inc;
243 STACK_OF(X509_NAME_ENTRY) *sk;
244
245 if (name == NULL) {
246 return 0;
247 }
248 sk = name->entries;
249 int n = (int)sk_X509_NAME_ENTRY_num(sk);
250 if (loc > n) {
251 loc = n;
252 } else if (loc < 0) {
253 loc = n;
254 }
255
256 inc = (set == 0);
257 name->modified = 1;
258
259 if (set == -1) {
260 if (loc == 0) {
261 set = 0;
262 inc = 1;
263 } else {
264 set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set;
265 }
266 } else { // if (set >= 0)
267
268 if (loc >= n) {
269 if (loc != 0) {
270 set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set + 1;
271 } else {
272 set = 0;
273 }
274 } else {
275 set = sk_X509_NAME_ENTRY_value(sk, loc)->set;
276 }
277 }
278
279 if ((new_name = X509_NAME_ENTRY_dup(entry)) == NULL) {
280 goto err;
281 }
282 new_name->set = set;
283 if (!sk_X509_NAME_ENTRY_insert(sk, new_name, loc)) {
284 goto err;
285 }
286 if (inc) {
287 n = (int)sk_X509_NAME_ENTRY_num(sk);
288 for (i = loc + 1; i < n; i++) {
289 sk_X509_NAME_ENTRY_value(sk, i)->set += 1;
290 }
291 }
292 return 1;
293 err:
294 if (new_name != NULL) {
295 X509_NAME_ENTRY_free(new_name);
296 }
297 return 0;
298 }
299
X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY ** ne,const char * field,int type,const unsigned char * bytes,ossl_ssize_t len)300 X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
301 const char *field, int type,
302 const unsigned char *bytes,
303 ossl_ssize_t len) {
304 ASN1_OBJECT *obj;
305 X509_NAME_ENTRY *nentry;
306
307 obj = OBJ_txt2obj(field, 0);
308 if (obj == NULL) {
309 OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_NAME);
310 ERR_add_error_data(2, "name=", field);
311 return NULL;
312 }
313 nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
314 ASN1_OBJECT_free(obj);
315 return nentry;
316 }
317
X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY ** ne,int nid,int type,const unsigned char * bytes,ossl_ssize_t len)318 X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
319 int type,
320 const unsigned char *bytes,
321 ossl_ssize_t len) {
322 const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
323 if (obj == NULL) {
324 OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID);
325 return NULL;
326 }
327 return X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
328 }
329
X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY ** ne,const ASN1_OBJECT * obj,int type,const unsigned char * bytes,ossl_ssize_t len)330 X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
331 const ASN1_OBJECT *obj, int type,
332 const unsigned char *bytes,
333 ossl_ssize_t len) {
334 X509_NAME_ENTRY *ret;
335
336 if ((ne == NULL) || (*ne == NULL)) {
337 if ((ret = X509_NAME_ENTRY_new()) == NULL) {
338 return NULL;
339 }
340 } else {
341 ret = *ne;
342 }
343
344 if (!X509_NAME_ENTRY_set_object(ret, obj)) {
345 goto err;
346 }
347 if (!X509_NAME_ENTRY_set_data(ret, type, bytes, len)) {
348 goto err;
349 }
350
351 if ((ne != NULL) && (*ne == NULL)) {
352 *ne = ret;
353 }
354 return ret;
355 err:
356 if ((ne == NULL) || (ret != *ne)) {
357 X509_NAME_ENTRY_free(ret);
358 }
359 return NULL;
360 }
361
X509_NAME_ENTRY_set_object(X509_NAME_ENTRY * ne,const ASN1_OBJECT * obj)362 int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, const ASN1_OBJECT *obj) {
363 if ((ne == NULL) || (obj == NULL)) {
364 OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER);
365 return 0;
366 }
367 ASN1_OBJECT_free(ne->object);
368 ne->object = OBJ_dup(obj);
369 return ((ne->object == NULL) ? 0 : 1);
370 }
371
X509_NAME_ENTRY_set_data(X509_NAME_ENTRY * ne,int type,const unsigned char * bytes,ossl_ssize_t len)372 int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type,
373 const unsigned char *bytes, ossl_ssize_t len) {
374 if ((ne == NULL) || ((bytes == NULL) && (len != 0))) {
375 return 0;
376 }
377 if ((type > 0) && (type & MBSTRING_FLAG)) {
378 return ASN1_STRING_set_by_NID(&ne->value, bytes, len, type,
379 OBJ_obj2nid(ne->object))
380 ? 1
381 : 0;
382 }
383 if (len < 0) {
384 len = strlen((const char *)bytes);
385 }
386 if (!ASN1_STRING_set(ne->value, bytes, len)) {
387 return 0;
388 }
389 if (type != V_ASN1_UNDEF) {
390 ne->value->type = type;
391 }
392 return 1;
393 }
394
X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY * ne)395 ASN1_OBJECT *X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY *ne) {
396 if (ne == NULL) {
397 return NULL;
398 }
399 return ne->object;
400 }
401
X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY * ne)402 ASN1_STRING *X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne) {
403 if (ne == NULL) {
404 return NULL;
405 }
406 return ne->value;
407 }
408