x509_cert_ext_parse.c
Go to the documentation of this file.
1 /**
2  * @file x509_cert_ext_parse.c
3  * @brief X.509 extension parsing
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 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.5.4
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"
38 #include "encoding/asn1.h"
39 #include "encoding/oid.h"
40 #include "debug.h"
41 
42 //Check crypto library configuration
43 #if (X509_SUPPORT == ENABLED)
44 
45 
46 /**
47  * @brief Parse X.509 certificate extensions
48  * @param[in] data Pointer to the ASN.1 structure to parse
49  * @param[in] length Length of the ASN.1 structure
50  * @param[out] totalLength Number of bytes that have been parsed
51  * @param[out] extensions Information resulting from the parsing process
52  * @param[in] options Certificate parsing options
53  * @return Error code
54  **/
55 
56 error_t x509ParseCertExtensions(const uint8_t *data, size_t length,
58 {
59  error_t error;
60  size_t n;
61  Asn1Tag tag;
62  X509Extension extension;
63 
64  //No more data to process?
65  if(length == 0)
66  {
67  //The Extensions field is optional
68  *totalLength = 0;
69  //Exit immediately
70  return NO_ERROR;
71  }
72 
73  //Explicit tagging is used to encode the Extensions field
74  error = asn1ReadTag(data, length, &tag);
75  //Failed to decode ASN.1 tag?
76  if(error)
77  return error;
78 
79  //Enforce encoding, class and type
81  //Invalid tag?
82  if(error)
83  {
84  //The Extensions field is optional
85  *totalLength = 0;
86  //Exit immediately
87  return NO_ERROR;
88  }
89 
90  //Save the total length of the field
91  *totalLength = tag.totalLength;
92 
93  //Debug message
94  TRACE_DEBUG(" Parsing Extensions...\r\n");
95 
96  //This field is a sequence of one or more certificate extensions
97  error = asn1ReadSequence(tag.value, tag.length, &tag);
98  //Failed to decode ASN.1 tag?
99  if(error)
100  return error;
101 
102  //Raw contents of the ASN.1 sequence
103  extensions->raw.value = tag.value;
104  extensions->raw.length = tag.length;
105 
106  //Point to the first item of the sequence
107  data = tag.value;
108  length = tag.length;
109 
110  //Loop through the extensions
111  while(length > 0)
112  {
113  //Each extension includes an OID and a value
114  error = x509ParseExtension(data, length, &n, &extension);
115  //Any error to report?
116  if(error)
117  return error;
118 
119  //Jump to the next extension
120  data += n;
121  length -= n;
122 
123  //Test if the current extension is a duplicate
124  error = x509CheckDuplicateExtension(extension.oid.value,
125  extension.oid.length, data, length);
126  //Duplicate extension found?
127  if(error)
128  return error;
129 
130  //Check extension identifier
131  if(OID_COMP(extension.oid.value, extension.oid.length,
133  {
134  //Parse BasicConstraints extension
135  error = x509ParseBasicConstraints(extension.critical, extension.data.value,
136  extension.data.length, &extensions->basicConstraints);
137  }
138  else if(OID_COMP(extension.oid.value, extension.oid.length,
140  {
141  //Parse NameConstraints extension
142  error = x509ParseNameConstraints(extension.critical, extension.data.value,
143  extension.data.length, &extensions->nameConstraints);
144  }
145  else if(OID_COMP(extension.oid.value, extension.oid.length,
146  X509_KEY_USAGE_OID) == 0)
147  {
148  //Parse KeyUsage extension
149  error = x509ParseKeyUsage(extension.critical, extension.data.value,
150  extension.data.length, &extensions->keyUsage);
151  }
152  else if(OID_COMP(extension.oid.value, extension.oid.length,
154  {
155  //Parse ExtendedKeyUsage extension
156  error = x509ParseExtendedKeyUsage(extension.critical, extension.data.value,
157  extension.data.length, &extensions->extKeyUsage);
158  }
159  else if(OID_COMP(extension.oid.value, extension.oid.length,
161  {
162  //Parse SubjectAltName extension
163  error = x509ParseSubjectAltName(extension.critical, extension.data.value,
164  extension.data.length, &extensions->subjectAltName);
165  }
166  else if(OID_COMP(extension.oid.value, extension.oid.length,
168  {
169  //Parse SubjectKeyIdentifier extension
170  error = x509ParseSubjectKeyId(extension.critical, extension.data.value,
171  extension.data.length, &extensions->subjectKeyId);
172  }
173  else if(OID_COMP(extension.oid.value, extension.oid.length,
175  {
176  //Parse AuthorityKeyIdentifier extension
177  error = x509ParseAuthKeyId(extension.critical, extension.data.value,
178  extension.data.length, &extensions->authKeyId);
179  }
180  else if(OID_COMP(extension.oid.value, extension.oid.length,
182  {
183  //Parse CRLDistributionPoints extension
184  error = x509ParseCrlDistrPoints(extension.critical, extension.data.value,
185  extension.data.length, &extensions->crlDistrPoints);
186  }
187  else if(OID_COMP(extension.oid.value, extension.oid.length,
189  {
190  //Parse AuthorityInformationAccess extension
191  error = x509ParseAuthInfoAccess(extension.critical, extension.data.value,
192  extension.data.length, &extensions->authInfoAccess);
193  }
194  else if(OID_COMP(extension.oid.value, extension.oid.length,
196  {
197  //Parse PkixOcspNoCheck extension
198  error = x509ParsePkixOcspNoCheck(extension.critical, extension.data.value,
199  extension.data.length, &extensions->pkixOcspNoCheck);
200  }
201  else if(OID_COMP(extension.oid.value, extension.oid.length,
202  X509_NS_CERT_TYPE_OID) == 0)
203  {
204  //Parse NetscapeCertType extension
205  error = x509ParseNsCertType(extension.critical, extension.data.value,
206  extension.data.length, &extensions->nsCertType);
207  }
208  else
209  {
210  //Parse unknown extension
211  error = x509ParseUnknownCertExtension(extension.oid.value,
212  extension.oid.length, extension.critical, extension.data.value,
213  extension.data.length, extensions);
214 
215  //Check status code
216  if(error == ERROR_UNSUPPORTED_EXTENSION)
217  {
218  //An application must reject the certificate if it encounters a
219  //critical extension it does not recognize or a critical extension
220  //that contains information that it cannot process
221  if(!extension.critical || options->ignoreUnknownExtensions)
222  {
223  error = NO_ERROR;
224  }
225  }
226  }
227 
228  //Any parsing error?
229  if(error)
230  return error;
231  }
232 
233  //Check whether the NameConstraints extension is present
234  if(extensions->nameConstraints.permittedSubtrees.length > 0 ||
235  extensions->nameConstraints.excludedSubtrees.length > 0)
236  {
237  //The NameConstraints extension, must be used only in a CA certificate
238  //(refer to RFC 5280, section 4.2.1.10)
239  if(!extensions->basicConstraints.cA)
240  return ERROR_INVALID_SYNTAX;
241  }
242 
243  //Successful processing
244  return NO_ERROR;
245 }
246 
247 
248 /**
249  * @brief Parse X.509 certificate extension
250  * @param[in] data Pointer to the ASN.1 structure to parse
251  * @param[in] length Length of the ASN.1 structure
252  * @param[out] totalLength Number of bytes that have been parsed
253  * @param[out] extension Information resulting from the parsing process
254  * @return Error code
255  **/
256 
257 error_t x509ParseExtension(const uint8_t *data, size_t length,
258  size_t *totalLength, X509Extension *extension)
259 {
260  error_t error;
261  Asn1Tag tag;
262 
263  //The X.509 extension is encapsulated within a sequence
264  error = asn1ReadSequence(data, length, &tag);
265  //Failed to decode ASN.1 tag?
266  if(error)
267  return error;
268 
269  //Save the total length of the X.509 extension
270  *totalLength = tag.totalLength;
271 
272  //Each extension includes an OID and a value
273  data = tag.value;
274  length = tag.length;
275 
276  //Read extension OID
277  error = asn1ReadOid(data, length, &tag);
278  //Failed to decode ASN.1 tag?
279  if(error)
280  return error;
281 
282  //Save the object identifier
283  extension->oid.value = tag.value;
284  extension->oid.length = tag.length;
285 
286  //Next item
287  data += tag.totalLength;
288  length -= tag.totalLength;
289 
290  //Read the Critical flag (if present)
291  error = asn1ReadTag(data, length, &tag);
292  //Failed to decode ASN.1 tag?
293  if(error)
294  return error;
295 
296  //Enforce encoding, class and type
298 
299  //Check whether the Critical field is present
300  if(!error)
301  {
302  //Make sure the length of the boolean is valid
303  if(tag.length != 1)
304  return ERROR_INVALID_LENGTH;
305 
306  //Each extension in a certificate is designated as either critical
307  //or non-critical
308  extension->critical = tag.value[0] ? TRUE : FALSE;
309 
310  //Next item
311  data += tag.totalLength;
312  length -= tag.totalLength;
313  }
314  else
315  {
316  //The extension is considered as non-critical
317  extension->critical = FALSE;
318  }
319 
320  //The extension value is encapsulated within an octet string
321  error = asn1ReadOctetString(data, length, &tag);
322  //Failed to decode ASN.1 tag?
323  if(error)
324  return error;
325 
326  //Save the value of the extension
327  extension->data.value = tag.value;
328  extension->data.length = tag.length;
329 
330  //Successful processing
331  return NO_ERROR;
332 }
333 
334 
335 /**
336  * @brief Parse BasicConstraints extension
337  * @param[in] critical Critical extension flag
338  * @param[in] data Pointer to the ASN.1 structure to parse
339  * @param[in] length Length of the ASN.1 structure
340  * @param[out] basicConstraints Information resulting from the parsing process
341  * @return Error code
342  **/
343 
345  size_t length, X509BasicConstraints *basicConstraints)
346 {
347  error_t error;
348  int32_t value;
349  Asn1Tag tag;
350 
351  //Debug message
352  TRACE_DEBUG(" Parsing BasicConstraints...\r\n");
353 
354  //An extension can be marked as critical
355  basicConstraints->critical = critical;
356 
357  //The BasicConstraints structure shall contain a valid sequence
358  error = asn1ReadSequence(data, length, &tag);
359  //Failed to decode ASN.1 tag?
360  if(error)
361  return error;
362 
363  //Point to the first item of the sequence
364  data = tag.value;
365  length = tag.length;
366 
367  //The cA field is optional
368  if(length > 0)
369  {
370  //The cA boolean indicates whether the certified public key may be used
371  //to verify certificate signatures
372  error = asn1ReadTag(data, length, &tag);
373  //Failed to decode ASN.1 tag?
374  if(error)
375  return error;
376 
377  //Enforce encoding, class and type
379 
380  //Check status code
381  if(!error)
382  {
383  //Make sure the length of the boolean is valid
384  if(tag.length != 1)
385  return ERROR_INVALID_LENGTH;
386 
387  //Get boolean value
388  basicConstraints->cA = tag.value[0] ? TRUE : FALSE;
389 
390  //Point to the next item
391  data += tag.totalLength;
392  length -= tag.totalLength;
393  }
394  }
395 
396  //The pathLenConstraint field is optional
397  if(length > 0)
398  {
399  //Read the pathLenConstraint field
400  error = asn1ReadInt32(data, length, &tag, &value);
401  //Failed to decode ASN.1 tag?
402  if(error)
403  return error;
404 
405  //The pathLenConstraint field is meaningful only if the cA boolean is
406  //asserted (refer to RFC 5280, section 4.2.1.9)
407  if(!basicConstraints->cA)
408  return ERROR_INVALID_SYNTAX;
409 
410  //Where it appears, the pathLenConstraint field must be greater than or
411  //equal to zero (refer to RFC 5280, section 4.2.1.9)
412  if(value < 0)
413  return ERROR_INVALID_SYNTAX;
414 
415  //The pathLenConstraint field gives the maximum number of non-self-issued
416  //intermediate certificates that may follow this certificate in a valid
417  //certification path
418  basicConstraints->pathLenConstraint = value;
419  }
420 
421  //Successful processing
422  return NO_ERROR;
423 }
424 
425 
426 /**
427  * @brief Parse NameConstraints extension
428  * @param[in] critical Critical extension flag
429  * @param[in] data Pointer to the ASN.1 structure to parse
430  * @param[in] length Length of the ASN.1 structure
431  * @param[out] nameConstraints Information resulting from the parsing process
432  * @return Error code
433  **/
434 
436  size_t length, X509NameConstraints *nameConstraints)
437 {
438  error_t error;
439  Asn1Tag tag;
440 
441  //Debug message
442  TRACE_DEBUG(" Parsing NameConstraints...\r\n");
443 
444  //An extension can be marked as critical
445  nameConstraints->critical = critical;
446 
447  //Conforming CAs must mark the NameConstraints extension as critical (refer
448  //to RFC 5280, section 4.2.1.10)
449  if(!nameConstraints->critical)
450  return ERROR_INVALID_SYNTAX;
451 
452  //The NameConstraints structure shall contain a valid sequence
453  error = asn1ReadSequence(data, length, &tag);
454  //Failed to decode ASN.1 tag?
455  if(error)
456  return error;
457 
458  //Conforming CAs must not issue certificates where name constraints is an
459  //empty sequence (refer to RFC 5280, section 4.2.1.10)
460  if(tag.length == 0)
461  return ERROR_INVALID_SYNTAX;
462 
463  //Point to the first item of the sequence
464  data = tag.value;
465  length = tag.length;
466 
467  //The name constraints extension indicates a name space within which all
468  //subject names in subsequent certificates in a certification path must
469  //be located
470  while(length > 0)
471  {
472  //Parse GeneralSubtrees field
473  error = asn1ReadTag(data, length, &tag);
474  //Failed to decode ASN.1 tag?
475  if(error)
476  return error;
477 
478  //Implicit tagging shall be used to encode the GeneralSubtrees field
480  return ERROR_INVALID_CLASS;
481 
482  //The sequence cannot be empty (refer to RFC 5280, section 4.2.1.10)
483  if(tag.length == 0)
484  return ERROR_INVALID_SYNTAX;
485 
486  //Restrictions are defined in terms of permitted or excluded name subtrees
487  if(tag.objType == 0)
488  {
489  //Parse the permittedSubtrees field
490  error = x509ParseGeneralSubtrees(tag.value, tag.length);
491  //Any error to report?
492  if(error)
493  return error;
494 
495  //Raw contents of the ASN.1 sequence
496  nameConstraints->permittedSubtrees.value = tag.value;
497  nameConstraints->permittedSubtrees.length = tag.length;
498  }
499  else if(tag.objType == 1)
500  {
501  //Parse the excludedSubtrees field
502  error = x509ParseGeneralSubtrees(tag.value, tag.length);
503  //Any error to report?
504  if(error)
505  return error;
506 
507  //Raw contents of the ASN.1 sequence
508  nameConstraints->excludedSubtrees.value = tag.value;
509  nameConstraints->excludedSubtrees.length = tag.length;
510  }
511  else
512  {
513  //Report an error
514  return ERROR_INVALID_TYPE;
515  }
516 
517  //Next item
518  data += tag.totalLength;
519  length -= tag.totalLength;
520  }
521 
522  //Successful processing
523  return NO_ERROR;
524 }
525 
526 
527 /**
528  * @brief Parse PolicyConstraints extension
529  * @param[in] critical Critical extension flag
530  * @param[in] data Pointer to the ASN.1 structure to parse
531  * @param[in] length Length of the ASN.1 structure
532  * @return Error code
533  **/
534 
536  size_t length)
537 {
538  error_t error;
539  Asn1Tag tag;
540 
541  //Debug message
542  TRACE_DEBUG(" Parsing PolicyConstraints...\r\n");
543 
544  //The PolicyConstraints structure shall contain a valid sequence
545  error = asn1ReadSequence(data, length, &tag);
546  //Failed to decode ASN.1 tag?
547  if(error)
548  return error;
549 
550  //Conforming CAs must not issue certificates where policy constraints is an
551  //empty sequence (refer to RFC 5280, section 4.2.1.11)
552  if(tag.length == 0)
553  return ERROR_INVALID_SYNTAX;
554 
555  //Successful processing
556  return NO_ERROR;
557 }
558 
559 
560 /**
561  * @brief Parse PolicyMappings extension
562  * @param[in] critical Critical extension flag
563  * @param[in] data Pointer to the ASN.1 structure to parse
564  * @param[in] length Length of the ASN.1 structure
565  * @return Error code
566  **/
567 
569  size_t length)
570 {
571  error_t error;
572  Asn1Tag tag;
573 
574  //Debug message
575  TRACE_DEBUG(" Parsing PolicyMappings...\r\n");
576 
577  //The PolicyMappings structure shall contain a valid sequence
578  error = asn1ReadSequence(data, length, &tag);
579  //Failed to decode ASN.1 tag?
580  if(error)
581  return error;
582 
583  //The sequence cannot be empty (refer to RFC 5280, section 4.2.1.5)
584  if(tag.length == 0)
585  return ERROR_INVALID_SYNTAX;
586 
587  //Successful processing
588  return NO_ERROR;
589 }
590 
591 
592 /**
593  * @brief Parse InhibitAnyPolicy extension
594  * @param[in] critical Critical extension flag
595  * @param[in] data Pointer to the ASN.1 structure to parse
596  * @param[in] length Length of the ASN.1 structure
597  * @return Error code
598  **/
599 
601  size_t length)
602 {
603  //Debug message
604  TRACE_DEBUG(" Parsing InhibitAnyPolicy...\r\n");
605 
606  //Successful processing
607  return NO_ERROR;
608 }
609 
610 
611 /**
612  * @brief Parse KeyUsage extension
613  * @param[in] critical Critical extension flag
614  * @param[in] data Pointer to the ASN.1 structure to parse
615  * @param[in] length Length of the ASN.1 structure
616  * @param[out] keyUsage Information resulting from the parsing process
617  * @return Error code
618  **/
619 
621  size_t length, X509KeyUsage *keyUsage)
622 {
623  error_t error;
624  Asn1Tag tag;
625 
626  //Debug message
627  TRACE_DEBUG(" Parsing KeyUsage...\r\n");
628 
629  //An extension can be marked as critical
630  keyUsage->critical = critical;
631 
632  //The key usage extension defines the purpose of the key contained in the
633  //certificate
634  error = asn1ReadTag(data, length, &tag);
635  //Failed to decode ASN.1 tag?
636  if(error)
637  return error;
638 
639  //Enforce encoding, class and type
640  error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL,
642  //Invalid tag?
643  if(error)
644  return error;
645 
646  //The bit string shall contain an initial octet which encodes the number
647  //of unused bits in the final subsequent octet
648  if(tag.length < 1)
649  return ERROR_INVALID_SYNTAX;
650 
651  //Sanity check
652  if(tag.value[0] >= 8)
653  return ERROR_INVALID_SYNTAX;
654 
655  //Clear bit string
656  keyUsage->bitmap = 0;
657 
658  //Read bits b0 to b7
659  if(tag.length >= 2)
660  {
661  keyUsage->bitmap |= reverseInt8(tag.value[1]);
662  }
663 
664  //Read bits b8 to b15
665  if(tag.length >= 3)
666  {
667  keyUsage->bitmap |= reverseInt8(tag.value[2]) << 8;
668  }
669 
670  //When the key usage extension appears in a certificate, at least one of
671  //the bits must be set to 1 (refer to RFC 5280, section 4.2.1.3)
672  if(keyUsage->bitmap == 0)
673  return ERROR_INVALID_SYNTAX;
674 
675  //Successful processing
676  return NO_ERROR;
677 }
678 
679 
680 /**
681  * @brief Parse ExtendedKeyUsage extension
682  * @param[in] critical Critical extension flag
683  * @param[in] data Pointer to the ASN.1 structure to parse
684  * @param[in] length Length of the ASN.1 structure
685  * @param[out] extKeyUsage Information resulting from the parsing process
686  * @return Error code
687  **/
688 
690  size_t length, X509ExtendedKeyUsage *extKeyUsage)
691 {
692  error_t error;
693  Asn1Tag tag;
694 
695  //Debug message
696  TRACE_DEBUG(" Parsing ExtendedKeyUsage...\r\n");
697 
698  //An extension can be marked as critical
699  extKeyUsage->critical = critical;
700 
701  //The ExtendedKeyUsage structure shall contain a valid sequence
702  error = asn1ReadSequence(data, length, &tag);
703  //Failed to decode ASN.1 tag?
704  if(error)
705  return error;
706 
707  //The sequence cannot be empty (refer to RFC 5280, section 4.2.1.12)
708  if(tag.length == 0)
709  return ERROR_INVALID_SYNTAX;
710 
711  //Point to the first item of the sequence
712  data = tag.value;
713  length = tag.length;
714 
715  //This extension indicates one or more purposes for which the certified
716  //public key may be used
717  while(length > 0)
718  {
719  //Read KeyPurposeId field
720  error = asn1ReadOid(data, length, &tag);
721  //Failed to decode ASN.1 tag?
722  if(error)
723  return error;
724 
725  //anyExtendedKeyUsage?
726  if(OID_COMP(tag.value, tag.length, X509_ANY_EXT_KEY_USAGE_OID) == 0)
727  {
728  //If a CA includes extended key usages to satisfy such applications,
729  //but does not wish to restrict usages of the key, the CA can include
730  //the special KeyPurposeId anyExtendedKeyUsage
731  extKeyUsage->bitmap |= X509_EXT_KEY_USAGE_ANY;
732  }
733  //id-kp-serverAuth?
734  else if(OID_COMP(tag.value, tag.length, X509_KP_SERVER_AUTH_OID) == 0)
735  {
736  //TLS WWW server authentication
737  extKeyUsage->bitmap |= X509_EXT_KEY_USAGE_SERVER_AUTH;
738  }
739  //id-kp-clientAuth?
740  else if(OID_COMP(tag.value, tag.length, X509_KP_CLIENT_AUTH_OID) == 0)
741  {
742  //TLS WWW client authentication
743  extKeyUsage->bitmap |= X509_EXT_KEY_USAGE_CLIENT_AUTH;
744  }
745  //id-kp-codeSigning?
746  else if(OID_COMP(tag.value, tag.length, X509_KP_CODE_SIGNING_OID) == 0)
747  {
748  //Signing of downloadable executable code
749  extKeyUsage->bitmap |= X509_EXT_KEY_USAGE_CODE_SIGNING;
750  }
751  //id-kp-emailProtection?
752  else if(OID_COMP(tag.value, tag.length, X509_KP_EMAIL_PROTECTION_OID) == 0)
753  {
754  //Email protection
756  }
757  //id-kp-ipsecEndSystem?
758  else if(OID_COMP(tag.value, tag.length, X509_KP_IPSEC_END_SYSTEM_OID) == 0)
759  {
760  //IPsec end system
762  }
763  //id-kp-ipsecTunnel?
764  else if(OID_COMP(tag.value, tag.length, X509_KP_IPSEC_TUNNEL_OID) == 0)
765  {
766  //IPsec tunnel
767  extKeyUsage->bitmap |= X509_EXT_KEY_USAGE_IPSEC_TUNNEL;
768  }
769  //id-kp-ipsecUser?
770  else if(OID_COMP(tag.value, tag.length, X509_KP_IPSEC_USER_OID) == 0)
771  {
772  //IPsec user
773  extKeyUsage->bitmap |= X509_EXT_KEY_USAGE_IPSEC_USER;
774  }
775  //id-kp-timeStamping?
776  else if(OID_COMP(tag.value, tag.length, X509_KP_TIME_STAMPING_OID) == 0)
777  {
778  //Binding the hash of an object to a time
780  }
781  //id-kp-OCSPSigning?
782  else if(OID_COMP(tag.value, tag.length, X509_KP_OCSP_SIGNING_OID) == 0)
783  {
784  //Signing OCSP responses
785  extKeyUsage->bitmap |= X509_EXT_KEY_USAGE_OCSP_SIGNING;
786  }
787  //id-kp-ipsecIKE?
788  else if(OID_COMP(tag.value, tag.length, X509_KP_IPSEC_IKE_OID) == 0)
789  {
790  //The certificate is intended to be used with IKE
791  extKeyUsage->bitmap |= X509_EXT_KEY_USAGE_IPSEC_IKE;
792  }
793  //id-kp-secureShellClient?
794  else if(OID_COMP(tag.value, tag.length, X509_KP_SSH_CLIENT_OID) == 0)
795  {
796  //The key can be used for a Secure Shell client
797  extKeyUsage->bitmap |= X509_EXT_KEY_USAGE_SSH_CLIENT;
798  }
799  //id-kp-secureShellServer?
800  else if(OID_COMP(tag.value, tag.length, X509_KP_SSH_SERVER_OID) == 0)
801  {
802  //The key can be used for a Secure Shell server
803  extKeyUsage->bitmap |= X509_EXT_KEY_USAGE_SSH_SERVER;
804  }
805  //id-kp-cmcCA?
806  else if(OID_COMP(tag.value, tag.length, X509_KP_CMC_CA_OID) == 0)
807  {
808  //CMC Certification Authorities are identified by the id-kp-cmcCA
809  //extended key usage (refer to RFC 6402, section 2.10)
810  extKeyUsage->bitmap |= X509_EXT_KEY_USAGE_CMC_CA;
811  }
812  //id-kp-cmcRA?
813  else if(OID_COMP(tag.value, tag.length, X509_KP_CMC_RA_OID) == 0)
814  {
815  //CMC Registration Authorities are identified by the id-kp-cmcRA
816  //extended key usage (refer to RFC 6402, section 2.10)
817  extKeyUsage->bitmap |= X509_EXT_KEY_USAGE_CMC_RA;
818  }
819  //id-kp-documentSigning?
820  else if(OID_COMP(tag.value, tag.length, X509_KP_DOC_SIGNING_OID) == 0)
821  {
822  //The public key encoded in the certificate has been certified to be
823  //used for cryptographic operations on contents that are consumed by
824  //people (refer to RFC 9336, section 3.1)
825  extKeyUsage->bitmap |= X509_EXT_KEY_USAGE_DOC_SIGNING;
826  }
827  //Unknown key purpose?
828  else
829  {
830  //Discard KeyPurposeId field
831  }
832 
833  //Next item
834  data += tag.totalLength;
835  length -= tag.totalLength;
836  }
837 
838  //Successful processing
839  return NO_ERROR;
840 }
841 
842 
843 /**
844  * @brief Parse SubjectAltName extension
845  * @param[in] critical Critical extension flag
846  * @param[in] data Pointer to the ASN.1 structure to parse
847  * @param[in] length Length of the ASN.1 structure
848  * @param[out] subjectAltName Information resulting from the parsing process
849  * @return Error code
850  **/
851 
853  size_t length, X509SubjectAltName *subjectAltName)
854 {
855  error_t error;
856  Asn1Tag tag;
857 
858  //Debug message
859  TRACE_DEBUG(" Parsing SubjectAltName...\r\n");
860 
861  //An extension can be marked as critical
862  subjectAltName->critical = critical;
863 
864  //The SubjectAltName structure shall contain a valid sequence
865  error = asn1ReadSequence(data, length, &tag);
866  //Failed to decode ASN.1 tag?
867  if(error)
868  return error;
869 
870  //Raw contents of the ASN.1 sequence
871  subjectAltName->raw.value = tag.value;
872  subjectAltName->raw.length = tag.length;
873 
874  //The subject alternative name extension allows identities to be bound to the
875  //subject of the certificate. These identities may be included in addition
876  //to or in place of the identity in the subject field of the certificate
877  return x509ParseGeneralNames(tag.value, tag.length,
878  subjectAltName->generalNames, X509_MAX_SUBJECT_ALT_NAMES,
879  &subjectAltName->numGeneralNames);
880 }
881 
882 
883 /**
884  * @brief Parse SubjectKeyIdentifier extension
885  * @param[in] critical Critical extension flag
886  * @param[in] data Pointer to the ASN.1 structure to parse
887  * @param[in] length Length of the ASN.1 structure
888  * @param[out] subjectKeyId Information resulting from the parsing process
889  * @return Error code
890  **/
891 
893  size_t length, X509SubjectKeyId *subjectKeyId)
894 {
895  error_t error;
896  Asn1Tag tag;
897 
898  //Debug message
899  TRACE_DEBUG(" Parsing SubjectKeyIdentifier...\r\n");
900 
901  //An extension can be marked as critical
902  subjectKeyId->critical = critical;
903 
904  //The subject key identifier extension provides a means of identifying
905  //certificates that contain a particular public key
906  error = asn1ReadOctetString(data, length, &tag);
907  //Failed to decode ASN.1 tag?
908  if(error)
909  return error;
910 
911  //Save the subject key identifier
912  subjectKeyId->value = tag.value;
913  subjectKeyId->length = tag.length;
914 
915  //Successful processing
916  return NO_ERROR;
917 }
918 
919 
920 /**
921  * @brief Parse AuthorityKeyIdentifier extension
922  * @param[in] critical Critical extension flag
923  * @param[in] data Pointer to the ASN.1 structure to parse
924  * @param[in] length Length of the ASN.1 structure
925  * @param[out] authKeyId Information resulting from the parsing process
926  * @return Error code
927  **/
928 
930  size_t length, X509AuthKeyId *authKeyId)
931 {
932  error_t error;
933  Asn1Tag tag;
934 
935  //Debug message
936  TRACE_DEBUG(" Parsing AuthorityKeyIdentifier...\r\n");
937 
938  //An extension can be marked as critical
939  authKeyId->critical = critical;
940 
941  //The AuthorityKeyIdentifier structure shall contain a valid sequence
942  error = asn1ReadSequence(data, length, &tag);
943  //Failed to decode ASN.1 tag?
944  if(error)
945  return error;
946 
947  //Point to the first item of the sequence
948  data = tag.value;
949  length = tag.length;
950 
951  //Parse the content of the sequence
952  while(length > 0)
953  {
954  //Read current item
955  error = asn1ReadTag(data, length, &tag);
956  //Failed to decode ASN.1 tag?
957  if(error)
958  return error;
959 
960  //Implicit tagging shall be used to encode the item
962  return ERROR_INVALID_CLASS;
963 
964  //keyIdentifier object found?
965  if(tag.objType == 0)
966  {
967  //Save the authority key identifier
968  authKeyId->keyId.value = tag.value;
969  authKeyId->keyId.length = tag.length;
970  }
971 
972  //Next item
973  data += tag.totalLength;
974  length -= tag.totalLength;
975  }
976 
977  //Successful processing
978  return NO_ERROR;
979 }
980 
981 
982 /**
983  * @brief Parse CRLDistributionPoints extension
984  * @param[in] critical Critical extension flag
985  * @param[in] data Pointer to the ASN.1 structure to parse
986  * @param[in] length Length of the ASN.1 structure
987  * @param[out] crlDistrPoints Information resulting from the parsing process
988  * @return Error code
989  **/
990 
992  size_t length, X509CrlDistrPoints *crlDistrPoints)
993 {
994  error_t error;
995  uint_t i;
996  size_t n;
997  Asn1Tag tag;
998  X509DistrPoint distrPoint;
999 
1000  //Debug message
1001  TRACE_DEBUG(" Parsing CRLDistributionPoints...\r\n");
1002 
1003  //An extension can be marked as critical
1004  crlDistrPoints->critical = critical;
1005 
1006  //The CRLDistributionPoints structure shall contain a valid sequence
1007  error = asn1ReadSequence(data, length, &tag);
1008  //Failed to decode ASN.1 tag?
1009  if(error)
1010  return error;
1011 
1012  //Raw contents of the ASN.1 sequence
1013  crlDistrPoints->raw.value = tag.value;
1014  crlDistrPoints->raw.length = tag.length;
1015 
1016  //Point to the first item of the sequence
1017  data = tag.value;
1018  length = tag.length;
1019 
1020  //Parse the content of the sequence
1021  for(i = 0; length > 0; i++)
1022  {
1023  //Parse DistributionPoint field
1024  error = x509ParseDistrPoint(data, length, &n, &distrPoint);
1025  //Any error to report?
1026  if(error)
1027  return error;
1028 
1029  //Save distribution point
1030  if(i < X509_MAX_DISTR_POINTS)
1031  {
1032  crlDistrPoints->distrPoints[i] = distrPoint;
1033  }
1034 
1035  //Next item
1036  data += n;
1037  length -= n;
1038  }
1039 
1040  //If the CRLDistributionPoints extension is present, the sequence must
1041  //contain at least one entry (refer to RFC 5280, section 4.2.1.13)
1042  if(i == 0)
1043  return ERROR_INVALID_SYNTAX;
1044 
1045  //Save the number of distribution points
1046  crlDistrPoints->numDistrPoints = MIN(i, X509_MAX_DISTR_POINTS);
1047 
1048  //Successful processing
1049  return NO_ERROR;
1050 }
1051 
1052 
1053 /**
1054  * @brief Parse DistributionPoint field
1055  * @param[in] data Pointer to the ASN.1 structure to parse
1056  * @param[in] length Length of the ASN.1 structure
1057  * @param[out] totalLength Number of bytes that have been parsed
1058  * @param[out] distrPoint Information resulting from the parsing process
1059  * @return Error code
1060  **/
1061 
1062 error_t x509ParseDistrPoint(const uint8_t *data, size_t length,
1063  size_t *totalLength, X509DistrPoint *distrPoint)
1064 {
1065  error_t error;
1066  Asn1Tag tag;
1067 
1068  //Clear the structure
1069  osMemset(distrPoint, 0, sizeof(X509DistrPoint));
1070 
1071  //The DistributionPoint structure shall contain a valid sequence
1072  error = asn1ReadSequence(data, length, &tag);
1073  //Failed to decode ASN.1 tag?
1074  if(error)
1075  return error;
1076 
1077  //Save the total length of the field
1078  *totalLength = tag.totalLength;
1079 
1080  //Point to the first item of the sequence
1081  data = tag.value;
1082  length = tag.length;
1083 
1084  //Parse the content of the sequence
1085  while(length > 0)
1086  {
1087  //Read current item
1088  error = asn1ReadTag(data, length, &tag);
1089  //Failed to decode ASN.1 tag?
1090  if(error)
1091  return error;
1092 
1093  //Implicit tagging shall be used to encode the item
1095  return ERROR_INVALID_CLASS;
1096 
1097  //A DistributionPoint consists of three fields, each of which is optional
1098  if(tag.objType == 0)
1099  {
1100  //Parse DistributionPointName field
1101  error = x509ParseDistrPointName(tag.value, tag.length,
1102  &distrPoint->distrPointName);
1103  }
1104  else if(tag.objType == 1)
1105  {
1106  //Parse ReasonFlags field
1107  error = x509ParseReasonFlags(tag.value, tag.length,
1108  &distrPoint->reasonFlags);
1109  }
1110  else if(tag.objType == 2)
1111  {
1112  //Parse CRLIssuer field
1113  error = x509ParseGeneralNames(tag.value, tag.length,
1114  distrPoint->crlIssuers, X509_MAX_CRL_ISSUERS,
1115  &distrPoint->numCrlIssuers);
1116  }
1117  else
1118  {
1119  //Report an error
1120  error = ERROR_INVALID_TYPE;
1121  }
1122 
1123  //Any error to report?
1124  if(error)
1125  return error;
1126 
1127  //Next item
1128  data += tag.totalLength;
1129  length -= tag.totalLength;
1130  }
1131 
1132  //Successful processing
1133  return NO_ERROR;
1134 }
1135 
1136 
1137 /**
1138  * @brief Parse DistributionPointName field
1139  * @param[in] data Pointer to the ASN.1 structure to parse
1140  * @param[in] length Length of the ASN.1 structure
1141  * @param[out] distrPointName Information resulting from the parsing process
1142  * @return Error code
1143  **/
1144 
1146  X509DistrPointName *distrPointName)
1147 {
1148  error_t error;
1149  Asn1Tag tag;
1150 
1151  //Parse ASN.1 tag
1152  error = asn1ReadTag(data, length, &tag);
1153  //Failed to decode ASN.1 tag?
1154  if(error)
1155  return error;
1156 
1157  //Implicit tagging shall be used to encode the item
1159  return ERROR_INVALID_CLASS;
1160 
1161  //When the distributionPoint field is present, it contains either a
1162  //sequence of general names or a single value, nameRelativeToCRLIssuer
1163  if(tag.objType == 0)
1164  {
1165  //Parse fullName field
1166  error = x509ParseGeneralNames(tag.value, tag.length,
1167  distrPointName->fullNames, X509_MAX_FULL_NAMES,
1168  &distrPointName->numFullNames);
1169  }
1170  else if(tag.objType == 1)
1171  {
1172  //Parse nameRelativeToCRLIssuer field
1173  error = x509ParseRelativeName(tag.value, tag.length,
1174  &distrPointName->relativeName);
1175  }
1176  else
1177  {
1178  //Report an error
1179  error = ERROR_INVALID_TYPE;
1180  }
1181 
1182  //Return status code
1183  return error;
1184 }
1185 
1186 
1187 /**
1188  * @brief Parse nameRelativeToCRLIssuer field
1189  * @param[in] data Pointer to the ASN.1 structure to parse
1190  * @param[in] length Length of the ASN.1 structure
1191  * @param[out] relativeName Information resulting from the parsing process
1192  * @return Error code
1193  **/
1194 
1195 error_t x509ParseRelativeName(const uint8_t *data, size_t length,
1196  X509NameAttribute *relativeName)
1197 {
1198  error_t error;
1199  Asn1Tag tag;
1200 
1201  //Read the first field of the set
1202  error = asn1ReadSequence(data, length, &tag);
1203  //Failed to decode ASN.1 tag?
1204  if(error)
1205  return error;
1206 
1207  //Point to the first field of the sequence
1208  data = tag.value;
1209  length = tag.length;
1210 
1211  //Read AttributeType field
1212  error = asn1ReadOid(data, length, &tag);
1213  //Failed to decode ASN.1 tag?
1214  if(error)
1215  return error;
1216 
1217  //Save attribute type
1218  relativeName->oid.value = tag.value;
1219  relativeName->oid.length = tag.length;
1220 
1221  //Point to the next field
1222  data += tag.totalLength;
1223  length -= tag.totalLength;
1224 
1225  //Read AttributeValue field
1226  error = asn1ReadTag(data, length, &tag);
1227  //Failed to decode ASN.1 tag?
1228  if(error)
1229  return error;
1230 
1231  //Save ASN.1 string type
1232  relativeName->type = tag.objType;
1233 
1234  //Save attribute value
1235  relativeName->data.value = (char_t *) tag.value;
1236  relativeName->data.length = tag.length;
1237 
1238  //Successful processing
1239  return NO_ERROR;
1240 }
1241 
1242 
1243 /**
1244  * @brief Parse ReasonFlags field
1245  * @param[in] data Pointer to the ASN.1 structure to parse
1246  * @param[in] length Length of the ASN.1 structure
1247  * @param[out] reasonFlags Information resulting from the parsing process
1248  * @return Error code
1249  **/
1250 
1251 error_t x509ParseReasonFlags(const uint8_t *data, size_t length,
1252  uint16_t *reasonFlags)
1253 {
1254  //The bit string shall contain an initial octet which encodes the number
1255  //of unused bits in the final subsequent octet
1256  if(length < 1)
1257  return ERROR_INVALID_SYNTAX;
1258 
1259  //Sanity check
1260  if(data[0] >= 8)
1261  return ERROR_INVALID_SYNTAX;
1262 
1263  //Clear bit string
1264  *reasonFlags = 0;
1265 
1266  //Read bits b0 to b7
1267  if(length >= 2)
1268  {
1269  *reasonFlags |= reverseInt8(data[1]);
1270  }
1271 
1272  //Read bits b8 to b15
1273  if(length >= 3)
1274  {
1275  *reasonFlags |= reverseInt8(data[2]) << 8;
1276  }
1277 
1278  //Successful processing
1279  return NO_ERROR;
1280 }
1281 
1282 
1283 /**
1284  * @brief Parse AuthorityInformationAccess extension
1285  * @param[in] critical Critical extension flag
1286  * @param[in] data Pointer to the ASN.1 structure to parse
1287  * @param[in] length Length of the ASN.1 structure
1288  * @param[out] authInfoAccess Information resulting from the parsing process
1289  * @return Error code
1290  **/
1291 
1293  size_t length, X509AuthInfoAccess *authInfoAccess)
1294 {
1295  error_t error;
1296  uint_t i;
1297  size_t n;
1298  Asn1Tag tag;
1299  X509AccessDescription accessDescription;
1300 
1301  //Debug message
1302  TRACE_DEBUG(" Parsing AuthorityInformationAccess...\r\n");
1303 
1304  //An extension can be marked as critical
1305  authInfoAccess->critical = critical;
1306 
1307  //The AuthorityInformationAccess structure shall contain a valid sequence
1308  error = asn1ReadSequence(data, length, &tag);
1309  //Failed to decode ASN.1 tag?
1310  if(error)
1311  return error;
1312 
1313  //Raw contents of the ASN.1 sequence
1314  authInfoAccess->raw.value = tag.value;
1315  authInfoAccess->raw.length = tag.length;
1316 
1317  //Point to the first item of the sequence
1318  data = tag.value;
1319  length = tag.length;
1320 
1321  //Parse the content of the sequence
1322  for(i = 0; length > 0; i++)
1323  {
1324  //Parse AccessDescription field
1325  error = x509ParseAccessDescription(data, length, &n, &accessDescription);
1326  //Any error to report?
1327  if(error)
1328  return error;
1329 
1330  //Save access description
1332  {
1333  authInfoAccess->accessDescriptions[i] = accessDescription;
1334  }
1335 
1336  //Next item
1337  data += n;
1338  length -= n;
1339  }
1340 
1341  //If the AuthorityInformationAccess extension is present, the sequence must
1342  //contain at least one entry (refer to RFC 5280, section 4.2.2.1)
1343  if(i == 0)
1344  return ERROR_INVALID_SYNTAX;
1345 
1346  //Save the number of access descriptions
1348 
1349  //Successful processing
1350  return NO_ERROR;
1351 }
1352 
1353 
1354 /**
1355  * @brief Parse AccessDescription field
1356  * @param[in] data Pointer to the ASN.1 structure to parse
1357  * @param[in] length Length of the ASN.1 structure
1358  * @param[out] totalLength Number of bytes that have been parsed
1359  * @param[out] accessDescription Information resulting from the parsing process
1360  * @return Error code
1361  **/
1362 
1364  size_t *totalLength, X509AccessDescription *accessDescription)
1365 {
1366  error_t error;
1367  size_t n;
1368  Asn1Tag tag;
1369 
1370  //Clear the structure
1371  osMemset(accessDescription, 0, sizeof(X509AccessDescription));
1372 
1373  //The AccessDescription structure shall contain a valid sequence
1374  error = asn1ReadSequence(data, length, &tag);
1375  //Failed to decode ASN.1 tag?
1376  if(error)
1377  return error;
1378 
1379  //Save the total length of the field
1380  *totalLength = tag.totalLength;
1381 
1382  //Point to the first item of the sequence
1383  data = tag.value;
1384  length = tag.length;
1385 
1386  //Read accessMethod field
1387  error = asn1ReadOid(data, length, &tag);
1388  //Failed to decode ASN.1 tag?
1389  if(error)
1390  return error;
1391 
1392  //The type and format of the information are specified by the accessMethod
1393  //field (refer to RFC 5280, section 4.2.2.1)
1394  accessDescription->accessMethod.value = tag.value;
1395  accessDescription->accessMethod.length = tag.length;
1396 
1397  //Point to the next field
1398  data += tag.totalLength;
1399  length -= tag.totalLength;
1400 
1401  //The accessLocation field specifies the location of the information
1402  error = x509ParseGeneralName(data, length, &n,
1403  &accessDescription->accessLocation);
1404  //Failed to decode ASN.1 tag?
1405  if(error)
1406  return error;
1407 
1408  //Point to the next field
1409  data += n;
1410  length -= n;
1411 
1412  //Successful processing
1413  return NO_ERROR;
1414 }
1415 
1416 
1417 /**
1418  * @brief Parse PkixOcspNoCheck extension
1419  * @param[in] critical Critical extension flag
1420  * @param[in] data Pointer to the ASN.1 structure to parse
1421  * @param[in] length Length of the ASN.1 structure
1422  * @param[out] pkixOcspNoCheck Information resulting from the parsing process
1423  * @return Error code
1424  **/
1425 
1427  size_t length, X509PkixOcspNoCheck *pkixOcspNoCheck)
1428 {
1429  error_t error;
1430  Asn1Tag tag;
1431 
1432  //Debug message
1433  TRACE_DEBUG(" Parsing PkixOcspNoCheck...\r\n");
1434 
1435  //The extension should be a non-critical extension
1436  pkixOcspNoCheck->critical = critical;
1437 
1438  //The value of the extension shall be NULL (refer to RFC 6960,
1439  //section 4.2.2.2.1)
1440  error = asn1ReadTag(data, length, &tag);
1441  //Failed to decode ASN.1 tag?
1442  if(error)
1443  return error;
1444 
1445  //Enforce encoding, class and type
1447  //Invalid tag?
1448  if(error)
1449  return error;
1450 
1451  //The certificate contains a valid id-pkix-ocsp-nocheck extension
1452  pkixOcspNoCheck->present = TRUE;
1453 
1454  //Successful processing
1455  return NO_ERROR;
1456 }
1457 
1458 
1459 /**
1460  * @brief Parse NetscapeCertType extension
1461  * @param[in] critical Critical extension flag
1462  * @param[in] data Pointer to the ASN.1 structure to parse
1463  * @param[in] length Length of the ASN.1 structure
1464  * @param[out] nsCertType Information resulting from the parsing process
1465  * @return Error code
1466  **/
1467 
1469  size_t length, X509NsCertType *nsCertType)
1470 {
1471  error_t error;
1472  Asn1Tag tag;
1473 
1474  //Debug message
1475  TRACE_DEBUG(" Parsing NetscapeCertType...\r\n");
1476 
1477  //An extension can be marked as critical
1478  nsCertType->critical = critical;
1479 
1480  //The NetscapeCertType extension limit the use of a certificate
1481  error = asn1ReadTag(data, length, &tag);
1482  //Failed to decode ASN.1 tag?
1483  if(error)
1484  return error;
1485 
1486  //Enforce encoding, class and type
1487  error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL,
1489  //Invalid tag?
1490  if(error)
1491  return error;
1492 
1493  //The bit string shall contain an initial octet which encodes the number
1494  //of unused bits in the final subsequent octet
1495  if(tag.length < 1)
1496  return ERROR_INVALID_SYNTAX;
1497 
1498  //Sanity check
1499  if(tag.value[0] >= 8)
1500  return ERROR_INVALID_SYNTAX;
1501 
1502  //Clear bit string
1503  nsCertType->bitmap = 0;
1504 
1505  //Read bits b0 to b7
1506  if(tag.length >= 2)
1507  {
1508  nsCertType->bitmap |= reverseInt8(tag.value[1]);
1509  }
1510 
1511  //Successful processing
1512  return NO_ERROR;
1513 }
1514 
1515 
1516 /**
1517  * @brief Parse unknown X.509 certificate extension
1518  * @param[in] oid Extension identifier
1519  * @param[in] oidLen Length of the extension identifier
1520  * @param[in] critical Critical extension flag
1521  * @param[in] data Extension value
1522  * @param[in] dataLen Length of the extension value
1523  * @param[out] extensions Information resulting from the parsing process
1524  * @return Error code
1525  **/
1526 
1527 __weak_func error_t x509ParseUnknownCertExtension(const uint8_t *oid,
1528  size_t oidLen, bool_t critical, const uint8_t *data, size_t dataLen,
1530 {
1531  //The extension is not supported
1533 }
1534 
1535 
1536 /**
1537  * @brief Check whether the specified extension is a duplicate
1538  * @param[in] oid Extension identifier
1539  * @param[in] oidLen Length of the extension identifier
1540  * @param[in] data Pointer to the extension list
1541  * @param[in] length Length of the extension list
1542  * @return Error code
1543  **/
1544 
1546  const uint8_t *data, size_t length)
1547 {
1548  error_t error;
1549  size_t n;
1550  X509Extension extension;
1551 
1552  //Loop through the extensions
1553  while(length > 0)
1554  {
1555  //Each extension includes an OID and a value
1556  error = x509ParseExtension(data, length, &n, &extension);
1557  //Any error to report?
1558  if(error)
1559  return error;
1560 
1561  //A certificate must not include more than one instance of a particular
1562  //extension (refer to RFC 5280, section 4.2)
1563  if(oidComp(extension.oid.value, extension.oid.length, oid, oidLen) == 0)
1564  {
1565  return ERROR_INVALID_SYNTAX;
1566  }
1567 
1568  //Jump to the next extension
1569  data += n;
1570  length -= n;
1571  }
1572 
1573  //Successful verification
1574  return NO_ERROR;
1575 }
1576 
1577 #endif
error_t x509ParseGeneralNames(const uint8_t *data, size_t length, X509GeneralName *generalNames, uint_t maxGeneralNames, uint_t *numGeneralNames)
Parse GeneralNames field.
#define X509_MAX_FULL_NAMES
Definition: x509_common.h:457
@ X509_EXT_KEY_USAGE_ANY
Definition: x509_common.h:559
X.509 certificate parsing.
uint8_t extensions[]
Definition: ntp_common.h:213
@ X509_EXT_KEY_USAGE_SSH_CLIENT
Definition: x509_common.h:554
@ X509_EXT_KEY_USAGE_IPSEC_IKE
Definition: x509_common.h:553
int bool_t
Definition: compiler_port.h:61
error_t x509ParseDistrPoint(const uint8_t *data, size_t length, size_t *totalLength, X509DistrPoint *distrPoint)
Parse DistributionPoint field.
X509GeneralName accessLocation
Definition: x509_common.h:997
X509DistrPointName distrPointName
Definition: x509_common.h:970
__weak_func error_t x509ParseUnknownCertExtension(const uint8_t *oid, size_t oidLen, bool_t critical, const uint8_t *data, size_t dataLen, X509Extensions *extensions)
Parse unknown X.509 certificate extension.
const uint8_t X509_KP_DOC_SIGNING_OID[8]
Definition: x509_common.c:158
@ X509_EXT_KEY_USAGE_CMC_CA
Definition: x509_common.h:556
const uint8_t X509_KP_SERVER_AUTH_OID[8]
Definition: x509_common.c:130
@ X509_EXT_KEY_USAGE_CMC_RA
Definition: x509_common.h:557
X509OctetString accessMethod
Definition: x509_common.h:996
const uint8_t X509_SUBJECT_ALT_NAME_OID[3]
Definition: x509_common.c:85
error_t x509ParseCertExtensions(const uint8_t *data, size_t length, size_t *totalLength, X509Extensions *extensions, const X509Options *options)
Parse X.509 certificate extensions.
error_t x509ParseGeneralSubtrees(const uint8_t *data, size_t length)
Parse GeneralSubtrees field.
#define X509_MAX_CRL_ISSUERS
Definition: x509_common.h:443
X509OctetString raw
Definition: x509_common.h:923
const uint8_t X509_KP_CODE_SIGNING_OID[8]
Definition: x509_common.c:134
OID (Object Identifier)
error_t x509ParseExtendedKeyUsage(bool_t critical, const uint8_t *data, size_t length, X509ExtendedKeyUsage *extKeyUsage)
Parse ExtendedKeyUsage extension.
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:224
X509OctetString raw
Definition: x509_common.h:984
const uint8_t X509_EXTENDED_KEY_USAGE_OID[3]
Definition: x509_common.c:115
const uint8_t X509_ANY_EXT_KEY_USAGE_OID[4]
Definition: x509_common.c:128
const uint8_t X509_KEY_USAGE_OID[3]
Definition: x509_common.c:83
const uint8_t X509_KP_TIME_STAMPING_OID[8]
Definition: x509_common.c:144
@ X509_EXT_KEY_USAGE_IPSEC_USER
Definition: x509_common.h:550
uint16_t totalLength
Definition: ipv4.h:323
@ X509_EXT_KEY_USAGE_CLIENT_AUTH
Definition: x509_common.h:545
@ X509_EXT_KEY_USAGE_SSH_SERVER
Definition: x509_common.h:555
const uint8_t X509_NAME_CONSTRAINTS_OID[3]
Definition: x509_common.c:103
@ X509_EXT_KEY_USAGE_IPSEC_END_SYSTEM
Definition: x509_common.h:548
bool_t critical
Definition: x509_common.h:947
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
const uint8_t X509_KP_OCSP_SIGNING_OID[8]
Definition: x509_common.c:146
error_t x509ParseReasonFlags(const uint8_t *data, size_t length, uint16_t *reasonFlags)
Parse ReasonFlags field.
X.509 extension parsing.
X509GeneralName crlIssuers[X509_MAX_CRL_ISSUERS]
Definition: x509_common.h:973
#define X509_MAX_SUBJECT_ALT_NAMES
Definition: x509_common.h:429
size_t length
Definition: x509_common.h:694
Subject Key Identifier extension.
Definition: x509_common.h:934
int_t oidComp(const uint8_t *oid1, size_t oidLen1, const uint8_t *oid2, size_t oidLen2)
Compare object identifiers.
Definition: oid.c:103
X509GeneralName fullNames[X509_MAX_FULL_NAMES]
Definition: x509_common.h:959
uint8_t oid[]
Definition: lldp_tlv.h:300
error_t asn1ReadOid(const uint8_t *data, size_t length, Asn1Tag *tag)
Read an object identifier from the input stream.
Definition: asn1.c:218
Certificate parsing options.
Definition: x509_common.h:1336
Distribution Point Name structure.
Definition: x509_common.h:957
uint_t numAccessDescriptions
Definition: x509_common.h:1009
const uint8_t X509_BASIC_CONSTRAINTS_OID[3]
Definition: x509_common.c:89
error_t x509ParseNsCertType(bool_t critical, const uint8_t *data, size_t length, X509NsCertType *nsCertType)
Parse NetscapeCertType extension.
size_t totalLength
Definition: asn1.h:111
error_t x509ParsePkixOcspNoCheck(bool_t critical, const uint8_t *data, size_t length, X509PkixOcspNoCheck *pkixOcspNoCheck)
Parse PkixOcspNoCheck extension.
size_t length
Definition: asn1.h:109
#define FALSE
Definition: os_port.h:46
error_t asn1ReadOctetString(const uint8_t *data, size_t length, Asn1Tag *tag)
Read an octet string from the input stream.
Definition: asn1.c:190
Authority Information Access extension.
Definition: x509_common.h:1006
bool_t critical
Definition: x509_common.h:888
error_t x509ParsePolicyMappings(bool_t critical, const uint8_t *data, size_t length)
Parse PolicyMappings extension.
const uint8_t X509_AUTH_INFO_ACCESS_OID[8]
Definition: x509_common.c:121
@ ERROR_UNSUPPORTED_EXTENSION
Definition: error.h:246
error_t
Error codes.
Definition: error.h:43
error_t x509CheckDuplicateExtension(const uint8_t *oid, size_t oidLen, const uint8_t *data, size_t length)
Check whether the specified extension is a duplicate.
error_t x509ParseInhibitAnyPolicy(bool_t critical, const uint8_t *data, size_t length)
Parse InhibitAnyPolicy extension.
error_t x509ParseAuthInfoAccess(bool_t critical, const uint8_t *data, size_t length, X509AuthInfoAccess *authInfoAccess)
Parse AuthorityInformationAccess extension.
Name attribute.
Definition: x509_common.h:753
Extended Key Usage extension.
Definition: x509_common.h:898
Distribution Point structure.
Definition: x509_common.h:969
#define ASN1_CLASS_UNIVERSAL
Definition: asn1.h:52
error_t x509ParseExtension(const uint8_t *data, size_t length, size_t *totalLength, X509Extension *extension)
Parse X.509 certificate extension.
ASN.1 tag.
Definition: asn1.h:105
X509NameAttribute relativeName
Definition: x509_common.h:960
X509OctetString permittedSubtrees
Definition: x509_common.h:877
error_t x509ParseBasicConstraints(bool_t critical, const uint8_t *data, size_t length, X509BasicConstraints *basicConstraints)
Parse BasicConstraints extension.
uint16_t reasonFlags
Definition: x509_common.h:971
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
error_t x509ParseDistrPointName(const uint8_t *data, size_t length, X509DistrPointName *distrPointName)
Parse DistributionPointName field.
const uint8_t X509_KP_EMAIL_PROTECTION_OID[8]
Definition: x509_common.c:136
error_t x509ParseRelativeName(const uint8_t *data, size_t length, X509NameAttribute *relativeName)
Parse nameRelativeToCRLIssuer field.
#define X509_MAX_ACCESS_DESCRIPTIONS
Definition: x509_common.h:464
X.509 certificate extension.
Definition: x509_common.h:1041
const uint8_t X509_AUTHORITY_KEY_ID_OID[3]
Definition: x509_common.c:111
@ ERROR_INVALID_LENGTH
Definition: error.h:111
Authority Key Identifier extension.
Definition: x509_common.h:946
General definitions for cryptographic algorithms.
const uint8_t X509_KP_IPSEC_USER_OID[8]
Definition: x509_common.c:142
X509OctetString excludedSubtrees
Definition: x509_common.h:878
PKIX OCSP No Check extension.
Definition: x509_common.h:1019
const uint8_t X509_PKIX_OCSP_NO_CHECK_OID[9]
Definition: x509_common.c:123
error_t x509ParseAuthKeyId(bool_t critical, const uint8_t *data, size_t length, X509AuthKeyId *authKeyId)
Parse AuthorityKeyIdentifier extension.
@ ERROR_INVALID_TYPE
Definition: error.h:115
@ X509_EXT_KEY_USAGE_SERVER_AUTH
Definition: x509_common.h:544
uint_t objClass
Definition: asn1.h:107
const uint8_t X509_KP_IPSEC_IKE_OID[8]
Definition: x509_common.c:148
uint8_t length
Definition: tcp.h:375
uint16_t bitmap
Definition: x509_common.h:889
#define MIN(a, b)
Definition: os_port.h:63
const uint8_t X509_KP_CLIENT_AUTH_OID[8]
Definition: x509_common.c:132
Subject Alternative Name extension.
Definition: x509_common.h:921
error_t x509ParseAccessDescription(const uint8_t *data, size_t length, size_t *totalLength, X509AccessDescription *accessDescription)
Parse AccessDescription field.
@ X509_EXT_KEY_USAGE_DOC_SIGNING
Definition: x509_common.h:558
uint32_t dataLen
Definition: sftp_common.h:229
Access Description extension.
Definition: x509_common.h:995
const uint8_t X509_CRL_DISTR_POINTS_OID[3]
Definition: x509_common.c:105
@ X509_EXT_KEY_USAGE_TIME_STAMPING
Definition: x509_common.h:551
Netscape certificate type.
Definition: x509_common.h:1030
@ X509_EXT_KEY_USAGE_IPSEC_TUNNEL
Definition: x509_common.h:549
error_t x509ParseSubjectAltName(bool_t critical, const uint8_t *data, size_t length, X509SubjectAltName *subjectAltName)
Parse SubjectAltName extension.
#define TRACE_DEBUG(...)
Definition: debug.h:119
char char_t
Definition: compiler_port.h:55
const uint8_t X509_KP_SSH_SERVER_OID[8]
Definition: x509_common.c:152
const char_t * value
Definition: x509_common.h:693
#define OID_COMP(oid1, oidLen1, oid2)
Definition: oid.h:42
uint8_t n
#define ASN1_CLASS_CONTEXT_SPECIFIC
Definition: asn1.h:54
const uint8_t X509_NS_CERT_TYPE_OID[9]
Definition: x509_common.c:125
X509OctetString raw
Definition: x509_common.h:1008
uint8_t value[]
Definition: tcp.h:376
uint8_t oidLen
Definition: lldp_tlv.h:299
Basic Constraints extension.
Definition: x509_common.h:863
uint8_t critical
Definition: ike.h:1438
uint8_t reverseInt8(uint8_t value)
Reverse bit order in a byte.
Definition: cpu_endian.c:90
#define X509_MAX_DISTR_POINTS
Definition: x509_common.h:450
@ X509_EXT_KEY_USAGE_OCSP_SIGNING
Definition: x509_common.h:552
X509AccessDescription accessDescriptions[X509_MAX_ACCESS_DESCRIPTIONS]
Definition: x509_common.h:1010
@ ERROR_INVALID_SYNTAX
Definition: error.h:68
error_t x509ParseNameConstraints(bool_t critical, const uint8_t *data, size_t length, X509NameConstraints *nameConstraints)
Parse NameConstraints extension.
const uint8_t X509_KP_IPSEC_TUNNEL_OID[8]
Definition: x509_common.c:140
const uint8_t X509_KP_CMC_RA_OID[8]
Definition: x509_common.c:156
Name Constraints extension.
Definition: x509_common.h:875
X.509 certificate extensions.
Definition: x509_common.h:1053
uint8_t options[]
Definition: tcp.h:364
CRL Distribution Points extension.
Definition: x509_common.h:982
X509OctetString oid
Definition: x509_common.h:754
X509OctetString oid
Definition: x509_common.h:1042
@ X509_EXT_KEY_USAGE_CODE_SIGNING
Definition: x509_common.h:546
const uint8_t X509_SUBJECT_KEY_ID_OID[3]
Definition: x509_common.c:81
const uint8_t * value
Definition: x509_common.h:704
const uint8_t * value
Definition: x509_common.h:936
uint_t numCrlIssuers
Definition: x509_common.h:972
const uint8_t X509_KP_IPSEC_END_SYSTEM_OID[8]
Definition: x509_common.c:138
error_t x509ParseKeyUsage(bool_t critical, const uint8_t *data, size_t length, X509KeyUsage *keyUsage)
Parse KeyUsage extension.
error_t x509ParseCrlDistrPoints(bool_t critical, const uint8_t *data, size_t length, X509CrlDistrPoints *crlDistrPoints)
Parse CRLDistributionPoints extension.
X509DistrPoint distrPoints[X509_MAX_DISTR_POINTS]
Definition: x509_common.h:986
@ ASN1_TYPE_BIT_STRING
Definition: asn1.h:74
@ ERROR_INVALID_CLASS
Definition: error.h:117
X509OctetString keyId
Definition: x509_common.h:948
unsigned int uint_t
Definition: compiler_port.h:57
#define osMemset(p, value, length)
Definition: os_port.h:138
X509OctetString data
Definition: x509_common.h:1044
error_t x509ParseGeneralName(const uint8_t *data, size_t length, size_t *totalLength, X509GeneralName *generalName)
Parse GeneralName field.
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
@ ASN1_TYPE_BOOLEAN
Definition: asn1.h:72
X509String data
Definition: x509_common.h:756
@ X509_EXT_KEY_USAGE_EMAIL_PROTECTION
Definition: x509_common.h:547
X509GeneralName generalNames[X509_MAX_SUBJECT_ALT_NAMES]
Definition: x509_common.h:925
const uint8_t X509_KP_CMC_CA_OID[8]
Definition: x509_common.c:154
const uint8_t * value
Definition: asn1.h:110
error_t x509ParsePolicyConstraints(bool_t critical, const uint8_t *data, size_t length)
Parse PolicyConstraints extension.
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:944
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
uint_t objType
Definition: asn1.h:108
ASN.1 (Abstract Syntax Notation One)
error_t x509ParseSubjectKeyId(bool_t critical, const uint8_t *data, size_t length, X509SubjectKeyId *subjectKeyId)
Parse SubjectKeyIdentifier extension.
const uint8_t X509_KP_SSH_CLIENT_OID[8]
Definition: x509_common.c:150
Key Usage extension.
Definition: x509_common.h:887
@ ASN1_TYPE_NULL
Definition: asn1.h:76