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