hax_lib_protocol/
crypto.rs

1//! This module defines a cryptographic abstraction layer for use in
2//! hax protocol specifications.
3
4use crate::ProtocolError;
5
6/// An abstract Diffie-Hellman scalar.
7#[derive(Clone)]
8pub struct DHScalar(Vec<u8>);
9
10impl DHScalar {
11    /// Wrap bytes into a Diffie-Hellman scalar. Does *not* perform
12    /// input validation.
13    pub fn from_bytes(bytes: &[u8]) -> Self {
14        DHScalar(bytes.to_vec())
15    }
16}
17
18/// An abstract Diffie-Hellman group element.
19pub struct DHElement(Vec<u8>);
20
21impl DHElement {
22    /// Wrap bytes into a Diffie-Hellman group element. Does *not* perform
23    /// input validation.
24    pub fn from_bytes(bytes: &[u8]) -> Self {
25        DHElement(bytes.to_vec())
26    }
27}
28
29/// Choice of Diffie-Hellman groups.
30pub enum DHGroup {
31    X25519,
32    X448,
33    P256,
34    P384,
35    P521,
36}
37
38impl From<DHGroup> for libcrux::ecdh::Algorithm {
39    /// Converter to `libcrux` type.
40    fn from(value: DHGroup) -> Self {
41        match value {
42            DHGroup::X25519 => libcrux::ecdh::Algorithm::X25519,
43            DHGroup::X448 => libcrux::ecdh::Algorithm::X448,
44            DHGroup::P256 => libcrux::ecdh::Algorithm::P256,
45            DHGroup::P384 => libcrux::ecdh::Algorithm::P384,
46            DHGroup::P521 => libcrux::ecdh::Algorithm::P521,
47        }
48    }
49}
50
51/// Scalar multiplication of `scalar` and `element`.
52pub fn dh_scalar_multiply(group: DHGroup, scalar: DHScalar, element: DHElement) -> Vec<u8> {
53    libcrux::ecdh::derive(group.into(), element.0, scalar.0).unwrap()
54}
55
56/// Scalar multiplication of a fixed generator and `scalar`.
57pub fn dh_scalar_multiply_base(group: DHGroup, scalar: DHScalar) -> Vec<u8> {
58    libcrux::ecdh::secret_to_public(group.into(), scalar.0).unwrap()
59}
60
61/// An abstract AEAD key.
62pub struct AEADKey(libcrux::aead::Key);
63
64/// Choice of AEAD algorithms.
65pub enum AEADAlgorithm {
66    Aes128Gcm,
67    Aes256Gcm,
68    Chacha20Poly1305,
69}
70
71impl From<AEADAlgorithm> for libcrux::aead::Algorithm {
72    /// Converter to `libcrux` type.
73    fn from(value: AEADAlgorithm) -> Self {
74        match value {
75            AEADAlgorithm::Aes128Gcm => libcrux::aead::Algorithm::Aes128Gcm,
76            AEADAlgorithm::Aes256Gcm => libcrux::aead::Algorithm::Aes256Gcm,
77            AEADAlgorithm::Chacha20Poly1305 => libcrux::aead::Algorithm::Chacha20Poly1305,
78        }
79    }
80}
81
82impl AEADKey {
83    /// Attempt deserialization of `bytes` into an AEAD key for
84    /// `algorithm`. Panics on failure.
85    pub fn from_bytes(algorithm: AEADAlgorithm, bytes: &[u8]) -> Self {
86        AEADKey(libcrux::aead::Key::from_bytes(algorithm.into(), bytes.to_vec()).unwrap())
87    }
88}
89
90/// An abstract AEAD initialization vector.
91pub struct AEADIV(libcrux::aead::Iv);
92
93impl AEADIV {
94    /// Attempt construction of an AEAD IV from `bytes`. Panics if
95    /// number of `bytes` is insufficient.
96    pub fn from_bytes(bytes: &[u8]) -> Self {
97        AEADIV(libcrux::aead::Iv::new(bytes).unwrap())
98    }
99}
100
101/// An abstract AEAD authentication tag.
102pub struct AEADTag(libcrux::aead::Tag);
103impl AEADTag {
104    /// Attempt deserialization of an AEAD tag from `bytes`. Panics if
105    /// number of `bytes` is insufficient.
106    pub fn from_bytes(bytes: &[u8]) -> Self {
107        let bytes: [u8; 16] = bytes.try_into().unwrap();
108        AEADTag(libcrux::aead::Tag::from(bytes))
109    }
110}
111
112/// Abstract AEAD encryption using `algorithm`. Returns a pair of byte
113/// vectors `(ciphertext, tag)`.
114pub fn aead_encrypt(key: AEADKey, iv: AEADIV, aad: &[u8], plain: &[u8]) -> (Vec<u8>, Vec<u8>) {
115    let (tag, cip) = libcrux::aead::encrypt_detached(&key.0, plain, iv.0, aad).unwrap();
116    (cip, tag.as_ref().to_vec())
117}
118
119/// Abstract AEAD decryption using `algorithm`. On success returns the
120/// decrypted plaintext, otherwise a `CryptoError`.
121pub fn aead_decrypt(
122    key: AEADKey,
123    iv: AEADIV,
124    aad: &[u8],
125    cip: &[u8],
126    tag: AEADTag,
127) -> Result<Vec<u8>, ProtocolError> {
128    libcrux::aead::decrypt_detached(&key.0, cip, iv.0, aad, &tag.0)
129        .map_err(|_| ProtocolError::CryptoError)
130}
131
132/// Choice of hashing algorithms.
133pub enum HashAlgorithm {
134    Sha1,
135    Sha224,
136    Sha256,
137    Sha384,
138    Sha512,
139    Blake2s,
140    Blake2b,
141    Sha3_224,
142    Sha3_256,
143    Sha3_384,
144    Sha3_512,
145}
146
147impl From<HashAlgorithm> for libcrux::digest::Algorithm {
148    /// Converter to `libcrux` type.
149    fn from(value: HashAlgorithm) -> Self {
150        match value {
151            HashAlgorithm::Sha1 => libcrux::digest::Algorithm::Sha1,
152            HashAlgorithm::Sha224 => libcrux::digest::Algorithm::Sha224,
153            HashAlgorithm::Sha256 => libcrux::digest::Algorithm::Sha256,
154            HashAlgorithm::Sha384 => libcrux::digest::Algorithm::Sha384,
155            HashAlgorithm::Sha512 => libcrux::digest::Algorithm::Sha512,
156            HashAlgorithm::Blake2s => libcrux::digest::Algorithm::Blake2s,
157            HashAlgorithm::Blake2b => libcrux::digest::Algorithm::Blake2b,
158            HashAlgorithm::Sha3_224 => libcrux::digest::Algorithm::Sha3_224,
159            HashAlgorithm::Sha3_256 => libcrux::digest::Algorithm::Sha3_256,
160            HashAlgorithm::Sha3_384 => libcrux::digest::Algorithm::Sha3_384,
161            HashAlgorithm::Sha3_512 => libcrux::digest::Algorithm::Sha3_512,
162        }
163    }
164}
165
166/// Abstract hashing using `algorithm`.
167pub fn hash(algorithm: HashAlgorithm, input: &[u8]) -> Vec<u8> {
168    libcrux::digest::hash(algorithm.into(), input)
169}
170
171/// Choice of algorithms for instantiation of HMAC.
172pub enum HMACAlgorithm {
173    Sha1,
174    Sha256,
175    Sha384,
176    Sha512,
177}
178
179impl From<HMACAlgorithm> for libcrux::hmac::Algorithm {
180    /// Converter to `libcrux` type.
181    fn from(value: HMACAlgorithm) -> Self {
182        match value {
183            HMACAlgorithm::Sha1 => libcrux::hmac::Algorithm::Sha1,
184            HMACAlgorithm::Sha256 => libcrux::hmac::Algorithm::Sha256,
185            HMACAlgorithm::Sha384 => libcrux::hmac::Algorithm::Sha384,
186            HMACAlgorithm::Sha512 => libcrux::hmac::Algorithm::Sha512,
187        }
188    }
189}
190
191/// Abstract HMAC using `algorithm` as the hash function.
192pub fn hmac(algorithm: HMACAlgorithm, key: &[u8], input: &[u8]) -> Vec<u8> {
193    libcrux::hmac::hmac(algorithm.into(), key, input, None)
194}