Home | History | Annotate | Download | only in x509
      1 /* crypto/x509/x509_att.c */
      2 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com)
      3  * All rights reserved.
      4  *
      5  * This package is an SSL implementation written
      6  * by Eric Young (eay (at) 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 (at) 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 (at) 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 (at) 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