x509_cert_validate.c
Go to the documentation of this file.
1 /**
2  * @file x509_cert_validate.c
3  * @brief X.509 certificate validation
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2020 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 1.9.8
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 "encoding/asn1.h"
40 #include "encoding/oid.h"
41 #include "pkc/rsa.h"
42 #include "pkc/dsa.h"
43 #include "ecc/ecdsa.h"
44 #include "ecc/ed25519.h"
45 #include "ecc/ed448.h"
46 #include "debug.h"
47 
48 //Check crypto library configuration
49 #if (X509_SUPPORT == ENABLED)
50 
51 
52 /**
53  * @brief X.509 certificate validation
54  * @param[in] certInfo X.509 certificate to be verified
55  * @param[in] issuerCertInfo Issuer certificate
56  * @param[in] pathLen Certificate path length
57  * @return Error code
58  **/
59 
61  const X509CertificateInfo *issuerCertInfo, uint_t pathLen)
62 {
63  error_t error;
64  time_t currentTime;
66 
67  //Check parameters
68  if(certInfo == NULL || issuerCertInfo == NULL)
70 
71  //Retrieve current time
72  currentTime = getCurrentUnixTime();
73 
74  //Any real-time clock implemented?
75  if(currentTime != 0)
76  {
77  DateTime currentDate;
78  const X509Validity *validity;
79 
80  //Convert Unix timestamp to date
81  convertUnixTimeToDate(currentTime, &currentDate);
82 
83  //The certificate validity period is the time interval during which the
84  //CA warrants that it will maintain information about the status of the
85  //certificate
86  validity = &certInfo->tbsCert.validity;
87 
88  //Check the validity period
89  if(compareDateTime(&currentDate, &validity->notBefore) < 0 ||
90  compareDateTime(&currentDate, &validity->notAfter) > 0)
91  {
92  //The certificate has expired or is not yet valid
94  }
95  }
96 
97  //Make sure that the subject and issuer names chain correctly
98  if(!x509CompareName(certInfo->tbsCert.issuer.rawData,
99  certInfo->tbsCert.issuer.rawDataLen,
100  issuerCertInfo->tbsCert.subject.rawData,
101  issuerCertInfo->tbsCert.subject.rawDataLen))
102  {
103  //Report an error
104  return ERROR_BAD_CERTIFICATE;
105  }
106 
107  //Point to the X.509 extensions of the issuer certificate
108  extensions = &issuerCertInfo->tbsCert.extensions;
109 
110  //X.509 version 3 certificate?
111  if(issuerCertInfo->tbsCert.version >= X509_VERSION_3)
112  {
113  //Ensure that the issuer certificate is a CA certificate
114  if(!extensions->basicConstraints.cA)
115  return ERROR_BAD_CERTIFICATE;
116  }
117 
118  //Where pathLenConstraint does not appear, no limit is imposed
119  if(extensions->basicConstraints.pathLenConstraint >= 0)
120  {
121  //The pathLenConstraint field gives the maximum number of non-self-issued
122  //intermediate certificates that may follow this certificate in a valid
123  //certification path
124  if(pathLen > (uint_t) extensions->basicConstraints.pathLenConstraint)
125  return ERROR_BAD_CERTIFICATE;
126  }
127 
128  //Check if the keyUsage extension is present
129  if(extensions->keyUsage.bitmap != 0)
130  {
131  //If the keyUsage extension is present, then the subject public key must
132  //not be used to verify signatures on certificates unless the keyCertSign
133  //bit is set (refer to RFC 5280, section 4.2.1.3)
134  if(!(extensions->keyUsage.bitmap & X509_KEY_USAGE_KEY_CERT_SIGN))
135  return ERROR_BAD_CERTIFICATE;
136  }
137 
138  //The ASN.1 DER-encoded tbsCertificate is used as the input to the signature
139  //function
140  error = x509VerifySignature(certInfo->tbsCert.rawData,
141  certInfo->tbsCert.rawDataLen, &certInfo->signatureAlgo,
142  &issuerCertInfo->tbsCert.subjectPublicKeyInfo, &certInfo->signatureValue);
143 
144  //Return status code
145  return error;
146 }
147 
148 
149 /**
150  * @brief Check whether the certificate matches the specified FQDN
151  * @param[in] certInfo Pointer to the X.509 certificate
152  * @param[in] fqdn NULL-terminated string that contains the fully-qualified domain name
153  * @return Error code
154  **/
155 
157  const char_t *fqdn)
158 {
159  error_t error;
160  bool_t res;
161  uint_t i;
162  size_t n;
163  size_t length;
164  const uint8_t *data;
165  const X509Extensions *extensions;
166  X509GeneralName generalName;
167 
168  //Point to the X.509 extensions of the CA certificate
169  extensions = &certInfo->tbsCert.extensions;
170 
171  //Valid FQDN name provided?
172  if(fqdn != NULL)
173  {
174  //Initialize flag
175  res = FALSE;
176 
177  //Total number of valid DNS names found in the SubjectAltName extension
178  i = 0;
179 
180  //Valid SubjectAltName extension?
181  if(extensions->subjectAltName.rawDataLen > 0)
182  {
183  //The subject alternative name extension allows identities to be bound
184  //to the subject of the certificate. These identities may be included
185  //in addition to or in place of the identity in the subject field of
186  //the certificate
187  data = extensions->subjectAltName.rawData;
188  length = extensions->subjectAltName.rawDataLen;
189 
190  //Loop through the list of subject alternative names
191  while(!res && length > 0)
192  {
193  //Parse GeneralName field
194  error = x509ParseGeneralName(data, length, &n, &generalName);
195  //Failed to decode ASN.1 tag?
196  if(error)
197  return error;
198 
199  //DNS name found?
200  if(generalName.type == X509_GENERAL_NAME_TYPE_DNS)
201  {
202  //Check whether the alternative name matches the specified FQDN
203  res = x509CompareSubjectName(generalName.value,
204  generalName.length, fqdn);
205 
206  //Increment counter
207  i++;
208  }
209 
210  //Next item
211  data += n;
212  length -= n;
213  }
214  }
215 
216  //No match?
217  if(!res)
218  {
219  //The implementation must not seek a match for a reference identifier
220  //of CN-ID if the presented identifiers include a DNS-ID, SRV-ID or
221  //URI-ID (refer to RFC 6125, section 6.4.4)
222  if(i == 0 && certInfo->tbsCert.subject.commonNameLen > 0)
223  {
224  //The implementation may as a last resort check the CN-ID for a match
226  certInfo->tbsCert.subject.commonNameLen, fqdn);
227  }
228  }
229 
230  //Check whether the subject name matches the specified FQDN
231  error = res ? NO_ERROR : ERROR_INVALID_NAME;
232  }
233  else
234  {
235  //If no valid FQDN name is provided, then the subject name of the
236  //certificate is not verified
237  error = NO_ERROR;
238  }
239 
240  //Return status code
241  return error;
242 }
243 
244 
245 /**
246  * @brief Check name constraints
247  * @param[in] subjectName Subject name to be verified
248  * @param[in] certInfo Pointer to the CA certificate
249  * @return Error code
250  **/
251 
253  const X509CertificateInfo *certInfo)
254 {
255  error_t error;
256  bool_t match;
257  size_t m;
258  size_t n;
259  size_t length;
260  const uint8_t *data;
261  const X509Extensions *extensions;
262  X509GeneralName subtree;
263 
264  //Initialize error code
265  error = NO_ERROR;
266 
267  //Point to the X.509 extensions of the CA certificate
268  extensions = &certInfo->tbsCert.extensions;
269 
270  //Valid subject name provided?
271  if(subjectName != NULL)
272  {
273  //Point to the list of excluded name subtrees
274  data = extensions->nameConstraints.excludedSubtrees;
275  length = extensions->nameConstraints.excludedSubtreesLen;
276 
277  //Loop through the names constraints
278  while(length > 0)
279  {
280  //Parse GeneralSubtree field
281  error = x509ParseGeneralSubtree(data, length, &n, &subtree);
282  //Failed to decode ASN.1 tag?
283  if(error)
284  break;
285 
286  //Initialize flag
287  match = FALSE;
288 
289  //Check name type
290  if(subtree.type == X509_GENERAL_NAME_TYPE_DNS)
291  {
292  //Check whether the subject name matches the subtree
293  match = x509CompareSubtree(subjectName, subtree.value,
294  subtree.length);
295  }
296  else if(subtree.type == X509_GENERAL_NAME_TYPE_DIRECTORY)
297  {
298  X509Name name;
299 
300  //Parse distinguished name
301  error = x509ParseName((uint8_t *) subtree.value, subtree.length,
302  &m, &name);
303  //Failed to decode ASN.1 structure?
304  if(error)
305  break;
306 
307  //Valid common name?
308  if(name.commonName != NULL)
309  {
310  //Check whether the subject name matches the subtree
311  match = x509CompareSubtree(subjectName, name.commonName,
312  name.commonNameLen);
313  }
314  }
315  else
316  {
317  //Just for sanity
318  }
319 
320  //Any match?
321  if(match)
322  {
323  //The subject name is not acceptable
324  error = ERROR_INVALID_NAME;
325  break;
326  }
327 
328  //Next item
329  data += n;
330  length -= n;
331  }
332 
333  //Any name matching a restriction in the excludedSubtrees field is
334  //invalid regardless of information appearing in the permittedSubtrees
335  //(Refer to RFC 5280, section 4.2.1.10)
336  if(!error)
337  {
338  //Point to the list of permitted name subtrees
339  data = extensions->nameConstraints.permittedSubtrees;
340  length = extensions->nameConstraints.permittedSubtreesLen;
341 
342  //Loop through the names constraints
343  while(length > 0)
344  {
345  //Parse GeneralSubtree field
346  error = x509ParseGeneralSubtree(data, length, &n, &subtree);
347  //Failed to decode ASN.1 tag?
348  if(error)
349  break;
350 
351  //Initialize flag
352  match = FALSE;
353 
354  //Check name type
355  if(subtree.type == X509_GENERAL_NAME_TYPE_DNS)
356  {
357  //Check whether the subject name matches the subtree
358  match = x509CompareSubtree(subjectName, subtree.value,
359  subtree.length);
360  }
361  else if(subtree.type == X509_GENERAL_NAME_TYPE_DIRECTORY)
362  {
363  X509Name name;
364 
365  //Parse distinguished name
366  error = x509ParseName((uint8_t *) subtree.value, subtree.length,
367  &m, &name);
368  //Failed to decode ASN.1 structure?
369  if(error)
370  break;
371 
372  //Valid common name?
373  if(name.commonName != NULL)
374  {
375  //Check whether the subject name matches the subtree
376  match = x509CompareSubtree(subjectName, name.commonName,
377  name.commonNameLen);
378  }
379  }
380  else
381  {
382  //Just for sanity
383  }
384 
385  //Any match?
386  if(match)
387  {
388  //The subject name is acceptable
389  error = NO_ERROR;
390  break;
391  }
392  else
393  {
394  //The subject name does not match the current field
395  error = ERROR_INVALID_NAME;
396  }
397 
398  //Next item
399  data += n;
400  length -= n;
401  }
402  }
403  }
404  else
405  {
406  //If no valid subject name is provided, then the name constraints
407  //are not verified
408  }
409 
410  //Return status code
411  return error;
412 }
413 
414 
415 /**
416  * @brief Compare distinguished names
417  * @param[in] name1 Pointer to the first distinguished name
418  * @param[in] nameLen1 Length of the first distinguished name
419  * @param[in] name2 Pointer to the second distinguished name
420  * @param[in] nameLen2 Length of the second distinguished name
421  * @return Comparison result
422  **/
423 
424 bool_t x509CompareName(const uint8_t *name1, size_t nameLen1,
425  const uint8_t *name2, size_t nameLen2)
426 {
427  //Compare the length of the distinguished names
428  if(nameLen1 != nameLen2)
429  return FALSE;
430 
431  //Compare the contents of the distinguished names
432  if(osMemcmp(name1, name2, nameLen1))
433  return FALSE;
434 
435  //The distinguished names match
436  return TRUE;
437 }
438 
439 
440 /**
441  * @brief Check whether the subject name matches the specified FQDN
442  * @param[in] subjectName Subject name
443  * @param[in] subjectNameLen Length of the subject name
444  * @param[in] fqdn NULL-terminated string that contains the fully-qualified domain name
445  * @return TRUE if the subject name matches the specified FQDN, else FALSE
446  **/
447 
449  size_t subjectNameLen, const char_t *fqdn)
450 {
451  size_t i;
452  size_t j;
453  size_t fqdnLen;
454 
455  //Retrieve the length of the FQDN
456  fqdnLen = osStrlen(fqdn);
457 
458  //Initialize variables
459  i = 0;
460  j = 0;
461 
462  //Parse the subject name
463  while(i < subjectNameLen && j < fqdnLen)
464  {
465  //Wildcard name found?
466  if(subjectName[i] == '*')
467  {
468  //The implementation should not attempt to match a presented
469  //identifier in which the wildcard character comprises a label other
470  //than the left-most label (refer to RFC 6125, section 6.4.3)
471  if(i != 0)
472  {
473  break;
474  }
475 
476  //The implementation should not compare against anything but the
477  //left-most label of the reference identifier
478  if(fqdn[j] == '.')
479  {
480  i++;
481  }
482  else
483  {
484  j++;
485  }
486  }
487  else
488  {
489  //Perform case insensitive character comparison
490  if(osTolower(subjectName[i]) != fqdn[j])
491  {
492  break;
493  }
494 
495  //Compare next characters
496  i++;
497  j++;
498  }
499  }
500 
501  //Check whether the subject name matches the specified FQDN
502  if(i == subjectNameLen && j == fqdnLen)
503  {
504  return TRUE;
505  }
506  else
507  {
508  return FALSE;
509  }
510 }
511 
512 
513 /**
514  * @brief Compare a subject name against the specified subtree
515  * @param[in] subjectName NULL-terminated string that contains the subject name
516  * @param[in] subtree Pointer to the subtree
517  * @param[in] subtreeLen Length of the subtree
518  * @return Comparison result
519  **/
520 
521 bool_t x509CompareSubtree(const char_t *subjectName,
522  const char_t *subtree, size_t subtreeLen)
523 {
524  int_t i;
525  int_t j;
526 
527  //Point to the last character of the subtree
528  i = subtreeLen - 1;
529  //Point to the last character of the subject name
530  j = osStrlen(subjectName) - 1;
531 
532  //Parse the subtree
533  while(i >= 0 && j >= 0)
534  {
535  //Perform case insensitive character comparison
536  if(osTolower(subtree[i]) != subjectName[j])
537  {
538  break;
539  }
540 
541  //The constraint may specify a host or a domain
542  if(subtree[i] == '.' && i == 0)
543  {
544  //When the constraint begins with a period, it may be expanded with
545  //one or more labels (refer to RFC 5280, section 4.2.1.10)
546  i = -1;
547  j = -1;
548  }
549  else
550  {
551  //Compare previous characters
552  i--;
553  j--;
554  }
555  }
556 
557  //Check whether the subject name matches the specified subtree
558  if(i < 0 && j < 0)
559  {
560  return TRUE;
561  }
562  else
563  {
564  return FALSE;
565  }
566 }
567 
568 
569 /**
570  * @brief Certificate signature verification
571  * @param[in] tbsCert TBSCertificate whose signature is to be verified
572  * @param[in] tbsCertLen Length of the TBSCertificate, in bytes
573  * @param[in] signatureAlgoId Signature algorithm identifier
574  * @param[in] publicKeyInfo Issuer's public key
575  * @param[in] signatureValue Signature to be verified
576  * @return Error code
577  **/
578 
579 error_t x509VerifySignature(const uint8_t *tbsCert, size_t tbsCertLen,
580  const X509SignatureAlgoId *signatureAlgoId,
581  const X509SubjectPublicKeyInfo *publicKeyInfo,
582  const X509SignatureValue *signatureValue)
583 {
584  error_t error;
585  X509SignatureAlgo signAlgo;
586  const HashAlgo *hashAlgo;
587  uint8_t digest[X509_MAX_HASH_DIGEST_SIZE];
588 
589  //Retrieve the signature algorithm that was used to sign the certificate
590  error = x509GetSignHashAlgo(signatureAlgoId, &signAlgo, &hashAlgo);
591  //Unsupported signature algorithm?
592  if(error)
593  return error;
594 
595  //Ed25519 and Ed448 are used in PureEdDSA mode, without pre-hashing
596  if(hashAlgo != NULL)
597  {
598  //Digest the TBSCertificate structure using the specified hash algorithm
599  error = hashAlgo->compute(tbsCert, tbsCertLen, digest);
600  //Any error to report?
601  if(error)
602  return error;
603 
604 #if (X509_RSA_SUPPORT == ENABLED && RSA_SUPPORT == ENABLED)
605  //RSA signature algorithm?
606  if(signAlgo == X509_SIGN_ALGO_RSA)
607  {
608  uint_t k;
609  RsaPublicKey publicKey;
610 
611  //Initialize RSA public key
612  rsaInitPublicKey(&publicKey);
613 
614  //Import the RSA public key
615  error = x509ImportRsaPublicKey(publicKeyInfo, &publicKey);
616 
617  //Check status code
618  if(!error)
619  {
620  //Get the length of the modulus, in bits
621  k = mpiGetBitLength(&publicKey.n);
622 
623  //Make sure the modulus is acceptable
624  if(k < X509_MIN_RSA_MODULUS_SIZE || k > X509_MAX_RSA_MODULUS_SIZE)
625  {
626  //Report an error
627  error = ERROR_INVALID_KEY;
628  }
629  }
630 
631  //Check status code
632  if(!error)
633  {
634  //Verify RSA signature (RSASSA-PKCS1-v1_5 signature scheme)
635  error = rsassaPkcs1v15Verify(&publicKey, hashAlgo, digest,
636  signatureValue->data, signatureValue->length);
637  }
638 
639  //Release previously allocated resources
640  rsaFreePublicKey(&publicKey);
641  }
642  else
643 #endif
644 #if (X509_RSA_PSS_SUPPORT == ENABLED && RSA_SUPPORT == ENABLED)
645  //RSA-PSS signature algorithm?
646  if(signAlgo == X509_SIGN_ALGO_RSA_PSS)
647  {
648  uint_t k;
649  RsaPublicKey publicKey;
650 
651  //Initialize RSA public key
652  rsaInitPublicKey(&publicKey);
653 
654  //Import the RSA public key
655  error = x509ImportRsaPublicKey(publicKeyInfo, &publicKey);
656 
657  //Check status code
658  if(!error)
659  {
660  //Get the length of the modulus, in bits
661  k = mpiGetBitLength(&publicKey.n);
662 
663  //Make sure the modulus is acceptable
664  if(k < X509_MIN_RSA_MODULUS_SIZE || k > X509_MAX_RSA_MODULUS_SIZE)
665  {
666  //Report an error
667  error = ERROR_INVALID_KEY;
668  }
669  }
670 
671  //Check status code
672  if(!error)
673  {
674  //Retrieve the length of the salt
675  k = signatureAlgoId->rsaPssParams.saltLen;
676 
677  //Verify RSA signature (RSASSA-PSS signature scheme)
678  error = rsassaPssVerify(&publicKey, hashAlgo, k, digest,
679  signatureValue->data, signatureValue->length);
680  }
681 
682  //Release previously allocated resources
683  rsaFreePublicKey(&publicKey);
684  }
685  else
686 #endif
687 #if (X509_DSA_SUPPORT == ENABLED && DSA_SUPPORT == ENABLED)
688  //DSA signature algorithm?
689  if(signAlgo == X509_SIGN_ALGO_DSA)
690  {
691  uint_t k;
692  DsaPublicKey publicKey;
694 
695  //Initialize DSA public key
696  dsaInitPublicKey(&publicKey);
697  //Initialize DSA signature
699 
700  //Import the DSA public key
701  error = x509ImportDsaPublicKey(publicKeyInfo, &publicKey);
702 
703  //Check status code
704  if(!error)
705  {
706  //Get the length of the prime modulus, in bits
707  k = mpiGetBitLength(&publicKey.p);
708 
709  //Make sure the prime modulus is acceptable
710  if(k < X509_MIN_DSA_MODULUS_SIZE || k > X509_MAX_DSA_MODULUS_SIZE)
711  {
712  //Report an error
713  error = ERROR_INVALID_KEY;
714  }
715  }
716 
717  //Check status code
718  if(!error)
719  {
720  //Read the ASN.1 encoded signature
721  error = dsaReadSignature(signatureValue->data,
722  signatureValue->length, &signature);
723  }
724 
725  //Check status code
726  if(!error)
727  {
728  //Verify DSA signature
729  error = dsaVerifySignature(&publicKey, digest, hashAlgo->digestSize,
730  &signature);
731  }
732 
733  //Release previously allocated resources
734  dsaFreePublicKey(&publicKey);
736  }
737  else
738 #endif
739 #if (X509_ECDSA_SUPPORT == ENABLED && ECDSA_SUPPORT == ENABLED)
740  //ECDSA signature algorithm?
741  if(signAlgo == X509_SIGN_ALGO_ECDSA)
742  {
743  const EcCurveInfo *curveInfo;
744  EcDomainParameters params;
745  EcPoint publicKey;
747 
748  //Initialize EC domain parameters
749  ecInitDomainParameters(&params);
750  //Initialize ECDSA public key
751  ecInit(&publicKey);
752  //Initialize ECDSA signature
754 
755  //Retrieve EC domain parameters
756  curveInfo = x509GetCurveInfo(publicKeyInfo->ecParams.namedCurve,
757  publicKeyInfo->ecParams.namedCurveLen);
758 
759  //Make sure the specified elliptic curve is supported
760  if(curveInfo != NULL)
761  {
762  //Load EC domain parameters
763  error = ecLoadDomainParameters(&params, curveInfo);
764  }
765  else
766  {
767  //Invalid EC domain parameters
768  error = ERROR_BAD_CERTIFICATE;
769  }
770 
771  //Check status code
772  if(!error)
773  {
774  //Retrieve the EC public key
775  error = ecImport(&params, &publicKey, publicKeyInfo->ecPublicKey.q,
776  publicKeyInfo->ecPublicKey.qLen);
777  }
778 
779  //Check status code
780  if(!error)
781  {
782  //Read the ASN.1 encoded signature
783  error = ecdsaReadSignature(signatureValue->data,
784  signatureValue->length, &signature);
785  }
786 
787  //Check status code
788  if(!error)
789  {
790  //Verify ECDSA signature
791  error = ecdsaVerifySignature(&params, &publicKey, digest,
792  hashAlgo->digestSize, &signature);
793  }
794 
795  //Release previously allocated resources
796  ecFreeDomainParameters(&params);
797  ecFree(&publicKey);
799  }
800  else
801 #endif
802  //Invalid signature algorithm?
803  {
804  //Report an error
806  }
807  }
808  else
809  {
810 #if (X509_ED25519_SUPPORT == ENABLED && ED25519_SUPPORT == ENABLED)
811  //Ed25519 signature algorithm?
812  if(signAlgo == X509_SIGN_ALGO_ED25519)
813  {
814  //Check the length of the public key
815  if(publicKeyInfo->ecPublicKey.qLen == ED25519_PUBLIC_KEY_LEN)
816  {
817  //Check the length of the EdDSA signature
818  if(signatureValue->length == ED25519_SIGNATURE_LEN)
819  {
820  //Verify signature (PureEdDSA mode)
821  error = ed25519VerifySignature(publicKeyInfo->ecPublicKey.q,
822  tbsCert, tbsCertLen, NULL, 0, 0, signatureValue->data);
823  }
824  else
825  {
826  //The length of the EdDSA signature is not valid
827  error = ERROR_INVALID_SIGNATURE;
828  }
829  }
830  else
831  {
832  //The length of the Ed25519 public key is not valid
833  error = ERROR_ILLEGAL_PARAMETER;
834  }
835  }
836  else
837 #endif
838 #if (X509_ED448_SUPPORT == ENABLED && ED448_SUPPORT == ENABLED)
839  //Ed448 signature algorithm?
840  if(signAlgo == X509_SIGN_ALGO_ED448)
841  {
842  //Check the length of the public key
843  if(publicKeyInfo->ecPublicKey.qLen == ED448_PUBLIC_KEY_LEN)
844  {
845  //Check the length of the EdDSA signature
846  if(signatureValue->length == ED448_SIGNATURE_LEN)
847  {
848  //Verify signature (PureEdDSA mode)
849  error = ed448VerifySignature(publicKeyInfo->ecPublicKey.q,
850  tbsCert, tbsCertLen, NULL, 0, 0, signatureValue->data);
851  }
852  else
853  {
854  //The length of the EdDSA signature is not valid
855  error = ERROR_INVALID_SIGNATURE;
856  }
857  }
858  else
859  {
860  //The length of the Ed448 public key is not valid
861  error = ERROR_ILLEGAL_PARAMETER;
862  }
863  }
864  else
865 #endif
866  //Invalid signature algorithm?
867  {
868  //Report an error
870  }
871  }
872 
873  //Return status code
874  return error;
875 }
876 
877 #endif
uint8_t length
Definition: coap_common.h:190
ECDSA signature.
Definition: ecdsa.h:48
X509Validity validity
Definition: x509_common.h:918
X.509 certificate parsing.
Ed25519 elliptic curve (constant-time implementation)
X509GeneralNameType type
Definition: x509_common.h:775
int bool_t
Definition: compiler_port.h:49
void rsaFreePublicKey(RsaPublicKey *key)
Release an RSA public key.
Definition: rsa.c:118
error_t x509ParseGeneralSubtree(const uint8_t *data, size_t length, size_t *totalLength, X509GeneralName *generalName)
Parse GeneralSubtree field.
uint8_t data[]
Definition: ethernet.h:209
const EcCurveInfo * x509GetCurveInfo(const uint8_t *oid, size_t length)
Get the elliptic curve that matches the specified OID.
Definition: x509_common.c:860
signed int int_t
Definition: compiler_port.h:44
const uint8_t * data
Definition: x509_common.h:901
error_t x509ImportRsaPublicKey(const X509SubjectPublicKeyInfo *publicKeyInfo, RsaPublicKey *publicKey)
Import an RSA public key.
Signature algorithm identifier.
Definition: x509_common.h:885
void ecInitDomainParameters(EcDomainParameters *params)
Initialize EC domain parameters.
Definition: ec.c:55
error_t ecImport(const EcDomainParameters *params, EcPoint *r, const uint8_t *data, size_t length)
Convert an octet string to an EC point.
Definition: ec.c:214
X509Extensions extensions
Definition: x509_common.h:921
#define ED25519_PUBLIC_KEY_LEN
Definition: ed25519.h:41
OID (Object Identifier)
ECDSA (Elliptic Curve Digital Signature Algorithm)
Validity.
Definition: x509_common.h:629
#define TRUE
Definition: os_port.h:50
#define ED448_PUBLIC_KEY_LEN
Definition: ed448.h:41
size_t rawDataLen
Definition: x509_common.h:578
X509RsaPssParameters rsaPssParams
Definition: x509_common.h:890
size_t digestSize
Definition: crypto.h:1069
X.509 certificate.
Definition: x509_common.h:929
uint8_t signature
Definition: tls.h:1381
X509EcParameters ecParams
Definition: x509_common.h:715
error_t ed448VerifySignature(const uint8_t *publicKey, const void *message, size_t messageLen, const void *context, uint8_t contextLen, uint8_t flag, const uint8_t *signature)
EdDSA signature verification.
Definition: ed448.c:286
#define ED448_SIGNATURE_LEN
Definition: ed448.h:43
#define osMemcmp(p1, p2, length)
Definition: os_port.h:146
error_t x509GetSignHashAlgo(const X509SignatureAlgoId *signAlgoId, X509SignatureAlgo *signAlgo, const HashAlgo **hashAlgo)
Get the signature and hash algorithms that match the specified identifier.
Definition: x509_common.c:337
void convertUnixTimeToDate(time_t t, DateTime *date)
Convert Unix timestamp to date.
Definition: date_time.c:198
char_t name[]
const uint8_t * q
Definition: x509_common.h:692
#define ED25519_SIGNATURE_LEN
Definition: ed25519.h:43
#define osStrlen(s)
Definition: os_port.h:152
error_t x509VerifySignature(const uint8_t *tbsCert, size_t tbsCertLen, const X509SignatureAlgoId *signatureAlgoId, const X509SubjectPublicKeyInfo *publicKeyInfo, const X509SignatureValue *signatureValue)
Certificate signature verification.
const uint8_t * rawData
Definition: x509_common.h:912
EC domain parameters.
Definition: ec.h:63
const uint8_t res[]
void ecFreeDomainParameters(EcDomainParameters *params)
Release EC domain parameters.
Definition: ec.c:75
__weak error_t ecdsaVerifySignature(const EcDomainParameters *params, const EcPoint *publicKey, const uint8_t *digest, size_t digestLen, const EcdsaSignature *signature)
ECDSA signature verification.
Definition: ecdsa.c:562
Mpi n
Modulus.
Definition: rsa.h:50
bool_t x509CompareName(const uint8_t *name1, size_t nameLen1, const uint8_t *name2, size_t nameLen2)
Compare distinguished names.
void ecdsaFreeSignature(EcdsaSignature *signature)
Release an ECDSA signature.
Definition: ecdsa.c:82
error_t x509CheckNameConstraints(const char_t *subjectName, const X509CertificateInfo *certInfo)
Check name constraints.
error_t ecLoadDomainParameters(EcDomainParameters *params, const EcCurveInfo *curveInfo)
Load EC domain parameters.
Definition: ec.c:93
DateTime notAfter
Definition: x509_common.h:632
#define FALSE
Definition: os_port.h:46
X509SignatureAlgo
Signature algorithms.
Definition: x509_common.h:528
Elliptic curve parameters.
Definition: ec_curves.h:292
General name.
Definition: x509_common.h:773
DSA public key.
Definition: dsa.h:60
Invalid parameter.
Definition: error.h:47
error_t x509ImportDsaPublicKey(const X509SubjectPublicKeyInfo *publicKeyInfo, DsaPublicKey *publicKey)
Import a DSA public key.
error_t
Error codes.
Definition: error.h:42
void dsaInitSignature(DsaSignature *signature)
Initialize a DSA signature.
Definition: dsa.c:137
HashAlgoCompute compute
Definition: crypto.h:1072
error_t x509ParseName(const uint8_t *data, size_t length, size_t *totalLength, X509Name *name)
Parse Name structure.
#define X509_MAX_HASH_DIGEST_SIZE
Definition: x509_common.h:366
X509Version version
Definition: x509_common.h:914
void ecInit(EcPoint *r)
Initialize elliptic curve point.
Definition: ec.c:156
RSA public key.
Definition: rsa.h:48
void ecdsaInitSignature(EcdsaSignature *signature)
Initialize an ECDSA signature.
Definition: ecdsa.c:69
X509SignatureValue signatureValue
Definition: x509_common.h:933
#define X509_MAX_DSA_MODULUS_SIZE
Definition: x509_common.h:331
General definitions for cryptographic algorithms.
RSA public-key cryptography standard.
DSA (Digital Signature Algorithm)
Date and time representation.
Definition: date_time.h:46
Elliptic curve point.
Definition: ec.h:51
const uint8_t * rawData
Definition: x509_common.h:577
size_t namedCurveLen
Definition: x509_common.h:682
Signature value.
Definition: x509_common.h:899
uint_t mpiGetBitLength(const Mpi *a)
Get the actual length in bits.
Definition: mpi.c:195
const char_t * value
Definition: x509_common.h:776
char char_t
Definition: compiler_port.h:43
error_t dsaVerifySignature(const DsaPublicKey *key, const uint8_t *digest, size_t digestLen, const DsaSignature *signature)
DSA signature verification.
Definition: dsa.c:563
error_t rsassaPkcs1v15Verify(const RsaPublicKey *key, const HashAlgo *hash, const uint8_t *digest, const uint8_t *signature, size_t signatureLen)
RSASSA-PKCS1-v1_5 signature verification operation.
Definition: rsa.c:811
const char_t * commonName
Definition: x509_common.h:579
Mpi p
Prime modulus.
Definition: dsa.h:62
DateTime notBefore
Definition: x509_common.h:631
size_t commonNameLen
Definition: x509_common.h:580
uint8_t m
Definition: ndp.h:302
uint8_t n
Issuer or subject name.
Definition: x509_common.h:575
uint8_t extensions[]
Definition: tls13_misc.h:327
Subject public key information.
Definition: x509_common.h:701
error_t rsassaPssVerify(const RsaPublicKey *key, const HashAlgo *hash, size_t saltLen, const uint8_t *digest, const uint8_t *signature, size_t signatureLen)
RSASSA-PSS signature verification operation.
Definition: rsa.c:1040
void dsaFreeSignature(DsaSignature *signature)
Release a DSA signature.
Definition: dsa.c:150
error_t dsaReadSignature(const uint8_t *data, size_t length, DsaSignature *signature)
Read an ASN.1 encoded DSA signature.
Definition: dsa.c:322
time_t getCurrentUnixTime(void)
Get current time.
Definition: date_time.c:180
error_t x509ValidateCertificate(const X509CertificateInfo *certInfo, const X509CertificateInfo *issuerCertInfo, uint_t pathLen)
X.509 certificate validation.
X.509 certificate validation.
#define osTolower(c)
Definition: os_port.h:224
X.509 certificate extensions.
Definition: x509_common.h:848
#define X509_MAX_RSA_MODULUS_SIZE
Definition: x509_common.h:317
X509SignatureAlgoId signatureAlgo
Definition: x509_common.h:932
error_t ecdsaReadSignature(const uint8_t *data, size_t length, EcdsaSignature *signature)
Read an ASN.1 encoded ECDSA signature.
Definition: ecdsa.c:255
Common interface for hash algorithms.
Definition: crypto.h:1062
error_t ed25519VerifySignature(const uint8_t *publicKey, const void *message, size_t messageLen, const void *context, uint8_t contextLen, uint8_t flag, const uint8_t *signature)
EdDSA signature verification.
Definition: ed25519.c:315
DSA signature.
Definition: dsa.h:86
Parsing of ASN.1 encoded keys.
bool_t x509CompareSubjectName(const char_t *subjectName, size_t subjectNameLen, const char_t *fqdn)
Check whether the subject name matches the specified FQDN.
unsigned int uint_t
Definition: compiler_port.h:45
void ecFree(EcPoint *r)
Release an elliptic curve point.
Definition: ec.c:170
error_t x509ParseGeneralName(const uint8_t *data, size_t length, size_t *totalLength, X509GeneralName *generalName)
Parse GeneralName field.
X509EcPublicKey ecPublicKey
Definition: x509_common.h:716
X509SubjectPublicKeyInfo subjectPublicKeyInfo
Definition: x509_common.h:920
Ed448 elliptic curve (constant-time implementation)
void dsaFreePublicKey(DsaPublicKey *key)
Release a DSA public key.
Definition: dsa.c:92
const uint8_t * namedCurve
Definition: x509_common.h:681
void dsaInitPublicKey(DsaPublicKey *key)
Initialize a DSA public key.
Definition: dsa.c:77
X509TbsCertificate tbsCert
Definition: x509_common.h:931
Success.
Definition: error.h:44
Debugging facilities.
void rsaInitPublicKey(RsaPublicKey *key)
Initialize an RSA public key.
Definition: rsa.c:105
ASN.1 (Abstract Syntax Notation One)
bool_t x509CompareSubtree(const char_t *subjectName, const char_t *subtree, size_t subtreeLen)
Compare a subject name against the specified subtree.
error_t x509CheckSubjectName(const X509CertificateInfo *certInfo, const char_t *fqdn)
Check whether the certificate matches the specified FQDN.
int_t compareDateTime(const DateTime *date1, const DateTime *date2)
Compare dates.
Definition: date_time.c:302