1 | /* crypto/x509/x509_att.c */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. |
4 | * |
5 | * This package is an SSL implementation written |
6 | * by Eric Young (eay@cryptsoft.com). |
7 | * The implementation was written so as to conform with Netscapes SSL. |
8 | * |
9 | * This library is free for commercial and non-commercial use as long as |
10 | * the following conditions are aheared to. The following conditions |
11 | * apply to all code found in this distribution, be it the RC4, RSA, |
12 | * lhash, DES, etc., code; not just the SSL code. The SSL documentation |
13 | * included with this distribution is covered by the same copyright terms |
14 | * except that the holder is Tim Hudson (tjh@cryptsoft.com). |
15 | * |
16 | * Copyright remains Eric Young's, and as such any Copyright notices in |
17 | * the code are not to be removed. |
18 | * If this package is used in a product, Eric Young should be given attribution |
19 | * as the author of the parts of the library used. |
20 | * This can be in the form of a textual message at program startup or |
21 | * in documentation (online or textual) provided with the package. |
22 | * |
23 | * Redistribution and use in source and binary forms, with or without |
24 | * modification, are permitted provided that the following conditions |
25 | * are met: |
26 | * 1. Redistributions of source code must retain the copyright |
27 | * notice, this list of conditions and the following disclaimer. |
28 | * 2. Redistributions in binary form must reproduce the above copyright |
29 | * notice, this list of conditions and the following disclaimer in the |
30 | * documentation and/or other materials provided with the distribution. |
31 | * 3. All advertising materials mentioning features or use of this software |
32 | * must display the following acknowledgement: |
33 | * "This product includes cryptographic software written by |
34 | * Eric Young (eay@cryptsoft.com)" |
35 | * The word 'cryptographic' can be left out if the rouines from the library |
36 | * being used are not cryptographic related :-). |
37 | * 4. If you include any Windows specific code (or a derivative thereof) from |
38 | * the apps directory (application code) you must include an acknowledgement: |
39 | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
40 | * |
41 | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
42 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
43 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
44 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
45 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
46 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
47 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
48 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
49 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
50 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
51 | * SUCH DAMAGE. |
52 | * |
53 | * The licence and distribution terms for any publically available version or |
54 | * derivative of this code cannot be changed. i.e. this code cannot simply be |
55 | * copied and put under another distribution licence |
56 | * [including the GNU Public Licence.] */ |
57 | |
58 | #include <openssl/asn1.h> |
59 | #include <openssl/err.h> |
60 | #include <openssl/evp.h> |
61 | #include <openssl/obj.h> |
62 | #include <openssl/stack.h> |
63 | #include <openssl/x509.h> |
64 | |
65 | int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x) |
66 | { |
67 | return sk_X509_ATTRIBUTE_num(x); |
68 | } |
69 | |
70 | int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid, |
71 | int lastpos) |
72 | { |
73 | const ASN1_OBJECT *obj; |
74 | |
75 | obj = OBJ_nid2obj(nid); |
76 | if (obj == NULL) |
77 | return (-2); |
78 | return (X509at_get_attr_by_OBJ(x, obj, lastpos)); |
79 | } |
80 | |
81 | int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, |
82 | const ASN1_OBJECT *obj, int lastpos) |
83 | { |
84 | int n; |
85 | X509_ATTRIBUTE *ex; |
86 | |
87 | if (sk == NULL) |
88 | return (-1); |
89 | lastpos++; |
90 | if (lastpos < 0) |
91 | lastpos = 0; |
92 | n = sk_X509_ATTRIBUTE_num(sk); |
93 | for (; lastpos < n; lastpos++) { |
94 | ex = sk_X509_ATTRIBUTE_value(sk, lastpos); |
95 | if (OBJ_cmp(ex->object, obj) == 0) |
96 | return (lastpos); |
97 | } |
98 | return (-1); |
99 | } |
100 | |
101 | X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc) |
102 | { |
103 | if (x == NULL || loc < 0 || sk_X509_ATTRIBUTE_num(x) <= (size_t)loc) |
104 | return NULL; |
105 | else |
106 | return sk_X509_ATTRIBUTE_value(x, loc); |
107 | } |
108 | |
109 | X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc) |
110 | { |
111 | X509_ATTRIBUTE *ret; |
112 | |
113 | if (x == NULL || loc < 0 || sk_X509_ATTRIBUTE_num(x) <= (size_t)loc) |
114 | return (NULL); |
115 | ret = sk_X509_ATTRIBUTE_delete(x, loc); |
116 | return (ret); |
117 | } |
118 | |
119 | STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x, |
120 | X509_ATTRIBUTE *attr) |
121 | { |
122 | X509_ATTRIBUTE *new_attr = NULL; |
123 | STACK_OF(X509_ATTRIBUTE) *sk = NULL; |
124 | |
125 | if (x == NULL) { |
126 | OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER); |
127 | goto err2; |
128 | } |
129 | |
130 | if (*x == NULL) { |
131 | if ((sk = sk_X509_ATTRIBUTE_new_null()) == NULL) |
132 | goto err; |
133 | } else |
134 | sk = *x; |
135 | |
136 | if ((new_attr = X509_ATTRIBUTE_dup(attr)) == NULL) |
137 | goto err2; |
138 | if (!sk_X509_ATTRIBUTE_push(sk, new_attr)) |
139 | goto err; |
140 | if (*x == NULL) |
141 | *x = sk; |
142 | return (sk); |
143 | err: |
144 | OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); |
145 | err2: |
146 | if (new_attr != NULL) |
147 | X509_ATTRIBUTE_free(new_attr); |
148 | if (sk != NULL) |
149 | sk_X509_ATTRIBUTE_free(sk); |
150 | return (NULL); |
151 | } |
152 | |
153 | STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) |
154 | **x, const ASN1_OBJECT *obj, |
155 | int type, |
156 | const unsigned char *bytes, |
157 | int len) |
158 | { |
159 | X509_ATTRIBUTE *attr; |
160 | STACK_OF(X509_ATTRIBUTE) *ret; |
161 | attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, type, bytes, len); |
162 | if (!attr) |
163 | return 0; |
164 | ret = X509at_add1_attr(x, attr); |
165 | X509_ATTRIBUTE_free(attr); |
166 | return ret; |
167 | } |
168 | |
169 | STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) |
170 | **x, int nid, int type, |
171 | const unsigned char *bytes, |
172 | int len) |
173 | { |
174 | X509_ATTRIBUTE *attr; |
175 | STACK_OF(X509_ATTRIBUTE) *ret; |
176 | attr = X509_ATTRIBUTE_create_by_NID(NULL, nid, type, bytes, len); |
177 | if (!attr) |
178 | return 0; |
179 | ret = X509at_add1_attr(x, attr); |
180 | X509_ATTRIBUTE_free(attr); |
181 | return ret; |
182 | } |
183 | |
184 | STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) |
185 | **x, const char *attrname, |
186 | int type, |
187 | const unsigned char *bytes, |
188 | int len) |
189 | { |
190 | X509_ATTRIBUTE *attr; |
191 | STACK_OF(X509_ATTRIBUTE) *ret; |
192 | attr = X509_ATTRIBUTE_create_by_txt(NULL, attrname, type, bytes, len); |
193 | if (!attr) |
194 | return 0; |
195 | ret = X509at_add1_attr(x, attr); |
196 | X509_ATTRIBUTE_free(attr); |
197 | return ret; |
198 | } |
199 | |
200 | void *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x, |
201 | ASN1_OBJECT *obj, int lastpos, int type) |
202 | { |
203 | int i; |
204 | X509_ATTRIBUTE *at; |
205 | i = X509at_get_attr_by_OBJ(x, obj, lastpos); |
206 | if (i == -1) |
207 | return NULL; |
208 | if ((lastpos <= -2) && (X509at_get_attr_by_OBJ(x, obj, i) != -1)) |
209 | return NULL; |
210 | at = X509at_get_attr(x, i); |
211 | if (lastpos <= -3 && (X509_ATTRIBUTE_count(at) != 1)) |
212 | return NULL; |
213 | return X509_ATTRIBUTE_get0_data(at, 0, type, NULL); |
214 | } |
215 | |
216 | X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid, |
217 | int atrtype, const void *data, |
218 | int len) |
219 | { |
220 | const ASN1_OBJECT *obj; |
221 | |
222 | obj = OBJ_nid2obj(nid); |
223 | if (obj == NULL) { |
224 | OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID); |
225 | return (NULL); |
226 | } |
227 | return X509_ATTRIBUTE_create_by_OBJ(attr, obj, atrtype, data, len); |
228 | } |
229 | |
230 | X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr, |
231 | const ASN1_OBJECT *obj, |
232 | int atrtype, const void *data, |
233 | int len) |
234 | { |
235 | X509_ATTRIBUTE *ret; |
236 | |
237 | if ((attr == NULL) || (*attr == NULL)) { |
238 | if ((ret = X509_ATTRIBUTE_new()) == NULL) { |
239 | OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); |
240 | return (NULL); |
241 | } |
242 | } else |
243 | ret = *attr; |
244 | |
245 | if (!X509_ATTRIBUTE_set1_object(ret, obj)) |
246 | goto err; |
247 | if (!X509_ATTRIBUTE_set1_data(ret, atrtype, data, len)) |
248 | goto err; |
249 | |
250 | if ((attr != NULL) && (*attr == NULL)) |
251 | *attr = ret; |
252 | return (ret); |
253 | err: |
254 | if ((attr == NULL) || (ret != *attr)) |
255 | X509_ATTRIBUTE_free(ret); |
256 | return (NULL); |
257 | } |
258 | |
259 | X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr, |
260 | const char *atrname, int type, |
261 | const unsigned char *bytes, |
262 | int len) |
263 | { |
264 | ASN1_OBJECT *obj; |
265 | X509_ATTRIBUTE *nattr; |
266 | |
267 | obj = OBJ_txt2obj(atrname, 0); |
268 | if (obj == NULL) { |
269 | OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_NAME); |
270 | ERR_add_error_data(2, "name=" , atrname); |
271 | return (NULL); |
272 | } |
273 | nattr = X509_ATTRIBUTE_create_by_OBJ(attr, obj, type, bytes, len); |
274 | ASN1_OBJECT_free(obj); |
275 | return nattr; |
276 | } |
277 | |
278 | int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj) |
279 | { |
280 | if ((attr == NULL) || (obj == NULL)) |
281 | return (0); |
282 | ASN1_OBJECT_free(attr->object); |
283 | attr->object = OBJ_dup(obj); |
284 | return attr->object != NULL; |
285 | } |
286 | |
287 | int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, |
288 | const void *data, int len) |
289 | { |
290 | ASN1_TYPE *ttmp = NULL; |
291 | ASN1_STRING *stmp = NULL; |
292 | int atype = 0; |
293 | if (!attr) |
294 | return 0; |
295 | if (attrtype & MBSTRING_FLAG) { |
296 | stmp = ASN1_STRING_set_by_NID(NULL, data, len, attrtype, |
297 | OBJ_obj2nid(attr->object)); |
298 | if (!stmp) { |
299 | OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB); |
300 | return 0; |
301 | } |
302 | atype = stmp->type; |
303 | } else if (len != -1) { |
304 | if (!(stmp = ASN1_STRING_type_new(attrtype))) |
305 | goto err; |
306 | if (!ASN1_STRING_set(stmp, data, len)) |
307 | goto err; |
308 | atype = attrtype; |
309 | } |
310 | if (!(attr->value.set = sk_ASN1_TYPE_new_null())) |
311 | goto err; |
312 | attr->single = 0; |
313 | /* |
314 | * This is a bit naughty because the attribute should really have at |
315 | * least one value but some types use and zero length SET and require |
316 | * this. |
317 | */ |
318 | if (attrtype == 0) { |
319 | ASN1_STRING_free(stmp); |
320 | return 1; |
321 | } |
322 | if (!(ttmp = ASN1_TYPE_new())) |
323 | goto err; |
324 | if ((len == -1) && !(attrtype & MBSTRING_FLAG)) { |
325 | if (!ASN1_TYPE_set1(ttmp, attrtype, data)) |
326 | goto err; |
327 | } else { |
328 | ASN1_TYPE_set(ttmp, atype, stmp); |
329 | stmp = NULL; |
330 | } |
331 | if (!sk_ASN1_TYPE_push(attr->value.set, ttmp)) |
332 | goto err; |
333 | return 1; |
334 | err: |
335 | OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); |
336 | ASN1_TYPE_free(ttmp); |
337 | ASN1_STRING_free(stmp); |
338 | return 0; |
339 | } |
340 | |
341 | int X509_ATTRIBUTE_count(X509_ATTRIBUTE *attr) |
342 | { |
343 | if (!attr->single) |
344 | return sk_ASN1_TYPE_num(attr->value.set); |
345 | if (attr->value.single) |
346 | return 1; |
347 | return 0; |
348 | } |
349 | |
350 | ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr) |
351 | { |
352 | if (attr == NULL) |
353 | return (NULL); |
354 | return (attr->object); |
355 | } |
356 | |
357 | void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, |
358 | int atrtype, void *data) |
359 | { |
360 | ASN1_TYPE *ttmp; |
361 | ttmp = X509_ATTRIBUTE_get0_type(attr, idx); |
362 | if (!ttmp) |
363 | return NULL; |
364 | if (atrtype != ASN1_TYPE_get(ttmp)) { |
365 | OPENSSL_PUT_ERROR(X509, X509_R_WRONG_TYPE); |
366 | return NULL; |
367 | } |
368 | return ttmp->value.ptr; |
369 | } |
370 | |
371 | ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx) |
372 | { |
373 | if (attr == NULL) |
374 | return (NULL); |
375 | if (idx >= X509_ATTRIBUTE_count(attr)) |
376 | return NULL; |
377 | if (!attr->single) |
378 | return sk_ASN1_TYPE_value(attr->value.set, idx); |
379 | else |
380 | return attr->value.single; |
381 | } |
382 | |