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-2024 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.4.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 
227 #if (SSH_SHA1_SUPPORT == ENABLED)
228  //RSA with SHA-1 public key algorithm?
229  if(sshCompareString(publicKeyAlgo, "ssh-rsa") ||
230  sshCompareString(publicKeyAlgo, "ssh-rsa-cert-v01@openssh.com"))
231  {
232  //Select the relevant hash algorithm
233  hashAlgo = SHA1_HASH_ALGO;
234  }
235  else
236 #endif
237 #if (SSH_SHA256_SUPPORT == ENABLED)
238  //RSA with SHA-256 public key algorithm?
239  if(sshCompareString(publicKeyAlgo, "rsa-sha2-256") ||
240  sshCompareString(publicKeyAlgo, "rsa-sha2-256-cert-v01@openssh.com"))
241  {
242  //Select the relevant hash algorithm
243  hashAlgo = SHA256_HASH_ALGO;
244  }
245  else
246 #endif
247 #if (SSH_SHA512_SUPPORT == ENABLED)
248  //RSA with SHA-512 public key algorithm?
249  if(sshCompareString(publicKeyAlgo, "rsa-sha2-512") ||
250  sshCompareString(publicKeyAlgo, "rsa-sha2-512-cert-v01@openssh.com"))
251  {
252  //Select the relevant hash algorithm
253  hashAlgo = SHA512_HASH_ALGO;
254  }
255  else
256 #endif
257  //Unknown public key algorithm?
258  {
259  //Just for sanity
260  hashAlgo = NULL;
261  }
262 
263  //Make sure the hash algorithm is supported
264  if(hashAlgo != NULL)
265  {
266  RsaPublicKey rsaPublicKey;
267 
268  //Initialize RSA public key
269  rsaInitPublicKey(&rsaPublicKey);
270 
271  //Initialize hash context
272  hashAlgo->init(&hashContext);
273 
274  //Valid session identifier?
275  if(sessionId != NULL)
276  {
277  uint8_t temp[4];
278 
279  //Encode the length of the session identifier as a 32-bit big-endian
280  //integer
281  STORE32BE(sessionId->length, temp);
282 
283  //Digest the length field
284  hashAlgo->update(&hashContext, temp, sizeof(temp));
285  //Digest the session identifier
286  hashAlgo->update(&hashContext, sessionId->value, sessionId->length);
287  }
288 
289  //Digest the message
290  hashAlgo->update(&hashContext, message->value, message->length);
291  hashAlgo->final(&hashContext, NULL);
292 
293 #if (SSH_CERT_SUPPORT == ENABLED)
294  //RSA certificate?
295  if(sshIsCertPublicKeyAlgo(publicKeyAlgo))
296  {
297  SshCertificate cert;
298 
299  //Parse RSA certificate structure
300  error = sshParseCertificate(publicKeyBlob->value,
301  publicKeyBlob->length, &cert);
302 
303  //Check status
304  if(!error)
305  {
306  //Import RSA public key
307  error = sshImportRsaCertPublicKey(&cert, &rsaPublicKey);
308  }
309  }
310  else
311 #endif
312  //RSA public key?
313  {
314  SshRsaHostKey hostKey;
315 
316  //Parse RSA host key structure
317  error = sshParseRsaHostKey(publicKeyBlob->value, publicKeyBlob->length,
318  &hostKey);
319 
320  //Check status code
321  if(!error)
322  {
323  //Import RSA public key
324  error = sshImportRsaHostKey(&hostKey, &rsaPublicKey);
325  }
326  }
327 
328  //Check status code
329  if(!error)
330  {
331  //Verify RSA signature
332  error = rsassaPkcs1v15Verify(&rsaPublicKey, hashAlgo,
333  hashContext.digest, signatureBlob->value, signatureBlob->length);
334  }
335 
336  //Free previously allocated resources
337  rsaFreePublicKey(&rsaPublicKey);
338  }
339  else
340  {
341  //Report an error
343  }
344 
345  //Return status code
346  return error;
347 #else
348  //Not implemented
349  return ERROR_NOT_IMPLEMENTED;
350 #endif
351 }
352 
353 
354 /**
355  * @brief DSA signature verification
356  * @param[in] publicKeyAlgo Public key algorithm
357  * @param[in] publicKeyBlob Signer's public key
358  * @param[in] sessionId Session identifier (optional parameter)
359  * @param[in] message Message whose signature is to be verified
360  * @param[in] signatureBlob Signature to be verified
361  * @return Error code
362  **/
363 
365  const SshBinaryString *publicKeyBlob, const SshBinaryString *sessionId,
366  const SshBinaryString *message, const SshBinaryString *signatureBlob)
367 {
368 #if (SSH_DSA_SIGN_SUPPORT == ENABLED)
369  error_t error;
370  DsaPublicKey dsaPublicKey;
371  DsaSignature dsaSignature;
372  Sha1Context sha1Context;
373 
374  //The DSA signature blob contains R followed by S (which are 160-bit
375  //integers)
376  if(signatureBlob->length == (2 * SHA1_DIGEST_SIZE))
377  {
378  //Initialize DSA public key
379  dsaInitPublicKey(&dsaPublicKey);
380  //Initialize DSA signature
381  dsaInitSignature(&dsaSignature);
382 
383  //Initialize hash context
384  sha1Init(&sha1Context);
385 
386  //Valid session identifier?
387  if(sessionId != NULL)
388  {
389  uint8_t temp[4];
390 
391  //Encode the length of the session identifier as a 32-bit big-endian
392  //integer
393  STORE32BE(sessionId->length, temp);
394 
395  //Digest the length field
396  sha1Update(&sha1Context, temp, sizeof(temp));
397  //Digest the session identifier
398  sha1Update(&sha1Context, sessionId->value, sessionId->length);
399  }
400 
401  //Digest the message
402  sha1Update(&sha1Context, message->value, message->length);
403  sha1Final(&sha1Context, NULL);
404 
405 #if (SSH_CERT_SUPPORT == ENABLED)
406  //DSA certificate?
407  if(sshIsCertPublicKeyAlgo(publicKeyAlgo))
408  {
409  SshCertificate cert;
410 
411  //Parse DSA certificate structure
412  error = sshParseCertificate(publicKeyBlob->value,
413  publicKeyBlob->length, &cert);
414 
415  //Check status
416  if(!error)
417  {
418  //Import DSA public key
419  error = sshImportDsaCertPublicKey(&cert, &dsaPublicKey);
420  }
421  }
422  else
423 #endif
424  //DSA public key?
425  {
426  SshDsaHostKey hostKey;
427 
428  //Parse DSA host key structure
429  error = sshParseDsaHostKey(publicKeyBlob->value, publicKeyBlob->length,
430  &hostKey);
431 
432  //Check status code
433  if(!error)
434  {
435  //Import DSA public key
436  error = sshImportDsaHostKey(&hostKey, &dsaPublicKey);
437  }
438  }
439 
440  //Check status code
441  if(!error)
442  {
443  //Import integer R
444  error = mpiImport(&dsaSignature.r, signatureBlob->value,
446  }
447 
448  //Check status code
449  if(!error)
450  {
451  //Import integer S
452  error = mpiImport(&dsaSignature.s, signatureBlob->value +
454  }
455 
456  //Check status code
457  if(!error)
458  {
459  //Verify DSA signature
460  error = dsaVerifySignature(&dsaPublicKey, sha1Context.digest,
461  SHA1_DIGEST_SIZE, &dsaSignature);
462  }
463 
464  //Free previously allocated resources
465  dsaFreePublicKey(&dsaPublicKey);
466  dsaFreeSignature(&dsaSignature);
467  }
468  else
469  {
470  //The length of the signature is not acceptable
471  error = ERROR_INVALID_MESSAGE;
472  }
473 
474  //Return status code
475  return error;
476 #else
477  //Not implemented
478  return ERROR_NOT_IMPLEMENTED;
479 #endif
480 }
481 
482 
483 /**
484  * @brief ECDSA signature verification
485  * @param[in] publicKeyAlgo Public key algorithm
486  * @param[in] publicKeyBlob Signer's public key
487  * @param[in] sessionId Session identifier (optional parameter)
488  * @param[in] message Message whose signature is to be verified
489  * @param[in] signatureBlob Signature to be verified
490  * @return Error code
491  **/
492 
494  const SshBinaryString *publicKeyBlob, const SshBinaryString *sessionId,
495  const SshBinaryString *message, const SshBinaryString *signatureBlob)
496 {
497 #if (SSH_ECDSA_SIGN_SUPPORT == ENABLED)
498  error_t error;
499  SshEcdsaSignature signature;
500  const HashAlgo *hashAlgo;
501  HashContext hashContext;
502 
503 #if (SSH_NISTP256_SUPPORT == ENABLED && SSH_SHA256_SUPPORT == ENABLED)
504  //ECDSA with NIST P-256 public key algorithm?
505  if(sshCompareString(publicKeyAlgo, "ecdsa-sha2-nistp256") ||
506  sshCompareString(publicKeyAlgo, "ecdsa-sha2-nistp256-cert-v01@openssh.com"))
507  {
508  //Select the relevant hash algorithm
509  hashAlgo = SHA256_HASH_ALGO;
510  }
511  else
512 #endif
513 #if (SSH_NISTP384_SUPPORT == ENABLED && SSH_SHA384_SUPPORT == ENABLED)
514  //ECDSA with NIST P-384 public key algorithm?
515  if(sshCompareString(publicKeyAlgo, "ecdsa-sha2-nistp384") ||
516  sshCompareString(publicKeyAlgo, "ecdsa-sha2-nistp384-cert-v01@openssh.com"))
517  {
518  //Select the relevant hash algorithm
519  hashAlgo = SHA384_HASH_ALGO;
520  }
521  else
522 #endif
523 #if (SSH_NISTP521_SUPPORT == ENABLED && SSH_SHA512_SUPPORT == ENABLED)
524  //ECDSA with NIST P-521 public key algorithm?
525  if(sshCompareString(publicKeyAlgo, "ecdsa-sha2-nistp521") ||
526  sshCompareString(publicKeyAlgo, "ecdsa-sha2-nistp521-cert-v01@openssh.com"))
527  {
528  //Select the relevant hash algorithm
529  hashAlgo = SHA512_HASH_ALGO;
530  }
531  else
532 #endif
533  //Unknown public key algorithm?
534  {
535  //Just for sanity
536  hashAlgo = NULL;
537  }
538 
539  //Make sure the hash algorithm is supported
540  if(hashAlgo != NULL)
541  {
542  EcDomainParameters ecParams;
543  EcPublicKey ecPublicKey;
544  EcdsaSignature ecdsaSignature;
545 
546  //Initialize EC domain parameters
547  ecInitDomainParameters(&ecParams);
548  //Initialize EC 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, NULL);
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(&cert, &ecParams, &ecPublicKey);
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, publicKeyBlob->length,
600  &hostKey);
601 
602  //Check status code
603  if(!error)
604  {
605  //Import ECDSA public key
606  error = sshImportEcdsaHostKey(&hostKey, &ecParams, &ecPublicKey);
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 = mpiImport(&ecdsaSignature.r, signature.r.value,
623  signature.r.length, MPI_FORMAT_BIG_ENDIAN);
624  }
625 
626  //Check status code
627  if(!error)
628  {
629  //Import integer S
630  error = mpiImport(&ecdsaSignature.s, signature.s.value,
631  signature.s.length, MPI_FORMAT_BIG_ENDIAN);
632  }
633 
634  //Check status code
635  if(!error)
636  {
637  //Verify ECDSA signature
638  error = ecdsaVerifySignature(&ecParams, &ecPublicKey,
639  hashContext.digest, hashAlgo->digestSize, &ecdsaSignature);
640  }
641 
642  //Free previously allocated resources
643  ecFreeDomainParameters(&ecParams);
644  ecFreePublicKey(&ecPublicKey);
645  ecdsaFreeSignature(&ecdsaSignature);
646  }
647  else
648  {
649  //Report an error
651  }
652 
653  //Return status code
654  return error;
655 #else
656  //Not implemented
657  return ERROR_NOT_IMPLEMENTED;
658 #endif
659 }
660 
661 
662 /**
663  * @brief Ed25519 signature verification
664  * @param[in] publicKeyAlgo Public key algorithm
665  * @param[in] publicKeyBlob Signer's public key
666  * @param[in] sessionId Session identifier (optional parameter)
667  * @param[in] message Message whose signature is to be verified
668  * @param[in] signatureBlob Signature to be verified
669  * @return Error code
670  **/
671 
673  const SshBinaryString *publicKeyBlob, const SshBinaryString *sessionId,
674  const SshBinaryString *message, const SshBinaryString *signatureBlob)
675 {
676 #if (SSH_ED25519_SIGN_SUPPORT == ENABLED)
677  error_t error;
678  const uint8_t *ed25519PublicKey;
679  EddsaMessageChunk messageChunks[4];
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  messageChunks[3].buffer = NULL;
740  messageChunks[3].length = 0;
741  }
742  else
743  {
744  //The message fits in a single chunk
745  messageChunks[0].buffer = message->value;
746  messageChunks[0].length = message->length;
747  messageChunks[1].buffer = NULL;
748  messageChunks[1].length = 0;
749  }
750 
751  //Verify Ed25519 signature (PureEdDSA mode)
752  error = ed25519VerifySignatureEx(ed25519PublicKey, messageChunks, NULL,
753  0, 0, signatureBlob->value);
754  }
755 
756  //Return status code
757  return error;
758 #else
759  //Not implemented
760  return ERROR_NOT_IMPLEMENTED;
761 #endif
762 }
763 
764 
765 /**
766  * @brief Ed448 signature verification
767  * @param[in] publicKeyAlgo Public key algorithm
768  * @param[in] publicKeyBlob Signer's public key
769  * @param[in] sessionId Session identifier (optional parameter)
770  * @param[in] message Message whose signature is to be verified
771  * @param[in] signatureBlob Signature to be verified
772  * @return Error code
773  **/
774 
776  const SshBinaryString *publicKeyBlob, const SshBinaryString *sessionId,
777  const SshBinaryString *message, const SshBinaryString *signatureBlob)
778 {
779 #if (SSH_ED448_SIGN_SUPPORT == ENABLED)
780  error_t error;
781  SshEddsaHostKey hostKey;
782  EddsaMessageChunk messageChunks[4];
783  uint8_t temp[4];
784 
785  //The Ed448 signature shall consist of 57 octets
786  if(signatureBlob->length != ED448_SIGNATURE_LEN)
788 
789  //Parse Ed448 host key structure
790  error = sshParseEd448HostKey(publicKeyBlob->value, publicKeyBlob->length,
791  &hostKey);
792 
793  //Check status
794  if(!error)
795  {
796  //Valid session identifier?
797  if(sessionId != NULL)
798  {
799  //Encode the length of the session identifier as a 32-bit big-endian
800  //integer
801  STORE32BE(sessionId->length, temp);
802 
803  //Data to be signed is run through the EdDSA algorithm without
804  //pre-hashing
805  messageChunks[0].buffer = temp;
806  messageChunks[0].length = sizeof(temp);
807  messageChunks[1].buffer = sessionId->value;
808  messageChunks[1].length = sessionId->length;
809  messageChunks[2].buffer = message->value;
810  messageChunks[2].length = message->length;
811  messageChunks[3].buffer = NULL;
812  messageChunks[3].length = 0;
813  }
814  else
815  {
816  //The message fits in a single chunk
817  messageChunks[0].buffer = message->value;
818  messageChunks[0].length = message->length;
819  messageChunks[1].buffer = NULL;
820  messageChunks[1].length = 0;
821  }
822 
823  //Verify Ed448 signature (PureEdDSA mode)
824  error = ed448VerifySignatureEx(hostKey.q.value, messageChunks, NULL,
825  0, 0, signatureBlob->value);
826  }
827 
828  //Return status code
829  return error;
830 #else
831  //Not implemented
832  return ERROR_NOT_IMPLEMENTED;
833 #endif
834 }
835 
836 #endif
void sha1Update(Sha1Context *context, const void *data, size_t length)
Update the SHA-1 context with a portion of the message being hashed.
uint8_t message[]
Definition: chap.h:154
char char_t
Definition: compiler_port.h:48
#define STORE32BE(a, p)
Definition: cpu_endian.h:286
Debugging facilities.
uint8_t n
error_t dsaVerifySignature(const DsaPublicKey *key, const uint8_t *digest, size_t digestLen, const DsaSignature *signature)
DSA signature verification.
Definition: dsa.c:585
void dsaInitSignature(DsaSignature *signature)
Initialize a DSA signature.
Definition: dsa.c:164
void dsaFreeSignature(DsaSignature *signature)
Release a DSA signature.
Definition: dsa.c:177
void dsaInitPublicKey(DsaPublicKey *key)
Initialize a DSA public key.
Definition: dsa.c:105
void dsaFreePublicKey(DsaPublicKey *key)
Release a DSA public key.
Definition: dsa.c:119
void ecFreeDomainParameters(EcDomainParameters *params)
Release EC domain parameters.
Definition: ec.c:72
void ecInitDomainParameters(EcDomainParameters *params)
Initialize EC domain parameters.
Definition: ec.c:51
void ecInitPublicKey(EcPublicKey *key)
Initialize an EC public key.
Definition: ec.c:153
void ecFreePublicKey(EcPublicKey *key)
Release an EC public key.
Definition: ec.c:165
__weak_func error_t ecdsaVerifySignature(const EcDomainParameters *params, const EcPublicKey *publicKey, const uint8_t *digest, size_t digestLen, const EcdsaSignature *signature)
ECDSA signature verification.
Definition: ecdsa.c:507
void ecdsaFreeSignature(EcdsaSignature *signature)
Release an ECDSA signature.
Definition: ecdsa.c:82
void ecdsaInitSignature(EcdsaSignature *signature)
Initialize an ECDSA signature.
Definition: ecdsa.c:69
error_t ed25519VerifySignatureEx(const uint8_t *publicKey, const EddsaMessageChunk *messageChunks, const void *context, uint8_t contextLen, uint8_t flag, const uint8_t *signature)
EdDSA signature verification.
Definition: ed25519.c:463
#define ED25519_SIGNATURE_LEN
Definition: ed25519.h:44
error_t ed448VerifySignatureEx(const uint8_t *publicKey, const EddsaMessageChunk *messageChunks, const void *context, uint8_t contextLen, uint8_t flag, const uint8_t *signature)
EdDSA signature verification.
Definition: ed448.c:438
#define ED448_SIGNATURE_LEN
Definition: ed448.h:44
error_t
Error codes.
Definition: error.h:43
@ ERROR_UNSUPPORTED_SIGNATURE_ALGO
Definition: error.h:132
@ ERROR_INVALID_MESSAGE
Definition: error.h:105
@ ERROR_INVALID_SIGNATURE
Definition: error.h:226
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
void sha1Final(Sha1Context *context, uint8_t *digest)
Finish the SHA-1 message digest.
void sha1Init(Sha1Context *context)
Initialize SHA-1 message digest context.
error_t mpiImport(Mpi *r, const uint8_t *data, uint_t length, MpiFormat format)
Octet string to integer conversion.
Definition: mpi.c:624
@ MPI_FORMAT_BIG_ENDIAN
Definition: mpi.h:71
uint8_t p
Definition: ndp.h:300
void rsaFreePublicKey(RsaPublicKey *key)
Release an RSA public key.
Definition: rsa.c:118
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:838
void rsaInitPublicKey(RsaPublicKey *key)
Initialize an RSA public key.
Definition: rsa.c:105
#define SHA1_HASH_ALGO
Definition: sha1.h:49
#define SHA1_DIGEST_SIZE
Definition: sha1.h:45
#define SHA256_HASH_ALGO
Definition: sha256.h:49
#define SHA384_HASH_ALGO
Definition: sha384.h:45
#define SHA512_HASH_ALGO
Definition: sha512.h:49
Secure Shell (SSH)
#define SshConnection
Definition: ssh.h:883
const char_t * sshGetKeyFormatId(const SshString *publicKeyAlgo)
Get the key format identifier used by a given public key algorithm.
const char_t * sshGetSignFormatId(const SshString *publicKeyAlgo)
Get the signature format identifier used by a given public key algorithm.
bool_t sshIsCertPublicKeyAlgo(const SshString *publicKeyAlgo)
Test if the specified public key algorithm is using certificates.
SSH algorithm negotiation.
error_t sshImportRsaCertPublicKey(const SshCertificate *cert, RsaPublicKey *publicKey)
Import an RSA public key from a certificate.
error_t sshImportEcdsaCertPublicKey(const SshCertificate *cert, EcDomainParameters *params, EcPublicKey *publicKey)
Import an ECDSA public key from a certificate.
error_t sshImportDsaCertPublicKey(const SshCertificate *cert, DsaPublicKey *publicKey)
Import a DSA public key from a certificate.
SSH certificate import functions.
error_t sshParseCertificate(const uint8_t *data, size_t length, SshCertificate *cert)
Parse SSH certificate.
error_t sshImportEcdsaHostKey(const SshEcdsaHostKey *hostKey, EcDomainParameters *params, EcPublicKey *publicKey)
Import a ECDSA host key.
error_t sshImportRsaHostKey(const SshRsaHostKey *hostKey, RsaPublicKey *publicKey)
Import an RSA host key.
error_t sshImportDsaHostKey(const SshDsaHostKey *hostKey, DsaPublicKey *publicKey)
Import a DSA host key.
SSH key file import functions.
error_t sshParseDsaHostKey(const uint8_t *data, size_t length, SshDsaHostKey *hostKey)
Parse a DSA host key structure.
error_t sshParseEd25519HostKey(const uint8_t *data, size_t length, SshEddsaHostKey *hostKey)
Parse an Ed25519 host key structure.
error_t sshParseRsaHostKey(const uint8_t *data, size_t length, SshRsaHostKey *hostKey)
Parse an RSA host key structure.
error_t sshParseEcdsaHostKey(const uint8_t *data, size_t length, SshEcdsaHostKey *hostKey)
Parse an ECDSA host key structure.
error_t sshParseEd448HostKey(const uint8_t *data, size_t length, SshEddsaHostKey *hostKey)
Parse an Ed448 host key structure.
error_t sshParseBinaryString(const uint8_t *p, size_t length, SshBinaryString *string)
Parse a binary string.
Definition: ssh_misc.c:1189
bool_t sshCompareString(const SshString *string, const char_t *value)
Compare a binary string against the supplied value.
Definition: ssh_misc.c:1586
error_t sshParseString(const uint8_t *p, size_t length, SshString *string)
Parse a string.
Definition: ssh_misc.c:1152
SSH helper functions.
error_t sshParseEcdsaSignature(const uint8_t *data, size_t length, SshEcdsaSignature *signature)
Parse an ECDSA signature.
Definition: ssh_sign_misc.c:98
Helper functions for signature generation and verification.
error_t sshVerifyEd448Signature(const SshString *publicKeyAlgo, const SshBinaryString *publicKeyBlob, const SshBinaryString *sessionId, const SshBinaryString *message, const SshBinaryString *signatureBlob)
Ed448 signature verification.
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_t sshVerifyEcdsaSignature(const SshString *publicKeyAlgo, const SshBinaryString *publicKeyBlob, const SshBinaryString *sessionId, const SshBinaryString *message, const SshBinaryString *signatureBlob)
ECDSA signature verification.
error_t sshVerifySignature(SshConnection *connection, const SshString *publicKeyAlgo, const SshBinaryString *publicKeyBlob, const SshBinaryString *sessionId, const SshBinaryString *message, const SshBinaryString *signature)
Signature verification.
error_t sshVerifyDsaSignature(const SshString *publicKeyAlgo, const SshBinaryString *publicKeyBlob, const SshBinaryString *sessionId, const SshBinaryString *message, const SshBinaryString *signatureBlob)
DSA signature verification.
RSA/DSA/ECDSA/EdDSA signature verification.
DSA public key.
Definition: dsa.h:61
DSA signature.
Definition: dsa.h:84
Mpi s
Definition: dsa.h:86
Mpi r
Definition: dsa.h:85
EC domain parameters.
Definition: ec.h:76
EC public key.
Definition: ec.h:94
ECDSA signature.
Definition: ecdsa.h:49
Message chunk descriptor.
Definition: eddsa.h:71
const void * buffer
Definition: eddsa.h:72
size_t length
Definition: eddsa.h:73
Common interface for hash algorithms.
Definition: crypto.h:1014
HashAlgoFinal final
Definition: crypto.h:1026
HashAlgoUpdate update
Definition: crypto.h:1025
size_t digestSize
Definition: crypto.h:1020
HashAlgoInit init
Definition: crypto.h:1024
RSA public key.
Definition: rsa.h:57
SHA-1 algorithm context.
Definition: sha1.h:62
uint8_t digest[20]
Definition: sha1.h:66
Binary string.
Definition: ssh_types.h:67
const uint8_t * value
Definition: ssh_types.h:68
size_t length
Definition: ssh_types.h:69
SSH certificate (OpenSSH format)
SshCertPublicKey publicKey
DSA host key.
Definition: ssh_key_parse.h:64
ECDSA host key.
Definition: ssh_key_parse.h:78
ECDSA signature.
Definition: ssh_sign_misc.h:48
SshBinaryString s
Definition: ssh_sign_misc.h:50
SshBinaryString r
Definition: ssh_sign_misc.h:49
EdDSA host key.
Definition: ssh_key_parse.h:90
SshBinaryString q
Definition: ssh_key_parse.h:92
RSA host key.
Definition: ssh_key_parse.h:52
String.
Definition: ssh_types.h:56
size_t length
Definition: ssh_types.h:58
uint8_t sessionId[]
Definition: tls.h:1756
Generic hash algorithm context.
uint8_t digest[MAX_HASH_DIGEST_SIZE]
SshEd25519CertPublicKey ed25519PublicKey