xref: /optee_os/lib/libmbedtls/mbedtls/library/x509_crl.c (revision c6672fdcd95b9a895eb5b4191f8ba3483a34a442)
1*c6672fdcSEdison Ai // SPDX-License-Identifier: Apache-2.0
2817466cbSJens Wiklander /*
3817466cbSJens Wiklander  *  X.509 Certidicate Revocation List (CRL) parsing
4817466cbSJens Wiklander  *
5817466cbSJens Wiklander  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
6817466cbSJens Wiklander  *
7817466cbSJens Wiklander  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8817466cbSJens Wiklander  *  not use this file except in compliance with the License.
9817466cbSJens Wiklander  *  You may obtain a copy of the License at
10817466cbSJens Wiklander  *
11817466cbSJens Wiklander  *  http://www.apache.org/licenses/LICENSE-2.0
12817466cbSJens Wiklander  *
13817466cbSJens Wiklander  *  Unless required by applicable law or agreed to in writing, software
14817466cbSJens Wiklander  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15817466cbSJens Wiklander  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16817466cbSJens Wiklander  *  See the License for the specific language governing permissions and
17817466cbSJens Wiklander  *  limitations under the License.
18817466cbSJens Wiklander  *
19817466cbSJens Wiklander  *  This file is part of mbed TLS (https://tls.mbed.org)
20817466cbSJens Wiklander  */
21817466cbSJens Wiklander /*
22817466cbSJens Wiklander  *  The ITU-T X.509 standard defines a certificate format for PKI.
23817466cbSJens Wiklander  *
24817466cbSJens Wiklander  *  http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
25817466cbSJens Wiklander  *  http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
26817466cbSJens Wiklander  *  http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
27817466cbSJens Wiklander  *
28817466cbSJens Wiklander  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
29817466cbSJens Wiklander  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
30817466cbSJens Wiklander  */
31817466cbSJens Wiklander 
32817466cbSJens Wiklander #if !defined(MBEDTLS_CONFIG_FILE)
33817466cbSJens Wiklander #include "mbedtls/config.h"
34817466cbSJens Wiklander #else
35817466cbSJens Wiklander #include MBEDTLS_CONFIG_FILE
36817466cbSJens Wiklander #endif
37817466cbSJens Wiklander 
38817466cbSJens Wiklander #if defined(MBEDTLS_X509_CRL_PARSE_C)
39817466cbSJens Wiklander 
40817466cbSJens Wiklander #include "mbedtls/x509_crl.h"
41817466cbSJens Wiklander #include "mbedtls/oid.h"
42817466cbSJens Wiklander 
43817466cbSJens Wiklander #include <string.h>
44817466cbSJens Wiklander 
45817466cbSJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C)
46817466cbSJens Wiklander #include "mbedtls/pem.h"
47817466cbSJens Wiklander #endif
48817466cbSJens Wiklander 
49817466cbSJens Wiklander #if defined(MBEDTLS_PLATFORM_C)
50817466cbSJens Wiklander #include "mbedtls/platform.h"
51817466cbSJens Wiklander #else
52817466cbSJens Wiklander #include <stdlib.h>
53817466cbSJens Wiklander #include <stdio.h>
54817466cbSJens Wiklander #define mbedtls_free       free
55817466cbSJens Wiklander #define mbedtls_calloc    calloc
56817466cbSJens Wiklander #define mbedtls_snprintf   snprintf
57817466cbSJens Wiklander #endif
58817466cbSJens Wiklander 
59817466cbSJens Wiklander #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
60817466cbSJens Wiklander #include <windows.h>
61817466cbSJens Wiklander #else
62817466cbSJens Wiklander #include <time.h>
63817466cbSJens Wiklander #endif
64817466cbSJens Wiklander 
65817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32)
66817466cbSJens Wiklander #include <stdio.h>
67817466cbSJens Wiklander #endif
68817466cbSJens Wiklander 
69817466cbSJens Wiklander /* Implementation that should never be optimized out by the compiler */
70817466cbSJens Wiklander static void mbedtls_zeroize( void *v, size_t n ) {
71817466cbSJens Wiklander     volatile unsigned char *p = v; while( n-- ) *p++ = 0;
72817466cbSJens Wiklander }
73817466cbSJens Wiklander 
74817466cbSJens Wiklander /*
75817466cbSJens Wiklander  *  Version  ::=  INTEGER  {  v1(0), v2(1)  }
76817466cbSJens Wiklander  */
77817466cbSJens Wiklander static int x509_crl_get_version( unsigned char **p,
78817466cbSJens Wiklander                              const unsigned char *end,
79817466cbSJens Wiklander                              int *ver )
80817466cbSJens Wiklander {
81817466cbSJens Wiklander     int ret;
82817466cbSJens Wiklander 
83817466cbSJens Wiklander     if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
84817466cbSJens Wiklander     {
85817466cbSJens Wiklander         if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
86817466cbSJens Wiklander         {
87817466cbSJens Wiklander             *ver = 0;
88817466cbSJens Wiklander             return( 0 );
89817466cbSJens Wiklander         }
90817466cbSJens Wiklander 
91817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_INVALID_VERSION + ret );
92817466cbSJens Wiklander     }
93817466cbSJens Wiklander 
94817466cbSJens Wiklander     return( 0 );
95817466cbSJens Wiklander }
96817466cbSJens Wiklander 
97817466cbSJens Wiklander /*
98817466cbSJens Wiklander  * X.509 CRL v2 extensions (no extensions parsed yet.)
99817466cbSJens Wiklander  */
100817466cbSJens Wiklander static int x509_get_crl_ext( unsigned char **p,
101817466cbSJens Wiklander                              const unsigned char *end,
102817466cbSJens Wiklander                              mbedtls_x509_buf *ext )
103817466cbSJens Wiklander {
104817466cbSJens Wiklander     int ret;
105817466cbSJens Wiklander     size_t len = 0;
106817466cbSJens Wiklander 
107817466cbSJens Wiklander     /* Get explicit tag */
108817466cbSJens Wiklander     if( ( ret = mbedtls_x509_get_ext( p, end, ext, 0) ) != 0 )
109817466cbSJens Wiklander     {
110817466cbSJens Wiklander         if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
111817466cbSJens Wiklander             return( 0 );
112817466cbSJens Wiklander 
113817466cbSJens Wiklander         return( ret );
114817466cbSJens Wiklander     }
115817466cbSJens Wiklander 
116817466cbSJens Wiklander     while( *p < end )
117817466cbSJens Wiklander     {
118817466cbSJens Wiklander         if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
119817466cbSJens Wiklander                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
120817466cbSJens Wiklander             return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
121817466cbSJens Wiklander 
122817466cbSJens Wiklander         *p += len;
123817466cbSJens Wiklander     }
124817466cbSJens Wiklander 
125817466cbSJens Wiklander     if( *p != end )
126817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
127817466cbSJens Wiklander                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
128817466cbSJens Wiklander 
129817466cbSJens Wiklander     return( 0 );
130817466cbSJens Wiklander }
131817466cbSJens Wiklander 
132817466cbSJens Wiklander /*
133817466cbSJens Wiklander  * X.509 CRL v2 entry extensions (no extensions parsed yet.)
134817466cbSJens Wiklander  */
135817466cbSJens Wiklander static int x509_get_crl_entry_ext( unsigned char **p,
136817466cbSJens Wiklander                              const unsigned char *end,
137817466cbSJens Wiklander                              mbedtls_x509_buf *ext )
138817466cbSJens Wiklander {
139817466cbSJens Wiklander     int ret;
140817466cbSJens Wiklander     size_t len = 0;
141817466cbSJens Wiklander 
142817466cbSJens Wiklander     /* OPTIONAL */
143817466cbSJens Wiklander     if( end <= *p )
144817466cbSJens Wiklander         return( 0 );
145817466cbSJens Wiklander 
146817466cbSJens Wiklander     ext->tag = **p;
147817466cbSJens Wiklander     ext->p = *p;
148817466cbSJens Wiklander 
149817466cbSJens Wiklander     /*
150817466cbSJens Wiklander      * Get CRL-entry extension sequence header
151817466cbSJens Wiklander      * crlEntryExtensions      Extensions OPTIONAL  -- if present, MUST be v2
152817466cbSJens Wiklander      */
153817466cbSJens Wiklander     if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len,
154817466cbSJens Wiklander             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
155817466cbSJens Wiklander     {
156817466cbSJens Wiklander         if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
157817466cbSJens Wiklander         {
158817466cbSJens Wiklander             ext->p = NULL;
159817466cbSJens Wiklander             return( 0 );
160817466cbSJens Wiklander         }
161817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
162817466cbSJens Wiklander     }
163817466cbSJens Wiklander 
164817466cbSJens Wiklander     end = *p + ext->len;
165817466cbSJens Wiklander 
166817466cbSJens Wiklander     if( end != *p + ext->len )
167817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
168817466cbSJens Wiklander                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
169817466cbSJens Wiklander 
170817466cbSJens Wiklander     while( *p < end )
171817466cbSJens Wiklander     {
172817466cbSJens Wiklander         if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
173817466cbSJens Wiklander                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
174817466cbSJens Wiklander             return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
175817466cbSJens Wiklander 
176817466cbSJens Wiklander         *p += len;
177817466cbSJens Wiklander     }
178817466cbSJens Wiklander 
179817466cbSJens Wiklander     if( *p != end )
180817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
181817466cbSJens Wiklander                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
182817466cbSJens Wiklander 
183817466cbSJens Wiklander     return( 0 );
184817466cbSJens Wiklander }
185817466cbSJens Wiklander 
186817466cbSJens Wiklander /*
187817466cbSJens Wiklander  * X.509 CRL Entries
188817466cbSJens Wiklander  */
189817466cbSJens Wiklander static int x509_get_entries( unsigned char **p,
190817466cbSJens Wiklander                              const unsigned char *end,
191817466cbSJens Wiklander                              mbedtls_x509_crl_entry *entry )
192817466cbSJens Wiklander {
193817466cbSJens Wiklander     int ret;
194817466cbSJens Wiklander     size_t entry_len;
195817466cbSJens Wiklander     mbedtls_x509_crl_entry *cur_entry = entry;
196817466cbSJens Wiklander 
197817466cbSJens Wiklander     if( *p == end )
198817466cbSJens Wiklander         return( 0 );
199817466cbSJens Wiklander 
200817466cbSJens Wiklander     if( ( ret = mbedtls_asn1_get_tag( p, end, &entry_len,
201817466cbSJens Wiklander             MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 )
202817466cbSJens Wiklander     {
203817466cbSJens Wiklander         if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
204817466cbSJens Wiklander             return( 0 );
205817466cbSJens Wiklander 
206817466cbSJens Wiklander         return( ret );
207817466cbSJens Wiklander     }
208817466cbSJens Wiklander 
209817466cbSJens Wiklander     end = *p + entry_len;
210817466cbSJens Wiklander 
211817466cbSJens Wiklander     while( *p < end )
212817466cbSJens Wiklander     {
213817466cbSJens Wiklander         size_t len2;
214817466cbSJens Wiklander         const unsigned char *end2;
215817466cbSJens Wiklander 
216817466cbSJens Wiklander         if( ( ret = mbedtls_asn1_get_tag( p, end, &len2,
217817466cbSJens Wiklander                 MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 )
218817466cbSJens Wiklander         {
219817466cbSJens Wiklander             return( ret );
220817466cbSJens Wiklander         }
221817466cbSJens Wiklander 
222817466cbSJens Wiklander         cur_entry->raw.tag = **p;
223817466cbSJens Wiklander         cur_entry->raw.p = *p;
224817466cbSJens Wiklander         cur_entry->raw.len = len2;
225817466cbSJens Wiklander         end2 = *p + len2;
226817466cbSJens Wiklander 
227817466cbSJens Wiklander         if( ( ret = mbedtls_x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 )
228817466cbSJens Wiklander             return( ret );
229817466cbSJens Wiklander 
230817466cbSJens Wiklander         if( ( ret = mbedtls_x509_get_time( p, end2,
231817466cbSJens Wiklander                                    &cur_entry->revocation_date ) ) != 0 )
232817466cbSJens Wiklander             return( ret );
233817466cbSJens Wiklander 
234817466cbSJens Wiklander         if( ( ret = x509_get_crl_entry_ext( p, end2,
235817466cbSJens Wiklander                                             &cur_entry->entry_ext ) ) != 0 )
236817466cbSJens Wiklander             return( ret );
237817466cbSJens Wiklander 
238817466cbSJens Wiklander         if( *p < end )
239817466cbSJens Wiklander         {
240817466cbSJens Wiklander             cur_entry->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl_entry ) );
241817466cbSJens Wiklander 
242817466cbSJens Wiklander             if( cur_entry->next == NULL )
243817466cbSJens Wiklander                 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
244817466cbSJens Wiklander 
245817466cbSJens Wiklander             cur_entry = cur_entry->next;
246817466cbSJens Wiklander         }
247817466cbSJens Wiklander     }
248817466cbSJens Wiklander 
249817466cbSJens Wiklander     return( 0 );
250817466cbSJens Wiklander }
251817466cbSJens Wiklander 
252817466cbSJens Wiklander /*
253817466cbSJens Wiklander  * Parse one  CRLs in DER format and append it to the chained list
254817466cbSJens Wiklander  */
255817466cbSJens Wiklander int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain,
256817466cbSJens Wiklander                         const unsigned char *buf, size_t buflen )
257817466cbSJens Wiklander {
258817466cbSJens Wiklander     int ret;
259817466cbSJens Wiklander     size_t len;
260817466cbSJens Wiklander     unsigned char *p, *end;
261817466cbSJens Wiklander     mbedtls_x509_buf sig_params1, sig_params2, sig_oid2;
262817466cbSJens Wiklander     mbedtls_x509_crl *crl = chain;
263817466cbSJens Wiklander 
264817466cbSJens Wiklander     /*
265817466cbSJens Wiklander      * Check for valid input
266817466cbSJens Wiklander      */
267817466cbSJens Wiklander     if( crl == NULL || buf == NULL )
268817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
269817466cbSJens Wiklander 
270817466cbSJens Wiklander     memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) );
271817466cbSJens Wiklander     memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) );
272817466cbSJens Wiklander     memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) );
273817466cbSJens Wiklander 
274817466cbSJens Wiklander     /*
275817466cbSJens Wiklander      * Add new CRL on the end of the chain if needed.
276817466cbSJens Wiklander      */
277817466cbSJens Wiklander     while( crl->version != 0 && crl->next != NULL )
278817466cbSJens Wiklander         crl = crl->next;
279817466cbSJens Wiklander 
280817466cbSJens Wiklander     if( crl->version != 0 && crl->next == NULL )
281817466cbSJens Wiklander     {
282817466cbSJens Wiklander         crl->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl ) );
283817466cbSJens Wiklander 
284817466cbSJens Wiklander         if( crl->next == NULL )
285817466cbSJens Wiklander         {
286817466cbSJens Wiklander             mbedtls_x509_crl_free( crl );
287817466cbSJens Wiklander             return( MBEDTLS_ERR_X509_ALLOC_FAILED );
288817466cbSJens Wiklander         }
289817466cbSJens Wiklander 
290817466cbSJens Wiklander         mbedtls_x509_crl_init( crl->next );
291817466cbSJens Wiklander         crl = crl->next;
292817466cbSJens Wiklander     }
293817466cbSJens Wiklander 
294817466cbSJens Wiklander     /*
295817466cbSJens Wiklander      * Copy raw DER-encoded CRL
296817466cbSJens Wiklander      */
297817466cbSJens Wiklander     if( ( p = mbedtls_calloc( 1, buflen ) ) == NULL )
298817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_ALLOC_FAILED );
299817466cbSJens Wiklander 
300817466cbSJens Wiklander     memcpy( p, buf, buflen );
301817466cbSJens Wiklander 
302817466cbSJens Wiklander     crl->raw.p = p;
303817466cbSJens Wiklander     crl->raw.len = buflen;
304817466cbSJens Wiklander 
305817466cbSJens Wiklander     end = p + buflen;
306817466cbSJens Wiklander 
307817466cbSJens Wiklander     /*
308817466cbSJens Wiklander      * CertificateList  ::=  SEQUENCE  {
309817466cbSJens Wiklander      *      tbsCertList          TBSCertList,
310817466cbSJens Wiklander      *      signatureAlgorithm   AlgorithmIdentifier,
311817466cbSJens Wiklander      *      signatureValue       BIT STRING  }
312817466cbSJens Wiklander      */
313817466cbSJens Wiklander     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
314817466cbSJens Wiklander             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
315817466cbSJens Wiklander     {
316817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
317817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_INVALID_FORMAT );
318817466cbSJens Wiklander     }
319817466cbSJens Wiklander 
320817466cbSJens Wiklander     if( len != (size_t) ( end - p ) )
321817466cbSJens Wiklander     {
322817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
323817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_INVALID_FORMAT +
324817466cbSJens Wiklander                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
325817466cbSJens Wiklander     }
326817466cbSJens Wiklander 
327817466cbSJens Wiklander     /*
328817466cbSJens Wiklander      * TBSCertList  ::=  SEQUENCE  {
329817466cbSJens Wiklander      */
330817466cbSJens Wiklander     crl->tbs.p = p;
331817466cbSJens Wiklander 
332817466cbSJens Wiklander     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
333817466cbSJens Wiklander             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
334817466cbSJens Wiklander     {
335817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
336817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
337817466cbSJens Wiklander     }
338817466cbSJens Wiklander 
339817466cbSJens Wiklander     end = p + len;
340817466cbSJens Wiklander     crl->tbs.len = end - crl->tbs.p;
341817466cbSJens Wiklander 
342817466cbSJens Wiklander     /*
343817466cbSJens Wiklander      * Version  ::=  INTEGER  OPTIONAL {  v1(0), v2(1)  }
344817466cbSJens Wiklander      *               -- if present, MUST be v2
345817466cbSJens Wiklander      *
346817466cbSJens Wiklander      * signature            AlgorithmIdentifier
347817466cbSJens Wiklander      */
348817466cbSJens Wiklander     if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 ||
349817466cbSJens Wiklander         ( ret = mbedtls_x509_get_alg( &p, end, &crl->sig_oid, &sig_params1 ) ) != 0 )
350817466cbSJens Wiklander     {
351817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
352817466cbSJens Wiklander         return( ret );
353817466cbSJens Wiklander     }
354817466cbSJens Wiklander 
355817466cbSJens Wiklander     if( crl->version < 0 || crl->version > 1 )
356817466cbSJens Wiklander     {
357817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
358817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_UNKNOWN_VERSION );
359817466cbSJens Wiklander     }
360817466cbSJens Wiklander 
361817466cbSJens Wiklander     crl->version++;
362817466cbSJens Wiklander 
363817466cbSJens Wiklander     if( ( ret = mbedtls_x509_get_sig_alg( &crl->sig_oid, &sig_params1,
364817466cbSJens Wiklander                                   &crl->sig_md, &crl->sig_pk,
365817466cbSJens Wiklander                                   &crl->sig_opts ) ) != 0 )
366817466cbSJens Wiklander     {
367817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
368817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG );
369817466cbSJens Wiklander     }
370817466cbSJens Wiklander 
371817466cbSJens Wiklander     /*
372817466cbSJens Wiklander      * issuer               Name
373817466cbSJens Wiklander      */
374817466cbSJens Wiklander     crl->issuer_raw.p = p;
375817466cbSJens Wiklander 
376817466cbSJens Wiklander     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
377817466cbSJens Wiklander             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
378817466cbSJens Wiklander     {
379817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
380817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
381817466cbSJens Wiklander     }
382817466cbSJens Wiklander 
383817466cbSJens Wiklander     if( ( ret = mbedtls_x509_get_name( &p, p + len, &crl->issuer ) ) != 0 )
384817466cbSJens Wiklander     {
385817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
386817466cbSJens Wiklander         return( ret );
387817466cbSJens Wiklander     }
388817466cbSJens Wiklander 
389817466cbSJens Wiklander     crl->issuer_raw.len = p - crl->issuer_raw.p;
390817466cbSJens Wiklander 
391817466cbSJens Wiklander     /*
392817466cbSJens Wiklander      * thisUpdate          Time
393817466cbSJens Wiklander      * nextUpdate          Time OPTIONAL
394817466cbSJens Wiklander      */
395817466cbSJens Wiklander     if( ( ret = mbedtls_x509_get_time( &p, end, &crl->this_update ) ) != 0 )
396817466cbSJens Wiklander     {
397817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
398817466cbSJens Wiklander         return( ret );
399817466cbSJens Wiklander     }
400817466cbSJens Wiklander 
401817466cbSJens Wiklander     if( ( ret = mbedtls_x509_get_time( &p, end, &crl->next_update ) ) != 0 )
402817466cbSJens Wiklander     {
403817466cbSJens Wiklander         if( ret != ( MBEDTLS_ERR_X509_INVALID_DATE +
404817466cbSJens Wiklander                         MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) &&
405817466cbSJens Wiklander             ret != ( MBEDTLS_ERR_X509_INVALID_DATE +
406817466cbSJens Wiklander                         MBEDTLS_ERR_ASN1_OUT_OF_DATA ) )
407817466cbSJens Wiklander         {
408817466cbSJens Wiklander             mbedtls_x509_crl_free( crl );
409817466cbSJens Wiklander             return( ret );
410817466cbSJens Wiklander         }
411817466cbSJens Wiklander     }
412817466cbSJens Wiklander 
413817466cbSJens Wiklander     /*
414817466cbSJens Wiklander      * revokedCertificates    SEQUENCE OF SEQUENCE   {
415817466cbSJens Wiklander      *      userCertificate        CertificateSerialNumber,
416817466cbSJens Wiklander      *      revocationDate         Time,
417817466cbSJens Wiklander      *      crlEntryExtensions     Extensions OPTIONAL
418817466cbSJens Wiklander      *                                   -- if present, MUST be v2
419817466cbSJens Wiklander      *                        } OPTIONAL
420817466cbSJens Wiklander      */
421817466cbSJens Wiklander     if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 )
422817466cbSJens Wiklander     {
423817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
424817466cbSJens Wiklander         return( ret );
425817466cbSJens Wiklander     }
426817466cbSJens Wiklander 
427817466cbSJens Wiklander     /*
428817466cbSJens Wiklander      * crlExtensions          EXPLICIT Extensions OPTIONAL
429817466cbSJens Wiklander      *                              -- if present, MUST be v2
430817466cbSJens Wiklander      */
431817466cbSJens Wiklander     if( crl->version == 2 )
432817466cbSJens Wiklander     {
433817466cbSJens Wiklander         ret = x509_get_crl_ext( &p, end, &crl->crl_ext );
434817466cbSJens Wiklander 
435817466cbSJens Wiklander         if( ret != 0 )
436817466cbSJens Wiklander         {
437817466cbSJens Wiklander             mbedtls_x509_crl_free( crl );
438817466cbSJens Wiklander             return( ret );
439817466cbSJens Wiklander         }
440817466cbSJens Wiklander     }
441817466cbSJens Wiklander 
442817466cbSJens Wiklander     if( p != end )
443817466cbSJens Wiklander     {
444817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
445817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_INVALID_FORMAT +
446817466cbSJens Wiklander                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
447817466cbSJens Wiklander     }
448817466cbSJens Wiklander 
449817466cbSJens Wiklander     end = crl->raw.p + crl->raw.len;
450817466cbSJens Wiklander 
451817466cbSJens Wiklander     /*
452817466cbSJens Wiklander      *  signatureAlgorithm   AlgorithmIdentifier,
453817466cbSJens Wiklander      *  signatureValue       BIT STRING
454817466cbSJens Wiklander      */
455817466cbSJens Wiklander     if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 )
456817466cbSJens Wiklander     {
457817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
458817466cbSJens Wiklander         return( ret );
459817466cbSJens Wiklander     }
460817466cbSJens Wiklander 
461817466cbSJens Wiklander     if( crl->sig_oid.len != sig_oid2.len ||
462817466cbSJens Wiklander         memcmp( crl->sig_oid.p, sig_oid2.p, crl->sig_oid.len ) != 0 ||
463817466cbSJens Wiklander         sig_params1.len != sig_params2.len ||
464817466cbSJens Wiklander         ( sig_params1.len != 0 &&
465817466cbSJens Wiklander           memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) )
466817466cbSJens Wiklander     {
467817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
468817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_SIG_MISMATCH );
469817466cbSJens Wiklander     }
470817466cbSJens Wiklander 
471817466cbSJens Wiklander     if( ( ret = mbedtls_x509_get_sig( &p, end, &crl->sig ) ) != 0 )
472817466cbSJens Wiklander     {
473817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
474817466cbSJens Wiklander         return( ret );
475817466cbSJens Wiklander     }
476817466cbSJens Wiklander 
477817466cbSJens Wiklander     if( p != end )
478817466cbSJens Wiklander     {
479817466cbSJens Wiklander         mbedtls_x509_crl_free( crl );
480817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_INVALID_FORMAT +
481817466cbSJens Wiklander                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
482817466cbSJens Wiklander     }
483817466cbSJens Wiklander 
484817466cbSJens Wiklander     return( 0 );
485817466cbSJens Wiklander }
486817466cbSJens Wiklander 
487817466cbSJens Wiklander /*
488817466cbSJens Wiklander  * Parse one or more CRLs and add them to the chained list
489817466cbSJens Wiklander  */
490817466cbSJens Wiklander int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen )
491817466cbSJens Wiklander {
492817466cbSJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C)
493817466cbSJens Wiklander     int ret;
494817466cbSJens Wiklander     size_t use_len;
495817466cbSJens Wiklander     mbedtls_pem_context pem;
496817466cbSJens Wiklander     int is_pem = 0;
497817466cbSJens Wiklander 
498817466cbSJens Wiklander     if( chain == NULL || buf == NULL )
499817466cbSJens Wiklander         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
500817466cbSJens Wiklander 
501817466cbSJens Wiklander     do
502817466cbSJens Wiklander     {
503817466cbSJens Wiklander         mbedtls_pem_init( &pem );
504817466cbSJens Wiklander 
505817466cbSJens Wiklander         // Avoid calling mbedtls_pem_read_buffer() on non-null-terminated
506817466cbSJens Wiklander         // string
507817466cbSJens Wiklander         if( buflen == 0 || buf[buflen - 1] != '\0' )
508817466cbSJens Wiklander             ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
509817466cbSJens Wiklander         else
510817466cbSJens Wiklander             ret = mbedtls_pem_read_buffer( &pem,
511817466cbSJens Wiklander                                            "-----BEGIN X509 CRL-----",
512817466cbSJens Wiklander                                            "-----END X509 CRL-----",
513817466cbSJens Wiklander                                             buf, NULL, 0, &use_len );
514817466cbSJens Wiklander 
515817466cbSJens Wiklander         if( ret == 0 )
516817466cbSJens Wiklander         {
517817466cbSJens Wiklander             /*
518817466cbSJens Wiklander              * Was PEM encoded
519817466cbSJens Wiklander              */
520817466cbSJens Wiklander             is_pem = 1;
521817466cbSJens Wiklander 
522817466cbSJens Wiklander             buflen -= use_len;
523817466cbSJens Wiklander             buf += use_len;
524817466cbSJens Wiklander 
525817466cbSJens Wiklander             if( ( ret = mbedtls_x509_crl_parse_der( chain,
526817466cbSJens Wiklander                                             pem.buf, pem.buflen ) ) != 0 )
527817466cbSJens Wiklander             {
528817466cbSJens Wiklander                 mbedtls_pem_free( &pem );
529817466cbSJens Wiklander                 return( ret );
530817466cbSJens Wiklander             }
531817466cbSJens Wiklander         }
532817466cbSJens Wiklander         else if( is_pem )
533817466cbSJens Wiklander         {
534817466cbSJens Wiklander             mbedtls_pem_free( &pem );
535817466cbSJens Wiklander             return( ret );
536817466cbSJens Wiklander         }
537817466cbSJens Wiklander 
538817466cbSJens Wiklander         mbedtls_pem_free( &pem );
539817466cbSJens Wiklander     }
540817466cbSJens Wiklander     /* In the PEM case, buflen is 1 at the end, for the terminated NULL byte.
541817466cbSJens Wiklander      * And a valid CRL cannot be less than 1 byte anyway. */
542817466cbSJens Wiklander     while( is_pem && buflen > 1 );
543817466cbSJens Wiklander 
544817466cbSJens Wiklander     if( is_pem )
545817466cbSJens Wiklander         return( 0 );
546817466cbSJens Wiklander     else
547817466cbSJens Wiklander #endif /* MBEDTLS_PEM_PARSE_C */
548817466cbSJens Wiklander         return( mbedtls_x509_crl_parse_der( chain, buf, buflen ) );
549817466cbSJens Wiklander }
550817466cbSJens Wiklander 
551817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO)
552817466cbSJens Wiklander /*
553817466cbSJens Wiklander  * Load one or more CRLs and add them to the chained list
554817466cbSJens Wiklander  */
555817466cbSJens Wiklander int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path )
556817466cbSJens Wiklander {
557817466cbSJens Wiklander     int ret;
558817466cbSJens Wiklander     size_t n;
559817466cbSJens Wiklander     unsigned char *buf;
560817466cbSJens Wiklander 
561817466cbSJens Wiklander     if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 )
562817466cbSJens Wiklander         return( ret );
563817466cbSJens Wiklander 
564817466cbSJens Wiklander     ret = mbedtls_x509_crl_parse( chain, buf, n );
565817466cbSJens Wiklander 
566817466cbSJens Wiklander     mbedtls_zeroize( buf, n );
567817466cbSJens Wiklander     mbedtls_free( buf );
568817466cbSJens Wiklander 
569817466cbSJens Wiklander     return( ret );
570817466cbSJens Wiklander }
571817466cbSJens Wiklander #endif /* MBEDTLS_FS_IO */
572817466cbSJens Wiklander 
573817466cbSJens Wiklander /*
574817466cbSJens Wiklander  * Return an informational string about the certificate.
575817466cbSJens Wiklander  */
576817466cbSJens Wiklander #define BEFORE_COLON    14
577817466cbSJens Wiklander #define BC              "14"
578817466cbSJens Wiklander /*
579817466cbSJens Wiklander  * Return an informational string about the CRL.
580817466cbSJens Wiklander  */
581817466cbSJens Wiklander int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix,
582817466cbSJens Wiklander                    const mbedtls_x509_crl *crl )
583817466cbSJens Wiklander {
584817466cbSJens Wiklander     int ret;
585817466cbSJens Wiklander     size_t n;
586817466cbSJens Wiklander     char *p;
587817466cbSJens Wiklander     const mbedtls_x509_crl_entry *entry;
588817466cbSJens Wiklander 
589817466cbSJens Wiklander     p = buf;
590817466cbSJens Wiklander     n = size;
591817466cbSJens Wiklander 
592817466cbSJens Wiklander     ret = mbedtls_snprintf( p, n, "%sCRL version   : %d",
593817466cbSJens Wiklander                                prefix, crl->version );
594817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
595817466cbSJens Wiklander 
596817466cbSJens Wiklander     ret = mbedtls_snprintf( p, n, "\n%sissuer name   : ", prefix );
597817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
598817466cbSJens Wiklander     ret = mbedtls_x509_dn_gets( p, n, &crl->issuer );
599817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
600817466cbSJens Wiklander 
601817466cbSJens Wiklander     ret = mbedtls_snprintf( p, n, "\n%sthis update   : " \
602817466cbSJens Wiklander                    "%04d-%02d-%02d %02d:%02d:%02d", prefix,
603817466cbSJens Wiklander                    crl->this_update.year, crl->this_update.mon,
604817466cbSJens Wiklander                    crl->this_update.day,  crl->this_update.hour,
605817466cbSJens Wiklander                    crl->this_update.min,  crl->this_update.sec );
606817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
607817466cbSJens Wiklander 
608817466cbSJens Wiklander     ret = mbedtls_snprintf( p, n, "\n%snext update   : " \
609817466cbSJens Wiklander                    "%04d-%02d-%02d %02d:%02d:%02d", prefix,
610817466cbSJens Wiklander                    crl->next_update.year, crl->next_update.mon,
611817466cbSJens Wiklander                    crl->next_update.day,  crl->next_update.hour,
612817466cbSJens Wiklander                    crl->next_update.min,  crl->next_update.sec );
613817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
614817466cbSJens Wiklander 
615817466cbSJens Wiklander     entry = &crl->entry;
616817466cbSJens Wiklander 
617817466cbSJens Wiklander     ret = mbedtls_snprintf( p, n, "\n%sRevoked certificates:",
618817466cbSJens Wiklander                                prefix );
619817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
620817466cbSJens Wiklander 
621817466cbSJens Wiklander     while( entry != NULL && entry->raw.len != 0 )
622817466cbSJens Wiklander     {
623817466cbSJens Wiklander         ret = mbedtls_snprintf( p, n, "\n%sserial number: ",
624817466cbSJens Wiklander                                prefix );
625817466cbSJens Wiklander         MBEDTLS_X509_SAFE_SNPRINTF;
626817466cbSJens Wiklander 
627817466cbSJens Wiklander         ret = mbedtls_x509_serial_gets( p, n, &entry->serial );
628817466cbSJens Wiklander         MBEDTLS_X509_SAFE_SNPRINTF;
629817466cbSJens Wiklander 
630817466cbSJens Wiklander         ret = mbedtls_snprintf( p, n, " revocation date: " \
631817466cbSJens Wiklander                    "%04d-%02d-%02d %02d:%02d:%02d",
632817466cbSJens Wiklander                    entry->revocation_date.year, entry->revocation_date.mon,
633817466cbSJens Wiklander                    entry->revocation_date.day,  entry->revocation_date.hour,
634817466cbSJens Wiklander                    entry->revocation_date.min,  entry->revocation_date.sec );
635817466cbSJens Wiklander         MBEDTLS_X509_SAFE_SNPRINTF;
636817466cbSJens Wiklander 
637817466cbSJens Wiklander         entry = entry->next;
638817466cbSJens Wiklander     }
639817466cbSJens Wiklander 
640817466cbSJens Wiklander     ret = mbedtls_snprintf( p, n, "\n%ssigned using  : ", prefix );
641817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
642817466cbSJens Wiklander 
643817466cbSJens Wiklander     ret = mbedtls_x509_sig_alg_gets( p, n, &crl->sig_oid, crl->sig_pk, crl->sig_md,
644817466cbSJens Wiklander                              crl->sig_opts );
645817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
646817466cbSJens Wiklander 
647817466cbSJens Wiklander     ret = mbedtls_snprintf( p, n, "\n" );
648817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
649817466cbSJens Wiklander 
650817466cbSJens Wiklander     return( (int) ( size - n ) );
651817466cbSJens Wiklander }
652817466cbSJens Wiklander 
653817466cbSJens Wiklander /*
654817466cbSJens Wiklander  * Initialize a CRL chain
655817466cbSJens Wiklander  */
656817466cbSJens Wiklander void mbedtls_x509_crl_init( mbedtls_x509_crl *crl )
657817466cbSJens Wiklander {
658817466cbSJens Wiklander     memset( crl, 0, sizeof(mbedtls_x509_crl) );
659817466cbSJens Wiklander }
660817466cbSJens Wiklander 
661817466cbSJens Wiklander /*
662817466cbSJens Wiklander  * Unallocate all CRL data
663817466cbSJens Wiklander  */
664817466cbSJens Wiklander void mbedtls_x509_crl_free( mbedtls_x509_crl *crl )
665817466cbSJens Wiklander {
666817466cbSJens Wiklander     mbedtls_x509_crl *crl_cur = crl;
667817466cbSJens Wiklander     mbedtls_x509_crl *crl_prv;
668817466cbSJens Wiklander     mbedtls_x509_name *name_cur;
669817466cbSJens Wiklander     mbedtls_x509_name *name_prv;
670817466cbSJens Wiklander     mbedtls_x509_crl_entry *entry_cur;
671817466cbSJens Wiklander     mbedtls_x509_crl_entry *entry_prv;
672817466cbSJens Wiklander 
673817466cbSJens Wiklander     if( crl == NULL )
674817466cbSJens Wiklander         return;
675817466cbSJens Wiklander 
676817466cbSJens Wiklander     do
677817466cbSJens Wiklander     {
678817466cbSJens Wiklander #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
679817466cbSJens Wiklander         mbedtls_free( crl_cur->sig_opts );
680817466cbSJens Wiklander #endif
681817466cbSJens Wiklander 
682817466cbSJens Wiklander         name_cur = crl_cur->issuer.next;
683817466cbSJens Wiklander         while( name_cur != NULL )
684817466cbSJens Wiklander         {
685817466cbSJens Wiklander             name_prv = name_cur;
686817466cbSJens Wiklander             name_cur = name_cur->next;
687817466cbSJens Wiklander             mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
688817466cbSJens Wiklander             mbedtls_free( name_prv );
689817466cbSJens Wiklander         }
690817466cbSJens Wiklander 
691817466cbSJens Wiklander         entry_cur = crl_cur->entry.next;
692817466cbSJens Wiklander         while( entry_cur != NULL )
693817466cbSJens Wiklander         {
694817466cbSJens Wiklander             entry_prv = entry_cur;
695817466cbSJens Wiklander             entry_cur = entry_cur->next;
696817466cbSJens Wiklander             mbedtls_zeroize( entry_prv, sizeof( mbedtls_x509_crl_entry ) );
697817466cbSJens Wiklander             mbedtls_free( entry_prv );
698817466cbSJens Wiklander         }
699817466cbSJens Wiklander 
700817466cbSJens Wiklander         if( crl_cur->raw.p != NULL )
701817466cbSJens Wiklander         {
702817466cbSJens Wiklander             mbedtls_zeroize( crl_cur->raw.p, crl_cur->raw.len );
703817466cbSJens Wiklander             mbedtls_free( crl_cur->raw.p );
704817466cbSJens Wiklander         }
705817466cbSJens Wiklander 
706817466cbSJens Wiklander         crl_cur = crl_cur->next;
707817466cbSJens Wiklander     }
708817466cbSJens Wiklander     while( crl_cur != NULL );
709817466cbSJens Wiklander 
710817466cbSJens Wiklander     crl_cur = crl;
711817466cbSJens Wiklander     do
712817466cbSJens Wiklander     {
713817466cbSJens Wiklander         crl_prv = crl_cur;
714817466cbSJens Wiklander         crl_cur = crl_cur->next;
715817466cbSJens Wiklander 
716817466cbSJens Wiklander         mbedtls_zeroize( crl_prv, sizeof( mbedtls_x509_crl ) );
717817466cbSJens Wiklander         if( crl_prv != crl )
718817466cbSJens Wiklander             mbedtls_free( crl_prv );
719817466cbSJens Wiklander     }
720817466cbSJens Wiklander     while( crl_cur != NULL );
721817466cbSJens Wiklander }
722817466cbSJens Wiklander 
723817466cbSJens Wiklander #endif /* MBEDTLS_X509_CRL_PARSE_C */
724