lakers_crypto_rustcrypto/
lib.rs1#![no_std]
2
3use lakers_shared::{
4 BufferCiphertext3, BufferPlaintext3, BytesCcmIvLen, BytesCcmKeyLen, BytesHashLen,
5 BytesMaxBuffer, BytesMaxInfoBuffer, BytesP256ElemLen, Crypto as CryptoTrait, EDHOCError,
6 AES_CCM_TAG_LEN, MAX_BUFFER_LEN,
7};
8
9use ccm::AeadInPlace;
10use ccm::KeyInit;
11use p256::elliptic_curve::point::AffineCoordinates;
12use p256::elliptic_curve::point::DecompressPoint;
13use sha2::Digest;
14
15type AesCcm16_64_128 = ccm::Ccm<aes::Aes128, ccm::consts::U8, ccm::consts::U13>;
16
17pub struct Crypto<Rng: rand_core::RngCore + rand_core::CryptoRng> {
22 rng: Rng,
23}
24
25impl<Rng: rand_core::RngCore + rand_core::CryptoRng> Crypto<Rng> {
26 pub const fn new(rng: Rng) -> Self {
27 Self { rng }
28 }
29}
30
31impl<Rng: rand_core::RngCore + rand_core::CryptoRng> core::fmt::Debug for Crypto<Rng> {
32 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
33 f.debug_struct("lakers_crypto_rustcrypto::Crypto")
34 .field("rng", &core::any::type_name::<Rng>())
35 .finish()
36 }
37}
38
39impl<Rng: rand_core::RngCore + rand_core::CryptoRng> CryptoTrait for Crypto<Rng> {
40 fn sha256_digest(&mut self, message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen {
41 let mut hasher = sha2::Sha256::new();
42 hasher.update(&message[..message_len]);
43 hasher.finalize().into()
44 }
45
46 fn hkdf_expand(
47 &mut self,
48 prk: &BytesHashLen,
49 info: &BytesMaxInfoBuffer,
50 info_len: usize,
51 length: usize,
52 ) -> BytesMaxBuffer {
53 let hkdf =
54 hkdf::Hkdf::<sha2::Sha256>::from_prk(prk).expect("Static size was checked at extract");
55 let mut output: BytesMaxBuffer = [0; MAX_BUFFER_LEN];
56 hkdf.expand(&info[..info_len], &mut output[..length])
57 .expect("Static lengths match the algorithm");
58 output
59 }
60
61 fn hkdf_extract(&mut self, salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen {
62 let mut extracted = hkdf::HkdfExtract::<sha2::Sha256>::new(Some(salt));
65 extracted.input_ikm(ikm);
66 extracted.finalize().0.into()
67 }
68
69 fn aes_ccm_encrypt_tag_8(
70 &mut self,
71 key: &BytesCcmKeyLen,
72 iv: &BytesCcmIvLen,
73 ad: &[u8],
74 plaintext: &BufferPlaintext3,
75 ) -> BufferCiphertext3 {
76 let key = AesCcm16_64_128::new(key.into());
77 let mut outbuffer = BufferCiphertext3::new();
78 outbuffer.content[..plaintext.len].copy_from_slice(plaintext.as_slice());
79 if let Ok(tag) =
80 key.encrypt_in_place_detached(iv.into(), ad, &mut outbuffer.content[..plaintext.len])
81 {
82 outbuffer.content[plaintext.len..][..AES_CCM_TAG_LEN].copy_from_slice(&tag);
83 } else {
84 panic!("Preconfigured sizes should not allow encryption to fail")
85 }
86 outbuffer.len = plaintext.len + AES_CCM_TAG_LEN;
87 outbuffer
88 }
89
90 fn aes_ccm_decrypt_tag_8(
91 &mut self,
92 key: &BytesCcmKeyLen,
93 iv: &BytesCcmIvLen,
94 ad: &[u8],
95 ciphertext: &BufferCiphertext3,
96 ) -> Result<BufferPlaintext3, EDHOCError> {
97 let key = AesCcm16_64_128::new(key.into());
98 let mut buffer = BufferPlaintext3::new();
99 buffer.len = ciphertext.len - AES_CCM_TAG_LEN;
100 buffer.content[..buffer.len].copy_from_slice(&ciphertext.content[..buffer.len]);
101 let tag = &ciphertext.content[buffer.len..][..AES_CCM_TAG_LEN];
102 key.decrypt_in_place_detached(iv.into(), ad, &mut buffer.content[..buffer.len], tag.into())
103 .map_err(|_| EDHOCError::MacVerificationFailed)?;
104 Ok(buffer)
105 }
106
107 fn p256_ecdh(
108 &mut self,
109 private_key: &BytesP256ElemLen,
110 public_key: &BytesP256ElemLen,
111 ) -> BytesP256ElemLen {
112 let secret = p256::SecretKey::from_bytes(private_key.as_slice().into())
113 .expect("Invalid secret key generated");
114 let public = p256::AffinePoint::decompress(
115 public_key.into(),
116 1.into(), )
118 .expect("Public key is not a good point");
123
124 (*p256::ecdh::diffie_hellman(secret.to_nonzero_scalar(), public).raw_secret_bytes()).into()
125 }
126
127 fn get_random_byte(&mut self) -> u8 {
128 self.rng.next_u32() as _
129 }
130
131 fn p256_generate_key_pair(&mut self) -> (BytesP256ElemLen, BytesP256ElemLen) {
132 let secret = p256::SecretKey::random(&mut self.rng);
133
134 let public_key = secret.public_key().as_affine().x();
135 let private_key = secret.to_bytes();
136
137 (private_key.into(), public_key.into())
138 }
139}