x509_att.c revision 296465
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
59#include <stdio.h>
60#include <openssl/stack.h>
61#include "cryptlib.h"
62#include <openssl/asn1.h>
63#include <openssl/objects.h>
64#include <openssl/evp.h>
65#include <openssl/x509.h>
66#include <openssl/x509v3.h>
67
68int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x)
69{
70    return sk_X509_ATTRIBUTE_num(x);
71}
72
73int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid,
74                           int lastpos)
75{
76    ASN1_OBJECT *obj;
77
78    obj = OBJ_nid2obj(nid);
79    if (obj == NULL)
80        return (-2);
81    return (X509at_get_attr_by_OBJ(x, obj, lastpos));
82}
83
84int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk,
85                           ASN1_OBJECT *obj, int lastpos)
86{
87    int n;
88    X509_ATTRIBUTE *ex;
89
90    if (sk == NULL)
91        return (-1);
92    lastpos++;
93    if (lastpos < 0)
94        lastpos = 0;
95    n = sk_X509_ATTRIBUTE_num(sk);
96    for (; lastpos < n; lastpos++) {
97        ex = sk_X509_ATTRIBUTE_value(sk, lastpos);
98        if (OBJ_cmp(ex->object, obj) == 0)
99            return (lastpos);
100    }
101    return (-1);
102}
103
104X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc)
105{
106    if (x == NULL || sk_X509_ATTRIBUTE_num(x) <= loc || loc < 0)
107        return NULL;
108    else
109        return sk_X509_ATTRIBUTE_value(x, loc);
110}
111
112X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc)
113{
114    X509_ATTRIBUTE *ret;
115
116    if (x == NULL || sk_X509_ATTRIBUTE_num(x) <= loc || loc < 0)
117        return (NULL);
118    ret = sk_X509_ATTRIBUTE_delete(x, loc);
119    return (ret);
120}
121
122STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x,
123                                           X509_ATTRIBUTE *attr)
124{
125    X509_ATTRIBUTE *new_attr = NULL;
126    STACK_OF(X509_ATTRIBUTE) *sk = NULL;
127
128    if (x == NULL) {
129        X509err(X509_F_X509AT_ADD1_ATTR, ERR_R_PASSED_NULL_PARAMETER);
130        goto err2;
131    }
132
133    if (*x == NULL) {
134        if ((sk = sk_X509_ATTRIBUTE_new_null()) == NULL)
135            goto err;
136    } else
137        sk = *x;
138
139    if ((new_attr = X509_ATTRIBUTE_dup(attr)) == NULL)
140        goto err2;
141    if (!sk_X509_ATTRIBUTE_push(sk, new_attr))
142        goto err;
143    if (*x == NULL)
144        *x = sk;
145    return (sk);
146 err:
147    X509err(X509_F_X509AT_ADD1_ATTR, ERR_R_MALLOC_FAILURE);
148 err2:
149    if (new_attr != NULL)
150        X509_ATTRIBUTE_free(new_attr);
151    if (sk != NULL)
152        sk_X509_ATTRIBUTE_free(sk);
153    return (NULL);
154}
155
156STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE)
157                                                  **x, const ASN1_OBJECT *obj,
158                                                  int type,
159                                                  const unsigned char *bytes,
160                                                  int len)
161{
162    X509_ATTRIBUTE *attr;
163    STACK_OF(X509_ATTRIBUTE) *ret;
164    attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, type, bytes, len);
165    if (!attr)
166        return 0;
167    ret = X509at_add1_attr(x, attr);
168    X509_ATTRIBUTE_free(attr);
169    return ret;
170}
171
172STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE)
173                                                  **x, int nid, int type,
174                                                  const unsigned char *bytes,
175                                                  int len)
176{
177    X509_ATTRIBUTE *attr;
178    STACK_OF(X509_ATTRIBUTE) *ret;
179    attr = X509_ATTRIBUTE_create_by_NID(NULL, nid, type, bytes, len);
180    if (!attr)
181        return 0;
182    ret = X509at_add1_attr(x, attr);
183    X509_ATTRIBUTE_free(attr);
184    return ret;
185}
186
187STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE)
188                                                  **x, const char *attrname,
189                                                  int type,
190                                                  const unsigned char *bytes,
191                                                  int len)
192{
193    X509_ATTRIBUTE *attr;
194    STACK_OF(X509_ATTRIBUTE) *ret;
195    attr = X509_ATTRIBUTE_create_by_txt(NULL, attrname, type, bytes, len);
196    if (!attr)
197        return 0;
198    ret = X509at_add1_attr(x, attr);
199    X509_ATTRIBUTE_free(attr);
200    return ret;
201}
202
203void *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x,
204                              ASN1_OBJECT *obj, int lastpos, int type)
205{
206    int i;
207    X509_ATTRIBUTE *at;
208    i = X509at_get_attr_by_OBJ(x, obj, lastpos);
209    if (i == -1)
210        return NULL;
211    if ((lastpos <= -2) && (X509at_get_attr_by_OBJ(x, obj, i) != -1))
212        return NULL;
213    at = X509at_get_attr(x, i);
214    if (lastpos <= -3 && (X509_ATTRIBUTE_count(at) != 1))
215        return NULL;
216    return X509_ATTRIBUTE_get0_data(at, 0, type, NULL);
217}
218
219X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid,
220                                             int atrtype, const void *data,
221                                             int len)
222{
223    ASN1_OBJECT *obj;
224    X509_ATTRIBUTE *ret;
225
226    obj = OBJ_nid2obj(nid);
227    if (obj == NULL) {
228        X509err(X509_F_X509_ATTRIBUTE_CREATE_BY_NID, X509_R_UNKNOWN_NID);
229        return (NULL);
230    }
231    ret = X509_ATTRIBUTE_create_by_OBJ(attr, obj, atrtype, data, len);
232    if (ret == NULL)
233        ASN1_OBJECT_free(obj);
234    return (ret);
235}
236
237X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr,
238                                             const ASN1_OBJECT *obj,
239                                             int atrtype, const void *data,
240                                             int len)
241{
242    X509_ATTRIBUTE *ret;
243
244    if ((attr == NULL) || (*attr == NULL)) {
245        if ((ret = X509_ATTRIBUTE_new()) == NULL) {
246            X509err(X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ,
247                    ERR_R_MALLOC_FAILURE);
248            return (NULL);
249        }
250    } else
251        ret = *attr;
252
253    if (!X509_ATTRIBUTE_set1_object(ret, obj))
254        goto err;
255    if (!X509_ATTRIBUTE_set1_data(ret, atrtype, data, len))
256        goto err;
257
258    if ((attr != NULL) && (*attr == NULL))
259        *attr = ret;
260    return (ret);
261 err:
262    if ((attr == NULL) || (ret != *attr))
263        X509_ATTRIBUTE_free(ret);
264    return (NULL);
265}
266
267X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr,
268                                             const char *atrname, int type,
269                                             const unsigned char *bytes,
270                                             int len)
271{
272    ASN1_OBJECT *obj;
273    X509_ATTRIBUTE *nattr;
274
275    obj = OBJ_txt2obj(atrname, 0);
276    if (obj == NULL) {
277        X509err(X509_F_X509_ATTRIBUTE_CREATE_BY_TXT,
278                X509_R_INVALID_FIELD_NAME);
279        ERR_add_error_data(2, "name=", atrname);
280        return (NULL);
281    }
282    nattr = X509_ATTRIBUTE_create_by_OBJ(attr, obj, type, bytes, len);
283    ASN1_OBJECT_free(obj);
284    return nattr;
285}
286
287int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj)
288{
289    if ((attr == NULL) || (obj == NULL))
290        return (0);
291    ASN1_OBJECT_free(attr->object);
292    attr->object = OBJ_dup(obj);
293    return (1);
294}
295
296int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype,
297                             const void *data, int len)
298{
299    ASN1_TYPE *ttmp;
300    ASN1_STRING *stmp = NULL;
301    int atype = 0;
302    if (!attr)
303        return 0;
304    if (attrtype & MBSTRING_FLAG) {
305        stmp = ASN1_STRING_set_by_NID(NULL, data, len, attrtype,
306                                      OBJ_obj2nid(attr->object));
307        if (!stmp) {
308            X509err(X509_F_X509_ATTRIBUTE_SET1_DATA, ERR_R_ASN1_LIB);
309            return 0;
310        }
311        atype = stmp->type;
312    } else if (len != -1) {
313        if (!(stmp = ASN1_STRING_type_new(attrtype)))
314            goto err;
315        if (!ASN1_STRING_set(stmp, data, len))
316            goto err;
317        atype = attrtype;
318    }
319    if (!(attr->value.set = sk_ASN1_TYPE_new_null()))
320        goto err;
321    attr->single = 0;
322    /*
323     * This is a bit naughty because the attribute should really have at
324     * least one value but some types use and zero length SET and require
325     * this.
326     */
327    if (attrtype == 0)
328        return 1;
329    if (!(ttmp = ASN1_TYPE_new()))
330        goto err;
331    if ((len == -1) && !(attrtype & MBSTRING_FLAG)) {
332        if (!ASN1_TYPE_set1(ttmp, attrtype, data))
333            goto err;
334    } else
335        ASN1_TYPE_set(ttmp, atype, stmp);
336    if (!sk_ASN1_TYPE_push(attr->value.set, ttmp))
337        goto err;
338    return 1;
339 err:
340    X509err(X509_F_X509_ATTRIBUTE_SET1_DATA, ERR_R_MALLOC_FAILURE);
341    return 0;
342}
343
344int X509_ATTRIBUTE_count(X509_ATTRIBUTE *attr)
345{
346    if (!attr->single)
347        return sk_ASN1_TYPE_num(attr->value.set);
348    if (attr->value.single)
349        return 1;
350    return 0;
351}
352
353ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr)
354{
355    if (attr == NULL)
356        return (NULL);
357    return (attr->object);
358}
359
360void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx,
361                               int atrtype, void *data)
362{
363    ASN1_TYPE *ttmp;
364    ttmp = X509_ATTRIBUTE_get0_type(attr, idx);
365    if (!ttmp)
366        return NULL;
367    if (atrtype != ASN1_TYPE_get(ttmp)) {
368        X509err(X509_F_X509_ATTRIBUTE_GET0_DATA, X509_R_WRONG_TYPE);
369        return NULL;
370    }
371    return ttmp->value.ptr;
372}
373
374ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx)
375{
376    if (attr == NULL)
377        return (NULL);
378    if (idx >= X509_ATTRIBUTE_count(attr))
379        return NULL;
380    if (!attr->single)
381        return sk_ASN1_TYPE_value(attr->value.set, idx);
382    else
383        return attr->value.single;
384}
385