synta 0.2.6

ASN.1 parser, decoder, and encoder library with DER/BER support and C FFI
Documentation
//! Tests for BER (Basic Encoding Rules) specific features

use synta::types::constructed::{Element, Sequence};
use synta::types::primitive::{Boolean, Integer};
use synta::types::string::OctetStringRef;
use synta::{Decoder, Encoding, ToDer};

#[test]
fn test_ber_indefinite_length_sequence() {
    // BER SEQUENCE with indefinite length
    // Tag: 0x30 (SEQUENCE, constructed)
    // Length: 0x80 (indefinite)
    // Content: INTEGER 42 (0x02 0x01 0x2A)
    // End-of-contents: 0x00 0x00
    let data = vec![
        0x30, 0x80, // SEQUENCE, indefinite length
        0x02, 0x01, 0x2A, // INTEGER 42
        0x00, 0x00, // End-of-contents
    ];

    let mut decoder = Decoder::new(&data, Encoding::Ber);
    let result = decoder.decode::<Sequence>();

    assert!(
        result.is_ok(),
        "Failed to decode indefinite length sequence"
    );
    let elements = result.unwrap().into_elements().unwrap();
    assert_eq!(elements.len(), 1);

    match &elements[0] {
        Element::Integer(i) => assert_eq!(i.as_i64().unwrap(), 42),
        _ => panic!("Expected Integer element"),
    }
}

#[test]
fn test_ber_nested_indefinite_length() {
    // Nested indefinite length sequences
    // Outer SEQUENCE with indefinite length containing
    // an inner SEQUENCE with indefinite length
    let data = vec![
        0x30, 0x80, // Outer SEQUENCE, indefinite
        0x30, 0x80, // Inner SEQUENCE, indefinite
        0x02, 0x01, 0x2A, // INTEGER 42
        0x00, 0x00, // End of inner SEQUENCE
        0x00, 0x00, // End of outer SEQUENCE
    ];

    let mut decoder = Decoder::new(&data, Encoding::Ber);
    let result = decoder.decode::<Sequence>();

    assert!(result.is_ok(), "Failed to decode nested indefinite length");
    let elements = result.unwrap().into_elements().unwrap();
    assert_eq!(elements.len(), 1);

    match &elements[0] {
        Element::Sequence(inner) => {
            let inner_els = inner.clone().into_elements().unwrap();
            assert_eq!(inner_els.len(), 1);
            match &inner_els[0] {
                Element::Integer(i) => assert_eq!(i.as_i64().unwrap(), 42),
                _ => panic!("Expected Integer in inner sequence"),
            }
        }
        _ => panic!("Expected Sequence element"),
    }
}

#[test]
fn test_ber_indefinite_length_multiple_elements() {
    // SEQUENCE with indefinite length containing multiple elements
    let data = vec![
        0x30, 0x80, // SEQUENCE, indefinite
        0x02, 0x01, 0x2A, // INTEGER 42
        0x01, 0x01, 0xFF, // BOOLEAN TRUE
        0x02, 0x01, 0x05, // INTEGER 5
        0x00, 0x00, // End-of-contents
    ];

    let mut decoder = Decoder::new(&data, Encoding::Ber);
    let result = decoder.decode::<Sequence>();

    assert!(result.is_ok());
    let elements = result.unwrap().into_elements().unwrap();
    assert_eq!(elements.len(), 3);

    match &elements[0] {
        Element::Integer(i) => assert_eq!(i.as_i64().unwrap(), 42),
        _ => panic!("Expected Integer"),
    }

    match &elements[1] {
        Element::Boolean(b) => assert!(b.value()),
        _ => panic!("Expected Boolean"),
    }

    match &elements[2] {
        Element::Integer(i) => assert_eq!(i.as_i64().unwrap(), 5),
        _ => panic!("Expected Integer"),
    }
}

#[test]
fn test_ber_indefinite_length_rejected_in_der() {
    // Same indefinite length sequence should be rejected in DER mode
    let data = vec![
        0x30, 0x80, // SEQUENCE, indefinite length
        0x02, 0x01, 0x2A, // INTEGER 42
        0x00, 0x00, // End-of-contents
    ];

    let mut decoder = Decoder::new(&data, Encoding::Der);
    let result = decoder.decode::<Sequence>();

    assert!(result.is_err(), "DER should reject indefinite length");
}

#[test]
fn test_ber_missing_end_of_contents() {
    // Indefinite length without proper termination
    let data = vec![
        0x30, 0x80, // SEQUENCE, indefinite length
        0x02, 0x01, 0x2A, // INTEGER 42
              // Missing end-of-contents octets
    ];

    let mut decoder = Decoder::new(&data, Encoding::Ber);
    let result = decoder.decode::<Sequence>();

    assert!(result.is_err(), "Should fail without end-of-contents");
}

#[test]
fn test_ber_definite_length_still_works() {
    // Verify that BER mode still handles definite length correctly
    let data = vec![
        0x30, 0x03, // SEQUENCE, definite length 3
        0x02, 0x01, 0x2A, // INTEGER 42
    ];

    let mut decoder = Decoder::new(&data, Encoding::Ber);
    let result = decoder.decode::<Sequence>();

    assert!(result.is_ok());
    let elements = result.unwrap().into_elements().unwrap();
    assert_eq!(elements.len(), 1);
}

#[test]
fn test_ber_relaxed_boolean() {
    // BER allows any non-zero value for TRUE (tested in der_compliance_tests.rs too)
    // This test is just to verify BER mode handles it
    let data = vec![0x01, 0x01, 0x42]; // BOOLEAN with value 0x42

    let mut decoder = Decoder::new(&data, Encoding::Ber);
    let result = decoder.decode::<Boolean>();

    assert!(result.is_ok());
    assert!(result.unwrap().value());
}

#[test]
fn test_ber_encoding_uses_definite_length() {
    // BER encoder should use definite length by default
    // (indefinite length encoding is optional)
    let mut seq = Sequence::new();
    seq.push(Element::Integer(Integer::from(42)));

    let encoded = seq.to_ber().unwrap();

    // Should not contain indefinite length marker (0x80)
    // and should have definite length encoding
    assert_eq!(encoded[0], 0x30); // SEQUENCE tag
    assert!(encoded[1] != 0x80); // Not indefinite length

    // Verify it decodes correctly
    // Sequence<'_> borrows from input, so use Decoder directly
    let mut decoder = Decoder::new(&encoded, Encoding::Ber);
    let decoded = decoder.decode::<Sequence>().unwrap();
    assert_eq!(decoded.into_elements().unwrap().len(), 1);
}

#[test]
fn test_ber_roundtrip() {
    // Encode in BER, decode in BER
    let mut seq = Sequence::new();
    let octet_data = vec![1, 2, 3, 4];
    seq.push(Element::Integer(Integer::from(100)));
    seq.push(Element::Boolean(Boolean::new(true)));
    seq.push(Element::OctetString(OctetStringRef::new(&octet_data)));

    let encoded = seq.to_ber().unwrap();

    // Sequence<'_> borrows from input, so use Decoder directly
    let mut decoder = Decoder::new(&encoded, Encoding::Ber);
    let decoded = decoder.decode::<Sequence>().unwrap();

    assert_eq!(decoded.into_elements().unwrap().len(), 3);
}