xref: /optee_os/lib/libmbedtls/mbedtls/library/x509_crl.c (revision 817466cb476de705a8e3dabe1ef165fe27a18c2f)
1*817466cbSJens Wiklander /*
2*817466cbSJens Wiklander  *  X.509 Certidicate Revocation List (CRL) parsing
3*817466cbSJens Wiklander  *
4*817466cbSJens Wiklander  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5*817466cbSJens Wiklander  *  SPDX-License-Identifier: Apache-2.0
6*817466cbSJens Wiklander  *
7*817466cbSJens Wiklander  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8*817466cbSJens Wiklander  *  not use this file except in compliance with the License.
9*817466cbSJens Wiklander  *  You may obtain a copy of the License at
10*817466cbSJens Wiklander  *
11*817466cbSJens Wiklander  *  http://www.apache.org/licenses/LICENSE-2.0
12*817466cbSJens Wiklander  *
13*817466cbSJens Wiklander  *  Unless required by applicable law or agreed to in writing, software
14*817466cbSJens Wiklander  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15*817466cbSJens Wiklander  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*817466cbSJens Wiklander  *  See the License for the specific language governing permissions and
17*817466cbSJens Wiklander  *  limitations under the License.
18*817466cbSJens Wiklander  *
19*817466cbSJens Wiklander  *  This file is part of mbed TLS (https://tls.mbed.org)
20*817466cbSJens Wiklander  */
21*817466cbSJens Wiklander /*
22*817466cbSJens Wiklander  *  The ITU-T X.509 standard defines a certificate format for PKI.
23*817466cbSJens Wiklander  *
24*817466cbSJens Wiklander  *  http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
25*817466cbSJens Wiklander  *  http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
26*817466cbSJens Wiklander  *  http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
27*817466cbSJens Wiklander  *
28*817466cbSJens Wiklander  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
29*817466cbSJens Wiklander  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
30*817466cbSJens Wiklander  */
31*817466cbSJens Wiklander 
32*817466cbSJens Wiklander #if !defined(MBEDTLS_CONFIG_FILE)
33*817466cbSJens Wiklander #include "mbedtls/config.h"
34*817466cbSJens Wiklander #else
35*817466cbSJens Wiklander #include MBEDTLS_CONFIG_FILE
36*817466cbSJens Wiklander #endif
37*817466cbSJens Wiklander 
38*817466cbSJens Wiklander #if defined(MBEDTLS_X509_CRL_PARSE_C)
39*817466cbSJens Wiklander 
40*817466cbSJens Wiklander #include "mbedtls/x509_crl.h"
41*817466cbSJens Wiklander #include "mbedtls/oid.h"
42*817466cbSJens Wiklander 
43*817466cbSJens Wiklander #include <string.h>
44*817466cbSJens Wiklander 
45*817466cbSJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C)
46*817466cbSJens Wiklander #include "mbedtls/pem.h"
47*817466cbSJens Wiklander #endif
48*817466cbSJens Wiklander 
49*817466cbSJens Wiklander #if defined(MBEDTLS_PLATFORM_C)
50*817466cbSJens Wiklander #include "mbedtls/platform.h"
51*817466cbSJens Wiklander #else
52*817466cbSJens Wiklander #include <stdlib.h>
53*817466cbSJens Wiklander #include <stdio.h>
54*817466cbSJens Wiklander #define mbedtls_free       free
55*817466cbSJens Wiklander #define mbedtls_calloc    calloc
56*817466cbSJens Wiklander #define mbedtls_snprintf   snprintf
57*817466cbSJens Wiklander #endif
58*817466cbSJens Wiklander 
59*817466cbSJens Wiklander #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
60*817466cbSJens Wiklander #include <windows.h>
61*817466cbSJens Wiklander #else
62*817466cbSJens Wiklander #include <time.h>
63*817466cbSJens Wiklander #endif
64*817466cbSJens Wiklander 
65*817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32)
66*817466cbSJens Wiklander #include <stdio.h>
67*817466cbSJens Wiklander #endif
68*817466cbSJens Wiklander 
69*817466cbSJens Wiklander /* Implementation that should never be optimized out by the compiler */
70*817466cbSJens Wiklander static void mbedtls_zeroize( void *v, size_t n ) {
71*817466cbSJens Wiklander     volatile unsigned char *p = v; while( n-- ) *p++ = 0;
72*817466cbSJens Wiklander }
73*817466cbSJens Wiklander 
74*817466cbSJens Wiklander /*
75*817466cbSJens Wiklander  *  Version  ::=  INTEGER  {  v1(0), v2(1)  }
76*817466cbSJens Wiklander  */
77*817466cbSJens Wiklander static int x509_crl_get_version( unsigned char **p,
78*817466cbSJens Wiklander                              const unsigned char *end,
79*817466cbSJens Wiklander                              int *ver )
80*817466cbSJens Wiklander {
81*817466cbSJens Wiklander     int ret;
82*817466cbSJens Wiklander 
83*817466cbSJens Wiklander     if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
84*817466cbSJens Wiklander     {
85*817466cbSJens Wiklander         if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
86*817466cbSJens Wiklander         {
87*817466cbSJens Wiklander             *ver = 0;
88*817466cbSJens Wiklander             return( 0 );
89*817466cbSJens Wiklander         }
90*817466cbSJens Wiklander 
91*817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_INVALID_VERSION + ret );
92*817466cbSJens Wiklander     }
93*817466cbSJens Wiklander 
94*817466cbSJens Wiklander     return( 0 );
95*817466cbSJens Wiklander }
96*817466cbSJens Wiklander 
97*817466cbSJens Wiklander /*
98*817466cbSJens Wiklander  * X.509 CRL v2 extensions (no extensions parsed yet.)
99*817466cbSJens Wiklander  */
100*817466cbSJens Wiklander static int x509_get_crl_ext( unsigned char **p,
101*817466cbSJens Wiklander                              const unsigned char *end,
102*817466cbSJens Wiklander                              mbedtls_x509_buf *ext )
103*817466cbSJens Wiklander {
104*817466cbSJens Wiklander     int ret;
105*817466cbSJens Wiklander     size_t len = 0;
106*817466cbSJens Wiklander 
107*817466cbSJens Wiklander     /* Get explicit tag */
108*817466cbSJens Wiklander     if( ( ret = mbedtls_x509_get_ext( p, end, ext, 0) ) != 0 )
109*817466cbSJens Wiklander     {
110*817466cbSJens Wiklander         if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
111*817466cbSJens Wiklander             return( 0 );
112*817466cbSJens Wiklander 
113*817466cbSJens Wiklander         return( ret );
114*817466cbSJens Wiklander     }
115*817466cbSJens Wiklander 
116*817466cbSJens Wiklander     while( *p < end )
117*817466cbSJens Wiklander     {
118*817466cbSJens Wiklander         if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
119*817466cbSJens Wiklander                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
120*817466cbSJens Wiklander             return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
121*817466cbSJens Wiklander 
122*817466cbSJens Wiklander         *p += len;
123*817466cbSJens Wiklander     }
124*817466cbSJens Wiklander 
125*817466cbSJens Wiklander     if( *p != end )
126*817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
127*817466cbSJens Wiklander                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
128*817466cbSJens Wiklander 
129*817466cbSJens Wiklander     return( 0 );
130*817466cbSJens Wiklander }
131*817466cbSJens Wiklander 
132*817466cbSJens Wiklander /*
133*817466cbSJens Wiklander  * X.509 CRL v2 entry extensions (no extensions parsed yet.)
134*817466cbSJens Wiklander  */
135*817466cbSJens Wiklander static int x509_get_crl_entry_ext( unsigned char **p,
136*817466cbSJens Wiklander                              const unsigned char *end,
137*817466cbSJens Wiklander                              mbedtls_x509_buf *ext )
138*817466cbSJens Wiklander {
139*817466cbSJens Wiklander     int ret;
140*817466cbSJens Wiklander     size_t len = 0;
141*817466cbSJens Wiklander 
142*817466cbSJens Wiklander     /* OPTIONAL */
143*817466cbSJens Wiklander     if( end <= *p )
144*817466cbSJens Wiklander         return( 0 );
145*817466cbSJens Wiklander 
146*817466cbSJens Wiklander     ext->tag = **p;
147*817466cbSJens Wiklander     ext->p = *p;
148*817466cbSJens Wiklander 
149*817466cbSJens Wiklander     /*
150*817466cbSJens Wiklander      * Get CRL-entry extension sequence header
151*817466cbSJens Wiklander      * crlEntryExtensions      Extensions OPTIONAL  -- if present, MUST be v2
152*817466cbSJens Wiklander      */
153*817466cbSJens Wiklander     if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len,
154*817466cbSJens Wiklander             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
155*817466cbSJens Wiklander     {
156*817466cbSJens Wiklander         if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
157*817466cbSJens Wiklander         {
158*817466cbSJens Wiklander             ext->p = NULL;
159*817466cbSJens Wiklander             return( 0 );
160*817466cbSJens Wiklander         }
161*817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
162*817466cbSJens Wiklander     }
163*817466cbSJens Wiklander 
164*817466cbSJens Wiklander     end = *p + ext->len;
165*817466cbSJens Wiklander 
166*817466cbSJens Wiklander     if( end != *p + ext->len )
167*817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
168*817466cbSJens Wiklander                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
169*817466cbSJens Wiklander 
170*817466cbSJens Wiklander     while( *p < end )
171*817466cbSJens Wiklander     {
172*817466cbSJens Wiklander         if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
173*817466cbSJens Wiklander                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
174*817466cbSJens Wiklander             return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
175*817466cbSJens Wiklander 
176*817466cbSJens Wiklander         *p += len;
177*817466cbSJens Wiklander     }
178*817466cbSJens Wiklander 
179*817466cbSJens Wiklander     if( *p != end )
180*817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
181*817466cbSJens Wiklander                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
182*817466cbSJens Wiklander 
183*817466cbSJens Wiklander     return( 0 );
184*817466cbSJens Wiklander }
185*817466cbSJens Wiklander 
186*817466cbSJens Wiklander /*
187*817466cbSJens Wiklander  * X.509 CRL Entries
188*817466cbSJens Wiklander  */
189*817466cbSJens Wiklander static int x509_get_entries( unsigned char **p,
190*817466cbSJens Wiklander                              const unsigned char *end,
191*817466cbSJens Wiklander                              mbedtls_x509_crl_entry *entry )
192*817466cbSJens Wiklander {
193*817466cbSJens Wiklander     int ret;
194*817466cbSJens Wiklander     size_t entry_len;
195*817466cbSJens Wiklander     mbedtls_x509_crl_entry *cur_entry = entry;
196*817466cbSJens Wiklander 
197*817466cbSJens Wiklander     if( *p == end )
198*817466cbSJens Wiklander         return( 0 );
199*817466cbSJens Wiklander 
200*817466cbSJens Wiklander     if( ( ret = mbedtls_asn1_get_tag( p, end, &entry_len,
201*817466cbSJens Wiklander             MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 )
202*817466cbSJens Wiklander     {
203*817466cbSJens Wiklander         if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
204*817466cbSJens Wiklander             return( 0 );
205*817466cbSJens Wiklander 
206*817466cbSJens Wiklander         return( ret );
207*817466cbSJens Wiklander     }
208*817466cbSJens Wiklander 
209*817466cbSJens Wiklander     end = *p + entry_len;
210*817466cbSJens Wiklander 
211*817466cbSJens Wiklander     while( *p < end )
212*817466cbSJens Wiklander     {
213*817466cbSJens Wiklander         size_t len2;
214*817466cbSJens Wiklander         const unsigned char *end2;
215*817466cbSJens Wiklander 
216*817466cbSJens Wiklander         if( ( ret = mbedtls_asn1_get_tag( p, end, &len2,
217*817466cbSJens Wiklander                 MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 )
218*817466cbSJens Wiklander         {
219*817466cbSJens Wiklander             return( ret );
220*817466cbSJens Wiklander         }
221*817466cbSJens Wiklander 
222*817466cbSJens Wiklander         cur_entry->raw.tag = **p;
223*817466cbSJens Wiklander         cur_entry->raw.p = *p;
224*817466cbSJens Wiklander         cur_entry->raw.len = len2;
225*817466cbSJens Wiklander         end2 = *p + len2;
226*817466cbSJens Wiklander 
227*817466cbSJens Wiklander         if( ( ret = mbedtls_x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 )
228*817466cbSJens Wiklander             return( ret );
229*817466cbSJens Wiklander 
230*817466cbSJens Wiklander         if( ( ret = mbedtls_x509_get_time( p, end2,
231*817466cbSJens Wiklander                                    &cur_entry->revocation_date ) ) != 0 )
232*817466cbSJens Wiklander             return( ret );
233*817466cbSJens Wiklander 
234*817466cbSJens Wiklander         if( ( ret = x509_get_crl_entry_ext( p, end2,
235*817466cbSJens Wiklander                                             &cur_entry->entry_ext ) ) != 0 )
236*817466cbSJens Wiklander             return( ret );
237*817466cbSJens Wiklander 
238*817466cbSJens Wiklander         if( *p < end )
239*817466cbSJens Wiklander         {
240*817466cbSJens Wiklander             cur_entry->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl_entry ) );
241*817466cbSJens Wiklander 
242*817466cbSJens Wiklander             if( cur_entry->next == NULL )
243*817466cbSJens Wiklander                 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
244*817466cbSJens Wiklander 
245*817466cbSJens Wiklander             cur_entry = cur_entry->next;
246*817466cbSJens Wiklander         }
247*817466cbSJens Wiklander     }
248*817466cbSJens Wiklander 
249*817466cbSJens Wiklander     return( 0 );
250*817466cbSJens Wiklander }
251*817466cbSJens Wiklander 
252*817466cbSJens Wiklander /*
253*817466cbSJens Wiklander  * Parse one  CRLs in DER format and append it to the chained list
254*817466cbSJens Wiklander  */
255*817466cbSJens Wiklander int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain,
256*817466cbSJens Wiklander                         const unsigned char *buf, size_t buflen )
257*817466cbSJens Wiklander {
258*817466cbSJens Wiklander     int ret;
259*817466cbSJens Wiklander     size_t len;
260*817466cbSJens Wiklander     unsigned char *p, *end;
261*817466cbSJens Wiklander     mbedtls_x509_buf sig_params1, sig_params2, sig_oid2;
262*817466cbSJens Wiklander     mbedtls_x509_crl *crl = chain;
263*817466cbSJens Wiklander 
264*817466cbSJens Wiklander     /*
265*817466cbSJens Wiklander      * Check for valid input
266*817466cbSJens Wiklander      */
267*817466cbSJens Wiklander     if( crl == NULL || buf == NULL )
268*817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
269*817466cbSJens Wiklander 
270*817466cbSJens Wiklander     memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) );
271*817466cbSJens Wiklander     memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) );
272*817466cbSJens Wiklander     memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) );
273*817466cbSJens Wiklander 
274*817466cbSJens Wiklander     /*
275*817466cbSJens Wiklander      * Add new CRL on the end of the chain if needed.
276*817466cbSJens Wiklander      */
277*817466cbSJens Wiklander     while( crl->version != 0 && crl->next != NULL )
278*817466cbSJens Wiklander         crl = crl->next;
279*817466cbSJens Wiklander 
280*817466cbSJens Wiklander     if( crl->version != 0 && crl->next == NULL )
281*817466cbSJens Wiklander     {
282*817466cbSJens Wiklander         crl->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl ) );
283*817466cbSJens Wiklander 
284*817466cbSJens Wiklander         if( crl->next == NULL )
285*817466cbSJens Wiklander         {
286*817466cbSJens Wiklander             mbedtls_x509_crl_free( crl );
287*817466cbSJens Wiklander             return( MBEDTLS_ERR_X509_ALLOC_FAILED );
288*817466cbSJens Wiklander         }
289*817466cbSJens Wiklander 
290*817466cbSJens Wiklander         mbedtls_x509_crl_init( crl->next );
291*817466cbSJens Wiklander         crl = crl->next;
292*817466cbSJens Wiklander     }
293*817466cbSJens Wiklander 
294*817466cbSJens Wiklander     /*
295*817466cbSJens Wiklander      * Copy raw DER-encoded CRL
296*817466cbSJens Wiklander      */
297*817466cbSJens Wiklander     if( ( p = mbedtls_calloc( 1, buflen ) ) == NULL )
298*817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_ALLOC_FAILED );
299*817466cbSJens Wiklander 
300*817466cbSJens Wiklander     memcpy( p, buf, buflen );
301*817466cbSJens Wiklander 
302*817466cbSJens Wiklander     crl->raw.p = p;
303*817466cbSJens Wiklander     crl->raw.len = buflen;
304*817466cbSJens Wiklander 
305*817466cbSJens Wiklander     end = p + buflen;
306*817466cbSJens Wiklander 
307*817466cbSJens Wiklander     /*
308*817466cbSJens Wiklander      * CertificateList  ::=  SEQUENCE  {
309*817466cbSJens Wiklander      *      tbsCertList          TBSCertList,
310*817466cbSJens Wiklander      *      signatureAlgorithm   AlgorithmIdentifier,
311*817466cbSJens Wiklander      *      signatureValue       BIT STRING  }
312*817466cbSJens Wiklander      */
313*817466cbSJens Wiklander     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
314*817466cbSJens Wiklander             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
315*817466cbSJens Wiklander     {
316*817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
317*817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_INVALID_FORMAT );
318*817466cbSJens Wiklander     }
319*817466cbSJens Wiklander 
320*817466cbSJens Wiklander     if( len != (size_t) ( end - p ) )
321*817466cbSJens Wiklander     {
322*817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
323*817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_INVALID_FORMAT +
324*817466cbSJens Wiklander                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
325*817466cbSJens Wiklander     }
326*817466cbSJens Wiklander 
327*817466cbSJens Wiklander     /*
328*817466cbSJens Wiklander      * TBSCertList  ::=  SEQUENCE  {
329*817466cbSJens Wiklander      */
330*817466cbSJens Wiklander     crl->tbs.p = p;
331*817466cbSJens Wiklander 
332*817466cbSJens Wiklander     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
333*817466cbSJens Wiklander             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
334*817466cbSJens Wiklander     {
335*817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
336*817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
337*817466cbSJens Wiklander     }
338*817466cbSJens Wiklander 
339*817466cbSJens Wiklander     end = p + len;
340*817466cbSJens Wiklander     crl->tbs.len = end - crl->tbs.p;
341*817466cbSJens Wiklander 
342*817466cbSJens Wiklander     /*
343*817466cbSJens Wiklander      * Version  ::=  INTEGER  OPTIONAL {  v1(0), v2(1)  }
344*817466cbSJens Wiklander      *               -- if present, MUST be v2
345*817466cbSJens Wiklander      *
346*817466cbSJens Wiklander      * signature            AlgorithmIdentifier
347*817466cbSJens Wiklander      */
348*817466cbSJens Wiklander     if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 ||
349*817466cbSJens Wiklander         ( ret = mbedtls_x509_get_alg( &p, end, &crl->sig_oid, &sig_params1 ) ) != 0 )
350*817466cbSJens Wiklander     {
351*817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
352*817466cbSJens Wiklander         return( ret );
353*817466cbSJens Wiklander     }
354*817466cbSJens Wiklander 
355*817466cbSJens Wiklander     if( crl->version < 0 || crl->version > 1 )
356*817466cbSJens Wiklander     {
357*817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
358*817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_UNKNOWN_VERSION );
359*817466cbSJens Wiklander     }
360*817466cbSJens Wiklander 
361*817466cbSJens Wiklander     crl->version++;
362*817466cbSJens Wiklander 
363*817466cbSJens Wiklander     if( ( ret = mbedtls_x509_get_sig_alg( &crl->sig_oid, &sig_params1,
364*817466cbSJens Wiklander                                   &crl->sig_md, &crl->sig_pk,
365*817466cbSJens Wiklander                                   &crl->sig_opts ) ) != 0 )
366*817466cbSJens Wiklander     {
367*817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
368*817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG );
369*817466cbSJens Wiklander     }
370*817466cbSJens Wiklander 
371*817466cbSJens Wiklander     /*
372*817466cbSJens Wiklander      * issuer               Name
373*817466cbSJens Wiklander      */
374*817466cbSJens Wiklander     crl->issuer_raw.p = p;
375*817466cbSJens Wiklander 
376*817466cbSJens Wiklander     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
377*817466cbSJens Wiklander             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
378*817466cbSJens Wiklander     {
379*817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
380*817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
381*817466cbSJens Wiklander     }
382*817466cbSJens Wiklander 
383*817466cbSJens Wiklander     if( ( ret = mbedtls_x509_get_name( &p, p + len, &crl->issuer ) ) != 0 )
384*817466cbSJens Wiklander     {
385*817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
386*817466cbSJens Wiklander         return( ret );
387*817466cbSJens Wiklander     }
388*817466cbSJens Wiklander 
389*817466cbSJens Wiklander     crl->issuer_raw.len = p - crl->issuer_raw.p;
390*817466cbSJens Wiklander 
391*817466cbSJens Wiklander     /*
392*817466cbSJens Wiklander      * thisUpdate          Time
393*817466cbSJens Wiklander      * nextUpdate          Time OPTIONAL
394*817466cbSJens Wiklander      */
395*817466cbSJens Wiklander     if( ( ret = mbedtls_x509_get_time( &p, end, &crl->this_update ) ) != 0 )
396*817466cbSJens Wiklander     {
397*817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
398*817466cbSJens Wiklander         return( ret );
399*817466cbSJens Wiklander     }
400*817466cbSJens Wiklander 
401*817466cbSJens Wiklander     if( ( ret = mbedtls_x509_get_time( &p, end, &crl->next_update ) ) != 0 )
402*817466cbSJens Wiklander     {
403*817466cbSJens Wiklander         if( ret != ( MBEDTLS_ERR_X509_INVALID_DATE +
404*817466cbSJens Wiklander                         MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) &&
405*817466cbSJens Wiklander             ret != ( MBEDTLS_ERR_X509_INVALID_DATE +
406*817466cbSJens Wiklander                         MBEDTLS_ERR_ASN1_OUT_OF_DATA ) )
407*817466cbSJens Wiklander         {
408*817466cbSJens Wiklander             mbedtls_x509_crl_free( crl );
409*817466cbSJens Wiklander             return( ret );
410*817466cbSJens Wiklander         }
411*817466cbSJens Wiklander     }
412*817466cbSJens Wiklander 
413*817466cbSJens Wiklander     /*
414*817466cbSJens Wiklander      * revokedCertificates    SEQUENCE OF SEQUENCE   {
415*817466cbSJens Wiklander      *      userCertificate        CertificateSerialNumber,
416*817466cbSJens Wiklander      *      revocationDate         Time,
417*817466cbSJens Wiklander      *      crlEntryExtensions     Extensions OPTIONAL
418*817466cbSJens Wiklander      *                                   -- if present, MUST be v2
419*817466cbSJens Wiklander      *                        } OPTIONAL
420*817466cbSJens Wiklander      */
421*817466cbSJens Wiklander     if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 )
422*817466cbSJens Wiklander     {
423*817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
424*817466cbSJens Wiklander         return( ret );
425*817466cbSJens Wiklander     }
426*817466cbSJens Wiklander 
427*817466cbSJens Wiklander     /*
428*817466cbSJens Wiklander      * crlExtensions          EXPLICIT Extensions OPTIONAL
429*817466cbSJens Wiklander      *                              -- if present, MUST be v2
430*817466cbSJens Wiklander      */
431*817466cbSJens Wiklander     if( crl->version == 2 )
432*817466cbSJens Wiklander     {
433*817466cbSJens Wiklander         ret = x509_get_crl_ext( &p, end, &crl->crl_ext );
434*817466cbSJens Wiklander 
435*817466cbSJens Wiklander         if( ret != 0 )
436*817466cbSJens Wiklander         {
437*817466cbSJens Wiklander             mbedtls_x509_crl_free( crl );
438*817466cbSJens Wiklander             return( ret );
439*817466cbSJens Wiklander         }
440*817466cbSJens Wiklander     }
441*817466cbSJens Wiklander 
442*817466cbSJens Wiklander     if( p != end )
443*817466cbSJens Wiklander     {
444*817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
445*817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_INVALID_FORMAT +
446*817466cbSJens Wiklander                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
447*817466cbSJens Wiklander     }
448*817466cbSJens Wiklander 
449*817466cbSJens Wiklander     end = crl->raw.p + crl->raw.len;
450*817466cbSJens Wiklander 
451*817466cbSJens Wiklander     /*
452*817466cbSJens Wiklander      *  signatureAlgorithm   AlgorithmIdentifier,
453*817466cbSJens Wiklander      *  signatureValue       BIT STRING
454*817466cbSJens Wiklander      */
455*817466cbSJens Wiklander     if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 )
456*817466cbSJens Wiklander     {
457*817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
458*817466cbSJens Wiklander         return( ret );
459*817466cbSJens Wiklander     }
460*817466cbSJens Wiklander 
461*817466cbSJens Wiklander     if( crl->sig_oid.len != sig_oid2.len ||
462*817466cbSJens Wiklander         memcmp( crl->sig_oid.p, sig_oid2.p, crl->sig_oid.len ) != 0 ||
463*817466cbSJens Wiklander         sig_params1.len != sig_params2.len ||
464*817466cbSJens Wiklander         ( sig_params1.len != 0 &&
465*817466cbSJens Wiklander           memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) )
466*817466cbSJens Wiklander     {
467*817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
468*817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_SIG_MISMATCH );
469*817466cbSJens Wiklander     }
470*817466cbSJens Wiklander 
471*817466cbSJens Wiklander     if( ( ret = mbedtls_x509_get_sig( &p, end, &crl->sig ) ) != 0 )
472*817466cbSJens Wiklander     {
473*817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
474*817466cbSJens Wiklander         return( ret );
475*817466cbSJens Wiklander     }
476*817466cbSJens Wiklander 
477*817466cbSJens Wiklander     if( p != end )
478*817466cbSJens Wiklander     {
479*817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
480*817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_INVALID_FORMAT +
481*817466cbSJens Wiklander                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
482*817466cbSJens Wiklander     }
483*817466cbSJens Wiklander 
484*817466cbSJens Wiklander     return( 0 );
485*817466cbSJens Wiklander }
486*817466cbSJens Wiklander 
487*817466cbSJens Wiklander /*
488*817466cbSJens Wiklander  * Parse one or more CRLs and add them to the chained list
489*817466cbSJens Wiklander  */
490*817466cbSJens Wiklander int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen )
491*817466cbSJens Wiklander {
492*817466cbSJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C)
493*817466cbSJens Wiklander     int ret;
494*817466cbSJens Wiklander     size_t use_len;
495*817466cbSJens Wiklander     mbedtls_pem_context pem;
496*817466cbSJens Wiklander     int is_pem = 0;
497*817466cbSJens Wiklander 
498*817466cbSJens Wiklander     if( chain == NULL || buf == NULL )
499*817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
500*817466cbSJens Wiklander 
501*817466cbSJens Wiklander     do
502*817466cbSJens Wiklander     {
503*817466cbSJens Wiklander         mbedtls_pem_init( &pem );
504*817466cbSJens Wiklander 
505*817466cbSJens Wiklander         // Avoid calling mbedtls_pem_read_buffer() on non-null-terminated
506*817466cbSJens Wiklander         // string
507*817466cbSJens Wiklander         if( buflen == 0 || buf[buflen - 1] != '\0' )
508*817466cbSJens Wiklander             ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
509*817466cbSJens Wiklander         else
510*817466cbSJens Wiklander             ret = mbedtls_pem_read_buffer( &pem,
511*817466cbSJens Wiklander                                            "-----BEGIN X509 CRL-----",
512*817466cbSJens Wiklander                                            "-----END X509 CRL-----",
513*817466cbSJens Wiklander                                             buf, NULL, 0, &use_len );
514*817466cbSJens Wiklander 
515*817466cbSJens Wiklander         if( ret == 0 )
516*817466cbSJens Wiklander         {
517*817466cbSJens Wiklander             /*
518*817466cbSJens Wiklander              * Was PEM encoded
519*817466cbSJens Wiklander              */
520*817466cbSJens Wiklander             is_pem = 1;
521*817466cbSJens Wiklander 
522*817466cbSJens Wiklander             buflen -= use_len;
523*817466cbSJens Wiklander             buf += use_len;
524*817466cbSJens Wiklander 
525*817466cbSJens Wiklander             if( ( ret = mbedtls_x509_crl_parse_der( chain,
526*817466cbSJens Wiklander                                             pem.buf, pem.buflen ) ) != 0 )
527*817466cbSJens Wiklander             {
528*817466cbSJens Wiklander                 mbedtls_pem_free( &pem );
529*817466cbSJens Wiklander                 return( ret );
530*817466cbSJens Wiklander             }
531*817466cbSJens Wiklander         }
532*817466cbSJens Wiklander         else if( is_pem )
533*817466cbSJens Wiklander         {
534*817466cbSJens Wiklander             mbedtls_pem_free( &pem );
535*817466cbSJens Wiklander             return( ret );
536*817466cbSJens Wiklander         }
537*817466cbSJens Wiklander 
538*817466cbSJens Wiklander         mbedtls_pem_free( &pem );
539*817466cbSJens Wiklander     }
540*817466cbSJens Wiklander     /* In the PEM case, buflen is 1 at the end, for the terminated NULL byte.
541*817466cbSJens Wiklander      * And a valid CRL cannot be less than 1 byte anyway. */
542*817466cbSJens Wiklander     while( is_pem && buflen > 1 );
543*817466cbSJens Wiklander 
544*817466cbSJens Wiklander     if( is_pem )
545*817466cbSJens Wiklander         return( 0 );
546*817466cbSJens Wiklander     else
547*817466cbSJens Wiklander #endif /* MBEDTLS_PEM_PARSE_C */
548*817466cbSJens Wiklander         return( mbedtls_x509_crl_parse_der( chain, buf, buflen ) );
549*817466cbSJens Wiklander }
550*817466cbSJens Wiklander 
551*817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO)
552*817466cbSJens Wiklander /*
553*817466cbSJens Wiklander  * Load one or more CRLs and add them to the chained list
554*817466cbSJens Wiklander  */
555*817466cbSJens Wiklander int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path )
556*817466cbSJens Wiklander {
557*817466cbSJens Wiklander     int ret;
558*817466cbSJens Wiklander     size_t n;
559*817466cbSJens Wiklander     unsigned char *buf;
560*817466cbSJens Wiklander 
561*817466cbSJens Wiklander     if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 )
562*817466cbSJens Wiklander         return( ret );
563*817466cbSJens Wiklander 
564*817466cbSJens Wiklander     ret = mbedtls_x509_crl_parse( chain, buf, n );
565*817466cbSJens Wiklander 
566*817466cbSJens Wiklander     mbedtls_zeroize( buf, n );
567*817466cbSJens Wiklander     mbedtls_free( buf );
568*817466cbSJens Wiklander 
569*817466cbSJens Wiklander     return( ret );
570*817466cbSJens Wiklander }
571*817466cbSJens Wiklander #endif /* MBEDTLS_FS_IO */
572*817466cbSJens Wiklander 
573*817466cbSJens Wiklander /*
574*817466cbSJens Wiklander  * Return an informational string about the certificate.
575*817466cbSJens Wiklander  */
576*817466cbSJens Wiklander #define BEFORE_COLON    14
577*817466cbSJens Wiklander #define BC              "14"
578*817466cbSJens Wiklander /*
579*817466cbSJens Wiklander  * Return an informational string about the CRL.
580*817466cbSJens Wiklander  */
581*817466cbSJens Wiklander int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix,
582*817466cbSJens Wiklander                    const mbedtls_x509_crl *crl )
583*817466cbSJens Wiklander {
584*817466cbSJens Wiklander     int ret;
585*817466cbSJens Wiklander     size_t n;
586*817466cbSJens Wiklander     char *p;
587*817466cbSJens Wiklander     const mbedtls_x509_crl_entry *entry;
588*817466cbSJens Wiklander 
589*817466cbSJens Wiklander     p = buf;
590*817466cbSJens Wiklander     n = size;
591*817466cbSJens Wiklander 
592*817466cbSJens Wiklander     ret = mbedtls_snprintf( p, n, "%sCRL version   : %d",
593*817466cbSJens Wiklander                                prefix, crl->version );
594*817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
595*817466cbSJens Wiklander 
596*817466cbSJens Wiklander     ret = mbedtls_snprintf( p, n, "\n%sissuer name   : ", prefix );
597*817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
598*817466cbSJens Wiklander     ret = mbedtls_x509_dn_gets( p, n, &crl->issuer );
599*817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
600*817466cbSJens Wiklander 
601*817466cbSJens Wiklander     ret = mbedtls_snprintf( p, n, "\n%sthis update   : " \
602*817466cbSJens Wiklander                    "%04d-%02d-%02d %02d:%02d:%02d", prefix,
603*817466cbSJens Wiklander                    crl->this_update.year, crl->this_update.mon,
604*817466cbSJens Wiklander                    crl->this_update.day,  crl->this_update.hour,
605*817466cbSJens Wiklander                    crl->this_update.min,  crl->this_update.sec );
606*817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
607*817466cbSJens Wiklander 
608*817466cbSJens Wiklander     ret = mbedtls_snprintf( p, n, "\n%snext update   : " \
609*817466cbSJens Wiklander                    "%04d-%02d-%02d %02d:%02d:%02d", prefix,
610*817466cbSJens Wiklander                    crl->next_update.year, crl->next_update.mon,
611*817466cbSJens Wiklander                    crl->next_update.day,  crl->next_update.hour,
612*817466cbSJens Wiklander                    crl->next_update.min,  crl->next_update.sec );
613*817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
614*817466cbSJens Wiklander 
615*817466cbSJens Wiklander     entry = &crl->entry;
616*817466cbSJens Wiklander 
617*817466cbSJens Wiklander     ret = mbedtls_snprintf( p, n, "\n%sRevoked certificates:",
618*817466cbSJens Wiklander                                prefix );
619*817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
620*817466cbSJens Wiklander 
621*817466cbSJens Wiklander     while( entry != NULL && entry->raw.len != 0 )
622*817466cbSJens Wiklander     {
623*817466cbSJens Wiklander         ret = mbedtls_snprintf( p, n, "\n%sserial number: ",
624*817466cbSJens Wiklander                                prefix );
625*817466cbSJens Wiklander         MBEDTLS_X509_SAFE_SNPRINTF;
626*817466cbSJens Wiklander 
627*817466cbSJens Wiklander         ret = mbedtls_x509_serial_gets( p, n, &entry->serial );
628*817466cbSJens Wiklander         MBEDTLS_X509_SAFE_SNPRINTF;
629*817466cbSJens Wiklander 
630*817466cbSJens Wiklander         ret = mbedtls_snprintf( p, n, " revocation date: " \
631*817466cbSJens Wiklander                    "%04d-%02d-%02d %02d:%02d:%02d",
632*817466cbSJens Wiklander                    entry->revocation_date.year, entry->revocation_date.mon,
633*817466cbSJens Wiklander                    entry->revocation_date.day,  entry->revocation_date.hour,
634*817466cbSJens Wiklander                    entry->revocation_date.min,  entry->revocation_date.sec );
635*817466cbSJens Wiklander         MBEDTLS_X509_SAFE_SNPRINTF;
636*817466cbSJens Wiklander 
637*817466cbSJens Wiklander         entry = entry->next;
638*817466cbSJens Wiklander     }
639*817466cbSJens Wiklander 
640*817466cbSJens Wiklander     ret = mbedtls_snprintf( p, n, "\n%ssigned using  : ", prefix );
641*817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
642*817466cbSJens Wiklander 
643*817466cbSJens Wiklander     ret = mbedtls_x509_sig_alg_gets( p, n, &crl->sig_oid, crl->sig_pk, crl->sig_md,
644*817466cbSJens Wiklander                              crl->sig_opts );
645*817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
646*817466cbSJens Wiklander 
647*817466cbSJens Wiklander     ret = mbedtls_snprintf( p, n, "\n" );
648*817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
649*817466cbSJens Wiklander 
650*817466cbSJens Wiklander     return( (int) ( size - n ) );
651*817466cbSJens Wiklander }
652*817466cbSJens Wiklander 
653*817466cbSJens Wiklander /*
654*817466cbSJens Wiklander  * Initialize a CRL chain
655*817466cbSJens Wiklander  */
656*817466cbSJens Wiklander void mbedtls_x509_crl_init( mbedtls_x509_crl *crl )
657*817466cbSJens Wiklander {
658*817466cbSJens Wiklander     memset( crl, 0, sizeof(mbedtls_x509_crl) );
659*817466cbSJens Wiklander }
660*817466cbSJens Wiklander 
661*817466cbSJens Wiklander /*
662*817466cbSJens Wiklander  * Unallocate all CRL data
663*817466cbSJens Wiklander  */
664*817466cbSJens Wiklander void mbedtls_x509_crl_free( mbedtls_x509_crl *crl )
665*817466cbSJens Wiklander {
666*817466cbSJens Wiklander     mbedtls_x509_crl *crl_cur = crl;
667*817466cbSJens Wiklander     mbedtls_x509_crl *crl_prv;
668*817466cbSJens Wiklander     mbedtls_x509_name *name_cur;
669*817466cbSJens Wiklander     mbedtls_x509_name *name_prv;
670*817466cbSJens Wiklander     mbedtls_x509_crl_entry *entry_cur;
671*817466cbSJens Wiklander     mbedtls_x509_crl_entry *entry_prv;
672*817466cbSJens Wiklander 
673*817466cbSJens Wiklander     if( crl == NULL )
674*817466cbSJens Wiklander         return;
675*817466cbSJens Wiklander 
676*817466cbSJens Wiklander     do
677*817466cbSJens Wiklander     {
678*817466cbSJens Wiklander #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
679*817466cbSJens Wiklander         mbedtls_free( crl_cur->sig_opts );
680*817466cbSJens Wiklander #endif
681*817466cbSJens Wiklander 
682*817466cbSJens Wiklander         name_cur = crl_cur->issuer.next;
683*817466cbSJens Wiklander         while( name_cur != NULL )
684*817466cbSJens Wiklander         {
685*817466cbSJens Wiklander             name_prv = name_cur;
686*817466cbSJens Wiklander             name_cur = name_cur->next;
687*817466cbSJens Wiklander             mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
688*817466cbSJens Wiklander             mbedtls_free( name_prv );
689*817466cbSJens Wiklander         }
690*817466cbSJens Wiklander 
691*817466cbSJens Wiklander         entry_cur = crl_cur->entry.next;
692*817466cbSJens Wiklander         while( entry_cur != NULL )
693*817466cbSJens Wiklander         {
694*817466cbSJens Wiklander             entry_prv = entry_cur;
695*817466cbSJens Wiklander             entry_cur = entry_cur->next;
696*817466cbSJens Wiklander             mbedtls_zeroize( entry_prv, sizeof( mbedtls_x509_crl_entry ) );
697*817466cbSJens Wiklander             mbedtls_free( entry_prv );
698*817466cbSJens Wiklander         }
699*817466cbSJens Wiklander 
700*817466cbSJens Wiklander         if( crl_cur->raw.p != NULL )
701*817466cbSJens Wiklander         {
702*817466cbSJens Wiklander             mbedtls_zeroize( crl_cur->raw.p, crl_cur->raw.len );
703*817466cbSJens Wiklander             mbedtls_free( crl_cur->raw.p );
704*817466cbSJens Wiklander         }
705*817466cbSJens Wiklander 
706*817466cbSJens Wiklander         crl_cur = crl_cur->next;
707*817466cbSJens Wiklander     }
708*817466cbSJens Wiklander     while( crl_cur != NULL );
709*817466cbSJens Wiklander 
710*817466cbSJens Wiklander     crl_cur = crl;
711*817466cbSJens Wiklander     do
712*817466cbSJens Wiklander     {
713*817466cbSJens Wiklander         crl_prv = crl_cur;
714*817466cbSJens Wiklander         crl_cur = crl_cur->next;
715*817466cbSJens Wiklander 
716*817466cbSJens Wiklander         mbedtls_zeroize( crl_prv, sizeof( mbedtls_x509_crl ) );
717*817466cbSJens Wiklander         if( crl_prv != crl )
718*817466cbSJens Wiklander             mbedtls_free( crl_prv );
719*817466cbSJens Wiklander     }
720*817466cbSJens Wiklander     while( crl_cur != NULL );
721*817466cbSJens Wiklander }
722*817466cbSJens Wiklander 
723*817466cbSJens Wiklander #endif /* MBEDTLS_X509_CRL_PARSE_C */
724