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