GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/x509v3/v3_lib.c Lines: 56 123 45.5 %
Date: 2017-11-13 Branches: 32 86 37.2 %

Line Branch Exec Source
1
/* $OpenBSD: v3_lib.c,v 1.17 2017/01/29 17:49:23 beck Exp $ */
2
/* Written by Dr Stephen N Henson (steve@openssl.org) 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
/* X509 v3 extension utilities */
59
60
#include <stdio.h>
61
62
#include <openssl/conf.h>
63
#include <openssl/err.h>
64
#include <openssl/x509v3.h>
65
66
#include "ext_dat.h"
67
68
static STACK_OF(X509V3_EXT_METHOD) *ext_list = NULL;
69
70
static int ext_cmp(const X509V3_EXT_METHOD * const *a,
71
    const X509V3_EXT_METHOD * const *b);
72
static void ext_list_free(X509V3_EXT_METHOD *ext);
73
74
int
75
X509V3_EXT_add(X509V3_EXT_METHOD *ext)
76
{
77
	if (!ext_list && !(ext_list = sk_X509V3_EXT_METHOD_new(ext_cmp))) {
78
		X509V3error(ERR_R_MALLOC_FAILURE);
79
		return 0;
80
	}
81
	if (!sk_X509V3_EXT_METHOD_push(ext_list, ext)) {
82
		X509V3error(ERR_R_MALLOC_FAILURE);
83
		return 0;
84
	}
85
	return 1;
86
}
87
88
static int
89
ext_cmp(const X509V3_EXT_METHOD * const *a, const X509V3_EXT_METHOD * const *b)
90
{
91
17212
	return ((*a)->ext_nid - (*b)->ext_nid);
92
}
93
94
static int ext_cmp_BSEARCH_CMP_FN(const void *, const void *);
95
static int ext_cmp(const X509V3_EXT_METHOD * const *, const X509V3_EXT_METHOD * const *);
96
static const X509V3_EXT_METHOD * *OBJ_bsearch_ext(const X509V3_EXT_METHOD * *key, const X509V3_EXT_METHOD * const *base, int num);
97
98
static int
99
ext_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_)
100
{
101
17212
	const X509V3_EXT_METHOD * const *a = a_;
102
8606
	const X509V3_EXT_METHOD * const *b = b_;
103
8606
	return ext_cmp(a, b);
104
}
105
106
static const X509V3_EXT_METHOD * *
107
OBJ_bsearch_ext(const X509V3_EXT_METHOD * *key, const X509V3_EXT_METHOD * const *base, int num)
108
{
109
3670
	return (const X509V3_EXT_METHOD * *)OBJ_bsearch_(key, base, num, sizeof(const X509V3_EXT_METHOD *),
110
	    ext_cmp_BSEARCH_CMP_FN);
111
}
112
113
const X509V3_EXT_METHOD *
114
X509V3_EXT_get_nid(int nid)
115
{
116
3670
	X509V3_EXT_METHOD tmp;
117
1835
	const X509V3_EXT_METHOD *t = &tmp, * const *ret;
118
	int idx;
119
120
1835
	if (nid < 0)
121
		return NULL;
122
1835
	tmp.ext_nid = nid;
123
1835
	ret = OBJ_bsearch_ext(&t, standard_exts, STANDARD_EXTENSION_COUNT);
124
1835
	if (ret)
125
1835
		return *ret;
126
	if (!ext_list)
127
		return NULL;
128
	idx = sk_X509V3_EXT_METHOD_find(ext_list, &tmp);
129
	if (idx == -1)
130
		return NULL;
131
	return sk_X509V3_EXT_METHOD_value(ext_list, idx);
132
1835
}
133
134
const X509V3_EXT_METHOD *
135
X509V3_EXT_get(X509_EXTENSION *ext)
136
{
137
	int nid;
138
139
3540
	if ((nid = OBJ_obj2nid(ext->object)) == NID_undef)
140
		return NULL;
141
1770
	return X509V3_EXT_get_nid(nid);
142
1770
}
143
144
int
145
X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist)
146
{
147
	for (; extlist->ext_nid!=-1; extlist++)
148
		if (!X509V3_EXT_add(extlist))
149
			return 0;
150
	return 1;
151
}
152
153
int
154
X509V3_EXT_add_alias(int nid_to, int nid_from)
155
{
156
	const X509V3_EXT_METHOD *ext;
157
	X509V3_EXT_METHOD *tmpext;
158
159
	if (!(ext = X509V3_EXT_get_nid(nid_from))) {
160
		X509V3error(X509V3_R_EXTENSION_NOT_FOUND);
161
		return 0;
162
	}
163
	if (!(tmpext = malloc(sizeof(X509V3_EXT_METHOD)))) {
164
		X509V3error(ERR_R_MALLOC_FAILURE);
165
		return 0;
166
	}
167
	*tmpext = *ext;
168
	tmpext->ext_nid = nid_to;
169
	tmpext->ext_flags |= X509V3_EXT_DYNAMIC;
170
	return X509V3_EXT_add(tmpext);
171
}
172
173
void
174
X509V3_EXT_cleanup(void)
175
{
176
	sk_X509V3_EXT_METHOD_pop_free(ext_list, ext_list_free);
177
	ext_list = NULL;
178
}
179
180
static void
181
ext_list_free(X509V3_EXT_METHOD *ext)
182
{
183
	if (ext->ext_flags & X509V3_EXT_DYNAMIC)
184
		free(ext);
185
}
186
187
/* Legacy function: we don't need to add standard extensions
188
 * any more because they are now kept in ext_dat.h.
189
 */
190
191
int
192
X509V3_add_standard_extensions(void)
193
{
194
	return 1;
195
}
196
197
/* Return an extension internal structure */
198
199
void *
200
X509V3_EXT_d2i(X509_EXTENSION *ext)
201
{
202
	const X509V3_EXT_METHOD *method;
203
3442
	const unsigned char *p;
204
205
1721
	if (!(method = X509V3_EXT_get(ext)))
206
		return NULL;
207
1721
	p = ext->value->data;
208
1721
	if (method->it)
209
1721
		return ASN1_item_d2i(NULL, &p, ext->value->length,
210
		    method->it);
211
	return method->d2i(NULL, &p, ext->value->length);
212
1721
}
213
214
/* Get critical flag and decoded version of extension from a NID.
215
 * The "idx" variable returns the last found extension and can
216
 * be used to retrieve multiple extensions of the same NID.
217
 * However multiple extensions with the same NID is usually
218
 * due to a badly encoded certificate so if idx is NULL we
219
 * choke if multiple extensions exist.
220
 * The "crit" variable is set to the critical value.
221
 * The return value is the decoded extension or NULL on
222
 * error. The actual error can have several different causes,
223
 * the value of *crit reflects the cause:
224
 * >= 0, extension found but not decoded (reflects critical value).
225
 * -1 extension not found.
226
 * -2 extension occurs more than once.
227
 */
228
229
void *
230
X509V3_get_d2i(STACK_OF(X509_EXTENSION) *x, int nid, int *crit, int *idx)
231
{
232
	int lastpos, i;
233
	X509_EXTENSION *ex, *found_ex = NULL;
234
235
57208
	if (!x) {
236
22449
		if (idx)
237
			*idx = -1;
238
22449
		if (crit)
239
2240
			*crit = -1;
240
22449
		return NULL;
241
	}
242
6155
	if (idx)
243
		lastpos = *idx + 1;
244
	else
245
		lastpos = 0;
246
6155
	if (lastpos < 0)
247
		lastpos = 0;
248
53408
	for (i = lastpos; i < sk_X509_EXTENSION_num(x); i++) {
249
20549
		ex = sk_X509_EXTENSION_value(x, i);
250
20549
		if (OBJ_obj2nid(ex->object) == nid) {
251
1721
			if (idx) {
252
				*idx = i;
253
				found_ex = ex;
254
				break;
255
1721
			} else if (found_ex) {
256
				/* Found more than one */
257
				if (crit)
258
					*crit = -2;
259
				return NULL;
260
			}
261
			found_ex = ex;
262
1721
		}
263
	}
264
6155
	if (found_ex) {
265
		/* Found it */
266
1721
		if (crit)
267
			*crit = X509_EXTENSION_get_critical(found_ex);
268
1721
		return X509V3_EXT_d2i(found_ex);
269
	}
270
271
	/* Extension not found */
272
4434
	if (idx)
273
		*idx = -1;
274
4434
	if (crit)
275
608
		*crit = -1;
276
4434
	return NULL;
277
28604
}
278
279
/* This function is a general extension append, replace and delete utility.
280
 * The precise operation is governed by the 'flags' value. The 'crit' and
281
 * 'value' arguments (if relevant) are the extensions internal structure.
282
 */
283
284
int
285
X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value,
286
    int crit, unsigned long flags)
287
{
288
	int extidx = -1;
289
	int errcode;
290
	X509_EXTENSION *ext, *extmp;
291
90
	unsigned long ext_op = flags & X509V3_ADD_OP_MASK;
292
293
	/* If appending we don't care if it exists, otherwise
294
	 * look for existing extension.
295
	 */
296
45
	if (ext_op != X509V3_ADD_APPEND)
297
45
		extidx = X509v3_get_ext_by_NID(*x, nid, -1);
298
299
	/* See if extension exists */
300
45
	if (extidx >= 0) {
301
		/* If keep existing, nothing to do */
302
		if (ext_op == X509V3_ADD_KEEP_EXISTING)
303
			return 1;
304
		/* If default then its an error */
305
		if (ext_op == X509V3_ADD_DEFAULT) {
306
			errcode = X509V3_R_EXTENSION_EXISTS;
307
			goto err;
308
		}
309
		/* If delete, just delete it */
310
		if (ext_op == X509V3_ADD_DELETE) {
311
			if (!sk_X509_EXTENSION_delete(*x, extidx))
312
				return -1;
313
			return 1;
314
		}
315
	} else {
316
		/* If replace existing or delete, error since
317
		 * extension must exist
318
		 */
319
90
		if ((ext_op == X509V3_ADD_REPLACE_EXISTING) ||
320
45
		    (ext_op == X509V3_ADD_DELETE)) {
321
			errcode = X509V3_R_EXTENSION_NOT_FOUND;
322
			goto err;
323
		}
324
	}
325
326
	/* If we get this far then we have to create an extension:
327
	 * could have some flags for alternative encoding schemes...
328
	 */
329
330
45
	ext = X509V3_EXT_i2d(nid, crit, value);
331
332
45
	if (!ext) {
333
		X509V3error(X509V3_R_ERROR_CREATING_EXTENSION);
334
		return 0;
335
	}
336
337
	/* If extension exists replace it.. */
338
45
	if (extidx >= 0) {
339
		extmp = sk_X509_EXTENSION_value(*x, extidx);
340
		X509_EXTENSION_free(extmp);
341
		if (!sk_X509_EXTENSION_set(*x, extidx, ext))
342
			return -1;
343
		return 1;
344
	}
345
346

90
	if (!*x && !(*x = sk_X509_EXTENSION_new_null()))
347
		return -1;
348
45
	if (!sk_X509_EXTENSION_push(*x, ext))
349
		return -1;
350
351
45
	return 1;
352
353
err:
354
	if (!(flags & X509V3_ADD_SILENT))
355
		X509V3error(errcode);
356
	return 0;
357
45
}