xref: /aosp_15_r20/external/cronet/third_party/boringssl/src/crypto/x509/x_crl.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 /* Copyright (C) 1995-1998 Eric Young ([email protected])
2  * All rights reserved.
3  *
4  * This package is an SSL implementation written
5  * by Eric Young ([email protected]).
6  * The implementation was written so as to conform with Netscapes SSL.
7  *
8  * This library is free for commercial and non-commercial use as long as
9  * the following conditions are aheared to.  The following conditions
10  * apply to all code found in this distribution, be it the RC4, RSA,
11  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12  * included with this distribution is covered by the same copyright terms
13  * except that the holder is Tim Hudson ([email protected]).
14  *
15  * Copyright remains Eric Young's, and as such any Copyright notices in
16  * the code are not to be removed.
17  * If this package is used in a product, Eric Young should be given attribution
18  * as the author of the parts of the library used.
19  * This can be in the form of a textual message at program startup or
20  * in documentation (online or textual) provided with the package.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the copyright
26  *    notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *    notice, this list of conditions and the following disclaimer in the
29  *    documentation and/or other materials provided with the distribution.
30  * 3. All advertising materials mentioning features or use of this software
31  *    must display the following acknowledgement:
32  *    "This product includes cryptographic software written by
33  *     Eric Young ([email protected])"
34  *    The word 'cryptographic' can be left out if the rouines from the library
35  *    being used are not cryptographic related :-).
36  * 4. If you include any Windows specific code (or a derivative thereof) from
37  *    the apps directory (application code) you must include an acknowledgement:
38  *    "This product includes software written by Tim Hudson ([email protected])"
39  *
40  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  *
52  * The licence and distribution terms for any publically available version or
53  * derivative of this code cannot be changed.  i.e. this code cannot simply be
54  * copied and put under another distribution licence
55  * [including the GNU Public Licence.] */
56 
57 #include <openssl/asn1.h>
58 #include <openssl/asn1t.h>
59 #include <openssl/digest.h>
60 #include <openssl/err.h>
61 #include <openssl/mem.h>
62 #include <openssl/obj.h>
63 #include <openssl/stack.h>
64 #include <openssl/thread.h>
65 #include <openssl/x509.h>
66 #include <openssl/x509v3.h>
67 
68 #include <assert.h>
69 
70 #include "../asn1/internal.h"
71 #include "../internal.h"
72 #include "internal.h"
73 
74 static int X509_REVOKED_cmp(const X509_REVOKED *const *a,
75                             const X509_REVOKED *const *b);
76 static int setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp);
77 
78 ASN1_SEQUENCE(X509_REVOKED) = {
79     ASN1_SIMPLE(X509_REVOKED, serialNumber, ASN1_INTEGER),
80     ASN1_SIMPLE(X509_REVOKED, revocationDate, ASN1_TIME),
81     ASN1_SEQUENCE_OF_OPT(X509_REVOKED, extensions, X509_EXTENSION),
82 } ASN1_SEQUENCE_END(X509_REVOKED)
83 
84 static int crl_lookup(X509_CRL *crl, X509_REVOKED **ret,
85                       const ASN1_INTEGER *serial, X509_NAME *issuer);
86 
87 // The X509_CRL_INFO structure needs a bit of customisation. Since we cache
88 // the original encoding the signature wont be affected by reordering of the
89 // revoked field.
crl_inf_cb(int operation,ASN1_VALUE ** pval,const ASN1_ITEM * it,void * exarg)90 static int crl_inf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
91                       void *exarg) {
92   X509_CRL_INFO *a = (X509_CRL_INFO *)*pval;
93 
94   if (!a || !a->revoked) {
95     return 1;
96   }
97   switch (operation) {
98       // Just set cmp function here. We don't sort because that would
99       // affect the output of X509_CRL_print().
100     case ASN1_OP_D2I_POST:
101       (void)sk_X509_REVOKED_set_cmp_func(a->revoked, X509_REVOKED_cmp);
102       break;
103   }
104   return 1;
105 }
106 
107 
108 ASN1_SEQUENCE_enc(X509_CRL_INFO, enc, crl_inf_cb) = {
109     ASN1_OPT(X509_CRL_INFO, version, ASN1_INTEGER),
110     ASN1_SIMPLE(X509_CRL_INFO, sig_alg, X509_ALGOR),
111     ASN1_SIMPLE(X509_CRL_INFO, issuer, X509_NAME),
112     ASN1_SIMPLE(X509_CRL_INFO, lastUpdate, ASN1_TIME),
113     ASN1_OPT(X509_CRL_INFO, nextUpdate, ASN1_TIME),
114     ASN1_SEQUENCE_OF_OPT(X509_CRL_INFO, revoked, X509_REVOKED),
115     ASN1_EXP_SEQUENCE_OF_OPT(X509_CRL_INFO, extensions, X509_EXTENSION, 0),
116 } ASN1_SEQUENCE_END_enc(X509_CRL_INFO, X509_CRL_INFO)
117 
118 static int crl_parse_entry_extensions(X509_CRL *crl) {
119   STACK_OF(X509_REVOKED) *revoked = X509_CRL_get_REVOKED(crl);
120   for (size_t i = 0; i < sk_X509_REVOKED_num(revoked); i++) {
121     X509_REVOKED *rev = sk_X509_REVOKED_value(revoked, i);
122 
123     int crit;
124     ASN1_ENUMERATED *reason =
125         X509_REVOKED_get_ext_d2i(rev, NID_crl_reason, &crit, NULL);
126     if (!reason && crit != -1) {
127       crl->flags |= EXFLAG_INVALID;
128       return 1;
129     }
130 
131     if (reason) {
132       rev->reason = ASN1_ENUMERATED_get(reason);
133       ASN1_ENUMERATED_free(reason);
134     } else {
135       rev->reason = CRL_REASON_NONE;
136     }
137 
138     // We do not support any critical CRL entry extensions.
139     const STACK_OF(X509_EXTENSION) *exts = rev->extensions;
140     for (size_t j = 0; j < sk_X509_EXTENSION_num(exts); j++) {
141       const X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, j);
142       if (X509_EXTENSION_get_critical(ext)) {
143         crl->flags |= EXFLAG_CRITICAL;
144         break;
145       }
146     }
147   }
148 
149   return 1;
150 }
151 
152 // The X509_CRL structure needs a bit of customisation. Cache some extensions
153 // and hash of the whole CRL.
crl_cb(int operation,ASN1_VALUE ** pval,const ASN1_ITEM * it,void * exarg)154 static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
155                   void *exarg) {
156   X509_CRL *crl = (X509_CRL *)*pval;
157   int i;
158 
159   switch (operation) {
160     case ASN1_OP_NEW_POST:
161       crl->idp = NULL;
162       crl->akid = NULL;
163       crl->flags = 0;
164       crl->idp_flags = 0;
165       break;
166 
167     case ASN1_OP_D2I_POST: {
168       // The version must be one of v1(0) or v2(1).
169       long version = X509_CRL_VERSION_1;
170       if (crl->crl->version != NULL) {
171         version = ASN1_INTEGER_get(crl->crl->version);
172         // TODO(https://crbug.com/boringssl/364): |X509_CRL_VERSION_1|
173         // should also be rejected. This means an explicitly-encoded X.509v1
174         // version. v1 is DEFAULT, so DER requires it be omitted.
175         if (version < X509_CRL_VERSION_1 || version > X509_CRL_VERSION_2) {
176           OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION);
177           return 0;
178         }
179       }
180 
181       // Per RFC 5280, section 5.1.2.1, extensions require v2.
182       if (version != X509_CRL_VERSION_2 && crl->crl->extensions != NULL) {
183         OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION);
184         return 0;
185       }
186 
187       if (!X509_CRL_digest(crl, EVP_sha256(), crl->crl_hash, NULL)) {
188         return 0;
189       }
190 
191       crl->idp =
192           X509_CRL_get_ext_d2i(crl, NID_issuing_distribution_point, &i, NULL);
193       if (crl->idp != NULL) {
194         if (!setup_idp(crl, crl->idp)) {
195           return 0;
196         }
197       } else if (i != -1) {
198         return 0;
199       }
200 
201       crl->akid =
202           X509_CRL_get_ext_d2i(crl, NID_authority_key_identifier, &i, NULL);
203       if (crl->akid == NULL && i != -1) {
204         return 0;
205       }
206 
207       // See if we have any unhandled critical CRL extensions and indicate
208       // this in a flag. We only currently handle IDP so anything else
209       // critical sets the flag. This code accesses the X509_CRL structure
210       // directly: applications shouldn't do this.
211       const STACK_OF(X509_EXTENSION) *exts = crl->crl->extensions;
212       for (size_t idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++) {
213         const X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, idx);
214         int nid = OBJ_obj2nid(X509_EXTENSION_get_object(ext));
215         if (X509_EXTENSION_get_critical(ext)) {
216           if (nid == NID_issuing_distribution_point ||
217               nid == NID_authority_key_identifier) {
218             continue;
219           }
220           crl->flags |= EXFLAG_CRITICAL;
221           break;
222         }
223       }
224 
225       if (!crl_parse_entry_extensions(crl)) {
226         return 0;
227       }
228 
229       break;
230     }
231 
232     case ASN1_OP_FREE_POST:
233       AUTHORITY_KEYID_free(crl->akid);
234       ISSUING_DIST_POINT_free(crl->idp);
235       break;
236   }
237   return 1;
238 }
239 
240 // Convert IDP into a more convenient form
241 //
242 // TODO(davidben): Each of these flags are already booleans, so this is not
243 // really more convenient. We can probably remove |idp_flags|.
setup_idp(X509_CRL * crl,ISSUING_DIST_POINT * idp)244 static int setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp) {
245   int idp_only = 0;
246   // Set various flags according to IDP
247   crl->idp_flags |= IDP_PRESENT;
248   if (idp->onlyuser > 0) {
249     idp_only++;
250     crl->idp_flags |= IDP_ONLYUSER;
251   }
252   if (idp->onlyCA > 0) {
253     idp_only++;
254     crl->idp_flags |= IDP_ONLYCA;
255   }
256   if (idp->onlyattr > 0) {
257     idp_only++;
258     crl->idp_flags |= IDP_ONLYATTR;
259   }
260 
261   // Per RFC 5280, section 5.2.5, at most one of onlyContainsUserCerts,
262   // onlyContainsCACerts, and onlyContainsAttributeCerts may be true.
263   //
264   // TODO(crbug.com/boringssl/443): Move this check to the |ISSUING_DIST_POINT|
265   // parser.
266   if (idp_only > 1) {
267     crl->idp_flags |= IDP_INVALID;
268   }
269 
270   if (idp->indirectCRL > 0) {
271     crl->idp_flags |= IDP_INDIRECT;
272   }
273 
274   if (idp->onlysomereasons) {
275     crl->idp_flags |= IDP_REASONS;
276   }
277 
278   // TODO(davidben): The new verifier does not support nameRelativeToCRLIssuer.
279   // Remove this?
280   return DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl));
281 }
282 
283 ASN1_SEQUENCE_ref(X509_CRL, crl_cb) = {
284     ASN1_SIMPLE(X509_CRL, crl, X509_CRL_INFO),
285     ASN1_SIMPLE(X509_CRL, sig_alg, X509_ALGOR),
286     ASN1_SIMPLE(X509_CRL, signature, ASN1_BIT_STRING),
287 } ASN1_SEQUENCE_END_ref(X509_CRL, X509_CRL)
288 
289 // Although |X509_REVOKED| contains an |X509_NAME|, it can be const. It is not
290 // affected by https://crbug.com/boringssl/407 because the  |X509_NAME| does
291 // not participate in serialization.
292 IMPLEMENT_ASN1_FUNCTIONS_const(X509_REVOKED)
293 IMPLEMENT_ASN1_DUP_FUNCTION_const(X509_REVOKED)
294 
295 IMPLEMENT_ASN1_FUNCTIONS(X509_CRL_INFO)
296 IMPLEMENT_ASN1_FUNCTIONS(X509_CRL)
297 IMPLEMENT_ASN1_DUP_FUNCTION(X509_CRL)
298 
299 static int X509_REVOKED_cmp(const X509_REVOKED *const *a,
300                             const X509_REVOKED *const *b) {
301   return ASN1_STRING_cmp((*a)->serialNumber, (*b)->serialNumber);
302 }
303 
X509_CRL_add0_revoked(X509_CRL * crl,X509_REVOKED * rev)304 int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev) {
305   X509_CRL_INFO *inf;
306   inf = crl->crl;
307   if (!inf->revoked) {
308     inf->revoked = sk_X509_REVOKED_new(X509_REVOKED_cmp);
309   }
310   if (!inf->revoked || !sk_X509_REVOKED_push(inf->revoked, rev)) {
311     return 0;
312   }
313   asn1_encoding_clear(&inf->enc);
314   return 1;
315 }
316 
X509_CRL_verify(X509_CRL * crl,EVP_PKEY * pkey)317 int X509_CRL_verify(X509_CRL *crl, EVP_PKEY *pkey) {
318   if (X509_ALGOR_cmp(crl->sig_alg, crl->crl->sig_alg) != 0) {
319     OPENSSL_PUT_ERROR(X509, X509_R_SIGNATURE_ALGORITHM_MISMATCH);
320     return 0;
321   }
322 
323   return ASN1_item_verify(ASN1_ITEM_rptr(X509_CRL_INFO), crl->sig_alg,
324                           crl->signature, crl->crl, pkey);
325 }
326 
X509_CRL_get0_by_serial(X509_CRL * crl,X509_REVOKED ** ret,const ASN1_INTEGER * serial)327 int X509_CRL_get0_by_serial(X509_CRL *crl, X509_REVOKED **ret,
328                             const ASN1_INTEGER *serial) {
329   return crl_lookup(crl, ret, serial, NULL);
330 }
331 
X509_CRL_get0_by_cert(X509_CRL * crl,X509_REVOKED ** ret,X509 * x)332 int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x) {
333   return crl_lookup(crl, ret, X509_get_serialNumber(x),
334                     X509_get_issuer_name(x));
335 }
336 
crl_revoked_issuer_match(X509_CRL * crl,X509_NAME * nm,X509_REVOKED * rev)337 static int crl_revoked_issuer_match(X509_CRL *crl, X509_NAME *nm,
338                                     X509_REVOKED *rev) {
339   return nm == NULL || X509_NAME_cmp(nm, X509_CRL_get_issuer(crl)) == 0;
340 }
341 
342 static CRYPTO_MUTEX g_crl_sort_lock = CRYPTO_MUTEX_INIT;
343 
crl_lookup(X509_CRL * crl,X509_REVOKED ** ret,const ASN1_INTEGER * serial,X509_NAME * issuer)344 static int crl_lookup(X509_CRL *crl, X509_REVOKED **ret,
345                       const ASN1_INTEGER *serial, X509_NAME *issuer) {
346   // Use an assert, rather than a runtime error, because returning nothing for a
347   // CRL is arguably failing open, rather than closed.
348   assert(serial->type == V_ASN1_INTEGER || serial->type == V_ASN1_NEG_INTEGER);
349   X509_REVOKED rtmp, *rev;
350   size_t idx;
351   rtmp.serialNumber = (ASN1_INTEGER *)serial;
352   // Sort revoked into serial number order if not already sorted. Do this
353   // under a lock to avoid race condition.
354 
355   CRYPTO_MUTEX_lock_read(&g_crl_sort_lock);
356   const int is_sorted = sk_X509_REVOKED_is_sorted(crl->crl->revoked);
357   CRYPTO_MUTEX_unlock_read(&g_crl_sort_lock);
358 
359   if (!is_sorted) {
360     CRYPTO_MUTEX_lock_write(&g_crl_sort_lock);
361     if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked)) {
362       sk_X509_REVOKED_sort(crl->crl->revoked);
363     }
364     CRYPTO_MUTEX_unlock_write(&g_crl_sort_lock);
365   }
366 
367   if (!sk_X509_REVOKED_find(crl->crl->revoked, &idx, &rtmp)) {
368     return 0;
369   }
370   // Need to look for matching name
371   for (; idx < sk_X509_REVOKED_num(crl->crl->revoked); idx++) {
372     rev = sk_X509_REVOKED_value(crl->crl->revoked, idx);
373     if (ASN1_INTEGER_cmp(rev->serialNumber, serial)) {
374       return 0;
375     }
376     if (crl_revoked_issuer_match(crl, issuer, rev)) {
377       if (ret) {
378         *ret = rev;
379       }
380       return 1;
381     }
382   }
383   return 0;
384 }
385