ssh_sign_generate.c
Go to the documentation of this file.
1 /**
2  * @file ssh_sign_generate.c
3  * @brief RSA/DSA/ECDSA/EdDSA signature generation
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.4
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_sign_generate.h"
39 #include "ssh/ssh_sign_misc.h"
40 #include "ssh/ssh_misc.h"
41 #include "debug.h"
42 
43 //Check SSH stack configuration
44 #if (SSH_SUPPORT == ENABLED)
45 
46 
47 /**
48  * @brief Signature generation
49  * @param[in] connection Pointer to the SSH connection
50  * @param[in] publicKeyAlgo Public key algorithm
51  * @param[in] hostKey Pointer to the signer's host key
52  * @param[in] sessionId Session identifier (optional parameter)
53  * @param[in] message Pointer to the message to be signed
54  * @param[out] p Output stream where to write the signature
55  * @param[out] written Total number of bytes that have been written
56  * @return Error code
57  **/
58 
60  const char_t *publicKeyAlgo, const SshHostKey *hostKey,
62  uint8_t *p, size_t *written)
63 {
64  error_t error;
65  size_t n;
67  const char_t *signFormatId;
68 
69  //Total length of the signature encoding
70  *written = 0;
71 
72  //Get the name of the public key algorithm
73  name.value = publicKeyAlgo;
74  name.length = osStrlen(publicKeyAlgo);
75 
76  //Public key/certificate formats that do not explicitly specify a signature
77  //format identifier must use the public key/certificate format identifier
78  //as the signature identifier (refer to RFC 4253, section 6.6)
79  signFormatId = sshGetSignFormatId(&name);
80 
81  //Valid signature format identifier?
82  if(signFormatId != NULL)
83  {
84  //Format signature format identifier
85  error = sshFormatString(signFormatId, p, &n);
86 
87  //Check status code
88  if(!error)
89  {
90  //Point to the signature blob
91  p += n;
92  *written += n;
93 
94 #if (SSH_SIGN_CALLBACK_SUPPORT == ENABLED)
95  //Valid signature generation callback function?
96  if(connection->context->signGenCallback != NULL)
97  {
98  //Invoke user-defined callback
99  error = connection->context->signGenCallback(connection,
100  signFormatId, hostKey, sessionId, message, p, &n);
101  }
102  else
103 #endif
104  {
105  //No callback function registered
107  }
108 
109  //Check status code
110  if(error == ERROR_UNSUPPORTED_SIGNATURE_ALGO ||
111  error == ERROR_UNKOWN_KEY)
112  {
113 #if (SSH_RSA_SIGN_SUPPORT == ENABLED)
114  //RSA signature algorithm?
115  if(sshCompareAlgo(signFormatId, "ssh-rsa") ||
116  sshCompareAlgo(signFormatId, "rsa-sha2-256") ||
117  sshCompareAlgo(signFormatId, "rsa-sha2-512"))
118  {
119  //Generate an RSA signature using the host private key
120  error = sshGenerateRsaSignature(connection, signFormatId,
121  hostKey, sessionId, message, p, &n);
122  }
123  else
124 #endif
125 #if (SSH_DSA_SIGN_SUPPORT == ENABLED)
126  //DSA signature algorithm?
127  if(sshCompareAlgo(signFormatId, "ssh-dss"))
128  {
129  //Generate a DSA signature using the host private key
130  error = sshGenerateDsaSignature(connection, signFormatId,
131  hostKey, sessionId, message, p, &n);
132  }
133  else
134 #endif
135 #if (SSH_ECDSA_SIGN_SUPPORT == ENABLED)
136  //ECDSA signature algorithm?
137  if(sshCompareAlgo(signFormatId, "ecdsa-sha2-nistp256") ||
138  sshCompareAlgo(signFormatId, "ecdsa-sha2-nistp384") ||
139  sshCompareAlgo(signFormatId, "ecdsa-sha2-nistp521"))
140  {
141  //Generate an ECDSA signature using the host private key
142  error = sshGenerateEcdsaSignature(connection, signFormatId,
143  hostKey, sessionId, message, p, &n);
144  }
145  else
146 #endif
147 #if (SSH_ED25519_SIGN_SUPPORT == ENABLED)
148  //Ed25519 signature algorithm?
149  if(sshCompareAlgo(signFormatId, "ssh-ed25519"))
150  {
151  //Generate an EdDSA signature using the host private key
152  error = sshGenerateEd25519Signature(connection, signFormatId,
153  hostKey, sessionId, message, p, &n);
154  }
155  else
156 #endif
157 #if (SSH_ED448_SIGN_SUPPORT == ENABLED)
158  //Ed448 signature algorithm?
159  if(sshCompareAlgo(signFormatId, "ssh-ed448"))
160  {
161  //Generate an EdDSA signature using the host private key
162  error = sshGenerateEd448Signature(connection, signFormatId,
163  hostKey, sessionId, message, p, &n);
164  }
165  else
166 #endif
167  //Unknown signature algorithm?
168  {
169  //Report an error
171  }
172  }
173  }
174 
175  //Check status code
176  if(!error)
177  {
178  //Total number of bytes that have been written
179  *written += n;
180  }
181  }
182  else
183  {
184  //Report an error
186  }
187 
188  //Return status code
189  return error;
190 }
191 
192 
193 /**
194  * @brief RSA signature generation
195  * @param[in] connection Pointer to the SSH connection
196  * @param[in] publicKeyAlgo Public key algorithm
197  * @param[in] hostKey Pointer to the signer's host key
198  * @param[in] sessionId Session identifier (optional parameter)
199  * @param[in] message Pointer to the message to be signed
200  * @param[out] p Output stream where to write the signature
201  * @param[out] written Total number of bytes that have been written
202  * @return Error code
203  **/
204 
206  const char_t *publicKeyAlgo, const SshHostKey *hostKey,
208  uint8_t *p, size_t *written)
209 {
210 #if (SSH_RSA_SIGN_SUPPORT == ENABLED)
211  error_t error;
212  size_t n;
213  const HashAlgo *hashAlgo;
214  HashContext hashContext;
215 
216 #if (SSH_SHA1_SUPPORT == ENABLED)
217  //RSA with SHA-1 public key algorithm?
218  if(sshCompareAlgo(publicKeyAlgo, "ssh-rsa"))
219  {
220  //Select the relevant hash algorithm
221  hashAlgo = SHA1_HASH_ALGO;
222  }
223  else
224 #endif
225 #if (SSH_SHA256_SUPPORT == ENABLED)
226  //RSA with SHA-256 public key algorithm?
227  if(sshCompareAlgo(publicKeyAlgo, "rsa-sha2-256"))
228  {
229  //Select the relevant hash algorithm
230  hashAlgo = SHA256_HASH_ALGO;
231  }
232  else
233 #endif
234 #if (SSH_SHA512_SUPPORT == ENABLED)
235  //RSA with SHA-512 public key algorithm?
236  if(sshCompareAlgo(publicKeyAlgo, "rsa-sha2-512"))
237  {
238  //Select the relevant hash algorithm
239  hashAlgo = SHA512_HASH_ALGO;
240  }
241  else
242 #endif
243  //Unknown host key algorithm?
244  {
245  //Just for sanity
246  hashAlgo = NULL;
247  }
248 
249  //Make sure the hash algorithm is supported
250  if(hashAlgo != NULL)
251  {
252  RsaPrivateKey rsaPrivateKey;
253 
254  //Initialize RSA private key
255  rsaInitPrivateKey(&rsaPrivateKey);
256 
257  //Initialize hash context
258  hashAlgo->init(&hashContext);
259 
260  //Valid session identifier?
261  if(sessionId != NULL)
262  {
263  uint8_t temp[4];
264 
265  //Encode the length of the session identifier as a 32-bit big-endian
266  //integer
267  STORE32BE(sessionId->length, temp);
268 
269  //Digest the length field
270  hashAlgo->update(&hashContext, temp, sizeof(temp));
271  //Digest the session identifier
272  hashAlgo->update(&hashContext, sessionId->value, sessionId->length);
273  }
274 
275  //Digest the message
276  hashAlgo->update(&hashContext, message->value, message->length);
277  hashAlgo->final(&hashContext, NULL);
278 
279  //Import RSA private key
280  error = sshImportRsaPrivateKey(hostKey->privateKey,
281  hostKey->privateKeyLen, hostKey->password, &rsaPrivateKey);
282 
283  //Check status code
284  if(!error)
285  {
286  //Generate RSA signature
287  error = rsassaPkcs1v15Sign(&rsaPrivateKey, hashAlgo,
288  hashContext.digest, p + 4, &n);
289  }
290 
291  //Check status code
292  if(!error)
293  {
294  //The resulting RSA signature blob is encoded as a string
295  STORE32BE(n, p);
296  //Total number of bytes that have been written
297  *written = sizeof(uint32_t) + n;
298  }
299 
300  //Free previously allocated memory
301  rsaFreePrivateKey(&rsaPrivateKey);
302  }
303  else
304  {
305  //Report an error
307  }
308 
309  //Return status code
310  return error;
311 #else
312  //Not implemented
313  return ERROR_NOT_IMPLEMENTED;
314 #endif
315 }
316 
317 
318 /**
319  * @brief DSA signature generation
320  * @param[in] connection Pointer to the SSH connection
321  * @param[in] publicKeyAlgo Public key algorithm
322  * @param[in] hostKey Pointer to the signer's host key
323  * @param[in] sessionId Session identifier (optional parameter)
324  * @param[in] message Pointer to the message to be signed
325  * @param[out] p Output stream where to write the signature
326  * @param[out] written Total number of bytes that have been written
327  * @return Error code
328  **/
329 
331  const char_t *publicKeyAlgo, const SshHostKey *hostKey,
333  uint8_t *p, size_t *written)
334 {
335 #if (SSH_DSA_SIGN_SUPPORT == ENABLED)
336  error_t error;
337  size_t n;
338  SshContext *context;
339  DsaPrivateKey dsaPrivateKey;
340  DsaSignature dsaSignature;
341  Sha1Context sha1Context;
342 
343  //Initialize variable
344  n = 0;
345 
346  //Point to the SSH context
347  context = connection->context;
348 
349  //Initialize DSA private key
350  dsaInitPrivateKey(&dsaPrivateKey);
351  //Initialize DSA signature
352  dsaInitSignature(&dsaSignature);
353 
354  //Initialize hash context
355  sha1Init(&sha1Context);
356 
357  //Valid session identifier?
358  if(sessionId != NULL)
359  {
360  uint8_t temp[4];
361 
362  //Encode the length of the session identifier as a 32-bit big-endian
363  //integer
364  STORE32BE(sessionId->length, temp);
365 
366  //Digest the length field
367  sha1Update(&sha1Context, temp, sizeof(temp));
368  //Digest the session identifier
369  sha1Update(&sha1Context, sessionId->value, sessionId->length);
370  }
371 
372  //Digest the message
373  sha1Update(&sha1Context, message->value, message->length);
374  sha1Final(&sha1Context, NULL);
375 
376  //Import DSA private key
377  error = sshImportDsaPrivateKey(hostKey->privateKey,
378  hostKey->privateKeyLen, hostKey->password, &dsaPrivateKey);
379 
380  //Check status code
381  if(!error)
382  {
383  //Generate DSA signature
384  error = dsaGenerateSignature(context->prngAlgo, context->prngContext,
385  &dsaPrivateKey, sha1Context.digest, SHA1_DIGEST_SIZE, &dsaSignature);
386  }
387 
388  //Check status code
389  if(!error)
390  {
391  //The DSA signature blob contains R followed by S (which are 160-bit
392  //integers)
393  n = mpiGetByteLength(&dsaPrivateKey.params.q);
394 
395  //Encode integer R
396  error = mpiExport(&dsaSignature.r, p + 4, n, MPI_FORMAT_BIG_ENDIAN);
397  }
398 
399  //Check status code
400  if(!error)
401  {
402  //Encode integer S
403  error = mpiExport(&dsaSignature.s, p + n + 4, n, MPI_FORMAT_BIG_ENDIAN);
404  }
405 
406  //Check status code
407  if(!error)
408  {
409  //The resulting DSA signature blob is encoded as a string
410  STORE32BE(2 * n, p);
411  //Total number of bytes that have been written
412  *written = sizeof(uint32_t) + 2 * n;
413  }
414 
415  //Free previously allocated resources
416  dsaFreePrivateKey(&dsaPrivateKey);
417  dsaFreeSignature(&dsaSignature);
418 
419  //Return status code
420  return error;
421 #else
422  //Not implemented
423  return ERROR_NOT_IMPLEMENTED;
424 #endif
425 }
426 
427 
428 /**
429  * @brief ECDSA signature generation
430  * @param[in] connection Pointer to the SSH connection
431  * @param[in] publicKeyAlgo Public key algorithm
432  * @param[in] hostKey Pointer to the signer's host key
433  * @param[in] sessionId Session identifier (optional parameter)
434  * @param[in] message Pointer to the message to be signed
435  * @param[out] p Output stream where to write the signature
436  * @param[out] written Total number of bytes that have been written
437  * @return Error code
438  **/
439 
441  const char_t *publicKeyAlgo, const SshHostKey *hostKey,
443  uint8_t *p, size_t *written)
444 {
445 #if (SSH_ECDSA_SIGN_SUPPORT == ENABLED)
446  error_t error;
447  size_t rLen;
448  size_t sLen;
449  SshContext *context;
450  const HashAlgo *hashAlgo;
451  const EcCurveInfo *curveInfo;
452  HashContext hashContext;
453 
454  //Point to the SSH context
455  context = connection->context;
456 
457 #if (SSH_NISTP256_SUPPORT == ENABLED && SSH_SHA256_SUPPORT == ENABLED)
458  //ECDSA with NIST P-256 public key algorithm?
459  if(sshCompareAlgo(publicKeyAlgo, "ecdsa-sha2-nistp256"))
460  {
461  //Select the relevant curve and hash algorithm
462  curveInfo = SECP256R1_CURVE;
463  hashAlgo = SHA256_HASH_ALGO;
464  }
465  else
466 #endif
467 #if (SSH_NISTP384_SUPPORT == ENABLED && SSH_SHA384_SUPPORT == ENABLED)
468  //ECDSA with NIST P-384 public key algorithm?
469  if(sshCompareAlgo(publicKeyAlgo, "ecdsa-sha2-nistp384"))
470  {
471  //Select the relevant curve and hash algorithm
472  curveInfo = SECP384R1_CURVE;
473  hashAlgo = SHA384_HASH_ALGO;
474  }
475  else
476 #endif
477 #if (SSH_NISTP521_SUPPORT == ENABLED && SSH_SHA512_SUPPORT == ENABLED)
478  //ECDSA with NIST P-521 public key algorithm?
479  if(sshCompareAlgo(publicKeyAlgo, "ecdsa-sha2-nistp521"))
480  {
481  //Select the relevant curve and hash algorithm
482  curveInfo = SECP521R1_CURVE;
483  hashAlgo = SHA512_HASH_ALGO;
484  }
485  else
486 #endif
487  //Unknown public key algorithm?
488  {
489  //Just for sanity
490  curveInfo = NULL;
491  hashAlgo = NULL;
492  }
493 
494  //Valid parameters?
495  if(curveInfo != NULL && hashAlgo != NULL)
496  {
497  EcDomainParameters ecParams;
498  EcPrivateKey ecPrivateKey;
499  EcdsaSignature ecdsaSignature;
500 
501  //Initialize EC domain parameters
502  ecInitDomainParameters(&ecParams);
503  //Initialize EC private key
504  ecInitPrivateKey(&ecPrivateKey);
505  //Initialize ECDSA signature
506  ecdsaInitSignature(&ecdsaSignature);
507 
508  //Initialize hash context
509  hashAlgo->init(&hashContext);
510 
511  //Valid session identifier?
512  if(sessionId != NULL)
513  {
514  uint8_t temp[4];
515 
516  //Encode the length of the session identifier as a 32-bit big-endian
517  //integer
518  STORE32BE(sessionId->length, temp);
519 
520  //Digest the length field
521  hashAlgo->update(&hashContext, temp, sizeof(temp));
522  //Digest the session identifier
523  hashAlgo->update(&hashContext, sessionId->value, sessionId->length);
524  }
525 
526  //Digest the message
527  hashAlgo->update(&hashContext, message->value, message->length);
528  hashAlgo->final(&hashContext, NULL);
529 
530  //Import EC domain parameters
531  error = ecLoadDomainParameters(&ecParams, curveInfo);
532 
533  //Check status code
534  if(!error)
535  {
536  //Import ECDSA private key
537  error = sshImportEcdsaPrivateKey(hostKey->privateKey,
538  hostKey->privateKeyLen, hostKey->password, &ecPrivateKey);
539  }
540 
541  //Check status code
542  if(!error)
543  {
544  //Generate ECDSA signature
545  error = ecdsaGenerateSignature(context->prngAlgo, context->prngContext,
546  &ecParams, &ecPrivateKey, hashContext.digest, hashAlgo->digestSize,
547  &ecdsaSignature);
548  }
549 
550  //Check status code
551  if(!error)
552  {
553  //Encode integer R
554  error = sshFormatMpint(&ecdsaSignature.r, p + 4, &rLen);
555  }
556 
557  //Check status code
558  if(!error)
559  {
560  //Encode integer S
561  error = sshFormatMpint(&ecdsaSignature.s, p + rLen + 4, &sLen);
562  }
563 
564  //Check status code
565  if(!error)
566  {
567  //The resulting ECDSA signature blob is encoded as a string
568  STORE32BE(rLen + sLen, p);
569  //Total number of bytes that have been written
570  *written = sizeof(uint32_t) + rLen + sLen;
571  }
572 
573  //Free previously allocated resources
574  ecFreeDomainParameters(&ecParams);
575  ecFreePrivateKey(&ecPrivateKey);
576  ecdsaFreeSignature(&ecdsaSignature);
577  }
578  else
579  {
580  //Report an error
582  }
583 
584  //Return status code
585  return error;
586 #else
587  //Not implemented
588  return ERROR_NOT_IMPLEMENTED;
589 #endif
590 }
591 
592 
593 /**
594  * @brief Ed25519 signature generation
595  * @param[in] connection Pointer to the SSH connection
596  * @param[in] publicKeyAlgo Public key algorithm
597  * @param[in] hostKey Pointer to the signer's host key
598  * @param[in] sessionId Session identifier (optional parameter)
599  * @param[in] message Pointer to the message to be signed
600  * @param[out] p Output stream where to write the signature
601  * @param[out] written Total number of bytes that have been written
602  * @return Error code
603  **/
604 
606  const char_t *publicKeyAlgo, const SshHostKey *hostKey,
608  uint8_t *p, size_t *written)
609 {
610 #if (SSH_ED25519_SIGN_SUPPORT == ENABLED)
611  error_t error;
612  size_t n;
613  EddsaPrivateKey eddsaPrivateKey;
614  DataChunk messageChunks[4];
615  uint8_t temp[4];
616  uint8_t d[ED25519_PRIVATE_KEY_LEN];
617 
618  //Initialize EdDSA private key
619  eddsaInitPrivateKey(&eddsaPrivateKey);
620 
621  //Import Ed25519 private key
622  error = sshImportEd25519PrivateKey(hostKey->privateKey,
623  hostKey->privateKeyLen, hostKey->password, &eddsaPrivateKey);
624 
625  //Check status code
626  if(!error)
627  {
628  //Retrieve raw private key
629  error = mpiExport(&eddsaPrivateKey.d, d, ED25519_PRIVATE_KEY_LEN,
631  }
632 
633  //Check status code
634  if(!error)
635  {
636  //Valid session identifier?
637  if(sessionId != NULL)
638  {
639  //Encode the length of the session identifier as a 32-bit big-endian
640  //integer
641  STORE32BE(sessionId->length, temp);
642 
643  //Data to be signed is run through the EdDSA algorithm without
644  //pre-hashing
645  messageChunks[0].buffer = temp;
646  messageChunks[0].length = sizeof(temp);
647  messageChunks[1].buffer = sessionId->value;
648  messageChunks[1].length = sessionId->length;
649  messageChunks[2].buffer = message->value;
650  messageChunks[2].length = message->length;
651  messageChunks[3].buffer = NULL;
652  messageChunks[3].length = 0;
653  }
654  else
655  {
656  //The message fits in a single chunk
657  messageChunks[0].buffer = message->value;
658  messageChunks[0].length = message->length;
659  messageChunks[1].buffer = NULL;
660  messageChunks[1].length = 0;
661  }
662 
663  //Generate Ed25519 signature (PureEdDSA mode)
664  error = ed25519GenerateSignatureEx(d, NULL, messageChunks, NULL, 0, 0,
665  p + 4);
666 
667  //The Ed25519 signature consists of 32 octets
669  }
670 
671  //Check status code
672  if(!error)
673  {
674  //The resulting EdDSA signature is encoded as a string
675  STORE32BE(n, p);
676  //Total number of bytes that have been written
677  *written = sizeof(uint32_t) + n;
678  }
679 
680  //Free previously allocated resources
681  eddsaFreePrivateKey(&eddsaPrivateKey);
682 
683  //Return status code
684  return error;
685 #else
686  //Not implemented
687  return ERROR_NOT_IMPLEMENTED;
688 #endif
689 }
690 
691 
692 /**
693  * @brief Ed448 signature generation
694  * @param[in] connection Pointer to the SSH connection
695  * @param[in] publicKeyAlgo Public key algorithm
696  * @param[in] hostKey Pointer to the signer's host key
697  * @param[in] sessionId Session identifier (optional parameter)
698  * @param[in] message Pointer to the message to be signed
699  * @param[out] p Output stream where to write the signature
700  * @param[out] written Total number of bytes that have been written
701  * @return Error code
702  **/
703 
705  const char_t *publicKeyAlgo, const SshHostKey *hostKey,
707  uint8_t *p, size_t *written)
708 {
709 #if (SSH_ED448_SIGN_SUPPORT == ENABLED)
710  error_t error;
711  size_t n;
712  EddsaPrivateKey eddsaPrivateKey;
713  DataChunk messageChunks[4];
714  uint8_t temp[4];
715  uint8_t d[ED448_PRIVATE_KEY_LEN];
716 
717  //Initialize EdDSA private key
718  eddsaInitPrivateKey(&eddsaPrivateKey);
719 
720  //Import Ed448 private key
721  error = sshImportEd448PrivateKey(hostKey->privateKey,
722  hostKey->privateKeyLen, hostKey->password, &eddsaPrivateKey);
723 
724  //Check status code
725  if(!error)
726  {
727  //Retrieve raw private key
728  error = mpiExport(&eddsaPrivateKey.d, d, ED448_PRIVATE_KEY_LEN,
730  }
731 
732  //Check status code
733  if(!error)
734  {
735  //Valid session identifier?
736  if(sessionId != NULL)
737  {
738  //Encode the length of the session identifier as a 32-bit big-endian
739  //integer
740  STORE32BE(sessionId->length, temp);
741 
742  //Data to be signed is run through the EdDSA algorithm without
743  //pre-hashing
744  messageChunks[0].buffer = temp;
745  messageChunks[0].length = sizeof(temp);
746  messageChunks[1].buffer = sessionId->value;
747  messageChunks[1].length = sessionId->length;
748  messageChunks[2].buffer = message->value;
749  messageChunks[2].length = message->length;
750  messageChunks[3].buffer = NULL;
751  messageChunks[3].length = 0;
752  }
753  else
754  {
755  //The message fits in a single chunk
756  messageChunks[0].buffer = message->value;
757  messageChunks[0].length = message->length;
758  messageChunks[1].buffer = NULL;
759  messageChunks[1].length = 0;
760  }
761 
762  //Generate Ed448 signature (PureEdDSA mode)
763  error = ed448GenerateSignatureEx(d, NULL, messageChunks, NULL, 0, 0,
764  p + 4);
765 
766  //The Ed448 signature consists of 57 octets
768  }
769 
770  //Check status code
771  if(!error)
772  {
773  //The resulting EdDSA signature is encoded as a string
774  STORE32BE(n, p);
775  //Total number of bytes that have been written
776  *written = sizeof(uint32_t) + n;
777  }
778 
779  //Free previously allocated resources
780  eddsaFreePrivateKey(&eddsaPrivateKey);
781 
782  //Return status code
783  return error;
784 #else
785  //Not implemented
786  return ERROR_NOT_IMPLEMENTED;
787 #endif
788 }
789 
790 #endif
error_t sshGenerateEd448Signature(SshConnection *connection, const char_t *publicKeyAlgo, const SshHostKey *hostKey, const SshBinaryString *sessionId, const SshBinaryString *message, uint8_t *p, size_t *written)
Ed448 signature generation.
Mpi s
Definition: dsa.h:86
ECDSA signature.
Definition: ecdsa.h:49
HashAlgoInit init
Definition: crypto.h:1056
Generic hash algorithm context.
#define SHA256_HASH_ALGO
Definition: sha256.h:49
uint8_t sessionId[]
Definition: tls.h:1773
#define SHA1_HASH_ALGO
Definition: sha1.h:49
#define SECP521R1_CURVE
Definition: ec_curves.h:249
#define SHA512_HASH_ALGO
Definition: sha512.h:49
error_t ed25519GenerateSignatureEx(const uint8_t *privateKey, const uint8_t *publicKey, const DataChunk *messageChunks, const void *context, uint8_t contextLen, uint8_t flag, uint8_t *signature)
EdDSA signature generation.
Definition: ed25519.c:271
void sha1Update(Sha1Context *context, const void *data, size_t length)
Update the SHA-1 context with a portion of the message being hashed.
Binary string.
Definition: ssh_types.h:67
const char_t * privateKey
Private key (PEM or OpenSSH format)
Definition: ssh.h:1147
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
void ecInitDomainParameters(EcDomainParameters *params)
Initialize EC domain parameters.
Definition: ec.c:51
#define SECP384R1_CURVE
Definition: ec_curves.h:248
void eddsaFreePrivateKey(EddsaPrivateKey *key)
Release an EdDSA private key.
Definition: eddsa.c:89
void eddsaInitPrivateKey(EddsaPrivateKey *key)
Initialize an EdDSA private key.
Definition: eddsa.c:73
uint8_t p
Definition: ndp.h:300
uint8_t message[]
Definition: chap.h:154
Mpi q
Group order.
Definition: dsa.h:51
void dsaFreePrivateKey(DsaPrivateKey *key)
Release a DSA private key.
Definition: dsa.c:150
#define SECP256R1_CURVE
Definition: ec_curves.h:247
size_t digestSize
Definition: crypto.h:1052
const void * buffer
Definition: crypto.h:982
HashAlgoUpdate update
Definition: crypto.h:1057
#define ED448_SIGNATURE_LEN
Definition: ed448.h:44
Mpi r
Definition: dsa.h:85
char_t name[]
error_t sshImportEd25519PrivateKey(const char_t *input, size_t length, const char_t *password, EddsaPrivateKey *privateKey)
Decode an SSH private key file containing an Ed25519 private key.
#define ED25519_SIGNATURE_LEN
Definition: ed25519.h:44
#define osStrlen(s)
Definition: os_port.h:165
SSH key file import functions.
EC domain parameters.
Definition: ec.h:76
void ecFreeDomainParameters(EcDomainParameters *params)
Release EC domain parameters.
Definition: ec.c:72
RSA/DSA/ECDSA/EdDSA signature generation.
#define ED25519_PRIVATE_KEY_LEN
Definition: ed25519.h:40
void rsaInitPrivateKey(RsaPrivateKey *key)
Initialize an RSA private key.
Definition: rsa.c:131
char_t password[SSH_MAX_PASSWORD_LEN+1]
Password used to decrypt the private key.
Definition: ssh.h:1149
void ecdsaFreeSignature(EcdsaSignature *signature)
Release an ECDSA signature.
Definition: ecdsa.c:82
error_t ed448GenerateSignatureEx(const uint8_t *privateKey, const uint8_t *publicKey, const DataChunk *messageChunks, const void *context, uint8_t contextLen, uint8_t flag, uint8_t *signature)
EdDSA signature generation.
Definition: ed448.c:258
error_t ecLoadDomainParameters(EcDomainParameters *params, const EcCurveInfo *curveInfo)
Load EC domain parameters.
Definition: ec.c:90
Elliptic curve parameters.
Definition: ec_curves.h:302
error_t mpiExport(const Mpi *a, uint8_t *data, uint_t length, MpiFormat format)
Integer to octet string conversion.
Definition: mpi.c:709
void sha1Init(Sha1Context *context)
Initialize SHA-1 message digest context.
__weak_func error_t ecdsaGenerateSignature(const PrngAlgo *prngAlgo, void *prngContext, const EcDomainParameters *params, const EcPrivateKey *privateKey, const uint8_t *digest, size_t digestLen, EcdsaSignature *signature)
ECDSA signature generation.
Definition: ecdsa.c:397
#define SshContext
Definition: ssh.h:870
error_t sshGenerateSignature(SshConnection *connection, const char_t *publicKeyAlgo, const SshHostKey *hostKey, const SshBinaryString *sessionId, const SshBinaryString *message, uint8_t *p, size_t *written)
Signature generation.
@ MPI_FORMAT_LITTLE_ENDIAN
Definition: mpi.h:70
error_t
Error codes.
Definition: error.h:43
void dsaInitSignature(DsaSignature *signature)
Initialize a DSA signature.
Definition: dsa.c:164
void rsaFreePrivateKey(RsaPrivateKey *key)
Release an RSA private key.
Definition: rsa.c:153
bool_t sshCompareAlgo(const char_t *name1, const char_t *name2)
Compare algorithm names.
Definition: ssh_misc.c:1653
void ecdsaInitSignature(EcdsaSignature *signature)
Initialize an ECDSA signature.
Definition: ecdsa.c:69
error_t dsaGenerateSignature(const PrngAlgo *prngAlgo, void *prngContext, const DsaPrivateKey *key, const uint8_t *digest, size_t digestLen, DsaSignature *signature)
DSA signature generation.
Definition: dsa.c:484
uint8_t digest[MAX_HASH_DIGEST_SIZE]
void dsaInitPrivateKey(DsaPrivateKey *key)
Initialize a DSA private key.
Definition: dsa.c:133
Host key.
Definition: ssh.h:1143
error_t sshImportEd448PrivateKey(const char_t *input, size_t length, const char_t *password, EddsaPrivateKey *privateKey)
Decode an SSH private key file containing an Ed448 private key.
EC private key.
Definition: ec.h:104
DSA private key.
Definition: dsa.h:72
error_t sshGenerateDsaSignature(SshConnection *connection, const char_t *publicKeyAlgo, const SshHostKey *hostKey, const SshBinaryString *sessionId, const SshBinaryString *message, uint8_t *p, size_t *written)
DSA signature generation.
void ecFreePrivateKey(EcPrivateKey *key)
Release an EdDSA private key.
Definition: ec.c:192
String.
Definition: ssh_types.h:56
EdDSA private key.
Definition: eddsa.h:59
error_t sshFormatMpint(const Mpi *value, uint8_t *p, size_t *written)
Format a multiple precision integer.
Definition: ssh_misc.c:1487
HashAlgoFinal final
Definition: crypto.h:1058
Data chunk descriptor.
Definition: crypto.h:981
#define ED448_PRIVATE_KEY_LEN
Definition: ed448.h:40
error_t sshGenerateRsaSignature(SshConnection *connection, const char_t *publicKeyAlgo, const SshHostKey *hostKey, const SshBinaryString *sessionId, const SshBinaryString *message, uint8_t *p, size_t *written)
RSA signature generation.
#define SHA384_HASH_ALGO
Definition: sha384.h:45
char char_t
Definition: compiler_port.h:48
error_t sshGenerateEcdsaSignature(SshConnection *connection, const char_t *publicKeyAlgo, const SshHostKey *hostKey, const SshBinaryString *sessionId, const SshBinaryString *message, uint8_t *p, size_t *written)
ECDSA signature generation.
#define SHA1_DIGEST_SIZE
Definition: sha1.h:45
Mpi d
Private key.
Definition: eddsa.h:60
uint8_t n
RSA private key.
Definition: rsa.h:68
#define SshConnection
Definition: ssh.h:874
@ ERROR_UNKOWN_KEY
Definition: error.h:294
error_t sshImportEcdsaPrivateKey(const char_t *input, size_t length, const char_t *password, EcPrivateKey *privateKey)
Decode an SSH private key file containing an ECDSA private key.
Helper functions for signature generation and verification.
void dsaFreeSignature(DsaSignature *signature)
Release a DSA signature.
Definition: dsa.c:177
void ecInitPrivateKey(EcPrivateKey *key)
Initialize an EC private key.
Definition: ec.c:177
SSH helper functions.
@ MPI_FORMAT_BIG_ENDIAN
Definition: mpi.h:71
SHA-1 algorithm context.
Definition: sha1.h:62
error_t sshImportRsaPrivateKey(const char_t *input, size_t length, const char_t *password, RsaPrivateKey *privateKey)
Decode an SSH private key file containing an RSA private key.
size_t length
Definition: crypto.h:983
size_t privateKeyLen
Length of the private key.
Definition: ssh.h:1148
DsaDomainParameters params
DSA domain parameters.
Definition: dsa.h:73
Common interface for hash algorithms.
Definition: crypto.h:1046
error_t rsassaPkcs1v15Sign(const RsaPrivateKey *key, const HashAlgo *hash, const uint8_t *digest, uint8_t *signature, size_t *signatureLen)
RSASSA-PKCS1-v1_5 signature generation operation.
Definition: rsa.c:705
DSA signature.
Definition: dsa.h:84
error_t sshFormatString(const char_t *value, uint8_t *p, size_t *written)
Format a string.
Definition: ssh_misc.c:1384
@ ERROR_UNSUPPORTED_SIGNATURE_ALGO
Definition: error.h:132
void sha1Final(Sha1Context *context, uint8_t *digest)
Finish the SHA-1 message digest.
Secure Shell (SSH)
SSH algorithm negotiation.
error_t sshGenerateEd25519Signature(SshConnection *connection, const char_t *publicKeyAlgo, const SshHostKey *hostKey, const SshBinaryString *sessionId, const SshBinaryString *message, uint8_t *p, size_t *written)
Ed25519 signature generation.
error_t sshImportDsaPrivateKey(const char_t *input, size_t length, const char_t *password, DsaPrivateKey *privateKey)
Decode an SSH private key file containing a DSA private key.
#define STORE32BE(a, p)
Definition: cpu_endian.h:286
uint8_t digest[20]
Definition: sha1.h:66
Debugging facilities.
uint_t mpiGetByteLength(const Mpi *a)
Get the actual length in bytes.
Definition: mpi.c:195
const char_t * sshGetSignFormatId(const SshString *publicKeyAlgo)
Get the signature format identifier used by a given public key algorithm.