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-2019 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.6
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(cryptoMemcmp(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 = cryptoStrlen(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(cryptoTolower(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  return TRUE;
504  else
505  return FALSE;
506 }
507 
508 
509 /**
510  * @brief Compare a subject name against the specified subtree
511  * @param[in] subjectName NULL-terminated string that contains the subject name
512  * @param[in] subtree Pointer to the subtree
513  * @param[in] subtreeLen Length of the subtree
514  * @return Comparison result
515  **/
516 
517 bool_t x509CompareSubtree(const char_t *subjectName,
518  const char_t *subtree, size_t subtreeLen)
519 {
520  int_t i;
521  int_t j;
522 
523  //Point to the last character of the subtree
524  i = subtreeLen - 1;
525  //Point to the last character of the subject name
526  j = cryptoStrlen(subjectName) - 1;
527 
528  //Parse the subtree
529  while(i >= 0 && j >= 0)
530  {
531  //Perform case insensitive character comparison
532  if(cryptoTolower(subtree[i]) != subjectName[j])
533  {
534  break;
535  }
536 
537  //The constraint may specify a host or a domain
538  if(subtree[i] == '.' && i == 0)
539  {
540  //When the constraint begins with a period, it may be expanded with
541  //one or more labels (refer to RFC 5280, section 4.2.1.10)
542  i = -1;
543  j = -1;
544  }
545  else
546  {
547  //Compare previous characters
548  i--;
549  j--;
550  }
551  }
552 
553  //Check whether the subject name matches the specified subtree
554  if(i < 0 && j < 0)
555  return TRUE;
556  else
557  return FALSE;
558 }
559 
560 
561 /**
562  * @brief Certificate signature verification
563  * @param[in] tbsCert TBSCertificate whose signature is to be verified
564  * @param[in] tbsCertLen Length of the TBSCertificate, in bytes
565  * @param[in] signatureAlgoId Signature algorithm identifier
566  * @param[in] publicKeyInfo Issuer's public key
567  * @param[in] signatureValue Signature to be verified
568  * @return Error code
569  **/
570 
571 error_t x509VerifySignature(const uint8_t *tbsCert, size_t tbsCertLen,
572  const X509SignatureAlgoId *signatureAlgoId,
573  const X509SubjectPublicKeyInfo *publicKeyInfo,
574  const X509SignatureValue *signatureValue)
575 {
576  error_t error;
577  X509SignatureAlgo signAlgo;
578  const HashAlgo *hashAlgo;
579  uint8_t digest[X509_MAX_HASH_DIGEST_SIZE];
580 
581  //Retrieve the signature algorithm that was used to sign the certificate
582  error = x509GetSignHashAlgo(signatureAlgoId, &signAlgo, &hashAlgo);
583  //Unsupported signature algorithm?
584  if(error)
585  return error;
586 
587  //Ed25519 and Ed448 are used in PureEdDSA mode, without pre-hashing
588  if(hashAlgo != NULL)
589  {
590  //Digest the TBSCertificate structure using the specified hash algorithm
591  error = hashAlgo->compute(tbsCert, tbsCertLen, digest);
592  //Any error to report?
593  if(error)
594  return error;
595 
596 #if (X509_RSA_SUPPORT == ENABLED && RSA_SUPPORT == ENABLED)
597  //RSA signature algorithm?
598  if(signAlgo == X509_SIGN_ALGO_RSA)
599  {
600  uint_t k;
601  RsaPublicKey publicKey;
602 
603  //Initialize RSA public key
604  rsaInitPublicKey(&publicKey);
605 
606  //Import the RSA public key
607  error = x509ImportRsaPublicKey(publicKeyInfo, &publicKey);
608 
609  //Check status code
610  if(!error)
611  {
612  //Get the length of the modulus, in bits
613  k = mpiGetBitLength(&publicKey.n);
614 
615  //Make sure the modulus is acceptable
616  if(k < X509_MIN_RSA_MODULUS_SIZE || k > X509_MAX_RSA_MODULUS_SIZE)
617  {
618  //Report an error
619  error = ERROR_INVALID_KEY;
620  }
621  }
622 
623  //Check status code
624  if(!error)
625  {
626  //Verify RSA signature (RSASSA-PKCS1-v1_5 signature scheme)
627  error = rsassaPkcs1v15Verify(&publicKey, hashAlgo, digest,
628  signatureValue->data, signatureValue->length);
629  }
630 
631  //Release previously allocated resources
632  rsaFreePublicKey(&publicKey);
633  }
634  else
635 #endif
636 #if (X509_RSA_PSS_SUPPORT == ENABLED && RSA_SUPPORT == ENABLED)
637  //RSA-PSS signature algorithm?
638  if(signAlgo == X509_SIGN_ALGO_RSA_PSS)
639  {
640  uint_t k;
641  RsaPublicKey publicKey;
642 
643  //Initialize RSA public key
644  rsaInitPublicKey(&publicKey);
645 
646  //Import the RSA public key
647  error = x509ImportRsaPublicKey(publicKeyInfo, &publicKey);
648 
649  //Check status code
650  if(!error)
651  {
652  //Get the length of the modulus, in bits
653  k = mpiGetBitLength(&publicKey.n);
654 
655  //Make sure the modulus is acceptable
656  if(k < X509_MIN_RSA_MODULUS_SIZE || k > X509_MAX_RSA_MODULUS_SIZE)
657  {
658  //Report an error
659  error = ERROR_INVALID_KEY;
660  }
661  }
662 
663  //Check status code
664  if(!error)
665  {
666  //Retrieve the length of the salt
667  k = signatureAlgoId->rsaPssParams.saltLen;
668 
669  //Verify RSA signature (RSASSA-PSS signature scheme)
670  error = rsassaPssVerify(&publicKey, hashAlgo, k, digest,
671  signatureValue->data, signatureValue->length);
672  }
673 
674  //Release previously allocated resources
675  rsaFreePublicKey(&publicKey);
676  }
677  else
678 #endif
679 #if (X509_DSA_SUPPORT == ENABLED && DSA_SUPPORT == ENABLED)
680  //DSA signature algorithm?
681  if(signAlgo == X509_SIGN_ALGO_DSA)
682  {
683  uint_t k;
684  DsaPublicKey publicKey;
686 
687  //Initialize DSA public key
688  dsaInitPublicKey(&publicKey);
689  //Initialize DSA signature
691 
692  //Import the DSA public key
693  error = x509ImportDsaPublicKey(publicKeyInfo, &publicKey);
694 
695  //Check status code
696  if(!error)
697  {
698  //Get the length of the prime modulus, in bits
699  k = mpiGetBitLength(&publicKey.p);
700 
701  //Make sure the prime modulus is acceptable
702  if(k < X509_MIN_DSA_MODULUS_SIZE || k > X509_MAX_DSA_MODULUS_SIZE)
703  {
704  //Report an error
705  error = ERROR_INVALID_KEY;
706  }
707  }
708 
709  //Check status code
710  if(!error)
711  {
712  //Read the ASN.1 encoded signature
713  error = dsaReadSignature(signatureValue->data,
714  signatureValue->length, &signature);
715  }
716 
717  //Check status code
718  if(!error)
719  {
720  //Verify DSA signature
721  error = dsaVerifySignature(&publicKey, digest, hashAlgo->digestSize,
722  &signature);
723  }
724 
725  //Release previously allocated resources
726  dsaFreePublicKey(&publicKey);
728  }
729  else
730 #endif
731 #if (X509_ECDSA_SUPPORT == ENABLED && ECDSA_SUPPORT == ENABLED)
732  //ECDSA signature algorithm?
733  if(signAlgo == X509_SIGN_ALGO_ECDSA)
734  {
735  const EcCurveInfo *curveInfo;
736  EcDomainParameters params;
737  EcPoint publicKey;
739 
740  //Initialize EC domain parameters
741  ecInitDomainParameters(&params);
742  //Initialize ECDSA public key
743  ecInit(&publicKey);
744  //Initialize ECDSA signature
746 
747  //Retrieve EC domain parameters
748  curveInfo = x509GetCurveInfo(publicKeyInfo->ecParams.namedCurve,
749  publicKeyInfo->ecParams.namedCurveLen);
750 
751  //Make sure the specified elliptic curve is supported
752  if(curveInfo != NULL)
753  {
754  //Load EC domain parameters
755  error = ecLoadDomainParameters(&params, curveInfo);
756  }
757  else
758  {
759  //Invalid EC domain parameters
760  error = ERROR_BAD_CERTIFICATE;
761  }
762 
763  //Check status code
764  if(!error)
765  {
766  //Retrieve the EC public key
767  error = ecImport(&params, &publicKey, publicKeyInfo->ecPublicKey.q,
768  publicKeyInfo->ecPublicKey.qLen);
769  }
770 
771  //Check status code
772  if(!error)
773  {
774  //Read the ASN.1 encoded signature
775  error = ecdsaReadSignature(signatureValue->data,
776  signatureValue->length, &signature);
777  }
778 
779  //Check status code
780  if(!error)
781  {
782  //Verify ECDSA signature
783  error = ecdsaVerifySignature(&params, &publicKey, digest,
784  hashAlgo->digestSize, &signature);
785  }
786 
787  //Release previously allocated resources
788  ecFreeDomainParameters(&params);
789  ecFree(&publicKey);
791  }
792  else
793 #endif
794  //Invalid signature algorithm?
795  {
796  //Report an error
798  }
799  }
800  else
801  {
802 #if (X509_ED25519_SUPPORT == ENABLED && ED25519_SUPPORT == ENABLED)
803  //Ed25519 signature algorithm?
804  if(signAlgo == X509_SIGN_ALGO_ED25519)
805  {
806  //Check the length of the public key
807  if(publicKeyInfo->ecPublicKey.qLen == ED25519_PUBLIC_KEY_LEN)
808  {
809  //Check the length of the EdDSA signature
810  if(signatureValue->length == ED25519_SIGNATURE_LEN)
811  {
812  //Verify signature (PureEdDSA mode)
813  error = ed25519VerifySignature(publicKeyInfo->ecPublicKey.q,
814  tbsCert, tbsCertLen, NULL, 0, 0, signatureValue->data);
815  }
816  else
817  {
818  //The length of the EdDSA signature is not valid
819  error = ERROR_INVALID_SIGNATURE;
820  }
821  }
822  else
823  {
824  //The length of the Ed25519 public key is not valid
825  error = ERROR_ILLEGAL_PARAMETER;
826  }
827  }
828  else
829 #endif
830 #if (X509_ED448_SUPPORT == ENABLED && ED448_SUPPORT == ENABLED)
831  //Ed448 signature algorithm?
832  if(signAlgo == X509_SIGN_ALGO_ED448)
833  {
834  //Check the length of the public key
835  if(publicKeyInfo->ecPublicKey.qLen == ED448_PUBLIC_KEY_LEN)
836  {
837  //Check the length of the EdDSA signature
838  if(signatureValue->length == ED448_SIGNATURE_LEN)
839  {
840  //Verify signature (PureEdDSA mode)
841  error = ed448VerifySignature(publicKeyInfo->ecPublicKey.q,
842  tbsCert, tbsCertLen, NULL, 0, 0, signatureValue->data);
843  }
844  else
845  {
846  //The length of the EdDSA signature is not valid
847  error = ERROR_INVALID_SIGNATURE;
848  }
849  }
850  else
851  {
852  //The length of the Ed448 public key is not valid
853  error = ERROR_ILLEGAL_PARAMETER;
854  }
855  }
856  else
857 #endif
858  //Invalid signature algorithm?
859  {
860  //Report an error
862  }
863  }
864 
865  //Return status code
866  return error;
867 }
868 
869 #endif
ECDSA signature.
Definition: ecdsa.h:48
#define cryptoTolower(c)
Definition: crypto.h:690
X509Validity validity
Definition: x509_common.h:909
X.509 certificate parsing.
uint8_t length
Definition: dtls_misc.h:149
Ed25519 elliptic curve (constant-time implementation)
X509GeneralNameType type
Definition: x509_common.h:768
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.
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:892
error_t x509ImportRsaPublicKey(const X509SubjectPublicKeyInfo *publicKeyInfo, RsaPublicKey *publicKey)
Import an RSA public key.
Signature algorithm identifier.
Definition: x509_common.h:876
@ ERROR_ILLEGAL_PARAMETER
Definition: error.h:237
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:912
#define ED25519_PUBLIC_KEY_LEN
Definition: ed25519.h:41
OID (Object Identifier)
ECDSA (Elliptic Curve Digital Signature Algorithm)
Validity.
Definition: x509_common.h:622
#define TRUE
Definition: os_port.h:50
#define ED448_PUBLIC_KEY_LEN
Definition: ed448.h:41
size_t rawDataLen
Definition: x509_common.h:571
X509RsaPssParameters rsaPssParams
Definition: x509_common.h:881
size_t digestSize
Definition: crypto.h:1135
X.509 certificate.
Definition: x509_common.h:920
uint8_t signature
Definition: tls.h:1370
X509EcParameters ecParams
Definition: x509_common.h:708
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
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:685
#define ED25519_SIGNATURE_LEN
Definition: ed25519.h:43
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:903
EC domain parameters.
Definition: ec.h:63
const uint8_t res[]
void ecFreeDomainParameters(EcDomainParameters *params)
Release EC domain parameters.
Definition: ec.c:75
@ X509_GENERAL_NAME_TYPE_DIRECTORY
Definition: x509_common.h:442
__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
@ ERROR_INVALID_NAME
Definition: error.h:96
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:625
#define FALSE
Definition: os_port.h:46
X509SignatureAlgo
Signature algorithms.
Definition: x509_common.h:521
Elliptic curve parameters.
Definition: ec_curves.h:292
General name.
Definition: x509_common.h:766
DSA public key.
Definition: dsa.h:60
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define cryptoStrlen(s)
Definition: crypto.h:660
error_t x509ImportDsaPublicKey(const X509SubjectPublicKeyInfo *publicKeyInfo, DsaPublicKey *publicKey)
Import a DSA public key.
@ X509_GENERAL_NAME_TYPE_DNS
Definition: x509_common.h:440
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:1138
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:359
X509Version version
Definition: x509_common.h:905
void ecInit(EcPoint *r)
Initialize elliptic curve point.
Definition: ec.c:156
@ X509_SIGN_ALGO_ECDSA
Definition: x509_common.h:527
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:924
#define X509_MAX_DSA_MODULUS_SIZE
Definition: x509_common.h:331
@ X509_VERSION_3
Definition: x509_common.h:394
General definitions for cryptographic algorithms.
RSA public-key cryptography standard.
@ ERROR_BAD_CERTIFICATE
Definition: error.h:230
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:570
size_t namedCurveLen
Definition: x509_common.h:675
Signature value.
Definition: x509_common.h:890
@ X509_SIGN_ALGO_RSA
Definition: x509_common.h:524
uint_t mpiGetBitLength(const Mpi *a)
Get the actual length in bits.
Definition: mpi.c:195
#define cryptoMemcmp(p1, p2, length)
Definition: crypto.h:654
const char_t * value
Definition: x509_common.h:769
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:572
Mpi p
Prime modulus.
Definition: dsa.h:62
DateTime notBefore
Definition: x509_common.h:624
@ X509_SIGN_ALGO_RSA_PSS
Definition: x509_common.h:525
size_t commonNameLen
Definition: x509_common.h:573
uint8_t m
Definition: ndp.h:302
uint8_t n
Issuer or subject name.
Definition: x509_common.h:568
uint8_t extensions[]
Definition: tls13_misc.h:327
Subject public key information.
Definition: x509_common.h:694
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
@ ERROR_CERTIFICATE_EXPIRED
Definition: error.h:232
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.
X.509 certificate extensions.
Definition: x509_common.h:841
#define X509_MAX_RSA_MODULUS_SIZE
Definition: x509_common.h:317
X509SignatureAlgoId signatureAlgo
Definition: x509_common.h:923
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:1128
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.
@ ERROR_UNSUPPORTED_SIGNATURE_ALGO
Definition: error.h:130
bool_t x509CompareSubjectName(const char_t *subjectName, size_t subjectNameLen, const char_t *fqdn)
Check whether the subject name matches the specified FQDN.
@ X509_SIGN_ALGO_ED25519
Definition: x509_common.h:528
unsigned int uint_t
Definition: compiler_port.h:45
uint8_t data[]
Definition: dtls_misc.h:176
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:709
X509SubjectPublicKeyInfo subjectPublicKeyInfo
Definition: x509_common.h:911
@ ERROR_INVALID_SIGNATURE
Definition: error.h:223
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:674
void dsaInitPublicKey(DsaPublicKey *key)
Initialize a DSA public key.
Definition: dsa.c:77
X509TbsCertificate tbsCert
Definition: x509_common.h:922
@ ERROR_INVALID_KEY
Definition: error.h:104
@ NO_ERROR
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)
@ X509_SIGN_ALGO_DSA
Definition: x509_common.h:526
@ X509_KEY_USAGE_KEY_CERT_SIGN
Definition: x509_common.h:409
@ X509_SIGN_ALGO_ED448
Definition: x509_common.h:529
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