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-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneSSH Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL SSH_TRACE_LEVEL
33 
34 //Dependencies
35 #include "ssh/ssh.h"
36 #include "ssh/ssh_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
51  * @param[out] written Length of the resulting SSH public key file
52  * @param[in] format Desired output format (SSH2 or OpenSSH)
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(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
95  * @param[out] written Length of the resulting SSH public key file
96  * @param[in] format Desired output format (SSH2 or OpenSSH)
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(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] params EC domain parameters
138  * @param[in] publicKey ECDSA public key
139  * @param[out] output Buffer where to store the SSH public key file
140  * @param[out] written Length of the resulting SSH public key file
141  * @param[in] format Desired output format (SSH2 or OpenSSH)
142  * @return Error code
143  **/
144 
146  const EcPublicKey *publicKey, char_t *output, size_t *written,
147  SshPublicKeyFormat format)
148 {
149 #if (SSH_ECDSA_SIGN_SUPPORT == ENABLED)
150  error_t error;
151  size_t n;
152 
153  //Check parameters
154  if(publicKey == NULL || written == NULL)
156 
157  //Format ECDSA host key structure
158  error = sshFormatEcdsaPublicKey(params, publicKey, (uint8_t *) output, &n);
159  //Any error to report?
160  if(error)
161  return error;
162 
163  //Convert the host key structure to the desired format
164  error = sshEncodePublicKeyFile(output, n, output, &n, format);
165  //Any error to report?
166  if(error)
167  return error;
168 
169  //Total number of bytes that have been written
170  *written = n;
171 
172  //Successful processing
173  return NO_ERROR;
174 #else
175  //Not implemented
176  return ERROR_NOT_IMPLEMENTED;
177 #endif
178 }
179 
180 
181 /**
182  * @brief Export a Ed25519 public key to SSH public key file format
183  * @param[in] publicKey Ed25519 public key
184  * @param[out] output Buffer where to store the SSH public key file
185  * @param[out] written Length of the resulting SSH public key file
186  * @param[in] format Desired output format (SSH2 or OpenSSH)
187  * @return Error code
188  **/
189 
191  char_t *output, size_t *written, SshPublicKeyFormat format)
192 
193 {
194 #if (SSH_ED25519_SIGN_SUPPORT == ENABLED)
195  error_t error;
196  size_t n;
197 
198  //Check parameters
199  if(publicKey == NULL || written == NULL)
201 
202  //Format Ed25519 host key structure
203  error = sshFormatEd25519PublicKey(publicKey, (uint8_t *) output, &n);
204  //Any error to report?
205  if(error)
206  return error;
207 
208  //Convert the host key structure to the desired format
209  error = sshEncodePublicKeyFile(output, n, output, &n, format);
210  //Any error to report?
211  if(error)
212  return error;
213 
214  //Total number of bytes that have been written
215  *written = n;
216 
217  //Successful processing
218  return NO_ERROR;
219 #else
220  //Not implemented
221  return ERROR_NOT_IMPLEMENTED;
222 #endif
223 }
224 
225 
226 /**
227  * @brief Export a Ed448 public key to SSH public key file format
228  * @param[in] publicKey Ed448 public key
229  * @param[out] output Buffer where to store the SSH public key file
230  * @param[out] written Length of the resulting SSH public key file
231  * @param[in] format Desired output format (SSH2 or OpenSSH)
232  * @return Error code
233  **/
234 
236  char_t *output, size_t *written, SshPublicKeyFormat format)
237 {
238 #if (SSH_ED448_SIGN_SUPPORT == ENABLED)
239  error_t error;
240  size_t n;
241 
242  //Check parameters
243  if(publicKey == NULL || written == NULL)
245 
246  //Format Ed448 host key structure
247  error = sshFormatEd448PublicKey(publicKey, (uint8_t *) output, &n);
248  //Any error to report?
249  if(error)
250  return error;
251 
252  //Convert the host key structure to the desired format
253  error = sshEncodePublicKeyFile(output, n, output, &n, format);
254  //Any error to report?
255  if(error)
256  return error;
257 
258  //Total number of bytes that have been written
259  *written = n;
260 
261  //Successful processing
262  return NO_ERROR;
263 #else
264  //Not implemented
265  return ERROR_NOT_IMPLEMENTED;
266 #endif
267 }
268 
269 
270 /**
271  * @brief Export an RSA private key to SSH private key file format
272  * @param[in] privateKey RSA private key
273  * @param[in] publicKey RSA public key
274  * @param[out] output Buffer where to store the SSH private key file
275  * @param[out] written Length of the resulting SSH private key file
276  * @param[in] format Desired output format (OpenSSH only is supported)
277  * @return Error code
278  **/
279 
281  const RsaPublicKey *publicKey, char_t *output, size_t *written,
282  SshPrivateKeyFormat format)
283 {
284  error_t error;
285 
286  //Check output format
287  if(format == SSH_PRIVATE_KEY_FORMAT_OPENSSH)
288  {
289  //Export RSA private key file (OpenSSH format)
290  error = sshExportOpenSshRsaPrivateKey(privateKey, publicKey, output,
291  written);
292  }
293  else
294  {
295  //Invalid format
296  error = ERROR_INVALID_PARAMETER;
297  }
298 
299  //Return error code
300  return error;
301 }
302 
303 
304 /**
305  * @brief Export a DSA private key to SSH private key file format
306  * @param[in] privateKey DSA private key
307  * @param[in] publicKey DSA public key
308  * @param[out] output Buffer where to store the SSH private key file
309  * @param[out] written Length of the resulting SSH private key file
310  * @param[in] format Desired output format (OpenSSH only is supported)
311  * @return Error code
312  **/
313 
315  const DsaPublicKey *publicKey, char_t *output, size_t *written,
316  SshPrivateKeyFormat format)
317 {
318  error_t error;
319 
320  //Check output format
321  if(format == SSH_PRIVATE_KEY_FORMAT_OPENSSH)
322  {
323  //Export DSA private key file (OpenSSH format)
324  error = sshExportOpenSshDsaPrivateKey(privateKey, publicKey, output,
325  written);
326  }
327  else
328  {
329  //Invalid format
330  error = ERROR_INVALID_PARAMETER;
331  }
332 
333  //Return error code
334  return error;
335 }
336 
337 
338 /**
339  * @brief Export an ECDSA private key to SSH private key file format
340  * @param[in] params EC domain parameters
341  * @param[in] privateKey ECDSA private key
342  * @param[in] publicKey ECDSA public key
343  * @param[out] output Buffer where to store the SSH private key file
344  * @param[out] written Length of the resulting SSH private key file
345  * @param[in] format Desired output format (OpenSSH only is supported)
346  * @return Error code
347  **/
348 
350  const EcPrivateKey *privateKey, const EcPublicKey *publicKey,
351  char_t *output, size_t *written, SshPrivateKeyFormat format)
352 {
353  error_t error;
354 
355  //Check output format
356  if(format == SSH_PRIVATE_KEY_FORMAT_OPENSSH)
357  {
358  //Export ECDSA private key file (OpenSSH format)
359  error = sshExportOpenSshEcdsaPrivateKey(params, privateKey, publicKey,
360  output, written);
361  }
362  else
363  {
364  //Invalid format
365  error = ERROR_INVALID_PARAMETER;
366  }
367 
368  //Return error code
369  return error;
370 }
371 
372 
373 /**
374  * @brief Export an Ed25519 private key to SSH private key file format
375  * @param[in] privateKey Ed25519 private key
376  * @param[in] publicKey Ed25519 public key
377  * @param[out] output Buffer where to store the SSH private key file
378  * @param[out] written Length of the resulting SSH private key file
379  * @param[in] format Desired output format (OpenSSH only is supported)
380  * @return Error code
381  **/
382 
384  const EddsaPublicKey *publicKey, char_t *output, size_t *written,
385  SshPrivateKeyFormat format)
386 {
387  error_t error;
388 
389  //Check output format
390  if(format == SSH_PRIVATE_KEY_FORMAT_OPENSSH)
391  {
392  //Export Ed25519 private key file (OpenSSH format)
393  error = sshExportOpenSshEd25519PrivateKey(privateKey, publicKey, output,
394  written);
395  }
396  else
397  {
398  //Invalid format
399  error = ERROR_INVALID_PARAMETER;
400  }
401 
402  //Return error code
403  return error;
404 }
405 
406 
407 /**
408  * @brief Export an Ed448 private key to SSH private key file format
409  * @param[in] privateKey Ed448 private key
410  * @param[in] publicKey Ed448 public key
411  * @param[out] output Buffer where to store the SSH private key file
412  * @param[out] written Length of the resulting SSH private key file
413  * @param[in] format Desired output format (OpenSSH only is supported)
414  * @return Error code
415  **/
416 
418  const EddsaPublicKey *publicKey, char_t *output, size_t *written,
419  SshPrivateKeyFormat format)
420 {
421  error_t error;
422 
423  //Check output format
424  if(format == SSH_PRIVATE_KEY_FORMAT_OPENSSH)
425  {
426  //Export Ed448 private key file (OpenSSH format)
427  error = sshExportOpenSshEd448PrivateKey(privateKey, publicKey, output,
428  written);
429  }
430  else
431  {
432  //Invalid format
433  error = ERROR_INVALID_PARAMETER;
434  }
435 
436  //Return error code
437  return error;
438 }
439 
440 
441 /**
442  * @brief Export an RSA private key to OpenSSH private key file format
443  * @param[in] privateKey RSA private key
444  * @param[in] publicKey RSA public key
445  * @param[out] output Buffer where to store the OpenSSH private key file
446  * @param[out] written Length of the resulting OpenSSH private key file
447  * @return Error code
448  **/
449 
451  const RsaPublicKey *publicKey, char_t *output, size_t *written)
452 {
453 #if (SSH_RSA_SIGN_SUPPORT == ENABLED)
454  error_t error;
455  size_t n;
456  size_t length;
457  uint8_t *p;
458 
459  //Initialize variables
460  p = (uint8_t *) output;
461  length = 0;
462 
463  //Format private key header
465  //Any error to report?
466  if(error)
467  return error;
468 
469  //Point to the next field
470  p += n;
471  length += n;
472 
473  //Format 'publickey' field
474  error = sshFormatRsaPublicKey(publicKey, p + sizeof(uint32_t), &n);
475  //Any error to report?
476  if(error)
477  return error;
478 
479  //The octet string value is preceded by a uint32 containing its length
480  STORE32BE(n, p);
481 
482  //Point to the next field
483  p += sizeof(uint32_t) + n;
484  length += sizeof(uint32_t) + n;
485 
486  //Format 'encrypted' field
487  error = sshFormatOpenSshRsaPrivateKey(privateKey, p + sizeof(uint32_t), &n);
488  //Any error to report?
489  if(error)
490  return error;
491 
492  //The octet string value is preceded by a uint32 containing its length
493  STORE32BE(n, p);
494 
495  //Total length of the private key structure
496  length += sizeof(uint32_t) + n;
497 
498  //Convert the private key structure to OpenSSH format
499  error = sshEncodeOpenSshPrivateKeyFile(output, length, output, &n);
500  //Any error to report?
501  if(error)
502  return error;
503 
504  //Total number of bytes that have been written
505  *written = n;
506 
507  //Successful processing
508  return NO_ERROR;
509 #else
510  //Not implemented
511  return ERROR_NOT_IMPLEMENTED;
512 #endif
513 }
514 
515 
516 /**
517  * @brief Export a DSA private key to OpenSSH private key file format
518  * @param[in] privateKey DSA private key
519  * @param[in] publicKey DSA public key
520  * @param[out] output Buffer where to store the OpenSSH private key file
521  * @param[out] written Length of the resulting OpenSSH private key file
522  * @return Error code
523  **/
524 
526  const DsaPublicKey *publicKey, char_t *output, size_t *written)
527 {
528 #if (SSH_DSA_SIGN_SUPPORT == ENABLED)
529  error_t error;
530  size_t n;
531  size_t length;
532  uint8_t *p;
533 
534  //Initialize variables
535  p = (uint8_t *) output;
536  length = 0;
537 
538  //Format private key header
540  //Any error to report?
541  if(error)
542  return error;
543 
544  //Point to the next field
545  p += n;
546  length += n;
547 
548  //Format 'publickey' field
549  error = sshFormatDsaPublicKey(publicKey, p + sizeof(uint32_t), &n);
550  //Any error to report?
551  if(error)
552  return error;
553 
554  //The octet string value is preceded by a uint32 containing its length
555  STORE32BE(n, p);
556 
557  //Point to the next field
558  p += sizeof(uint32_t) + n;
559  length += sizeof(uint32_t) + n;
560 
561  //Format 'encrypted' field
562  error = sshFormatOpenSshDsaPrivateKey(privateKey, publicKey,
563  p + sizeof(uint32_t), &n);
564  //Any error to report?
565  if(error)
566  return error;
567 
568  //The octet string value is preceded by a uint32 containing its length
569  STORE32BE(n, p);
570 
571  //Total length of the private key structure
572  length += sizeof(uint32_t) + n;
573 
574  //Convert the private key structure to OpenSSH format
575  error = sshEncodeOpenSshPrivateKeyFile(output, length, output, &n);
576  //Any error to report?
577  if(error)
578  return error;
579 
580  //Total number of bytes that have been written
581  *written = n;
582 
583  //Successful processing
584  return NO_ERROR;
585 #else
586  //Not implemented
587  return ERROR_NOT_IMPLEMENTED;
588 #endif
589 }
590 
591 
592 /**
593  * @brief Export an ECDSA private key to OpenSSH private key file format
594  * @param[in] params EC domain parameters
595  * @param[in] privateKey ECDSA private key
596  * @param[in] publicKey ECDSA public key
597  * @param[out] output Buffer where to store the OpenSSH private key file
598  * @param[out] written Length of the resulting OpenSSH private key file
599  * @return Error code
600  **/
601 
603  const EcPrivateKey *privateKey, const EcPublicKey *publicKey,
604  char_t *output, size_t *written)
605 {
606 #if (SSH_ECDSA_SIGN_SUPPORT == ENABLED)
607  error_t error;
608  size_t n;
609  size_t length;
610  uint8_t *p;
611 
612  //Initialize variables
613  p = (uint8_t *) output;
614  length = 0;
615 
616  //Format private key header
618  //Any error to report?
619  if(error)
620  return error;
621 
622  //Point to the next field
623  p += n;
624  length += n;
625 
626  //Format 'publickey' field
627  error = sshFormatEcdsaPublicKey(params, publicKey, p + sizeof(uint32_t), &n);
628  //Any error to report?
629  if(error)
630  return error;
631 
632  //The octet string value is preceded by a uint32 containing its length
633  STORE32BE(n, p);
634 
635  //Point to the next field
636  p += sizeof(uint32_t) + n;
637  length += sizeof(uint32_t) + n;
638 
639  //Format 'encrypted' field
640  error = sshFormatOpenSshEcdsaPrivateKey(params, privateKey, publicKey,
641  p + sizeof(uint32_t), &n);
642  //Any error to report?
643  if(error)
644  return error;
645 
646  //The octet string value is preceded by a uint32 containing its length
647  STORE32BE(n, p);
648 
649  //Total length of the private key structure
650  length += sizeof(uint32_t) + n;
651 
652  //Convert the private key structure to OpenSSH format
653  error = sshEncodeOpenSshPrivateKeyFile(output, length, output, &n);
654  //Any error to report?
655  if(error)
656  return error;
657 
658  //Total number of bytes that have been written
659  *written = n;
660 
661  //Successful processing
662  return NO_ERROR;
663 #else
664  //Not implemented
665  return ERROR_NOT_IMPLEMENTED;
666 #endif
667 }
668 
669 
670 /**
671  * @brief Export an Ed25519 private key to OpenSSH private key file format
672  * @param[in] privateKey Ed25519 private key
673  * @param[in] publicKey Ed25519 public key
674  * @param[out] output Buffer where to store the OpenSSH private key file
675  * @param[out] written Length of the resulting OpenSSH private key file
676  * @return Error code
677  **/
678 
680  const EddsaPublicKey *publicKey, char_t *output, size_t *written)
681 {
682 #if (SSH_ED25519_SIGN_SUPPORT == ENABLED)
683  error_t error;
684  size_t n;
685  size_t length;
686  uint8_t *p;
687 
688  //Initialize variables
689  p = (uint8_t *) output;
690  length = 0;
691 
692  //Format private key header
694  //Any error to report?
695  if(error)
696  return error;
697 
698  //Point to the next field
699  p += n;
700  length += n;
701 
702  //Format 'publickey' field
703  error = sshFormatEd25519PublicKey(publicKey, p + sizeof(uint32_t), &n);
704  //Any error to report?
705  if(error)
706  return error;
707 
708  //The octet string value is preceded by a uint32 containing its length
709  STORE32BE(n, p);
710 
711  //Point to the next field
712  p += sizeof(uint32_t) + n;
713  length += sizeof(uint32_t) + n;
714 
715  //Format 'encrypted' field
716  error = sshFormatOpenSshEd25519PrivateKey(privateKey, publicKey,
717  p + sizeof(uint32_t), &n);
718  //Any error to report?
719  if(error)
720  return error;
721 
722  //The octet string value is preceded by a uint32 containing its length
723  STORE32BE(n, p);
724 
725  //Total length of the private key structure
726  length += sizeof(uint32_t) + n;
727 
728  //Convert the private key structure to OpenSSH format
729  error = sshEncodeOpenSshPrivateKeyFile(output, length, output, &n);
730  //Any error to report?
731  if(error)
732  return error;
733 
734  //Total number of bytes that have been written
735  *written = n;
736 
737  //Successful processing
738  return NO_ERROR;
739 #else
740  //Not implemented
741  return ERROR_NOT_IMPLEMENTED;
742 #endif
743 }
744 
745 
746 /**
747  * @brief Export an Ed448 private key to OpenSSH private key file format
748  * @param[in] privateKey Ed448 private key
749  * @param[in] publicKey Ed448 public key
750  * @param[out] output Buffer where to store the OpenSSH private key file
751  * @param[out] written Length of the resulting OpenSSH private key file
752  * @return Error code
753  **/
754 
756  const EddsaPublicKey *publicKey, char_t *output, size_t *written)
757 {
758 #if (SSH_ED448_SIGN_SUPPORT == ENABLED)
759  error_t error;
760  size_t n;
761  size_t length;
762  uint8_t *p;
763 
764  //Initialize variables
765  p = (uint8_t *) output;
766  length = 0;
767 
768  //Format private key header
770  //Any error to report?
771  if(error)
772  return error;
773 
774  //Point to the next field
775  p += n;
776  length += n;
777 
778  //Format 'publickey' field
779  error = sshFormatEd448PublicKey(publicKey, p + sizeof(uint32_t), &n);
780  //Any error to report?
781  if(error)
782  return error;
783 
784  //The octet string value is preceded by a uint32 containing its length
785  STORE32BE(n, p);
786 
787  //Point to the next field
788  p += sizeof(uint32_t) + n;
789  length += sizeof(uint32_t) + n;
790 
791  //Format 'encrypted' field
792  error = sshFormatOpenSshEd448PrivateKey(privateKey, publicKey,
793  p + sizeof(uint32_t), &n);
794  //Any error to report?
795  if(error)
796  return error;
797 
798  //The octet string value is preceded by a uint32 containing its length
799  STORE32BE(n, p);
800 
801  //Total length of the private key structure
802  length += sizeof(uint32_t) + n;
803 
804  //Convert the private key structure to OpenSSH format
805  error = sshEncodeOpenSshPrivateKeyFile(output, length, output, &n);
806  //Any error to report?
807  if(error)
808  return error;
809 
810  //Total number of bytes that have been written
811  *written = n;
812 
813  //Successful processing
814  return NO_ERROR;
815 #else
816  //Not implemented
817  return ERROR_NOT_IMPLEMENTED;
818 #endif
819 }
820 
821 
822 /**
823  * @brief Encode SSH public key file (SSH2 or OpenSSH format)
824  * @param[in] input Host key structure to encode
825  * @param[in] inputLen Length of the host key structure to encode
826  * @param[out] output SSH public key file (optional parameter)
827  * @param[out] outputLen Length of the SSH public key file
828  * @param[in] format Desired output format (SSH2 or OpenSSH)
829  **/
830 
831 error_t sshEncodePublicKeyFile(const void *input, size_t inputLen,
832  char_t *output, size_t *outputLen, SshPublicKeyFormat format)
833 {
834  error_t error;
835 
836  //Check output format
837  if(format == SSH_PUBLIC_KEY_FORMAT_SSH2)
838  {
839  //Encode SSH public key file (SSH2 format)
840  error = sshEncodeSsh2PublicKeyFile(input, inputLen, output, outputLen);
841  }
842  else if(format == SSH_PUBLIC_KEY_FORMAT_OPENSSH)
843  {
844  //Encode SSH public key file (OpenSSH format)
845  error = sshEncodeOpenSshPublicKeyFile(input, inputLen, output, outputLen);
846  }
847  else
848  {
849  //Invalid format
850  error = ERROR_INVALID_PARAMETER;
851  }
852 
853  //Return error code
854  return error;
855 }
856 
857 
858 /**
859  * @brief Encode SSH public key file (SSH2 format)
860  * @param[in] input Host key structure to encode
861  * @param[in] inputLen Length of the host key structure to encode
862  * @param[out] output SSH public key file (optional parameter)
863  * @param[out] outputLen Length of the SSH public key file
864  **/
865 
866 error_t sshEncodeSsh2PublicKeyFile(const void *input, size_t inputLen,
867  char_t *output, size_t *outputLen)
868 {
869  size_t n;
870 
871  //Check parameters
872  if(input == NULL || outputLen == NULL)
874 
875  //Each line in the body must not be longer than 72 8-bit bytes excluding
876  //line termination characters (refer to RFC 4716, section 3.4)
877  base64EncodeMultiline(input, inputLen, output, &n, 70);
878 
879  //If the output parameter is NULL, then the function calculates the length
880  //of the resulting SSH public key file without copying any data
881  if(output != NULL)
882  {
883  //Make room for the begin marker
884  osMemmove(output + 33, output, n);
885 
886  //The first line of a conforming key file must be a begin marker (refer
887  //to RFC 4716, section 3.2)
888  osMemcpy(output, "---- BEGIN SSH2 PUBLIC KEY ----\r\n", 33);
889 
890  //The last line of a conforming key file must be an end marker (refer to
891  //RFC 4716, section 3.2)
892  osStrcpy(output + n + 33, "\r\n---- END SSH2 PUBLIC KEY ----\r\n");
893  }
894 
895  //Consider the length of the markers
896  n += osStrlen("---- BEGIN SSH2 PUBLIC KEY ----\r\n");
897  n += osStrlen("\r\n---- END SSH2 PUBLIC KEY ----\r\n");
898 
899  //Total number of bytes that have been written
900  *outputLen = n;
901 
902  //Successful processing
903  return NO_ERROR;
904 }
905 
906 
907 /**
908  * @brief Encode SSH public key file (OpenSSH format)
909  * @param[in] input Host key structure to encode
910  * @param[in] inputLen Length of the host key structure to encode
911  * @param[out] output SSH public key file (optional parameter)
912  * @param[out] outputLen Length of the SSH public key file
913  **/
914 
915 error_t sshEncodeOpenSshPublicKeyFile(const void *input, size_t inputLen,
916  char_t *output, size_t *outputLen)
917 {
918  error_t error;
919  size_t n;
920  SshString keyFormatId;
921  uint8_t identifier[40];
922 
923  //Check parameters
924  if(input == NULL || outputLen == NULL)
926 
927  //Parse host key structure
928  error = sshParseHostKey(input, inputLen, &keyFormatId);
929  //Any error to report?
930  if(error)
931  return error;
932 
933  //Sanity check
934  if(keyFormatId.length > sizeof(identifier))
935  return ERROR_WRONG_IDENTIFIER;
936 
937  //Save key format identifier
938  osMemcpy(identifier, keyFormatId.value, keyFormatId.length);
939 
940  //Encode the host key structure using Base64
941  base64Encode(input, inputLen, output, &n);
942 
943  //If the output parameter is NULL, then the function calculates the length
944  //of the resulting certificate file without copying any data
945  if(output != NULL)
946  {
947  //Make room for the identifier string
948  osMemmove(output + keyFormatId.length + 1, output, n + 1);
949  //Copy identifier string
950  osMemcpy(output, identifier, keyFormatId.length);
951  //The identifier must be followed by a whitespace character
952  output[keyFormatId.length] = ' ';
953  }
954 
955  //Consider the length of the identifier string
956  n += keyFormatId.length + 1;
957 
958  //Total number of bytes that have been written
959  *outputLen = n;
960 
961  //Successful processing
962  return NO_ERROR;
963 }
964 
965 
966 /**
967  * @brief Encode SSH private key file (OpenSSH format)
968  * @param[in] input Private key structure to encode
969  * @param[in] inputLen Length of the private key structure to encode
970  * @param[out] output SSH private key file (optional parameter)
971  * @param[out] outputLen Length of the SSH private key file
972  **/
973 
974 error_t sshEncodeOpenSshPrivateKeyFile(const void *input, size_t inputLen,
975  char_t *output, size_t *outputLen)
976 {
977  size_t n;
978 
979  //Check parameters
980  if(input == NULL || outputLen == NULL)
982 
983  //Encode the private key structure using Base64
984  base64EncodeMultiline(input, inputLen, output, &n, 70);
985 
986  //If the output parameter is NULL, then the function calculates the length
987  //of the resulting SSH private key file without copying any data
988  if(output != NULL)
989  {
990  //Make room for the begin marker
991  osMemmove(output + 37, output, n);
992 
993  //The first line of the private key file must be a begin marker
994  osMemcpy(output, "-----BEGIN OPENSSH PRIVATE KEY-----\r\n", 37);
995 
996  //The last line of the private key file must be an end marker
997  osStrcpy(output + n + 37, "\r\n-----END OPENSSH PRIVATE KEY-----\r\n");
998  }
999 
1000  //Consider the length of the markers
1001  n += osStrlen("-----BEGIN OPENSSH PRIVATE KEY-----\r\n");
1002  n += osStrlen("\r\n-----END OPENSSH PRIVATE KEY-----\r\n");
1003 
1004  //Total number of bytes that have been written
1005  *outputLen = n;
1006 
1007  //Successful processing
1008  return NO_ERROR;
1009 }
1010 
1011 #endif
void base64Encode(const void *input, size_t inputLen, char_t *output, size_t *outputLen)
Base64 encoding algorithm.
Definition: base64.c:142
void base64EncodeMultiline(const void *input, size_t inputLen, char_t *output, size_t *outputLen, size_t lineWidth)
Base64 multiline encoding.
Definition: base64.c:79
Base64 encoding scheme.
char char_t
Definition: compiler_port.h:48
#define STORE32BE(a, p)
Definition: cpu_endian.h:286
Debugging facilities.
uint8_t n
uint8_t identifier[]
error_t
Error codes.
Definition: error.h:43
@ ERROR_WRONG_IDENTIFIER
Definition: error.h:89
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
uint8_t p
Definition: ndp.h:300
#define osMemmove(dest, src, length)
Definition: os_port.h:147
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
#define osStrlen(s)
Definition: os_port.h:165
#define osStrcpy(s1, s2)
Definition: os_port.h:207
Secure Shell (SSH)
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.
error_t sshExportOpenSshEd25519PrivateKey(const EddsaPrivateKey *privateKey, const EddsaPublicKey *publicKey, char_t *output, size_t *written)
Export an Ed25519 private key to OpenSSH private key file format.
error_t sshExportOpenSshEcdsaPrivateKey(const EcDomainParameters *params, const EcPrivateKey *privateKey, const EcPublicKey *publicKey, char_t *output, size_t *written)
Export an ECDSA private key to OpenSSH private key file format.
error_t sshExportOpenSshRsaPrivateKey(const RsaPrivateKey *privateKey, const RsaPublicKey *publicKey, char_t *output, size_t *written)
Export an RSA private key to OpenSSH private key file format.
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.
error_t sshExportRsaPrivateKey(const RsaPrivateKey *privateKey, const RsaPublicKey *publicKey, char_t *output, size_t *written, SshPrivateKeyFormat format)
Export an RSA private key to SSH private key file format.
error_t sshExportOpenSshEd448PrivateKey(const EddsaPrivateKey *privateKey, const EddsaPublicKey *publicKey, char_t *output, size_t *written)
Export an Ed448 private key to OpenSSH private key file format.
error_t sshExportEd25519PrivateKey(const EddsaPrivateKey *privateKey, const EddsaPublicKey *publicKey, char_t *output, size_t *written, SshPrivateKeyFormat format)
Export an Ed25519 private key to SSH private key file format.
error_t sshExportDsaPrivateKey(const DsaPrivateKey *privateKey, const DsaPublicKey *publicKey, char_t *output, size_t *written, SshPrivateKeyFormat format)
Export a DSA private key to SSH private key file format.
error_t sshExportEd448PrivateKey(const EddsaPrivateKey *privateKey, const EddsaPublicKey *publicKey, char_t *output, size_t *written, SshPrivateKeyFormat format)
Export an Ed448 private key to SSH private key file format.
error_t sshExportEcdsaPrivateKey(const EcDomainParameters *params, const EcPrivateKey *privateKey, const EcPublicKey *publicKey, char_t *output, size_t *written, SshPrivateKeyFormat format)
Export an ECDSA private key to SSH private key file format.
error_t sshExportEcdsaPublicKey(const EcDomainParameters *params, const EcPublicKey *publicKey, char_t *output, size_t *written, SshPublicKeyFormat format)
Export an ECDSA public key to SSH public key file format.
error_t sshExportOpenSshDsaPrivateKey(const DsaPrivateKey *privateKey, const DsaPublicKey *publicKey, char_t *output, size_t *written)
Export a DSA private key to OpenSSH private key file format.
error_t sshEncodeOpenSshPrivateKeyFile(const void *input, size_t inputLen, char_t *output, size_t *outputLen)
Encode SSH private key file (OpenSSH format)
error_t sshEncodePublicKeyFile(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 sshExportEd25519PublicKey(const EddsaPublicKey *publicKey, char_t *output, size_t *written, SshPublicKeyFormat format)
Export a Ed25519 public key to SSH public key file format.
error_t sshEncodeOpenSshPublicKeyFile(const void *input, size_t inputLen, char_t *output, size_t *outputLen)
Encode SSH public key file (OpenSSH format)
error_t sshEncodeSsh2PublicKeyFile(const void *input, size_t inputLen, char_t *output, size_t *outputLen)
Encode SSH public key file (SSH2 format)
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.
SSH key file export functions.
SshPublicKeyFormat
SSH public key formats.
@ SSH_PUBLIC_KEY_FORMAT_OPENSSH
OpenSSH public key format.
@ SSH_PUBLIC_KEY_FORMAT_SSH2
SSH2 public key format.
SshPrivateKeyFormat
SSH private key formats.
@ SSH_PRIVATE_KEY_FORMAT_OPENSSH
OpenSSH private key format.
error_t sshFormatEcdsaPublicKey(const EcDomainParameters *params, const EcPublicKey *publicKey, uint8_t *p, size_t *written)
Format an ECDSA public host key.
error_t sshFormatOpenSshEd25519PrivateKey(const EddsaPrivateKey *privateKey, const EddsaPublicKey *publicKey, uint8_t *p, size_t *written)
Format Ed25519 private key blob (OpenSSH format)
error_t sshFormatOpenSshEd448PrivateKey(const EddsaPrivateKey *privateKey, const EddsaPublicKey *publicKey, uint8_t *p, size_t *written)
Format Ed448 private key blob (OpenSSH format)
error_t sshFormatOpenSshDsaPrivateKey(const DsaPrivateKey *privateKey, const DsaPublicKey *publicKey, uint8_t *p, size_t *written)
Format DSA private key blob (OpenSSH format)
error_t sshFormatOpenSshRsaPrivateKey(const RsaPrivateKey *privateKey, uint8_t *p, size_t *written)
Format RSA private key blob (OpenSSH format)
error_t sshFormatOpenSshPrivateKeyHeader(uint8_t *p, size_t *written)
Format private key header (OpenSSH format)
error_t sshFormatEd25519PublicKey(const EddsaPublicKey *publicKey, uint8_t *p, size_t *written)
Format an Ed25519 public host key.
error_t sshFormatRsaPublicKey(const RsaPublicKey *publicKey, uint8_t *p, size_t *written)
Format an RSA public host key.
error_t sshFormatDsaPublicKey(const DsaPublicKey *publicKey, uint8_t *p, size_t *written)
Format a DSA public host key.
error_t sshFormatOpenSshEcdsaPrivateKey(const EcDomainParameters *params, const EcPrivateKey *privateKey, const EcPublicKey *publicKey, uint8_t *p, size_t *written)
Format ECDSA private key blob (OpenSSH format)
error_t sshFormatEd448PublicKey(const EddsaPublicKey *publicKey, uint8_t *p, size_t *written)
Format an Ed448 public host key.
SSH key formatting.
error_t sshParseHostKey(const uint8_t *data, size_t length, SshString *keyFormatId)
Parse host key structure.
Definition: ssh_key_parse.c:53
SSH key parsing.
SSH helper functions.
DSA private key.
Definition: dsa.h:72
DSA public key.
Definition: dsa.h:61
EC domain parameters.
Definition: ec.h:76
EC private key.
Definition: ec.h:104
EC public key.
Definition: ec.h:94
EdDSA private key.
Definition: eddsa.h:59
EdDSA public key.
Definition: eddsa.h:49
RSA private key.
Definition: rsa.h:68
RSA public key.
Definition: rsa.h:57
String.
Definition: ssh_types.h:56
const char_t * value
Definition: ssh_types.h:57
size_t length
Definition: ssh_types.h:58
uint8_t length
Definition: tcp.h:368