Skip to content
File

Blob: firmware/crates/esp32-radio/src/platform/crypto/ec.rs

rust103 lines
1//! EC protocol traits with Rust-owned secret bytes and synchronous native calls.
2use super::{hashes, native};
3use dimpl::{
4 CryptoError, CryptoOperation, HashAlgorithm, NamedGroup, SignatureAlgorithm,
5 crypto::{ActiveKeyExchange, Buf, KeyProvider, SigningKey, SupportedKxGroup},
6};
7use zeroize::Zeroizing;
8 
9#[derive(Debug)]
10pub(super) struct P256;
11pub(super) static GROUPS: &[&dyn SupportedKxGroup] = &[&P256];
12 
13struct Exchange {
14 secret: Zeroizing<[u8; 32]>,
15 public: Buf,
16}
17impl std::fmt::Debug for Exchange {
18 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19 f.debug_struct("P256Exchange").finish_non_exhaustive()
20 }
21}
22impl SupportedKxGroup for P256 {
23 fn name(&self) -> NamedGroup {
24 NamedGroup::Secp256r1
25 }
26 fn start_exchange(&self, mut public: Buf) -> Result<Box<dyn ActiveKeyExchange>, CryptoError> {
27 let (secret, bytes) = native::p256_keygen()
28 .map_err(|_| CryptoError::OperationFailed(CryptoOperation::StartKeyExchange))?;
29 public.clear();
30 public.extend_from_slice(&bytes);
31 Ok(Box::new(Exchange { secret, public }))
32 }
33}
34impl ActiveKeyExchange for Exchange {
35 fn pub_key(&self) -> &[u8] {
36 &self.public
37 }
38 fn group(&self) -> NamedGroup {
39 NamedGroup::Secp256r1
40 }
41 fn complete(self: Box<Self>, peer: &[u8], out: &mut Buf) -> Result<(), CryptoError> {
42 let peer: &[u8; 65] = peer
43 .try_into()
44 .map_err(|_| CryptoError::OperationFailed(CryptoOperation::CompleteKeyExchange))?;
45 let value = native::p256_shared(&self.secret, peer)
46 .map_err(|_| CryptoError::OperationFailed(CryptoOperation::CompleteKeyExchange))?;
47 out.clear();
48 out.extend_from_slice(value.as_ref());
49 Ok(())
50 }
51}
52 
53#[derive(Debug)]
54pub(super) struct Keys;
55struct Signer {
56 der: Zeroizing<Vec<u8>>,
57 bits: i32,
58}
59impl std::fmt::Debug for Signer {
60 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61 f.debug_struct("EcSigningKey")
62 .field("bits", &self.bits)
63 .finish_non_exhaustive()
64 }
65}
66impl KeyProvider for Keys {
67 fn load_private_key(&self, der: &[u8]) -> Result<Box<dyn SigningKey>, CryptoError> {
68 let bits = native::key_info(der)
69 .map_err(|_| CryptoError::OperationFailed(CryptoOperation::LoadPrivateKey))?;
70 Ok(Box::new(Signer {
71 der: Zeroizing::new(der.to_vec()),
72 bits,
73 }))
74 }
75}
76impl SigningKey for Signer {
77 fn algorithm(&self) -> SignatureAlgorithm {
78 SignatureAlgorithm::ECDSA
79 }
80 fn hash_algorithm(&self) -> HashAlgorithm {
81 if self.bits == 256 {
82 HashAlgorithm::SHA256
83 } else {
84 HashAlgorithm::SHA384
85 }
86 }
87 fn supported_hash_algorithms(&self) -> &[HashAlgorithm] {
88 &[HashAlgorithm::SHA256, HashAlgorithm::SHA384]
89 }
90 fn sign(&mut self, data: &[u8], hash: HashAlgorithm, out: &mut Buf) -> Result<(), CryptoError> {
91 let bits = hashes::bits(hash).ok_or(CryptoError::UnsupportedSignaturePair {
92 signature: SignatureAlgorithm::ECDSA,
93 hash,
94 })?;
95 let mut signature = [0; 128];
96 let used = native::sign(&self.der, data, bits, &mut signature)
97 .map_err(|_| CryptoError::OperationFailed(CryptoOperation::Sign))?;
98 out.clear();
99 out.extend_from_slice(&signature[..used]);
100 Ok(())
101 }
102}