xref: /openbsd-src/lib/libcrypto/x509/x509_v3.c (revision 3374c67d44f9b75b98444cbf63020f777792342e)
1 /* $OpenBSD: x509_v3.c,v 1.20 2022/11/26 16:08:55 tb Exp $ */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  *
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  *
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  *
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  *
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58 
59 #include <stdio.h>
60 
61 #include <openssl/asn1.h>
62 #include <openssl/err.h>
63 #include <openssl/evp.h>
64 #include <openssl/objects.h>
65 #include <openssl/stack.h>
66 #include <openssl/x509.h>
67 #include <openssl/x509v3.h>
68 
69 #include "x509_local.h"
70 
71 int
72 X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x)
73 {
74 	if (x == NULL)
75 		return (0);
76 	return (sk_X509_EXTENSION_num(x));
77 }
78 LCRYPTO_ALIAS(X509v3_get_ext_count)
79 
80 int
81 X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x, int nid, int lastpos)
82 {
83 	ASN1_OBJECT *obj;
84 
85 	obj = OBJ_nid2obj(nid);
86 	if (obj == NULL)
87 		return (-2);
88 	return (X509v3_get_ext_by_OBJ(x, obj, lastpos));
89 }
90 LCRYPTO_ALIAS(X509v3_get_ext_by_NID)
91 
92 int
93 X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *sk,
94     const ASN1_OBJECT *obj, int lastpos)
95 {
96 	int n;
97 	X509_EXTENSION *ex;
98 
99 	if (sk == NULL)
100 		return (-1);
101 	lastpos++;
102 	if (lastpos < 0)
103 		lastpos = 0;
104 	n = sk_X509_EXTENSION_num(sk);
105 	for (; lastpos < n; lastpos++) {
106 		ex = sk_X509_EXTENSION_value(sk, lastpos);
107 		if (OBJ_cmp(ex->object, obj) == 0)
108 			return (lastpos);
109 	}
110 	return (-1);
111 }
112 LCRYPTO_ALIAS(X509v3_get_ext_by_OBJ)
113 
114 int
115 X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *sk, int crit,
116     int lastpos)
117 {
118 	int n;
119 	X509_EXTENSION *ex;
120 
121 	if (sk == NULL)
122 		return (-1);
123 	lastpos++;
124 	if (lastpos < 0)
125 		lastpos = 0;
126 	n = sk_X509_EXTENSION_num(sk);
127 	for (; lastpos < n; lastpos++) {
128 		ex = sk_X509_EXTENSION_value(sk, lastpos);
129 		if (((ex->critical > 0) && crit) ||
130 		    ((ex->critical <= 0) && !crit))
131 			return (lastpos);
132 	}
133 	return (-1);
134 }
135 LCRYPTO_ALIAS(X509v3_get_ext_by_critical)
136 
137 X509_EXTENSION *
138 X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc)
139 {
140 	if (x == NULL || sk_X509_EXTENSION_num(x) <= loc || loc < 0)
141 		return NULL;
142 	else
143 		return sk_X509_EXTENSION_value(x, loc);
144 }
145 LCRYPTO_ALIAS(X509v3_get_ext)
146 
147 X509_EXTENSION *
148 X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc)
149 {
150 	X509_EXTENSION *ret;
151 
152 	if (x == NULL || sk_X509_EXTENSION_num(x) <= loc || loc < 0)
153 		return (NULL);
154 	ret = sk_X509_EXTENSION_delete(x, loc);
155 	return (ret);
156 }
157 LCRYPTO_ALIAS(X509v3_delete_ext)
158 
159 STACK_OF(X509_EXTENSION) *
160 X509v3_add_ext(STACK_OF(X509_EXTENSION) **x, X509_EXTENSION *ex, int loc)
161 {
162 	X509_EXTENSION *new_ex = NULL;
163 	int n;
164 	STACK_OF(X509_EXTENSION) *sk = NULL;
165 
166 	if (x == NULL) {
167 		X509error(ERR_R_PASSED_NULL_PARAMETER);
168 		goto err2;
169 	}
170 
171 	if (*x == NULL) {
172 		if ((sk = sk_X509_EXTENSION_new_null()) == NULL)
173 			goto err;
174 	} else
175 		sk= *x;
176 
177 	n = sk_X509_EXTENSION_num(sk);
178 	if (loc > n)
179 		loc = n;
180 	else if (loc < 0)
181 		loc = n;
182 
183 	if ((new_ex = X509_EXTENSION_dup(ex)) == NULL)
184 		goto err2;
185 	if (!sk_X509_EXTENSION_insert(sk, new_ex, loc))
186 		goto err;
187 	if (*x == NULL)
188 		*x = sk;
189 	return (sk);
190 
191 err:
192 	X509error(ERR_R_MALLOC_FAILURE);
193 err2:
194 	if (new_ex != NULL)
195 		X509_EXTENSION_free(new_ex);
196 	if (sk != NULL && (x != NULL && sk != *x))
197 		sk_X509_EXTENSION_free(sk);
198 	return (NULL);
199 }
200 LCRYPTO_ALIAS(X509v3_add_ext)
201 
202 X509_EXTENSION *
203 X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, int nid, int crit,
204     ASN1_OCTET_STRING *data)
205 {
206 	ASN1_OBJECT *obj;
207 	X509_EXTENSION *ret;
208 
209 	obj = OBJ_nid2obj(nid);
210 	if (obj == NULL) {
211 		X509error(X509_R_UNKNOWN_NID);
212 		return (NULL);
213 	}
214 	ret = X509_EXTENSION_create_by_OBJ(ex, obj, crit, data);
215 	if (ret == NULL)
216 		ASN1_OBJECT_free(obj);
217 	return (ret);
218 }
219 LCRYPTO_ALIAS(X509_EXTENSION_create_by_NID)
220 
221 X509_EXTENSION *
222 X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex, const ASN1_OBJECT *obj,
223     int crit, ASN1_OCTET_STRING *data)
224 {
225 	X509_EXTENSION *ret;
226 
227 	if ((ex == NULL) || (*ex == NULL)) {
228 		if ((ret = X509_EXTENSION_new()) == NULL) {
229 			X509error(ERR_R_MALLOC_FAILURE);
230 			return (NULL);
231 		}
232 	} else
233 		ret= *ex;
234 
235 	if (!X509_EXTENSION_set_object(ret, obj))
236 		goto err;
237 	if (!X509_EXTENSION_set_critical(ret, crit))
238 		goto err;
239 	if (!X509_EXTENSION_set_data(ret, data))
240 		goto err;
241 
242 	if ((ex != NULL) && (*ex == NULL))
243 		*ex = ret;
244 	return (ret);
245 
246 err:
247 	if ((ex == NULL) || (ret != *ex))
248 		X509_EXTENSION_free(ret);
249 	return (NULL);
250 }
251 LCRYPTO_ALIAS(X509_EXTENSION_create_by_OBJ)
252 
253 int
254 X509_EXTENSION_set_object(X509_EXTENSION *ex, const ASN1_OBJECT *obj)
255 {
256 	if ((ex == NULL) || (obj == NULL))
257 		return (0);
258 	ASN1_OBJECT_free(ex->object);
259 	ex->object = OBJ_dup(obj);
260 	return ex->object != NULL;
261 }
262 LCRYPTO_ALIAS(X509_EXTENSION_set_object)
263 
264 int
265 X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit)
266 {
267 	if (ex == NULL)
268 		return (0);
269 	ex->critical = (crit) ? 0xFF : -1;
270 	return (1);
271 }
272 LCRYPTO_ALIAS(X509_EXTENSION_set_critical)
273 
274 int
275 X509_EXTENSION_set_data(X509_EXTENSION *ex, ASN1_OCTET_STRING *data)
276 {
277 	int i;
278 
279 	if (ex == NULL)
280 		return (0);
281 	i = ASN1_STRING_set(ex->value, data->data, data->length);
282 	if (!i)
283 		return (0);
284 	return (1);
285 }
286 LCRYPTO_ALIAS(X509_EXTENSION_set_data)
287 
288 ASN1_OBJECT *
289 X509_EXTENSION_get_object(X509_EXTENSION *ex)
290 {
291 	if (ex == NULL)
292 		return (NULL);
293 	return (ex->object);
294 }
295 LCRYPTO_ALIAS(X509_EXTENSION_get_object)
296 
297 ASN1_OCTET_STRING *
298 X509_EXTENSION_get_data(X509_EXTENSION *ex)
299 {
300 	if (ex == NULL)
301 		return (NULL);
302 	return (ex->value);
303 }
304 LCRYPTO_ALIAS(X509_EXTENSION_get_data)
305 
306 int
307 X509_EXTENSION_get_critical(const X509_EXTENSION *ex)
308 {
309 	if (ex == NULL)
310 		return (0);
311 	if (ex->critical > 0)
312 		return 1;
313 	return 0;
314 }
315 LCRYPTO_ALIAS(X509_EXTENSION_get_critical)
316