Skip to main content

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