159191Skris/* crypto/x509/x509_att.c */ 259191Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 359191Skris * All rights reserved. 459191Skris * 559191Skris * This package is an SSL implementation written 659191Skris * by Eric Young (eay@cryptsoft.com). 759191Skris * The implementation was written so as to conform with Netscapes SSL. 8296341Sdelphij * 959191Skris * This library is free for commercial and non-commercial use as long as 1059191Skris * the following conditions are aheared to. The following conditions 1159191Skris * apply to all code found in this distribution, be it the RC4, RSA, 1259191Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1359191Skris * included with this distribution is covered by the same copyright terms 1459191Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15296341Sdelphij * 1659191Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1759191Skris * the code are not to be removed. 1859191Skris * If this package is used in a product, Eric Young should be given attribution 1959191Skris * as the author of the parts of the library used. 2059191Skris * This can be in the form of a textual message at program startup or 2159191Skris * in documentation (online or textual) provided with the package. 22296341Sdelphij * 2359191Skris * Redistribution and use in source and binary forms, with or without 2459191Skris * modification, are permitted provided that the following conditions 2559191Skris * are met: 2659191Skris * 1. Redistributions of source code must retain the copyright 2759191Skris * notice, this list of conditions and the following disclaimer. 2859191Skris * 2. Redistributions in binary form must reproduce the above copyright 2959191Skris * notice, this list of conditions and the following disclaimer in the 3059191Skris * documentation and/or other materials provided with the distribution. 3159191Skris * 3. All advertising materials mentioning features or use of this software 3259191Skris * must display the following acknowledgement: 3359191Skris * "This product includes cryptographic software written by 3459191Skris * Eric Young (eay@cryptsoft.com)" 3559191Skris * The word 'cryptographic' can be left out if the rouines from the library 3659191Skris * being used are not cryptographic related :-). 37296341Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from 3859191Skris * the apps directory (application code) you must include an acknowledgement: 3959191Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40296341Sdelphij * 4159191Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4259191Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4359191Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4459191Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4559191Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4659191Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4759191Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4859191Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4959191Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5059191Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5159191Skris * SUCH DAMAGE. 52296341Sdelphij * 5359191Skris * The licence and distribution terms for any publically available version or 5459191Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5559191Skris * copied and put under another distribution licence 5659191Skris * [including the GNU Public Licence.] 5759191Skris */ 5859191Skris 5959191Skris#include <stdio.h> 6059191Skris#include <openssl/stack.h> 6159191Skris#include "cryptlib.h" 6259191Skris#include <openssl/asn1.h> 6359191Skris#include <openssl/objects.h> 6459191Skris#include <openssl/evp.h> 6559191Skris#include <openssl/x509.h> 6659191Skris#include <openssl/x509v3.h> 6759191Skris 6859191Skrisint X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x) 6959191Skris{ 70296341Sdelphij return sk_X509_ATTRIBUTE_num(x); 7159191Skris} 7259191Skris 7359191Skrisint X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid, 74296341Sdelphij int lastpos) 7559191Skris{ 76296341Sdelphij ASN1_OBJECT *obj; 7759191Skris 78296341Sdelphij obj = OBJ_nid2obj(nid); 79296341Sdelphij if (obj == NULL) 80296341Sdelphij return (-2); 81296341Sdelphij return (X509at_get_attr_by_OBJ(x, obj, lastpos)); 8259191Skris} 8359191Skris 84296341Sdelphijint X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, 85296341Sdelphij ASN1_OBJECT *obj, int lastpos) 8659191Skris{ 87296341Sdelphij int n; 88296341Sdelphij X509_ATTRIBUTE *ex; 8959191Skris 90296341Sdelphij if (sk == NULL) 91296341Sdelphij return (-1); 92296341Sdelphij lastpos++; 93296341Sdelphij if (lastpos < 0) 94296341Sdelphij lastpos = 0; 95296341Sdelphij n = sk_X509_ATTRIBUTE_num(sk); 96296341Sdelphij for (; lastpos < n; lastpos++) { 97296341Sdelphij ex = sk_X509_ATTRIBUTE_value(sk, lastpos); 98296341Sdelphij if (OBJ_cmp(ex->object, obj) == 0) 99296341Sdelphij return (lastpos); 100296341Sdelphij } 101296341Sdelphij return (-1); 10259191Skris} 10359191Skris 10459191SkrisX509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc) 10559191Skris{ 106296341Sdelphij if (x == NULL || sk_X509_ATTRIBUTE_num(x) <= loc || loc < 0) 107296341Sdelphij return NULL; 108296341Sdelphij else 109296341Sdelphij return sk_X509_ATTRIBUTE_value(x, loc); 11059191Skris} 11159191Skris 11259191SkrisX509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc) 11359191Skris{ 114296341Sdelphij X509_ATTRIBUTE *ret; 11559191Skris 116296341Sdelphij if (x == NULL || sk_X509_ATTRIBUTE_num(x) <= loc || loc < 0) 117296341Sdelphij return (NULL); 118296341Sdelphij ret = sk_X509_ATTRIBUTE_delete(x, loc); 119296341Sdelphij return (ret); 12059191Skris} 12159191Skris 12259191SkrisSTACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x, 123296341Sdelphij X509_ATTRIBUTE *attr) 12459191Skris{ 125296341Sdelphij X509_ATTRIBUTE *new_attr = NULL; 126296341Sdelphij STACK_OF(X509_ATTRIBUTE) *sk = NULL; 12759191Skris 128296341Sdelphij if (x == NULL) { 129296341Sdelphij X509err(X509_F_X509AT_ADD1_ATTR, ERR_R_PASSED_NULL_PARAMETER); 130296341Sdelphij goto err2; 131296341Sdelphij } 132160814Ssimon 133296341Sdelphij if (*x == NULL) { 134296341Sdelphij if ((sk = sk_X509_ATTRIBUTE_new_null()) == NULL) 135296341Sdelphij goto err; 136296341Sdelphij } else 137296341Sdelphij sk = *x; 13859191Skris 139296341Sdelphij if ((new_attr = X509_ATTRIBUTE_dup(attr)) == NULL) 140296341Sdelphij goto err2; 141296341Sdelphij if (!sk_X509_ATTRIBUTE_push(sk, new_attr)) 142296341Sdelphij goto err; 143296341Sdelphij if (*x == NULL) 144296341Sdelphij *x = sk; 145296341Sdelphij return (sk); 146296341Sdelphij err: 147296341Sdelphij X509err(X509_F_X509AT_ADD1_ATTR, ERR_R_MALLOC_FAILURE); 148296341Sdelphij err2: 149296341Sdelphij if (new_attr != NULL) 150296341Sdelphij X509_ATTRIBUTE_free(new_attr); 151296341Sdelphij if (sk != NULL) 152296341Sdelphij sk_X509_ATTRIBUTE_free(sk); 153296341Sdelphij return (NULL); 15459191Skris} 15559191Skris 156296341SdelphijSTACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) 157296341Sdelphij **x, const ASN1_OBJECT *obj, 158296341Sdelphij int type, 159296341Sdelphij const unsigned char *bytes, 160296341Sdelphij int len) 16159191Skris{ 162296341Sdelphij X509_ATTRIBUTE *attr; 163296341Sdelphij STACK_OF(X509_ATTRIBUTE) *ret; 164296341Sdelphij attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, type, bytes, len); 165296341Sdelphij if (!attr) 166296341Sdelphij return 0; 167296341Sdelphij ret = X509at_add1_attr(x, attr); 168296341Sdelphij X509_ATTRIBUTE_free(attr); 169296341Sdelphij return ret; 17059191Skris} 17159191Skris 172296341SdelphijSTACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) 173296341Sdelphij **x, int nid, int type, 174296341Sdelphij const unsigned char *bytes, 175296341Sdelphij int len) 17659191Skris{ 177296341Sdelphij X509_ATTRIBUTE *attr; 178296341Sdelphij STACK_OF(X509_ATTRIBUTE) *ret; 179296341Sdelphij attr = X509_ATTRIBUTE_create_by_NID(NULL, nid, type, bytes, len); 180296341Sdelphij if (!attr) 181296341Sdelphij return 0; 182296341Sdelphij ret = X509at_add1_attr(x, attr); 183296341Sdelphij X509_ATTRIBUTE_free(attr); 184296341Sdelphij return ret; 18559191Skris} 18659191Skris 187296341SdelphijSTACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) 188296341Sdelphij **x, const char *attrname, 189296341Sdelphij int type, 190296341Sdelphij const unsigned char *bytes, 191296341Sdelphij int len) 19259191Skris{ 193296341Sdelphij X509_ATTRIBUTE *attr; 194296341Sdelphij STACK_OF(X509_ATTRIBUTE) *ret; 195296341Sdelphij attr = X509_ATTRIBUTE_create_by_txt(NULL, attrname, type, bytes, len); 196296341Sdelphij if (!attr) 197296341Sdelphij return 0; 198296341Sdelphij ret = X509at_add1_attr(x, attr); 199296341Sdelphij X509_ATTRIBUTE_free(attr); 200296341Sdelphij return ret; 20159191Skris} 20259191Skris 203194206Ssimonvoid *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x, 204296341Sdelphij ASN1_OBJECT *obj, int lastpos, int type) 205194206Ssimon{ 206296341Sdelphij int i; 207296341Sdelphij X509_ATTRIBUTE *at; 208296341Sdelphij i = X509at_get_attr_by_OBJ(x, obj, lastpos); 209296341Sdelphij if (i == -1) 210296341Sdelphij return NULL; 211296341Sdelphij if ((lastpos <= -2) && (X509at_get_attr_by_OBJ(x, obj, i) != -1)) 212296341Sdelphij return NULL; 213296341Sdelphij at = X509at_get_attr(x, i); 214296341Sdelphij if (lastpos <= -3 && (X509_ATTRIBUTE_count(at) != 1)) 215296341Sdelphij return NULL; 216296341Sdelphij return X509_ATTRIBUTE_get0_data(at, 0, type, NULL); 217194206Ssimon} 218194206Ssimon 21959191SkrisX509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid, 220296341Sdelphij int atrtype, const void *data, 221296341Sdelphij int len) 22259191Skris{ 223296341Sdelphij ASN1_OBJECT *obj; 224296341Sdelphij X509_ATTRIBUTE *ret; 22559191Skris 226296341Sdelphij obj = OBJ_nid2obj(nid); 227296341Sdelphij if (obj == NULL) { 228296341Sdelphij X509err(X509_F_X509_ATTRIBUTE_CREATE_BY_NID, X509_R_UNKNOWN_NID); 229296341Sdelphij return (NULL); 230296341Sdelphij } 231296341Sdelphij ret = X509_ATTRIBUTE_create_by_OBJ(attr, obj, atrtype, data, len); 232296341Sdelphij if (ret == NULL) 233296341Sdelphij ASN1_OBJECT_free(obj); 234296341Sdelphij return (ret); 23559191Skris} 23659191Skris 23759191SkrisX509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr, 238296341Sdelphij const ASN1_OBJECT *obj, 239296341Sdelphij int atrtype, const void *data, 240296341Sdelphij int len) 24159191Skris{ 242296341Sdelphij X509_ATTRIBUTE *ret; 24359191Skris 244296341Sdelphij if ((attr == NULL) || (*attr == NULL)) { 245296341Sdelphij if ((ret = X509_ATTRIBUTE_new()) == NULL) { 246296341Sdelphij X509err(X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ, 247296341Sdelphij ERR_R_MALLOC_FAILURE); 248296341Sdelphij return (NULL); 249296341Sdelphij } 250296341Sdelphij } else 251296341Sdelphij ret = *attr; 25259191Skris 253296341Sdelphij if (!X509_ATTRIBUTE_set1_object(ret, obj)) 254296341Sdelphij goto err; 255296341Sdelphij if (!X509_ATTRIBUTE_set1_data(ret, atrtype, data, len)) 256296341Sdelphij goto err; 257194206Ssimon 258296341Sdelphij if ((attr != NULL) && (*attr == NULL)) 259296341Sdelphij *attr = ret; 260296341Sdelphij return (ret); 261296341Sdelphij err: 262296341Sdelphij if ((attr == NULL) || (ret != *attr)) 263296341Sdelphij X509_ATTRIBUTE_free(ret); 264296341Sdelphij return (NULL); 26559191Skris} 26659191Skris 26759191SkrisX509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr, 268296341Sdelphij const char *atrname, int type, 269296341Sdelphij const unsigned char *bytes, 270296341Sdelphij int len) 271296341Sdelphij{ 272296341Sdelphij ASN1_OBJECT *obj; 273296341Sdelphij X509_ATTRIBUTE *nattr; 27459191Skris 275296341Sdelphij obj = OBJ_txt2obj(atrname, 0); 276296341Sdelphij if (obj == NULL) { 277296341Sdelphij X509err(X509_F_X509_ATTRIBUTE_CREATE_BY_TXT, 278296341Sdelphij X509_R_INVALID_FIELD_NAME); 279296341Sdelphij ERR_add_error_data(2, "name=", atrname); 280296341Sdelphij return (NULL); 281296341Sdelphij } 282296341Sdelphij nattr = X509_ATTRIBUTE_create_by_OBJ(attr, obj, type, bytes, len); 283296341Sdelphij ASN1_OBJECT_free(obj); 284296341Sdelphij return nattr; 285296341Sdelphij} 28659191Skris 287109998Smarkmint X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj) 28859191Skris{ 289296341Sdelphij if ((attr == NULL) || (obj == NULL)) 290296341Sdelphij return (0); 291296341Sdelphij ASN1_OBJECT_free(attr->object); 292296341Sdelphij attr->object = OBJ_dup(obj); 293296341Sdelphij return (1); 29459191Skris} 29559191Skris 296296341Sdelphijint X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, 297296341Sdelphij const void *data, int len) 29859191Skris{ 299296341Sdelphij ASN1_TYPE *ttmp; 300296341Sdelphij ASN1_STRING *stmp = NULL; 301296341Sdelphij int atype = 0; 302296341Sdelphij if (!attr) 303296341Sdelphij return 0; 304296341Sdelphij if (attrtype & MBSTRING_FLAG) { 305296341Sdelphij stmp = ASN1_STRING_set_by_NID(NULL, data, len, attrtype, 306296341Sdelphij OBJ_obj2nid(attr->object)); 307296341Sdelphij if (!stmp) { 308296341Sdelphij X509err(X509_F_X509_ATTRIBUTE_SET1_DATA, ERR_R_ASN1_LIB); 309296341Sdelphij return 0; 310296341Sdelphij } 311296341Sdelphij atype = stmp->type; 312296341Sdelphij } else if (len != -1) { 313296341Sdelphij if (!(stmp = ASN1_STRING_type_new(attrtype))) 314296341Sdelphij goto err; 315296341Sdelphij if (!ASN1_STRING_set(stmp, data, len)) 316296341Sdelphij goto err; 317296341Sdelphij atype = attrtype; 318296341Sdelphij } 319296341Sdelphij if (!(attr->value.set = sk_ASN1_TYPE_new_null())) 320296341Sdelphij goto err; 321296341Sdelphij attr->single = 0; 322296341Sdelphij /* 323296341Sdelphij * This is a bit naughty because the attribute should really have at 324296341Sdelphij * least one value but some types use and zero length SET and require 325296341Sdelphij * this. 326296341Sdelphij */ 327296341Sdelphij if (attrtype == 0) 328296341Sdelphij return 1; 329296341Sdelphij if (!(ttmp = ASN1_TYPE_new())) 330296341Sdelphij goto err; 331296341Sdelphij if ((len == -1) && !(attrtype & MBSTRING_FLAG)) { 332296341Sdelphij if (!ASN1_TYPE_set1(ttmp, attrtype, data)) 333296341Sdelphij goto err; 334296341Sdelphij } else 335296341Sdelphij ASN1_TYPE_set(ttmp, atype, stmp); 336296341Sdelphij if (!sk_ASN1_TYPE_push(attr->value.set, ttmp)) 337296341Sdelphij goto err; 338296341Sdelphij return 1; 339296341Sdelphij err: 340296341Sdelphij X509err(X509_F_X509_ATTRIBUTE_SET1_DATA, ERR_R_MALLOC_FAILURE); 341296341Sdelphij return 0; 34259191Skris} 34359191Skris 34459191Skrisint X509_ATTRIBUTE_count(X509_ATTRIBUTE *attr) 34559191Skris{ 346296341Sdelphij if (!attr->single) 347296341Sdelphij return sk_ASN1_TYPE_num(attr->value.set); 348296341Sdelphij if (attr->value.single) 349296341Sdelphij return 1; 350296341Sdelphij return 0; 35159191Skris} 35259191Skris 35359191SkrisASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr) 35459191Skris{ 355296341Sdelphij if (attr == NULL) 356296341Sdelphij return (NULL); 357296341Sdelphij return (attr->object); 35859191Skris} 35959191Skris 36059191Skrisvoid *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, 361296341Sdelphij int atrtype, void *data) 36259191Skris{ 363296341Sdelphij ASN1_TYPE *ttmp; 364296341Sdelphij ttmp = X509_ATTRIBUTE_get0_type(attr, idx); 365296341Sdelphij if (!ttmp) 366296341Sdelphij return NULL; 367296341Sdelphij if (atrtype != ASN1_TYPE_get(ttmp)) { 368296341Sdelphij X509err(X509_F_X509_ATTRIBUTE_GET0_DATA, X509_R_WRONG_TYPE); 369296341Sdelphij return NULL; 370296341Sdelphij } 371296341Sdelphij return ttmp->value.ptr; 37259191Skris} 37359191Skris 37459191SkrisASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx) 37559191Skris{ 376296341Sdelphij if (attr == NULL) 377296341Sdelphij return (NULL); 378296341Sdelphij if (idx >= X509_ATTRIBUTE_count(attr)) 379296341Sdelphij return NULL; 380296341Sdelphij if (!attr->single) 381296341Sdelphij return sk_ASN1_TYPE_value(attr->value.set, idx); 382296341Sdelphij else 383296341Sdelphij return attr->value.single; 38459191Skris} 385