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-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_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  uint8_t digest[SSH_MAX_HASH_DIGEST_SIZE];
216 
217 #if (SSH_SHA1_SUPPORT == ENABLED)
218  //RSA with SHA-1 public key algorithm?
219  if(sshCompareAlgo(publicKeyAlgo, "ssh-rsa"))
220  {
221  //Select the relevant hash algorithm
222  hashAlgo = SHA1_HASH_ALGO;
223  }
224  else
225 #endif
226 #if (SSH_SHA256_SUPPORT == ENABLED)
227  //RSA with SHA-256 public key algorithm?
228  if(sshCompareAlgo(publicKeyAlgo, "rsa-sha2-256"))
229  {
230  //Select the relevant hash algorithm
231  hashAlgo = SHA256_HASH_ALGO;
232  }
233  else
234 #endif
235 #if (SSH_SHA512_SUPPORT == ENABLED)
236  //RSA with SHA-512 public key algorithm?
237  if(sshCompareAlgo(publicKeyAlgo, "rsa-sha2-512"))
238  {
239  //Select the relevant hash algorithm
240  hashAlgo = SHA512_HASH_ALGO;
241  }
242  else
243 #endif
244  //Unknown host key algorithm?
245  {
246  //Just for sanity
247  hashAlgo = NULL;
248  }
249 
250  //Make sure the hash algorithm is supported
251  if(hashAlgo != NULL)
252  {
253  RsaPrivateKey rsaPrivateKey;
254 
255  //Initialize RSA private key
256  rsaInitPrivateKey(&rsaPrivateKey);
257 
258  //Initialize hash context
259  hashAlgo->init(&hashContext);
260 
261  //Valid session identifier?
262  if(sessionId != NULL)
263  {
264  uint8_t temp[4];
265 
266  //Encode the length of the session identifier as a 32-bit big-endian
267  //integer
268  STORE32BE(sessionId->length, temp);
269 
270  //Digest the length field
271  hashAlgo->update(&hashContext, temp, sizeof(temp));
272  //Digest the session identifier
273  hashAlgo->update(&hashContext, sessionId->value, sessionId->length);
274  }
275 
276  //Digest the message
277  hashAlgo->update(&hashContext, message->value, message->length);
278  hashAlgo->final(&hashContext, digest);
279 
280  //Import RSA private key
281  error = sshImportRsaPrivateKey(&rsaPrivateKey, hostKey->privateKey,
282  hostKey->privateKeyLen, hostKey->password);
283 
284  //Check status code
285  if(!error)
286  {
287  //Generate RSA signature
288  error = rsassaPkcs1v15Sign(&rsaPrivateKey, hashAlgo, digest, p + 4,
289  &n);
290  }
291 
292  //Check status code
293  if(!error)
294  {
295  //The resulting RSA signature blob is encoded as a string
296  STORE32BE(n, p);
297  //Total number of bytes that have been written
298  *written = sizeof(uint32_t) + n;
299  }
300 
301  //Free previously allocated memory
302  rsaFreePrivateKey(&rsaPrivateKey);
303  }
304  else
305  {
306  //Report an error
308  }
309 
310  //Return status code
311  return error;
312 #else
313  //Not implemented
314  return ERROR_NOT_IMPLEMENTED;
315 #endif
316 }
317 
318 
319 /**
320  * @brief DSA signature generation
321  * @param[in] connection Pointer to the SSH connection
322  * @param[in] publicKeyAlgo Public key algorithm
323  * @param[in] hostKey Pointer to the signer's host key
324  * @param[in] sessionId Session identifier (optional parameter)
325  * @param[in] message Pointer to the message to be signed
326  * @param[out] p Output stream where to write the signature
327  * @param[out] written Total number of bytes that have been written
328  * @return Error code
329  **/
330 
332  const char_t *publicKeyAlgo, const SshHostKey *hostKey,
334  uint8_t *p, size_t *written)
335 {
336 #if (SSH_DSA_SIGN_SUPPORT == ENABLED)
337  error_t error;
338  size_t n;
339  SshContext *context;
340  DsaPrivateKey dsaPrivateKey;
341  DsaSignature dsaSignature;
342  Sha1Context sha1Context;
343  uint8_t digest[SHA1_DIGEST_SIZE];
344 
345  //Initialize variable
346  n = 0;
347 
348  //Point to the SSH context
349  context = connection->context;
350 
351  //Initialize DSA private key
352  dsaInitPrivateKey(&dsaPrivateKey);
353  //Initialize DSA signature
354  dsaInitSignature(&dsaSignature);
355 
356  //Initialize hash context
357  sha1Init(&sha1Context);
358 
359  //Valid session identifier?
360  if(sessionId != NULL)
361  {
362  uint8_t temp[4];
363 
364  //Encode the length of the session identifier as a 32-bit big-endian
365  //integer
366  STORE32BE(sessionId->length, temp);
367 
368  //Digest the length field
369  sha1Update(&sha1Context, temp, sizeof(temp));
370  //Digest the session identifier
371  sha1Update(&sha1Context, sessionId->value, sessionId->length);
372  }
373 
374  //Digest the message
375  sha1Update(&sha1Context, message->value, message->length);
376  sha1Final(&sha1Context, digest);
377 
378  //Import DSA private key
379  error = sshImportDsaPrivateKey(&dsaPrivateKey, hostKey->privateKey,
380  hostKey->privateKeyLen, hostKey->password);
381 
382  //Check status code
383  if(!error)
384  {
385  //Generate DSA signature
386  error = dsaGenerateSignature(context->prngAlgo, context->prngContext,
387  &dsaPrivateKey, digest, SHA1_DIGEST_SIZE, &dsaSignature);
388  }
389 
390  //Check status code
391  if(!error)
392  {
393  //The DSA signature blob contains R followed by S (which are 160-bit
394  //integers)
395  n = mpiGetByteLength(&dsaPrivateKey.params.q);
396 
397  //Encode integer R
398  error = mpiExport(&dsaSignature.r, p + 4, n, MPI_FORMAT_BIG_ENDIAN);
399  }
400 
401  //Check status code
402  if(!error)
403  {
404  //Encode integer S
405  error = mpiExport(&dsaSignature.s, p + n + 4, n, MPI_FORMAT_BIG_ENDIAN);
406  }
407 
408  //Check status code
409  if(!error)
410  {
411  //The resulting DSA signature blob is encoded as a string
412  STORE32BE(2 * n, p);
413  //Total number of bytes that have been written
414  *written = sizeof(uint32_t) + 2 * n;
415  }
416 
417  //Free previously allocated resources
418  dsaFreePrivateKey(&dsaPrivateKey);
419  dsaFreeSignature(&dsaSignature);
420 
421  //Return status code
422  return error;
423 #else
424  //Not implemented
425  return ERROR_NOT_IMPLEMENTED;
426 #endif
427 }
428 
429 
430 /**
431  * @brief ECDSA signature generation
432  * @param[in] connection Pointer to the SSH connection
433  * @param[in] publicKeyAlgo Public key algorithm
434  * @param[in] hostKey Pointer to the signer's host key
435  * @param[in] sessionId Session identifier (optional parameter)
436  * @param[in] message Pointer to the message to be signed
437  * @param[out] p Output stream where to write the signature
438  * @param[out] written Total number of bytes that have been written
439  * @return Error code
440  **/
441 
443  const char_t *publicKeyAlgo, const SshHostKey *hostKey,
445  uint8_t *p, size_t *written)
446 {
447 #if (SSH_ECDSA_SIGN_SUPPORT == ENABLED)
448  error_t error;
449  size_t rLen;
450  size_t sLen;
451  SshContext *context;
452  const EcCurve *curve;
453  const HashAlgo *hashAlgo;
454  HashContext hashContext;
455  uint8_t digest[SSH_MAX_HASH_DIGEST_SIZE];
456 
457  //Point to the SSH context
458  context = connection->context;
459 
460 #if (SSH_NISTP256_SUPPORT == ENABLED && SSH_SHA256_SUPPORT == ENABLED)
461  //ECDSA with NIST P-256 public key algorithm?
462  if(sshCompareAlgo(publicKeyAlgo, "ecdsa-sha2-nistp256"))
463  {
464  //Select the relevant curve and hash algorithm
465  curve = SECP256R1_CURVE;
466  hashAlgo = SHA256_HASH_ALGO;
467  }
468  else
469 #endif
470 #if (SSH_NISTP384_SUPPORT == ENABLED && SSH_SHA384_SUPPORT == ENABLED)
471  //ECDSA with NIST P-384 public key algorithm?
472  if(sshCompareAlgo(publicKeyAlgo, "ecdsa-sha2-nistp384"))
473  {
474  //Select the relevant curve and hash algorithm
475  curve = SECP384R1_CURVE;
476  hashAlgo = SHA384_HASH_ALGO;
477  }
478  else
479 #endif
480 #if (SSH_NISTP521_SUPPORT == ENABLED && SSH_SHA512_SUPPORT == ENABLED)
481  //ECDSA with NIST P-521 public key algorithm?
482  if(sshCompareAlgo(publicKeyAlgo, "ecdsa-sha2-nistp521"))
483  {
484  //Select the relevant curve and hash algorithm
485  curve = SECP521R1_CURVE;
486  hashAlgo = SHA512_HASH_ALGO;
487  }
488  else
489 #endif
490  //Unknown public key algorithm?
491  {
492  //Just for sanity
493  curve = NULL;
494  hashAlgo = NULL;
495  }
496 
497  //Valid parameters?
498  if(curve != NULL && hashAlgo != NULL)
499  {
500  EcPrivateKey ecPrivateKey;
501  EcdsaSignature ecdsaSignature;
502 
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, digest);
529 
530  //Import ECDSA private key
531  error = sshImportEcdsaPrivateKey(&ecPrivateKey, hostKey->privateKey,
532  hostKey->privateKeyLen, hostKey->password);
533 
534  //Check status code
535  if(!error)
536  {
537  //Generate ECDSA signature
538  error = ecdsaGenerateSignature(context->prngAlgo, context->prngContext,
539  &ecPrivateKey, digest, hashAlgo->digestSize, &ecdsaSignature);
540  }
541 
542  //Check status code
543  if(!error)
544  {
545  //Encode integer R
546  error = sshConvertScalarToMpint(ecdsaSignature.r, EC_MAX_ORDER_SIZE,
547  p + 4, &rLen);
548  }
549 
550  //Check status code
551  if(!error)
552  {
553  //Encode integer S
554  error = sshConvertScalarToMpint(ecdsaSignature.s, EC_MAX_ORDER_SIZE,
555  p + rLen + 4, &sLen);
556  }
557 
558  //Check status code
559  if(!error)
560  {
561  //The resulting ECDSA signature blob is encoded as a string
562  STORE32BE(rLen + sLen, p);
563  //Total number of bytes that have been written
564  *written = sizeof(uint32_t) + rLen + sLen;
565  }
566 
567  //Free previously allocated resources
568  ecFreePrivateKey(&ecPrivateKey);
569  ecdsaFreeSignature(&ecdsaSignature);
570  }
571  else
572  {
573  //Report an error
575  }
576 
577  //Return status code
578  return error;
579 #else
580  //Not implemented
581  return ERROR_NOT_IMPLEMENTED;
582 #endif
583 }
584 
585 
586 /**
587  * @brief Ed25519 signature generation
588  * @param[in] connection Pointer to the SSH connection
589  * @param[in] publicKeyAlgo Public key algorithm
590  * @param[in] hostKey Pointer to the signer's host key
591  * @param[in] sessionId Session identifier (optional parameter)
592  * @param[in] message Pointer to the message to be signed
593  * @param[out] p Output stream where to write the signature
594  * @param[out] written Total number of bytes that have been written
595  * @return Error code
596  **/
597 
599  const char_t *publicKeyAlgo, const SshHostKey *hostKey,
601  uint8_t *p, size_t *written)
602 {
603 #if (SSH_ED25519_SIGN_SUPPORT == ENABLED)
604  error_t error;
605  size_t n;
606  const uint8_t *q;
607  EddsaPrivateKey eddsaPrivateKey;
608  uint_t numMessageChunks;
609  DataChunk messageChunks[3];
610  uint8_t temp[4];
611 
612  //Initialize EdDSA private key
613  eddsaInitPrivateKey(&eddsaPrivateKey);
614 
615  //Import Ed25519 private key
616  error = sshImportEd25519PrivateKey(&eddsaPrivateKey, hostKey->privateKey,
617  hostKey->privateKeyLen, hostKey->password);
618 
619  //Check status code
620  if(!error)
621  {
622  //Valid session identifier?
623  if(sessionId != NULL)
624  {
625  //Encode the length of the session identifier as a 32-bit big-endian
626  //integer
627  STORE32BE(sessionId->length, temp);
628 
629  //Data to be signed is run through the EdDSA algorithm without
630  //pre-hashing
631  messageChunks[0].buffer = temp;
632  messageChunks[0].length = sizeof(temp);
633  messageChunks[1].buffer = sessionId->value;
634  messageChunks[1].length = sessionId->length;
635  messageChunks[2].buffer = message->value;
636  messageChunks[2].length = message->length;
637 
638  //Number of data chunks representing the message to be signed
639  numMessageChunks = 3;
640  }
641  else
642  {
643  //Data to be signed is run through the EdDSA algorithm without
644  //pre-hashing
645  messageChunks[0].buffer = message->value;
646  messageChunks[0].length = message->length;
647 
648  //The message fits in a single chunk
649  numMessageChunks = 1;
650  }
651 
652  //The public key is optional
653  q = (eddsaPrivateKey.q.curve != NULL) ? eddsaPrivateKey.q.q : NULL;
654 
655  //Generate Ed25519 signature (PureEdDSA mode)
656  error = ed25519GenerateSignatureEx(eddsaPrivateKey.d, q, messageChunks,
657  numMessageChunks, NULL, 0, 0, p + 4);
658  }
659 
660  //Check status code
661  if(!error)
662  {
663  //The Ed25519 signature consists of 32 octets
665  //The resulting EdDSA signature is encoded as a string
666  STORE32BE(n, p);
667  //Total number of bytes that have been written
668  *written = sizeof(uint32_t) + n;
669  }
670 
671  //Free previously allocated resources
672  eddsaFreePrivateKey(&eddsaPrivateKey);
673 
674  //Return status code
675  return error;
676 #else
677  //Not implemented
678  return ERROR_NOT_IMPLEMENTED;
679 #endif
680 }
681 
682 
683 /**
684  * @brief Ed448 signature generation
685  * @param[in] connection Pointer to the SSH connection
686  * @param[in] publicKeyAlgo Public key algorithm
687  * @param[in] hostKey Pointer to the signer's host key
688  * @param[in] sessionId Session identifier (optional parameter)
689  * @param[in] message Pointer to the message to be signed
690  * @param[out] p Output stream where to write the signature
691  * @param[out] written Total number of bytes that have been written
692  * @return Error code
693  **/
694 
696  const char_t *publicKeyAlgo, const SshHostKey *hostKey,
698  uint8_t *p, size_t *written)
699 {
700 #if (SSH_ED448_SIGN_SUPPORT == ENABLED)
701  error_t error;
702  size_t n;
703  const uint8_t *q;
704  EddsaPrivateKey eddsaPrivateKey;
705  uint_t numMessageChunks;
706  DataChunk messageChunks[3];
707  uint8_t temp[4];
708 
709  //Initialize EdDSA private key
710  eddsaInitPrivateKey(&eddsaPrivateKey);
711 
712  //Import Ed448 private key
713  error = sshImportEd448PrivateKey(&eddsaPrivateKey, hostKey->privateKey,
714  hostKey->privateKeyLen, hostKey->password);
715 
716  //Check status code
717  if(!error)
718  {
719  //Valid session identifier?
720  if(sessionId != NULL)
721  {
722  //Encode the length of the session identifier as a 32-bit big-endian
723  //integer
724  STORE32BE(sessionId->length, temp);
725 
726  //Data to be signed is run through the EdDSA algorithm without
727  //pre-hashing
728  messageChunks[0].buffer = temp;
729  messageChunks[0].length = sizeof(temp);
730  messageChunks[1].buffer = sessionId->value;
731  messageChunks[1].length = sessionId->length;
732  messageChunks[2].buffer = message->value;
733  messageChunks[2].length = message->length;
734 
735  //Number of data chunks representing the message to be signed
736  numMessageChunks = 3;
737  }
738  else
739  {
740  //Data to be signed is run through the EdDSA algorithm without
741  //pre-hashing
742  messageChunks[0].buffer = message->value;
743  messageChunks[0].length = message->length;
744 
745  //The message fits in a single chunk
746  numMessageChunks = 1;
747  }
748 
749  //The public key is optional
750  q = (eddsaPrivateKey.q.curve != NULL) ? eddsaPrivateKey.q.q : NULL;
751 
752  //Generate Ed448 signature (PureEdDSA mode)
753  error = ed448GenerateSignatureEx(eddsaPrivateKey.d, q, messageChunks,
754  numMessageChunks, NULL, 0, 0, p + 4);
755  }
756 
757  //Check status code
758  if(!error)
759  {
760  //The Ed448 signature consists of 57 octets
762  //The resulting EdDSA signature is encoded as a string
763  STORE32BE(n, p);
764  //Total number of bytes that have been written
765  *written = sizeof(uint32_t) + n;
766  }
767 
768  //Free previously allocated resources
769  eddsaFreePrivateKey(&eddsaPrivateKey);
770 
771  //Return status code
772  return error;
773 #else
774  //Not implemented
775  return ERROR_NOT_IMPLEMENTED;
776 #endif
777 }
778 
779 #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.
__weak_func error_t ecdsaGenerateSignature(const PrngAlgo *prngAlgo, void *prngContext, const EcPrivateKey *privateKey, const uint8_t *digest, size_t digestLen, EcdsaSignature *signature)
ECDSA signature generation.
Definition: ecdsa.c:509
Mpi s
Definition: dsa.h:87
error_t sshImportDsaPrivateKey(DsaPrivateKey *privateKey, const char_t *input, size_t length, const char_t *password)
Decode an SSH private key file containing a DSA private key.
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
#define SHA1_HASH_ALGO
Definition: sha1.h:49
error_t sshConvertScalarToMpint(const uint32_t *value, uint_t length, uint8_t *p, size_t *written)
Convert a scalar to mpint representation.
Definition: ssh_misc.c:1527
#define SECP521R1_CURVE
Definition: ec_curves.h:53
uint8_t d[EDDSA_MAX_PRIVATE_KEY_LEN]
Private key.
Definition: eddsa.h:77
#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.
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
#define SECP384R1_CURVE
Definition: ec_curves.h:52
void eddsaFreePrivateKey(EddsaPrivateKey *key)
Release an EdDSA private key.
Definition: eddsa.c:95
void eddsaInitPrivateKey(EddsaPrivateKey *key)
Initialize an EdDSA private key.
Definition: eddsa.c:75
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:152
#define SECP256R1_CURVE
Definition: ec_curves.h:51
size_t digestSize
Definition: crypto.h:1088
#define EC_MAX_ORDER_SIZE
Definition: ec.h:315
const void * buffer
Definition: crypto.h:1018
HashAlgoUpdate update
Definition: crypto.h:1093
#define ED448_SIGNATURE_LEN
Definition: ed448.h:44
Mpi r
Definition: dsa.h:86
char_t name[]
#define ED25519_SIGNATURE_LEN
Definition: ed25519.h:44
#define osStrlen(s)
Definition: os_port.h:168
SSH key file import functions.
RSA/DSA/ECDSA/EdDSA signature generation.
void rsaInitPrivateKey(RsaPrivateKey *key)
Initialize an RSA private key.
Definition: rsa.c:126
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:86
uint8_t q[EDDSA_MAX_PUBLIC_KEY_LEN]
Public key.
Definition: eddsa.h:66
void sha1Init(Sha1Context *context)
Initialize SHA-1 message digest context.
#define SshContext
Definition: ssh.h:870
error_t sshImportRsaPrivateKey(RsaPrivateKey *privateKey, const char_t *input, size_t length, const char_t *password)
Decode an SSH private key file containing an RSA private key.
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.
const EcCurve * curve
Elliptic curve parameters.
Definition: eddsa.h:65
error_t
Error codes.
Definition: error.h:43
void dsaInitSignature(DsaSignature *signature)
Initialize a DSA signature.
Definition: dsa.c:168
void rsaFreePrivateKey(RsaPrivateKey *key)
Release an RSA private key.
Definition: rsa.c:148
bool_t sshCompareAlgo(const char_t *name1, const char_t *name2)
Compare algorithm names.
Definition: ssh_misc.c:1693
void ecdsaInitSignature(EcdsaSignature *signature)
Initialize an ECDSA signature.
Definition: ecdsa.c:73
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:500
uint32_t r[EC_MAX_ORDER_SIZE]
Integer R.
Definition: ecdsa.h:65
void dsaInitPrivateKey(DsaPrivateKey *key)
Initialize a DSA private key.
Definition: dsa.c:133
Host key.
Definition: ssh.h:1143
error_t sshImportEd448PrivateKey(EddsaPrivateKey *privateKey, const char_t *input, size_t length, const char_t *password)
Decode an SSH private key file containing an Ed448 private key.
EC private key.
Definition: ec.h:432
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.
error_t mpiExport(const Mpi *a, uint8_t *output, size_t length, MpiFormat format)
Integer to octet string conversion.
Definition: mpi.c:809
void ecFreePrivateKey(EcPrivateKey *key)
Release an EC private key.
Definition: ec.c:100
String.
Definition: ssh_types.h:56
error_t sshImportEcdsaPrivateKey(EcPrivateKey *privateKey, const char_t *input, size_t length, const char_t *password)
Decode an SSH private key file containing an ECDSA private key.
#define SSH_MAX_HASH_DIGEST_SIZE
Definition: ssh.h:789
EdDSA private key.
Definition: eddsa.h:75
HashAlgoFinal final
Definition: crypto.h:1094
Data chunk descriptor.
Definition: crypto.h:1017
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:55
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
error_t ed25519GenerateSignatureEx(const uint8_t *privateKey, const uint8_t *publicKey, const DataChunk *message, uint_t messageLen, const void *context, uint8_t contextLen, uint8_t flag, uint8_t *signature)
EdDSA signature generation.
Definition: ed25519.c:268
uint8_t n
RSA private key.
Definition: rsa.h:68
#define SshConnection
Definition: ssh.h:874
@ ERROR_UNKOWN_KEY
Definition: error.h:295
Helper functions for signature generation and verification.
void dsaFreeSignature(DsaSignature *signature)
Release a DSA signature.
Definition: dsa.c:181
void ecInitPrivateKey(EcPrivateKey *key)
Initialize an EC private key.
Definition: ec.c:80
uint32_t s[EC_MAX_ORDER_SIZE]
Integer S.
Definition: ecdsa.h:66
SSH helper functions.
@ MPI_FORMAT_BIG_ENDIAN
Definition: mpi.h:93
SHA-1 algorithm context.
Definition: sha1.h:62
EddsaPublicKey q
Public key.
Definition: eddsa.h:79
error_t sshImportEd25519PrivateKey(EddsaPrivateKey *privateKey, const char_t *input, size_t length, const char_t *password)
Decode an SSH private key file containing an Ed25519 private key.
size_t length
Definition: crypto.h:1019
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:1082
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:935
error_t ed448GenerateSignatureEx(const uint8_t *privateKey, const uint8_t *publicKey, const DataChunk *message, uint_t messageLen, const void *context, uint8_t contextLen, uint8_t flag, uint8_t *signature)
EdDSA signature generation.
Definition: ed448.c:257
DSA signature.
Definition: dsa.h:85
#define EcCurve
Definition: ec.h:346
error_t sshFormatString(const char_t *value, uint8_t *p, size_t *written)
Format a string.
Definition: ssh_misc.c:1380
@ ERROR_UNSUPPORTED_SIGNATURE_ALGO
Definition: error.h:132
unsigned int uint_t
Definition: compiler_port.h:57
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.
#define STORE32BE(a, p)
Definition: cpu_endian.h:286
Debugging facilities.
uint_t mpiGetByteLength(const Mpi *a)
Get the actual length in bytes.
Definition: mpi.c:215
const char_t * sshGetSignFormatId(const SshString *publicKeyAlgo)
Get the signature format identifier used by a given public key algorithm.