Add more CT utility routines to be used as part of larger patch.
[openssl.git] / crypto / x509v3 / v3_lib.c
1 /*
2  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
3  * 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 #include "internal/cryptlib.h"
62 #include <openssl/conf.h>
63 #include <openssl/x509v3.h>
64
65 #include "ext_dat.h"
66
67 static STACK_OF(X509V3_EXT_METHOD) *ext_list = NULL;
68
69 static int ext_cmp(const X509V3_EXT_METHOD *const *a,
70                    const X509V3_EXT_METHOD *const *b);
71 static void ext_list_free(X509V3_EXT_METHOD *ext);
72
73 int X509V3_EXT_add(X509V3_EXT_METHOD *ext)
74 {
75     if (ext_list == NULL
76         && (ext_list = sk_X509V3_EXT_METHOD_new(ext_cmp)) == NULL) {
77         X509V3err(X509V3_F_X509V3_EXT_ADD, ERR_R_MALLOC_FAILURE);
78         return 0;
79     }
80     if (!sk_X509V3_EXT_METHOD_push(ext_list, ext)) {
81         X509V3err(X509V3_F_X509V3_EXT_ADD, ERR_R_MALLOC_FAILURE);
82         return 0;
83     }
84     return 1;
85 }
86
87 static int ext_cmp(const X509V3_EXT_METHOD *const *a,
88                    const X509V3_EXT_METHOD *const *b)
89 {
90     return ((*a)->ext_nid - (*b)->ext_nid);
91 }
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 /*
99  * This table will be searched using OBJ_bsearch so it *must* kept in order
100  * of the ext_nid values.
101  */
102
103 static const X509V3_EXT_METHOD *standard_exts[] = {
104     &v3_nscert,
105     &v3_ns_ia5_list[0],
106     &v3_ns_ia5_list[1],
107     &v3_ns_ia5_list[2],
108     &v3_ns_ia5_list[3],
109     &v3_ns_ia5_list[4],
110     &v3_ns_ia5_list[5],
111     &v3_ns_ia5_list[6],
112     &v3_skey_id,
113     &v3_key_usage,
114     &v3_pkey_usage_period,
115     &v3_alt[0],
116     &v3_alt[1],
117     &v3_bcons,
118     &v3_crl_num,
119     &v3_cpols,
120     &v3_akey_id,
121     &v3_crld,
122     &v3_ext_ku,
123     &v3_delta_crl,
124     &v3_crl_reason,
125 #ifndef OPENSSL_NO_OCSP
126     &v3_crl_invdate,
127 #endif
128     &v3_sxnet,
129     &v3_info,
130 #ifndef OPENSSL_NO_RFC3779
131     &v3_addr,
132     &v3_asid,
133 #endif
134 #ifndef OPENSSL_NO_OCSP
135     &v3_ocsp_nonce,
136     &v3_ocsp_crlid,
137     &v3_ocsp_accresp,
138     &v3_ocsp_nocheck,
139     &v3_ocsp_acutoff,
140     &v3_ocsp_serviceloc,
141 #endif
142     &v3_sinfo,
143     &v3_policy_constraints,
144 #ifndef OPENSSL_NO_OCSP
145     &v3_crl_hold,
146 #endif
147     &v3_pci,
148     &v3_name_constraints,
149     &v3_policy_mappings,
150     &v3_inhibit_anyp,
151     &v3_idp,
152     &v3_alt[2],
153     &v3_freshest_crl,
154 #ifndef OPENSSL_NO_CT
155     &v3_ct_scts[0],
156     &v3_ct_scts[1],
157     &v3_ct_scts[2],
158 #endif
159     &v3_tls_feature,
160 };
161
162 /* Number of standard extensions */
163
164 #define STANDARD_EXTENSION_COUNT OSSL_NELEM(standard_exts)
165
166 const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid)
167 {
168     X509V3_EXT_METHOD tmp;
169     const X509V3_EXT_METHOD *t = &tmp, *const *ret;
170     int idx;
171     if (nid < 0)
172         return NULL;
173     tmp.ext_nid = nid;
174     ret = OBJ_bsearch_ext(&t, standard_exts, STANDARD_EXTENSION_COUNT);
175     if (ret)
176         return *ret;
177     if (!ext_list)
178         return NULL;
179     idx = sk_X509V3_EXT_METHOD_find(ext_list, &tmp);
180     if (idx == -1)
181         return NULL;
182     return sk_X509V3_EXT_METHOD_value(ext_list, idx);
183 }
184
185 const X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext)
186 {
187     int nid;
188     if ((nid = OBJ_obj2nid(X509_EXTENSION_get_object(ext))) == NID_undef)
189         return NULL;
190     return X509V3_EXT_get_nid(nid);
191 }
192
193 int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist)
194 {
195     for (; extlist->ext_nid != -1; extlist++)
196         if (!X509V3_EXT_add(extlist))
197             return 0;
198     return 1;
199 }
200
201 int X509V3_EXT_add_alias(int nid_to, int nid_from)
202 {
203     const X509V3_EXT_METHOD *ext;
204     X509V3_EXT_METHOD *tmpext;
205
206     if ((ext = X509V3_EXT_get_nid(nid_from)) == NULL) {
207         X509V3err(X509V3_F_X509V3_EXT_ADD_ALIAS, X509V3_R_EXTENSION_NOT_FOUND);
208         return 0;
209     }
210     if ((tmpext = OPENSSL_malloc(sizeof(*tmpext))) == NULL) {
211         X509V3err(X509V3_F_X509V3_EXT_ADD_ALIAS, ERR_R_MALLOC_FAILURE);
212         return 0;
213     }
214     *tmpext = *ext;
215     tmpext->ext_nid = nid_to;
216     tmpext->ext_flags |= X509V3_EXT_DYNAMIC;
217     return X509V3_EXT_add(tmpext);
218 }
219
220 void X509V3_EXT_cleanup(void)
221 {
222     sk_X509V3_EXT_METHOD_pop_free(ext_list, ext_list_free);
223     ext_list = NULL;
224 }
225
226 static void ext_list_free(X509V3_EXT_METHOD *ext)
227 {
228     if (ext->ext_flags & X509V3_EXT_DYNAMIC)
229         OPENSSL_free(ext);
230 }
231
232 /*
233  * Legacy function: we don't need to add standard extensions any more because
234  * they are now kept in ext_dat.h.
235  */
236
237 int X509V3_add_standard_extensions(void)
238 {
239     return 1;
240 }
241
242 /* Return an extension internal structure */
243
244 void *X509V3_EXT_d2i(X509_EXTENSION *ext)
245 {
246     const X509V3_EXT_METHOD *method;
247     const unsigned char *p;
248     ASN1_STRING *extvalue;
249     int extlen;
250
251     if ((method = X509V3_EXT_get(ext)) == NULL)
252         return NULL;
253     extvalue = X509_EXTENSION_get_data(ext);
254     p = ASN1_STRING_data(extvalue);
255     extlen = ASN1_STRING_length(extvalue);
256     if (method->it)
257         return ASN1_item_d2i(NULL, &p, extlen, ASN1_ITEM_ptr(method->it));
258     return method->d2i(NULL, &p, extlen);
259 }
260
261 /*-
262  * Get critical flag and decoded version of extension from a NID.
263  * The "idx" variable returns the last found extension and can
264  * be used to retrieve multiple extensions of the same NID.
265  * However multiple extensions with the same NID is usually
266  * due to a badly encoded certificate so if idx is NULL we
267  * choke if multiple extensions exist.
268  * The "crit" variable is set to the critical value.
269  * The return value is the decoded extension or NULL on
270  * error. The actual error can have several different causes,
271  * the value of *crit reflects the cause:
272  * >= 0, extension found but not decoded (reflects critical value).
273  * -1 extension not found.
274  * -2 extension occurs more than once.
275  */
276
277 void *X509V3_get_d2i(STACK_OF(X509_EXTENSION) *x, int nid, int *crit,
278                      int *idx)
279 {
280     int lastpos, i;
281     X509_EXTENSION *ex, *found_ex = NULL;
282     if (!x) {
283         if (idx)
284             *idx = -1;
285         if (crit)
286             *crit = -1;
287         return NULL;
288     }
289     if (idx)
290         lastpos = *idx + 1;
291     else
292         lastpos = 0;
293     if (lastpos < 0)
294         lastpos = 0;
295     for (i = lastpos; i < sk_X509_EXTENSION_num(x); i++) {
296         ex = sk_X509_EXTENSION_value(x, i);
297         if (OBJ_obj2nid(X509_EXTENSION_get_object(ex)) == nid) {
298             if (idx) {
299                 *idx = i;
300                 found_ex = ex;
301                 break;
302             } else if (found_ex) {
303                 /* Found more than one */
304                 if (crit)
305                     *crit = -2;
306                 return NULL;
307             }
308             found_ex = ex;
309         }
310     }
311     if (found_ex) {
312         /* Found it */
313         if (crit)
314             *crit = X509_EXTENSION_get_critical(found_ex);
315         return X509V3_EXT_d2i(found_ex);
316     }
317
318     /* Extension not found */
319     if (idx)
320         *idx = -1;
321     if (crit)
322         *crit = -1;
323     return NULL;
324 }
325
326 /*
327  * This function is a general extension append, replace and delete utility.
328  * The precise operation is governed by the 'flags' value. The 'crit' and
329  * 'value' arguments (if relevant) are the extensions internal structure.
330  */
331
332 int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value,
333                     int crit, unsigned long flags)
334 {
335     int extidx = -1;
336     int errcode;
337     X509_EXTENSION *ext, *extmp;
338     unsigned long ext_op = flags & X509V3_ADD_OP_MASK;
339
340     /*
341      * If appending we don't care if it exists, otherwise look for existing
342      * extension.
343      */
344     if (ext_op != X509V3_ADD_APPEND)
345         extidx = X509v3_get_ext_by_NID(*x, nid, -1);
346
347     /* See if extension exists */
348     if (extidx >= 0) {
349         /* If keep existing, nothing to do */
350         if (ext_op == X509V3_ADD_KEEP_EXISTING)
351             return 1;
352         /* If default then its an error */
353         if (ext_op == X509V3_ADD_DEFAULT) {
354             errcode = X509V3_R_EXTENSION_EXISTS;
355             goto err;
356         }
357         /* If delete, just delete it */
358         if (ext_op == X509V3_ADD_DELETE) {
359             if (!sk_X509_EXTENSION_delete(*x, extidx))
360                 return -1;
361             return 1;
362         }
363     } else {
364         /*
365          * If replace existing or delete, error since extension must exist
366          */
367         if ((ext_op == X509V3_ADD_REPLACE_EXISTING) ||
368             (ext_op == X509V3_ADD_DELETE)) {
369             errcode = X509V3_R_EXTENSION_NOT_FOUND;
370             goto err;
371         }
372     }
373
374     /*
375      * If we get this far then we have to create an extension: could have
376      * some flags for alternative encoding schemes...
377      */
378
379     ext = X509V3_EXT_i2d(nid, crit, value);
380
381     if (!ext) {
382         X509V3err(X509V3_F_X509V3_ADD1_I2D,
383                   X509V3_R_ERROR_CREATING_EXTENSION);
384         return 0;
385     }
386
387     /* If extension exists replace it.. */
388     if (extidx >= 0) {
389         extmp = sk_X509_EXTENSION_value(*x, extidx);
390         X509_EXTENSION_free(extmp);
391         if (!sk_X509_EXTENSION_set(*x, extidx, ext))
392             return -1;
393         return 1;
394     }
395
396     if (*x == NULL
397         && (*x = sk_X509_EXTENSION_new_null()) == NULL)
398         return -1;
399     if (!sk_X509_EXTENSION_push(*x, ext))
400         return -1;
401
402     return 1;
403
404  err:
405     if (!(flags & X509V3_ADD_SILENT))
406         X509V3err(X509V3_F_X509V3_ADD1_I2D, errcode);
407     return 0;
408 }