ssh_key/private/
sk.rs

1//! Security Key (FIDO/U2F) private keys as described in [PROTOCOL.u2f].
2//!
3//! [PROTOCOL.u2f]: https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.u2f?annotate=HEAD
4
5use crate::{public, Error, Result};
6use alloc::vec::Vec;
7use encoding::{CheckedSum, Decode, Encode, Reader, Writer};
8
9/// Security Key (FIDO/U2F) ECDSA/NIST P-256 private key as specified in
10/// [PROTOCOL.u2f](https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.u2f?annotate=HEAD).
11#[cfg(all(feature = "alloc", feature = "ecdsa"))]
12#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
13pub struct SkEcdsaSha2NistP256 {
14    /// Public key.
15    public: public::SkEcdsaSha2NistP256,
16
17    /// Flags.
18    flags: u8,
19
20    /// FIDO/U2F key handle.
21    key_handle: Vec<u8>,
22
23    /// Reserved data.
24    reserved: Vec<u8>,
25}
26
27#[cfg(feature = "ecdsa")]
28impl SkEcdsaSha2NistP256 {
29    /// Construct new instance of SkEcdsaSha2NistP256.
30    #[cfg(feature = "alloc")]
31    pub fn new(
32        public: public::SkEcdsaSha2NistP256,
33        flags: u8,
34        key_handle: impl Into<Vec<u8>>,
35    ) -> Result<Self> {
36        let key_handle = key_handle.into();
37
38        if key_handle.len() <= 255 {
39            Ok(SkEcdsaSha2NistP256 {
40                public,
41                flags,
42                key_handle,
43                reserved: Vec::<u8>::new(),
44            })
45        } else {
46            Err(encoding::Error::Length.into())
47        }
48    }
49
50    /// Get the ECDSA/NIST P-256 public key.
51    pub fn public(&self) -> &public::SkEcdsaSha2NistP256 {
52        &self.public
53    }
54
55    /// Get flags.
56    pub fn flags(&self) -> u8 {
57        self.flags
58    }
59
60    /// Get FIDO/U2F key handle.
61    pub fn key_handle(&self) -> &[u8] {
62        &self.key_handle
63    }
64}
65
66#[cfg(feature = "ecdsa")]
67impl Decode for SkEcdsaSha2NistP256 {
68    type Error = Error;
69
70    fn decode(reader: &mut impl Reader) -> Result<Self> {
71        Ok(Self {
72            public: public::SkEcdsaSha2NistP256::decode(reader)?,
73            flags: u8::decode(reader)?,
74            key_handle: Vec::decode(reader)?,
75            reserved: Vec::decode(reader)?,
76        })
77    }
78}
79
80#[cfg(feature = "ecdsa")]
81impl Encode for SkEcdsaSha2NistP256 {
82    fn encoded_len(&self) -> encoding::Result<usize> {
83        [
84            self.public.encoded_len()?,
85            self.flags.encoded_len()?,
86            self.key_handle.encoded_len()?,
87            self.reserved.encoded_len()?,
88        ]
89        .checked_sum()
90    }
91
92    fn encode(&self, writer: &mut impl Writer) -> encoding::Result<()> {
93        self.public.encode(writer)?;
94        self.flags.encode(writer)?;
95        self.key_handle.encode(writer)?;
96        self.reserved.encode(writer)?;
97        Ok(())
98    }
99}
100
101/// Security Key (FIDO/U2F) Ed25519 private key as specified in
102/// [PROTOCOL.u2f](https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.u2f?annotate=HEAD).
103#[cfg(feature = "alloc")]
104#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
105pub struct SkEd25519 {
106    /// Public key.
107    public: public::SkEd25519,
108
109    /// Flags.
110    flags: u8,
111
112    /// FIDO/U2F key handle.
113    key_handle: Vec<u8>,
114
115    /// Reserved data.
116    reserved: Vec<u8>,
117}
118
119impl SkEd25519 {
120    /// Construct new instance of SkEd25519.
121    #[cfg(feature = "alloc")]
122    pub fn new(
123        public: public::SkEd25519,
124        flags: u8,
125        key_handle: impl Into<Vec<u8>>,
126    ) -> Result<Self> {
127        let key_handle = key_handle.into();
128
129        if key_handle.len() <= 255 {
130            Ok(SkEd25519 {
131                public,
132                flags,
133                key_handle,
134                reserved: Vec::<u8>::new(),
135            })
136        } else {
137            Err(encoding::Error::Length.into())
138        }
139    }
140
141    /// Get the Ed25519 public key.
142    pub fn public(&self) -> &public::SkEd25519 {
143        &self.public
144    }
145
146    /// Get flags.
147    pub fn flags(&self) -> u8 {
148        self.flags
149    }
150
151    /// Get FIDO/U2F key handle.
152    pub fn key_handle(&self) -> &[u8] {
153        &self.key_handle
154    }
155}
156
157impl Decode for SkEd25519 {
158    type Error = Error;
159
160    fn decode(reader: &mut impl Reader) -> Result<Self> {
161        Ok(Self {
162            public: public::SkEd25519::decode(reader)?,
163            flags: u8::decode(reader)?,
164            key_handle: Vec::decode(reader)?,
165            reserved: Vec::decode(reader)?,
166        })
167    }
168}
169
170impl Encode for SkEd25519 {
171    fn encoded_len(&self) -> encoding::Result<usize> {
172        [
173            self.public.encoded_len()?,
174            self.flags.encoded_len()?,
175            self.key_handle.encoded_len()?,
176            self.reserved.encoded_len()?,
177        ]
178        .checked_sum()
179    }
180
181    fn encode(&self, writer: &mut impl Writer) -> encoding::Result<()> {
182        self.public.encode(writer)?;
183        self.flags.encode(writer)?;
184        self.key_handle.encode(writer)?;
185        self.reserved.encode(writer)?;
186        Ok(())
187    }
188}