ssh_cert_parse.c
Go to the documentation of this file.
1 /**
2  * @file ssh_cert_parse.c
3  * @brief SSH certificate parsing
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_cert_parse.h"
37 #include "ssh/ssh_misc.h"
38 #include "debug.h"
39 
40 //Check SSH stack configuration
41 #if (SSH_SUPPORT == ENABLED && SSH_CERT_SUPPORT == ENABLED)
42 
43 
44 /**
45  * @brief Parse SSH certificate
46  * @param[in] data Pointer to the certificate
47  * @param[in] length Length of the certificate, in bytes
48  * @param[out] cert Information resulting from the parsing process
49  * @return Error code
50  **/
51 
52 error_t sshParseCertificate(const uint8_t *data, size_t length,
53  SshCertificate *cert)
54 {
55  error_t error;
56  size_t n;
57 
58  //Clear the certificate information structure
59  osMemset(cert, 0, sizeof(SshCertificate));
60 
61  //Decode key format identifier
62  error = sshParseString(data, length, &cert->keyFormatId);
63  //Any error to report?
64  if(error)
65  return error;
66 
67  //Point to the next field
68  data += sizeof(uint32_t) + cert->keyFormatId.length;
69  length -= sizeof(uint32_t) + cert->keyFormatId.length;
70 
71  //Parse 'nonce' field
72  error = sshParseBinaryString(data, length, &cert->nonce);
73  //Any error to report?
74  if(error)
75  return error;
76 
77  //Point to the next field
78  data += sizeof(uint32_t) + cert->nonce.length;
79  length -= sizeof(uint32_t) + cert->nonce.length;
80 
81 #if (SSH_RSA_SIGN_SUPPORT == ENABLED)
82  //RSA certificate?
83  if(sshCompareString(&cert->keyFormatId, "ssh-rsa-cert-v01@openssh.com"))
84  {
85  //Parse RSA public key
87  &cert->publicKey.rsaPublicKey);
88  }
89  else
90 #endif
91 #if (SSH_DSA_SIGN_SUPPORT == ENABLED)
92  //DSA certificate?
93  if(sshCompareString(&cert->keyFormatId, "ssh-dss-cert-v01@openssh.com"))
94  {
95  //Parse DSA public key
97  &cert->publicKey.dsaPublicKey);
98  }
99  else
100 #endif
101 #if (SSH_ECDSA_SIGN_SUPPORT == ENABLED)
102  //ECDSA certificate?
103  if(sshCompareString(&cert->keyFormatId, "ecdsa-sha2-nistp256-cert-v01@openssh.com") ||
104  sshCompareString(&cert->keyFormatId, "ecdsa-sha2-nistp384-cert-v01@openssh.com") ||
105  sshCompareString(&cert->keyFormatId, "ecdsa-sha2-nistp521-cert-v01@openssh.com"))
106  {
107  //Parse ECDSA public key
109  &cert->publicKey.ecdsaPublicKey);
110  }
111  else
112 #endif
113 #if (SSH_ED25519_SIGN_SUPPORT == ENABLED)
114  //Ed25519 certificate?
115  if(sshCompareString(&cert->keyFormatId, "ssh-ed25519-cert-v01@openssh.com"))
116  {
117  //Parse Ed25519 public key
119  &cert->publicKey.ed25519PublicKey);
120  }
121  else
122 #endif
123  //Unknown certificate type?
124  {
125  //Report an error
126  error = ERROR_WRONG_IDENTIFIER;
127  }
128 
129  //Any error to report?
130  if(error)
131  return error;
132 
133  //Point to the next field
134  data += n;
135  length -= n;
136 
137  //Malformed certificate?
138  if(length < sizeof(uint64_t))
139  return ERROR_INVALID_SYNTAX;
140 
141  //Parse 'serial' field
142  cert->serial = LOAD64BE(data);
143 
144  //Point to the next field
145  data += sizeof(uint64_t);
146  length -= sizeof(uint64_t);
147 
148  //Malformed certificate?
149  if(length < sizeof(uint32_t))
150  return ERROR_INVALID_SYNTAX;
151 
152  //Parse 'type' field
153  cert->type = LOAD32BE(data);
154 
155  //Check certificate type
156  if(cert->type != SSH_CERT_TYPE_USER && cert->type != SSH_CERT_TYPE_HOST)
157  return ERROR_WRONG_TYPE;
158 
159  //Point to the next field
160  data += sizeof(uint32_t);
161  length -= sizeof(uint32_t);
162 
163  //Parse 'key id' field
164  error = sshParseString(data, length, &cert->keyId);
165  //Any error to report?
166  if(error)
167  return error;
168 
169  //Point to the next field
170  data += sizeof(uint32_t) + cert->keyId.length;
171  length -= sizeof(uint32_t) + cert->keyId.length;
172 
173  //Parse 'valid principals' field
175  //Any error to report?
176  if(error)
177  return error;
178 
179  //Point to the next field
180  data += sizeof(uint32_t) + cert->validPrincipals.length;
181  length -= sizeof(uint32_t) + cert->validPrincipals.length;
182 
183  //Malformed certificate?
184  if(length < sizeof(uint64_t))
185  return ERROR_INVALID_SYNTAX;
186 
187  //Parse 'valid after' field
188  cert->validAfter = LOAD64BE(data);
189 
190  //Point to the next field
191  data += sizeof(uint64_t);
192  length -= sizeof(uint64_t);
193 
194  //Malformed certificate?
195  if(length < sizeof(uint64_t))
196  return ERROR_INVALID_SYNTAX;
197 
198  //Parse 'valid before' field
199  cert->validBefore = LOAD64BE(data);
200 
201  //Point to the next field
202  data += sizeof(uint64_t);
203  length -= sizeof(uint64_t);
204 
205  //Parse 'critical options' field
207  //Any error to report?
208  if(error)
209  return error;
210 
211  //Point to the next field
212  data += sizeof(uint32_t) + cert->criticalOptions.length;
213  length -= sizeof(uint32_t) + cert->criticalOptions.length;
214 
215  //Parse 'extensions' field
216  error = sshParseExtensions(data, length, &cert->extensions);
217  //Any error to report?
218  if(error)
219  return error;
220 
221  //Point to the next field
222  data += sizeof(uint32_t) + cert->extensions.length;
223  length -= sizeof(uint32_t) + cert->extensions.length;
224 
225  //Parse 'reserved' field
226  error = sshParseBinaryString(data, length, &cert->reserved);
227  //Any error to report?
228  if(error)
229  return error;
230 
231  //Point to the next field
232  data += sizeof(uint32_t) + cert->reserved.length;
233  length -= sizeof(uint32_t) + cert->reserved.length;
234 
235  //Parse 'signature key' field
236  error = sshParseBinaryString(data, length, &cert->signatureKey);
237  //Any error to report?
238  if(error)
239  return error;
240 
241  //Point to the next field
242  data += sizeof(uint32_t) + cert->signatureKey.length;
243  length -= sizeof(uint32_t) + cert->signatureKey.length;
244 
245  //Parse 'signature' field
246  error = sshParseBinaryString(data, length, &cert->signature);
247  //Any error to report?
248  if(error)
249  return error;
250 
251  //Point to the next field
252  data += sizeof(uint32_t) + cert->signature.length;
253  length -= sizeof(uint32_t) + cert->signature.length;
254 
255  //Malformed certificate?
256  if(length != 0)
257  return ERROR_INVALID_SYNTAX;
258 
259  //Successful processing
260  return NO_ERROR;
261 }
262 
263 /**
264  * @brief Parse an RSA public key
265  * @param[in] data Pointer to the input data to parse
266  * @param[in] length Number of bytes available in the input data
267  * @param[in] consumed Number of bytes that have been consumed
268  * @param[out] publicKey Information resulting from the parsing process
269  * @return Error code
270  **/
271 
273  size_t *consumed, SshRsaCertPublicKey *publicKey)
274 {
275 #if (SSH_RSA_SIGN_SUPPORT == ENABLED)
276  error_t error;
277 
278  //Total number of bytes that have been consumed
279  *consumed = 0;
280 
281  //Parse RSA public exponent
282  error = sshParseBinaryString(data, length, &publicKey->e);
283  //Any error to report?
284  if(error)
285  return error;
286 
287  //Point to the next field
288  data += sizeof(uint32_t) + publicKey->e.length;
289  length -= sizeof(uint32_t) + publicKey->e.length;
290  *consumed += sizeof(uint32_t) + publicKey->e.length;
291 
292  //Parse RSA modulus
293  error = sshParseBinaryString(data, length, &publicKey->n);
294  //Any error to report?
295  if(error)
296  return error;
297 
298  //Point to the next field
299  data += sizeof(uint32_t) + publicKey->n.length;
300  length -= sizeof(uint32_t) + publicKey->n.length;
301  *consumed += sizeof(uint32_t) + publicKey->n.length;
302 
303  //Successful processing
304  return NO_ERROR;
305 #else
306  //Not implemented
307  return ERROR_NOT_IMPLEMENTED;
308 #endif
309 }
310 
311 
312 /**
313  * @brief Parse a DSA public key
314  * @param[in] data Pointer to the input data to parse
315  * @param[in] length Number of bytes available in the input data
316  * @param[in] consumed Number of bytes that have been consumed
317  * @param[out] publicKey Information resulting from the parsing process
318  * @return Error code
319  **/
320 
322  size_t *consumed, SshDsaCertPublicKey *publicKey)
323 {
324 #if (SSH_DSA_SIGN_SUPPORT == ENABLED)
325  error_t error;
326 
327  //Total number of bytes that have been consumed
328  *consumed = 0;
329 
330  //Parse DSA prime modulus
331  error = sshParseBinaryString(data, length, &publicKey->p);
332  //Any error to report?
333  if(error)
334  return error;
335 
336  //Point to the next field
337  data += sizeof(uint32_t) + publicKey->p.length;
338  length -= sizeof(uint32_t) + publicKey->p.length;
339  *consumed += sizeof(uint32_t) + publicKey->p.length;
340 
341  //Parse DSA group order
342  error = sshParseBinaryString(data, length, &publicKey->q);
343  //Any error to report?
344  if(error)
345  return error;
346 
347  //Point to the next field
348  data += sizeof(uint32_t) + publicKey->q.length;
349  length -= sizeof(uint32_t) + publicKey->q.length;
350  *consumed += sizeof(uint32_t) + publicKey->q.length;
351 
352  //Parse DSA group generator
353  error = sshParseBinaryString(data, length, &publicKey->g);
354  //Any error to report?
355  if(error)
356  return error;
357 
358  //Point to the next field
359  data += sizeof(uint32_t) + publicKey->g.length;
360  length -= sizeof(uint32_t) + publicKey->g.length;
361  *consumed += sizeof(uint32_t) + publicKey->g.length;
362 
363  //Parse DSA public key value
364  error = sshParseBinaryString(data, length, &publicKey->y);
365  //Any error to report?
366  if(error)
367  return error;
368 
369  //Point to the next field
370  data += sizeof(uint32_t) + publicKey->y.length;
371  length -= sizeof(uint32_t) + publicKey->y.length;
372  *consumed += sizeof(uint32_t) + publicKey->y.length;
373 
374  //Successful processing
375  return NO_ERROR;
376 #else
377  //Not implemented
378  return ERROR_NOT_IMPLEMENTED;
379 #endif
380 }
381 
382 
383 /**
384  * @brief Parse an ECDSA public key
385  * @param[in] data Pointer to the input data to parse
386  * @param[in] length Number of bytes available in the input data
387  * @param[in] consumed Number of bytes that have been consumed
388  * @param[out] publicKey Information resulting from the parsing process
389  * @return Error code
390  **/
391 
393  size_t *consumed, SshEcdsaCertPublicKey *publicKey)
394 {
395 #if (SSH_ECDSA_SIGN_SUPPORT == ENABLED)
396  error_t error;
397 
398  //Total number of bytes that have been consumed
399  *consumed = 0;
400 
401  //Parse curve name
402  error = sshParseString(data, length, &publicKey->curveName);
403  //Any error to report?
404  if(error)
405  return error;
406 
407  //Point to the next field
408  data += sizeof(uint32_t) + publicKey->curveName.length;
409  length -= sizeof(uint32_t) + publicKey->curveName.length;
410  *consumed += sizeof(uint32_t) + publicKey->curveName.length;
411 
412  //Parse EC public key
413  error = sshParseBinaryString(data, length, &publicKey->q);
414  //Any error to report?
415  if(error)
416  return error;
417 
418  //Point to the next field
419  data += sizeof(uint32_t) + publicKey->q.length;
420  length -= sizeof(uint32_t) + publicKey->q.length;
421  *consumed += sizeof(uint32_t) + publicKey->q.length;
422 
423  //Successful processing
424  return NO_ERROR;
425 #else
426  //Not implemented
427  return ERROR_NOT_IMPLEMENTED;
428 #endif
429 }
430 
431 
432 /**
433  * @brief Parse an Ed25519 public key
434  * @param[in] data Pointer to the input data to parse
435  * @param[in] length Number of bytes available in the input data
436  * @param[in] consumed Number of bytes that have been consumed
437  * @param[out] publicKey Information resulting from the parsing process
438  * @return Error code
439  **/
440 
442  size_t *consumed, SshEd25519CertPublicKey *publicKey)
443 {
444 #if (SSH_ED25519_SIGN_SUPPORT == ENABLED)
445  error_t error;
446 
447  //Total number of bytes that have been consumed
448  *consumed = 0;
449 
450  //Parse Ed25519 public key value
451  error = sshParseBinaryString(data, length, &publicKey->q);
452  //Any error to report?
453  if(error)
454  return error;
455 
456  //Point to the next field
457  data += sizeof(uint32_t) + publicKey->q.length;
458  length -= sizeof(uint32_t) + publicKey->q.length;
459  *consumed += sizeof(uint32_t) + publicKey->q.length;
460 
461  //Successful processing
462  return NO_ERROR;
463 #else
464  //Not implemented
465  return ERROR_NOT_IMPLEMENTED;
466 #endif
467 }
468 
469 
470 /**
471  * @brief Parse 'valid principals' field
472  * @param[in] data Pointer to the input data to parse
473  * @param[in] length Number of bytes available in the input data
474  * @param[out] validPrincipals Information resulting from the parsing process
475  * @return Error code
476  **/
477 
479  SshBinaryString *validPrincipals)
480 {
481  error_t error;
482  SshString name;
483 
484  //'valid principals' is a string containing zero or more principals as
485  //strings packed inside it
486  error = sshParseBinaryString(data, length, validPrincipals);
487 
488  //Check status code
489  if(!error)
490  {
491  //Check the length of the string
492  if(validPrincipals->length > 0)
493  {
494  //Point to the first item of the list
495  data = validPrincipals->value;
496  length = validPrincipals->length;
497 
498  //These principals list the names for which this certificate is
499  //valid; hostnames for SSH_CERT_TYPE_HOST certificates and usernames
500  //for SSH_CERT_TYPE_USER certificates
501  while(length > 0)
502  {
503  //Decode current name
504  error = sshParseString(data, length, &name);
505  //Any error to report?
506  if(error)
507  break;
508 
509  //Point to the next field
510  data += sizeof(uint32_t) + name.length;
511  length -= sizeof(uint32_t) + name.length;
512  }
513  }
514  else
515  {
516  //As a special case, a zero-length 'valid principals' field means the
517  //certificate is valid for any principal of the specified type
518  }
519  }
520 
521  //Return status code
522  return error;
523 }
524 
525 
526 /**
527  * @brief Parse 'critical options' field
528  * @param[in] data Pointer to the input data to parse
529  * @param[in] length Number of bytes available in the input data
530  * @param[out] criticalOptions Information resulting from the parsing process
531  * @return Error code
532  **/
533 
535  SshBinaryString *criticalOptions)
536 {
537  error_t error;
538  SshString optionName;
539  SshString optionData;
540 
541  //'critical options' is a set of zero or more key options. All such options
542  //are critical in the sense that an implementation must refuse to authorize
543  //a key that has an unrecognized option
544  error = sshParseBinaryString(data, length, criticalOptions);
545 
546  //Check status code
547  if(!error)
548  {
549  //Point to the first item of the list
550  data = criticalOptions->value;
551  length = criticalOptions->length;
552 
553  //Loop through critical options
554  while(length > 0)
555  {
556  //The name field identifies the option
557  error = sshParseString(data, length, &optionName);
558  //Any error to report?
559  if(error)
560  break;
561 
562  //Point to the next field
563  data += sizeof(uint32_t) + optionName.length;
564  length -= sizeof(uint32_t) + optionName.length;
565 
566  //The data field encodes option-specific information
567  error = sshParseString(data, length, &optionData);
568  //Any error to report?
569  if(error)
570  break;
571 
572  //Point to the next field
573  data += sizeof(uint32_t) + optionData.length;
574  length -= sizeof(uint32_t) + optionData.length;
575  }
576  }
577 
578  //Return status code
579  return error;
580 }
581 
582 
583 /**
584  * @brief Parse 'extensions' field
585  * @param[in] data Pointer to the input data to parse
586  * @param[in] length Number of bytes available in the input data
587  * @param[out] extensions Information resulting from the parsing process
588  * @return Error code
589  **/
590 
591 error_t sshParseExtensions(const uint8_t *data, size_t length,
593 {
594  error_t error;
595  SshString extensionName;
596  SshString extensionData;
597 
598  //'extensions' is a set of zero or more optional extensions. These extensions
599  //are not critical, and an implementation that encounters one that it does
600  //not recognize may safely ignore it
602 
603  //Check status code
604  if(!error)
605  {
606  //Point to the first item of the list
607  data = extensions->value;
608  length = extensions->length;
609 
610  //Loop through extensions
611  while(length > 0)
612  {
613  //The name field identifies the extension
614  error = sshParseString(data, length, &extensionName);
615  //Any error to report?
616  if(error)
617  break;
618 
619  //Point to the next field
620  data += sizeof(uint32_t) + extensionName.length;
621  length -= sizeof(uint32_t) + extensionName.length;
622 
623  //The data field encodes extension-specific information
624  error = sshParseString(data, length, &extensionData);
625  //Any error to report?
626  if(error)
627  break;
628 
629  //Point to the next field
630  data += sizeof(uint32_t) + extensionData.length;
631  length -= sizeof(uint32_t) + extensionData.length;
632  }
633  }
634 
635  //Return status code
636  return error;
637 }
638 
639 
640 /**
641  * @brief Extract the principal name at specified index
642  * @param[in] cert Pointer to the SSH certificate
643  * @param[in] index Zero-based index of the element to get
644  * @param[out] name Principal name
645  * @return TRUE if the index is valid, else FALSE
646  **/
647 
649  SshString *name)
650 {
651  error_t error;
652  uint_t i;
653  size_t length;
654  const uint8_t *p;
655 
656  //Point to the first item of the list
657  p = cert->validPrincipals.value;
658  length = cert->validPrincipals.length;
659 
660  //Loop through principals
661  for(i = 0; length > 0; i++)
662  {
663  //Decode current name
664  error = sshParseString(p, length, name);
665  //Any error to report?
666  if(error)
667  return FALSE;
668 
669  //Point to the next field
670  p += sizeof(uint32_t) + name->length;
671  length -= sizeof(uint32_t) + name->length;
672 
673  //Matching index?
674  if(i == index)
675  return TRUE;
676  }
677 
678  //The index is out of range
679  return FALSE;
680 }
681 
682 
683 /**
684  * @brief Extract the critical option at specified index
685  * @param[in] cert Pointer to the SSH certificate
686  * @param[in] index Zero-based index of the element to get
687  * @param[out] name Option name
688  * @param[out] data Option value
689  * @return TRUE if the index is valid, else FALSE
690  **/
691 
694 {
695  error_t error;
696  uint_t i;
697  size_t length;
698  const uint8_t *p;
699 
700  //Point to the first item of the list
701  p = cert->criticalOptions.value;
702  length = cert->criticalOptions.length;
703 
704  //Loop through critical options
705  for(i = 0; length > 0; i++)
706  {
707  //The name field identifies the option
708  error = sshParseString(p, length, name);
709  //Any error to report?
710  if(error)
711  break;
712 
713  //Point to the next field
714  p += sizeof(uint32_t) + name->length;
715  length -= sizeof(uint32_t) + name->length;
716 
717  //The data field encodes option-specific information
718  error = sshParseBinaryString(p, length, data);
719  //Any error to report?
720  if(error)
721  break;
722 
723  //Point to the next field
724  p += sizeof(uint32_t) + data->length;
725  length -= sizeof(uint32_t) + data->length;
726 
727  //Matching index?
728  if(i == index)
729  return TRUE;
730  }
731 
732  //The index is out of range
733  return FALSE;
734 }
735 
736 
737 /**
738  * @brief Extract the extension at specified index
739  * @param[in] cert Pointer to the SSH certificate
740  * @param[in] index Zero-based index of the element to get
741  * @param[out] name Extension name
742  * @param[out] data Extension value
743  * @return TRUE if the index is valid, else FALSE
744  **/
745 
748 {
749  error_t error;
750  uint_t i;
751  size_t length;
752  const uint8_t *p;
753 
754  //Point to the first item of the list
755  p = cert->extensions.value;
756  length = cert->extensions.length;
757 
758  //Loop through extensions
759  for(i = 0; length > 0; i++)
760  {
761  //The name field identifies the extension
762  error = sshParseString(p, length, name);
763  //Any error to report?
764  if(error)
765  break;
766 
767  //Point to the next field
768  p += sizeof(uint32_t) + name->length;
769  length -= sizeof(uint32_t) + name->length;
770 
771  //The data field encodes extension-specific information
772  error = sshParseBinaryString(p, length, data);
773  //Any error to report?
774  if(error)
775  break;
776 
777  //Point to the next field
778  p += sizeof(uint32_t) + data->length;
779  length -= sizeof(uint32_t) + data->length;
780 
781  //Matching index?
782  if(i == index)
783  return TRUE;
784  }
785 
786  //The index is out of range
787  return FALSE;
788 }
789 
790 #endif
unsigned int uint_t
Definition: compiler_port.h:50
int bool_t
Definition: compiler_port.h:53
#define LOAD32BE(p)
Definition: cpu_endian.h:210
#define LOAD64BE(p)
Definition: cpu_endian.h:246
Debugging facilities.
uint8_t n
error_t
Error codes.
Definition: error.h:43
@ ERROR_WRONG_TYPE
Definition: error.h:121
@ ERROR_WRONG_IDENTIFIER
Definition: error.h:89
@ ERROR_INVALID_SYNTAX
Definition: error.h:68
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t data[]
Definition: ethernet.h:222
uint8_t p
Definition: ndp.h:300
#define osMemset(p, value, length)
Definition: os_port.h:135
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
char_t name[]
Secure Shell (SSH)
bool_t sshGetCriticalOption(const SshCertificate *cert, uint_t index, SshString *name, SshBinaryString *data)
Extract the critical option at specified index.
error_t sshParseEd25519CertPublicKey(const uint8_t *data, size_t length, size_t *consumed, SshEd25519CertPublicKey *publicKey)
Parse an Ed25519 public key.
error_t sshParseDsaCertPublicKey(const uint8_t *data, size_t length, size_t *consumed, SshDsaCertPublicKey *publicKey)
Parse a DSA public key.
error_t sshParseRsaCertPublicKey(const uint8_t *data, size_t length, size_t *consumed, SshRsaCertPublicKey *publicKey)
Parse an RSA public key.
error_t sshParseValidPrincipals(const uint8_t *data, size_t length, SshBinaryString *validPrincipals)
Parse 'valid principals' field.
error_t sshParseExtensions(const uint8_t *data, size_t length, SshBinaryString *extensions)
Parse 'extensions' field.
error_t sshParseEcdsaCertPublicKey(const uint8_t *data, size_t length, size_t *consumed, SshEcdsaCertPublicKey *publicKey)
Parse an ECDSA public key.
bool_t sshGetValidPrincipal(const SshCertificate *cert, uint_t index, SshString *name)
Extract the principal name at specified index.
error_t sshParseCriticalOptions(const uint8_t *data, size_t length, SshBinaryString *criticalOptions)
Parse 'critical options' field.
bool_t sshGetExtension(const SshCertificate *cert, uint_t index, SshString *name, SshBinaryString *data)
Extract the extension at specified index.
error_t sshParseCertificate(const uint8_t *data, size_t length, SshCertificate *cert)
Parse SSH certificate.
SSH certificate parsing.
@ SSH_CERT_TYPE_USER
@ SSH_CERT_TYPE_HOST
error_t sshParseBinaryString(const uint8_t *p, size_t length, SshBinaryString *string)
Parse a binary string.
Definition: ssh_misc.c:1189
bool_t sshCompareString(const SshString *string, const char_t *value)
Compare a binary string against the supplied value.
Definition: ssh_misc.c:1586
error_t sshParseString(const uint8_t *p, size_t length, SshString *string)
Parse a string.
Definition: ssh_misc.c:1152
SSH helper functions.
Binary string.
Definition: ssh_types.h:67
const uint8_t * value
Definition: ssh_types.h:68
size_t length
Definition: ssh_types.h:69
SSH certificate (OpenSSH format)
SshBinaryString criticalOptions
SshBinaryString signatureKey
SshBinaryString reserved
SshBinaryString nonce
uint64_t validAfter
SshBinaryString validPrincipals
SshBinaryString signature
SshString keyFormatId
SshBinaryString extensions
uint64_t validBefore
SshCertPublicKey publicKey
DSA public key.
SshBinaryString q
SshBinaryString y
SshBinaryString g
SshBinaryString p
ECDSA public key.
SshBinaryString q
Ed25519 public key.
RSA public key.
SshBinaryString n
SshBinaryString e
String.
Definition: ssh_types.h:56
size_t length
Definition: ssh_types.h:58
uint8_t length
Definition: tcp.h:368
uint8_t extensions[]
Definition: tls13_misc.h:300
SshEcdsaCertPublicKey ecdsaPublicKey
SshRsaCertPublicKey rsaPublicKey
SshEd25519CertPublicKey ed25519PublicKey
SshDsaCertPublicKey dsaPublicKey