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-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_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] params EC domain parameters
180  * @param[in] publicKey Pointer to the ECDSA public key
181  * @param[out] p Buffer where to store the host key structure
182  * @param[out] written Length of the resulting host key structure
183  * @return Error code
184  **/
185 
187  const EcPublicKey *publicKey, uint8_t *p, size_t *written)
188 {
189 #if (SSH_ECDSA_SIGN_SUPPORT == ENABLED)
190  error_t error;
191  size_t n;
192  const char_t *keyFormatId;
193  const char_t *curveName;
194 
195  //Total length of the public host key structure
196  *written = 0;
197 
198  //Check elliptic curve
199  if(!osStrcmp(params->name, "secp256r1"))
200  {
201  //Select NIST P-256 elliptic curve
202  keyFormatId = "ecdsa-sha2-nistp256";
203  curveName = "nistp256";
204  }
205  else if(!osStrcmp(params->name, "secp384r1"))
206  {
207  //Select NIST P-384 elliptic curve
208  keyFormatId = "ecdsa-sha2-nistp384";
209  curveName = "nistp384";
210  }
211  else if(!osStrcmp(params->name, "secp521r1"))
212  {
213  //Select NIST P-521 elliptic curve
214  keyFormatId = "ecdsa-sha2-nistp521";
215  curveName = "nistp521";
216  }
217  else
218  {
219  //Unknown host key algorithm
221  }
222 
223  //Format public key format identifier
224  error = sshFormatString(keyFormatId, p, &n);
225  //Any error to report?
226  if(error)
227  return error;
228 
229  //Point to the next field
230  p += n;
231  *written += n;
232 
233  //Format the elliptic curve domain parameter identifier
234  error = sshFormatString(curveName, p, &n);
235  //Any error to report?
236  if(error)
237  return error;
238 
239  //Point to the next field
240  p += n;
241  *written += n;
242 
243  //Format EC public key
244  error = ecExport(params, &publicKey->q, p + 4, &n);
245  //Any error to report?
246  if(error)
247  return error;
248 
249  //The octet string value is preceded by a uint32 containing its length
250  STORE32BE(n, p);
251 
252  //Total number of bytes that have been written
253  *written += sizeof(uint32_t) + n;
254 
255  //Successful processing
256  return NO_ERROR;
257 #else
258  //Not implemented
259  return ERROR_NOT_IMPLEMENTED;
260 #endif
261 }
262 
263 
264 /**
265  * @brief Format an Ed25519 public host key
266  * @param[in] publicKey Pointer to the Ed25519 public key
267  * @param[out] p Buffer where to store the host key structure
268  * @param[out] written Length of the resulting host key structure
269  * @return Error code
270  **/
271 
273  uint8_t *p, size_t *written)
274 {
275 #if (SSH_ED25519_SIGN_SUPPORT == ENABLED)
276  error_t error;
277  size_t n;
278 
279  //Total length of the public host key structure
280  *written = 0;
281 
282  //Format public key format identifier
283  error = sshFormatString("ssh-ed25519", p, &n);
284  //Any error to report?
285  if(error)
286  return error;
287 
288  //Point to the next field
289  p += n;
290  *written += n;
291 
292  //The public key shall consist of 32 octets
294 
295  //Format Ed25519 public key
296  error = mpiExport(&publicKey->q, p + 4, n, MPI_FORMAT_LITTLE_ENDIAN);
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  //The public key shall consist of 57 octets
346 
347  //Format Ed448 public key
348  error = mpiExport(&publicKey->q, p + 4, n, MPI_FORMAT_LITTLE_ENDIAN);
349  //Any error to report?
350  if(error)
351  return error;
352 
353  //The octet string value is preceded by a uint32 containing its length
354  STORE32BE(n, p);
355 
356  //Total number of bytes that have been written
357  *written += sizeof(uint32_t) + n;
358 
359  //Successful processing
360  return NO_ERROR;
361 #else
362  //Not implemented
363  return ERROR_NOT_IMPLEMENTED;
364 #endif
365 }
366 
367 
368 /**
369  * @brief Format private key header (OpenSSH format)
370  * @param[out] p Buffer where to store the private key header
371  * @param[out] written Length of the resulting private key header
372  * @return Error code
373  **/
374 
375 error_t sshFormatOpenSshPrivateKeyHeader(uint8_t *p, size_t *written)
376 {
377  error_t error;
378  size_t n;
379 
380  //Total length of the private key header
381  *written = 0;
382 
383  //Format magic identifier
384  osMemmove(p, "openssh-key-v1", SSH_AUTH_MAGIC_SIZE);
385 
386  //Point to the next field
388  *written += SSH_AUTH_MAGIC_SIZE;
389 
390  //Format 'ciphername' field (for unencrypted keys the cipher "none" is used)
391  error = sshFormatString("none", p, &n);
392  //Any error to report?
393  if(error)
394  return error;
395 
396  //Point to the next field
397  p += n;
398  *written += n;
399 
400  //Format 'kdfname' field (for unencrypted keys the KDF "none" is used)
401  error = sshFormatString("none", p, &n);
402  //Any error to report?
403  if(error)
404  return error;
405 
406  //Point to the next field
407  p += n;
408  *written += n;
409 
410  //Format 'kdfoptions' field
411  error = sshFormatString("", p, &n);
412  //Any error to report?
413  if(error)
414  return error;
415 
416  //Point to the next field
417  p += n;
418  *written += n;
419 
420  //Format 'number of keys' field
421  STORE32BE(1, p);
422 
423  //Total number of bytes that have been written
424  *written += n;
425 
426  //Successful processing
427  return NO_ERROR;
428 }
429 
430 
431 /**
432  * @brief Format RSA private key blob (OpenSSH format)
433  * @param[in] privateKey Pointer to the RSA private key
434  * @param[out] p Buffer where to store the private key blob
435  * @param[out] written Length of the resulting private key blob
436  * @return Error code
437  **/
438 
440  uint8_t *p, size_t *written)
441 {
442 #if (SSH_RSA_SIGN_SUPPORT == ENABLED)
443  error_t error;
444  size_t n;
445  size_t length;
446 
447  //Total length of the private key blob
448  length = 0;
449 
450  //Format 'checkint' fields
451  STORE32BE(0x12345678, p);
452  STORE32BE(0x12345678, p + sizeof(uint32_t));
453 
454  //Point to the next field
455  p += 2 * sizeof(uint32_t);
456  length += 2 * sizeof(uint32_t);
457 
458  //Format key format identifier
459  error = sshFormatString("ssh-rsa", p, &n);
460  //Any error to report?
461  if(error)
462  return error;
463 
464  //Point to the next field
465  p += n;
466  length += n;
467 
468  //Format RSA modulus
469  error = sshFormatMpint(&privateKey->n, p, &n);
470  //Any error to report?
471  if(error)
472  return error;
473 
474  //Point to the next field
475  p += n;
476  length += n;
477 
478  //Format RSA public exponent
479  error = sshFormatMpint(&privateKey->e, p, &n);
480  //Any error to report?
481  if(error)
482  return error;
483 
484  //Point to the next field
485  p += n;
486  length += n;
487 
488  //Format RSA private exponent
489  error = sshFormatMpint(&privateKey->d, p, &n);
490  //Any error to report?
491  if(error)
492  return error;
493 
494  //Point to the next field
495  p += n;
496  length += n;
497 
498  //Format RSA CRT coefficient
499  error = sshFormatMpint(&privateKey->qinv, p, &n);
500  //Any error to report?
501  if(error)
502  return error;
503 
504  //Point to the next field
505  p += n;
506  length += n;
507 
508  //Parse RSA first factor
509  error = sshFormatMpint(&privateKey->p, p, &n);
510  //Any error to report?
511  if(error)
512  return error;
513 
514  //Point to the next field
515  p += n;
516  length += n;
517 
518  //Parse RSA second factor
519  error = sshFormatMpint(&privateKey->q, p, &n);
520  //Any error to report?
521  if(error)
522  return error;
523 
524  //Point to the next field
525  p += n;
526  length += n;
527 
528  //The private key is followed by a comment
529  error = sshFormatString("", p, &n);
530  //Any error to report?
531  if(error)
532  return error;
533 
534  //Point to the next field
535  p += n;
536  length += n;
537 
538  //The padding size is determined by the 'ciphername' field
539  for(n = 0; (length % 8) != 0; n++, length++)
540  {
541  p[n] = n + 1;
542  }
543 
544  //Total number of bytes that have been written
545  *written = length;
546 
547  //Successful processing
548  return NO_ERROR;
549 #else
550  //Not implemented
551  return ERROR_NOT_IMPLEMENTED;
552 #endif
553 }
554 
555 
556 /**
557  * @brief Format DSA private key blob (OpenSSH format)
558  * @param[in] privateKey Pointer to the DSA private key
559  * @param[in] publicKey Pointer to the DSA public key
560  * @param[out] p Buffer where to store the private key blob
561  * @param[out] written Length of the resulting private key blob
562  * @return Error code
563  **/
564 
566  const DsaPublicKey *publicKey, uint8_t *p, size_t *written)
567 {
568 #if (SSH_DSA_SIGN_SUPPORT == ENABLED)
569  error_t error;
570  size_t n;
571  size_t length;
572 
573  //Total length of the private key blob
574  length = 0;
575 
576  //Format 'checkint' fields
577  STORE32BE(0x12345678, p);
578  STORE32BE(0x12345678, p + sizeof(uint32_t));
579 
580  //Point to the next field
581  p += 2 * sizeof(uint32_t);
582  length += 2 * sizeof(uint32_t);
583 
584  //Format key format identifier
585  error = sshFormatString("ssh-dss", p, &n);
586  //Any error to report?
587  if(error)
588  return error;
589 
590  //Point to the next field
591  p += n;
592  length += n;
593 
594  //Format DSA prime modulus
595  error = sshFormatMpint(&privateKey->params.p, p, &n);
596  //Any error to report?
597  if(error)
598  return error;
599 
600  //Point to the next field
601  p += n;
602  length += n;
603 
604  //Format DSA group order
605  error = sshFormatMpint(&privateKey->params.q, p, &n);
606  //Any error to report?
607  if(error)
608  return error;
609 
610  //Point to the next field
611  p += n;
612  length += n;
613 
614  //Format DSA group generator
615  error = sshFormatMpint(&privateKey->params.g, p, &n);
616  //Any error to report?
617  if(error)
618  return error;
619 
620  //Point to the next field
621  p += n;
622  length += n;
623 
624  //Format DSA public key value
625  error = sshFormatMpint(&publicKey->y, p, &n);
626  //Any error to report?
627  if(error)
628  return error;
629 
630  //Point to the next field
631  p += n;
632  length += n;
633 
634  //Format DSA private key value
635  error = sshFormatMpint(&privateKey->x, p, &n);
636  //Any error to report?
637  if(error)
638  return error;
639 
640  //Point to the next field
641  p += n;
642  length += n;
643 
644  //The private key is followed by a comment
645  error = sshFormatString("", p, &n);
646  //Any error to report?
647  if(error)
648  return error;
649 
650  //Point to the next field
651  p += n;
652  length += n;
653 
654  //The padding size is determined by the 'ciphername' field
655  for(n = 0; (length % 8) != 0; n++, length++)
656  {
657  p[n] = n + 1;
658  }
659 
660  //Total number of bytes that have been written
661  *written = length;
662 
663  //Successful processing
664  return NO_ERROR;
665 #else
666  //Not implemented
667  return ERROR_NOT_IMPLEMENTED;
668 #endif
669 }
670 
671 
672 /**
673  * @brief Format ECDSA private key blob (OpenSSH format)
674  * @param[in] params EC domain parameters
675  * @param[in] privateKey Pointer to the ECDSA private key
676  * @param[in] publicKey Pointer to the ECDSA public key
677  * @param[out] p Buffer where to store the private key blob
678  * @param[out] written Length of the resulting private key blob
679  * @return Error code
680  **/
681 
683  const EcPrivateKey *privateKey, const EcPublicKey *publicKey,
684  uint8_t *p, size_t *written)
685 {
686 #if (SSH_ECDSA_SIGN_SUPPORT == ENABLED)
687  error_t error;
688  size_t n;
689  size_t length;
690  const char_t *keyFormatId;
691  const char_t *curveName;
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(params->name, "secp256r1"))
706  {
707  //Select NIST P-256 elliptic curve
708  keyFormatId = "ecdsa-sha2-nistp256";
709  curveName = "nistp256";
710  }
711  else if(!osStrcmp(params->name, "secp384r1"))
712  {
713  //Select NIST P-384 elliptic curve
714  keyFormatId = "ecdsa-sha2-nistp384";
715  curveName = "nistp384";
716  }
717  else if(!osStrcmp(params->name, "secp521r1"))
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 = ecExport(params, &publicKey->q, p + 4, &n);
751  //Any error to report?
752  if(error)
753  return error;
754 
755  //The octet string value is preceded by a uint32 containing its length
756  STORE32BE(n, p);
757 
758  //Point to the next field
759  p += sizeof(uint32_t) + n;
760  length += sizeof(uint32_t) + n;
761 
762  //Format EC private key
763  error = sshFormatMpint(&privateKey->d, p, &n);
764  //Any error to report?
765  if(error)
766  return error;
767 
768  //Point to the next field
769  p += n;
770  length += n;
771 
772  //The private key is followed by a comment
773  error = sshFormatString("", p, &n);
774  //Any error to report?
775  if(error)
776  return error;
777 
778  //Point to the next field
779  p += n;
780  length += n;
781 
782  //The padding size is determined by the 'ciphername' field
783  for(n = 0; (length % 8) != 0; n++, length++)
784  {
785  p[n] = n + 1;
786  }
787 
788  //Total number of bytes that have been written
789  *written = length;
790 
791  //Successful processing
792  return NO_ERROR;
793 #else
794  //Not implemented
795  return ERROR_NOT_IMPLEMENTED;
796 #endif
797 }
798 
799 
800 /**
801  * @brief Format Ed25519 private key blob (OpenSSH format)
802  * @param[in] privateKey Pointer to the Ed25519 private key
803  * @param[in] publicKey Pointer to the Ed25519 public key
804  * @param[out] p Buffer where to store the private key blob
805  * @param[out] written Length of the resulting private key blob
806  * @return Error code
807  **/
808 
810  const EddsaPublicKey *publicKey, uint8_t *p, size_t *written)
811 {
812 #if (SSH_ED25519_SIGN_SUPPORT == ENABLED)
813  error_t error;
814  size_t n;
815  size_t length;
816 
817  //Total length of the private key blob
818  length = 0;
819 
820  //Format 'checkint' fields
821  STORE32BE(0x12345678, p);
822  STORE32BE(0x12345678, p + sizeof(uint32_t));
823 
824  //Point to the next field
825  p += 2 * sizeof(uint32_t);
826  length += 2 * sizeof(uint32_t);
827 
828  //Format key format identifier
829  error = sshFormatString("ssh-ed25519", p, &n);
830  //Any error to report?
831  if(error)
832  return error;
833 
834  //Point to the next field
835  p += n;
836  length += n;
837 
838  //The public key shall consist of 32 octets
840 
841  //Format Ed25519 public key
842  error = mpiExport(&publicKey->q, p + 4, n, MPI_FORMAT_LITTLE_ENDIAN);
843  //Any error to report?
844  if(error)
845  return error;
846 
847  //The octet string value is preceded by a uint32 containing its length
848  STORE32BE(n, p);
849 
850  //Point to the next field
851  p += sizeof(uint32_t) + n;
852  length += sizeof(uint32_t) + n;
853 
854  //The private key shall consist of 64 octets
856 
857  //Format Ed25519 private key
858  error = mpiExport(&privateKey->d, p + 4, ED25519_PRIVATE_KEY_LEN,
860  //Any error to report?
861  if(error)
862  return error;
863 
864  //Format Ed25519 public key
865  error = mpiExport(&publicKey->q, p + 4 + ED25519_PRIVATE_KEY_LEN,
867  //Any error to report?
868  if(error)
869  return error;
870 
871  //The octet string value is preceded by a uint32 containing its length
872  STORE32BE(n, p);
873 
874  //Point to the next field
875  p += sizeof(uint32_t) + n;
876  length += sizeof(uint32_t) + n;
877 
878  //The private key is followed by a comment
879  error = sshFormatString("", p, &n);
880  //Any error to report?
881  if(error)
882  return error;
883 
884  //Point to the next field
885  p += n;
886  length += n;
887 
888  //The padding size is determined by the 'ciphername' field
889  for(n = 0; (length % 8) != 0; n++, length++)
890  {
891  p[n] = n + 1;
892  }
893 
894  //Total number of bytes that have been written
895  *written = length;
896 
897  //Successful processing
898  return NO_ERROR;
899 #else
900  //Not implemented
901  return ERROR_NOT_IMPLEMENTED;
902 #endif
903 }
904 
905 
906 /**
907  * @brief Format Ed448 private key blob (OpenSSH format)
908  * @param[in] privateKey Pointer to the Ed448 private key
909  * @param[in] publicKey Pointer to the Ed448 public key
910  * @param[out] p Buffer where to store the private key blob
911  * @param[out] written Length of the resulting private key blob
912  * @return Error code
913  **/
914 
916  const EddsaPublicKey *publicKey, uint8_t *p, size_t *written)
917 {
918 #if (SSH_ED448_SIGN_SUPPORT == ENABLED)
919  error_t error;
920  size_t n;
921  size_t length;
922 
923  //Total length of the private key blob
924  length = 0;
925 
926  //Format 'checkint' fields
927  STORE32BE(0x12345678, p);
928  STORE32BE(0x12345678, p + sizeof(uint32_t));
929 
930  //Point to the next field
931  p += 2 * sizeof(uint32_t);
932  length += 2 * sizeof(uint32_t);
933 
934  //Format key format identifier
935  error = sshFormatString("ssh-ed448", p, &n);
936  //Any error to report?
937  if(error)
938  return error;
939 
940  //Point to the next field
941  p += n;
942  length += n;
943 
944  //The public key shall consist of 57 octets
946 
947  //Format Ed448 public key
948  error = mpiExport(&publicKey->q, p + 4, n, MPI_FORMAT_LITTLE_ENDIAN);
949  //Any error to report?
950  if(error)
951  return error;
952 
953  //The octet string value is preceded by a uint32 containing its length
954  STORE32BE(n, p);
955 
956  //Point to the next field
957  p += sizeof(uint32_t) + n;
958  length += sizeof(uint32_t) + n;
959 
960  //The private key shall consist of 114 octets
962 
963  //Format Ed448 private key
964  error = mpiExport(&privateKey->d, p + 4, ED448_PRIVATE_KEY_LEN,
966  //Any error to report?
967  if(error)
968  return error;
969 
970  //Format Ed448 public key
971  error = mpiExport(&publicKey->q, p + 4 + ED448_PRIVATE_KEY_LEN,
973  //Any error to report?
974  if(error)
975  return error;
976 
977  //The octet string value is preceded by a uint32 containing its length
978  STORE32BE(n, p);
979 
980  //Point to the next field
981  p += sizeof(uint32_t) + n;
982  length += sizeof(uint32_t) + n;
983 
984  //The private key is followed by a comment
985  error = sshFormatString("", p, &n);
986  //Any error to report?
987  if(error)
988  return error;
989 
990  //Point to the next field
991  p += n;
992  length += n;
993 
994  //The padding size is determined by the 'ciphername' field
995  for(n = 0; (length % 8) != 0; n++, length++)
996  {
997  p[n] = n + 1;
998  }
999 
1000  //Total number of bytes that have been written
1001  *written = length;
1002 
1003  //Successful processing
1004  return NO_ERROR;
1005 #else
1006  //Not implemented
1007  return ERROR_NOT_IMPLEMENTED;
1008 #endif
1009 }
1010 
1011 #endif
char char_t
Definition: compiler_port.h:48
#define STORE32BE(a, p)
Definition: cpu_endian.h:286
Debugging facilities.
uint8_t n
error_t ecExport(const EcDomainParameters *params, const EcPoint *a, uint8_t *data, size_t *length)
Convert an EC point to an octet string.
Definition: ec.c:438
#define ED25519_PUBLIC_KEY_LEN
Definition: ed25519.h:42
#define ED25519_PRIVATE_KEY_LEN
Definition: ed25519.h:40
#define ED448_PRIVATE_KEY_LEN
Definition: ed448.h:40
#define ED448_PUBLIC_KEY_LEN
Definition: ed448.h:42
error_t
Error codes.
Definition: error.h:43
@ ERROR_UNSUPPORTED_SIGNATURE_ALGO
Definition: error.h:132
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
@ NO_ERROR
Success.
Definition: error.h:44
error_t mpiExport(const Mpi *a, uint8_t *data, uint_t length, MpiFormat format)
Integer to octet string conversion.
Definition: mpi.c:709
@ MPI_FORMAT_LITTLE_ENDIAN
Definition: mpi.h:70
uint8_t p
Definition: ndp.h:300
#define osStrcmp(s1, s2)
Definition: os_port.h:171
#define osMemmove(dest, src, length)
Definition: os_port.h:147
Secure Shell (SSH)
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.
SSH key parsing.
#define SSH_AUTH_MAGIC_SIZE
Definition: ssh_key_parse.h:38
error_t sshFormatString(const char_t *value, uint8_t *p, size_t *written)
Format a string.
Definition: ssh_misc.c:1384
error_t sshFormatMpint(const Mpi *value, uint8_t *p, size_t *written)
Format a multiple precision integer.
Definition: ssh_misc.c:1487
SSH helper functions.
Mpi p
Prime modulus.
Definition: dsa.h:50
Mpi q
Group order.
Definition: dsa.h:51
Mpi g
Group generator.
Definition: dsa.h:52
DSA private key.
Definition: dsa.h:72
DsaDomainParameters params
DSA domain parameters.
Definition: dsa.h:73
Mpi x
Secret exponent.
Definition: dsa.h:74
DSA public key.
Definition: dsa.h:61
Mpi y
Public key value.
Definition: dsa.h:63
DsaDomainParameters params
DSA domain parameters.
Definition: dsa.h:62
EC domain parameters.
Definition: ec.h:76
const char_t * name
Curve name.
Definition: ec.h:77
EC private key.
Definition: ec.h:104
Mpi d
Private key.
Definition: ec.h:105
EC public key.
Definition: ec.h:94
EcPoint q
Public key.
Definition: ec.h:95
EdDSA private key.
Definition: eddsa.h:59
Mpi d
Private key.
Definition: eddsa.h:60
EdDSA public key.
Definition: eddsa.h:49
Mpi q
Public key.
Definition: eddsa.h:50
RSA private key.
Definition: rsa.h:68
Mpi p
First factor.
Definition: rsa.h:72
Mpi e
Public exponent.
Definition: rsa.h:70
Mpi q
Second factor.
Definition: rsa.h:73
Mpi d
Private exponent.
Definition: rsa.h:71
Mpi qinv
CRT coefficient.
Definition: rsa.h:76
Mpi n
Modulus.
Definition: rsa.h:69
RSA public key.
Definition: rsa.h:57
Mpi e
Public exponent.
Definition: rsa.h:59
Mpi n
Modulus.
Definition: rsa.h:58
uint8_t length
Definition: tcp.h:368