x509_cert_parse.c
Go to the documentation of this file.
1 /**
2  * @file x509_cert_parse.c
3  * @brief X.509 certificate 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 "pkix/x509_key_parse.h"
39 #include "pkix/x509_sign_parse.h"
40 #include "encoding/asn1.h"
41 #include "encoding/oid.h"
42 #include "debug.h"
43 
44 //Check crypto library configuration
45 #if (X509_SUPPORT == ENABLED)
46 
47 
48 /**
49  * @brief Parse a X.509 certificate
50  * @param[in] data Pointer to the X.509 certificate to parse
51  * @param[in] length Length of the X.509 certificate
52  * @param[out] certInfo Information resulting from the parsing process
53  * @return Error code
54  **/
55 
56 error_t x509ParseCertificate(const uint8_t *data, size_t length,
57  X509CertInfo *certInfo)
58 {
59  //Parse the certificate
61 }
62 
63 
64 /**
65  * @brief Parse a X.509 certificate
66  * @param[in] data Pointer to the X.509 certificate to parse
67  * @param[in] length Length of the X.509 certificate
68  * @param[out] certInfo Information resulting from the parsing process
69  * @param[in] options Certificate parsing options
70  * @return Error code
71  **/
72 
73 error_t x509ParseCertificateEx(const uint8_t *data, size_t length,
74  X509CertInfo *certInfo, const X509Options *options)
75 {
76  error_t error;
77  size_t n;
78  Asn1Tag tag;
79 
80  //Debug message
81  TRACE_DEBUG("Parsing X.509 certificate...\r\n");
82 
83  //Check parameters
84  if(data == NULL || certInfo == NULL)
86 
87  //Clear the certificate information structure
88  osMemset(certInfo, 0, sizeof(X509CertInfo));
89 
90  //Where pathLenConstraint does not appear, no limit is imposed
92 
93  //Read the contents of the certificate
94  error = asn1ReadSequence(data, length, &tag);
95  //Failed to decode ASN.1 tag?
96  if(error)
97  return ERROR_BAD_CERTIFICATE;
98 
99  //Raw contents of the ASN.1 sequence
100  certInfo->raw.value = data;
101  certInfo->raw.length = tag.totalLength;
102 
103  //Point to the very first field
104  data = tag.value;
105  length = tag.length;
106 
107  //Parse TBSCertificate structure
108  error = x509ParseTbsCertificate(data, length, &n, &certInfo->tbsCert,
109  options);
110  //Any error to report?
111  if(error)
112  return ERROR_BAD_CERTIFICATE;
113 
114  //Point to the next field
115  data += n;
116  length -= n;
117 
118  //Parse SignatureAlgorithm structure
119  error = x509ParseSignatureAlgo(data, length, &n, &certInfo->signatureAlgo);
120  //Any error to report?
121  if(error)
122  return ERROR_BAD_CERTIFICATE;
123 
124  //This field must contain the same algorithm identifier as the signature
125  //field in the TBSCertificate sequence (refer to RFC 5280, section 4.1.1.2)
126  if(oidComp(certInfo->signatureAlgo.oid.value,
127  certInfo->signatureAlgo.oid.length,
128  certInfo->tbsCert.signatureAlgo.oid.value,
129  certInfo->tbsCert.signatureAlgo.oid.length))
130  {
131  //Report an error
132  return ERROR_WRONG_IDENTIFIER;
133  }
134 
135  //Point to the next field
136  data += n;
137  length -= n;
138 
139  //Parse SignatureValue structure
140  error = x509ParseSignatureValue(data, length, &n, &certInfo->signatureValue);
141  //Any error to report?
142  if(error)
143  return ERROR_BAD_CERTIFICATE;
144 
145  //Certificate successfully parsed
146  return NO_ERROR;
147 }
148 
149 
150 /**
151  * @brief Parse TBSCertificate structure
152  * @param[in] data Pointer to the ASN.1 structure to parse
153  * @param[in] length Length of the ASN.1 structure
154  * @param[out] totalLength Number of bytes that have been parsed
155  * @param[out] tbsCert Information resulting from the parsing process
156  * @param[in] options Certificate parsing options
157  * @return Error code
158  **/
159 
161  size_t *totalLength, X509TbsCertificate *tbsCert,
162  const X509Options *options)
163 {
164  error_t error;
165  size_t n;
166  Asn1Tag tag;
167 
168  //Debug message
169  TRACE_DEBUG(" Parsing TBSCertificate...\r\n");
170 
171  //Read the contents of the TBSCertificate structure
172  error = asn1ReadSequence(data, length, &tag);
173  //Failed to decode ASN.1 tag?
174  if(error)
175  return error;
176 
177  //Save the total length of the field
178  *totalLength = tag.totalLength;
179 
180  //The ASN.1 DER-encoded TBSCertificate is used as the input to the
181  //signature function
182  tbsCert->raw.value = data;
183  tbsCert->raw.length = tag.totalLength;
184 
185  //Point to the very first field of the TBSCertificate
186  data = tag.value;
187  length = tag.length;
188 
189  //Parse Version field
190  error = x509ParseVersion(data, length, &n, &tbsCert->version);
191  //Any parsing error?
192  if(error)
193  return error;
194 
195  //Point to the next field
196  data += n;
197  length -= n;
198 
199  //Parse SerialNumber field
200  error = x509ParseSerialNumber(data, length, &n, &tbsCert->serialNumber);
201  //Any parsing error?
202  if(error)
203  return error;
204 
205  //Point to the next field
206  data += n;
207  length -= n;
208 
209  //Parse Signature field
210  error = x509ParseSignatureAlgo(data, length, &n, &tbsCert->signatureAlgo);
211  //Any parsing error?
212  if(error)
213  return error;
214 
215  //Point to the next field
216  data += n;
217  length -= n;
218 
219  //Parse Issuer field
220  error = x509ParseName(data, length, &n, &tbsCert->issuer);
221  //Any parsing error?
222  if(error)
223  return error;
224 
225  //Point to the next field
226  data += n;
227  length -= n;
228 
229  //Parse Validity field
230  error = x509ParseValidity(data, length, &n, &tbsCert->validity);
231  //Any parsing error?
232  if(error)
233  return error;
234 
235  //Point to the next field
236  data += n;
237  length -= n;
238 
239  //Parse Subject field
240  error = x509ParseName(data, length, &n, &tbsCert->subject);
241  //Any parsing error?
242  if(error)
243  return error;
244 
245  //Point to the next field
246  data += n;
247  length -= n;
248 
249  //Parse SubjectPublicKeyInfo field
251  &tbsCert->subjectPublicKeyInfo);
252  //Any parsing error?
253  if(error)
254  return error;
255 
256  //Point to the next field
257  data += n;
258  length -= n;
259 
260  //Parse IssuerUniqueID field
261  error = x509ParseIssuerUniqueId(data, length, &n);
262  //Any parsing error?
263  if(error)
264  return error;
265 
266  //The IssuerUniqueID field is optional
267  if(n > 0)
268  {
269  //This field must only appear if the version is 2 or 3
270  if(tbsCert->version < X509_VERSION_2)
271  return ERROR_INVALID_VERSION;
272  }
273 
274  //Point to the next field
275  data += n;
276  length -= n;
277 
278  //Parse SubjectUniqueID field
280  //Any parsing error?
281  if(error)
282  return error;
283 
284  //The SubjectUniqueID field is optional
285  if(n > 0)
286  {
287  //This field must only appear if the version is 2 or 3
288  if(tbsCert->version < X509_VERSION_2)
289  return ERROR_INVALID_VERSION;
290  }
291 
292  //Point to the next field
293  data += n;
294  length -= n;
295 
296  //Parse Extensions field
297  error = x509ParseCertExtensions(data, length, &n, &tbsCert->extensions,
298  options);
299  //Any parsing error?
300  if(error)
301  return error;
302 
303  //The Extensions field is optional
304  if(n > 0)
305  {
306  //This field must only appear if the version is 3
307  if(tbsCert->version < X509_VERSION_3)
308  return ERROR_INVALID_VERSION;
309  }
310 
311  //Self-signed certificate?
312  if(x509CompareName(tbsCert->subject.raw.value, tbsCert->subject.raw.length,
313  tbsCert->issuer.raw.value, tbsCert->issuer.raw.length))
314  {
315  //The use of self-issued certificates and self-signed certificates issued
316  //by entities other than CAs are outside the scope of RFC 5280 (refer to
317  //RFC 6818, section 2)
318  }
319  else
320  {
321  //Check whether the keyCertSign bit is asserted
322  if((tbsCert->extensions.keyUsage.bitmap &
324  {
325  //If the keyCertSign bit is asserted, then the cA bit in the basic
326  //constraints extension must also be asserted (refer to RFC 5280,
327  //section 4.2.1.3)
328  if(!tbsCert->extensions.basicConstraints.cA)
329  return ERROR_INVALID_SYNTAX;
330  }
331  }
332 
333  //Successful processing
334  return NO_ERROR;
335 }
336 
337 
338 /**
339  * @brief Parse Version field
340  * @param[in] data Pointer to the ASN.1 structure to parse
341  * @param[in] length Length of the ASN.1 structure
342  * @param[out] totalLength Number of bytes that have been parsed
343  * @param[out] version Information resulting from the parsing process
344  * @return Error code
345  **/
346 
347 error_t x509ParseVersion(const uint8_t *data, size_t length,
348  size_t *totalLength, X509Version *version)
349 {
350  error_t error;
351  int32_t value;
352  Asn1Tag tag;
353 
354  //Debug message
355  TRACE_DEBUG(" Parsing Version...\r\n");
356 
357  //Explicit tagging shall be used to encode version
358  error = asn1ReadTag(data, length, &tag);
359  //Failed to decode ASN.1 tag?
360  if(error)
361  return error;
362 
363  //Enforce encoding, class and type
364  error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_CONTEXT_SPECIFIC, 0);
365 
366  //Invalid tag?
367  if(error)
368  {
369  //Assume X.509 version 1 format
371  //Skip the current field
372  *totalLength = 0;
373 
374  //Exit immediately
375  return NO_ERROR;
376  }
377 
378  //Save the total length of the field
379  *totalLength = tag.totalLength;
380 
381  //Read the inner tag
382  error = asn1ReadInt32(tag.value, tag.length, &tag, &value);
383  //Failed to decode ASN.1 tag?
384  if(error)
385  return error;
386 
387  //Check version
388  if(value > X509_VERSION_3)
389  return ERROR_INVALID_VERSION;
390 
391  //Save certificate version
393 
394  //Successful processing
395  return NO_ERROR;
396 }
397 
398 
399 /**
400  * @brief Parse SerialNumber field
401  * @param[in] data Pointer to the ASN.1 structure to parse
402  * @param[in] length Length of the ASN.1 structure
403  * @param[out] totalLength Number of bytes that have been parsed
404  * @param[out] serialNumber Information resulting from the parsing process
405  * @return Error code
406  **/
407 
408 error_t x509ParseSerialNumber(const uint8_t *data, size_t length,
409  size_t *totalLength, X509SerialNumber *serialNumber)
410 {
411  error_t error;
412  Asn1Tag tag;
413 
414  //Debug message
415  TRACE_DEBUG(" Parsing SerialNumber...\r\n");
416 
417  //Read the contents of the SerialNumber structure
418  error = asn1ReadTag(data, length, &tag);
419  //Failed to decode ASN.1 tag?
420  if(error)
421  return error;
422 
423  //Save the total length of the field
424  *totalLength = tag.totalLength;
425 
426  //Enforce encoding, class and type
428  //Invalid tag?
429  if(error)
430  return error;
431 
432  //Check the length of the serial number
433  if(tag.length < 1)
434  return ERROR_INVALID_SYNTAX;
435 
436  //Non-conforming CAs may issue certificates with serial numbers that are
437  //negative or zero. Certificate users should be prepared to gracefully
438  //handle such certificates (refer to RFC 5280, section 4.1.2.2)
439  serialNumber->value = tag.value;
440  serialNumber->length = tag.length;
441 
442  //Successful processing
443  return NO_ERROR;
444 }
445 
446 
447 /**
448  * @brief Parse IssuerUniqueID structure
449  * @param[in] data Pointer to the ASN.1 structure to parse
450  * @param[in] length Length of the ASN.1 structure
451  * @param[out] totalLength Number of bytes that have been parsed
452  * @return Error code
453  **/
454 
456  size_t *totalLength)
457 {
458  error_t error;
459  Asn1Tag tag;
460 
461  //No more data to process?
462  if(length == 0)
463  {
464  //The IssuerUniqueID field is optional
465  *totalLength = 0;
466  //Exit immediately
467  return NO_ERROR;
468  }
469 
470  //Implicit tagging is used to encode the IssuerUniqueID field
471  error = asn1ReadTag(data, length, &tag);
472  //Failed to decode ASN.1 tag?
473  if(error)
474  return error;
475 
476  //Enforce encoding, class and type
477  error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_CONTEXT_SPECIFIC, 1);
478  //Invalid tag?
479  if(error)
480  {
481  //The IssuerUniqueID field is optional
482  *totalLength = 0;
483  //Exit immediately
484  return NO_ERROR;
485  }
486 
487  //Save the total length of the field
488  *totalLength = tag.totalLength;
489 
490  //Debug message
491  TRACE_DEBUG(" Parsing IssuerUniqueID...\r\n");
492 
493  //Conforming applications should be capable of parsing certificates that
494  //include unique identifiers, but there are no processing requirements
495  //associated with the unique identifiers
496  return NO_ERROR;
497 }
498 
499 
500 /**
501  * @brief Parse SubjectUniqueID structure
502  * @param[in] data Pointer to the ASN.1 structure to parse
503  * @param[in] length Length of the ASN.1 structure
504  * @param[out] totalLength Number of bytes that have been parsed
505  * @return Error code
506  **/
507 
509  size_t *totalLength)
510 {
511  error_t error;
512  Asn1Tag tag;
513 
514  //No more data to process?
515  if(length == 0)
516  {
517  //The SubjectUniqueID field is optional
518  *totalLength = 0;
519  //Exit immediately
520  return NO_ERROR;
521  }
522 
523  //Implicit tagging is used to encode the SubjectUniqueID field
524  error = asn1ReadTag(data, length, &tag);
525  //Failed to decode ASN.1 tag?
526  if(error)
527  return error;
528 
529  //Enforce encoding, class and type
530  error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_CONTEXT_SPECIFIC, 2);
531  //Invalid tag?
532  if(error)
533  {
534  //The SubjectUniqueID field is optional
535  *totalLength = 0;
536  //Exit immediately
537  return NO_ERROR;
538  }
539 
540  //Save the total length of the field
541  *totalLength = tag.totalLength;
542 
543  //Debug message
544  TRACE_DEBUG(" Parsing SubjectUniqueID...\r\n");
545 
546  //Conforming applications should be capable of parsing certificates that
547  //include unique identifiers, but there are no processing requirements
548  //associated with the unique identifiers
549  return NO_ERROR;
550 }
551 
552 
553 /**
554  * @brief Parse Name structure
555  * @param[in] data Pointer to the ASN.1 structure to parse
556  * @param[in] length Length of the ASN.1 structure
557  * @param[out] totalLength Number of bytes that have been parsed
558  * @param[out] name Information resulting from the parsing process
559  * @return Error code
560  **/
561 
562 error_t x509ParseName(const uint8_t *data, size_t length,
563  size_t *totalLength, X509Name *name)
564 {
565  error_t error;
566  uint_t i;
567  size_t n;
568  Asn1Tag tag;
569  X509NameAttribute nameAttribute;
570 
571  //Debug message
572  TRACE_DEBUG(" Parsing Name...\r\n");
573 
574  //Clear the structure
575  osMemset(name, 0, sizeof(X509Name));
576 
577  //Read the contents of the Name structure
578  error = asn1ReadSequence(data, length, &tag);
579  //Failed to decode ASN.1 tag?
580  if(error)
581  return error;
582 
583  //Save the total length of the field
584  *totalLength = tag.totalLength;
585 
586  //Raw contents of the ASN.1 sequence
587  name->raw.value = data;
588  name->raw.length = tag.totalLength;
589 
590  //The Name describes a hierarchical name composed of attributes
591  data = tag.value;
592  length = tag.length;
593 
594  //Number of domain components
595  i = 0;
596 
597  //Loop through all the attributes
598  while(length > 0)
599  {
600  //Read current attribute
601  error = x509ParseNameAttribute(data, length, &n, &nameAttribute);
602  //Any error to report?
603  if(error)
604  return error;
605 
606  //Check attribute type
607  if(OID_COMP(nameAttribute.oid.value, nameAttribute.oid.length,
608  X509_COMMON_NAME_OID) == 0)
609  {
610  //Save Common Name attribute
611  name->commonName.value = nameAttribute.data.value;
612  name->commonName.length = nameAttribute.data.length;
613  }
614  else if(OID_COMP(nameAttribute.oid.value, nameAttribute.oid.length,
615  X509_SURNAME_OID) == 0)
616  {
617  //Save Surname attribute
618  name->surname.value = nameAttribute.data.value;
619  name->surname.length = nameAttribute.data.length;
620  }
621  else if(OID_COMP(nameAttribute.oid.value, nameAttribute.oid.length,
623  {
624  //Save Serial Number attribute
625  name->serialNumber.value = nameAttribute.data.value;
626  name->serialNumber.length = nameAttribute.data.length;
627  }
628  else if(OID_COMP(nameAttribute.oid.value, nameAttribute.oid.length,
629  X509_COUNTRY_NAME_OID) == 0)
630  {
631  //Save Country Name attribute
632  name->countryName.value = nameAttribute.data.value;
633  name->countryName.length = nameAttribute.data.length;
634  }
635  else if(OID_COMP(nameAttribute.oid.value, nameAttribute.oid.length,
637  {
638  //Save Locality Name attribute
639  name->localityName.value = nameAttribute.data.value;
640  name->localityName.length = nameAttribute.data.length;
641  }
642  else if(OID_COMP(nameAttribute.oid.value, nameAttribute.oid.length,
644  {
645  //Save State Or Province Name attribute
646  name->stateOrProvinceName.value = nameAttribute.data.value;
647  name->stateOrProvinceName.length = nameAttribute.data.length;
648  }
649  else if(OID_COMP(nameAttribute.oid.value, nameAttribute.oid.length,
651  {
652  //Save Organization Name attribute
653  name->organizationName.value = nameAttribute.data.value;
654  name->organizationName.length = nameAttribute.data.length;
655  }
656  else if(OID_COMP(nameAttribute.oid.value, nameAttribute.oid.length,
658  {
659  //Save Organizational Unit Name attribute
660  name->organizationalUnitName.value = nameAttribute.data.value;
661  name->organizationalUnitName.length = nameAttribute.data.length;
662  }
663  else if(OID_COMP(nameAttribute.oid.value, nameAttribute.oid.length,
664  X509_TITLE_OID) == 0)
665  {
666  //Save Title attribute
667  name->title.value = nameAttribute.data.value;
668  name->title.length = nameAttribute.data.length;
669  }
670  else if(OID_COMP(nameAttribute.oid.value, nameAttribute.oid.length,
671  X509_NAME_OID) == 0)
672  {
673  //Save Name attribute
674  name->name.value = nameAttribute.data.value;
675  name->name.length = nameAttribute.data.length;
676  }
677  else if(OID_COMP(nameAttribute.oid.value, nameAttribute.oid.length,
678  X509_GIVEN_NAME_OID) == 0)
679  {
680  //Save Given Name attribute
681  name->givenName.value = nameAttribute.data.value;
682  name->givenName.length = nameAttribute.data.length;
683  }
684  else if(OID_COMP(nameAttribute.oid.value, nameAttribute.oid.length,
685  X509_INITIALS_OID) == 0)
686  {
687  //Save Initials attribute
688  name->initials.value = nameAttribute.data.value;
689  name->initials.length = nameAttribute.data.length;
690  }
691  else if(OID_COMP(nameAttribute.oid.value, nameAttribute.oid.length,
693  {
694  //Save Generation Qualifier attribute
695  name->generationQualifier.value = nameAttribute.data.value;
696  name->generationQualifier.length = nameAttribute.data.length;
697  }
698  else if(OID_COMP(nameAttribute.oid.value, nameAttribute.oid.length,
699  X509_DN_QUALIFIER_OID) == 0)
700  {
701  //Save DN Qualifier attribute
702  name->dnQualifier.value = nameAttribute.data.value;
703  name->dnQualifier.length = nameAttribute.data.length;
704  }
705  else if(OID_COMP(nameAttribute.oid.value, nameAttribute.oid.length,
706  X509_PSEUDONYM_OID) == 0)
707  {
708  //Save Pseudonym attribute
709  name->pseudonym.value = nameAttribute.data.value;
710  name->pseudonym.length = nameAttribute.data.length;
711  }
712  else if(OID_COMP(nameAttribute.oid.value, nameAttribute.oid.length,
713  PKCS9_EMAIL_ADDR_OID) == 0)
714  {
715  //Save E-mail Address attribute
716  name->emailAddress.value = nameAttribute.data.value;
717  name->emailAddress.length = nameAttribute.data.length;
718  }
719  else if(OID_COMP(nameAttribute.oid.value, nameAttribute.oid.length,
721  {
722  //Save Domain Component attribute
724  {
725  name->domainComponents[i].value = nameAttribute.data.value;
726  name->domainComponents[i].length = nameAttribute.data.length;
727  }
728 
729  //Increment the number of domain components
730  i++;
731  }
732  else
733  {
734  //Discard unknown attributes
735  }
736 
737  //Next attribute
738  data += n;
739  length -= n;
740  }
741 
742  //Save the number of domain components
743  name->numDomainComponents = MIN(i, X509_MAX_DOMAIN_COMPONENTS);
744 
745  //Name field successfully parsed
746  return NO_ERROR;
747 }
748 
749 
750 /**
751  * @brief Parse name attribute
752  * @param[in] data Pointer to the ASN.1 structure to parse
753  * @param[in] length Length of the ASN.1 structure
754  * @param[out] totalLength Number of bytes that have been parsed
755  * @param[out] nameAttribute Information resulting from the parsing process
756  * @return Error code
757  **/
758 
759 error_t x509ParseNameAttribute(const uint8_t *data, size_t length,
760  size_t *totalLength, X509NameAttribute *nameAttribute)
761 {
762  error_t error;
763  Asn1Tag tag;
764 
765  //Attributes are encapsulated within a set
766  error = asn1ReadTag(data, length, &tag);
767  //Failed to decode ASN.1 tag?
768  if(error)
769  return error;
770 
771  //Enforce encoding, class and type
773  //Invalid tag?
774  if(error)
775  return error;
776 
777  //Save the total length of the attribute
778  *totalLength = tag.totalLength;
779 
780  //Read the first field of the set
781  error = asn1ReadSequence(tag.value, tag.length, &tag);
782  //Failed to decode ASN.1 tag?
783  if(error)
784  return error;
785 
786  //Point to the first field of the sequence
787  data = tag.value;
788  length = tag.length;
789 
790  //Read AttributeType field
791  error = asn1ReadOid(data, length, &tag);
792  //Failed to decode ASN.1 tag?
793  if(error)
794  return error;
795 
796  //Save attribute type
797  nameAttribute->oid.value = tag.value;
798  nameAttribute->oid.length = tag.length;
799 
800  //Point to the next field
801  data += tag.totalLength;
802  length -= tag.totalLength;
803 
804  //Read AttributeValue field
805  error = asn1ReadTag(data, length, &tag);
806  //Failed to decode ASN.1 tag?
807  if(error)
808  return error;
809 
810  //Save ASN.1 string type
811  nameAttribute->type = tag.objType;
812 
813  //Save attribute value
814  nameAttribute->data.value = (char_t *) tag.value;
815  nameAttribute->data.length = tag.length;
816 
817  //Successful processing
818  return NO_ERROR;
819 }
820 
821 
822 /**
823  * @brief Parse GeneralNames field
824  * @param[in] data Pointer to the ASN.1 structure to parse
825  * @param[in] length Length of the ASN.1 structure
826  * @param[out] generalNames Array of GeneralName entries
827  * @param[in] maxGeneralNames Maximum number of entries the array can hold
828  * @param[out] numGeneralNames Actual number of entries in the array
829  * @return Error code
830  **/
831 
832 error_t x509ParseGeneralNames(const uint8_t *data, size_t length,
833  X509GeneralName *generalNames, uint_t maxGeneralNames,
834  uint_t *numGeneralNames)
835 {
836  error_t error;
837  uint_t i;
838  size_t n;
839  X509GeneralName generalName;
840 
841  //Parse the content of the sequence
842  for(i = 0; length > 0; i++)
843  {
844  //Parse current entry
845  error = x509ParseGeneralName(data, length, &n, &generalName);
846  //Any error to report?
847  if(error)
848  return error;
849 
850  //Save GeneralName field
851  if(i < maxGeneralNames)
852  {
853  generalNames[i] = generalName;
854  }
855 
856  //Next field
857  data += n;
858  length -= n;
859  }
860 
861  //The sequence must contain at least one entry
862  if(i == 0)
863  return ERROR_INVALID_SYNTAX;
864 
865  //Save the number of GeneralName entries
866  *numGeneralNames = MIN(i, maxGeneralNames);
867 
868  //Successful processing
869  return NO_ERROR;
870 }
871 
872 
873 /**
874  * @brief Parse GeneralName field
875  * @param[in] data Pointer to the ASN.1 structure to parse
876  * @param[in] length Length of the ASN.1 structure
877  * @param[out] totalLength Number of bytes that have been parsed
878  * @param[out] generalName Information resulting from the parsing process
879  * @return Error code
880  **/
881 
882 error_t x509ParseGeneralName(const uint8_t *data, size_t length,
883  size_t *totalLength, X509GeneralName *generalName)
884 {
885  error_t error;
886  Asn1Tag tag;
887 
888  //Debug message
889  TRACE_DEBUG(" Parsing GeneralName...\r\n");
890 
891  //Clear the structure
892  osMemset(generalName, 0, sizeof(X509GeneralName));
893 
894  //Read current item
895  error = asn1ReadTag(data, length, &tag);
896  //Failed to decode ASN.1 tag?
897  if(error)
898  return error;
899 
900  //Implicit tagging shall be used to encode the GeneralName field
902  return ERROR_INVALID_CLASS;
903 
904  //Empty field?
905  if(tag.length == 0)
906  return ERROR_INVALID_SYNTAX;
907 
908  //Save GeneralName field
909  generalName->type = (X509GeneralNameType) tag.objType;
910  generalName->value = (char_t *) tag.value;
911  generalName->length = tag.length;
912 
913  //Save the total length of the field
914  *totalLength = tag.totalLength;
915 
916  //Successful processing
917  return NO_ERROR;
918 }
919 
920 
921 /**
922  * @brief Parse GeneralSubtrees field
923  * @param[in] data Pointer to the ASN.1 structure to parse
924  * @param[in] length Length of the ASN.1 structure
925  * @return Error code
926  **/
927 
929 {
930  error_t error;
931  size_t n;
932  X509GeneralName generalName;
933 
934  //Loop through the list of GeneralSubtree fields
935  while(length > 0)
936  {
937  //Parse current GeneralSubtree field
938  error = x509ParseGeneralSubtree(data, length, &n, &generalName);
939  //Any error to report?
940  if(error)
941  return error;
942 
943  //Next item
944  data += n;
945  length -= n;
946  }
947 
948  //Successful processing
949  return NO_ERROR;
950 }
951 
952 
953 /**
954  * @brief Parse GeneralSubtree field
955  * @param[in] data Pointer to the ASN.1 structure to parse
956  * @param[in] length Length of the ASN.1 structure
957  * @param[out] totalLength Number of bytes that have been parsed
958  * @param[out] generalName Information resulting from the parsing process
959  * @return Error code
960  **/
961 
963  size_t *totalLength, X509GeneralName *generalName)
964 {
965  error_t error;
966  size_t n;
967  Asn1Tag tag;
968 
969  //The GeneralSubtrees structure shall contain a valid sequence
970  error = asn1ReadSequence(data, length, &tag);
971  //Failed to decode ASN.1 tag?
972  if(error)
973  return error;
974 
975  //Save the total length of the field
976  *totalLength = tag.totalLength;
977 
978  //Parse GeneralName field
979  error = x509ParseGeneralName(tag.value, tag.length, &n, generalName);
980 
981  //Discard minimum and maximum fields
982  return error;
983 }
984 
985 
986 /**
987  * @brief Parse Validity structure
988  * @param[in] data Pointer to the ASN.1 structure to parse
989  * @param[in] length Length of the ASN.1 structure
990  * @param[out] totalLength Number of bytes that have been parsed
991  * @param[out] validity Information resulting from the parsing process
992  * @return Error code
993  **/
994 
995 error_t x509ParseValidity(const uint8_t *data, size_t length,
996  size_t *totalLength, X509Validity *validity)
997 {
998  error_t error;
999  size_t n;
1000  Asn1Tag tag;
1001 
1002  //Debug message
1003  TRACE_DEBUG(" Parsing Validity...\r\n");
1004 
1005  //Read the contents of the Validity structure
1006  error = asn1ReadSequence(data, length, &tag);
1007  //Failed to decode ASN.1 tag?
1008  if(error)
1009  return error;
1010 
1011  //Save the total length of the field
1012  *totalLength = tag.totalLength;
1013 
1014  //Point to the very first field of the sequence
1015  data = tag.value;
1016  length = tag.length;
1017 
1018  //The NotBefore field may be encoded as UTCTime or GeneralizedTime
1019  error = x509ParseTime(data, length, &n, &validity->notBefore);
1020  //Failed to decode ASN.1 tag?
1021  if(error)
1022  return error;
1023 
1024  //Point to the next field
1025  data += n;
1026  length -= n;
1027 
1028  //The NotAfter field may be encoded as UTCTime or GeneralizedTime
1029  error = x509ParseTime(data, length, &n, &validity->notAfter);
1030  //Failed to decode ASN.1 tag?
1031  if(error)
1032  return error;
1033 
1034  //Validity field successfully parsed
1035  return NO_ERROR;
1036 }
1037 
1038 
1039 /**
1040  * @brief Parse UTCTime or GeneralizedTime 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] dateTime date resulting from the parsing process
1045  * @return Error code
1046  **/
1047 
1048 error_t x509ParseTime(const uint8_t *data, size_t length,
1049  size_t *totalLength, DateTime *dateTime)
1050 {
1051  error_t error;
1052  Asn1Tag tag;
1053 
1054  //Debug message
1055  TRACE_DEBUG(" Parsing Time...\r\n");
1056 
1057  //Read current ASN.1 tag
1058  error = asn1ReadTag(data, length, &tag);
1059 
1060  //Check status code
1061  if(!error)
1062  {
1063  //Enforce encoding and class
1064  if(tag.constructed == FALSE && tag.objClass == ASN1_CLASS_UNIVERSAL)
1065  {
1066  //The date may be encoded as UTCTime or GeneralizedTime
1067  error = x509ParseTimeString(tag.value, tag.length, tag.objType,
1068  dateTime);
1069  }
1070  else
1071  {
1072  //Report an error
1073  error = ERROR_WRONG_ENCODING;
1074  }
1075  }
1076 
1077  //Check status code
1078  if(!error)
1079  {
1080  //Save the total length of the field
1081  *totalLength = tag.totalLength;
1082  }
1083 
1084  //Return status code
1085  return error;
1086 }
1087 
1088 
1089 /**
1090  * @brief Parse UTCTime or GeneralizedTime string
1091  * @param[in] data Pointer to the string to parse
1092  * @param[in] length Length of the string
1093  * @param[out] type Time format (UTCTime or GeneralizedTime)
1094  * @param[out] dateTime date resulting from the parsing process
1095  * @return Error code
1096  **/
1097 
1099  DateTime *dateTime)
1100 {
1101  error_t error;
1102  uint_t value;
1103 
1104  //The date may be encoded as UTCTime or GeneralizedTime
1105  if(type == ASN1_TYPE_UTC_TIME)
1106  {
1107  //Check the length of the UTCTime field
1108  if(length != 13)
1109  return ERROR_INVALID_SYNTAX;
1110 
1111  //The UTCTime uses a 2-digit representation of the year
1112  error = x509ParseInt(data, 2, &value);
1113  //Any error to report?
1114  if(error)
1115  return error;
1116 
1117  //If YY is greater than or equal to 50, the year shall be interpreted
1118  //as 19YY. If YY is less than 50, the year shall be interpreted as 20YY
1119  if(value >= 50)
1120  {
1121  dateTime->year = 1900 + value;
1122  }
1123  else
1124  {
1125  dateTime->year = 2000 + value;
1126  }
1127 
1128  //Point to the next field
1129  data += 2;
1130  }
1131  else if(type == ASN1_TYPE_GENERALIZED_TIME)
1132  {
1133  //Check the length of the GeneralizedTime field
1134  if(length != 15)
1135  return ERROR_INVALID_SYNTAX;
1136 
1137  //The GeneralizedTime uses a 4-digit representation of the year
1138  error = x509ParseInt(data, 4, &value);
1139  //Any error to report?
1140  if(error)
1141  return error;
1142 
1143  //Save the resulting value
1144  dateTime->year = value;
1145 
1146  //Point to the next field
1147  data += 4;
1148  }
1149  else
1150  {
1151  //The tag does not contain a valid date
1152  return ERROR_FAILURE;
1153  }
1154 
1155  //Month
1156  error = x509ParseInt(data, 2, &value);
1157  //Any error to report?
1158  if(error)
1159  return error;
1160 
1161  //Save the resulting value
1162  dateTime->month = value;
1163 
1164  //Day
1165  error = x509ParseInt(data + 2, 2, &value);
1166  //Any error to report?
1167  if(error)
1168  return error;
1169 
1170  //Save the resulting value
1171  dateTime->day = value;
1172 
1173  //Hours
1174  error = x509ParseInt(data + 4, 2, &value);
1175  //Any error to report?
1176  if(error)
1177  return error;
1178 
1179  //Save the resulting value
1180  dateTime->hours = value;
1181 
1182  //Minutes
1183  error = x509ParseInt(data + 6, 2, &value);
1184  //Any error to report?
1185  if(error)
1186  return error;
1187 
1188  //Save the resulting value
1189  dateTime->minutes = value;
1190 
1191  //Seconds
1192  error = x509ParseInt(data + 8, 2, &value);
1193  //Any error to report?
1194  if(error)
1195  return error;
1196 
1197  //The encoding shall terminate with a "Z"
1198  if(data[10] != 'Z')
1199  return ERROR_INVALID_SYNTAX;
1200 
1201  //Save the resulting value
1202  dateTime->seconds = value;
1203 
1204  //Milliseconds
1205  dateTime->milliseconds = 0;
1206 
1207  //Successful processing
1208  return NO_ERROR;
1209 }
1210 
1211 
1212 /**
1213  * @brief Convert string to integer
1214  * @param[in] data String containing the representation of an integral number
1215  * @param[in] length Length of the string
1216  * @param[out] value On success, the function returns the converted integral number
1217  * @return Error code
1218  **/
1219 
1220 error_t x509ParseInt(const uint8_t *data, size_t length, uint_t *value)
1221 {
1222  error_t error;
1223  size_t i;
1224 
1225  //Initialize status code
1226  error = NO_ERROR;
1227 
1228  //Initialize integer value
1229  *value = 0;
1230 
1231  //Parse the string
1232  for(i = 0; i < length && !error; i++)
1233  {
1234  //Check whether the character is decimal digit
1235  if(osIsdigit(data[i]))
1236  {
1237  //Convert the string to integer
1238  *value = *value * 10 + (data[i] - '0');
1239  }
1240  else
1241  {
1242  //Report an error
1243  error = ERROR_INVALID_SYNTAX;
1244  }
1245  }
1246 
1247  //Return status code
1248  return error;
1249 }
1250 
1251 #endif
error_t x509ParseTime(const uint8_t *data, size_t length, size_t *totalLength, DateTime *dateTime)
Parse UTCTime or GeneralizedTime field.
error_t x509ParseGeneralNames(const uint8_t *data, size_t length, X509GeneralName *generalNames, uint_t maxGeneralNames, uint_t *numGeneralNames)
Parse GeneralNames field.
X509Validity validity
Definition: x509_common.h:1107
const uint8_t X509_DOMAIN_COMPONENT_OID[10]
Definition: x509_common.c:76
X.509 certificate parsing.
@ ASN1_TYPE_UTC_TIME
Definition: asn1.h:90
@ ASN1_TYPE_GENERALIZED_TIME
Definition: asn1.h:91
X509GeneralNameType type
Definition: x509_common.h:908
X509SignAlgoId signatureAlgo
Definition: x509_common.h:1122
const uint8_t * value
Definition: x509_common.h:713
error_t x509ParseGeneralSubtree(const uint8_t *data, size_t length, size_t *totalLength, X509GeneralName *generalName)
Parse GeneralSubtree field.
X509TbsCertificate tbsCert
Definition: x509_common.h:1121
error_t x509ParseCertExtensions(const uint8_t *data, size_t length, size_t *totalLength, X509Extensions *extensions, const X509Options *options)
Parse X.509 certificate extensions.
TBSCertificate structure.
Definition: x509_common.h:1101
error_t x509ParseGeneralSubtrees(const uint8_t *data, size_t length)
Parse GeneralSubtrees field.
X509Extensions extensions
Definition: x509_common.h:1110
const uint8_t X509_ORGANIZATION_NAME_OID[3]
Definition: x509_common.c:58
error_t x509ParseSubjectPublicKeyInfo(const uint8_t *data, size_t length, size_t *totalLength, X509SubjectPublicKeyInfo *publicKeyInfo)
Parse SubjectPublicKeyInfo structure.
OID (Object Identifier)
Validity.
Definition: x509_common.h:763
X509KeyUsage keyUsage
Definition: x509_common.h:1055
uint16_t year
Definition: date_time.h:48
X509OctetString raw
Definition: x509_common.h:1102
#define TRUE
Definition: os_port.h:50
error_t x509ParseCertificate(const uint8_t *data, size_t length, X509CertInfo *certInfo)
Parse a X.509 certificate.
uint8_t data[]
Definition: ethernet.h:224
X509SignAlgoId signatureAlgo
Definition: x509_common.h:1105
error_t x509ParseNameAttribute(const uint8_t *data, size_t length, size_t *totalLength, X509NameAttribute *nameAttribute)
Parse name attribute.
uint8_t type
Definition: coap_common.h:176
char_t name[]
@ X509_VERSION_1
Definition: x509_common.h:514
uint16_t totalLength
Definition: ipv4.h:323
error_t x509ParseSerialNumber(const uint8_t *data, size_t length, size_t *totalLength, X509SerialNumber *serialNumber)
Parse SerialNumber field.
uint8_t version
Definition: coap_common.h:177
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_COUNTRY_NAME_OID[3]
Definition: x509_common.c:52
X.509 extension parsing.
error_t x509ParseSubjectUniqueId(const uint8_t *data, size_t length, size_t *totalLength)
Parse SubjectUniqueID structure.
@ ERROR_INVALID_VERSION
Definition: error.h:118
size_t length
Definition: x509_common.h:692
int_t oidComp(const uint8_t *oid1, size_t oidLen1, const uint8_t *oid2, size_t oidLen2)
Compare object identifiers.
Definition: oid.c:103
const uint8_t X509_PSEUDONYM_OID[3]
Definition: x509_common.c:74
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
uint8_t day
Definition: date_time.h:50
const uint8_t X509_TITLE_OID[3]
Definition: x509_common.c:62
size_t totalLength
Definition: asn1.h:111
size_t length
Definition: asn1.h:109
DateTime notAfter
Definition: x509_common.h:765
#define FALSE
Definition: os_port.h:46
General name.
Definition: x509_common.h:907
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
X509OctetString raw
Definition: x509_common.h:1120
const X509Options X509_DEFAULT_OPTIONS
Definition: x509_common.c:169
X.509 certificate.
Definition: x509_common.h:1119
uint8_t minutes
Definition: date_time.h:53
error_t
Error codes.
Definition: error.h:43
error_t x509ParseCertificateEx(const uint8_t *data, size_t length, X509CertInfo *certInfo, const X509Options *options)
Parse a X.509 certificate.
error_t x509ParseName(const uint8_t *data, size_t length, size_t *totalLength, X509Name *name)
Parse Name structure.
const uint8_t X509_INITIALS_OID[3]
Definition: x509_common.c:68
Name attribute.
Definition: x509_common.h:751
#define ASN1_CLASS_UNIVERSAL
Definition: asn1.h:52
X509BasicConstraints basicConstraints
Definition: x509_common.h:1053
X509Version
X.509 versions.
Definition: x509_common.h:513
const uint8_t X509_DN_QUALIFIER_OID[3]
Definition: x509_common.c:72
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
X509Version version
Definition: x509_common.h:1103
ASN.1 tag.
Definition: asn1.h:105
const uint8_t X509_LOCALITY_NAME_OID[3]
Definition: x509_common.c:54
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
const uint8_t X509_SERIAL_NUMBER_OID[3]
Definition: x509_common.c:50
@ X509_VERSION_3
Definition: x509_common.h:516
const uint8_t X509_COMMON_NAME_OID[3]
Definition: x509_common.c:46
General definitions for cryptographic algorithms.
@ ERROR_BAD_CERTIFICATE
Definition: error.h:236
X509SerialNumber serialNumber
Definition: x509_common.h:1104
X509OctetString signatureValue
Definition: x509_common.h:1123
uint8_t hours
Definition: date_time.h:52
Date and time representation.
Definition: date_time.h:47
#define osIsdigit(c)
Definition: os_port.h:288
uint_t objClass
Definition: asn1.h:107
uint8_t length
Definition: tcp.h:375
X509OctetString oid
Definition: x509_common.h:1089
uint16_t bitmap
Definition: x509_common.h:887
#define MIN(a, b)
Definition: os_port.h:63
error_t x509ParseTimeString(const uint8_t *data, size_t length, uint_t type, DateTime *dateTime)
Parse UTCTime or GeneralizedTime string.
uint8_t seconds
Definition: date_time.h:54
error_t x509ParseSignatureValue(const uint8_t *data, size_t length, size_t *totalLength, X509OctetString *signature)
Parse SignatureValue field.
const uint8_t PKCS9_EMAIL_ADDR_OID[9]
Definition: x509_common.c:162
const char_t * value
Definition: x509_common.h:909
error_t x509ParseVersion(const uint8_t *data, size_t length, size_t *totalLength, X509Version *version)
Parse Version field.
@ ASN1_TYPE_INTEGER
Definition: asn1.h:73
#define TRACE_DEBUG(...)
Definition: debug.h:119
uint8_t month
Definition: date_time.h:49
char char_t
Definition: compiler_port.h:55
@ X509_VERSION_2
Definition: x509_common.h:515
DateTime notBefore
Definition: x509_common.h:764
const char_t * value
Definition: x509_common.h:691
#define X509_MAX_DOMAIN_COMPONENTS
Definition: x509_common.h:422
const uint8_t X509_NAME_OID[3]
Definition: x509_common.c:64
#define OID_COMP(oid1, oidLen1, oid2)
Definition: oid.h:42
uint8_t n
Issuer or subject name.
Definition: x509_common.h:723
#define ASN1_CLASS_CONTEXT_SPECIFIC
Definition: asn1.h:54
error_t x509ParseIssuerUniqueId(const uint8_t *data, size_t length, size_t *totalLength)
Parse IssuerUniqueID structure.
error_t x509ParseInt(const uint8_t *data, size_t length, uint_t *value)
Convert string to integer.
const uint8_t X509_GENERATION_QUALIFIER_OID[3]
Definition: x509_common.c:70
uint8_t value[]
Definition: tcp.h:376
error_t x509ParseSignatureAlgo(const uint8_t *data, size_t length, size_t *totalLength, X509SignAlgoId *signatureAlgo)
Parse SignatureAlgorithm structure.
bool_t constructed
Definition: asn1.h:106
@ ERROR_WRONG_IDENTIFIER
Definition: error.h:89
@ ERROR_INVALID_SYNTAX
Definition: error.h:68
uint16_t milliseconds
Definition: date_time.h:55
const uint8_t X509_ORGANIZATIONAL_UNIT_NAME_OID[3]
Definition: x509_common.c:60
@ ERROR_WRONG_ENCODING
Definition: error.h:122
uint8_t options[]
Definition: tcp.h:364
const uint8_t X509_SURNAME_OID[3]
Definition: x509_common.c:48
error_t x509ParseValidity(const uint8_t *data, size_t length, size_t *totalLength, X509Validity *validity)
Parse Validity structure.
X509OctetString oid
Definition: x509_common.h:752
const uint8_t X509_GIVEN_NAME_OID[3]
Definition: x509_common.c:66
const uint8_t * value
Definition: x509_common.h:702
Parsing of ASN.1 encoded keys.
bool_t x509CompareName(const uint8_t *name1, size_t nameLen1, const uint8_t *name2, size_t nameLen2)
Compare distinguished names.
Definition: x509_common.c:184
@ ERROR_INVALID_CLASS
Definition: error.h:117
Serial number.
Definition: x509_common.h:712
unsigned int uint_t
Definition: compiler_port.h:57
#define osMemset(p, value, length)
Definition: os_port.h:138
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
X509SubjectPublicKeyInfo subjectPublicKeyInfo
Definition: x509_common.h:1109
X509GeneralNameType
General name types.
Definition: x509_common.h:566
X509String data
Definition: x509_common.h:754
const uint8_t X509_STATE_OR_PROVINCE_NAME_OID[]
Definition: x509_common.c:56
@ ASN1_TYPE_SET
Definition: asn1.h:84
X509OctetString raw
Definition: x509_common.h:724
const uint8_t * value
Definition: asn1.h:110
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)
@ X509_KEY_USAGE_KEY_CERT_SIGN
Definition: x509_common.h:531
error_t x509ParseTbsCertificate(const uint8_t *data, size_t length, size_t *totalLength, X509TbsCertificate *tbsCert, const X509Options *options)
Parse TBSCertificate structure.