xref: /aosp_15_r20/external/boringssl/src/crypto/x509/x509_vpm.c (revision 8fb009dc861624b67b6cdb62ea21f0f22d0c584b)
1 /*
2  * Written by Dr Stephen N Henson ([email protected]) for the OpenSSL project
3  * 2004.
4  */
5 /* ====================================================================
6  * Copyright (c) 2004 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  *    [email protected].
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  * ([email protected]).  This product includes software written by Tim
55  * Hudson ([email protected]). */
56 
57 #include <string.h>
58 
59 #include <openssl/mem.h>
60 #include <openssl/obj.h>
61 #include <openssl/stack.h>
62 #include <openssl/x509.h>
63 
64 #include "../internal.h"
65 #include "internal.h"
66 
67 
68 // X509_VERIFY_PARAM functions
69 
70 #define SET_HOST 0
71 #define ADD_HOST 1
72 
str_free(char * s)73 static void str_free(char *s) { OPENSSL_free(s); }
74 
int_x509_param_set_hosts(X509_VERIFY_PARAM * param,int mode,const char * name,size_t namelen)75 static int int_x509_param_set_hosts(X509_VERIFY_PARAM *param, int mode,
76                                     const char *name, size_t namelen) {
77   char *copy;
78 
79   if (name == NULL || namelen == 0) {
80     // Unlike OpenSSL, we reject trying to set or add an empty name.
81     return 0;
82   }
83 
84   // Refuse names with embedded NUL bytes.
85   // XXX: Do we need to push an error onto the error stack?
86   if (name && OPENSSL_memchr(name, '\0', namelen)) {
87     return 0;
88   }
89 
90   if (mode == SET_HOST && param->hosts) {
91     sk_OPENSSL_STRING_pop_free(param->hosts, str_free);
92     param->hosts = NULL;
93   }
94 
95   copy = OPENSSL_strndup(name, namelen);
96   if (copy == NULL) {
97     return 0;
98   }
99 
100   if (param->hosts == NULL &&
101       (param->hosts = sk_OPENSSL_STRING_new_null()) == NULL) {
102     OPENSSL_free(copy);
103     return 0;
104   }
105 
106   if (!sk_OPENSSL_STRING_push(param->hosts, copy)) {
107     OPENSSL_free(copy);
108     if (sk_OPENSSL_STRING_num(param->hosts) == 0) {
109       sk_OPENSSL_STRING_free(param->hosts);
110       param->hosts = NULL;
111     }
112     return 0;
113   }
114 
115   return 1;
116 }
117 
X509_VERIFY_PARAM_new(void)118 X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void) {
119   X509_VERIFY_PARAM *param = OPENSSL_zalloc(sizeof(X509_VERIFY_PARAM));
120   if (!param) {
121     return NULL;
122   }
123   param->depth = -1;
124   return param;
125 }
126 
X509_VERIFY_PARAM_free(X509_VERIFY_PARAM * param)127 void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param) {
128   if (param == NULL) {
129     return;
130   }
131   sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
132   sk_OPENSSL_STRING_pop_free(param->hosts, str_free);
133   OPENSSL_free(param->email);
134   OPENSSL_free(param->ip);
135   OPENSSL_free(param);
136 }
137 
should_copy(int dest_is_set,int src_is_set,int prefer_src)138 static int should_copy(int dest_is_set, int src_is_set, int prefer_src) {
139   if (prefer_src) {
140     // We prefer the source, so as long as there is a value to copy, copy it.
141     return src_is_set;
142   }
143 
144   // We prefer the destination, so only copy if the destination is unset.
145   return src_is_set && !dest_is_set;
146 }
147 
copy_int_param(int * dest,const int * src,int default_val,int prefer_src)148 static void copy_int_param(int *dest, const int *src, int default_val,
149                            int prefer_src) {
150   if (should_copy(*dest != default_val, *src != default_val, prefer_src)) {
151     *dest = *src;
152   }
153 }
154 
155 // x509_verify_param_copy copies fields from |src| to |dest|. If both |src| and
156 // |dest| have some field set, |prefer_src| determines whether |src| or |dest|'s
157 // version is used.
x509_verify_param_copy(X509_VERIFY_PARAM * dest,const X509_VERIFY_PARAM * src,int prefer_src)158 static int x509_verify_param_copy(X509_VERIFY_PARAM *dest,
159                                   const X509_VERIFY_PARAM *src,
160                                   int prefer_src) {
161   if (src == NULL) {
162     return 1;
163   }
164 
165   copy_int_param(&dest->purpose, &src->purpose, /*default_val=*/0, prefer_src);
166   copy_int_param(&dest->trust, &src->trust, /*default_val=*/0, prefer_src);
167   copy_int_param(&dest->depth, &src->depth, /*default_val=*/-1, prefer_src);
168 
169   // |check_time|, unlike all other parameters, does not honor |prefer_src|.
170   // This means |X509_VERIFY_PARAM_set1| will not overwrite it. This behavior
171   // comes from OpenSSL but may have been a bug.
172   if (!(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) {
173     dest->check_time = src->check_time;
174     // The source |X509_V_FLAG_USE_CHECK_TIME| flag, if set, is copied below.
175   }
176 
177   dest->flags |= src->flags;
178 
179   if (should_copy(dest->policies != NULL, src->policies != NULL, prefer_src)) {
180     if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies)) {
181       return 0;
182     }
183   }
184 
185   if (should_copy(dest->hosts != NULL, src->hosts != NULL, prefer_src)) {
186     sk_OPENSSL_STRING_pop_free(dest->hosts, str_free);
187     dest->hosts = NULL;
188     if (src->hosts) {
189       dest->hosts =
190           sk_OPENSSL_STRING_deep_copy(src->hosts, OPENSSL_strdup, str_free);
191       if (dest->hosts == NULL) {
192         return 0;
193       }
194       // Copy the host flags if and only if we're copying the host list. Note
195       // this means mechanisms like |X509_STORE_CTX_set_default| cannot be used
196       // to set host flags. E.g. we cannot change the defaults using
197       // |kDefaultParam| below.
198       dest->hostflags = src->hostflags;
199     }
200   }
201 
202   if (should_copy(dest->email != NULL, src->email != NULL, prefer_src)) {
203     if (!X509_VERIFY_PARAM_set1_email(dest, src->email, src->emaillen)) {
204       return 0;
205     }
206   }
207 
208   if (should_copy(dest->ip != NULL, src->ip != NULL, prefer_src)) {
209     if (!X509_VERIFY_PARAM_set1_ip(dest, src->ip, src->iplen)) {
210       return 0;
211     }
212   }
213 
214   dest->poison = src->poison;
215   return 1;
216 }
217 
X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM * dest,const X509_VERIFY_PARAM * src)218 int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
219                               const X509_VERIFY_PARAM *src) {
220   // Prefer the destination. That is, this function only changes unset
221   // parameters in |dest|.
222   return x509_verify_param_copy(dest, src, /*prefer_src=*/0);
223 }
224 
X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM * to,const X509_VERIFY_PARAM * from)225 int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to,
226                            const X509_VERIFY_PARAM *from) {
227   // Prefer the source. That is, values in |to| are only preserved if they were
228   // unset in |from|.
229   return x509_verify_param_copy(to, from, /*prefer_src=*/1);
230 }
231 
int_x509_param_set1(char ** pdest,size_t * pdestlen,const char * src,size_t srclen)232 static int int_x509_param_set1(char **pdest, size_t *pdestlen, const char *src,
233                                size_t srclen) {
234   void *tmp;
235   if (src == NULL || srclen == 0) {
236     // Unlike OpenSSL, we do not allow an empty string to disable previously
237     // configured checks.
238     return 0;
239   }
240 
241   tmp = OPENSSL_memdup(src, srclen);
242   if (!tmp) {
243     return 0;
244   }
245 
246   if (*pdest) {
247     OPENSSL_free(*pdest);
248   }
249   *pdest = tmp;
250   if (pdestlen) {
251     *pdestlen = srclen;
252   }
253   return 1;
254 }
255 
X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM * param,unsigned long flags)256 int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags) {
257   param->flags |= flags;
258   return 1;
259 }
260 
X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM * param,unsigned long flags)261 int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param,
262                                   unsigned long flags) {
263   param->flags &= ~flags;
264   return 1;
265 }
266 
X509_VERIFY_PARAM_get_flags(const X509_VERIFY_PARAM * param)267 unsigned long X509_VERIFY_PARAM_get_flags(const X509_VERIFY_PARAM *param) {
268   return param->flags;
269 }
270 
X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM * param,int purpose)271 int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose) {
272   if (X509_PURPOSE_get0(purpose) == NULL) {
273     OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_PURPOSE);
274     return 0;
275   }
276   param->purpose = purpose;
277   return 1;
278 }
279 
X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM * param,int trust)280 int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust) {
281   if (!X509_is_valid_trust_id(trust)) {
282     OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_TRUST_ID);
283     return 0;
284   }
285 
286   param->trust = trust;
287   return 1;
288 }
289 
X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM * param,int depth)290 void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth) {
291   param->depth = depth;
292 }
293 
X509_VERIFY_PARAM_set_time_posix(X509_VERIFY_PARAM * param,int64_t t)294 void X509_VERIFY_PARAM_set_time_posix(X509_VERIFY_PARAM *param, int64_t t) {
295   param->check_time = t;
296   param->flags |= X509_V_FLAG_USE_CHECK_TIME;
297 }
298 
X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM * param,time_t t)299 void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t) {
300   X509_VERIFY_PARAM_set_time_posix(param, t);
301 }
302 
X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM * param,ASN1_OBJECT * policy)303 int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param,
304                                   ASN1_OBJECT *policy) {
305   if (!param->policies) {
306     param->policies = sk_ASN1_OBJECT_new_null();
307     if (!param->policies) {
308       return 0;
309     }
310   }
311   if (!sk_ASN1_OBJECT_push(param->policies, policy)) {
312     return 0;
313   }
314   return 1;
315 }
316 
X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM * param,const STACK_OF (ASN1_OBJECT)* policies)317 int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
318                                     const STACK_OF(ASN1_OBJECT) *policies) {
319   if (!param) {
320     return 0;
321   }
322 
323   sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
324   if (!policies) {
325     param->policies = NULL;
326     return 1;
327   }
328 
329   param->policies =
330       sk_ASN1_OBJECT_deep_copy(policies, OBJ_dup, ASN1_OBJECT_free);
331   if (!param->policies) {
332     return 0;
333   }
334 
335   return 1;
336 }
337 
X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM * param,const char * name,size_t namelen)338 int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, const char *name,
339                                 size_t namelen) {
340   if (!int_x509_param_set_hosts(param, SET_HOST, name, namelen)) {
341     param->poison = 1;
342     return 0;
343   }
344   return 1;
345 }
346 
X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM * param,const char * name,size_t namelen)347 int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param, const char *name,
348                                 size_t namelen) {
349   if (!int_x509_param_set_hosts(param, ADD_HOST, name, namelen)) {
350     param->poison = 1;
351     return 0;
352   }
353   return 1;
354 }
355 
X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM * param,unsigned int flags)356 void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
357                                      unsigned int flags) {
358   param->hostflags = flags;
359 }
360 
X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM * param,const char * email,size_t emaillen)361 int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, const char *email,
362                                  size_t emaillen) {
363   if (OPENSSL_memchr(email, '\0', emaillen) != NULL ||
364       !int_x509_param_set1(&param->email, &param->emaillen, email, emaillen)) {
365     param->poison = 1;
366     return 0;
367   }
368 
369   return 1;
370 }
371 
X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM * param,const unsigned char * ip,size_t iplen)372 int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, const unsigned char *ip,
373                               size_t iplen) {
374   if ((iplen != 4 && iplen != 16) ||
375       !int_x509_param_set1((char **)&param->ip, &param->iplen, (char *)ip,
376                            iplen)) {
377     param->poison = 1;
378     return 0;
379   }
380 
381   return 1;
382 }
383 
X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM * param,const char * ipasc)384 int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc) {
385   unsigned char ipout[16];
386   size_t iplen;
387 
388   iplen = (size_t)x509v3_a2i_ipadd(ipout, ipasc);
389   if (iplen == 0) {
390     return 0;
391   }
392   return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen);
393 }
394 
X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM * param)395 int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param) {
396   return param->depth;
397 }
398 
399 static const X509_VERIFY_PARAM kDefaultParam = {
400     .flags = X509_V_FLAG_TRUSTED_FIRST,
401     .depth = 100,
402 };
403 
404 static const X509_VERIFY_PARAM kSMIMESignParam = {
405     .purpose = X509_PURPOSE_SMIME_SIGN,
406     .trust = X509_TRUST_EMAIL,
407     .depth = -1,
408 };
409 
410 static const X509_VERIFY_PARAM kSSLClientParam = {
411     .purpose = X509_PURPOSE_SSL_CLIENT,
412     .trust = X509_TRUST_SSL_CLIENT,
413     .depth = -1,
414 };
415 
416 static const X509_VERIFY_PARAM kSSLServerParam = {
417     .purpose = X509_PURPOSE_SSL_SERVER,
418     .trust = X509_TRUST_SSL_SERVER,
419     .depth = -1,
420 };
421 
X509_VERIFY_PARAM_lookup(const char * name)422 const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name) {
423   if (strcmp(name, "default") == 0) {
424     return &kDefaultParam;
425   }
426   if (strcmp(name, "pkcs7") == 0) {
427     // PKCS#7 and S/MIME signing use the same defaults.
428     return &kSMIMESignParam;
429   }
430   if (strcmp(name, "smime_sign") == 0) {
431     return &kSMIMESignParam;
432   }
433   if (strcmp(name, "ssl_client") == 0) {
434     return &kSSLClientParam;
435   }
436   if (strcmp(name, "ssl_server") == 0) {
437     return &kSSLServerParam;
438   }
439   return NULL;
440 }
441