Coverage Report

Created: 2022-11-30 06:20

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