x509_crl_parse.c
Go to the documentation of this file.
1 /**
2  * @file x509_crl_parse.c
3  * @brief CRL (Certificate Revocation List) parsing
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneCRYPTO Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/crypto.h"
36 #include "pkix/x509_cert_parse.h"
37 #include "pkix/x509_crl_parse.h"
39 #include "pkix/x509_sign_parse.h"
40 #include "encoding/asn1.h"
41 #include "encoding/oid.h"
42 #include "debug.h"
43 
44 //Check crypto library configuration
45 #if (X509_SUPPORT == ENABLED)
46 
47 
48 /**
49  * @brief Parse a CRL (Certificate Revocation List)
50  * @param[in] data Pointer to the CRL to parse
51  * @param[in] length Length of the CRL
52  * @param[out] crlInfo Information resulting from the parsing process
53  * @return Error code
54  **/
55 
56 error_t x509ParseCrl(const uint8_t *data, size_t length,
57  X509CrlInfo *crlInfo)
58 {
59  error_t error;
60  size_t n;
61  Asn1Tag tag;
62 
63  //Debug message
64  TRACE_DEBUG("Parsing X.509 CRL...\r\n");
65 
66  //Check parameters
67  if(data == NULL || crlInfo == NULL)
69 
70  //Clear the CRL information structure
71  osMemset(crlInfo, 0, sizeof(X509CrlInfo));
72 
73  //The CRL is encapsulated within a sequence
74  error = asn1ReadTag(data, length, &tag);
75  //Failed to decode ASN.1 tag?
76  if(error)
77  return error;
78 
79  //Point to the very first field
80  data = tag.value;
81  length = tag.length;
82 
83  //Parse TBSCertList structure
84  error = x509ParseTbsCertList(data, length, &n, &crlInfo->tbsCertList);
85  //Any error to report?
86  if(error)
87  return error;
88 
89  //Point to the next field
90  data += n;
91  length -= n;
92 
93  //Parse SignatureAlgorithm structure
94  error = x509ParseSignatureAlgo(data, length, &n, &crlInfo->signatureAlgo);
95  //Any error to report?
96  if(error)
97  return error;
98 
99  //This field must contain the same algorithm identifier as the signature
100  //field in the TBSCertList sequence (refer to RFC 5280, section 5.1.1.2)
101  if(oidComp(crlInfo->signatureAlgo.oid.value,
102  crlInfo->signatureAlgo.oid.length,
105  {
106  //Report an error
107  return ERROR_WRONG_IDENTIFIER;
108  }
109 
110  //Point to the next field
111  data += n;
112  length -= n;
113 
114  //Parse SignatureValue structure
115  error = x509ParseSignatureValue(data, length, &n, &crlInfo->signatureValue);
116  //Any error to report?
117  if(error)
118  return error;
119 
120  //CRL successfully parsed
121  return NO_ERROR;
122 }
123 
124 
125 /**
126  * @brief Parse TBSCertList structure
127  * @param[in] data Pointer to the ASN.1 structure to parse
128  * @param[in] length Length of the ASN.1 structure
129  * @param[out] totalLength Number of bytes that have been parsed
130  * @param[out] tbsCertList Information resulting from the parsing process
131  * @return Error code
132  **/
133 
134 error_t x509ParseTbsCertList(const uint8_t *data, size_t length,
135  size_t *totalLength, X509TbsCertList *tbsCertList)
136 {
137  error_t error;
138  size_t n;
139  Asn1Tag tag;
140 
141  //Debug message
142  TRACE_DEBUG(" Parsing TBSCertList...\r\n");
143 
144  //Read the contents of the TBSCertList structure
145  error = asn1ReadTag(data, length, &tag);
146  //Failed to decode ASN.1 tag?
147  if(error)
148  return error;
149 
150  //Save the total length of the field
151  *totalLength = tag.totalLength;
152 
153  //The ASN.1 DER-encoded TBSCertList is used as the input to the
154  //signature function
155  tbsCertList->raw.value = data;
156  tbsCertList->raw.length = tag.totalLength;
157 
158  //Point to the very first field of the TBSCertList
159  data = tag.value;
160  length = tag.length;
161 
162  //Parse Version field
163  error = x509ParseCrlVersion(data, length, &n, &tbsCertList->version);
164  //Any parsing error?
165  if(error)
166  return error;
167 
168  //Point to the next field
169  data += n;
170  length -= n;
171 
172  //Parse Signature field
173  error = x509ParseSignatureAlgo(data, length, &n,
174  &tbsCertList->signatureAlgo);
175  //Any parsing error?
176  if(error)
177  return error;
178 
179  //Point to the next field
180  data += n;
181  length -= n;
182 
183  //Parse Issuer field
184  error = x509ParseName(data, length, &n, &tbsCertList->issuer);
185  //Any parsing error?
186  if(error)
187  return error;
188 
189  //Point to the next field
190  data += n;
191  length -= n;
192 
193  //Parse ThisUpdate field
194  error = x509ParseTime(data, length, &n, &tbsCertList->thisUpdate);
195  //Any parsing error?
196  if(error)
197  return error;
198 
199  //Point to the next field
200  data += n;
201  length -= n;
202 
203  //Parse NextUpdate field
204  error = x509ParseTime(data, length, &n, &tbsCertList->nextUpdate);
205  //Any parsing error?
206  if(error)
207  return error;
208 
209  //Point to the next field
210  data += n;
211  length -= n;
212 
213  //Parse RevokedCertificates field
214  error = x509ParseRevokedCertificates(data, length, &n, tbsCertList);
215  //Any parsing error?
216  if(error)
217  return error;
218 
219  //Point to the next field
220  data += n;
221  length -= n;
222 
223  //Parse CrlExtensions field
224  error = x509ParseCrlExtensions(data, length, &n, &tbsCertList->crlExtensions);
225  //Any parsing error?
226  if(error)
227  return error;
228 
229  //The CrlExtensions field is optional
230  if(n > 0)
231  {
232  //This field must only appear if the version is 2
233  if(tbsCertList->version < X509_VERSION_2)
234  return ERROR_INVALID_VERSION;
235  }
236 
237  //No error to report
238  return NO_ERROR;
239 }
240 
241 
242 /**
243  * @brief Parse Version field
244  * @param[in] data Pointer to the ASN.1 structure to parse
245  * @param[in] length Length of the ASN.1 structure
246  * @param[out] totalLength Number of bytes that have been parsed
247  * @param[out] version Information resulting from the parsing process
248  * @return Error code
249  **/
250 
251 error_t x509ParseCrlVersion(const uint8_t *data, size_t length,
252  size_t *totalLength, X509Version *version)
253 {
254  error_t error;
255  int32_t value;
256  Asn1Tag tag;
257 
258  //Debug message
259  TRACE_DEBUG(" Parsing Version...\r\n");
260 
261  //The Version field is optional
262  error = asn1ReadTag(data, length, &tag);
263  //Failed to decode ASN.1 tag?
264  if(error)
265  return error;
266 
267  //Check encoding, class and type
269 
270  //The tag does not match the criteria?
271  if(error)
272  {
273  //Assume X.509 version 1 format
275  //Skip the current field
276  *totalLength = 0;
277 
278  //Exit immediately
279  return NO_ERROR;
280  }
281 
282  //Parse Version field
283  error = asn1ReadInt32(data, length, &tag, &value);
284  //Failed to decode ASN.1 tag?
285  if(error)
286  return error;
287 
288  //Save the version
290  //Save the total length of the field
291  *totalLength = tag.totalLength;
292 
293  //Successful processing
294  return NO_ERROR;
295 }
296 
297 
298 /**
299  * @brief Parse RevokedCertificates field
300  * @param[in] data Pointer to the ASN.1 structure to parse
301  * @param[in] length Length of the ASN.1 structure
302  * @param[out] totalLength Number of bytes that have been parsed
303  * @param[out] tbsCertList Information resulting from the parsing process
304  * @return Error code
305  **/
306 
308  size_t *totalLength, X509TbsCertList *tbsCertList)
309 {
310  error_t error;
311  size_t n;
312  Asn1Tag tag;
313  X509RevokedCertificate revokedCertificate;
314 
315  //Debug message
316  TRACE_DEBUG(" Parsing RevokedCertificates...\r\n");
317 
318  //No more data to process?
319  if(length == 0)
320  {
321  //The RevokedCertificates field is optional
322  *totalLength = 0;
323  //Exit immediately
324  return NO_ERROR;
325  }
326 
327  //The RevokedCertificates field is encapsulated within a sequence
328  error = asn1ReadTag(data, length, &tag);
329  //Failed to decode ASN.1 tag?
330  if(error)
331  return error;
332 
333  //Check encoding, class and type
335 
336  //The tag does not match the criteria?
337  if(error)
338  {
339  //The RevokedCertificates field is optional
340  *totalLength = 0;
341  //Exit immediately
342  return NO_ERROR;
343  }
344 
345  //Save the total length of the field
346  *totalLength = tag.totalLength;
347 
348  //Raw contents of the ASN.1 sequence
349  tbsCertList->revokedCerts.value = tag.value;
350  tbsCertList->revokedCerts.length = tag.length;
351 
352  //Point to the first item of the sequence
353  data = tag.value;
354  length = tag.length;
355 
356  //Loop through the list of revoked certificates
357  while(length > 0)
358  {
359  //Parse current item
360  error = x509ParseRevokedCertificate(data, length, &n, &revokedCertificate);
361  //Any error to report?
362  if(error)
363  return error;
364 
365  //Next item
366  data += n;
367  length -= n;
368  }
369 
370  //Successful processing
371  return NO_ERROR;
372 }
373 
374 
375 /**
376  * @brief Parse RevokedCertificate field
377  * @param[in] data Pointer to the ASN.1 structure to parse
378  * @param[in] length Length of the ASN.1 structure
379  * @param[out] totalLength Number of bytes that have been parsed
380  * @param[out] revokedCertificate Information resulting from the parsing process
381  * @return Error code
382  **/
383 
385  size_t *totalLength, X509RevokedCertificate *revokedCertificate)
386 {
387  error_t error;
388  size_t n;
389  Asn1Tag tag;
390 
391  //Debug message
392  TRACE_DEBUG(" Parsing RevokedCertificate...\r\n");
393 
394  //Clear the RevokedCertificate structure
395  osMemset(revokedCertificate, 0, sizeof(X509RevokedCertificate));
396 
397  //The RevokedCertificate structure shall contain a valid sequence
398  error = asn1ReadSequence(data, length, &tag);
399  //Failed to decode ASN.1 tag?
400  if(error)
401  return error;
402 
403  //Save the total length of the field
404  *totalLength = tag.totalLength;
405 
406  //Point to the first item of the sequence
407  data = tag.value;
408  length = tag.length;
409 
410  //Parse UserCertificate field
411  error = x509ParseSerialNumber(data, length, &n,
412  &revokedCertificate->userCert);
413  //Any error to report?
414  if(error)
415  return error;
416 
417  //Point to the next field
418  data += n;
419  length -= n;
420 
421  //Parse RevocationDate field
422  error = x509ParseTime(data, length, &n,
423  &revokedCertificate->revocationDate);
424  //Any error to report?
425  if(error)
426  return error;
427 
428  //Point to the next field
429  data += n;
430  length -= n;
431 
432  //Parse CrlEntryExtensions field
434  &revokedCertificate->crlEntryExtensions);
435  //Any parsing error?
436  if(error)
437  return error;
438 
439  //Successful processing
440  return NO_ERROR;
441 }
442 
443 #endif
error_t asn1ReadTag(const uint8_t *data, size_t length, Asn1Tag *tag)
Read an ASN.1 tag from the input stream.
Definition: asn1.c:52
error_t asn1ReadSequence(const uint8_t *data, size_t length, Asn1Tag *tag)
Read an ASN.1 sequence from the input stream.
Definition: asn1.c:163
error_t asn1CheckTag(const Asn1Tag *tag, bool_t constructed, uint_t objClass, uint_t objType)
Enforce the type of a specified tag.
Definition: asn1.c:653
error_t asn1ReadInt32(const uint8_t *data, size_t length, Asn1Tag *tag, int32_t *value)
Read a 32-bit integer from the input stream.
Definition: asn1.c:285
ASN.1 (Abstract Syntax Notation One)
@ ASN1_TYPE_INTEGER
Definition: asn1.h:70
@ ASN1_TYPE_SEQUENCE
Definition: asn1.h:80
#define ASN1_CLASS_UNIVERSAL
Definition: asn1.h:52
uint8_t version
Definition: coap_common.h:177
General definitions for cryptographic algorithms.
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
uint8_t n
error_t
Error codes.
Definition: error.h:43
@ ERROR_WRONG_IDENTIFIER
Definition: error.h:89
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
@ ERROR_INVALID_VERSION
Definition: error.h:118
uint8_t data[]
Definition: ethernet.h:222
uint16_t totalLength
Definition: ipv4.h:292
int_t oidComp(const uint8_t *oid1, size_t oidLen1, const uint8_t *oid2, size_t oidLen2)
Compare object identifiers.
Definition: oid.c:103
OID (Object Identifier)
#define osMemset(p, value, length)
Definition: os_port.h:135
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
ASN.1 tag.
Definition: asn1.h:102
size_t totalLength
Definition: asn1.h:108
const uint8_t * value
Definition: asn1.h:107
size_t length
Definition: asn1.h:106
CRL (Certificate Revocation List)
Definition: x509_common.h:1206
X509TbsCertList tbsCertList
Definition: x509_common.h:1207
X509OctetString signatureValue
Definition: x509_common.h:1209
X509SignAlgoId signatureAlgo
Definition: x509_common.h:1208
const uint8_t * value
Definition: x509_common.h:647
Revoked certificate.
Definition: x509_common.h:1124
X509SerialNumber userCert
Definition: x509_common.h:1125
X509CrlEntryExtensions crlEntryExtensions
Definition: x509_common.h:1127
X509OctetString oid
Definition: x509_common.h:1034
TBSCertList structure.
Definition: x509_common.h:1189
X509Version version
Definition: x509_common.h:1191
DateTime thisUpdate
Definition: x509_common.h:1194
X509OctetString raw
Definition: x509_common.h:1190
X509CrlExtensions crlExtensions
Definition: x509_common.h:1197
DateTime nextUpdate
Definition: x509_common.h:1195
X509OctetString revokedCerts
Definition: x509_common.h:1196
X509SignAlgoId signatureAlgo
Definition: x509_common.h:1192
uint8_t length
Definition: tcp.h:368
uint8_t value[]
Definition: tcp.h:369
error_t x509ParseName(const uint8_t *data, size_t length, size_t *totalLength, X509Name *name)
Parse Name structure.
error_t x509ParseSerialNumber(const uint8_t *data, size_t length, size_t *totalLength, X509SerialNumber *serialNumber)
Parse SerialNumber field.
error_t x509ParseTime(const uint8_t *data, size_t length, size_t *totalLength, DateTime *dateTime)
Parse UTCTime or GeneralizedTime field.
X.509 certificate parsing.
X509Version
X.509 versions.
Definition: x509_common.h:458
@ X509_VERSION_1
Definition: x509_common.h:459
@ X509_VERSION_2
Definition: x509_common.h:460
error_t x509ParseCrlExtensions(const uint8_t *data, size_t length, size_t *totalLength, X509CrlExtensions *crlExtensions)
Parse CRL extensions.
error_t x509ParseCrlEntryExtensions(const uint8_t *data, size_t length, size_t *totalLength, X509CrlEntryExtensions *crlEntryExtensions)
Parse CRL entry extensions.
CRL extension parsing.
error_t x509ParseCrlVersion(const uint8_t *data, size_t length, size_t *totalLength, X509Version *version)
Parse Version field.
error_t x509ParseTbsCertList(const uint8_t *data, size_t length, size_t *totalLength, X509TbsCertList *tbsCertList)
Parse TBSCertList structure.
error_t x509ParseRevokedCertificates(const uint8_t *data, size_t length, size_t *totalLength, X509TbsCertList *tbsCertList)
Parse RevokedCertificates field.
error_t x509ParseRevokedCertificate(const uint8_t *data, size_t length, size_t *totalLength, X509RevokedCertificate *revokedCertificate)
Parse RevokedCertificate field.
error_t x509ParseCrl(const uint8_t *data, size_t length, X509CrlInfo *crlInfo)
Parse a CRL (Certificate Revocation List)
CRL (Certificate Revocation List) parsing.
error_t x509ParseSignatureValue(const uint8_t *data, size_t length, size_t *totalLength, X509OctetString *signature)
Parse SignatureValue field.
error_t x509ParseSignatureAlgo(const uint8_t *data, size_t length, size_t *totalLength, X509SignAlgoId *signatureAlgo)
Parse SignatureAlgorithm structure.