ssh_key_format.c
Go to the documentation of this file.
1 /**
2  * @file ssh_key_format.c
3  * @brief SSH key formatting
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_key_parse.h"
37 #include "ssh/ssh_key_format.h"
38 #include "ssh/ssh_misc.h"
39 #include "debug.h"
40 
41 //Check SSH stack configuration
42 #if (SSH_SUPPORT == ENABLED)
43 
44 
45 /**
46  * @brief Format an RSA public host key
47  * @param[in] publicKey Pointer to the RSA public key
48  * @param[out] p Buffer where to store the host key structure
49  * @param[out] written Length of the resulting host key structure
50  * @return Error code
51  **/
52 
54  uint8_t *p, size_t *written)
55 {
56 #if (SSH_RSA_SIGN_SUPPORT == ENABLED)
57  error_t error;
58  size_t n;
59 
60  //Total length of the public host key structure
61  *written = 0;
62 
63  //Format public key format identifier
64  error = sshFormatString("ssh-rsa", p, &n);
65  //Any error to report?
66  if(error)
67  return error;
68 
69  //Point to the next field
70  p += n;
71  *written += n;
72 
73  //Format RSA public exponent
74  error = sshFormatMpint(&publicKey->e, p, &n);
75  //Any error to report?
76  if(error)
77  return error;
78 
79  //Point to the next field
80  p += n;
81  *written += n;
82 
83  //Format RSA modulus
84  error = sshFormatMpint(&publicKey->n, p, &n);
85  //Any error to report?
86  if(error)
87  return error;
88 
89  //Total number of bytes that have been written
90  *written += n;
91 
92  //Successful processing
93  return NO_ERROR;
94 #else
95  //Not implemented
96  return ERROR_NOT_IMPLEMENTED;
97 #endif
98 }
99 
100 
101 /**
102  * @brief Format a DSA public host key
103  * @param[in] publicKey Pointer to the DSA public key
104  * @param[out] p Buffer where to store the host key structure
105  * @param[out] written Length of the resulting host key structure
106  * @return Error code
107  **/
108 
110  uint8_t *p, size_t *written)
111 {
112 #if (SSH_DSA_SIGN_SUPPORT == ENABLED)
113  error_t error;
114  size_t n;
115 
116  //Total length of the public host key structure
117  *written = 0;
118 
119  //Format public key format identifier
120  error = sshFormatString("ssh-dss", p, &n);
121  //Any error to report?
122  if(error)
123  return error;
124 
125  //Point to the next field
126  p += n;
127  *written += n;
128 
129  //Format DSA prime modulus
130  error = sshFormatMpint(&publicKey->params.p, p, &n);
131  //Any error to report?
132  if(error)
133  return error;
134 
135  //Point to the next field
136  p += n;
137  *written += n;
138 
139  //Format DSA group order
140  error = sshFormatMpint(&publicKey->params.q, p, &n);
141  //Any error to report?
142  if(error)
143  return error;
144 
145  //Point to the next field
146  p += n;
147  *written += n;
148 
149  //Format DSA group generator
150  error = sshFormatMpint(&publicKey->params.g, p, &n);
151  //Any error to report?
152  if(error)
153  return error;
154 
155  //Point to the next field
156  p += n;
157  *written += n;
158 
159  //Format DSA public key value
160  error = sshFormatMpint(&publicKey->y, p, &n);
161  //Any error to report?
162  if(error)
163  return error;
164 
165  //Total number of bytes that have been written
166  *written += n;
167 
168  //Successful processing
169  return NO_ERROR;
170 #else
171  //Not implemented
172  return ERROR_NOT_IMPLEMENTED;
173 #endif
174 }
175 
176 
177 /**
178  * @brief Format an ECDSA public host key
179  * @param[in] publicKey Pointer to the ECDSA public key
180  * @param[out] p Buffer where to store the host key structure
181  * @param[out] written Length of the resulting host key structure
182  * @return Error code
183  **/
184 
186  uint8_t *p, size_t *written)
187 {
188 #if (SSH_ECDSA_SIGN_SUPPORT == ENABLED)
189  error_t error;
190  size_t n;
191  const char_t *keyFormatId;
192  const char_t *curveName;
193 
194  //Total length of the public host key structure
195  *written = 0;
196 
197  //Invalid ECDSA public key?
198  if(publicKey->curve == NULL)
200 
201  //Check elliptic curve
202  if(osStrcmp(publicKey->curve->name, "secp256r1") == 0)
203  {
204  //Select NIST P-256 elliptic curve
205  keyFormatId = "ecdsa-sha2-nistp256";
206  curveName = "nistp256";
207  }
208  else if(osStrcmp(publicKey->curve->name, "secp384r1") == 0)
209  {
210  //Select NIST P-384 elliptic curve
211  keyFormatId = "ecdsa-sha2-nistp384";
212  curveName = "nistp384";
213  }
214  else if(osStrcmp(publicKey->curve->name, "secp521r1") == 0)
215  {
216  //Select NIST P-521 elliptic curve
217  keyFormatId = "ecdsa-sha2-nistp521";
218  curveName = "nistp521";
219  }
220  else
221  {
222  //Unknown host key algorithm
224  }
225 
226  //Format public key format identifier
227  error = sshFormatString(keyFormatId, p, &n);
228  //Any error to report?
229  if(error)
230  return error;
231 
232  //Point to the next field
233  p += n;
234  *written += n;
235 
236  //Format the elliptic curve domain parameter identifier
237  error = sshFormatString(curveName, p, &n);
238  //Any error to report?
239  if(error)
240  return error;
241 
242  //Point to the next field
243  p += n;
244  *written += n;
245 
246  //Format EC public key
247  error = ecExportPublicKey(publicKey, p + 4, &n, EC_PUBLIC_KEY_FORMAT_X963);
248  //Any error to report?
249  if(error)
250  return error;
251 
252  //The octet string value is preceded by a uint32 containing its length
253  STORE32BE(n, p);
254 
255  //Total number of bytes that have been written
256  *written += sizeof(uint32_t) + n;
257 
258  //Successful processing
259  return NO_ERROR;
260 #else
261  //Not implemented
262  return ERROR_NOT_IMPLEMENTED;
263 #endif
264 }
265 
266 
267 /**
268  * @brief Format an Ed25519 public host key
269  * @param[in] publicKey Pointer to the Ed25519 public key
270  * @param[out] p Buffer where to store the host key structure
271  * @param[out] written Length of the resulting host key structure
272  * @return Error code
273  **/
274 
276  uint8_t *p, size_t *written)
277 {
278 #if (SSH_ED25519_SIGN_SUPPORT == ENABLED)
279  error_t error;
280  size_t n;
281 
282  //Total length of the public host key structure
283  *written = 0;
284 
285  //Format public key format identifier
286  error = sshFormatString("ssh-ed25519", p, &n);
287  //Any error to report?
288  if(error)
289  return error;
290 
291  //Point to the next field
292  p += n;
293  *written += n;
294 
295  //Format Ed25519 public key
296  error = eddsaExportPublicKey(publicKey, p + 4, &n);
297  //Any error to report?
298  if(error)
299  return error;
300 
301  //The octet string value is preceded by a uint32 containing its length
302  STORE32BE(n, p);
303 
304  //Total number of bytes that have been written
305  *written += sizeof(uint32_t) + n;
306 
307  //Successful processing
308  return NO_ERROR;
309 #else
310  //Not implemented
311  return ERROR_NOT_IMPLEMENTED;
312 #endif
313 }
314 
315 
316 /**
317  * @brief Format an Ed448 public host key
318  * @param[in] publicKey Pointer to the Ed448 public key
319  * @param[out] p Buffer where to store the host key structure
320  * @param[out] written Length of the resulting host key structure
321  * @return Error code
322  **/
323 
325  uint8_t *p, size_t *written)
326 {
327 #if (SSH_ED448_SIGN_SUPPORT == ENABLED)
328  error_t error;
329  size_t n;
330 
331  //Total length of the public host key structure
332  *written = 0;
333 
334  //Format public key format identifier
335  error = sshFormatString("ssh-ed448", p, &n);
336  //Any error to report?
337  if(error)
338  return error;
339 
340  //Point to the next field
341  p += n;
342  *written += n;
343 
344  //Format Ed448 public key
345  error = eddsaExportPublicKey(publicKey, p + 4, &n);
346  //Any error to report?
347  if(error)
348  return error;
349 
350  //The octet string value is preceded by a uint32 containing its length
351  STORE32BE(n, p);
352 
353  //Total number of bytes that have been written
354  *written += sizeof(uint32_t) + n;
355 
356  //Successful processing
357  return NO_ERROR;
358 #else
359  //Not implemented
360  return ERROR_NOT_IMPLEMENTED;
361 #endif
362 }
363 
364 
365 /**
366  * @brief Format private key header (OpenSSH format)
367  * @param[out] p Buffer where to store the private key header
368  * @param[out] written Length of the resulting private key header
369  * @return Error code
370  **/
371 
372 error_t sshFormatOpenSshPrivateKeyHeader(uint8_t *p, size_t *written)
373 {
374  error_t error;
375  size_t n;
376 
377  //Total length of the private key header
378  *written = 0;
379 
380  //Format magic identifier
381  osMemmove(p, "openssh-key-v1", SSH_AUTH_MAGIC_SIZE);
382 
383  //Point to the next field
385  *written += SSH_AUTH_MAGIC_SIZE;
386 
387  //Format 'ciphername' field (for unencrypted keys the cipher "none" is used)
388  error = sshFormatString("none", p, &n);
389  //Any error to report?
390  if(error)
391  return error;
392 
393  //Point to the next field
394  p += n;
395  *written += n;
396 
397  //Format 'kdfname' field (for unencrypted keys the KDF "none" is used)
398  error = sshFormatString("none", p, &n);
399  //Any error to report?
400  if(error)
401  return error;
402 
403  //Point to the next field
404  p += n;
405  *written += n;
406 
407  //Format 'kdfoptions' field
408  error = sshFormatString("", p, &n);
409  //Any error to report?
410  if(error)
411  return error;
412 
413  //Point to the next field
414  p += n;
415  *written += n;
416 
417  //Format 'number of keys' field
418  STORE32BE(1, p);
419 
420  //Total number of bytes that have been written
421  *written += n;
422 
423  //Successful processing
424  return NO_ERROR;
425 }
426 
427 
428 /**
429  * @brief Format RSA private key blob (OpenSSH format)
430  * @param[in] privateKey Pointer to the RSA private key
431  * @param[out] p Buffer where to store the private key blob
432  * @param[out] written Length of the resulting private key blob
433  * @return Error code
434  **/
435 
437  uint8_t *p, size_t *written)
438 {
439 #if (SSH_RSA_SIGN_SUPPORT == ENABLED)
440  error_t error;
441  size_t n;
442  size_t length;
443 
444  //Total length of the private key blob
445  length = 0;
446 
447  //Format 'checkint' fields
448  STORE32BE(0x12345678, p);
449  STORE32BE(0x12345678, p + sizeof(uint32_t));
450 
451  //Point to the next field
452  p += 2 * sizeof(uint32_t);
453  length += 2 * sizeof(uint32_t);
454 
455  //Format key format identifier
456  error = sshFormatString("ssh-rsa", p, &n);
457  //Any error to report?
458  if(error)
459  return error;
460 
461  //Point to the next field
462  p += n;
463  length += n;
464 
465  //Format RSA modulus
466  error = sshFormatMpint(&privateKey->n, p, &n);
467  //Any error to report?
468  if(error)
469  return error;
470 
471  //Point to the next field
472  p += n;
473  length += n;
474 
475  //Format RSA public exponent
476  error = sshFormatMpint(&privateKey->e, p, &n);
477  //Any error to report?
478  if(error)
479  return error;
480 
481  //Point to the next field
482  p += n;
483  length += n;
484 
485  //Format RSA private exponent
486  error = sshFormatMpint(&privateKey->d, p, &n);
487  //Any error to report?
488  if(error)
489  return error;
490 
491  //Point to the next field
492  p += n;
493  length += n;
494 
495  //Format RSA CRT coefficient
496  error = sshFormatMpint(&privateKey->qinv, p, &n);
497  //Any error to report?
498  if(error)
499  return error;
500 
501  //Point to the next field
502  p += n;
503  length += n;
504 
505  //Parse RSA first factor
506  error = sshFormatMpint(&privateKey->p, p, &n);
507  //Any error to report?
508  if(error)
509  return error;
510 
511  //Point to the next field
512  p += n;
513  length += n;
514 
515  //Parse RSA second factor
516  error = sshFormatMpint(&privateKey->q, p, &n);
517  //Any error to report?
518  if(error)
519  return error;
520 
521  //Point to the next field
522  p += n;
523  length += n;
524 
525  //The private key is followed by a comment
526  error = sshFormatString("", p, &n);
527  //Any error to report?
528  if(error)
529  return error;
530 
531  //Point to the next field
532  p += n;
533  length += n;
534 
535  //The padding size is determined by the 'ciphername' field
536  for(n = 0; (length % 8) != 0; n++, length++)
537  {
538  p[n] = n + 1;
539  }
540 
541  //Total number of bytes that have been written
542  *written = length;
543 
544  //Successful processing
545  return NO_ERROR;
546 #else
547  //Not implemented
548  return ERROR_NOT_IMPLEMENTED;
549 #endif
550 }
551 
552 
553 /**
554  * @brief Format DSA private key blob (OpenSSH format)
555  * @param[in] privateKey Pointer to the DSA private key
556  * @param[out] p Buffer where to store the private key blob
557  * @param[out] written Length of the resulting private key blob
558  * @return Error code
559  **/
560 
562  uint8_t *p, size_t *written)
563 {
564 #if (SSH_DSA_SIGN_SUPPORT == ENABLED)
565  error_t error;
566  size_t n;
567  size_t length;
568 
569  //Total length of the private key blob
570  length = 0;
571 
572  //Format 'checkint' fields
573  STORE32BE(0x12345678, p);
574  STORE32BE(0x12345678, p + sizeof(uint32_t));
575 
576  //Point to the next field
577  p += 2 * sizeof(uint32_t);
578  length += 2 * sizeof(uint32_t);
579 
580  //Format key format identifier
581  error = sshFormatString("ssh-dss", p, &n);
582  //Any error to report?
583  if(error)
584  return error;
585 
586  //Point to the next field
587  p += n;
588  length += n;
589 
590  //Format DSA prime modulus
591  error = sshFormatMpint(&privateKey->params.p, p, &n);
592  //Any error to report?
593  if(error)
594  return error;
595 
596  //Point to the next field
597  p += n;
598  length += n;
599 
600  //Format DSA group order
601  error = sshFormatMpint(&privateKey->params.q, p, &n);
602  //Any error to report?
603  if(error)
604  return error;
605 
606  //Point to the next field
607  p += n;
608  length += n;
609 
610  //Format DSA group generator
611  error = sshFormatMpint(&privateKey->params.g, p, &n);
612  //Any error to report?
613  if(error)
614  return error;
615 
616  //Point to the next field
617  p += n;
618  length += n;
619 
620  //Format DSA public key value
621  error = sshFormatMpint(&privateKey->y, p, &n);
622  //Any error to report?
623  if(error)
624  return error;
625 
626  //Point to the next field
627  p += n;
628  length += n;
629 
630  //Format DSA private key value
631  error = sshFormatMpint(&privateKey->x, p, &n);
632  //Any error to report?
633  if(error)
634  return error;
635 
636  //Point to the next field
637  p += n;
638  length += n;
639 
640  //The private key is followed by a comment
641  error = sshFormatString("", p, &n);
642  //Any error to report?
643  if(error)
644  return error;
645 
646  //Point to the next field
647  p += n;
648  length += n;
649 
650  //The padding size is determined by the 'ciphername' field
651  for(n = 0; (length % 8) != 0; n++, length++)
652  {
653  p[n] = n + 1;
654  }
655 
656  //Total number of bytes that have been written
657  *written = length;
658 
659  //Successful processing
660  return NO_ERROR;
661 #else
662  //Not implemented
663  return ERROR_NOT_IMPLEMENTED;
664 #endif
665 }
666 
667 
668 /**
669  * @brief Format ECDSA private key blob (OpenSSH format)
670  * @param[in] privateKey Pointer to the ECDSA private key
671  * @param[out] p Buffer where to store the private key blob
672  * @param[out] written Length of the resulting private key blob
673  * @return Error code
674  **/
675 
677  uint8_t *p, size_t *written)
678 {
679 #if (SSH_ECDSA_SIGN_SUPPORT == ENABLED)
680  error_t error;
681  size_t n;
682  size_t length;
683  const char_t *keyFormatId;
684  const char_t *curveName;
685 
686  //Invalid elliptic curve?
687  if(privateKey->curve == NULL ||
688  privateKey->curve != privateKey->q.curve)
689  {
691  }
692 
693  //Total length of the private key blob
694  length = 0;
695 
696  //Format 'checkint' fields
697  STORE32BE(0x12345678, p);
698  STORE32BE(0x12345678, p + sizeof(uint32_t));
699 
700  //Point to the next field
701  p += 2 * sizeof(uint32_t);
702  length += 2 * sizeof(uint32_t);
703 
704  //Check elliptic curve
705  if(osStrcmp(privateKey->curve->name, "secp256r1") == 0)
706  {
707  //Select NIST P-256 elliptic curve
708  keyFormatId = "ecdsa-sha2-nistp256";
709  curveName = "nistp256";
710  }
711  else if(osStrcmp(privateKey->curve->name, "secp384r1") == 0)
712  {
713  //Select NIST P-384 elliptic curve
714  keyFormatId = "ecdsa-sha2-nistp384";
715  curveName = "nistp384";
716  }
717  else if(osStrcmp(privateKey->curve->name, "secp521r1") == 0)
718  {
719  //Select NIST P-521 elliptic curve
720  keyFormatId = "ecdsa-sha2-nistp521";
721  curveName = "nistp521";
722  }
723  else
724  {
725  //Unknown host key algorithm
727  }
728 
729  //Format public key format identifier
730  error = sshFormatString(keyFormatId, p, &n);
731  //Any error to report?
732  if(error)
733  return error;
734 
735  //Point to the next field
736  p += n;
737  length += n;
738 
739  //Format the elliptic curve domain parameter identifier
740  error = sshFormatString(curveName, p, &n);
741  //Any error to report?
742  if(error)
743  return error;
744 
745  //Point to the next field
746  p += n;
747  length += n;
748 
749  //Format EC public key
750  error = ecExportPublicKey(&privateKey->q, p + 4, &n,
752  //Any error to report?
753  if(error)
754  return error;
755 
756  //The octet string value is preceded by a uint32 containing its length
757  STORE32BE(n, p);
758 
759  //Point to the next field
760  p += sizeof(uint32_t) + n;
761  length += sizeof(uint32_t) + n;
762 
763  //Get the length of the private key, in words
764  n = (privateKey->curve->orderSize + 31) / 32;
765 
766  //Format EC private key
767  error = sshConvertScalarToMpint(privateKey->d, n, p, &n);
768  //Any error to report?
769  if(error)
770  return error;
771 
772  //Point to the next field
773  p += n;
774  length += n;
775 
776  //The private key is followed by a comment
777  error = sshFormatString("", p, &n);
778  //Any error to report?
779  if(error)
780  return error;
781 
782  //Point to the next field
783  p += n;
784  length += n;
785 
786  //The padding size is determined by the 'ciphername' field
787  for(n = 0; (length % 8) != 0; n++, length++)
788  {
789  p[n] = n + 1;
790  }
791 
792  //Total number of bytes that have been written
793  *written = length;
794 
795  //Successful processing
796  return NO_ERROR;
797 #else
798  //Not implemented
799  return ERROR_NOT_IMPLEMENTED;
800 #endif
801 }
802 
803 
804 /**
805  * @brief Format Ed25519 private key blob (OpenSSH format)
806  * @param[in] privateKey Pointer to the Ed25519 private key
807  * @param[out] p Buffer where to store the private key blob
808  * @param[out] written Length of the resulting private key blob
809  * @return Error code
810  **/
811 
813  uint8_t *p, size_t *written)
814 {
815 #if (SSH_ED25519_SIGN_SUPPORT == ENABLED)
816  error_t error;
817  size_t m;
818  size_t n;
819  size_t length;
820 
821  //Total length of the private key blob
822  length = 0;
823 
824  //Format 'checkint' fields
825  STORE32BE(0x12345678, p);
826  STORE32BE(0x12345678, p + sizeof(uint32_t));
827 
828  //Point to the next field
829  p += 2 * sizeof(uint32_t);
830  length += 2 * sizeof(uint32_t);
831 
832  //Format key format identifier
833  error = sshFormatString("ssh-ed25519", p, &n);
834  //Any error to report?
835  if(error)
836  return error;
837 
838  //Point to the next field
839  p += n;
840  length += n;
841 
842  //Format Ed25519 public key
843  error = eddsaExportPublicKey(&privateKey->q, p + 4, &n);
844  //Any error to report?
845  if(error)
846  return error;
847 
848  //The octet string value is preceded by a uint32 containing its length
849  STORE32BE(n, p);
850 
851  //Point to the next field
852  p += sizeof(uint32_t) + n;
853  length += sizeof(uint32_t) + n;
854 
855  //Format Ed25519 private key
856  error = eddsaExportPrivateKey(privateKey, p + 4, &m);
857  //Any error to report?
858  if(error)
859  return error;
860 
861  //Concatenate the Ed25519 public key
862  error = eddsaExportPublicKey(&privateKey->q, p + 4 + m, &n);
863  //Any error to report?
864  if(error)
865  return error;
866 
867  //The octet string value is preceded by a uint32 containing its length
868  STORE32BE(m + n, p);
869 
870  //Point to the next field
871  p += sizeof(uint32_t) + m + n;
872  length += sizeof(uint32_t) + m + n;
873 
874  //The private key is followed by a comment
875  error = sshFormatString("", p, &n);
876  //Any error to report?
877  if(error)
878  return error;
879 
880  //Point to the next field
881  p += n;
882  length += n;
883 
884  //The padding size is determined by the 'ciphername' field
885  for(n = 0; (length % 8) != 0; n++, length++)
886  {
887  p[n] = n + 1;
888  }
889 
890  //Total number of bytes that have been written
891  *written = length;
892 
893  //Successful processing
894  return NO_ERROR;
895 #else
896  //Not implemented
897  return ERROR_NOT_IMPLEMENTED;
898 #endif
899 }
900 
901 
902 /**
903  * @brief Format Ed448 private key blob (OpenSSH format)
904  * @param[in] privateKey Pointer to the Ed448 private key
905  * @param[out] p Buffer where to store the private key blob
906  * @param[out] written Length of the resulting private key blob
907  * @return Error code
908  **/
909 
911  uint8_t *p, size_t *written)
912 {
913 #if (SSH_ED448_SIGN_SUPPORT == ENABLED)
914  error_t error;
915  size_t m;
916  size_t n;
917  size_t length;
918 
919  //Total length of the private key blob
920  length = 0;
921 
922  //Format 'checkint' fields
923  STORE32BE(0x12345678, p);
924  STORE32BE(0x12345678, p + sizeof(uint32_t));
925 
926  //Point to the next field
927  p += 2 * sizeof(uint32_t);
928  length += 2 * sizeof(uint32_t);
929 
930  //Format key format identifier
931  error = sshFormatString("ssh-ed448", p, &n);
932  //Any error to report?
933  if(error)
934  return error;
935 
936  //Point to the next field
937  p += n;
938  length += n;
939 
940  //Format Ed448 public key
941  error = eddsaExportPublicKey(&privateKey->q, p + 4, &n);
942  //Any error to report?
943  if(error)
944  return error;
945 
946  //The octet string value is preceded by a uint32 containing its length
947  STORE32BE(n, p);
948 
949  //Point to the next field
950  p += sizeof(uint32_t) + n;
951  length += sizeof(uint32_t) + n;
952 
953  //Format Ed448 private key
954  error = eddsaExportPrivateKey(privateKey, p + 4, &m);
955  //Any error to report?
956  if(error)
957  return error;
958 
959  //Concatenate the Ed448 public key
960  error = eddsaExportPublicKey(&privateKey->q, p + 4 + m, &n);
961  //Any error to report?
962  if(error)
963  return error;
964 
965  //The octet string value is preceded by a uint32 containing its length
966  STORE32BE(m + n, p);
967 
968  //Point to the next field
969  p += sizeof(uint32_t) + m + n;
970  length += sizeof(uint32_t) + m + n;
971 
972  //The private key is followed by a comment
973  error = sshFormatString("", p, &n);
974  //Any error to report?
975  if(error)
976  return error;
977 
978  //Point to the next field
979  p += n;
980  length += n;
981 
982  //The padding size is determined by the 'ciphername' field
983  for(n = 0; (length % 8) != 0; n++, length++)
984  {
985  p[n] = n + 1;
986  }
987 
988  //Total number of bytes that have been written
989  *written = length;
990 
991  //Successful processing
992  return NO_ERROR;
993 #else
994  //Not implemented
995  return ERROR_NOT_IMPLEMENTED;
996 #endif
997 }
998 
999 #endif
@ 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 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
Mpi p
First factor.
Definition: rsa.h:72
error_t sshFormatOpenSshEcdsaPrivateKey(const EcPrivateKey *privateKey, uint8_t *p, size_t *written)
Format ECDSA private key blob (OpenSSH format)
error_t eddsaExportPrivateKey(const EddsaPrivateKey *key, uint8_t *data, size_t *length)
Export an EdDSA private key.
Definition: eddsa.c:424
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
error_t eddsaExportPublicKey(const EddsaPublicKey *key, uint8_t *data, size_t *length)
Export an EdDSA public key.
Definition: eddsa.c:327
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
const EcCurve * curve
Elliptic curve parameters.
Definition: ec.h:433
Mpi q
Group order.
Definition: dsa.h:51
Mpi n
Modulus.
Definition: rsa.h:69
error_t sshFormatOpenSshEd448PrivateKey(const EddsaPrivateKey *privateKey, uint8_t *p, size_t *written)
Format Ed448 private key blob (OpenSSH format)
@ EC_PUBLIC_KEY_FORMAT_X963
Definition: ec.h:386
#define osStrcmp(s1, s2)
Definition: os_port.h:174
SSH key parsing.
Mpi e
Public exponent.
Definition: rsa.h:59
Mpi p
Prime modulus.
Definition: dsa.h:50
error_t sshFormatEd448PublicKey(const EddsaPublicKey *publicKey, uint8_t *p, size_t *written)
Format an Ed448 public host key.
Mpi d
Private exponent.
Definition: rsa.h:71
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.
DSA public key.
Definition: dsa.h:61
error_t
Error codes.
Definition: error.h:43
Mpi g
Group generator.
Definition: dsa.h:52
EdDSA public key.
Definition: eddsa.h:64
Mpi q
Second factor.
Definition: rsa.h:73
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
error_t sshFormatEd25519PublicKey(const EddsaPublicKey *publicKey, uint8_t *p, size_t *written)
Format an Ed25519 public host key.
Mpi y
Public key value.
Definition: dsa.h:75
EcPublicKey q
Public key.
Definition: ec.h:436
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 sshFormatDsaPublicKey(const DsaPublicKey *publicKey, uint8_t *p, size_t *written)
Format a DSA public host key.
Mpi qinv
CRT coefficient.
Definition: rsa.h:76
error_t ecExportPublicKey(const EcPublicKey *key, uint8_t *data, size_t *length, EcPublicKeyFormat format)
Export an EC public key.
Definition: ec.c:378
EdDSA private key.
Definition: eddsa.h:75
error_t sshFormatMpint(const Mpi *value, uint8_t *p, size_t *written)
Format a multiple precision integer.
Definition: ssh_misc.c:1483
EC public key.
Definition: ec.h:421
char char_t
Definition: compiler_port.h:55
uint32_t d[EC_MAX_ORDER_SIZE]
Private key.
Definition: ec.h:434
uint8_t m
Definition: ndp.h:304
uint8_t n
RSA private key.
Definition: rsa.h:68
Mpi x
Secret exponent.
Definition: dsa.h:74
SSH helper functions.
Mpi y
Public key value.
Definition: dsa.h:63
EddsaPublicKey q
Public key.
Definition: eddsa.h:79
DsaDomainParameters params
DSA domain parameters.
Definition: dsa.h:73
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
#define SSH_AUTH_MAGIC_SIZE
Definition: ssh_key_parse.h:38
Secure Shell (SSH)
const EcCurve * curve
Elliptic curve parameters.
Definition: ec.h:422
#define STORE32BE(a, p)
Definition: cpu_endian.h:286
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:150