File
Blob: firmware/crates/esp32-radio/src/platform/crypto/self_test.rs
| 1 | //! Small public-vector startup checks for the private native boundary. |
| 2 | use super::{hashes::Hashes, native, srtp}; |
| 3 | use dimpl::{ |
| 4 | HashAlgorithm, |
| 5 | crypto::{Buf, HashProvider}, |
| 6 | }; |
| 7 | use radio_webrtc::crypto::SrtpProvider; |
| 8 | |
| 9 | #[cfg(feature = "crypto-self-test")] |
| 10 | mod extended; |
| 11 | |
| 12 | pub(super) fn run() { |
| 13 | #[cfg(feature = "crypto-self-test")] |
| 14 | extended::run(); |
| 15 | let reference = str0m_rust_crypto::default_provider(); |
| 16 | let iv = [0x13; 12]; |
| 17 | let aad = [0xab; 12]; |
| 18 | for length in [16, 32] { |
| 19 | // Public synthetic keys and inputs; never used for a network session. |
| 20 | let key = vec![0x42; length]; |
| 21 | let mut native_round = [0; 32]; |
| 22 | let mut reference_round = [0; 32]; |
| 23 | let mut block = [0; 16]; |
| 24 | native::ecb(&key, &[0; 16], &mut block).expect("native AES-ECB self-test"); |
| 25 | if length == 16 { |
| 26 | srtp::Provider.srtp_aes_128_ecb_round(&key, &[0; 16], &mut native_round); |
| 27 | reference |
| 28 | .srtp_provider |
| 29 | .srtp_aes_128_ecb_round(&key, &[0; 16], &mut reference_round); |
| 30 | } else { |
| 31 | srtp::Provider.srtp_aes_256_ecb_round(&key, &[0; 16], &mut native_round); |
| 32 | reference |
| 33 | .srtp_provider |
| 34 | .srtp_aes_256_ecb_round(&key, &[0; 16], &mut reference_round); |
| 35 | } |
| 36 | assert!( |
| 37 | native_round == reference_round && block == reference_round[..16], |
| 38 | "AES-ECB self-test mismatch" |
| 39 | ); |
| 40 | for n in [0, 1, 17, 1275] { |
| 41 | let clear = vec![0x5a; n]; |
| 42 | let mut expected = vec![0; n + 16]; |
| 43 | if length == 16 { |
| 44 | reference |
| 45 | .srtp_provider |
| 46 | .aead_aes_128_gcm() |
| 47 | .create_cipher(key[..].try_into().unwrap(), true) |
| 48 | .encrypt(&iv, &aad, &clear, &mut expected) |
| 49 | .expect("reference GCM"); |
| 50 | } else { |
| 51 | reference |
| 52 | .srtp_provider |
| 53 | .aead_aes_256_gcm() |
| 54 | .create_cipher(key[..].try_into().unwrap(), true) |
| 55 | .encrypt(&iv, &aad, &clear, &mut expected) |
| 56 | .expect("reference GCM"); |
| 57 | } |
| 58 | let mut buffer = clear.clone(); |
| 59 | buffer.resize(n + 16, 0); |
| 60 | native::gcm_in_place(false, &key, &iv, &aad, &mut buffer, n) |
| 61 | .expect("GCM encryption self-test"); |
| 62 | assert!(buffer == expected, "GCM encryption self-test mismatch"); |
| 63 | native::gcm_in_place(true, &key, &iv, &aad, &mut buffer, n + 16) |
| 64 | .expect("GCM decryption self-test"); |
| 65 | assert!(buffer[..n] == clear, "GCM decryption self-test mismatch"); |
| 66 | buffer.copy_from_slice(&expected); |
| 67 | buffer[n + 15] ^= 1; |
| 68 | assert!( |
| 69 | native::gcm_in_place(true, &key, &iv, &aad, &mut buffer, n + 16).is_err(), |
| 70 | "GCM accepted a bad tag" |
| 71 | ); |
| 72 | assert!( |
| 73 | buffer[..n].iter().all(|byte| *byte == 0), |
| 74 | "GCM retained unauthenticated plaintext" |
| 75 | ); |
| 76 | } |
| 77 | } |
| 78 | for algorithm in [HashAlgorithm::SHA256, HashAlgorithm::SHA384] { |
| 79 | let mut actual = Hashes.create_hash(algorithm); |
| 80 | let mut expected = dimpl::crypto::rust_crypto::default_provider() |
| 81 | .hash_provider |
| 82 | .create_hash(algorithm); |
| 83 | let mut a = Buf::new(); |
| 84 | let mut b = Buf::new(); |
| 85 | for part in [b"a".as_slice(), b"bc", &[0x5a; 1275]] { |
| 86 | actual.update(part); |
| 87 | expected.update(part); |
| 88 | actual.clone_and_finalize(&mut a); |
| 89 | expected.clone_and_finalize(&mut b); |
| 90 | assert!(a[..] == b[..], "SHA snapshot self-test mismatch"); |
| 91 | } |
| 92 | } |
| 93 | let mut mac = [0; 20]; |
| 94 | native::hmac(160, b"public test key", &[b"a", b"bc"], &mut mac).expect("native HMAC self-test"); |
| 95 | assert!( |
| 96 | mac == reference |
| 97 | .sha1_hmac_provider |
| 98 | .sha1_hmac(b"public test key", &[b"abc"]), |
| 99 | "HMAC self-test mismatch" |
| 100 | ); |
| 101 | super::super::log("Crypto boundary self-tests passed"); |
| 102 | } |