@@ -5,7 +5,11 @@ use crate::{Algorithm, Error, Fingerprint, HashAlg, Result};
55use encoding:: { CheckedSum , Decode , Encode , Reader , Writer } ;
66
77#[ cfg( feature = "alloc" ) ]
8- use super :: { DsaPublicKey , OpaquePublicKey , RsaPublicKey } ;
8+ use {
9+ super :: { DsaPublicKey , OpaquePublicKey , RsaPublicKey } ,
10+ crate :: Certificate ,
11+ alloc:: boxed:: Box ,
12+ } ;
913
1014#[ cfg( feature = "ecdsa" ) ]
1115use super :: { EcdsaPublicKey , SkEcdsaSha2NistP256 } ;
@@ -40,6 +44,14 @@ pub enum KeyData {
4044 /// [PROTOCOL.u2f]: https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.u2f?annotate=HEAD
4145 SkEd25519 ( SkEd25519 ) ,
4246
47+ /// Certificate key as specified in [draft-miller-ssh-cert]
48+ /// (and [PROTOCOL.certkeys], now deprecated in favor of the IETF draft).
49+ ///
50+ /// [draft-miller-ssh-cert]: https://datatracker.ietf.org/doc/draft-miller-ssh-cert
51+ /// [PROTOCOL.certkeys]: https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.certkeys?annotate=HEAD
52+ #[ cfg( feature = "alloc" ) ]
53+ Certificate ( Box < Certificate > ) ,
54+
4355 /// Opaque public key data.
4456 #[ cfg( feature = "alloc" ) ]
4557 Other ( OpaquePublicKey ) ,
@@ -60,6 +72,8 @@ impl KeyData {
6072 Self :: SkEcdsaSha2NistP256 ( _) => Algorithm :: SkEcdsaSha2NistP256 ,
6173 Self :: SkEd25519 ( _) => Algorithm :: SkEd25519 ,
6274 #[ cfg( feature = "alloc" ) ]
75+ Self :: Certificate ( cert) => cert. algorithm ( ) ,
76+ #[ cfg( feature = "alloc" ) ]
6377 Self :: Other ( key) => key. algorithm ( ) ,
6478 }
6579 }
@@ -133,6 +147,24 @@ impl KeyData {
133147 }
134148 }
135149
150+ /// Get the certificate if this key is the correct type.
151+ #[ cfg( feature = "alloc" ) ]
152+ pub fn certificate ( & self ) -> Option < & Certificate > {
153+ match self {
154+ Self :: Certificate ( certificate) => Some ( certificate. as_ref ( ) ) ,
155+ _ => None ,
156+ }
157+ }
158+
159+ /// Get the certificate, consuming the [`KeyData`], if this key is the correct type.
160+ #[ cfg( feature = "alloc" ) ]
161+ pub fn into_certificate ( self ) -> Option < Certificate > {
162+ match self {
163+ Self :: Certificate ( certificate) => Some ( * certificate) ,
164+ _ => None ,
165+ }
166+ }
167+
136168 /// Is this key a DSA key?
137169 #[ cfg( feature = "alloc" ) ]
138170 pub fn is_dsa ( & self ) -> bool {
@@ -173,6 +205,12 @@ impl KeyData {
173205 matches ! ( self , Self :: Other ( _) )
174206 }
175207
208+ /// Is this a certificate?
209+ #[ cfg( feature = "alloc" ) ]
210+ pub fn is_certificate ( & self ) -> bool {
211+ matches ! ( self , Self :: Certificate ( _) )
212+ }
213+
176214 /// Decode [`KeyData`] for the specified algorithm.
177215 pub fn decode_as ( reader : & mut impl Reader , algorithm : Algorithm ) -> Result < Self > {
178216 match algorithm {
@@ -198,6 +236,12 @@ impl KeyData {
198236 }
199237 }
200238
239+ /// Decode [`KeyData`] as a certificate with the specified algorithm.
240+ #[ cfg( feature = "alloc" ) ]
241+ pub fn decode_as_certificate ( reader : & mut impl Reader , algorithm : Algorithm ) -> Result < Self > {
242+ Certificate :: decode_as ( reader, algorithm) . map ( |cert| Self :: Certificate ( Box :: new ( cert) ) )
243+ }
244+
201245 /// Get the encoded length of this key data without a leading algorithm
202246 /// identifier.
203247 pub ( crate ) fn encoded_key_data_len ( & self ) -> encoding:: Result < usize > {
@@ -213,6 +257,8 @@ impl KeyData {
213257 Self :: SkEcdsaSha2NistP256 ( sk) => sk. encoded_len ( ) ,
214258 Self :: SkEd25519 ( sk) => sk. encoded_len ( ) ,
215259 #[ cfg( feature = "alloc" ) ]
260+ Self :: Certificate ( cert) => cert. encoded_len ( ) ,
261+ #[ cfg( feature = "alloc" ) ]
216262 Self :: Other ( other) => other. key . encoded_len ( ) ,
217263 }
218264 }
@@ -231,6 +277,8 @@ impl KeyData {
231277 Self :: SkEcdsaSha2NistP256 ( sk) => sk. encode ( writer) ,
232278 Self :: SkEd25519 ( sk) => sk. encode ( writer) ,
233279 #[ cfg( feature = "alloc" ) ]
280+ Self :: Certificate ( cert) => cert. encode ( writer) ,
281+ #[ cfg( feature = "alloc" ) ]
234282 Self :: Other ( other) => other. key . encode ( writer) ,
235283 }
236284 }
@@ -241,6 +289,12 @@ impl Decode for KeyData {
241289
242290 fn decode ( reader : & mut impl Reader ) -> Result < Self > {
243291 let algorithm = Algorithm :: decode ( reader) ?;
292+ #[ cfg( feature = "alloc" ) ]
293+ if let Algorithm :: Other ( name) = & algorithm {
294+ if let Ok ( certificate_algorithm) = Algorithm :: new_certificate ( name. as_str ( ) ) {
295+ return Self :: decode_as_certificate ( reader, certificate_algorithm) ;
296+ }
297+ }
244298 Self :: decode_as ( reader, algorithm)
245299 }
246300}
@@ -299,3 +353,10 @@ impl From<SkEd25519> for KeyData {
299353 Self :: SkEd25519 ( public_key)
300354 }
301355}
356+
357+ #[ cfg( feature = "alloc" ) ]
358+ impl From < Certificate > for KeyData {
359+ fn from ( certificate : Certificate ) -> KeyData {
360+ Self :: Certificate ( Box :: new ( certificate) )
361+ }
362+ }
0 commit comments