tasign 0.2.0

TA ELF signing utilities with CMS/PKCS#7 support
//! SM2 PKCS#8 PEM → `Pk` (mbedtls backend).

extern crate alloc;

use alloc::string::String;
use num_bigint::BigUint;

use super::hash::map_mbedtls_err;
use super::pk::Pk;
use super::rng::{CtrDrbg, OsEntropy};
use crate::crypto::key_parse::{sm2_scalar_fixed32_be, sm2_secret_from_pkcs8_pem_with_pass};
use crate::crypto::CryptoError;

/// Parse PKCS#8 PEM into an SM2 `Pk` with `PkType::SM2`.
pub fn sm2_pk_from_pkcs8_pem_with_pass(pem: &str, pass: &str) -> Result<Pk, CryptoError> {
    let sk = sm2_secret_from_pkcs8_pem_with_pass(pem, pass)?;
    sm2_pk_from_scalar(&sk)
}

/// Build SM2 `Pk` from a private scalar (`PkType::SM2`).
pub fn sm2_pk_from_scalar(sk: &BigUint) -> Result<Pk, CryptoError> {
    use mbedtls::bignum::Mpi;
    use mbedtls::ecp::EcGroup;
    use mbedtls::pk::{EcGroupId, Type as PkType};
    use std::sync::Arc;

    let sk_bytes = sm2_scalar_fixed32_be(sk)?;
    let curve = EcGroup::new(EcGroupId::SM2P256R1).map_err(map_mbedtls_err)?;
    let d = Mpi::from_binary(&sk_bytes).map_err(map_mbedtls_err)?;
    let entropy = Arc::new(OsEntropy::new());
    let mut rng = CtrDrbg::new(entropy, None).map_err(map_mbedtls_err)?;
    mbedtls::pk::Pk::private_from_ec_scalar_with_rng_extend(
        curve,
        d,
        &mut rng,
        PkType::SM2.into(),
    )
    .map_err(map_mbedtls_err)
}

/// Build SM2 signing `Pk` from a 32-byte private scalar.
pub fn sm2_pk_from_scalar_bytes(scalar: &[u8; 32]) -> Result<Pk, CryptoError> {
    use num_bigint::BigUint;
    sm2_pk_from_scalar(&BigUint::from_bytes_be(scalar))
}

/// Build verifying `Pk` from certificate DER (SM2 / RSA / ECDSA).
pub fn pk_from_cert_der(cert_der: &[u8]) -> Result<Pk, CryptoError> {
    sm2_pk_from_cert_der(cert_der)
}

/// Parse a PEM/DER key file (RSA / ECDSA / SM2 PKCS#8) into `Pk`.
pub fn pk_parse_keyfile(path: &str, password: Option<String>) -> Result<Pk, CryptoError> {
    use alloc::string::ToString;
    Pk::parse_keyfile(path.to_string(), password).map_err(map_mbedtls_err)
}

/// Build SM2 verifying `Pk` from certificate DER.
pub fn sm2_pk_from_cert_der(cert_der: &[u8]) -> Result<Pk, CryptoError> {
    let mut cert =
        mbedtls::x509::Certificate::from_der(cert_der).map_err(map_mbedtls_err)?;
    let pub_der = cert
        .public_key_mut()
        .write_public_der_vec()
        .map_err(map_mbedtls_err)?;
    Pk::from_public_key(&pub_der).map_err(map_mbedtls_err)
}