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