1*de0e0e4dSAntonio Huete Jimenez /* $OpenBSD: x509_lib.c,v 1.4 2022/07/24 21:41:29 tb Exp $ */
28edacedfSDaniel Fojt /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
38edacedfSDaniel Fojt  * project 1999.
48edacedfSDaniel Fojt  */
58edacedfSDaniel Fojt /* ====================================================================
68edacedfSDaniel Fojt  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
78edacedfSDaniel Fojt  *
88edacedfSDaniel Fojt  * Redistribution and use in source and binary forms, with or without
98edacedfSDaniel Fojt  * modification, are permitted provided that the following conditions
108edacedfSDaniel Fojt  * are met:
118edacedfSDaniel Fojt  *
128edacedfSDaniel Fojt  * 1. Redistributions of source code must retain the above copyright
138edacedfSDaniel Fojt  *    notice, this list of conditions and the following disclaimer.
148edacedfSDaniel Fojt  *
158edacedfSDaniel Fojt  * 2. Redistributions in binary form must reproduce the above copyright
168edacedfSDaniel Fojt  *    notice, this list of conditions and the following disclaimer in
178edacedfSDaniel Fojt  *    the documentation and/or other materials provided with the
188edacedfSDaniel Fojt  *    distribution.
198edacedfSDaniel Fojt  *
208edacedfSDaniel Fojt  * 3. All advertising materials mentioning features or use of this
218edacedfSDaniel Fojt  *    software must display the following acknowledgment:
228edacedfSDaniel Fojt  *    "This product includes software developed by the OpenSSL Project
238edacedfSDaniel Fojt  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
248edacedfSDaniel Fojt  *
258edacedfSDaniel Fojt  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
268edacedfSDaniel Fojt  *    endorse or promote products derived from this software without
278edacedfSDaniel Fojt  *    prior written permission. For written permission, please contact
288edacedfSDaniel Fojt  *    licensing@OpenSSL.org.
298edacedfSDaniel Fojt  *
308edacedfSDaniel Fojt  * 5. Products derived from this software may not be called "OpenSSL"
318edacedfSDaniel Fojt  *    nor may "OpenSSL" appear in their names without prior written
328edacedfSDaniel Fojt  *    permission of the OpenSSL Project.
338edacedfSDaniel Fojt  *
348edacedfSDaniel Fojt  * 6. Redistributions of any form whatsoever must retain the following
358edacedfSDaniel Fojt  *    acknowledgment:
368edacedfSDaniel Fojt  *    "This product includes software developed by the OpenSSL Project
378edacedfSDaniel Fojt  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
388edacedfSDaniel Fojt  *
398edacedfSDaniel Fojt  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
408edacedfSDaniel Fojt  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
418edacedfSDaniel Fojt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
428edacedfSDaniel Fojt  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
438edacedfSDaniel Fojt  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
448edacedfSDaniel Fojt  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
458edacedfSDaniel Fojt  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
468edacedfSDaniel Fojt  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
478edacedfSDaniel Fojt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
488edacedfSDaniel Fojt  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
498edacedfSDaniel Fojt  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
508edacedfSDaniel Fojt  * OF THE POSSIBILITY OF SUCH DAMAGE.
518edacedfSDaniel Fojt  * ====================================================================
528edacedfSDaniel Fojt  *
538edacedfSDaniel Fojt  * This product includes cryptographic software written by Eric Young
548edacedfSDaniel Fojt  * (eay@cryptsoft.com).  This product includes software written by Tim
558edacedfSDaniel Fojt  * Hudson (tjh@cryptsoft.com).
568edacedfSDaniel Fojt  *
578edacedfSDaniel Fojt  */
588edacedfSDaniel Fojt /* X509 v3 extension utilities */
598edacedfSDaniel Fojt 
608edacedfSDaniel Fojt #include <stdio.h>
618edacedfSDaniel Fojt 
628edacedfSDaniel Fojt #include <openssl/conf.h>
638edacedfSDaniel Fojt #include <openssl/err.h>
648edacedfSDaniel Fojt #include <openssl/x509v3.h>
658edacedfSDaniel Fojt 
668edacedfSDaniel Fojt #include "ext_dat.h"
67*de0e0e4dSAntonio Huete Jimenez #include "x509_lcl.h"
688edacedfSDaniel Fojt 
698edacedfSDaniel Fojt static STACK_OF(X509V3_EXT_METHOD) *ext_list = NULL;
708edacedfSDaniel Fojt 
718edacedfSDaniel Fojt static int ext_cmp(const X509V3_EXT_METHOD * const *a,
728edacedfSDaniel Fojt     const X509V3_EXT_METHOD * const *b);
738edacedfSDaniel Fojt static void ext_list_free(X509V3_EXT_METHOD *ext);
748edacedfSDaniel Fojt 
758edacedfSDaniel Fojt int
X509V3_EXT_add(X509V3_EXT_METHOD * ext)768edacedfSDaniel Fojt X509V3_EXT_add(X509V3_EXT_METHOD *ext)
778edacedfSDaniel Fojt {
788edacedfSDaniel Fojt 	if (!ext_list && !(ext_list = sk_X509V3_EXT_METHOD_new(ext_cmp))) {
798edacedfSDaniel Fojt 		X509V3error(ERR_R_MALLOC_FAILURE);
808edacedfSDaniel Fojt 		return 0;
818edacedfSDaniel Fojt 	}
828edacedfSDaniel Fojt 	if (!sk_X509V3_EXT_METHOD_push(ext_list, ext)) {
838edacedfSDaniel Fojt 		X509V3error(ERR_R_MALLOC_FAILURE);
848edacedfSDaniel Fojt 		return 0;
858edacedfSDaniel Fojt 	}
868edacedfSDaniel Fojt 	return 1;
878edacedfSDaniel Fojt }
888edacedfSDaniel Fojt 
898edacedfSDaniel Fojt static int
ext_cmp(const X509V3_EXT_METHOD * const * a,const X509V3_EXT_METHOD * const * b)908edacedfSDaniel Fojt ext_cmp(const X509V3_EXT_METHOD * const *a, const X509V3_EXT_METHOD * const *b)
918edacedfSDaniel Fojt {
928edacedfSDaniel Fojt 	return ((*a)->ext_nid - (*b)->ext_nid);
938edacedfSDaniel Fojt }
948edacedfSDaniel Fojt 
958edacedfSDaniel Fojt static int ext_cmp_BSEARCH_CMP_FN(const void *, const void *);
968edacedfSDaniel Fojt static int ext_cmp(const X509V3_EXT_METHOD * const *, const X509V3_EXT_METHOD * const *);
978edacedfSDaniel Fojt static const X509V3_EXT_METHOD * *OBJ_bsearch_ext(const X509V3_EXT_METHOD * *key, const X509V3_EXT_METHOD * const *base, int num);
988edacedfSDaniel Fojt 
998edacedfSDaniel Fojt static int
ext_cmp_BSEARCH_CMP_FN(const void * a_,const void * b_)1008edacedfSDaniel Fojt ext_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_)
1018edacedfSDaniel Fojt {
1028edacedfSDaniel Fojt 	const X509V3_EXT_METHOD * const *a = a_;
1038edacedfSDaniel Fojt 	const X509V3_EXT_METHOD * const *b = b_;
1048edacedfSDaniel Fojt 	return ext_cmp(a, b);
1058edacedfSDaniel Fojt }
1068edacedfSDaniel Fojt 
1078edacedfSDaniel Fojt static const X509V3_EXT_METHOD **
OBJ_bsearch_ext(const X509V3_EXT_METHOD ** key,const X509V3_EXT_METHOD * const * base,int num)1088edacedfSDaniel Fojt OBJ_bsearch_ext(const X509V3_EXT_METHOD **key,
1098edacedfSDaniel Fojt     const X509V3_EXT_METHOD *const *base, int num)
1108edacedfSDaniel Fojt {
1118edacedfSDaniel Fojt 	return (const X509V3_EXT_METHOD **)OBJ_bsearch_(key, base, num,
1128edacedfSDaniel Fojt 	    sizeof(const X509V3_EXT_METHOD *), ext_cmp_BSEARCH_CMP_FN);
1138edacedfSDaniel Fojt }
1148edacedfSDaniel Fojt 
1158edacedfSDaniel Fojt const X509V3_EXT_METHOD *
X509V3_EXT_get_nid(int nid)1168edacedfSDaniel Fojt X509V3_EXT_get_nid(int nid)
1178edacedfSDaniel Fojt {
1188edacedfSDaniel Fojt 	X509V3_EXT_METHOD tmp;
1198edacedfSDaniel Fojt 	const X509V3_EXT_METHOD *t = &tmp, * const *ret;
1208edacedfSDaniel Fojt 	int idx;
1218edacedfSDaniel Fojt 
1228edacedfSDaniel Fojt 	if (nid < 0)
1238edacedfSDaniel Fojt 		return NULL;
1248edacedfSDaniel Fojt 	tmp.ext_nid = nid;
1258edacedfSDaniel Fojt 	ret = OBJ_bsearch_ext(&t, standard_exts, STANDARD_EXTENSION_COUNT);
1268edacedfSDaniel Fojt 	if (ret)
1278edacedfSDaniel Fojt 		return *ret;
1288edacedfSDaniel Fojt 	if (!ext_list)
1298edacedfSDaniel Fojt 		return NULL;
1308edacedfSDaniel Fojt 	idx = sk_X509V3_EXT_METHOD_find(ext_list, &tmp);
1318edacedfSDaniel Fojt 	if (idx == -1)
1328edacedfSDaniel Fojt 		return NULL;
1338edacedfSDaniel Fojt 	return sk_X509V3_EXT_METHOD_value(ext_list, idx);
1348edacedfSDaniel Fojt }
1358edacedfSDaniel Fojt 
1368edacedfSDaniel Fojt const X509V3_EXT_METHOD *
X509V3_EXT_get(X509_EXTENSION * ext)1378edacedfSDaniel Fojt X509V3_EXT_get(X509_EXTENSION *ext)
1388edacedfSDaniel Fojt {
1398edacedfSDaniel Fojt 	int nid;
1408edacedfSDaniel Fojt 
1418edacedfSDaniel Fojt 	if ((nid = OBJ_obj2nid(ext->object)) == NID_undef)
1428edacedfSDaniel Fojt 		return NULL;
1438edacedfSDaniel Fojt 	return X509V3_EXT_get_nid(nid);
1448edacedfSDaniel Fojt }
1458edacedfSDaniel Fojt 
1468edacedfSDaniel Fojt int
X509V3_EXT_add_list(X509V3_EXT_METHOD * extlist)1478edacedfSDaniel Fojt X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist)
1488edacedfSDaniel Fojt {
1498edacedfSDaniel Fojt 	for (; extlist->ext_nid!=-1; extlist++)
1508edacedfSDaniel Fojt 		if (!X509V3_EXT_add(extlist))
1518edacedfSDaniel Fojt 			return 0;
1528edacedfSDaniel Fojt 	return 1;
1538edacedfSDaniel Fojt }
1548edacedfSDaniel Fojt 
1558edacedfSDaniel Fojt int
X509V3_EXT_add_alias(int nid_to,int nid_from)1568edacedfSDaniel Fojt X509V3_EXT_add_alias(int nid_to, int nid_from)
1578edacedfSDaniel Fojt {
1588edacedfSDaniel Fojt 	const X509V3_EXT_METHOD *ext;
1598edacedfSDaniel Fojt 	X509V3_EXT_METHOD *tmpext;
1608edacedfSDaniel Fojt 
1618edacedfSDaniel Fojt 	if (!(ext = X509V3_EXT_get_nid(nid_from))) {
1628edacedfSDaniel Fojt 		X509V3error(X509V3_R_EXTENSION_NOT_FOUND);
1638edacedfSDaniel Fojt 		return 0;
1648edacedfSDaniel Fojt 	}
1658edacedfSDaniel Fojt 	if (!(tmpext = malloc(sizeof(X509V3_EXT_METHOD)))) {
1668edacedfSDaniel Fojt 		X509V3error(ERR_R_MALLOC_FAILURE);
1678edacedfSDaniel Fojt 		return 0;
1688edacedfSDaniel Fojt 	}
1698edacedfSDaniel Fojt 	*tmpext = *ext;
1708edacedfSDaniel Fojt 	tmpext->ext_nid = nid_to;
1718edacedfSDaniel Fojt 	tmpext->ext_flags |= X509V3_EXT_DYNAMIC;
1728edacedfSDaniel Fojt 	if (!X509V3_EXT_add(tmpext)) {
1738edacedfSDaniel Fojt 		free(tmpext);
1748edacedfSDaniel Fojt 		return 0;
1758edacedfSDaniel Fojt 	}
1768edacedfSDaniel Fojt 	return 1;
1778edacedfSDaniel Fojt }
1788edacedfSDaniel Fojt 
1798edacedfSDaniel Fojt void
X509V3_EXT_cleanup(void)1808edacedfSDaniel Fojt X509V3_EXT_cleanup(void)
1818edacedfSDaniel Fojt {
1828edacedfSDaniel Fojt 	sk_X509V3_EXT_METHOD_pop_free(ext_list, ext_list_free);
1838edacedfSDaniel Fojt 	ext_list = NULL;
1848edacedfSDaniel Fojt }
1858edacedfSDaniel Fojt 
1868edacedfSDaniel Fojt static void
ext_list_free(X509V3_EXT_METHOD * ext)1878edacedfSDaniel Fojt ext_list_free(X509V3_EXT_METHOD *ext)
1888edacedfSDaniel Fojt {
1898edacedfSDaniel Fojt 	if (ext->ext_flags & X509V3_EXT_DYNAMIC)
1908edacedfSDaniel Fojt 		free(ext);
1918edacedfSDaniel Fojt }
1928edacedfSDaniel Fojt 
1938edacedfSDaniel Fojt /* Legacy function: we don't need to add standard extensions
1948edacedfSDaniel Fojt  * any more because they are now kept in ext_dat.h.
1958edacedfSDaniel Fojt  */
1968edacedfSDaniel Fojt 
1978edacedfSDaniel Fojt int
X509V3_add_standard_extensions(void)1988edacedfSDaniel Fojt X509V3_add_standard_extensions(void)
1998edacedfSDaniel Fojt {
2008edacedfSDaniel Fojt 	return 1;
2018edacedfSDaniel Fojt }
2028edacedfSDaniel Fojt 
2038edacedfSDaniel Fojt /* Return an extension internal structure */
2048edacedfSDaniel Fojt 
2058edacedfSDaniel Fojt void *
X509V3_EXT_d2i(X509_EXTENSION * ext)2068edacedfSDaniel Fojt X509V3_EXT_d2i(X509_EXTENSION *ext)
2078edacedfSDaniel Fojt {
2088edacedfSDaniel Fojt 	const X509V3_EXT_METHOD *method;
2098edacedfSDaniel Fojt 	const unsigned char *p;
2108edacedfSDaniel Fojt 
2118edacedfSDaniel Fojt 	if (!(method = X509V3_EXT_get(ext)))
2128edacedfSDaniel Fojt 		return NULL;
2138edacedfSDaniel Fojt 	p = ext->value->data;
2148edacedfSDaniel Fojt 	if (method->it)
2158edacedfSDaniel Fojt 		return ASN1_item_d2i(NULL, &p, ext->value->length,
2168edacedfSDaniel Fojt 		    method->it);
2178edacedfSDaniel Fojt 	return method->d2i(NULL, &p, ext->value->length);
2188edacedfSDaniel Fojt }
2198edacedfSDaniel Fojt 
2208edacedfSDaniel Fojt /* Get critical flag and decoded version of extension from a NID.
2218edacedfSDaniel Fojt  * The "idx" variable returns the last found extension and can
2228edacedfSDaniel Fojt  * be used to retrieve multiple extensions of the same NID.
2238edacedfSDaniel Fojt  * However multiple extensions with the same NID is usually
2248edacedfSDaniel Fojt  * due to a badly encoded certificate so if idx is NULL we
2258edacedfSDaniel Fojt  * choke if multiple extensions exist.
2268edacedfSDaniel Fojt  * The "crit" variable is set to the critical value.
2278edacedfSDaniel Fojt  * The return value is the decoded extension or NULL on
2288edacedfSDaniel Fojt  * error. The actual error can have several different causes,
2298edacedfSDaniel Fojt  * the value of *crit reflects the cause:
2308edacedfSDaniel Fojt  * >= 0, extension found but not decoded (reflects critical value).
2318edacedfSDaniel Fojt  * -1 extension not found.
2328edacedfSDaniel Fojt  * -2 extension occurs more than once.
2338edacedfSDaniel Fojt  */
2348edacedfSDaniel Fojt 
2358edacedfSDaniel Fojt void *
X509V3_get_d2i(const STACK_OF (X509_EXTENSION)* x,int nid,int * crit,int * idx)2368edacedfSDaniel Fojt X509V3_get_d2i(const STACK_OF(X509_EXTENSION) *x, int nid, int *crit, int *idx)
2378edacedfSDaniel Fojt {
2388edacedfSDaniel Fojt 	int lastpos, i;
2398edacedfSDaniel Fojt 	X509_EXTENSION *ex, *found_ex = NULL;
2408edacedfSDaniel Fojt 
2418edacedfSDaniel Fojt 	if (!x) {
2428edacedfSDaniel Fojt 		if (idx)
2438edacedfSDaniel Fojt 			*idx = -1;
2448edacedfSDaniel Fojt 		if (crit)
2458edacedfSDaniel Fojt 			*crit = -1;
2468edacedfSDaniel Fojt 		return NULL;
2478edacedfSDaniel Fojt 	}
2488edacedfSDaniel Fojt 	if (idx)
2498edacedfSDaniel Fojt 		lastpos = *idx + 1;
2508edacedfSDaniel Fojt 	else
2518edacedfSDaniel Fojt 		lastpos = 0;
2528edacedfSDaniel Fojt 	if (lastpos < 0)
2538edacedfSDaniel Fojt 		lastpos = 0;
2548edacedfSDaniel Fojt 	for (i = lastpos; i < sk_X509_EXTENSION_num(x); i++) {
2558edacedfSDaniel Fojt 		ex = sk_X509_EXTENSION_value(x, i);
2568edacedfSDaniel Fojt 		if (OBJ_obj2nid(ex->object) == nid) {
2578edacedfSDaniel Fojt 			if (idx) {
2588edacedfSDaniel Fojt 				*idx = i;
2598edacedfSDaniel Fojt 				found_ex = ex;
2608edacedfSDaniel Fojt 				break;
2618edacedfSDaniel Fojt 			} else if (found_ex) {
2628edacedfSDaniel Fojt 				/* Found more than one */
2638edacedfSDaniel Fojt 				if (crit)
2648edacedfSDaniel Fojt 					*crit = -2;
2658edacedfSDaniel Fojt 				return NULL;
2668edacedfSDaniel Fojt 			}
2678edacedfSDaniel Fojt 			found_ex = ex;
2688edacedfSDaniel Fojt 		}
2698edacedfSDaniel Fojt 	}
2708edacedfSDaniel Fojt 	if (found_ex) {
2718edacedfSDaniel Fojt 		/* Found it */
2728edacedfSDaniel Fojt 		if (crit)
2738edacedfSDaniel Fojt 			*crit = X509_EXTENSION_get_critical(found_ex);
2748edacedfSDaniel Fojt 		return X509V3_EXT_d2i(found_ex);
2758edacedfSDaniel Fojt 	}
2768edacedfSDaniel Fojt 
2778edacedfSDaniel Fojt 	/* Extension not found */
2788edacedfSDaniel Fojt 	if (idx)
2798edacedfSDaniel Fojt 		*idx = -1;
2808edacedfSDaniel Fojt 	if (crit)
2818edacedfSDaniel Fojt 		*crit = -1;
2828edacedfSDaniel Fojt 	return NULL;
2838edacedfSDaniel Fojt }
2848edacedfSDaniel Fojt 
2858edacedfSDaniel Fojt /* This function is a general extension append, replace and delete utility.
2868edacedfSDaniel Fojt  * The precise operation is governed by the 'flags' value. The 'crit' and
2878edacedfSDaniel Fojt  * 'value' arguments (if relevant) are the extensions internal structure.
2888edacedfSDaniel Fojt  */
2898edacedfSDaniel Fojt 
2908edacedfSDaniel Fojt int
X509V3_add1_i2d(STACK_OF (X509_EXTENSION)** x,int nid,void * value,int crit,unsigned long flags)2918edacedfSDaniel Fojt X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value,
2928edacedfSDaniel Fojt     int crit, unsigned long flags)
2938edacedfSDaniel Fojt {
2948edacedfSDaniel Fojt 	int extidx = -1;
2958edacedfSDaniel Fojt 	int errcode;
2968edacedfSDaniel Fojt 	X509_EXTENSION *ext, *extmp;
2978edacedfSDaniel Fojt 	unsigned long ext_op = flags & X509V3_ADD_OP_MASK;
2988edacedfSDaniel Fojt 
2998edacedfSDaniel Fojt 	/* If appending we don't care if it exists, otherwise
3008edacedfSDaniel Fojt 	 * look for existing extension.
3018edacedfSDaniel Fojt 	 */
3028edacedfSDaniel Fojt 	if (ext_op != X509V3_ADD_APPEND)
3038edacedfSDaniel Fojt 		extidx = X509v3_get_ext_by_NID(*x, nid, -1);
3048edacedfSDaniel Fojt 
3058edacedfSDaniel Fojt 	/* See if extension exists */
3068edacedfSDaniel Fojt 	if (extidx >= 0) {
3078edacedfSDaniel Fojt 		/* If keep existing, nothing to do */
3088edacedfSDaniel Fojt 		if (ext_op == X509V3_ADD_KEEP_EXISTING)
3098edacedfSDaniel Fojt 			return 1;
3108edacedfSDaniel Fojt 		/* If default then its an error */
3118edacedfSDaniel Fojt 		if (ext_op == X509V3_ADD_DEFAULT) {
3128edacedfSDaniel Fojt 			errcode = X509V3_R_EXTENSION_EXISTS;
3138edacedfSDaniel Fojt 			goto err;
3148edacedfSDaniel Fojt 		}
3158edacedfSDaniel Fojt 		/* If delete, just delete it */
3168edacedfSDaniel Fojt 		if (ext_op == X509V3_ADD_DELETE) {
317*de0e0e4dSAntonio Huete Jimenez 			if ((extmp = sk_X509_EXTENSION_delete(*x, extidx)) == NULL)
3188edacedfSDaniel Fojt 				return -1;
319*de0e0e4dSAntonio Huete Jimenez 			X509_EXTENSION_free(extmp);
3208edacedfSDaniel Fojt 			return 1;
3218edacedfSDaniel Fojt 		}
3228edacedfSDaniel Fojt 	} else {
3238edacedfSDaniel Fojt 		/* If replace existing or delete, error since
3248edacedfSDaniel Fojt 		 * extension must exist
3258edacedfSDaniel Fojt 		 */
3268edacedfSDaniel Fojt 		if ((ext_op == X509V3_ADD_REPLACE_EXISTING) ||
3278edacedfSDaniel Fojt 		    (ext_op == X509V3_ADD_DELETE)) {
3288edacedfSDaniel Fojt 			errcode = X509V3_R_EXTENSION_NOT_FOUND;
3298edacedfSDaniel Fojt 			goto err;
3308edacedfSDaniel Fojt 		}
3318edacedfSDaniel Fojt 	}
3328edacedfSDaniel Fojt 
3338edacedfSDaniel Fojt 	/* If we get this far then we have to create an extension:
3348edacedfSDaniel Fojt 	 * could have some flags for alternative encoding schemes...
3358edacedfSDaniel Fojt 	 */
3368edacedfSDaniel Fojt 
3378edacedfSDaniel Fojt 	ext = X509V3_EXT_i2d(nid, crit, value);
3388edacedfSDaniel Fojt 
3398edacedfSDaniel Fojt 	if (!ext) {
3408edacedfSDaniel Fojt 		X509V3error(X509V3_R_ERROR_CREATING_EXTENSION);
3418edacedfSDaniel Fojt 		return 0;
3428edacedfSDaniel Fojt 	}
3438edacedfSDaniel Fojt 
3448edacedfSDaniel Fojt 	/* If extension exists replace it.. */
3458edacedfSDaniel Fojt 	if (extidx >= 0) {
3468edacedfSDaniel Fojt 		extmp = sk_X509_EXTENSION_value(*x, extidx);
3478edacedfSDaniel Fojt 		X509_EXTENSION_free(extmp);
3488edacedfSDaniel Fojt 		if (!sk_X509_EXTENSION_set(*x, extidx, ext))
3498edacedfSDaniel Fojt 			return -1;
3508edacedfSDaniel Fojt 		return 1;
3518edacedfSDaniel Fojt 	}
3528edacedfSDaniel Fojt 
3538edacedfSDaniel Fojt 	if (!*x && !(*x = sk_X509_EXTENSION_new_null()))
3548edacedfSDaniel Fojt 		return -1;
3558edacedfSDaniel Fojt 	if (!sk_X509_EXTENSION_push(*x, ext))
3568edacedfSDaniel Fojt 		return -1;
3578edacedfSDaniel Fojt 
3588edacedfSDaniel Fojt 	return 1;
3598edacedfSDaniel Fojt 
3608edacedfSDaniel Fojt err:
3618edacedfSDaniel Fojt 	if (!(flags & X509V3_ADD_SILENT))
3628edacedfSDaniel Fojt 		X509V3error(errcode);
3638edacedfSDaniel Fojt 	return 0;
3648edacedfSDaniel Fojt }
365