os/ossrv/ssl/libcrypto/src/crypto/x509v3/v3_lib.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /* v3_lib.c */
     2 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
     3  * project 1999.
     4  */
     5 /* ====================================================================
     6  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
     7  *
     8  * Redistribution and use in source and binary forms, with or without
     9  * modification, are permitted provided that the following conditions
    10  * are met:
    11  *
    12  * 1. Redistributions of source code must retain the above copyright
    13  *    notice, this list of conditions and the following disclaimer. 
    14  *
    15  * 2. Redistributions in binary form must reproduce the above copyright
    16  *    notice, this list of conditions and the following disclaimer in
    17  *    the documentation and/or other materials provided with the
    18  *    distribution.
    19  *
    20  * 3. All advertising materials mentioning features or use of this
    21  *    software must display the following acknowledgment:
    22  *    "This product includes software developed by the OpenSSL Project
    23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
    24  *
    25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
    26  *    endorse or promote products derived from this software without
    27  *    prior written permission. For written permission, please contact
    28  *    licensing@OpenSSL.org.
    29  *
    30  * 5. Products derived from this software may not be called "OpenSSL"
    31  *    nor may "OpenSSL" appear in their names without prior written
    32  *    permission of the OpenSSL Project.
    33  *
    34  * 6. Redistributions of any form whatsoever must retain the following
    35  *    acknowledgment:
    36  *    "This product includes software developed by the OpenSSL Project
    37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
    38  *
    39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
    40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
    43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
    48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
    50  * OF THE POSSIBILITY OF SUCH DAMAGE.
    51  * ====================================================================
    52  *
    53  * This product includes cryptographic software written by Eric Young
    54  * (eay@cryptsoft.com).  This product includes software written by Tim
    55  * Hudson (tjh@cryptsoft.com).
    56  *
    57  */
    58  /*
    59  © Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
    60  */
    61 
    62 /* X509 v3 extension utilities */
    63 
    64 #include <stdio.h>
    65 #include "cryptlib.h"
    66 #include <openssl/conf.h>
    67 #include <openssl/x509v3.h>
    68 #if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__)))
    69 #include "libcrypto_wsd_macros.h"
    70 #include "libcrypto_wsd.h"
    71 #endif
    72 
    73 #include "ext_dat.h"
    74 
    75 #ifndef EMULATOR
    76 static STACK_OF(X509V3_EXT_METHOD) *ext_list = NULL;
    77 #else
    78 GET_STATIC_VAR_FROM_TLS(ext_list,v3_lib,STACK_OF(X509V3_EXT_METHOD) *)
    79 #define ext_list (*GET_WSD_VAR_NAME(ext_list,v3_lib, s)())
    80 #endif
    81 
    82 static int ext_cmp(const X509V3_EXT_METHOD * const *a,
    83 		const X509V3_EXT_METHOD * const *b);
    84 static void ext_list_free(X509V3_EXT_METHOD *ext);
    85 
    86 EXPORT_C int X509V3_EXT_add(X509V3_EXT_METHOD *ext)
    87 {
    88 	if(!ext_list && !(ext_list = sk_X509V3_EXT_METHOD_new(ext_cmp))) {
    89 		X509V3err(X509V3_F_X509V3_EXT_ADD,ERR_R_MALLOC_FAILURE);
    90 		return 0;
    91 	}
    92 	if(!sk_X509V3_EXT_METHOD_push(ext_list, ext)) {
    93 		X509V3err(X509V3_F_X509V3_EXT_ADD,ERR_R_MALLOC_FAILURE);
    94 		return 0;
    95 	}
    96 	return 1;
    97 }
    98 
    99 static int ext_cmp(const X509V3_EXT_METHOD * const *a,
   100 		const X509V3_EXT_METHOD * const *b)
   101 {
   102 	return ((*a)->ext_nid - (*b)->ext_nid);
   103 }
   104 
   105 EXPORT_C X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid)
   106 {
   107 	X509V3_EXT_METHOD tmp, *t = &tmp, **ret;
   108 	int idx;
   109 	if(nid < 0) return NULL;
   110 	tmp.ext_nid = nid;
   111 	ret = (X509V3_EXT_METHOD **) OBJ_bsearch((char *)&t,
   112 			(char *)standard_exts, STANDARD_EXTENSION_COUNT,
   113 			sizeof(X509V3_EXT_METHOD *), (int (*)(const void *, const void *))ext_cmp);
   114 	if(ret) return *ret;
   115 	if(!ext_list) return NULL;
   116 	idx = sk_X509V3_EXT_METHOD_find(ext_list, &tmp);
   117 	if(idx == -1) return NULL;
   118 	return sk_X509V3_EXT_METHOD_value(ext_list, idx);
   119 }
   120 
   121 EXPORT_C X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext)
   122 {
   123 	int nid;
   124 	if((nid = OBJ_obj2nid(ext->object)) == NID_undef) return NULL;
   125 	return X509V3_EXT_get_nid(nid);
   126 }
   127 
   128 
   129 EXPORT_C int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist)
   130 {
   131 	for(;extlist->ext_nid!=-1;extlist++) 
   132 			if(!X509V3_EXT_add(extlist)) return 0;
   133 	return 1;
   134 }
   135 
   136 EXPORT_C int X509V3_EXT_add_alias(int nid_to, int nid_from)
   137 {
   138 	X509V3_EXT_METHOD *ext, *tmpext;
   139 	if(!(ext = X509V3_EXT_get_nid(nid_from))) {
   140 		X509V3err(X509V3_F_X509V3_EXT_ADD_ALIAS,X509V3_R_EXTENSION_NOT_FOUND);
   141 		return 0;
   142 	}
   143 	if(!(tmpext = (X509V3_EXT_METHOD *)OPENSSL_malloc(sizeof(X509V3_EXT_METHOD)))) {
   144 		X509V3err(X509V3_F_X509V3_EXT_ADD_ALIAS,ERR_R_MALLOC_FAILURE);
   145 		return 0;
   146 	}
   147 	*tmpext = *ext;
   148 	tmpext->ext_nid = nid_to;
   149 	tmpext->ext_flags |= X509V3_EXT_DYNAMIC;
   150 	return X509V3_EXT_add(tmpext);
   151 }
   152 
   153 EXPORT_C void X509V3_EXT_cleanup(void)
   154 {
   155 	sk_X509V3_EXT_METHOD_pop_free(ext_list, ext_list_free);
   156 	ext_list = NULL;
   157 }
   158 
   159 static void ext_list_free(X509V3_EXT_METHOD *ext)
   160 {
   161 	if(ext->ext_flags & X509V3_EXT_DYNAMIC) OPENSSL_free(ext);
   162 }
   163 
   164 /* Legacy function: we don't need to add standard extensions
   165  * any more because they are now kept in ext_dat.h.
   166  */
   167 
   168 EXPORT_C int X509V3_add_standard_extensions(void)
   169 {
   170 	return 1;
   171 }
   172 
   173 /* Return an extension internal structure */
   174 
   175 EXPORT_C void *X509V3_EXT_d2i(X509_EXTENSION *ext)
   176 {
   177 	X509V3_EXT_METHOD *method;
   178 	const unsigned char *p;
   179 
   180 	if(!(method = X509V3_EXT_get(ext))) return NULL;
   181 	p = ext->value->data;
   182 	if(method->it) return ASN1_item_d2i(NULL, &p, ext->value->length, ASN1_ITEM_ptr(method->it));
   183 	return method->d2i(NULL, &p, ext->value->length);
   184 }
   185 
   186 /* Get critical flag and decoded version of extension from a NID.
   187  * The "idx" variable returns the last found extension and can
   188  * be used to retrieve multiple extensions of the same NID.
   189  * However multiple extensions with the same NID is usually
   190  * due to a badly encoded certificate so if idx is NULL we
   191  * choke if multiple extensions exist.
   192  * The "crit" variable is set to the critical value.
   193  * The return value is the decoded extension or NULL on
   194  * error. The actual error can have several different causes,
   195  * the value of *crit reflects the cause:
   196  * >= 0, extension found but not decoded (reflects critical value).
   197  * -1 extension not found.
   198  * -2 extension occurs more than once.
   199  */
   200 
   201 EXPORT_C void *X509V3_get_d2i(STACK_OF(X509_EXTENSION) *x, int nid, int *crit, int *idx)
   202 {
   203 	int lastpos, i;
   204 	X509_EXTENSION *ex, *found_ex = NULL;
   205 	if(!x) {
   206 		if(idx) *idx = -1;
   207 		if(crit) *crit = -1;
   208 		return NULL;
   209 	}
   210 	if(idx) lastpos = *idx + 1;
   211 	else lastpos = 0;
   212 	if(lastpos < 0) lastpos = 0;
   213 	for(i = lastpos; i < sk_X509_EXTENSION_num(x); i++)
   214 	{
   215 		ex = sk_X509_EXTENSION_value(x, i);
   216 		if(OBJ_obj2nid(ex->object) == nid) {
   217 			if(idx) {
   218 				*idx = i;
   219 				found_ex = ex;
   220 				break;
   221 			} else if(found_ex) {
   222 				/* Found more than one */
   223 				if(crit) *crit = -2;
   224 				return NULL;
   225 			}
   226 			found_ex = ex;
   227 		}
   228 	}
   229 	if(found_ex) {
   230 		/* Found it */
   231 		if(crit) *crit = X509_EXTENSION_get_critical(found_ex);
   232 		return X509V3_EXT_d2i(found_ex);
   233 	}
   234 
   235 	/* Extension not found */
   236 	if(idx) *idx = -1;
   237 	if(crit) *crit = -1;
   238 	return NULL;
   239 }
   240 
   241 /* This function is a general extension append, replace and delete utility.
   242  * The precise operation is governed by the 'flags' value. The 'crit' and
   243  * 'value' arguments (if relevant) are the extensions internal structure.
   244  */
   245 
   246 EXPORT_C int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value,
   247 					int crit, unsigned long flags)
   248 {
   249 	int extidx = -1;
   250 	int errcode;
   251 	X509_EXTENSION *ext, *extmp;
   252 	unsigned long ext_op = flags & X509V3_ADD_OP_MASK;
   253 
   254 	/* If appending we don't care if it exists, otherwise
   255 	 * look for existing extension.
   256 	 */
   257 	if(ext_op != X509V3_ADD_APPEND)
   258 		extidx = X509v3_get_ext_by_NID(*x, nid, -1);
   259 
   260 	/* See if extension exists */
   261 	if(extidx >= 0) {
   262 		/* If keep existing, nothing to do */
   263 		if(ext_op == X509V3_ADD_KEEP_EXISTING)
   264 			return 1;
   265 		/* If default then its an error */
   266 		if(ext_op == X509V3_ADD_DEFAULT) {
   267 			errcode = X509V3_R_EXTENSION_EXISTS;
   268 			goto err;
   269 		}
   270 		/* If delete, just delete it */
   271 		if(ext_op == X509V3_ADD_DELETE) {
   272 			if(!sk_X509_EXTENSION_delete(*x, extidx)) return -1;
   273 			return 1;
   274 		}
   275 	} else {
   276 		/* If replace existing or delete, error since 
   277 		 * extension must exist
   278 		 */
   279 		if((ext_op == X509V3_ADD_REPLACE_EXISTING) ||
   280 		   (ext_op == X509V3_ADD_DELETE)) {
   281 			errcode = X509V3_R_EXTENSION_NOT_FOUND;
   282 			goto err;
   283 		}
   284 	}
   285 
   286 	/* If we get this far then we have to create an extension:
   287 	 * could have some flags for alternative encoding schemes...
   288 	 */
   289 
   290 	ext = X509V3_EXT_i2d(nid, crit, value);
   291 
   292 	if(!ext) {
   293 		X509V3err(X509V3_F_X509V3_ADD1_I2D, X509V3_R_ERROR_CREATING_EXTENSION);
   294 		return 0;
   295 	}
   296 
   297 	/* If extension exists replace it.. */
   298 	if(extidx >= 0) {
   299 		extmp = sk_X509_EXTENSION_value(*x, extidx);
   300 		X509_EXTENSION_free(extmp);
   301 		if(!sk_X509_EXTENSION_set(*x, extidx, ext)) return -1;
   302 		return 1;
   303 	}
   304 
   305 	if(!*x && !(*x = sk_X509_EXTENSION_new_null())) return -1;
   306 	if(!sk_X509_EXTENSION_push(*x, ext)) return -1;
   307 
   308 	return 1;
   309 
   310 	err:
   311 	if(!(flags & X509V3_ADD_SILENT))
   312 		X509V3err(X509V3_F_X509V3_ADD1_I2D, errcode);
   313 	return 0;
   314 }
   315 
   316 IMPLEMENT_STACK_OF(X509V3_EXT_METHOD)