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