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.2
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-documentSigning?
806  else if(OID_COMP(tag.value, tag.length, X509_KP_DOC_SIGNING_OID) == 0)
807  {
808  //The public key encoded in the certificate has been certified to be
809  //used for cryptographic operations on contents that are consumed by
810  //people (refer to RFC 9336, section 3.1)
811  extKeyUsage->bitmap |= X509_EXT_KEY_USAGE_DOC_SIGNING;
812  }
813  //Unknown key purpose?
814  else
815  {
816  //Discard KeyPurposeId field
817  }
818 
819  //Next item
820  data += tag.totalLength;
821  length -= tag.totalLength;
822  }
823 
824  //Successful processing
825  return NO_ERROR;
826 }
827 
828 
829 /**
830  * @brief Parse SubjectAltName extension
831  * @param[in] critical Critical extension flag
832  * @param[in] data Pointer to the ASN.1 structure to parse
833  * @param[in] length Length of the ASN.1 structure
834  * @param[out] subjectAltName Information resulting from the parsing process
835  * @return Error code
836  **/
837 
839  size_t length, X509SubjectAltName *subjectAltName)
840 {
841  error_t error;
842  Asn1Tag tag;
843 
844  //Debug message
845  TRACE_DEBUG(" Parsing SubjectAltName...\r\n");
846 
847  //An extension can be marked as critical
848  subjectAltName->critical = critical;
849 
850  //The SubjectAltName structure shall contain a valid sequence
851  error = asn1ReadSequence(data, length, &tag);
852  //Failed to decode ASN.1 tag?
853  if(error)
854  return error;
855 
856  //Raw contents of the ASN.1 sequence
857  subjectAltName->raw.value = tag.value;
858  subjectAltName->raw.length = tag.length;
859 
860  //The subject alternative name extension allows identities to be bound to the
861  //subject of the certificate. These identities may be included in addition
862  //to or in place of the identity in the subject field of the certificate
863  return x509ParseGeneralNames(tag.value, tag.length,
864  subjectAltName->generalNames, X509_MAX_SUBJECT_ALT_NAMES,
865  &subjectAltName->numGeneralNames);
866 }
867 
868 
869 /**
870  * @brief Parse SubjectKeyIdentifier extension
871  * @param[in] critical Critical extension flag
872  * @param[in] data Pointer to the ASN.1 structure to parse
873  * @param[in] length Length of the ASN.1 structure
874  * @param[out] subjectKeyId Information resulting from the parsing process
875  * @return Error code
876  **/
877 
879  size_t length, X509SubjectKeyId *subjectKeyId)
880 {
881  error_t error;
882  Asn1Tag tag;
883 
884  //Debug message
885  TRACE_DEBUG(" Parsing SubjectKeyIdentifier...\r\n");
886 
887  //An extension can be marked as critical
888  subjectKeyId->critical = critical;
889 
890  //The subject key identifier extension provides a means of identifying
891  //certificates that contain a particular public key
892  error = asn1ReadOctetString(data, length, &tag);
893  //Failed to decode ASN.1 tag?
894  if(error)
895  return error;
896 
897  //Save the subject key identifier
898  subjectKeyId->value = tag.value;
899  subjectKeyId->length = tag.length;
900 
901  //Successful processing
902  return NO_ERROR;
903 }
904 
905 
906 /**
907  * @brief Parse AuthorityKeyIdentifier extension
908  * @param[in] critical Critical extension flag
909  * @param[in] data Pointer to the ASN.1 structure to parse
910  * @param[in] length Length of the ASN.1 structure
911  * @param[out] authKeyId Information resulting from the parsing process
912  * @return Error code
913  **/
914 
916  size_t length, X509AuthKeyId *authKeyId)
917 {
918  error_t error;
919  Asn1Tag tag;
920 
921  //Debug message
922  TRACE_DEBUG(" Parsing AuthorityKeyIdentifier...\r\n");
923 
924  //An extension can be marked as critical
925  authKeyId->critical = critical;
926 
927  //The AuthorityKeyIdentifier structure shall contain a valid sequence
928  error = asn1ReadSequence(data, length, &tag);
929  //Failed to decode ASN.1 tag?
930  if(error)
931  return error;
932 
933  //Point to the first item of the sequence
934  data = tag.value;
935  length = tag.length;
936 
937  //Parse the content of the sequence
938  while(length > 0)
939  {
940  //Read current item
941  error = asn1ReadTag(data, length, &tag);
942  //Failed to decode ASN.1 tag?
943  if(error)
944  return error;
945 
946  //Implicit tagging shall be used to encode the item
948  return ERROR_INVALID_CLASS;
949 
950  //keyIdentifier object found?
951  if(tag.objType == 0)
952  {
953  //Save the authority key identifier
954  authKeyId->keyId.value = tag.value;
955  authKeyId->keyId.length = tag.length;
956  }
957 
958  //Next item
959  data += tag.totalLength;
960  length -= tag.totalLength;
961  }
962 
963  //Successful processing
964  return NO_ERROR;
965 }
966 
967 
968 /**
969  * @brief Parse CRLDistributionPoints extension
970  * @param[in] critical Critical extension flag
971  * @param[in] data Pointer to the ASN.1 structure to parse
972  * @param[in] length Length of the ASN.1 structure
973  * @param[out] crlDistrPoints Information resulting from the parsing process
974  * @return Error code
975  **/
976 
978  size_t length, X509CrlDistrPoints *crlDistrPoints)
979 {
980  error_t error;
981  uint_t i;
982  size_t n;
983  Asn1Tag tag;
984  X509DistrPoint distrPoint;
985 
986  //Debug message
987  TRACE_DEBUG(" Parsing CRLDistributionPoints...\r\n");
988 
989  //An extension can be marked as critical
990  crlDistrPoints->critical = critical;
991 
992  //The CRLDistributionPoints structure shall contain a valid sequence
993  error = asn1ReadSequence(data, length, &tag);
994  //Failed to decode ASN.1 tag?
995  if(error)
996  return error;
997 
998  //Raw contents of the ASN.1 sequence
999  crlDistrPoints->raw.value = tag.value;
1000  crlDistrPoints->raw.length = tag.length;
1001 
1002  //Point to the first item of the sequence
1003  data = tag.value;
1004  length = tag.length;
1005 
1006  //Parse the content of the sequence
1007  for(i = 0; length > 0; i++)
1008  {
1009  //Parse DistributionPoint field
1010  error = x509ParseDistrPoint(data, length, &n, &distrPoint);
1011  //Any error to report?
1012  if(error)
1013  return error;
1014 
1015  //Save distribution point
1016  if(i < X509_MAX_DISTR_POINTS)
1017  {
1018  crlDistrPoints->distrPoints[i] = distrPoint;
1019  }
1020 
1021  //Next item
1022  data += n;
1023  length -= n;
1024  }
1025 
1026  //If the CRLDistributionPoints extension is present, the sequence must
1027  //contain at least one entry (refer to RFC 5280, section 4.2.1.13)
1028  if(i == 0)
1029  return ERROR_INVALID_SYNTAX;
1030 
1031  //Save the number of distribution points
1032  crlDistrPoints->numDistrPoints = MIN(i, X509_MAX_DISTR_POINTS);
1033 
1034  //Successful processing
1035  return NO_ERROR;
1036 }
1037 
1038 
1039 /**
1040  * @brief Parse DistributionPoint field
1041  * @param[in] data Pointer to the ASN.1 structure to parse
1042  * @param[in] length Length of the ASN.1 structure
1043  * @param[out] totalLength Number of bytes that have been parsed
1044  * @param[out] distrPoint Information resulting from the parsing process
1045  * @return Error code
1046  **/
1047 
1048 error_t x509ParseDistrPoint(const uint8_t *data, size_t length,
1049  size_t *totalLength, X509DistrPoint *distrPoint)
1050 {
1051  error_t error;
1052  Asn1Tag tag;
1053 
1054  //Clear the structure
1055  osMemset(distrPoint, 0, sizeof(X509DistrPoint));
1056 
1057  //The DistributionPoint structure shall contain a valid sequence
1058  error = asn1ReadSequence(data, length, &tag);
1059  //Failed to decode ASN.1 tag?
1060  if(error)
1061  return error;
1062 
1063  //Save the total length of the field
1064  *totalLength = tag.totalLength;
1065 
1066  //Point to the first item of the sequence
1067  data = tag.value;
1068  length = tag.length;
1069 
1070  //Parse the content of the sequence
1071  while(length > 0)
1072  {
1073  //Read current item
1074  error = asn1ReadTag(data, length, &tag);
1075  //Failed to decode ASN.1 tag?
1076  if(error)
1077  return error;
1078 
1079  //Implicit tagging shall be used to encode the item
1081  return ERROR_INVALID_CLASS;
1082 
1083  //A DistributionPoint consists of three fields, each of which is optional
1084  if(tag.objType == 0)
1085  {
1086  //Parse DistributionPointName field
1087  error = x509ParseDistrPointName(tag.value, tag.length,
1088  &distrPoint->distrPointName);
1089  }
1090  else if(tag.objType == 1)
1091  {
1092  //Parse ReasonFlags field
1093  error = x509ParseReasonFlags(tag.value, tag.length,
1094  &distrPoint->reasonFlags);
1095  }
1096  else if(tag.objType == 2)
1097  {
1098  //Parse CRLIssuer field
1099  error = x509ParseGeneralNames(tag.value, tag.length,
1100  distrPoint->crlIssuers, X509_MAX_CRL_ISSUERS,
1101  &distrPoint->numCrlIssuers);
1102  }
1103  else
1104  {
1105  //Report an error
1106  error = ERROR_INVALID_TYPE;
1107  }
1108 
1109  //Any error to report?
1110  if(error)
1111  return error;
1112 
1113  //Next item
1114  data += tag.totalLength;
1115  length -= tag.totalLength;
1116  }
1117 
1118  //Successful processing
1119  return NO_ERROR;
1120 }
1121 
1122 
1123 /**
1124  * @brief Parse DistributionPointName field
1125  * @param[in] data Pointer to the ASN.1 structure to parse
1126  * @param[in] length Length of the ASN.1 structure
1127  * @param[out] distrPointName Information resulting from the parsing process
1128  * @return Error code
1129  **/
1130 
1132  X509DistrPointName *distrPointName)
1133 {
1134  error_t error;
1135  Asn1Tag tag;
1136 
1137  //Parse ASN.1 tag
1138  error = asn1ReadTag(data, length, &tag);
1139  //Failed to decode ASN.1 tag?
1140  if(error)
1141  return error;
1142 
1143  //Implicit tagging shall be used to encode the item
1145  return ERROR_INVALID_CLASS;
1146 
1147  //When the distributionPoint field is present, it contains either a
1148  //sequence of general names or a single value, nameRelativeToCRLIssuer
1149  if(tag.objType == 0)
1150  {
1151  //Parse fullName field
1152  error = x509ParseGeneralNames(tag.value, tag.length,
1153  distrPointName->fullNames, X509_MAX_FULL_NAMES,
1154  &distrPointName->numFullNames);
1155  }
1156  else if(tag.objType == 1)
1157  {
1158  //Parse nameRelativeToCRLIssuer field
1159  error = x509ParseRelativeName(tag.value, tag.length,
1160  &distrPointName->relativeName);
1161  }
1162  else
1163  {
1164  //Report an error
1165  error = ERROR_INVALID_TYPE;
1166  }
1167 
1168  //Return status code
1169  return error;
1170 }
1171 
1172 
1173 /**
1174  * @brief Parse nameRelativeToCRLIssuer field
1175  * @param[in] data Pointer to the ASN.1 structure to parse
1176  * @param[in] length Length of the ASN.1 structure
1177  * @param[out] relativeName Information resulting from the parsing process
1178  * @return Error code
1179  **/
1180 
1181 error_t x509ParseRelativeName(const uint8_t *data, size_t length,
1182  X509NameAttribute *relativeName)
1183 {
1184  error_t error;
1185  Asn1Tag tag;
1186 
1187  //Read the first field of the set
1188  error = asn1ReadSequence(data, length, &tag);
1189  //Failed to decode ASN.1 tag?
1190  if(error)
1191  return error;
1192 
1193  //Point to the first field of the sequence
1194  data = tag.value;
1195  length = tag.length;
1196 
1197  //Read AttributeType field
1198  error = asn1ReadOid(data, length, &tag);
1199  //Failed to decode ASN.1 tag?
1200  if(error)
1201  return error;
1202 
1203  //Save attribute type
1204  relativeName->oid.value = tag.value;
1205  relativeName->oid.length = tag.length;
1206 
1207  //Point to the next field
1208  data += tag.totalLength;
1209  length -= tag.totalLength;
1210 
1211  //Read AttributeValue field
1212  error = asn1ReadTag(data, length, &tag);
1213  //Failed to decode ASN.1 tag?
1214  if(error)
1215  return error;
1216 
1217  //Save ASN.1 string type
1218  relativeName->type = tag.objType;
1219 
1220  //Save attribute value
1221  relativeName->data.value = (char_t *) tag.value;
1222  relativeName->data.length = tag.length;
1223 
1224  //Successful processing
1225  return NO_ERROR;
1226 }
1227 
1228 
1229 /**
1230  * @brief Parse ReasonFlags field
1231  * @param[in] data Pointer to the ASN.1 structure to parse
1232  * @param[in] length Length of the ASN.1 structure
1233  * @param[out] reasonFlags Information resulting from the parsing process
1234  * @return Error code
1235  **/
1236 
1237 error_t x509ParseReasonFlags(const uint8_t *data, size_t length,
1238  uint16_t *reasonFlags)
1239 {
1240  //The bit string shall contain an initial octet which encodes the number
1241  //of unused bits in the final subsequent octet
1242  if(length < 1)
1243  return ERROR_INVALID_SYNTAX;
1244 
1245  //Sanity check
1246  if(data[0] >= 8)
1247  return ERROR_INVALID_SYNTAX;
1248 
1249  //Clear bit string
1250  *reasonFlags = 0;
1251 
1252  //Read bits b0 to b7
1253  if(length >= 2)
1254  {
1255  *reasonFlags |= reverseInt8(data[1]);
1256  }
1257 
1258  //Read bits b8 to b15
1259  if(length >= 3)
1260  {
1261  *reasonFlags |= reverseInt8(data[2]) << 8;
1262  }
1263 
1264  //Successful processing
1265  return NO_ERROR;
1266 }
1267 
1268 
1269 /**
1270  * @brief Parse AuthorityInformationAccess extension
1271  * @param[in] critical Critical extension flag
1272  * @param[in] data Pointer to the ASN.1 structure to parse
1273  * @param[in] length Length of the ASN.1 structure
1274  * @param[out] authInfoAccess Information resulting from the parsing process
1275  * @return Error code
1276  **/
1277 
1279  size_t length, X509AuthInfoAccess *authInfoAccess)
1280 {
1281  error_t error;
1282  uint_t i;
1283  size_t n;
1284  Asn1Tag tag;
1285  X509AccessDescription accessDescription;
1286 
1287  //Debug message
1288  TRACE_DEBUG(" Parsing AuthorityInformationAccess...\r\n");
1289 
1290  //An extension can be marked as critical
1291  authInfoAccess->critical = critical;
1292 
1293  //The AuthorityInformationAccess structure shall contain a valid sequence
1294  error = asn1ReadSequence(data, length, &tag);
1295  //Failed to decode ASN.1 tag?
1296  if(error)
1297  return error;
1298 
1299  //Raw contents of the ASN.1 sequence
1300  authInfoAccess->raw.value = tag.value;
1301  authInfoAccess->raw.length = tag.length;
1302 
1303  //Point to the first item of the sequence
1304  data = tag.value;
1305  length = tag.length;
1306 
1307  //Parse the content of the sequence
1308  for(i = 0; length > 0; i++)
1309  {
1310  //Parse AccessDescription field
1311  error = x509ParseAccessDescription(data, length, &n, &accessDescription);
1312  //Any error to report?
1313  if(error)
1314  return error;
1315 
1316  //Save access description
1318  {
1319  authInfoAccess->accessDescriptions[i] = accessDescription;
1320  }
1321 
1322  //Next item
1323  data += n;
1324  length -= n;
1325  }
1326 
1327  //If the AuthorityInformationAccess extension is present, the sequence must
1328  //contain at least one entry (refer to RFC 5280, section 4.2.2.1)
1329  if(i == 0)
1330  return ERROR_INVALID_SYNTAX;
1331 
1332  //Save the number of access descriptions
1334 
1335  //Successful processing
1336  return NO_ERROR;
1337 }
1338 
1339 
1340 /**
1341  * @brief Parse AccessDescription field
1342  * @param[in] data Pointer to the ASN.1 structure to parse
1343  * @param[in] length Length of the ASN.1 structure
1344  * @param[out] totalLength Number of bytes that have been parsed
1345  * @param[out] accessDescription Information resulting from the parsing process
1346  * @return Error code
1347  **/
1348 
1350  size_t *totalLength, X509AccessDescription *accessDescription)
1351 {
1352  error_t error;
1353  size_t n;
1354  Asn1Tag tag;
1355 
1356  //Clear the structure
1357  osMemset(accessDescription, 0, sizeof(X509AccessDescription));
1358 
1359  //The AccessDescription structure shall contain a valid sequence
1360  error = asn1ReadSequence(data, length, &tag);
1361  //Failed to decode ASN.1 tag?
1362  if(error)
1363  return error;
1364 
1365  //Save the total length of the field
1366  *totalLength = tag.totalLength;
1367 
1368  //Point to the first item of the sequence
1369  data = tag.value;
1370  length = tag.length;
1371 
1372  //Read accessMethod field
1373  error = asn1ReadOid(data, length, &tag);
1374  //Failed to decode ASN.1 tag?
1375  if(error)
1376  return error;
1377 
1378  //The type and format of the information are specified by the accessMethod
1379  //field (refer to RFC 5280, section 4.2.2.1)
1380  accessDescription->accessMethod.value = tag.value;
1381  accessDescription->accessMethod.length = tag.length;
1382 
1383  //Point to the next field
1384  data += tag.totalLength;
1385  length -= tag.totalLength;
1386 
1387  //The accessLocation field specifies the location of the information
1388  error = x509ParseGeneralName(data, length, &n,
1389  &accessDescription->accessLocation);
1390  //Failed to decode ASN.1 tag?
1391  if(error)
1392  return error;
1393 
1394  //Point to the next field
1395  data += n;
1396  length -= n;
1397 
1398  //Successful processing
1399  return NO_ERROR;
1400 }
1401 
1402 
1403 /**
1404  * @brief Parse PkixOcspNoCheck extension
1405  * @param[in] critical Critical extension flag
1406  * @param[in] data Pointer to the ASN.1 structure to parse
1407  * @param[in] length Length of the ASN.1 structure
1408  * @param[out] pkixOcspNoCheck Information resulting from the parsing process
1409  * @return Error code
1410  **/
1411 
1413  size_t length, X509PkixOcspNoCheck *pkixOcspNoCheck)
1414 {
1415  error_t error;
1416  Asn1Tag tag;
1417 
1418  //Debug message
1419  TRACE_DEBUG(" Parsing PkixOcspNoCheck...\r\n");
1420 
1421  //The extension should be a non-critical extension
1422  pkixOcspNoCheck->critical = critical;
1423 
1424  //The value of the extension shall be NULL (refer to RFC 6960,
1425  //section 4.2.2.2.1)
1426  error = asn1ReadTag(data, length, &tag);
1427  //Failed to decode ASN.1 tag?
1428  if(error)
1429  return error;
1430 
1431  //Enforce encoding, class and type
1433  //Invalid tag?
1434  if(error)
1435  return error;
1436 
1437  //The certificate contains a valid id-pkix-ocsp-nocheck extension
1438  pkixOcspNoCheck->present = TRUE;
1439 
1440  //Successful processing
1441  return NO_ERROR;
1442 }
1443 
1444 
1445 /**
1446  * @brief Parse NetscapeCertType extension
1447  * @param[in] critical Critical extension flag
1448  * @param[in] data Pointer to the ASN.1 structure to parse
1449  * @param[in] length Length of the ASN.1 structure
1450  * @param[out] nsCertType Information resulting from the parsing process
1451  * @return Error code
1452  **/
1453 
1455  size_t length, X509NsCertType *nsCertType)
1456 {
1457  error_t error;
1458  Asn1Tag tag;
1459 
1460  //Debug message
1461  TRACE_DEBUG(" Parsing NetscapeCertType...\r\n");
1462 
1463  //An extension can be marked as critical
1464  nsCertType->critical = critical;
1465 
1466  //The NetscapeCertType extension limit the use of a certificate
1467  error = asn1ReadTag(data, length, &tag);
1468  //Failed to decode ASN.1 tag?
1469  if(error)
1470  return error;
1471 
1472  //Enforce encoding, class and type
1473  error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL,
1475  //Invalid tag?
1476  if(error)
1477  return error;
1478 
1479  //The bit string shall contain an initial octet which encodes the number
1480  //of unused bits in the final subsequent octet
1481  if(tag.length < 1)
1482  return ERROR_INVALID_SYNTAX;
1483 
1484  //Sanity check
1485  if(tag.value[0] >= 8)
1486  return ERROR_INVALID_SYNTAX;
1487 
1488  //Clear bit string
1489  nsCertType->bitmap = 0;
1490 
1491  //Read bits b0 to b7
1492  if(tag.length >= 2)
1493  {
1494  nsCertType->bitmap |= reverseInt8(tag.value[1]);
1495  }
1496 
1497  //Successful processing
1498  return NO_ERROR;
1499 }
1500 
1501 
1502 /**
1503  * @brief Parse unknown X.509 certificate extension
1504  * @param[in] oid Extension identifier
1505  * @param[in] oidLen Length of the extension identifier
1506  * @param[in] critical Critical extension flag
1507  * @param[in] data Extension value
1508  * @param[in] dataLen Length of the extension value
1509  * @param[out] extensions Information resulting from the parsing process
1510  * @return Error code
1511  **/
1512 
1513 __weak_func error_t x509ParseUnknownCertExtension(const uint8_t *oid,
1514  size_t oidLen, bool_t critical, const uint8_t *data, size_t dataLen,
1516 {
1517  //The extension is not supported
1519 }
1520 
1521 
1522 /**
1523  * @brief Check whether the specified extension is a duplicate
1524  * @param[in] oid Extension identifier
1525  * @param[in] oidLen Length of the extension identifier
1526  * @param[in] data Pointer to the extension list
1527  * @param[in] length Length of the extension list
1528  * @return Error code
1529  **/
1530 
1532  const uint8_t *data, size_t length)
1533 {
1534  error_t error;
1535  size_t n;
1536  X509Extension extension;
1537 
1538  //Loop through the extensions
1539  while(length > 0)
1540  {
1541  //Each extension includes an OID and a value
1542  error = x509ParseExtension(data, length, &n, &extension);
1543  //Any error to report?
1544  if(error)
1545  return error;
1546 
1547  //A certificate must not include more than one instance of a particular
1548  //extension (refer to RFC 5280, section 4.2)
1549  if(oidComp(extension.oid.value, extension.oid.length, oid, oidLen) == 0)
1550  {
1551  return ERROR_INVALID_SYNTAX;
1552  }
1553 
1554  //Jump to the next extension
1555  data += n;
1556  length -= n;
1557  }
1558 
1559  //Successful verification
1560  return NO_ERROR;
1561 }
1562 
1563 #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:557
X.509 certificate parsing.
uint8_t extensions[]
Definition: ntp_common.h:207
@ 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:995
X509DistrPointName distrPointName
Definition: x509_common.h:968
__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:154
const uint8_t X509_KP_SERVER_AUTH_OID[8]
Definition: x509_common.c:130
X509OctetString accessMethod
Definition: x509_common.h:994
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:921
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:982
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:945
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:971
#define X509_MAX_SUBJECT_ALT_NAMES
Definition: x509_common.h:429
size_t length
Definition: x509_common.h:692
Subject Key Identifier extension.
Definition: x509_common.h:932
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:957
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:1334
Distribution Point Name structure.
Definition: x509_common.h:955
uint_t numAccessDescriptions
Definition: x509_common.h:1007
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:1004
bool_t critical
Definition: x509_common.h:886
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:751
Extended Key Usage extension.
Definition: x509_common.h:896
Distribution Point structure.
Definition: x509_common.h:967
#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:958
X509OctetString permittedSubtrees
Definition: x509_common.h:875
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:969
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:1039
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:944
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:876
PKIX OCSP No Check extension.
Definition: x509_common.h:1017
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:887
#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:919
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:556
uint32_t dataLen
Definition: sftp_common.h:229
Access Description extension.
Definition: x509_common.h:993
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:1028
@ 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:691
#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:1006
uint8_t value[]
Definition: tcp.h:376
uint8_t oidLen
Definition: lldp_tlv.h:299
Basic Constraints extension.
Definition: x509_common.h:861
uint8_t critical
Definition: ike.h:1405
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:1008
@ 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
Name Constraints extension.
Definition: x509_common.h:873
X.509 certificate extensions.
Definition: x509_common.h:1051
uint8_t options[]
Definition: tcp.h:364
CRL Distribution Points extension.
Definition: x509_common.h:980
X509OctetString oid
Definition: x509_common.h:752
X509OctetString oid
Definition: x509_common.h:1040
@ 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:702
const uint8_t * value
Definition: x509_common.h:934
uint_t numCrlIssuers
Definition: x509_common.h:970
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:984
@ ASN1_TYPE_BIT_STRING
Definition: asn1.h:74
@ ERROR_INVALID_CLASS
Definition: error.h:117
X509OctetString keyId
Definition: x509_common.h:946
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:1042
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:754
@ X509_EXT_KEY_USAGE_EMAIL_PROTECTION
Definition: x509_common.h:547
X509GeneralName generalNames[X509_MAX_SUBJECT_ALT_NAMES]
Definition: x509_common.h:923
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:885
@ ASN1_TYPE_NULL
Definition: asn1.h:76