tasign 0.2.0

TA ELF signing utilities with CMS/PKCS#7 support
//! Hash types and SM3 digest (RustCrypto backend).

extern crate alloc;

use alloc::vec::Vec;

use digest::Digest as _;

/// Hash algorithm identifier (aligned with mbedtls `MdType` naming).
///
/// Currently only SM3 (国密 CMS) and SHA-256 (RSA/ECDSA CMS) are supported.
/// Other digest algorithms return [`CryptoError::UnsupportedAlgorithm`].
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MdType {
    SM3,
    Sha256,
}

/// Trait for cryptographic hash functions.
pub trait Digest {
    fn new() -> Self
    where
        Self: Sized;

    fn update(&mut self, data: &[u8]);

    fn finalize(self) -> Vec<u8>;

    fn output_size() -> usize;

    fn name() -> &'static str;
}

/// SM3 hash (32-byte output).
#[derive(Clone)]
pub struct Sm3 {
    inner: sm3::Sm3,
}

impl Digest for Sm3 {
    fn new() -> Self {
        Self {
            inner: sm3::Sm3::new(),
        }
    }

    fn update(&mut self, data: &[u8]) {
        self.inner.update(data);
    }

    fn finalize(self) -> Vec<u8> {
        self.inner.finalize().to_vec()
    }

    fn output_size() -> usize {
        32
    }

    fn name() -> &'static str {
        "SM3"
    }
}

/// Compute a 32-byte digest.
pub fn digest32(md: MdType, data: &[u8]) -> crate::crypto::Result<[u8; 32]> {
    match md {
        MdType::SM3 => {
            let mut h = Sm3::new();
            h.update(data);
            let v = h.finalize();
            let mut out = [0u8; 32];
            out.copy_from_slice(&v);
            Ok(out)
        }
        MdType::Sha256 => {
            use sha2::{Digest as Sha2Digest, Sha256};
            let digest = Sha256::digest(data);
            Ok(digest.into())
        }
    }
}