Skip to content
File

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

rust97 lines
1use super::native;
2use dimpl::{
3 HashAlgorithm,
4 crypto::{Buf, HashContext, HashProvider, HmacProvider},
5};
6use radio_webrtc::crypto::{Sha1HmacProvider, Sha256Provider};
7 
8#[derive(Debug)]
9pub(super) struct Hashes;
10 
11pub(super) fn bits(algorithm: HashAlgorithm) -> Option<i32> {
12 match algorithm {
13 HashAlgorithm::SHA256 => Some(256),
14 HashAlgorithm::SHA384 => Some(384),
15 _ => None,
16 }
17}
18 
19impl Sha256Provider for Hashes {
20 fn sha256(&self, data: &[u8]) -> [u8; 32] {
21 native::sha256(data).unwrap_or_else(|_| {
22 str0m_rust_crypto::default_provider()
23 .sha256_provider
24 .sha256(data)
25 })
26 }
27}
28impl Sha1HmacProvider for Hashes {
29 fn sha1_hmac(&self, key: &[u8], payloads: &[&[u8]]) -> [u8; 20] {
30 let mut out = [0; 20];
31 if native::hmac(160, key, payloads, &mut out).is_ok() {
32 out
33 } else {
34 str0m_rust_crypto::default_provider()
35 .sha1_hmac_provider
36 .sha1_hmac(key, payloads)
37 }
38 }
39}
40impl HmacProvider for Hashes {
41 fn hmac(
42 &self,
43 algorithm: HashAlgorithm,
44 key: &[u8],
45 data: &[u8],
46 out: &mut [u8],
47 ) -> Result<usize, dimpl::CryptoError> {
48 if let Some(bits) = bits(algorithm)
49 && native::hmac(bits, key, &[data], out).is_ok()
50 {
51 return Ok(bits as usize / 8);
52 }
53 dimpl::crypto::rust_crypto::default_provider()
54 .hmac_provider
55 .hmac(algorithm, key, data, out)
56 }
57}
58 
59struct Hash {
60 state: native::HashState,
61 length: usize,
62}
63impl std::fmt::Debug for Hash {
64 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65 f.debug_struct("EspHash").finish_non_exhaustive()
66 }
67}
68impl HashProvider for Hashes {
69 fn create_hash(&self, algorithm: HashAlgorithm) -> Box<dyn HashContext> {
70 if let Some(bits) = bits(algorithm) {
71 Box::new(Hash {
72 state: native::HashState::new(bits).expect("SHA state initialization failed"),
73 length: bits as usize / 8,
74 })
75 } else {
76 dimpl::crypto::rust_crypto::default_provider()
77 .hash_provider
78 .create_hash(algorithm)
79 }
80 }
81}
82impl HashContext for Hash {
83 fn update(&mut self, data: &[u8]) {
84 // This upstream trait cannot return errors. A failed incremental hash
85 // aborts the firmware rather than producing an invalid transcript.
86 self.state.update(data).expect("SHA hardware update failed");
87 }
88 fn clone_and_finalize(&self, out: &mut Buf) {
89 let mut digest = [0; 64];
90 self.state
91 .finish(&mut digest)
92 .expect("SHA hardware finalization failed");
93 out.clear();
94 out.extend_from_slice(&digest[..self.length]);
95 }
96}