matc 0.1.3

Matter protocol library (controller side)
Documentation
#![allow(dead_code)]

use aes::cipher::crypto_common;
use anyhow::{Context, Result};

use hmac::Mac;
use sha1::Sha1;
use sha2::{Digest, Sha256};

pub fn hkdf_sha256(salt: &[u8], secret: &[u8], info: &[u8], size: usize) -> Result<Vec<u8>> {
    let hk = hkdf::Hkdf::<Sha256>::new(Some(salt), secret);
    let mut okm = vec![0u8; size];
    match hk.expand(info, &mut okm) {
        Ok(()) => Ok(okm),
        Err(e) => Err(anyhow::anyhow!(format!("hkdf error {:?}", e))),
    }
}

pub fn hmac_sha256(data: &[u8], key: &[u8]) -> Result<Vec<u8>> {
    if let Ok(mut hm) = hmac::Hmac::<Sha256>::new_from_slice(key) {
        hm.update(data);
        Ok(hm.finalize().into_bytes().to_vec())
    } else {
        Err(anyhow::anyhow!(format!("can't create hmac {:?}", key)))
    }
}

pub fn sha256(data: &[u8]) -> Vec<u8> {
    let mut hasher = Sha256::new();
    hasher.update(data);
    hasher.finalize().to_vec()
}
pub fn sha1_enc(data: &[u8]) -> Vec<u8> {
    let mut hasher = Sha1::new();
    hasher.update(data);
    hasher.finalize().to_vec()
}

type Aes128Ccm = ccm::Ccm<aes::Aes128, ccm::consts::U16, ccm::consts::U13>;
pub fn aes128_ccm_encrypt(
    key: &crypto_common::Key<Aes128Ccm>,
    nonce: &[u8],
    aad: &[u8],
    msg: &[u8],
) -> Result<Vec<u8>> {
    let cipher = <Aes128Ccm as ccm::KeyInit>::new(key);
    match ccm::aead::Aead::encrypt(
        &cipher,
        crypto_common::generic_array::GenericArray::from_slice(nonce),
        ccm::aead::Payload { msg, aad },
    ) {
        Ok(o) => Ok(o),
        Err(e) => Err(anyhow::anyhow!("encrypt error {:?}", e)),
    }
}

pub fn aes128_ccm_decrypt(
    key: &crypto_common::Key<Aes128Ccm>,
    nonce: &[u8],
    aad: &[u8],
    msg: &[u8],
) -> Result<Vec<u8>> {
    let cipher = <Aes128Ccm as ccm::KeyInit>::new(key);
    match ccm::aead::Aead::decrypt(
        &cipher,
        crypto_common::generic_array::GenericArray::from_slice(nonce),
        ccm::aead::Payload { msg, aad },
    ) {
        Ok(o) => Ok(o),
        Err(e) => Err(anyhow::anyhow!(format!("decrypt error {:?}", e))),
    }
}

pub fn read_private_key_from_pem(fname: &str) -> Result<p256::SecretKey> {
    let file_contents = std::fs::read_to_string(fname)
    .context(format!("can't read file {}", fname))?;
    Ok(p256::SecretKey::from_sec1_pem(&file_contents)?)
}
pub fn read_private_key_bytes_from_pem(fname: &str) -> Result<Vec<u8>> {
    let file_contents = std::fs::read_to_string(fname)
    .context(format!("can't read file {}", fname))?;
    Ok(pem::parse(file_contents)?.contents().to_vec())
}

pub fn read_signing_key_from_pem(fname: &str) -> Result<ecdsa::SigningKey<p256::NistP256>> {
    let file_contents = std::fs::read_to_string(fname)
    .context(format!("can't read file {}", fname))?;
    Ok(ecdsa::SigningKey::from(p256::SecretKey::from_sec1_pem(
        &file_contents,
    )?))
}

pub fn read_pub_key_from_pem(fname: &str) -> Result<Vec<u8>> {
    let file_contents = std::fs::read_to_string(fname)
    .context(format!("can't read file {}", fname))?;
    let secretkey = p256::SecretKey::from_sec1_pem(&file_contents)?;
    Ok(secretkey.public_key().to_sec1_bytes().to_vec())
}

pub fn read_data_from_pem(fname: &str) -> Result<Vec<u8>> {
    let file_contents = std::fs::read_to_string(fname)
    .context(format!("can't read file {}", fname))?;
    Ok(pem::parse(file_contents)?.contents().to_vec())
}

pub fn write_pem(tag: &str, data: &[u8], fname: &str) -> Result<()> {
    let p = pem::Pem::new(tag, data);
    let enc = pem::encode(&p);
    std::fs::write(fname, enc)?;
    Ok(())
}

pub fn secret_key_to_rfc5915(key: &p256::SecretKey) -> Result<Vec<u8>> {
    let mut enc = crate::util::asn1::Encoder::new();
    enc.start_seq(0x30)?;
    enc.write_int(1)?;
    enc.write_octet_string(key.to_bytes().as_slice())?;
    enc.start_seq(0xa0)?;
    enc.write_oid("1.2.840.10045.3.1.7")?;
    enc.end_seq();
    enc.start_seq(0xa1)?;
    let mut b: Vec<u8> = vec![0];
    b.extend_from_slice(&key.public_key().to_sec1_bytes());
    enc.write_octet_string_with_tag(0x3, &b)?;
    enc.end_seq();
    enc.end_seq();
    Ok(enc.encode())
}