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.2
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 = SSH_INC_POINTER(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 = SSH_INC_POINTER(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 = SSH_INC_POINTER(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 = SSH_INC_POINTER(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 = SSH_INC_POINTER(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 = SSH_INC_POINTER(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 = SSH_INC_POINTER(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 = SSH_INC_POINTER(p, n);
244  *written += n;
245 
246  //Format EC public key
247  error = ecExportPublicKey(publicKey, SSH_INC_POINTER(p, sizeof(uint32_t)),
249  //Any error to report?
250  if(error)
251  return error;
252 
253  //The octet string value is preceded by a uint32 containing its length
254  if(p != NULL)
255  {
256  STORE32BE(n, p);
257  }
258 
259  //Total number of bytes that have been written
260  *written += sizeof(uint32_t) + n;
261 
262  //Successful processing
263  return NO_ERROR;
264 #else
265  //Not implemented
266  return ERROR_NOT_IMPLEMENTED;
267 #endif
268 }
269 
270 
271 /**
272  * @brief Format an Ed25519 public host key
273  * @param[in] publicKey Pointer to the Ed25519 public key
274  * @param[out] p Buffer where to store the host key structure
275  * @param[out] written Length of the resulting host key structure
276  * @return Error code
277  **/
278 
280  uint8_t *p, size_t *written)
281 {
282 #if (SSH_ED25519_SIGN_SUPPORT == ENABLED)
283  error_t error;
284  size_t n;
285 
286  //Total length of the public host key structure
287  *written = 0;
288 
289  //Format public key format identifier
290  error = sshFormatString("ssh-ed25519", p, &n);
291  //Any error to report?
292  if(error)
293  return error;
294 
295  //Point to the next field
296  p = SSH_INC_POINTER(p, n);
297  *written += n;
298 
299  //Format Ed25519 public key
300  error = eddsaExportPublicKey(publicKey,
301  SSH_INC_POINTER(p, sizeof(uint32_t)), &n);
302  //Any error to report?
303  if(error)
304  return error;
305 
306  //The octet string value is preceded by a uint32 containing its length
307  if(p != NULL)
308  {
309  STORE32BE(n, p);
310  }
311 
312  //Total number of bytes that have been written
313  *written += sizeof(uint32_t) + n;
314 
315  //Successful processing
316  return NO_ERROR;
317 #else
318  //Not implemented
319  return ERROR_NOT_IMPLEMENTED;
320 #endif
321 }
322 
323 
324 /**
325  * @brief Format an Ed448 public host key
326  * @param[in] publicKey Pointer to the Ed448 public key
327  * @param[out] p Buffer where to store the host key structure
328  * @param[out] written Length of the resulting host key structure
329  * @return Error code
330  **/
331 
333  uint8_t *p, size_t *written)
334 {
335 #if (SSH_ED448_SIGN_SUPPORT == ENABLED)
336  error_t error;
337  size_t n;
338 
339  //Total length of the public host key structure
340  *written = 0;
341 
342  //Format public key format identifier
343  error = sshFormatString("ssh-ed448", p, &n);
344  //Any error to report?
345  if(error)
346  return error;
347 
348  //Point to the next field
349  p = SSH_INC_POINTER(p, n);
350  *written += n;
351 
352  //Format Ed448 public key
353  error = eddsaExportPublicKey(publicKey,
354  SSH_INC_POINTER(p, sizeof(uint32_t)), &n);
355  //Any error to report?
356  if(error)
357  return error;
358 
359  //The octet string value is preceded by a uint32 containing its length
360  if(p != NULL)
361  {
362  STORE32BE(n, p);
363  }
364 
365  //Total number of bytes that have been written
366  *written += sizeof(uint32_t) + n;
367 
368  //Successful processing
369  return NO_ERROR;
370 #else
371  //Not implemented
372  return ERROR_NOT_IMPLEMENTED;
373 #endif
374 }
375 
376 
377 /**
378  * @brief Format private key header (OpenSSH format)
379  * @param[out] p Buffer where to store the private key header
380  * @param[out] written Length of the resulting private key header
381  * @return Error code
382  **/
383 
384 error_t sshFormatOpenSshPrivateKeyHeader(uint8_t *p, size_t *written)
385 {
386  error_t error;
387  size_t n;
388 
389  //Total length of the private key header
390  *written = 0;
391 
392  //Format magic identifier
393  if(p != NULL)
394  {
395  osMemmove(p, "openssh-key-v1", SSH_AUTH_MAGIC_SIZE);
396  }
397 
398  //Point to the next field
400  *written += SSH_AUTH_MAGIC_SIZE;
401 
402  //Format 'ciphername' field (for unencrypted keys the cipher "none" is used)
403  error = sshFormatString("none", p, &n);
404  //Any error to report?
405  if(error)
406  return error;
407 
408  //Point to the next field
409  p = SSH_INC_POINTER(p, n);
410  *written += n;
411 
412  //Format 'kdfname' field (for unencrypted keys the KDF "none" is used)
413  error = sshFormatString("none", p, &n);
414  //Any error to report?
415  if(error)
416  return error;
417 
418  //Point to the next field
419  p = SSH_INC_POINTER(p, n);
420  *written += n;
421 
422  //Format 'kdfoptions' field
423  error = sshFormatString("", p, &n);
424  //Any error to report?
425  if(error)
426  return error;
427 
428  //Point to the next field
429  p = SSH_INC_POINTER(p, n);
430  *written += n;
431 
432  //Format 'number of keys' field
433  if(p != NULL)
434  {
435  STORE32BE(1, p);
436  }
437 
438  //Total number of bytes that have been written
439  *written += sizeof(uint32_t);
440 
441  //Successful processing
442  return NO_ERROR;
443 }
444 
445 
446 /**
447  * @brief Format RSA private key blob (OpenSSH format)
448  * @param[in] privateKey Pointer to the RSA private key
449  * @param[out] p Buffer where to store the private key blob
450  * @param[out] written Length of the resulting private key blob
451  * @return Error code
452  **/
453 
455  uint8_t *p, size_t *written)
456 {
457 #if (SSH_RSA_SIGN_SUPPORT == ENABLED)
458  error_t error;
459  size_t n;
460  size_t length;
461 
462  //Total length of the private key blob
463  length = 0;
464 
465  //Format 'checkint' fields
466  if(p != NULL)
467  {
468  STORE32BE(0x12345678, p);
469  STORE32BE(0x12345678, p + sizeof(uint32_t));
470  }
471 
472  //Point to the next field
473  p = SSH_INC_POINTER(p, 2 * sizeof(uint32_t));
474  length += 2 * sizeof(uint32_t);
475 
476  //Format key format identifier
477  error = sshFormatString("ssh-rsa", p, &n);
478  //Any error to report?
479  if(error)
480  return error;
481 
482  //Point to the next field
483  p = SSH_INC_POINTER(p, n);
484  length += n;
485 
486  //Format RSA modulus
487  error = sshFormatMpint(&privateKey->n, p, &n);
488  //Any error to report?
489  if(error)
490  return error;
491 
492  //Point to the next field
493  p = SSH_INC_POINTER(p, n);
494  length += n;
495 
496  //Format RSA public exponent
497  error = sshFormatMpint(&privateKey->e, p, &n);
498  //Any error to report?
499  if(error)
500  return error;
501 
502  //Point to the next field
503  p = SSH_INC_POINTER(p, n);
504  length += n;
505 
506  //Format RSA private exponent
507  error = sshFormatMpint(&privateKey->d, p, &n);
508  //Any error to report?
509  if(error)
510  return error;
511 
512  //Point to the next field
513  p = SSH_INC_POINTER(p, n);
514  length += n;
515 
516  //Format RSA CRT coefficient
517  error = sshFormatMpint(&privateKey->qinv, p, &n);
518  //Any error to report?
519  if(error)
520  return error;
521 
522  //Point to the next field
523  p = SSH_INC_POINTER(p, n);
524  length += n;
525 
526  //Parse RSA first factor
527  error = sshFormatMpint(&privateKey->p, p, &n);
528  //Any error to report?
529  if(error)
530  return error;
531 
532  //Point to the next field
533  p = SSH_INC_POINTER(p, n);
534  length += n;
535 
536  //Parse RSA second factor
537  error = sshFormatMpint(&privateKey->q, p, &n);
538  //Any error to report?
539  if(error)
540  return error;
541 
542  //Point to the next field
543  p = SSH_INC_POINTER(p, n);
544  length += n;
545 
546  //The private key is followed by a comment
547  error = sshFormatString("", p, &n);
548  //Any error to report?
549  if(error)
550  return error;
551 
552  //Point to the next field
553  p = SSH_INC_POINTER(p, n);
554  length += n;
555 
556  //The padding size is determined by the 'ciphername' field
557  for(n = 0; (length % 8) != 0; n++, length++)
558  {
559  if(p != NULL)
560  {
561  p[n] = n + 1;
562  }
563  }
564 
565  //Total number of bytes that have been written
566  *written = length;
567 
568  //Successful processing
569  return NO_ERROR;
570 #else
571  //Not implemented
572  return ERROR_NOT_IMPLEMENTED;
573 #endif
574 }
575 
576 
577 /**
578  * @brief Format DSA private key blob (OpenSSH format)
579  * @param[in] privateKey Pointer to the DSA private key
580  * @param[out] p Buffer where to store the private key blob
581  * @param[out] written Length of the resulting private key blob
582  * @return Error code
583  **/
584 
586  uint8_t *p, size_t *written)
587 {
588 #if (SSH_DSA_SIGN_SUPPORT == ENABLED)
589  error_t error;
590  size_t n;
591  size_t length;
592 
593  //Total length of the private key blob
594  length = 0;
595 
596  //Format 'checkint' fields
597  if(p != NULL)
598  {
599  STORE32BE(0x12345678, p);
600  STORE32BE(0x12345678, p + sizeof(uint32_t));
601  }
602 
603  //Point to the next field
604  p = SSH_INC_POINTER(p, 2 * sizeof(uint32_t));
605  length += 2 * sizeof(uint32_t);
606 
607  //Format key format identifier
608  error = sshFormatString("ssh-dss", p, &n);
609  //Any error to report?
610  if(error)
611  return error;
612 
613  //Point to the next field
614  p = SSH_INC_POINTER(p, n);
615  length += n;
616 
617  //Format DSA prime modulus
618  error = sshFormatMpint(&privateKey->params.p, p, &n);
619  //Any error to report?
620  if(error)
621  return error;
622 
623  //Point to the next field
624  p = SSH_INC_POINTER(p, n);
625  length += n;
626 
627  //Format DSA group order
628  error = sshFormatMpint(&privateKey->params.q, p, &n);
629  //Any error to report?
630  if(error)
631  return error;
632 
633  //Point to the next field
634  p = SSH_INC_POINTER(p, n);
635  length += n;
636 
637  //Format DSA group generator
638  error = sshFormatMpint(&privateKey->params.g, p, &n);
639  //Any error to report?
640  if(error)
641  return error;
642 
643  //Point to the next field
644  p = SSH_INC_POINTER(p, n);
645  length += n;
646 
647  //Format DSA public key value
648  error = sshFormatMpint(&privateKey->y, p, &n);
649  //Any error to report?
650  if(error)
651  return error;
652 
653  //Point to the next field
654  p = SSH_INC_POINTER(p, n);
655  length += n;
656 
657  //Format DSA private key value
658  error = sshFormatMpint(&privateKey->x, p, &n);
659  //Any error to report?
660  if(error)
661  return error;
662 
663  //Point to the next field
664  p = SSH_INC_POINTER(p, n);
665  length += n;
666 
667  //The private key is followed by a comment
668  error = sshFormatString("", p, &n);
669  //Any error to report?
670  if(error)
671  return error;
672 
673  //Point to the next field
674  p = SSH_INC_POINTER(p, n);
675  length += n;
676 
677  //The padding size is determined by the 'ciphername' field
678  for(n = 0; (length % 8) != 0; n++, length++)
679  {
680  if(p != NULL)
681  {
682  p[n] = n + 1;
683  }
684  }
685 
686  //Total number of bytes that have been written
687  *written = length;
688 
689  //Successful processing
690  return NO_ERROR;
691 #else
692  //Not implemented
693  return ERROR_NOT_IMPLEMENTED;
694 #endif
695 }
696 
697 
698 /**
699  * @brief Format ECDSA private key blob (OpenSSH format)
700  * @param[in] privateKey Pointer to the ECDSA private key
701  * @param[out] p Buffer where to store the private key blob
702  * @param[out] written Length of the resulting private key blob
703  * @return Error code
704  **/
705 
707  uint8_t *p, size_t *written)
708 {
709 #if (SSH_ECDSA_SIGN_SUPPORT == ENABLED)
710  error_t error;
711  size_t n;
712  size_t length;
713  const char_t *keyFormatId;
714  const char_t *curveName;
715 
716  //Invalid elliptic curve?
717  if(privateKey->curve == NULL ||
718  privateKey->curve != privateKey->q.curve)
719  {
721  }
722 
723  //Total length of the private key blob
724  length = 0;
725 
726  //Format 'checkint' fields
727  if(p != NULL)
728  {
729  STORE32BE(0x12345678, p);
730  STORE32BE(0x12345678, p + sizeof(uint32_t));
731  }
732 
733  //Point to the next field
734  p = SSH_INC_POINTER(p, 2 * sizeof(uint32_t));
735  length += 2 * sizeof(uint32_t);
736 
737  //Check elliptic curve
738  if(osStrcmp(privateKey->curve->name, "secp256r1") == 0)
739  {
740  //Select NIST P-256 elliptic curve
741  keyFormatId = "ecdsa-sha2-nistp256";
742  curveName = "nistp256";
743  }
744  else if(osStrcmp(privateKey->curve->name, "secp384r1") == 0)
745  {
746  //Select NIST P-384 elliptic curve
747  keyFormatId = "ecdsa-sha2-nistp384";
748  curveName = "nistp384";
749  }
750  else if(osStrcmp(privateKey->curve->name, "secp521r1") == 0)
751  {
752  //Select NIST P-521 elliptic curve
753  keyFormatId = "ecdsa-sha2-nistp521";
754  curveName = "nistp521";
755  }
756  else
757  {
758  //Unknown host key algorithm
760  }
761 
762  //Format public key format identifier
763  error = sshFormatString(keyFormatId, p, &n);
764  //Any error to report?
765  if(error)
766  return error;
767 
768  //Point to the next field
769  p = SSH_INC_POINTER(p, n);
770  length += n;
771 
772  //Format the elliptic curve domain parameter identifier
773  error = sshFormatString(curveName, p, &n);
774  //Any error to report?
775  if(error)
776  return error;
777 
778  //Point to the next field
779  p = SSH_INC_POINTER(p, n);
780  length += n;
781 
782  //Format EC public key
783  error = ecExportPublicKey(&privateKey->q,
784  SSH_INC_POINTER(p, sizeof(uint32_t)), &n, EC_PUBLIC_KEY_FORMAT_X963);
785  //Any error to report?
786  if(error)
787  return error;
788 
789  //The octet string value is preceded by a uint32 containing its length
790  if(p != NULL)
791  {
792  STORE32BE(n, p);
793  }
794 
795  //Point to the next field
796  p = SSH_INC_POINTER(p, sizeof(uint32_t) + n);
797  length += sizeof(uint32_t) + n;
798 
799  //Get the length of the private key, in words
800  n = (privateKey->curve->orderSize + 31) / 32;
801 
802  //Format EC private key
803  error = sshConvertScalarToMpint(privateKey->d, n, p, &n);
804  //Any error to report?
805  if(error)
806  return error;
807 
808  //Point to the next field
809  p = SSH_INC_POINTER(p, n);
810  length += n;
811 
812  //The private key is followed by a comment
813  error = sshFormatString("", p, &n);
814  //Any error to report?
815  if(error)
816  return error;
817 
818  //Point to the next field
819  p = SSH_INC_POINTER(p, n);
820  length += n;
821 
822  //The padding size is determined by the 'ciphername' field
823  for(n = 0; (length % 8) != 0; n++, length++)
824  {
825  if(p != NULL)
826  {
827  p[n] = n + 1;
828  }
829  }
830 
831  //Total number of bytes that have been written
832  *written = length;
833 
834  //Successful processing
835  return NO_ERROR;
836 #else
837  //Not implemented
838  return ERROR_NOT_IMPLEMENTED;
839 #endif
840 }
841 
842 
843 /**
844  * @brief Format Ed25519 private key blob (OpenSSH format)
845  * @param[in] privateKey Pointer to the Ed25519 private key
846  * @param[out] p Buffer where to store the private key blob
847  * @param[out] written Length of the resulting private key blob
848  * @return Error code
849  **/
850 
852  uint8_t *p, size_t *written)
853 {
854 #if (SSH_ED25519_SIGN_SUPPORT == ENABLED)
855  error_t error;
856  size_t m;
857  size_t n;
858  size_t length;
859 
860  //Total length of the private key blob
861  length = 0;
862 
863  //Format 'checkint' fields
864  if(p != NULL)
865  {
866  STORE32BE(0x12345678, p);
867  STORE32BE(0x12345678, p + sizeof(uint32_t));
868  }
869 
870  //Point to the next field
871  p = SSH_INC_POINTER(p, 2 * sizeof(uint32_t));
872  length += 2 * sizeof(uint32_t);
873 
874  //Format key format identifier
875  error = sshFormatString("ssh-ed25519", p, &n);
876  //Any error to report?
877  if(error)
878  return error;
879 
880  //Point to the next field
881  p = SSH_INC_POINTER(p, n);
882  length += n;
883 
884  //Format Ed25519 public key
885  error = eddsaExportPublicKey(&privateKey->q,
886  SSH_INC_POINTER(p, sizeof(uint32_t)), &n);
887  //Any error to report?
888  if(error)
889  return error;
890 
891  //The octet string value is preceded by a uint32 containing its length
892  if(p != NULL)
893  {
894  STORE32BE(n, p);
895  }
896 
897  //Point to the next field
898  p = SSH_INC_POINTER(p, sizeof(uint32_t) + n);
899  length += sizeof(uint32_t) + n;
900 
901  //Format Ed25519 private key
902  error = eddsaExportPrivateKey(privateKey,
903  SSH_INC_POINTER(p, sizeof(uint32_t)), &m);
904  //Any error to report?
905  if(error)
906  return error;
907 
908  //Concatenate the Ed25519 public key
909  error = eddsaExportPublicKey(&privateKey->q,
910  SSH_INC_POINTER(p, sizeof(uint32_t) + m), &n);
911  //Any error to report?
912  if(error)
913  return error;
914 
915  //The octet string value is preceded by a uint32 containing its length
916  if(p != NULL)
917  {
918  STORE32BE(m + n, p);
919  }
920 
921  //Point to the next field
922  p = SSH_INC_POINTER(p, sizeof(uint32_t) + m + n);
923  length += sizeof(uint32_t) + m + n;
924 
925  //The private key is followed by a comment
926  error = sshFormatString("", p, &n);
927  //Any error to report?
928  if(error)
929  return error;
930 
931  //Point to the next field
932  p = SSH_INC_POINTER(p, n);
933  length += n;
934 
935  //The padding size is determined by the 'ciphername' field
936  for(n = 0; (length % 8) != 0; n++, length++)
937  {
938  if(p != NULL)
939  {
940  p[n] = n + 1;
941  }
942  }
943 
944  //Total number of bytes that have been written
945  *written = length;
946 
947  //Successful processing
948  return NO_ERROR;
949 #else
950  //Not implemented
951  return ERROR_NOT_IMPLEMENTED;
952 #endif
953 }
954 
955 
956 /**
957  * @brief Format Ed448 private key blob (OpenSSH format)
958  * @param[in] privateKey Pointer to the Ed448 private key
959  * @param[out] p Buffer where to store the private key blob
960  * @param[out] written Length of the resulting private key blob
961  * @return Error code
962  **/
963 
965  uint8_t *p, size_t *written)
966 {
967 #if (SSH_ED448_SIGN_SUPPORT == ENABLED)
968  error_t error;
969  size_t m;
970  size_t n;
971  size_t length;
972 
973  //Total length of the private key blob
974  length = 0;
975 
976  //Format 'checkint' fields
977  if(p != NULL)
978  {
979  STORE32BE(0x12345678, p);
980  STORE32BE(0x12345678, p + sizeof(uint32_t));
981  }
982 
983  //Point to the next field
984  p = SSH_INC_POINTER(p, 2 * sizeof(uint32_t));
985  length += 2 * sizeof(uint32_t);
986 
987  //Format key format identifier
988  error = sshFormatString("ssh-ed448", p, &n);
989  //Any error to report?
990  if(error)
991  return error;
992 
993  //Point to the next field
994  p = SSH_INC_POINTER(p, n);
995  length += n;
996 
997  //Format Ed448 public key
998  error = eddsaExportPublicKey(&privateKey->q,
999  SSH_INC_POINTER(p, sizeof(uint32_t)), &n);
1000  //Any error to report?
1001  if(error)
1002  return error;
1003 
1004  //The octet string value is preceded by a uint32 containing its length
1005  if(p != NULL)
1006  {
1007  STORE32BE(n, p);
1008  }
1009 
1010  //Point to the next field
1011  p = SSH_INC_POINTER(p, sizeof(uint32_t) + n);
1012  length += sizeof(uint32_t) + n;
1013 
1014  //Format Ed448 private key
1015  error = eddsaExportPrivateKey(privateKey,
1016  SSH_INC_POINTER(p, sizeof(uint32_t)), &m);
1017  //Any error to report?
1018  if(error)
1019  return error;
1020 
1021  //Concatenate the Ed448 public key
1022  error = eddsaExportPublicKey(&privateKey->q,
1023  SSH_INC_POINTER(p, sizeof(uint32_t) + m), &n);
1024  //Any error to report?
1025  if(error)
1026  return error;
1027 
1028  //The octet string value is preceded by a uint32 containing its length
1029  if(p != NULL)
1030  {
1031  STORE32BE(m + n, p);
1032  }
1033 
1034  //Point to the next field
1035  p = SSH_INC_POINTER(p, sizeof(uint32_t) + m + n);
1036  length += sizeof(uint32_t) + m + n;
1037 
1038  //The private key is followed by a comment
1039  error = sshFormatString("", p, &n);
1040  //Any error to report?
1041  if(error)
1042  return error;
1043 
1044  //Point to the next field
1045  p = SSH_INC_POINTER(p, n);
1046  length += n;
1047 
1048  //The padding size is determined by the 'ciphername' field
1049  for(n = 0; (length % 8) != 0; n++, length++)
1050  {
1051  if(p != NULL)
1052  {
1053  p[n] = n + 1;
1054  }
1055  }
1056 
1057  //Total number of bytes that have been written
1058  *written = length;
1059 
1060  //Successful processing
1061  return NO_ERROR;
1062 #else
1063  //Not implemented
1064  return ERROR_NOT_IMPLEMENTED;
1065 #endif
1066 }
1067 
1068 #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:1563
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_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
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
error_t ecExportPublicKey(const EcPublicKey *key, uint8_t *output, size_t *written, EcPublicKeyFormat format)
Export an EC public key.
Definition: ec.c:378
#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.
error_t eddsaExportPublicKey(const EddsaPublicKey *key, uint8_t *output, size_t *written)
Export an EdDSA public key.
Definition: eddsa.c:328
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
#define SSH_INC_POINTER(p, n)
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
error_t eddsaExportPrivateKey(const EddsaPrivateKey *key, uint8_t *output, size_t *written)
Export an EdDSA private key.
Definition: eddsa.c:436
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
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:1507
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:1399
@ 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