synta 0.2.6

ASN.1 parser, decoder, and encoder library with DER/BER support and C FFI
Documentation
//! CER (Canonical Encoding Rules) tests
//!
//! CER is designed for streaming applications where the length may not be known
//! in advance. Key rules:
//! - Constructed types >1000 bytes MUST use indefinite length
//! - Primitive types MUST use definite length
//! - Boolean, Integer follow same strict rules as DER (minimal encoding)

use synta::types::constructed::Sequence;
use synta::types::primitive::{Boolean, Integer};
use synta::{Decoder, Encoder, Encoding};

#[test]
fn test_cer_boolean_strict() {
    // CER requires strict boolean encoding (0x00 or 0xFF only)

    // Valid: 0xFF for true
    let data = [0x01, 0x01, 0xFF];
    let mut decoder = Decoder::new(&data, Encoding::Cer);
    let result = decoder.decode::<Boolean>();
    assert!(result.is_ok());
    assert!(result.unwrap().value());

    // Valid: 0x00 for false
    let data = [0x01, 0x01, 0x00];
    let mut decoder = Decoder::new(&data, Encoding::Cer);
    let result = decoder.decode::<Boolean>();
    assert!(result.is_ok());
    assert!(!result.unwrap().value());

    // Invalid: 0x01 (BER allows this but CER doesn't)
    let data = [0x01, 0x01, 0x01];
    let mut decoder = Decoder::new(&data, Encoding::Cer);
    let result = decoder.decode::<Boolean>();
    assert!(result.is_err());
    assert!(matches!(
        result.unwrap_err(),
        synta::Error::CerViolation { .. }
    ));

    // Invalid: 0x42
    let data = [0x01, 0x01, 0x42];
    let mut decoder = Decoder::new(&data, Encoding::Cer);
    let result = decoder.decode::<Boolean>();
    assert!(result.is_err());
    assert!(matches!(
        result.unwrap_err(),
        synta::Error::CerViolation { .. }
    ));
}

#[test]
fn test_cer_integer_minimal_encoding() {
    // CER requires minimal integer encoding (same as DER)

    // Valid: minimal encoding of 127
    let data = [0x02, 0x01, 0x7F];
    let mut decoder = Decoder::new(&data, Encoding::Cer);
    let result = decoder.decode::<Integer>();
    assert!(result.is_ok());
    assert_eq!(result.unwrap().as_i64().unwrap(), 127);

    // Valid: 128 requires two bytes (0x00 0x80)
    let data = [0x02, 0x02, 0x00, 0x80];
    let mut decoder = Decoder::new(&data, Encoding::Cer);
    let result = decoder.decode::<Integer>();
    assert!(result.is_ok());
    assert_eq!(result.unwrap().as_i64().unwrap(), 128);

    // Invalid: unnecessary leading 0x00
    // 127 should be encoded as 0x7F, not 0x00 0x7F
    let data = [0x02, 0x02, 0x00, 0x7F];
    let mut decoder = Decoder::new(&data, Encoding::Cer);
    let result = decoder.decode::<Integer>();
    assert!(result.is_err());
    assert!(matches!(
        result.unwrap_err(),
        synta::Error::CerViolation { .. }
    ));

    // Invalid: unnecessary leading 0xFF
    // -1 should be encoded as 0xFF, not 0xFF 0xFF
    let data = [0x02, 0x02, 0xFF, 0xFF];
    let mut decoder = Decoder::new(&data, Encoding::Cer);
    let result = decoder.decode::<Integer>();
    assert!(result.is_err());
    assert!(matches!(
        result.unwrap_err(),
        synta::Error::CerViolation { .. }
    ));
}

#[test]
fn test_cer_large_constructed_requires_indefinite() {
    // CER requires indefinite length for constructed types >1000 bytes

    // Create a SEQUENCE with content >1000 bytes using definite length
    // This should fail in CER mode

    let mut content = vec![0x02, 0x01, 0x00]; // INTEGER 0
                                              // Pad with more integers to exceed 1000 bytes
    while content.len() < 1001 {
        content.extend_from_slice(&[0x02, 0x01, 0x00]);
    }

    let content_len = content.len();

    // Build SEQUENCE with definite length
    let mut data = vec![0x30]; // SEQUENCE tag

    // Encode length (definite, long form for >1000 bytes)
    if content_len > 127 {
        let len_bytes = if content_len <= 0xFF {
            vec![content_len as u8]
        } else {
            vec![(content_len >> 8) as u8, (content_len & 0xFF) as u8]
        };
        data.push(0x80 | len_bytes.len() as u8);
        data.extend_from_slice(&len_bytes);
    } else {
        data.push(content_len as u8);
    }

    data.extend_from_slice(&content);

    // This should fail in CER mode (definite length >1000 bytes)
    let mut decoder = Decoder::new(&data, Encoding::Cer);
    let result = decoder.decode::<Sequence>();
    assert!(result.is_err());
    assert!(matches!(
        result.unwrap_err(),
        synta::Error::CerViolation { .. }
    ));
}

#[test]
fn test_cer_small_constructed_allows_definite() {
    // CER allows definite length for constructed types <=1000 bytes

    // Create a small SEQUENCE (well under 1000 bytes)
    let data = [
        0x30, 0x06, // SEQUENCE, length 6
        0x02, 0x01, 0x2A, // INTEGER 42
        0x02, 0x01, 0x64, // INTEGER 100
    ];

    let mut decoder = Decoder::new(&data, Encoding::Cer);
    let result = decoder.decode::<Sequence>();
    assert!(result.is_ok());
}

#[test]
fn test_cer_encoding_roundtrip() {
    // Test that encoding in CER mode and decoding works

    let value = Integer::from(42);

    // Encode in CER mode
    let mut encoder = Encoder::new(Encoding::Cer);
    encoder.encode(&value).expect("Failed to encode");
    let encoded = encoder.finish().expect("Failed to finish");

    // Decode in CER mode
    let mut decoder = Decoder::new(&encoded, Encoding::Cer);
    let decoded: Integer = decoder.decode().expect("Failed to decode");

    assert_eq!(value.as_i64().unwrap(), decoded.as_i64().unwrap());
}

#[test]
fn test_cer_vs_der_boolean() {
    // Valid CER boolean should also be valid DER
    let data = [0x01, 0x01, 0xFF];

    // Should work in both CER and DER modes
    let mut cer_decoder = Decoder::new(&data, Encoding::Cer);
    assert!(cer_decoder.decode::<Boolean>().is_ok());

    let mut der_decoder = Decoder::new(&data, Encoding::Der);
    assert!(der_decoder.decode::<Boolean>().is_ok());

    // Invalid boolean should fail in both
    let invalid_data = [0x01, 0x01, 0x42];

    let mut cer_decoder = Decoder::new(&invalid_data, Encoding::Cer);
    assert!(cer_decoder.decode::<Boolean>().is_err());

    let mut der_decoder = Decoder::new(&invalid_data, Encoding::Der);
    assert!(der_decoder.decode::<Boolean>().is_err());
}

#[test]
fn test_cer_vs_ber_boolean() {
    // BER is more lenient than CER
    let data = [0x01, 0x01, 0x01]; // 0x01 for true (valid in BER, invalid in CER)

    // Should fail in CER
    let mut cer_decoder = Decoder::new(&data, Encoding::Cer);
    assert!(cer_decoder.decode::<Boolean>().is_err());

    // Should work in BER
    let mut ber_decoder = Decoder::new(&data, Encoding::Ber);
    let result = ber_decoder.decode::<Boolean>();
    assert!(result.is_ok());
    assert!(result.unwrap().value());
}