mls_rs_crypto_openssl/
mac.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// Copyright by contributors to this project.
3// SPDX-License-Identifier: (Apache-2.0 OR MIT)
4
5use std::ops::Deref;
6
7use mls_rs_core::crypto::CipherSuite;
8use openssl::{
9    hash::{hash, MessageDigest},
10    pkey::PKey,
11    sign::Signer,
12};
13use thiserror::Error;
14
15#[derive(Debug, Error)]
16pub enum HashError {
17    #[error(transparent)]
18    OpensslError(#[from] openssl::error::ErrorStack),
19    #[error("unsupported cipher suite")]
20    UnsupportedCipherSuite,
21}
22
23#[derive(Clone)]
24pub struct Hash(MessageDigest);
25
26impl Deref for Hash {
27    type Target = MessageDigest;
28
29    fn deref(&self) -> &Self::Target {
30        &self.0
31    }
32}
33
34impl Hash {
35    pub fn new(cipher_suite: CipherSuite) -> Result<Self, HashError> {
36        let md = match cipher_suite {
37            CipherSuite::CURVE25519_AES128
38            | CipherSuite::P256_AES128
39            | CipherSuite::CURVE25519_CHACHA => Ok(MessageDigest::sha256()),
40            CipherSuite::P384_AES256 => Ok(MessageDigest::sha384()),
41            CipherSuite::CURVE448_CHACHA
42            | CipherSuite::CURVE448_AES256
43            | CipherSuite::P521_AES256 => Ok(MessageDigest::sha512()),
44            _ => Err(HashError::UnsupportedCipherSuite),
45        }?;
46
47        Ok(Self(md))
48    }
49
50    pub fn hash(&self, data: &[u8]) -> Result<Vec<u8>, HashError> {
51        Ok(hash(self.0, data)?.to_vec())
52    }
53
54    pub fn mac(&self, key: &[u8], data: &[u8]) -> Result<Vec<u8>, HashError> {
55        let key = PKey::hmac(key)?;
56        let mut signer = Signer::new(self.0, &key)?;
57        Ok(signer.sign_oneshot_to_vec(data)?)
58    }
59}