ssh_key_export.c
Go to the documentation of this file.
1 /**
2  * @file ssh_key_export.c
3  * @brief SSH key file export functions
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2019-2026 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.6.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_key_export.h"
37 #include "ssh/ssh_key_parse.h"
38 #include "ssh/ssh_key_format.h"
39 #include "ssh/ssh_misc.h"
40 #include "encoding/base64.h"
41 #include "debug.h"
42 
43 //Check SSH stack configuration
44 #if (SSH_SUPPORT == ENABLED)
45 
46 
47 /**
48  * @brief Export an RSA public key to SSH public key file format
49  * @param[in] publicKey RSA public key
50  * @param[out] output Buffer where to store the SSH public key file (optional parameter)
51  * @param[out] written Length of the resulting SSH public key file
52  * @param[in] format Desired output format (SSH2 or OpenSSH format)
53  * @return Error code
54  **/
55 
57  char_t *output, size_t *written, SshPublicKeyFormat format)
58 {
59 #if (SSH_RSA_SIGN_SUPPORT == ENABLED)
60  error_t error;
61  size_t n;
62 
63  //Check parameters
64  if(publicKey == NULL || written == NULL)
66 
67  //Format RSA host key structure
68  error = sshFormatRsaPublicKey(publicKey, (uint8_t *) output, &n);
69  //Any error to report?
70  if(error)
71  return error;
72 
73  //Convert the host key structure to the desired format
74  error = sshEncodePublicKeyFile("ssh-rsa", output, n, output, &n, format);
75  //Any error to report?
76  if(error)
77  return error;
78 
79  //Total number of bytes that have been written
80  *written = n;
81 
82  //Successful processing
83  return NO_ERROR;
84 #else
85  //Not implemented
86  return ERROR_NOT_IMPLEMENTED;
87 #endif
88 }
89 
90 
91 /**
92  * @brief Export a DSA public key to SSH public key file format
93  * @param[in] publicKey DSA public key
94  * @param[out] output Buffer where to store the SSH public key file (optional parameter)
95  * @param[out] written Length of the resulting SSH public key file
96  * @param[in] format Desired output format (SSH2 or OpenSSH format)
97  * @return Error code
98  **/
99 
101  char_t *output, size_t *written, SshPublicKeyFormat format)
102 {
103 #if (SSH_DSA_SIGN_SUPPORT == ENABLED)
104  error_t error;
105  size_t n;
106 
107  //Check parameters
108  if(publicKey == NULL || written == NULL)
110 
111  //Format DSA host key structure
112  error = sshFormatDsaPublicKey(publicKey, (uint8_t *) output, &n);
113  //Any error to report?
114  if(error)
115  return error;
116 
117  //Convert the host key structure to the desired format
118  error = sshEncodePublicKeyFile("ssh-dss", output, n, output, &n, format);
119  //Any error to report?
120  if(error)
121  return error;
122 
123  //Total number of bytes that have been written
124  *written = n;
125 
126  //Successful processing
127  return NO_ERROR;
128 #else
129  //Not implemented
130  return ERROR_NOT_IMPLEMENTED;
131 #endif
132 }
133 
134 
135 /**
136  * @brief Export an ECDSA public key to SSH public key file format
137  * @param[in] publicKey ECDSA public key
138  * @param[out] output Buffer where to store the SSH public key file (optional parameter)
139  * @param[out] written Length of the resulting SSH public key file
140  * @param[in] format Desired output format (SSH2 or OpenSSH format)
141  * @return Error code
142  **/
143 
145  char_t *output, size_t *written, SshPublicKeyFormat format)
146 {
147 #if (SSH_ECDSA_SIGN_SUPPORT == ENABLED)
148  error_t error;
149  size_t n;
150  const char_t *keyFormatId;
151 
152  //Check parameters
153  if(publicKey == NULL || written == NULL)
155 
156  //Invalid ECDSA public key?
157  if(publicKey->curve == NULL)
159 
160  //Check elliptic curve
161  if(osStrcmp(publicKey->curve->name, "secp256r1") == 0)
162  {
163  //Select NIST P-256 elliptic curve
164  keyFormatId = "ecdsa-sha2-nistp256";
165  }
166  else if(osStrcmp(publicKey->curve->name, "secp384r1") == 0)
167  {
168  //Select NIST P-384 elliptic curve
169  keyFormatId = "ecdsa-sha2-nistp384";
170  }
171  else if(osStrcmp(publicKey->curve->name, "secp521r1") == 0)
172  {
173  //Select NIST P-521 elliptic curve
174  keyFormatId = "ecdsa-sha2-nistp521";
175  }
176  else
177  {
178  //Unknown host key algorithm
180  }
181 
182  //Format ECDSA host key structure
183  error = sshFormatEcdsaPublicKey(publicKey, (uint8_t *) output, &n);
184  //Any error to report?
185  if(error)
186  return error;
187 
188  //Convert the host key structure to the desired format
189  error = sshEncodePublicKeyFile(keyFormatId, output, n, output, &n, format);
190  //Any error to report?
191  if(error)
192  return error;
193 
194  //Total number of bytes that have been written
195  *written = n;
196 
197  //Successful processing
198  return NO_ERROR;
199 #else
200  //Not implemented
201  return ERROR_NOT_IMPLEMENTED;
202 #endif
203 }
204 
205 
206 /**
207  * @brief Export a Ed25519 public key to SSH public key file format
208  * @param[in] publicKey Ed25519 public key
209  * @param[out] output Buffer where to store the SSH public key file (optional parameter)
210  * @param[out] written Length of the resulting SSH public key file
211  * @param[in] format Desired output format (SSH2 or OpenSSH format)
212  * @return Error code
213  **/
214 
216  char_t *output, size_t *written, SshPublicKeyFormat format)
217 
218 {
219 #if (SSH_ED25519_SIGN_SUPPORT == ENABLED)
220  error_t error;
221  size_t n;
222 
223  //Check parameters
224  if(publicKey == NULL || written == NULL)
226 
227  //Format Ed25519 host key structure
228  error = sshFormatEd25519PublicKey(publicKey, (uint8_t *) output, &n);
229  //Any error to report?
230  if(error)
231  return error;
232 
233  //Convert the host key structure to the desired format
234  error = sshEncodePublicKeyFile("ssh-ed25519", output, n, output, &n, format);
235  //Any error to report?
236  if(error)
237  return error;
238 
239  //Total number of bytes that have been written
240  *written = n;
241 
242  //Successful processing
243  return NO_ERROR;
244 #else
245  //Not implemented
246  return ERROR_NOT_IMPLEMENTED;
247 #endif
248 }
249 
250 
251 /**
252  * @brief Export a Ed448 public key to SSH public key file format
253  * @param[in] publicKey Ed448 public key
254  * @param[out] output Buffer where to store the SSH public key file (optional parameter)
255  * @param[out] written Length of the resulting SSH public key file
256  * @param[in] format Desired output format (SSH2 or OpenSSH format)
257  * @return Error code
258  **/
259 
261  char_t *output, size_t *written, SshPublicKeyFormat format)
262 {
263 #if (SSH_ED448_SIGN_SUPPORT == ENABLED)
264  error_t error;
265  size_t n;
266 
267  //Check parameters
268  if(publicKey == NULL || written == NULL)
270 
271  //Format Ed448 host key structure
272  error = sshFormatEd448PublicKey(publicKey, (uint8_t *) output, &n);
273  //Any error to report?
274  if(error)
275  return error;
276 
277  //Convert the host key structure to the desired format
278  error = sshEncodePublicKeyFile("ssh-ed448", output, n, output, &n, format);
279  //Any error to report?
280  if(error)
281  return error;
282 
283  //Total number of bytes that have been written
284  *written = n;
285 
286  //Successful processing
287  return NO_ERROR;
288 #else
289  //Not implemented
290  return ERROR_NOT_IMPLEMENTED;
291 #endif
292 }
293 
294 
295 /**
296  * @brief Export a ML-DSA public key to SSH public key file format
297  * @param[in] publicKey ML-DSA public key
298  * @param[out] output Buffer where to store the SSH public key file (optional parameter)
299  * @param[out] written Length of the resulting SSH public key file
300  * @param[in] format Desired output format (SSH2 or OpenSSH format)
301  * @return Error code
302  **/
303 
305  char_t *output, size_t *written, SshPublicKeyFormat format)
306 {
307 #if (SSH_MLDSA44_SIGN_SUPPORT == ENABLED || SSH_MLDSA65_SIGN_SUPPORT == ENABLED || \
308  SSH_MLDSA87_SIGN_SUPPORT == ENABLED)
309  error_t error;
310  size_t n;
311  const char_t *keyFormatId;
312 
313  //Check parameters
314  if(publicKey == NULL || written == NULL)
316 
317  //Check security level
318  if(publicKey->level == MLDSA44_SECURITY_LEVEL)
319  {
320  //Select ML-DSA-44 parameter set
321  keyFormatId = "ssh-mldsa-44";
322  }
323  else if(publicKey->level == MLDSA65_SECURITY_LEVEL)
324  {
325  //Select ML-DSA-65 parameter set
326  keyFormatId = "ssh-mldsa-65";
327  }
328  else if(publicKey->level == MLDSA87_SECURITY_LEVEL)
329  {
330  //Select ML-DSA-87 parameter set
331  keyFormatId = "ssh-mldsa-87";
332  }
333  else
334  {
335  //Invalid security level
336  return ERROR_INVALID_KEY;
337  }
338 
339  //Format ML-DSA host key structure
340  error = sshFormatMldsaPublicKey(publicKey, (uint8_t *) output, &n);
341  //Any error to report?
342  if(error)
343  return error;
344 
345  //Convert the host key structure to the desired format
346  error = sshEncodePublicKeyFile(keyFormatId, output, n, output, &n, format);
347  //Any error to report?
348  if(error)
349  return error;
350 
351  //Total number of bytes that have been written
352  *written = n;
353 
354  //Successful processing
355  return NO_ERROR;
356 #else
357  //Not implemented
358  return ERROR_NOT_IMPLEMENTED;
359 #endif
360 }
361 
362 
363 /**
364  * @brief Export an RSA private key to SSH private key file format
365  * @param[in] privateKey RSA private key
366  * @param[out] output Buffer where to store the SSH private key file
367  * @param[out] written Length of the resulting SSH private key file
368  * @param[in] format Desired output format (OpenSSH format only)
369  * @return Error code
370  **/
371 
373  char_t *output, size_t *written, SshPrivateKeyFormat format)
374 {
375  error_t error;
376 
377  //Check output format
378  if(format == SSH_PRIVATE_KEY_FORMAT_OPENSSH ||
380  {
381  //Export RSA private key file (OpenSSH format)
382  error = sshExportOpenSshRsaPrivateKey(privateKey, output, written);
383  }
384  else
385  {
386  //Invalid format
387  error = ERROR_INVALID_PARAMETER;
388  }
389 
390  //Return error code
391  return error;
392 }
393 
394 
395 /**
396  * @brief Export a DSA private key to SSH private key file format
397  * @param[in] privateKey DSA private key
398  * @param[out] output Buffer where to store the SSH private key file
399  * @param[out] written Length of the resulting SSH private key file
400  * @param[in] format Desired output format (OpenSSH format only)
401  * @return Error code
402  **/
403 
405  char_t *output, size_t *written, SshPrivateKeyFormat format)
406 {
407  error_t error;
408 
409  //Check output format
410  if(format == SSH_PRIVATE_KEY_FORMAT_OPENSSH ||
412  {
413  //Export DSA private key file (OpenSSH format)
414  error = sshExportOpenSshDsaPrivateKey(privateKey, output, written);
415  }
416  else
417  {
418  //Invalid format
419  error = ERROR_INVALID_PARAMETER;
420  }
421 
422  //Return error code
423  return error;
424 }
425 
426 
427 /**
428  * @brief Export an ECDSA private key to SSH private key file format
429  * @param[in] privateKey ECDSA private key
430  * @param[out] output Buffer where to store the SSH private key file
431  * @param[out] written Length of the resulting SSH private key file
432  * @param[in] format Desired output format (OpenSSH format only)
433  * @return Error code
434  **/
435 
437  char_t *output, size_t *written, SshPrivateKeyFormat format)
438 {
439  error_t error;
440 
441  //Check output format
442  if(format == SSH_PRIVATE_KEY_FORMAT_OPENSSH ||
444  {
445  //Export ECDSA private key file (OpenSSH format)
446  error = sshExportOpenSshEcdsaPrivateKey(privateKey, output, written);
447  }
448  else
449  {
450  //Invalid format
451  error = ERROR_INVALID_PARAMETER;
452  }
453 
454  //Return error code
455  return error;
456 }
457 
458 
459 /**
460  * @brief Export an Ed25519 private key to SSH private key file format
461  * @param[in] privateKey Ed25519 private key
462  * @param[out] output Buffer where to store the SSH private key file
463  * @param[out] written Length of the resulting SSH private key file
464  * @param[in] format Desired output format (OpenSSH format only)
465  * @return Error code
466  **/
467 
469  char_t *output, size_t *written, SshPrivateKeyFormat format)
470 {
471  error_t error;
472 
473  //Check output format
474  if(format == SSH_PRIVATE_KEY_FORMAT_OPENSSH ||
476  {
477  //Export Ed25519 private key file (OpenSSH format)
478  error = sshExportOpenSshEd25519PrivateKey(privateKey, output, written);
479  }
480  else
481  {
482  //Invalid format
483  error = ERROR_INVALID_PARAMETER;
484  }
485 
486  //Return error code
487  return error;
488 }
489 
490 
491 /**
492  * @brief Export an Ed448 private key to SSH private key file format
493  * @param[in] privateKey Ed448 private key
494  * @param[out] output Buffer where to store the SSH private key file
495  * @param[out] written Length of the resulting SSH private key file
496  * @param[in] format Desired output format (OpenSSH format only)
497  * @return Error code
498  **/
499 
501  char_t *output, size_t *written, SshPrivateKeyFormat format)
502 {
503  error_t error;
504 
505  //Check output format
506  if(format == SSH_PRIVATE_KEY_FORMAT_OPENSSH ||
508  {
509  //Export Ed448 private key file (OpenSSH format)
510  error = sshExportOpenSshEd448PrivateKey(privateKey, output, written);
511  }
512  else
513  {
514  //Invalid format
515  error = ERROR_INVALID_PARAMETER;
516  }
517 
518  //Return error code
519  return error;
520 }
521 
522 
523 /**
524  * @brief Export an RSA private key to OpenSSH private key file format
525  * @param[in] privateKey RSA private key
526  * @param[out] output Buffer where to store the OpenSSH private key file
527  * @param[out] written Length of the resulting OpenSSH private key file
528  * @return Error code
529  **/
530 
532  char_t *output, size_t *written)
533 {
534 #if (SSH_RSA_SIGN_SUPPORT == ENABLED)
535  error_t error;
536  size_t n;
537  size_t length;
538  uint8_t *p;
539  RsaPublicKey publicKey;
540 
541  //Initialize variables
542  p = (uint8_t *) output;
543  length = 0;
544 
545  //Format private key header
547  //Any error to report?
548  if(error)
549  return error;
550 
551  //Point to the next field
552  p = SSH_INC_POINTER(p, n);
553  length += n;
554 
555  //The pair of numbers (n, e) form the RSA public key
556  publicKey.n = privateKey->n;
557  publicKey.e = privateKey->e;
558 
559  //Format 'publickey' field
560  error = sshFormatRsaPublicKey(&publicKey,
561  SSH_INC_POINTER(p, sizeof(uint32_t)), &n);
562  //Any error to report?
563  if(error)
564  return error;
565 
566  //The octet string value is preceded by a uint32 containing its length
567  if(p != NULL)
568  {
569  STORE32BE(n, p);
570  }
571 
572  //Point to the next field
573  p = SSH_INC_POINTER(p, sizeof(uint32_t) + n);
574  length += sizeof(uint32_t) + n;
575 
576  //Format 'encrypted' field
577  error = sshFormatOpenSshRsaPrivateKey(privateKey,
578  SSH_INC_POINTER(p, sizeof(uint32_t)), &n);
579  //Any error to report?
580  if(error)
581  return error;
582 
583  //The octet string value is preceded by a uint32 containing its length
584  if(p != NULL)
585  {
586  STORE32BE(n, p);
587  }
588 
589  //Total length of the private key structure
590  length += sizeof(uint32_t) + n;
591 
592  //Convert the private key structure to OpenSSH format
593  error = sshEncodeOpenSshPrivateKeyFile(output, length, output, &n);
594  //Any error to report?
595  if(error)
596  return error;
597 
598  //Total number of bytes that have been written
599  *written = n;
600 
601  //Successful processing
602  return NO_ERROR;
603 #else
604  //Not implemented
605  return ERROR_NOT_IMPLEMENTED;
606 #endif
607 }
608 
609 
610 /**
611  * @brief Export a DSA private key to OpenSSH private key file format
612  * @param[in] privateKey DSA private key
613  * @param[out] output Buffer where to store the OpenSSH private key file
614  * @param[out] written Length of the resulting OpenSSH private key file
615  * @return Error code
616  **/
617 
619  char_t *output, size_t *written)
620 {
621 #if (SSH_DSA_SIGN_SUPPORT == ENABLED)
622  error_t error;
623  size_t n;
624  size_t length;
625  uint8_t *p;
626  DsaPublicKey publicKey;
627 
628  //Initialize variables
629  p = (uint8_t *) output;
630  length = 0;
631 
632  //Format private key header
634  //Any error to report?
635  if(error)
636  return error;
637 
638  //Point to the next field
639  p = SSH_INC_POINTER(p, n);
640  length += n;
641 
642  //These four parameters (p, q, g and y) form the DSA public key
643  publicKey.params = privateKey->params;
644  publicKey.y = privateKey->y;
645 
646  //Format 'publickey' field
647  error = sshFormatDsaPublicKey(&publicKey,
648  SSH_INC_POINTER(p, sizeof(uint32_t)), &n);
649  //Any error to report?
650  if(error)
651  return error;
652 
653  //The octet string value is preceded by a uint32 containing its length
654  if(p != NULL)
655  {
656  STORE32BE(n, p);
657  }
658 
659  //Point to the next field
660  p = SSH_INC_POINTER(p, sizeof(uint32_t) + n);
661  length += sizeof(uint32_t) + n;
662 
663  //Format 'encrypted' field
664  error = sshFormatOpenSshDsaPrivateKey(privateKey,
665  SSH_INC_POINTER(p, sizeof(uint32_t)), &n);
666  //Any error to report?
667  if(error)
668  return error;
669 
670  //The octet string value is preceded by a uint32 containing its length
671  if(p != NULL)
672  {
673  STORE32BE(n, p);
674  }
675 
676  //Total length of the private key structure
677  length += sizeof(uint32_t) + n;
678 
679  //Convert the private key structure to OpenSSH format
680  error = sshEncodeOpenSshPrivateKeyFile(output, length, output, &n);
681  //Any error to report?
682  if(error)
683  return error;
684 
685  //Total number of bytes that have been written
686  *written = n;
687 
688  //Successful processing
689  return NO_ERROR;
690 #else
691  //Not implemented
692  return ERROR_NOT_IMPLEMENTED;
693 #endif
694 }
695 
696 
697 /**
698  * @brief Export an ECDSA private key to OpenSSH private key file format
699  * @param[in] privateKey ECDSA private key
700  * @param[out] output Buffer where to store the OpenSSH private key file
701  * @param[out] written Length of the resulting OpenSSH private key file
702  * @return Error code
703  **/
704 
706  char_t *output, size_t *written)
707 {
708 #if (SSH_ECDSA_SIGN_SUPPORT == ENABLED)
709  error_t error;
710  size_t n;
711  size_t length;
712  uint8_t *p;
713 
714  //Initialize variables
715  p = (uint8_t *) output;
716  length = 0;
717 
718  //Format private key header
720  //Any error to report?
721  if(error)
722  return error;
723 
724  //Point to the next field
725  p = SSH_INC_POINTER(p, n);
726  length += n;
727 
728  //Format 'publickey' field
729  error = sshFormatEcdsaPublicKey(&privateKey->q,
730  SSH_INC_POINTER(p, sizeof(uint32_t)), &n);
731  //Any error to report?
732  if(error)
733  return error;
734 
735  //The octet string value is preceded by a uint32 containing its length
736  if(p != NULL)
737  {
738  STORE32BE(n, p);
739  }
740 
741  //Point to the next field
742  p = SSH_INC_POINTER(p, sizeof(uint32_t) + n);
743  length += sizeof(uint32_t) + n;
744 
745  //Format 'encrypted' field
746  error = sshFormatOpenSshEcdsaPrivateKey(privateKey,
747  SSH_INC_POINTER(p, sizeof(uint32_t)), &n);
748  //Any error to report?
749  if(error)
750  return error;
751 
752  //The octet string value is preceded by a uint32 containing its length
753  if(p != NULL)
754  {
755  STORE32BE(n, p);
756  }
757 
758  //Total length of the private key structure
759  length += sizeof(uint32_t) + n;
760 
761  //Convert the private key structure to OpenSSH format
762  error = sshEncodeOpenSshPrivateKeyFile(output, length, output, &n);
763  //Any error to report?
764  if(error)
765  return error;
766 
767  //Total number of bytes that have been written
768  *written = n;
769 
770  //Successful processing
771  return NO_ERROR;
772 #else
773  //Not implemented
774  return ERROR_NOT_IMPLEMENTED;
775 #endif
776 }
777 
778 
779 /**
780  * @brief Export an Ed25519 private key to OpenSSH private key file format
781  * @param[in] privateKey Ed25519 private key
782  * @param[out] output Buffer where to store the OpenSSH private key file
783  * @param[out] written Length of the resulting OpenSSH private key file
784  * @return Error code
785  **/
786 
788  char_t *output, size_t *written)
789 {
790 #if (SSH_ED25519_SIGN_SUPPORT == ENABLED)
791  error_t error;
792  size_t n;
793  size_t length;
794  uint8_t *p;
795 
796  //Initialize variables
797  p = (uint8_t *) output;
798  length = 0;
799 
800  //Format private key header
802  //Any error to report?
803  if(error)
804  return error;
805 
806  //Point to the next field
807  p = SSH_INC_POINTER(p, n);
808  length += n;
809 
810  //Format 'publickey' field
811  error = sshFormatEd25519PublicKey(&privateKey->q,
812  SSH_INC_POINTER(p, sizeof(uint32_t)), &n);
813  //Any error to report?
814  if(error)
815  return error;
816 
817  //The octet string value is preceded by a uint32 containing its length
818  if(p != NULL)
819  {
820  STORE32BE(n, p);
821  }
822 
823  //Point to the next field
824  p = SSH_INC_POINTER(p, sizeof(uint32_t) + n);
825  length += sizeof(uint32_t) + n;
826 
827  //Format 'encrypted' field
828  error = sshFormatOpenSshEd25519PrivateKey(privateKey,
829  SSH_INC_POINTER(p, sizeof(uint32_t)), &n);
830  //Any error to report?
831  if(error)
832  return error;
833 
834  //The octet string value is preceded by a uint32 containing its length
835  if(p != NULL)
836  {
837  STORE32BE(n, p);
838  }
839 
840  //Total length of the private key structure
841  length += sizeof(uint32_t) + n;
842 
843  //Convert the private key structure to OpenSSH format
844  error = sshEncodeOpenSshPrivateKeyFile(output, length, output, &n);
845  //Any error to report?
846  if(error)
847  return error;
848 
849  //Total number of bytes that have been written
850  *written = n;
851 
852  //Successful processing
853  return NO_ERROR;
854 #else
855  //Not implemented
856  return ERROR_NOT_IMPLEMENTED;
857 #endif
858 }
859 
860 
861 /**
862  * @brief Export an Ed448 private key to OpenSSH private key file format
863  * @param[in] privateKey Ed448 private key
864  * @param[out] output Buffer where to store the OpenSSH private key file
865  * @param[out] written Length of the resulting OpenSSH private key file
866  * @return Error code
867  **/
868 
870  char_t *output, size_t *written)
871 {
872 #if (SSH_ED448_SIGN_SUPPORT == ENABLED)
873  error_t error;
874  size_t n;
875  size_t length;
876  uint8_t *p;
877 
878  //Initialize variables
879  p = (uint8_t *) output;
880  length = 0;
881 
882  //Format private key header
884  //Any error to report?
885  if(error)
886  return error;
887 
888  //Point to the next field
889  p = SSH_INC_POINTER(p, n);
890  length += n;
891 
892  //Format 'publickey' field
893  error = sshFormatEd448PublicKey(&privateKey->q,
894  SSH_INC_POINTER(p, sizeof(uint32_t)), &n);
895  //Any error to report?
896  if(error)
897  return error;
898 
899  //The octet string value is preceded by a uint32 containing its length
900  if(p != NULL)
901  {
902  STORE32BE(n, p);
903  }
904 
905  //Point to the next field
906  p = SSH_INC_POINTER(p, sizeof(uint32_t) + n);
907  length += sizeof(uint32_t) + n;
908 
909  //Format 'encrypted' field
910  error = sshFormatOpenSshEd448PrivateKey(privateKey,
911  SSH_INC_POINTER(p, sizeof(uint32_t)), &n);
912  //Any error to report?
913  if(error)
914  return error;
915 
916  //The octet string value is preceded by a uint32 containing its length
917  if(p != NULL)
918  {
919  STORE32BE(n, p);
920  }
921 
922  //Total length of the private key structure
923  length += sizeof(uint32_t) + n;
924 
925  //Convert the private key structure to OpenSSH format
926  error = sshEncodeOpenSshPrivateKeyFile(output, length, output, &n);
927  //Any error to report?
928  if(error)
929  return error;
930 
931  //Total number of bytes that have been written
932  *written = n;
933 
934  //Successful processing
935  return NO_ERROR;
936 #else
937  //Not implemented
938  return ERROR_NOT_IMPLEMENTED;
939 #endif
940 }
941 
942 
943 /**
944  * @brief Encode SSH public key file (SSH2 or OpenSSH format)
945  * @param[in] keyFormatId Key format identifier
946  * @param[in] input Host key structure to encode
947  * @param[in] inputLen Length of the host key structure to encode
948  * @param[out] output SSH public key file (optional parameter)
949  * @param[out] outputLen Length of the SSH public key file
950  * @param[in] format Desired output format (SSH2 or OpenSSH format)
951  **/
952 
953 error_t sshEncodePublicKeyFile(const char_t *keyFormatId, const void *input,
954  size_t inputLen, char_t *output, size_t *outputLen, SshPublicKeyFormat format)
955 {
956  error_t error;
957 
958  //Check output format
959  if(format == SSH_PUBLIC_KEY_FORMAT_SSH2)
960  {
961  //Encode SSH public key file (SSH2 format)
962  error = sshEncodeSsh2PublicKeyFile(input, inputLen, output, outputLen);
963  }
964  else if(format == SSH_PUBLIC_KEY_FORMAT_OPENSSH ||
966  {
967  //Encode SSH public key file (OpenSSH format)
968  error = sshEncodeOpenSshPublicKeyFile(keyFormatId, input, inputLen,
969  output, outputLen);
970  }
971  else
972  {
973  //Invalid format
974  error = ERROR_INVALID_PARAMETER;
975  }
976 
977  //Return error code
978  return error;
979 }
980 
981 
982 /**
983  * @brief Encode SSH public key file (SSH2 format)
984  * @param[in] input Host key structure to encode
985  * @param[in] inputLen Length of the host key structure to encode
986  * @param[out] output SSH public key file (optional parameter)
987  * @param[out] outputLen Length of the SSH public key file
988  **/
989 
990 error_t sshEncodeSsh2PublicKeyFile(const void *input, size_t inputLen,
991  char_t *output, size_t *outputLen)
992 {
993  size_t n;
994 
995  //Check parameters
996  if(outputLen == NULL)
998 
999  //Sanity check
1000  if(input == NULL && output != NULL)
1001  return ERROR_INVALID_PARAMETER;
1002 
1003  //Each line in the body must not be longer than 72 8-bit bytes excluding
1004  //line termination characters (refer to RFC 4716, section 3.4)
1005  base64EncodeMultiline(input, inputLen, output, &n, 70);
1006 
1007  //If the output parameter is NULL, then the function calculates the length
1008  //of the resulting SSH public key file without copying any data
1009  if(output != NULL)
1010  {
1011  //Make room for the begin marker
1012  osMemmove(output + 33, output, n);
1013 
1014  //The first line of a conforming key file must be a begin marker (refer
1015  //to RFC 4716, section 3.2)
1016  osMemcpy(output, "---- BEGIN SSH2 PUBLIC KEY ----\r\n", 33);
1017 
1018  //The last line of a conforming key file must be an end marker (refer to
1019  //RFC 4716, section 3.2)
1020  osStrcpy(output + n + 33, "\r\n---- END SSH2 PUBLIC KEY ----\r\n");
1021  }
1022 
1023  //Consider the length of the markers
1024  n += osStrlen("---- BEGIN SSH2 PUBLIC KEY ----\r\n");
1025  n += osStrlen("\r\n---- END SSH2 PUBLIC KEY ----\r\n");
1026 
1027  //Total number of bytes that have been written
1028  *outputLen = n;
1029 
1030  //Successful processing
1031  return NO_ERROR;
1032 }
1033 
1034 
1035 /**
1036  * @brief Encode SSH public key file (OpenSSH format)
1037  * @param[in] keyFormatId Key format identifier
1038  * @param[in] input Host key structure to encode
1039  * @param[in] inputLen Length of the host key structure to encode
1040  * @param[out] output SSH public key file (optional parameter)
1041  * @param[out] outputLen Length of the SSH public key file
1042  **/
1043 
1045  const void *input, size_t inputLen, char_t *output, size_t *outputLen)
1046 {
1047  size_t n;
1048  size_t keyFormatIdLen;
1049 
1050  //Check parameters
1051  if(keyFormatId == NULL || outputLen == NULL)
1052  return ERROR_INVALID_PARAMETER;
1053 
1054  //Sanity check
1055  if(input == NULL && output != NULL)
1056  return ERROR_INVALID_PARAMETER;
1057 
1058  //Get the length of the key format identifier
1059  keyFormatIdLen = osStrlen(keyFormatId);
1060 
1061  //Encode the host key structure using Base64
1062  base64Encode(input, inputLen, output, &n);
1063 
1064  //If the output parameter is NULL, then the function calculates the length
1065  //of the resulting certificate file without copying any data
1066  if(output != NULL)
1067  {
1068  //Make room for the identifier string
1069  osMemmove(output + keyFormatIdLen + 1, output, n + 1);
1070  //Copy identifier string
1071  osMemcpy(output, keyFormatId, keyFormatIdLen);
1072  //The identifier must be followed by a whitespace character
1073  output[keyFormatIdLen] = ' ';
1074  }
1075 
1076  //Consider the length of the identifier string
1077  n += keyFormatIdLen + 1;
1078 
1079  //Total number of bytes that have been written
1080  *outputLen = n;
1081 
1082  //Successful processing
1083  return NO_ERROR;
1084 }
1085 
1086 
1087 /**
1088  * @brief Encode SSH private key file (OpenSSH format)
1089  * @param[in] input Private key structure to encode
1090  * @param[in] inputLen Length of the private key structure to encode
1091  * @param[out] output SSH private key file (optional parameter)
1092  * @param[out] outputLen Length of the SSH private key file
1093  **/
1094 
1095 error_t sshEncodeOpenSshPrivateKeyFile(const void *input, size_t inputLen,
1096  char_t *output, size_t *outputLen)
1097 {
1098  size_t n;
1099 
1100  //Check parameters
1101  if(outputLen == NULL)
1102  return ERROR_INVALID_PARAMETER;
1103 
1104  //Sanity check
1105  if(input == NULL && output != NULL)
1106  return ERROR_INVALID_PARAMETER;
1107 
1108  //Encode the private key structure using Base64
1109  base64EncodeMultiline(input, inputLen, output, &n, 70);
1110 
1111  //If the output parameter is NULL, then the function calculates the length
1112  //of the resulting SSH private key file without copying any data
1113  if(output != NULL)
1114  {
1115  //Make room for the begin marker
1116  osMemmove(output + 37, output, n);
1117 
1118  //The first line of the private key file must be a begin marker
1119  osMemcpy(output, "-----BEGIN OPENSSH PRIVATE KEY-----\r\n", 37);
1120 
1121  //The last line of the private key file must be an end marker
1122  osStrcpy(output + n + 37, "\r\n-----END OPENSSH PRIVATE KEY-----\r\n");
1123  }
1124 
1125  //Consider the length of the markers
1126  n += osStrlen("-----BEGIN OPENSSH PRIVATE KEY-----\r\n");
1127  n += osStrlen("\r\n-----END OPENSSH PRIVATE KEY-----\r\n");
1128 
1129  //Total number of bytes that have been written
1130  *outputLen = n;
1131 
1132  //Successful processing
1133  return NO_ERROR;
1134 }
1135 
1136 #endif
@ SSH_PRIVATE_KEY_FORMAT_DEFAULT
Default private key format.
@ ERROR_UNSUPPORTED_ELLIPTIC_CURVE
Definition: error.h:133
error_t sshFormatOpenSshPrivateKeyHeader(uint8_t *p, size_t *written)
Format private key header (OpenSSH format)
error_t sshFormatOpenSshEd25519PrivateKey(const EddsaPrivateKey *privateKey, uint8_t *p, size_t *written)
Format Ed25519 private key blob (OpenSSH format)
error_t sshFormatOpenSshEcdsaPrivateKey(const EcPrivateKey *privateKey, uint8_t *p, size_t *written)
Format ECDSA private key blob (OpenSSH format)
error_t sshExportEd25519PrivateKey(const EddsaPrivateKey *privateKey, char_t *output, size_t *written, SshPrivateKeyFormat format)
Export an Ed25519 private key to SSH private key file format.
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
error_t sshFormatOpenSshRsaPrivateKey(const RsaPrivateKey *privateKey, uint8_t *p, size_t *written)
Format RSA private key blob (OpenSSH format)
uint8_t p
Definition: ndp.h:300
void base64Encode(const void *input, size_t inputLen, char_t *output, size_t *outputLen)
Base64 encoding algorithm.
Definition: base64.c:142
Mpi n
Modulus.
Definition: rsa.h:69
error_t sshExportRsaPublicKey(const RsaPublicKey *publicKey, char_t *output, size_t *written, SshPublicKeyFormat format)
Export an RSA public key to SSH public key file format.
#define MLDSA87_SECURITY_LEVEL
Definition: mldsa.h:61
error_t sshFormatOpenSshEd448PrivateKey(const EddsaPrivateKey *privateKey, uint8_t *p, size_t *written)
Format Ed448 private key blob (OpenSSH format)
error_t sshExportEcdsaPublicKey(const EcPublicKey *publicKey, char_t *output, size_t *written, SshPublicKeyFormat format)
Export an ECDSA public key to SSH public key file format.
#define osStrcmp(s1, s2)
Definition: os_port.h:177
SSH key parsing.
Mpi e
Public exponent.
Definition: rsa.h:59
#define osStrlen(s)
Definition: os_port.h:171
#define MLDSA65_SECURITY_LEVEL
Definition: mldsa.h:50
error_t sshExportOpenSshRsaPrivateKey(const RsaPrivateKey *privateKey, char_t *output, size_t *written)
Export an RSA private key to OpenSSH private key file format.
error_t sshFormatEd448PublicKey(const EddsaPublicKey *publicKey, uint8_t *p, size_t *written)
Format an Ed448 public host key.
void base64EncodeMultiline(const void *input, size_t inputLen, char_t *output, size_t *outputLen, size_t lineWidth)
Base64 multiline encoding.
Definition: base64.c:79
Mpi n
Modulus.
Definition: rsa.h:58
error_t sshFormatRsaPublicKey(const RsaPublicKey *publicKey, uint8_t *p, size_t *written)
Format an RSA public host key.
error_t sshExportOpenSshEd448PrivateKey(const EddsaPrivateKey *privateKey, char_t *output, size_t *written)
Export an Ed448 private key to OpenSSH private key file format.
error_t sshExportOpenSshEcdsaPrivateKey(const EcPrivateKey *privateKey, char_t *output, size_t *written)
Export an ECDSA private key to OpenSSH private key file format.
#define MLDSA44_SECURITY_LEVEL
Definition: mldsa.h:39
ML-DSA public key.
Definition: mldsa.h:82
DSA public key.
Definition: dsa.h:61
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
SshPublicKeyFormat
SSH public key formats.
#define osMemcpy(dest, src, length)
Definition: os_port.h:147
error_t
Error codes.
Definition: error.h:43
EdDSA public key.
Definition: eddsa.h:64
error_t sshExportDsaPrivateKey(const DsaPrivateKey *privateKey, char_t *output, size_t *written, SshPrivateKeyFormat format)
Export a DSA private key to SSH private key file format.
@ SSH_PUBLIC_KEY_FORMAT_OPENSSH
OpenSSH public key format.
error_t sshFormatOpenSshDsaPrivateKey(const DsaPrivateKey *privateKey, uint8_t *p, size_t *written)
Format DSA private key blob (OpenSSH format)
RSA public key.
Definition: rsa.h:57
#define SSH_INC_POINTER(p, n)
@ SSH_PRIVATE_KEY_FORMAT_OPENSSH
OpenSSH private key format.
error_t sshFormatEd25519PublicKey(const EddsaPublicKey *publicKey, uint8_t *p, size_t *written)
Format an Ed25519 public host key.
error_t sshExportMldsaPublicKey(const MldsaPublicKey *publicKey, char_t *output, size_t *written, SshPublicKeyFormat format)
Export a ML-DSA public key to SSH public key file format.
Mpi y
Public key value.
Definition: dsa.h:75
EcPublicKey q
Public key.
Definition: ec.h:436
error_t sshFormatMldsaPublicKey(const MldsaPublicKey *publicKey, uint8_t *p, size_t *written)
Format an ML-DSA public host key.
error_t sshEncodeOpenSshPrivateKeyFile(const void *input, size_t inputLen, char_t *output, size_t *outputLen)
Encode SSH private key file (OpenSSH format)
Base64 encoding scheme.
EC private key.
Definition: ec.h:432
DsaDomainParameters params
DSA domain parameters.
Definition: dsa.h:62
DSA private key.
Definition: dsa.h:72
SSH key formatting.
uint8_t length
Definition: tcp.h:375
Mpi e
Public exponent.
Definition: rsa.h:70
error_t sshExportOpenSshEd25519PrivateKey(const EddsaPrivateKey *privateKey, char_t *output, size_t *written)
Export an Ed25519 private key to OpenSSH private key file format.
error_t sshEncodePublicKeyFile(const char_t *keyFormatId, const void *input, size_t inputLen, char_t *output, size_t *outputLen, SshPublicKeyFormat format)
Encode SSH public key file (SSH2 or OpenSSH format)
error_t sshExportEcdsaPrivateKey(const EcPrivateKey *privateKey, char_t *output, size_t *written, SshPrivateKeyFormat format)
Export an ECDSA private key to SSH private key file format.
error_t sshFormatDsaPublicKey(const DsaPublicKey *publicKey, uint8_t *p, size_t *written)
Format a DSA public host key.
EdDSA private key.
Definition: eddsa.h:75
error_t sshExportRsaPrivateKey(const RsaPrivateKey *privateKey, char_t *output, size_t *written, SshPrivateKeyFormat format)
Export an RSA private key to SSH private key file format.
EC public key.
Definition: ec.h:421
char char_t
Definition: compiler_port.h:55
@ SSH_PUBLIC_KEY_FORMAT_SSH2
SSH2 public key format.
uint8_t n
RSA private key.
Definition: rsa.h:68
SshPrivateKeyFormat
SSH private key formats.
error_t sshExportDsaPublicKey(const DsaPublicKey *publicKey, char_t *output, size_t *written, SshPublicKeyFormat format)
Export a DSA public key to SSH public key file format.
SSH helper functions.
Mpi y
Public key value.
Definition: dsa.h:63
error_t sshEncodeOpenSshPublicKeyFile(const char_t *keyFormatId, const void *input, size_t inputLen, char_t *output, size_t *outputLen)
Encode SSH public key file (OpenSSH format)
EddsaPublicKey q
Public key.
Definition: eddsa.h:79
@ SSH_PUBLIC_KEY_FORMAT_DEFAULT
Default public key format.
DsaDomainParameters params
DSA domain parameters.
Definition: dsa.h:73
@ ERROR_UNSUPPORTED_SIGNATURE_ALGO
Definition: error.h:132
error_t sshEncodeSsh2PublicKeyFile(const void *input, size_t inputLen, char_t *output, size_t *outputLen)
Encode SSH public key file (SSH2 format)
uint_t level
Security level.
Definition: mldsa.h:83
error_t sshExportEd448PublicKey(const EddsaPublicKey *publicKey, char_t *output, size_t *written, SshPublicKeyFormat format)
Export a Ed448 public key to SSH public key file format.
Secure Shell (SSH)
error_t sshExportEd25519PublicKey(const EddsaPublicKey *publicKey, char_t *output, size_t *written, SshPublicKeyFormat format)
Export a Ed25519 public key to SSH public key file format.
#define osStrcpy(s1, s2)
Definition: os_port.h:213
const EcCurve * curve
Elliptic curve parameters.
Definition: ec.h:422
error_t sshExportOpenSshDsaPrivateKey(const DsaPrivateKey *privateKey, char_t *output, size_t *written)
Export a DSA private key to OpenSSH private key file format.
#define STORE32BE(a, p)
Definition: cpu_endian.h:286
@ ERROR_INVALID_KEY
Definition: error.h:106
error_t sshFormatEcdsaPublicKey(const EcPublicKey *publicKey, uint8_t *p, size_t *written)
Format an ECDSA public host key.
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
#define osMemmove(dest, src, length)
Definition: os_port.h:153
SSH key file export functions.
error_t sshExportEd448PrivateKey(const EddsaPrivateKey *privateKey, char_t *output, size_t *written, SshPrivateKeyFormat format)
Export an Ed448 private key to SSH private key file format.