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