tee_crypto 0.1.4

TEE Crypto Crate.
Documentation
// SPDX-License-Identifier: Apache-2.0
// Copyright 2025 KylinSoft Co., Ltd. <https://www.kylinos.cn/>
// See LICENSES for license details.

extern crate alloc;

mod common;

use tee_crypto::{
    CryptoError,
    ed25519::{
        ED25519_CTX_MAX_LENGTH, ED25519_SIGNATURE_SIZE_BYTES, Ed25519Variant,
        ed25519_generate_keypair, ed25519_sign, ed25519_sign_variant, ed25519_verify,
        ed25519_verify_variant,
    },
};

fn hex_decode(s: &str) -> alloc::vec::Vec<u8> {
    hex::decode(s).expect("valid test hex")
}

fn key32(bytes: &[u8]) -> [u8; 32] {
    bytes.try_into().expect("32-byte key")
}

#[test]
fn test_ed25519_keygen_sign_verify_roundtrip() {
    let mut rng = common::seeded_rng(42);
    let (seed, public_key) = ed25519_generate_keypair(&mut rng).expect("keygen");
    let message = b"hello Ed25519";

    let sig = ed25519_sign(&seed, message).expect("sign");
    assert_eq!(sig.as_bytes().len(), ED25519_SIGNATURE_SIZE_BYTES);
    ed25519_verify(&public_key, message, sig.as_bytes()).expect("verify");
}

#[test]
fn test_ed25519_verify_wrong_message_fails() {
    let mut rng = common::seeded_rng(55);
    let (seed, public_key) = ed25519_generate_keypair(&mut rng).expect("keygen");
    let sig = ed25519_sign(&seed, b"correct").expect("sign");
    assert_eq!(
        ed25519_verify(&public_key, b"wrong", sig.as_bytes()).unwrap_err(),
        CryptoError::VerificationFailed
    );
}

/// CBOR SigStructure verify vector from `tee_svc_cryp2::test_cryp_ed25519_verify_sig_structure_vector`.
#[test]
fn test_ed25519_verify_sig_structure_vector() {
    let public_key = key32(&hex_decode(
        "720e968320f6d324d29423d546524c7acbb549c12a49e059dbc508c56099f82e",
    ));
    let signature = hex_decode(
        "8399c94482427c9831776073c2e5c3b73f4f8a659601606f3c56aab6b27c68543948cb578a1c7b17f178ac203546d69f6174443a885448e8371659788162a400",
    );
    let message = hex_decode(
        "846a5369676e61747572653143a1012740590188a901782830323836306133303533633262626339666336396262383235663134653134333136393965323930027828376266386562323866393934323830373062363862346263356534323163373166313765306166313a0047445058400bde5e136fceb2c6fdeda53ec8faac595e88f46c5b5a93fe03a3d17f76f5753ce94d5748d2f8709ac546585da5aa1cc13bdba7b013e00fe6b4d1646eb05423bf3a0047445354a23a00011171634156423a000111721a1a0001733a004744525840a6793f45095c98d12b197fd255c2401c885d042df34c25779febefbbd179e7f3fce6b0393526a57e7637a3a7884d78e7047c152d64fcc01928dbc57a00e25f6d3a004744545840000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003a0047445641023a00474457582da50101032704810220062158202ce5042362885a95d0897c033359516fd8e98cd2f5b8e3052dd0a1cd540ddb283a004744584120",
    );

    assert_eq!(signature.len(), ED25519_SIGNATURE_SIZE_BYTES);
    assert_eq!(message.len(), 412);

    ed25519_verify(&public_key, &message, &signature).expect("verify sig structure vector");
}

#[test]
fn test_ed25519_verify_sig_structure_vector_tampered_signature_fails() {
    let public_key = key32(&hex_decode(
        "720e968320f6d324d29423d546524c7acbb549c12a49e059dbc508c56099f82e",
    ));
    let mut signature = hex_decode(
        "8399c94482427c9831776073c2e5c3b73f4f8a659601606f3c56aab6b27c68543948cb578a1c7b17f178ac203546d69f6174443a885448e8371659788162a400",
    );
    let message = hex_decode(
        "846a5369676e61747572653143a1012740590188a901782830323836306133303533633262626339666336396262383235663134653134333136393965323930027828376266386562323866393934323830373062363862346263356534323163373166313765306166313a0047445058400bde5e136fceb2c6fdeda53ec8faac595e88f46c5b5a93fe03a3d17f76f5753ce94d5748d2f8709ac546585da5aa1cc13bdba7b013e00fe6b4d1646eb05423bf3a0047445354a23a00011171634156423a000111721a1a0001733a004744525840a6793f45095c98d12b197fd255c2401c885d042df34c25779febefbbd179e7f3fce6b0393526a57e7637a3a7884d78e7047c152d64fcc01928dbc57a00e25f6d3a004744545840000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003a0047445641023a00474457582da50101032704810220062158202ce5042362885a95d0897c033359516fd8e98cd2f5b8e3052dd0a1cd540ddb283a004744584120",
    );

    signature[ED25519_SIGNATURE_SIZE_BYTES - 1] ^= 0xff;
    assert_eq!(
        ed25519_verify(&public_key, &message, &signature).unwrap_err(),
        CryptoError::VerificationFailed
    );
}

/// RFC 8032 section 7.2 Ed25519ctx test vector.
#[test]
fn test_ed25519ctx_rfc8032_7_2_sign_verify() {
    const PRIVATE: [u8; 32] = [
        0x03, 0x05, 0x33, 0x4e, 0x38, 0x1a, 0xf7, 0x8f, 0x14, 0x1c, 0xb6, 0x66, 0xf6, 0x19, 0x9f,
        0x57, 0xbc, 0x34, 0x95, 0x33, 0x5a, 0x25, 0x6a, 0x95, 0xbd, 0x2a, 0x55, 0xbf, 0x54, 0x66,
        0x63, 0xf6,
    ];
    const PUBLIC: [u8; 32] = [
        0xdf, 0xc9, 0x42, 0x5e, 0x4f, 0x96, 0x8f, 0x7f, 0x0c, 0x29, 0xf0, 0x25, 0x9c, 0xf5, 0xf9,
        0xae, 0xd6, 0x85, 0x1c, 0x2b, 0xb4, 0xad, 0x8b, 0xfb, 0x86, 0x0c, 0xfe, 0xe0, 0xab, 0x24,
        0x82, 0x92,
    ];
    const MESSAGE: [u8; 16] = [
        0xf7, 0x26, 0x93, 0x6d, 0x19, 0xc8, 0x00, 0x49, 0x4e, 0x3f, 0xda, 0xff, 0x20, 0xb2, 0x76,
        0xa8,
    ];
    const CONTEXT: [u8; 3] = [0x66, 0x6f, 0x6f];
    const SIGNATURE: [u8; 64] = [
        0x55, 0xa4, 0xcc, 0x2f, 0x70, 0xa5, 0x4e, 0x04, 0x28, 0x8c, 0x5f, 0x4c, 0xd1, 0xe4, 0x5a,
        0x7b, 0xb5, 0x20, 0xb3, 0x62, 0x92, 0x91, 0x18, 0x76, 0xca, 0xda, 0x73, 0x23, 0x19, 0x8d,
        0xd8, 0x7a, 0x8b, 0x36, 0x95, 0x0b, 0x95, 0x13, 0x00, 0x22, 0x90, 0x7a, 0x7f, 0xb7, 0xc4,
        0xe9, 0xb2, 0xd5, 0xf6, 0xcc, 0xa6, 0x85, 0xa5, 0x87, 0xb4, 0xb2, 0x1f, 0x4b, 0x88, 0x8e,
        0x4e, 0x7e, 0xdb, 0x0d,
    ];

    let variant = Ed25519Variant {
        prehash: false,
        context: Some(CONTEXT.to_vec()),
    };
    let sig = ed25519_sign_variant(&PRIVATE, &MESSAGE, &variant).expect("sign");
    assert_eq!(sig.as_bytes(), SIGNATURE);
    ed25519_verify_variant(&PUBLIC, &MESSAGE, &SIGNATURE, &variant).expect("verify");
}

#[test]
fn test_ed25519ctx_sign_verify_roundtrip() {
    let mut rng = common::seeded_rng(77);
    let (seed, public_key) = ed25519_generate_keypair(&mut rng).expect("keygen");
    let message = b"Ed25519ctx roundtrip";
    let variant = Ed25519Variant {
        prehash: false,
        context: Some(b"tee-crypto-test".to_vec()),
    };

    let sig = ed25519_sign_variant(&seed, message, &variant).expect("sign");
    ed25519_verify_variant(&public_key, message, sig.as_bytes(), &variant).expect("verify");
}

#[test]
fn test_ed25519_invalid_signature_length_fails() {
    let mut rng = common::seeded_rng(88);
    let (_, public_key) = ed25519_generate_keypair(&mut rng).expect("keygen");
    assert_eq!(
        ed25519_verify(&public_key, b"msg", &[0u8; 63]).unwrap_err(),
        CryptoError::InvalidLength
    );
}

#[test]
fn test_ed25519_variant_context_too_long_fails() {
    let variant = Ed25519Variant {
        prehash: false,
        context: Some(alloc::vec![0u8; ED25519_CTX_MAX_LENGTH + 1]),
    };
    assert_eq!(variant.validate().unwrap_err(), CryptoError::InvalidLength);
}