ssh_sign_verify.c
Go to the documentation of this file.
1 /**
2  * @file ssh_sign_verify.c
3  * @brief RSA/DSA/ECDSA/EdDSA signature verification
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2019-2025 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneSSH Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.5.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL SSH_TRACE_LEVEL
33 
34 //Dependencies
35 #include "ssh/ssh.h"
36 #include "ssh/ssh_algorithms.h"
37 #include "ssh/ssh_key_import.h"
38 #include "ssh/ssh_cert_import.h"
39 #include "ssh/ssh_sign_verify.h"
40 #include "ssh/ssh_sign_misc.h"
41 #include "ssh/ssh_misc.h"
42 #include "debug.h"
43 
44 //Check SSH stack configuration
45 #if (SSH_SUPPORT == ENABLED)
46 
47 
48 /**
49  * @brief Signature verification
50  * @param[in] connection Pointer to the SSH connection
51  * @param[in] publicKeyAlgo Public key algorithm
52  * @param[in] publicKeyBlob Signer's public key
53  * @param[in] sessionId Session identifier (optional parameter)
54  * @param[in] message Message whose signature is to be verified
55  * @param[in] signature Signature to be verified
56  * @return Error code
57  **/
58 
60  const SshString *publicKeyAlgo, const SshBinaryString *publicKeyBlob,
62  const SshBinaryString *signature)
63 {
64  error_t error;
65  size_t n;
66  const uint8_t *p;
67  SshString keyFormatId;
68  SshString signFormatId;
69  SshBinaryString signatureBlob;
70  const char_t *expectedKeyFormatId;
71  const char_t *expectedSignFormatId;
72 
73  //Point to the first field of the signature
74  p = signature->value;
75  n = signature->length;
76 
77  //Decode signature format identifier
78  error = sshParseString(p, n, &signFormatId);
79  //Any error to report?
80  if(error)
81  return error;
82 
83  //Point to the next field
84  p += sizeof(uint32_t) + signFormatId.length;
85  n -= sizeof(uint32_t) + signFormatId.length;
86 
87  //Decode signature blob
88  error = sshParseBinaryString(p, n, &signatureBlob);
89  //Any error to report?
90  if(error)
91  return error;
92 
93  //Point to the next field
94  p += sizeof(uint32_t) + signatureBlob.length;
95  n -= sizeof(uint32_t) + signatureBlob.length;
96 
97  //Malformed signature?
98  if(n != 0)
99  return ERROR_INVALID_MESSAGE;
100 
101  //Extract key format identifier from public key blob
102  error = sshParseString(publicKeyBlob->value, publicKeyBlob->length,
103  &keyFormatId);
104  //Any error to report?
105  if(error)
106  return error;
107 
108  //Each public key algorithm is associated with a particular key format
109  expectedKeyFormatId = sshGetKeyFormatId(publicKeyAlgo);
110 
111  //Inconsistent key format identifier?
112  if(!sshCompareString(&keyFormatId, expectedKeyFormatId))
114 
115  //Public key/certificate formats that do not explicitly specify a signature
116  //format identifier must use the public key/certificate format identifier
117  //as the signature identifier (refer to RFC 4253, section 6.6)
118  expectedSignFormatId = sshGetSignFormatId(publicKeyAlgo);
119 
120  //Inconsistent signature format identifier?
121  if(!sshCompareString(&signFormatId, expectedSignFormatId))
123 
124 #if (SSH_SIGN_CALLBACK_SUPPORT == ENABLED)
125  //Valid signature verification callback function?
126  if(connection->context->signVerifyCallback != NULL)
127  {
128  //Invoke user-defined callback
129  error = connection->context->signVerifyCallback(connection,
130  publicKeyAlgo, publicKeyBlob, sessionId, message, &signatureBlob);
131  }
132  else
133 #endif
134  {
135  //No callback function registered
137  }
138 
139  //Check status code
141  {
142 #if (SSH_RSA_SIGN_SUPPORT == ENABLED)
143  //RSA signature algorithm?
144  if(sshCompareString(&signFormatId, "ssh-rsa") ||
145  sshCompareString(&signFormatId, "rsa-sha2-256") ||
146  sshCompareString(&signFormatId, "rsa-sha2-512"))
147  {
148  //RSA signature verification
149  error = sshVerifyRsaSignature(publicKeyAlgo, publicKeyBlob,
150  sessionId, message, &signatureBlob);
151  }
152  else
153 #endif
154 #if (SSH_DSA_SIGN_SUPPORT == ENABLED)
155  //DSA signature algorithm?
156  if(sshCompareString(&signFormatId, "ssh-dss"))
157  {
158  //DSA signature verification
159  error = sshVerifyDsaSignature(publicKeyAlgo, publicKeyBlob,
160  sessionId, message, &signatureBlob);
161  }
162  else
163 #endif
164 #if (SSH_ECDSA_SIGN_SUPPORT == ENABLED)
165  //ECDSA signature algorithm?
166  if(sshCompareString(&signFormatId, "ecdsa-sha2-nistp256") ||
167  sshCompareString(&signFormatId, "ecdsa-sha2-nistp384") ||
168  sshCompareString(&signFormatId, "ecdsa-sha2-nistp521"))
169  {
170  //ECDSA signature verification
171  error = sshVerifyEcdsaSignature(publicKeyAlgo, publicKeyBlob,
172  sessionId, message, &signatureBlob);
173  }
174  else
175 #endif
176 #if (SSH_ED25519_SIGN_SUPPORT == ENABLED)
177  //Ed25519 signature algorithm?
178  if(sshCompareString(&signFormatId, "ssh-ed25519"))
179  {
180  //Ed25519 signature verification
181  error = sshVerifyEd25519Signature(publicKeyAlgo, publicKeyBlob,
182  sessionId, message, &signatureBlob);
183  }
184  else
185 #endif
186 #if (SSH_ED448_SIGN_SUPPORT == ENABLED)
187  //Ed448 signature algorithm?
188  if(sshCompareString(&signFormatId, "ssh-ed448"))
189  {
190  //Ed448 signature verification
191  error = sshVerifyEd448Signature(publicKeyAlgo, publicKeyBlob,
192  sessionId, message, &signatureBlob);
193  }
194  else
195 #endif
196  //Unknown public key type?
197  {
198  //Report an error
200  }
201  }
202 
203  //Return status code
204  return error;
205 }
206 
207 
208 /**
209  * @brief RSA signature verification
210  * @param[in] publicKeyAlgo Public key algorithm
211  * @param[in] publicKeyBlob Signer's public key
212  * @param[in] sessionId Session identifier (optional parameter)
213  * @param[in] message Message whose signature is to be verified
214  * @param[in] signatureBlob Signature to be verified
215  * @return Error code
216  **/
217 
219  const SshBinaryString *publicKeyBlob, const SshBinaryString *sessionId,
220  const SshBinaryString *message, const SshBinaryString *signatureBlob)
221 {
222 #if (SSH_RSA_SIGN_SUPPORT == ENABLED)
223  error_t error;
224  const HashAlgo *hashAlgo;
225  HashContext hashContext;
226  uint8_t digest[SSH_MAX_HASH_DIGEST_SIZE];
227 
228 #if (SSH_SHA1_SUPPORT == ENABLED)
229  //RSA with SHA-1 public key algorithm?
230  if(sshCompareString(publicKeyAlgo, "ssh-rsa") ||
231  sshCompareString(publicKeyAlgo, "ssh-rsa-cert-v01@openssh.com"))
232  {
233  //Select the relevant hash algorithm
234  hashAlgo = SHA1_HASH_ALGO;
235  }
236  else
237 #endif
238 #if (SSH_SHA256_SUPPORT == ENABLED)
239  //RSA with SHA-256 public key algorithm?
240  if(sshCompareString(publicKeyAlgo, "rsa-sha2-256") ||
241  sshCompareString(publicKeyAlgo, "rsa-sha2-256-cert-v01@openssh.com"))
242  {
243  //Select the relevant hash algorithm
244  hashAlgo = SHA256_HASH_ALGO;
245  }
246  else
247 #endif
248 #if (SSH_SHA512_SUPPORT == ENABLED)
249  //RSA with SHA-512 public key algorithm?
250  if(sshCompareString(publicKeyAlgo, "rsa-sha2-512") ||
251  sshCompareString(publicKeyAlgo, "rsa-sha2-512-cert-v01@openssh.com"))
252  {
253  //Select the relevant hash algorithm
254  hashAlgo = SHA512_HASH_ALGO;
255  }
256  else
257 #endif
258  //Unknown public key algorithm?
259  {
260  //Just for sanity
261  hashAlgo = NULL;
262  }
263 
264  //Make sure the hash algorithm is supported
265  if(hashAlgo != NULL)
266  {
267  RsaPublicKey rsaPublicKey;
268 
269  //Initialize RSA public key
270  rsaInitPublicKey(&rsaPublicKey);
271 
272  //Initialize hash context
273  hashAlgo->init(&hashContext);
274 
275  //Valid session identifier?
276  if(sessionId != NULL)
277  {
278  uint8_t temp[4];
279 
280  //Encode the length of the session identifier as a 32-bit big-endian
281  //integer
282  STORE32BE(sessionId->length, temp);
283 
284  //Digest the length field
285  hashAlgo->update(&hashContext, temp, sizeof(temp));
286  //Digest the session identifier
287  hashAlgo->update(&hashContext, sessionId->value, sessionId->length);
288  }
289 
290  //Digest the message
291  hashAlgo->update(&hashContext, message->value, message->length);
292  hashAlgo->final(&hashContext, digest);
293 
294 #if (SSH_CERT_SUPPORT == ENABLED)
295  //RSA certificate?
296  if(sshIsCertPublicKeyAlgo(publicKeyAlgo))
297  {
298  SshCertificate cert;
299 
300  //Parse RSA certificate structure
301  error = sshParseCertificate(publicKeyBlob->value,
302  publicKeyBlob->length, &cert);
303 
304  //Check status
305  if(!error)
306  {
307  //Import RSA public key
308  error = sshImportRsaCertPublicKey(&rsaPublicKey, &cert);
309  }
310  }
311  else
312 #endif
313  //RSA public key?
314  {
315  SshRsaHostKey hostKey;
316 
317  //Parse RSA host key structure
318  error = sshParseRsaHostKey(publicKeyBlob->value, publicKeyBlob->length,
319  &hostKey);
320 
321  //Check status code
322  if(!error)
323  {
324  //Import RSA public key
325  error = sshImportRsaHostKey(&rsaPublicKey, &hostKey);
326  }
327  }
328 
329  //Check status code
330  if(!error)
331  {
332  //Verify RSA signature
333  error = rsassaPkcs1v15Verify(&rsaPublicKey, hashAlgo, digest,
334  signatureBlob->value, signatureBlob->length);
335  }
336 
337  //Free previously allocated resources
338  rsaFreePublicKey(&rsaPublicKey);
339  }
340  else
341  {
342  //Report an error
344  }
345 
346  //Return status code
347  return error;
348 #else
349  //Not implemented
350  return ERROR_NOT_IMPLEMENTED;
351 #endif
352 }
353 
354 
355 /**
356  * @brief DSA signature verification
357  * @param[in] publicKeyAlgo Public key algorithm
358  * @param[in] publicKeyBlob Signer's public key
359  * @param[in] sessionId Session identifier (optional parameter)
360  * @param[in] message Message whose signature is to be verified
361  * @param[in] signatureBlob Signature to be verified
362  * @return Error code
363  **/
364 
366  const SshBinaryString *publicKeyBlob, const SshBinaryString *sessionId,
367  const SshBinaryString *message, const SshBinaryString *signatureBlob)
368 {
369 #if (SSH_DSA_SIGN_SUPPORT == ENABLED)
370  error_t error;
371  DsaPublicKey dsaPublicKey;
372  DsaSignature dsaSignature;
373  Sha1Context sha1Context;
374  uint8_t digest[SHA1_DIGEST_SIZE];
375 
376  //The DSA signature blob contains R followed by S (which are 160-bit
377  //integers)
378  if(signatureBlob->length == (2 * SHA1_DIGEST_SIZE))
379  {
380  //Initialize DSA public key
381  dsaInitPublicKey(&dsaPublicKey);
382  //Initialize DSA signature
383  dsaInitSignature(&dsaSignature);
384 
385  //Initialize hash context
386  sha1Init(&sha1Context);
387 
388  //Valid session identifier?
389  if(sessionId != NULL)
390  {
391  uint8_t temp[4];
392 
393  //Encode the length of the session identifier as a 32-bit big-endian
394  //integer
395  STORE32BE(sessionId->length, temp);
396 
397  //Digest the length field
398  sha1Update(&sha1Context, temp, sizeof(temp));
399  //Digest the session identifier
400  sha1Update(&sha1Context, sessionId->value, sessionId->length);
401  }
402 
403  //Digest the message
404  sha1Update(&sha1Context, message->value, message->length);
405  sha1Final(&sha1Context, digest);
406 
407 #if (SSH_CERT_SUPPORT == ENABLED)
408  //DSA certificate?
409  if(sshIsCertPublicKeyAlgo(publicKeyAlgo))
410  {
411  SshCertificate cert;
412 
413  //Parse DSA certificate structure
414  error = sshParseCertificate(publicKeyBlob->value,
415  publicKeyBlob->length, &cert);
416 
417  //Check status
418  if(!error)
419  {
420  //Import DSA public key
421  error = sshImportDsaCertPublicKey(&dsaPublicKey, &cert);
422  }
423  }
424  else
425 #endif
426  //DSA public key?
427  {
428  SshDsaHostKey hostKey;
429 
430  //Parse DSA host key structure
431  error = sshParseDsaHostKey(publicKeyBlob->value, publicKeyBlob->length,
432  &hostKey);
433 
434  //Check status code
435  if(!error)
436  {
437  //Import DSA public key
438  error = sshImportDsaHostKey(&dsaPublicKey, &hostKey);
439  }
440  }
441 
442  //Check status code
443  if(!error)
444  {
445  //Import integer R
446  error = mpiImport(&dsaSignature.r, signatureBlob->value,
448  }
449 
450  //Check status code
451  if(!error)
452  {
453  //Import integer S
454  error = mpiImport(&dsaSignature.s, signatureBlob->value +
456  }
457 
458  //Check status code
459  if(!error)
460  {
461  //Verify DSA signature
462  error = dsaVerifySignature(&dsaPublicKey, digest, SHA1_DIGEST_SIZE,
463  &dsaSignature);
464  }
465 
466  //Free previously allocated resources
467  dsaFreePublicKey(&dsaPublicKey);
468  dsaFreeSignature(&dsaSignature);
469  }
470  else
471  {
472  //The length of the signature is not acceptable
473  error = ERROR_INVALID_MESSAGE;
474  }
475 
476  //Return status code
477  return error;
478 #else
479  //Not implemented
480  return ERROR_NOT_IMPLEMENTED;
481 #endif
482 }
483 
484 
485 /**
486  * @brief ECDSA signature verification
487  * @param[in] publicKeyAlgo Public key algorithm
488  * @param[in] publicKeyBlob Signer's public key
489  * @param[in] sessionId Session identifier (optional parameter)
490  * @param[in] message Message whose signature is to be verified
491  * @param[in] signatureBlob Signature to be verified
492  * @return Error code
493  **/
494 
496  const SshBinaryString *publicKeyBlob, const SshBinaryString *sessionId,
497  const SshBinaryString *message, const SshBinaryString *signatureBlob)
498 {
499 #if (SSH_ECDSA_SIGN_SUPPORT == ENABLED)
500  error_t error;
501  SshEcdsaSignature signature;
502  const HashAlgo *hashAlgo;
503  HashContext hashContext;
504  uint8_t digest[SSH_MAX_HASH_DIGEST_SIZE];
505 
506 #if (SSH_NISTP256_SUPPORT == ENABLED && SSH_SHA256_SUPPORT == ENABLED)
507  //ECDSA with NIST P-256 public key algorithm?
508  if(sshCompareString(publicKeyAlgo, "ecdsa-sha2-nistp256") ||
509  sshCompareString(publicKeyAlgo, "ecdsa-sha2-nistp256-cert-v01@openssh.com"))
510  {
511  //Select the relevant hash algorithm
512  hashAlgo = SHA256_HASH_ALGO;
513  }
514  else
515 #endif
516 #if (SSH_NISTP384_SUPPORT == ENABLED && SSH_SHA384_SUPPORT == ENABLED)
517  //ECDSA with NIST P-384 public key algorithm?
518  if(sshCompareString(publicKeyAlgo, "ecdsa-sha2-nistp384") ||
519  sshCompareString(publicKeyAlgo, "ecdsa-sha2-nistp384-cert-v01@openssh.com"))
520  {
521  //Select the relevant hash algorithm
522  hashAlgo = SHA384_HASH_ALGO;
523  }
524  else
525 #endif
526 #if (SSH_NISTP521_SUPPORT == ENABLED && SSH_SHA512_SUPPORT == ENABLED)
527  //ECDSA with NIST P-521 public key algorithm?
528  if(sshCompareString(publicKeyAlgo, "ecdsa-sha2-nistp521") ||
529  sshCompareString(publicKeyAlgo, "ecdsa-sha2-nistp521-cert-v01@openssh.com"))
530  {
531  //Select the relevant hash algorithm
532  hashAlgo = SHA512_HASH_ALGO;
533  }
534  else
535 #endif
536  //Unknown public key algorithm?
537  {
538  //Just for sanity
539  hashAlgo = NULL;
540  }
541 
542  //Make sure the hash algorithm is supported
543  if(hashAlgo != NULL)
544  {
545  EcPublicKey ecPublicKey;
546  EcdsaSignature ecdsaSignature;
547 
548  //Initialize ECDSA public key
549  ecInitPublicKey(&ecPublicKey);
550  //Initialize ECDSA signature
551  ecdsaInitSignature(&ecdsaSignature);
552 
553  //Initialize hash context
554  hashAlgo->init(&hashContext);
555 
556  //Valid session identifier?
557  if(sessionId != NULL)
558  {
559  uint8_t temp[4];
560 
561  //Encode the length of the session identifier as a 32-bit big-endian
562  //integer
563  STORE32BE(sessionId->length, temp);
564 
565  //Digest the length field
566  hashAlgo->update(&hashContext, temp, sizeof(temp));
567  //Digest the session identifier
568  hashAlgo->update(&hashContext, sessionId->value, sessionId->length);
569  }
570 
571  //Digest the message
572  hashAlgo->update(&hashContext, message->value, message->length);
573  hashAlgo->final(&hashContext, digest);
574 
575 #if (SSH_CERT_SUPPORT == ENABLED)
576  //ECDSA certificate?
577  if(sshIsCertPublicKeyAlgo(publicKeyAlgo))
578  {
579  SshCertificate cert;
580 
581  //Parse ECDSA certificate structure
582  error = sshParseCertificate(publicKeyBlob->value,
583  publicKeyBlob->length, &cert);
584 
585  //Check status
586  if(!error)
587  {
588  //Import ECDSA public key
589  error = sshImportEcdsaCertPublicKey(&ecPublicKey, &cert);
590  }
591  }
592  else
593 #endif
594  //ECDSA public key?
595  {
596  SshEcdsaHostKey hostKey;
597 
598  //Parse ECDSA host key structure
599  error = sshParseEcdsaHostKey(publicKeyBlob->value,
600  publicKeyBlob->length, &hostKey);
601 
602  //Check status code
603  if(!error)
604  {
605  //Import ECDSA public key
606  error = sshImportEcdsaHostKey(&ecPublicKey, &hostKey);
607  }
608  }
609 
610  //Check status code
611  if(!error)
612  {
613  //Parse ECDSA signature structure
614  error = sshParseEcdsaSignature(signatureBlob->value,
615  signatureBlob->length, &signature);
616  }
617 
618  //Check status code
619  if(!error)
620  {
621  //Import integer R
622  error = ecdsaImportSignature(&ecdsaSignature, ecPublicKey.curve,
623  signature.r.value, signature.r.length, ECDSA_SIGNATURE_FORMAT_RAW_R);
624  }
625 
626  //Check status code
627  if(!error)
628  {
629  //Import integer S
630  error = ecdsaImportSignature(&ecdsaSignature, ecPublicKey.curve,
631  signature.s.value, signature.s.length, ECDSA_SIGNATURE_FORMAT_RAW_S);
632  }
633 
634  //Check status code
635  if(!error)
636  {
637  //Verify ECDSA signature
638  error = ecdsaVerifySignature(&ecPublicKey, digest,
639  hashAlgo->digestSize, &ecdsaSignature);
640  }
641 
642  //Free previously allocated resources
643  ecFreePublicKey(&ecPublicKey);
644  ecdsaFreeSignature(&ecdsaSignature);
645  }
646  else
647  {
648  //Report an error
650  }
651 
652  //Return status code
653  return error;
654 #else
655  //Not implemented
656  return ERROR_NOT_IMPLEMENTED;
657 #endif
658 }
659 
660 
661 /**
662  * @brief Ed25519 signature verification
663  * @param[in] publicKeyAlgo Public key algorithm
664  * @param[in] publicKeyBlob Signer's public key
665  * @param[in] sessionId Session identifier (optional parameter)
666  * @param[in] message Message whose signature is to be verified
667  * @param[in] signatureBlob Signature to be verified
668  * @return Error code
669  **/
670 
672  const SshBinaryString *publicKeyBlob, const SshBinaryString *sessionId,
673  const SshBinaryString *message, const SshBinaryString *signatureBlob)
674 {
675 #if (SSH_ED25519_SIGN_SUPPORT == ENABLED)
676  error_t error;
677  const uint8_t *ed25519PublicKey;
678  uint_t numMessageChunks;
679  DataChunk messageChunks[3];
680  uint8_t temp[4];
681 
682  //The Ed25519 signature shall consist of 32 octets
683  if(signatureBlob->length != ED25519_SIGNATURE_LEN)
685 
686 #if (SSH_CERT_SUPPORT == ENABLED)
687  //Ed25519 certificate?
688  if(sshIsCertPublicKeyAlgo(publicKeyAlgo))
689  {
690  SshCertificate cert;
691 
692  //Parse Ed25519 certificate structure
693  error = sshParseCertificate(publicKeyBlob->value, publicKeyBlob->length,
694  &cert);
695 
696  //Check status
697  if(!error)
698  {
699  //The Ed25519 public key consists of 32 octets
700  ed25519PublicKey = cert.publicKey.ed25519PublicKey.q.value;
701  }
702  }
703  else
704 #endif
705  //Ed25519 public key?
706  {
707  SshEddsaHostKey hostKey;
708 
709  //Parse Ed25519 host key structure
710  error = sshParseEd25519HostKey(publicKeyBlob->value,
711  publicKeyBlob->length, &hostKey);
712 
713  //Check status
714  if(!error)
715  {
716  //The Ed25519 public key consists of 32 octets
717  ed25519PublicKey = hostKey.q.value;
718  }
719  }
720 
721  //Check status
722  if(!error)
723  {
724  //Valid session identifier?
725  if(sessionId != NULL)
726  {
727  //Encode the length of the session identifier as a 32-bit big-endian
728  //integer
729  STORE32BE(sessionId->length, temp);
730 
731  //Data to be signed is run through the EdDSA algorithm without
732  //pre-hashing
733  messageChunks[0].buffer = temp;
734  messageChunks[0].length = sizeof(temp);
735  messageChunks[1].buffer = sessionId->value;
736  messageChunks[1].length = sessionId->length;
737  messageChunks[2].buffer = message->value;
738  messageChunks[2].length = message->length;
739 
740  //Number of data chunks representing the message to be signed
741  numMessageChunks = 3;
742  }
743  else
744  {
745  //Data to be signed is run through the EdDSA algorithm without
746  //pre-hashing
747  messageChunks[0].buffer = message->value;
748  messageChunks[0].length = message->length;
749 
750  //The message fits in a single chunk
751  numMessageChunks = 1;
752  }
753 
754  //Verify Ed25519 signature (PureEdDSA mode)
755  error = ed25519VerifySignatureEx(ed25519PublicKey, messageChunks,
756  numMessageChunks, NULL, 0, 0, signatureBlob->value);
757  }
758 
759  //Return status code
760  return error;
761 #else
762  //Not implemented
763  return ERROR_NOT_IMPLEMENTED;
764 #endif
765 }
766 
767 
768 /**
769  * @brief Ed448 signature verification
770  * @param[in] publicKeyAlgo Public key algorithm
771  * @param[in] publicKeyBlob Signer's public key
772  * @param[in] sessionId Session identifier (optional parameter)
773  * @param[in] message Message whose signature is to be verified
774  * @param[in] signatureBlob Signature to be verified
775  * @return Error code
776  **/
777 
779  const SshBinaryString *publicKeyBlob, const SshBinaryString *sessionId,
780  const SshBinaryString *message, const SshBinaryString *signatureBlob)
781 {
782 #if (SSH_ED448_SIGN_SUPPORT == ENABLED)
783  error_t error;
784  SshEddsaHostKey hostKey;
785  uint_t numMessageChunks;
786  DataChunk messageChunks[3];
787  uint8_t temp[4];
788 
789  //The Ed448 signature shall consist of 57 octets
790  if(signatureBlob->length != ED448_SIGNATURE_LEN)
792 
793  //Parse Ed448 host key structure
794  error = sshParseEd448HostKey(publicKeyBlob->value, publicKeyBlob->length,
795  &hostKey);
796 
797  //Check status
798  if(!error)
799  {
800  //Valid session identifier?
801  if(sessionId != NULL)
802  {
803  //Encode the length of the session identifier as a 32-bit big-endian
804  //integer
805  STORE32BE(sessionId->length, temp);
806 
807  //Data to be signed is run through the EdDSA algorithm without
808  //pre-hashing
809  messageChunks[0].buffer = temp;
810  messageChunks[0].length = sizeof(temp);
811  messageChunks[1].buffer = sessionId->value;
812  messageChunks[1].length = sessionId->length;
813  messageChunks[2].buffer = message->value;
814  messageChunks[2].length = message->length;
815 
816  //Number of data chunks representing the message to be signed
817  numMessageChunks = 3;
818  }
819  else
820  {
821  //Data to be signed is run through the EdDSA algorithm without
822  //pre-hashing
823  messageChunks[0].buffer = message->value;
824  messageChunks[0].length = message->length;
825 
826  //The message fits in a single chunk
827  numMessageChunks = 1;
828  }
829 
830  //Verify Ed448 signature (PureEdDSA mode)
831  error = ed448VerifySignatureEx(hostKey.q.value, messageChunks,
832  numMessageChunks, NULL, 0, 0, signatureBlob->value);
833  }
834 
835  //Return status code
836  return error;
837 #else
838  //Not implemented
839  return ERROR_NOT_IMPLEMENTED;
840 #endif
841 }
842 
843 #endif
Mpi s
Definition: dsa.h:87
ECDSA signature.
Definition: ecdsa.h:63
HashAlgoInit init
Definition: crypto.h:1092
Generic hash algorithm context.
#define SHA256_HASH_ALGO
Definition: sha256.h:49
uint8_t sessionId[]
Definition: tls.h:1811
void rsaFreePublicKey(RsaPublicKey *key)
Release an RSA public key.
Definition: rsa.c:113
#define SHA1_HASH_ALGO
Definition: sha1.h:49
#define SHA512_HASH_ALGO
Definition: sha512.h:49
void sha1Update(Sha1Context *context, const void *data, size_t length)
Update the SHA-1 context with a portion of the message being hashed.
error_t sshParseDsaHostKey(const uint8_t *data, size_t length, SshDsaHostKey *hostKey)
Parse a DSA host key structure.
Binary string.
Definition: ssh_types.h:67
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
DSA host key.
Definition: ssh_key_parse.h:64
uint8_t p
Definition: ndp.h:300
uint8_t message[]
Definition: chap.h:154
error_t sshParseEd448HostKey(const uint8_t *data, size_t length, SshEddsaHostKey *hostKey)
Parse an Ed448 host key structure.
size_t digestSize
Definition: crypto.h:1088
const void * buffer
Definition: crypto.h:1018
HashAlgoUpdate update
Definition: crypto.h:1093
error_t sshParseString(const uint8_t *p, size_t length, SshString *string)
Parse a string.
Definition: ssh_misc.c:1148
#define ED448_SIGNATURE_LEN
Definition: ed448.h:44
Mpi r
Definition: dsa.h:86
size_t length
Definition: ssh_types.h:58
#define ED25519_SIGNATURE_LEN
Definition: ed25519.h:44
error_t sshVerifyEd448Signature(const SshString *publicKeyAlgo, const SshBinaryString *publicKeyBlob, const SshBinaryString *sessionId, const SshBinaryString *message, const SshBinaryString *signatureBlob)
Ed448 signature verification.
@ ERROR_INVALID_MESSAGE
Definition: error.h:105
error_t sshImportEcdsaCertPublicKey(EcPublicKey *publicKey, const SshCertificate *cert)
Import an ECDSA public key from a certificate.
error_t sshParseRsaHostKey(const uint8_t *data, size_t length, SshRsaHostKey *hostKey)
Parse an RSA host key structure.
SSH key file import functions.
error_t sshVerifyEcdsaSignature(const SshString *publicKeyAlgo, const SshBinaryString *publicKeyBlob, const SshBinaryString *sessionId, const SshBinaryString *message, const SshBinaryString *signatureBlob)
ECDSA signature verification.
bool_t sshCompareString(const SshString *string, const char_t *value)
Compare a binary string against the supplied value.
Definition: ssh_misc.c:1626
bool_t sshIsCertPublicKeyAlgo(const SshString *publicKeyAlgo)
Test if the specified public key algorithm is using certificates.
ECDSA signature.
Definition: ssh_sign_misc.h:48
size_t length
Definition: ssh_types.h:69
void ecdsaFreeSignature(EcdsaSignature *signature)
Release an ECDSA signature.
Definition: ecdsa.c:86
const char_t * sshGetKeyFormatId(const SshString *publicKeyAlgo)
Get the key format identifier used by a given public key algorithm.
DSA public key.
Definition: dsa.h:61
void sha1Init(Sha1Context *context)
Initialize SHA-1 message digest context.
error_t
Error codes.
Definition: error.h:43
void dsaInitSignature(DsaSignature *signature)
Initialize a DSA signature.
Definition: dsa.c:168
error_t ecdsaImportSignature(EcdsaSignature *signature, const EcCurve *curve, const uint8_t *data, size_t length, EcdsaSignatureFormat format)
Import an ECDSA signature.
Definition: ecdsa.c:104
void ecInitPublicKey(EcPublicKey *key)
Initialize an EC public key.
Definition: ec.c:52
error_t sshVerifySignature(SshConnection *connection, const SshString *publicKeyAlgo, const SshBinaryString *publicKeyBlob, const SshBinaryString *sessionId, const SshBinaryString *message, const SshBinaryString *signature)
Signature verification.
RSA public key.
Definition: rsa.h:57
void ecdsaInitSignature(EcdsaSignature *signature)
Initialize an ECDSA signature.
Definition: ecdsa.c:73
error_t mpiImport(Mpi *r, const uint8_t *input, size_t length, MpiFormat format)
Octet string to integer conversion.
Definition: mpi.c:712
SshBinaryString s
Definition: ssh_sign_misc.h:50
error_t sshParseEcdsaHostKey(const uint8_t *data, size_t length, SshEcdsaHostKey *hostKey)
Parse an ECDSA host key structure.
error_t sshImportDsaHostKey(DsaPublicKey *publicKey, const SshDsaHostKey *hostKey)
Import a DSA host key.
error_t sshParseEd25519HostKey(const uint8_t *data, size_t length, SshEddsaHostKey *hostKey)
Parse an Ed25519 host key structure.
EdDSA host key.
Definition: ssh_key_parse.h:90
SshBinaryString r
Definition: ssh_sign_misc.h:49
String.
Definition: ssh_types.h:56
#define SSH_MAX_HASH_DIGEST_SIZE
Definition: ssh.h:789
const uint8_t * value
Definition: ssh_types.h:68
HashAlgoFinal final
Definition: crypto.h:1094
Data chunk descriptor.
Definition: crypto.h:1017
EC public key.
Definition: ec.h:421
#define SHA384_HASH_ALGO
Definition: sha384.h:45
error_t ed448VerifySignatureEx(const uint8_t *publicKey, const DataChunk *message, uint_t messageLen, const void *context, uint8_t contextLen, uint8_t flag, const uint8_t *signature)
EdDSA signature verification.
Definition: ed448.c:437
char char_t
Definition: compiler_port.h:55
error_t dsaVerifySignature(const DsaPublicKey *key, const uint8_t *digest, size_t digestLen, const DsaSignature *signature)
DSA signature verification.
Definition: dsa.c:601
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:1068
#define SHA1_DIGEST_SIZE
Definition: sha1.h:45
error_t sshImportRsaHostKey(RsaPublicKey *publicKey, const SshRsaHostKey *hostKey)
Import an RSA host key.
SshCertPublicKey publicKey
uint8_t n
error_t sshParseEcdsaSignature(const uint8_t *data, size_t length, SshEcdsaSignature *signature)
Parse an ECDSA signature.
Definition: ssh_sign_misc.c:98
#define SshConnection
Definition: ssh.h:874
error_t sshParseCertificate(const uint8_t *data, size_t length, SshCertificate *cert)
Parse SSH certificate.
Helper functions for signature generation and verification.
@ ECDSA_SIGNATURE_FORMAT_RAW_R
Definition: ecdsa.h:53
ECDSA host key.
Definition: ssh_key_parse.h:78
__weak_func error_t ecdsaVerifySignature(const EcPublicKey *publicKey, const uint8_t *digest, size_t digestLen, const EcdsaSignature *signature)
ECDSA signature verification.
Definition: ecdsa.c:655
void dsaFreeSignature(DsaSignature *signature)
Release a DSA signature.
Definition: dsa.c:181
SSH certificate import functions.
SSH helper functions.
@ MPI_FORMAT_BIG_ENDIAN
Definition: mpi.h:93
RSA host key.
Definition: ssh_key_parse.h:52
SHA-1 algorithm context.
Definition: sha1.h:62
size_t length
Definition: crypto.h:1019
error_t sshImportEcdsaHostKey(EcPublicKey *publicKey, const SshEcdsaHostKey *hostKey)
Import a ECDSA host key.
Common interface for hash algorithms.
Definition: crypto.h:1082
error_t sshImportDsaCertPublicKey(DsaPublicKey *publicKey, const SshCertificate *cert)
Import a DSA public key from a certificate.
error_t sshParseBinaryString(const uint8_t *p, size_t length, SshBinaryString *string)
Parse a binary string.
Definition: ssh_misc.c:1185
DSA signature.
Definition: dsa.h:85
error_t sshVerifyRsaSignature(const SshString *publicKeyAlgo, const SshBinaryString *publicKeyBlob, const SshBinaryString *sessionId, const SshBinaryString *message, const SshBinaryString *signatureBlob)
RSA signature verification.
error_t sshVerifyEd25519Signature(const SshString *publicKeyAlgo, const SshBinaryString *publicKeyBlob, const SshBinaryString *sessionId, const SshBinaryString *message, const SshBinaryString *signatureBlob)
Ed25519 signature verification.
@ ERROR_UNSUPPORTED_SIGNATURE_ALGO
Definition: error.h:132
unsigned int uint_t
Definition: compiler_port.h:57
@ ECDSA_SIGNATURE_FORMAT_RAW_S
Definition: ecdsa.h:54
error_t sshVerifyDsaSignature(const SshString *publicKeyAlgo, const SshBinaryString *publicKeyBlob, const SshBinaryString *sessionId, const SshBinaryString *message, const SshBinaryString *signatureBlob)
DSA signature verification.
void sha1Final(Sha1Context *context, uint8_t *digest)
Finish the SHA-1 message digest.
Secure Shell (SSH)
SSH algorithm negotiation.
SshBinaryString q
Definition: ssh_key_parse.h:92
@ ERROR_INVALID_SIGNATURE
Definition: error.h:228
const EcCurve * curve
Elliptic curve parameters.
Definition: ec.h:422
void dsaFreePublicKey(DsaPublicKey *key)
Release a DSA public key.
Definition: dsa.c:119
RSA/DSA/ECDSA/EdDSA signature verification.
#define STORE32BE(a, p)
Definition: cpu_endian.h:286
void dsaInitPublicKey(DsaPublicKey *key)
Initialize a DSA public key.
Definition: dsa.c:105
SSH certificate (OpenSSH format)
Debugging facilities.
void rsaInitPublicKey(RsaPublicKey *key)
Initialize an RSA public key.
Definition: rsa.c:100
void ecFreePublicKey(EcPublicKey *key)
Release an EC public key.
Definition: ec.c:68
error_t sshImportRsaCertPublicKey(RsaPublicKey *publicKey, const SshCertificate *cert)
Import an RSA public key from a certificate.
const char_t * sshGetSignFormatId(const SshString *publicKeyAlgo)
Get the signature format identifier used by a given public key algorithm.
SshEd25519CertPublicKey ed25519PublicKey
error_t ed25519VerifySignatureEx(const uint8_t *publicKey, const DataChunk *message, uint_t messageLen, const void *context, uint8_t contextLen, uint8_t flag, const uint8_t *signature)
EdDSA signature verification.
Definition: ed25519.c:459