Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decoding output a bit unintuitive #13

Open
ssadler opened this issue Apr 1, 2020 · 7 comments
Open

Decoding output a bit unintuitive #13

ssadler opened this issue Apr 1, 2020 · 7 comments

Comments

@ssadler
Copy link

ssadler commented Apr 1, 2020

In the below script, the function test_encode prints:

a: [Explicit(ContextSpecific, 0, BigUint { data: [] }, Unknown(ContextSpecific, false, 2, BigUint { data: [] }, [0]))]
b: [Unknown(ContextSpecific, true, 0, BigUint { data: [] }, [128, 1, 0, 129, 1, 1])]

This is unexpected as the structure is the same in both occasions, and it appears to relate to this. I would expect the output to be as it is in b both times. I'm not exactly sure if the encoding is being done in the best way, but it conforms to the ASN model I am working with so I can't change it. For reference, the Haskell library asn1-encoding produces the following:

[Start (Container Context 0),Other Context 0 "\NUL",End (Container Context 0)]
[Start (Container Context 0),Other Context 0 "\NUL",Other Context 1 "\SOH",End (Container Context 0)]

Test script:

use num_traits::cast::{FromPrimitive};
use num_bigint::{BigInt, BigUint};
use simple_asn1::*;

#[test]
fn test_encode() {
    let a = encode_structure(0, &vec![vec![0]]);
    let b = encode_structure(0, &vec![vec![0], vec![1]]);
    println!("a: {:?}\nb: {:?}", from_der(&a).unwrap(), from_der(&b).unwrap());
}

fn encode_structure(type_id: u8, bufs: &[Vec<u8>]) -> Vec<u8> {
    let mut body = Vec::new();
    for (i, buf) in bufs.iter().enumerate() {
        let mut der = to_der(&ASN1Block::Unknown(ASN1Class::ContextSpecific, false, 0, BigUint::from_usize(i).unwrap(), buf.to_vec())).unwrap();
        body.append(&mut der);
    }
    to_der(&ASN1Block::Unknown(ASN1Class::ContextSpecific, true, 0, BigUint::from_u8(type_id).unwrap(), body)).unwrap()
}
@acw
Copy link
Owner

acw commented Apr 2, 2020

OK, interesting. Let me track back the reason for that particular if. Upon first examination, it does seem very suspicious.

Also, welcome fellow Haskell/Rust polyglot.

@Flakebi
Copy link
Contributor

Flakebi commented Apr 2, 2020

Seems like I introduced that code in #7.

I don’t remember why I wrote it that way, the goal was to parse OpenSSL EC keys, which contains explicitly tagged data. This comment might be the reason:

I am not sure how (and if at all) we can distinguish explicitly and
implicitly tagged data. For now they should be parsed as unknown (or
explicit if they are a valid ASN.1 block).

@acw
Copy link
Owner

acw commented Apr 2, 2020

Hmmmm! Maybe we can work together so we don't replicate each others work? Specifically:

@Flakebi: could you maybe commit an OpenSSL EC key or two in tests/, and maybe a test case that shows what you need the output to be?

@ssadler: could you commit this test case somewhere reasonable, with an assert for what you'd expect things to look like?

Maybe do this all in a fix/13 branch, since this will all be broken for a bit? Then we can all look for what the best solution is to meet both goals.

@ssadler
Copy link
Author

ssadler commented Apr 2, 2020

I've made a branch here with the test: https://github.com/ssadler/simple_asn1/tree/fix/13

It passes without the the if constructed { block here. There's also a suggested fix for a warning but I don't know if it gives the right behavior.

@Flakebi
Copy link
Contributor

Flakebi commented Apr 2, 2020

I added a small test with an explicit tag in #14.

@acw
Copy link
Owner

acw commented Apr 6, 2020

So, after doing some digging, I found this interesting quote:

If the type is tagged in EXPLICIT mode (or if the module includes the EXPLICIT TAGS clause in its header):
v [APPLICATION 0] EXPLICIT INTEGER ::= 38
the value is encoded in constructed form as a series of TLV triplets where the tag fields T contain all the subsequent tags until the UNIVERSAL class tag of the type is encountered;

(source, page 409)

Which makes me think that the current implementation is definitely wrong, but that the example @ssadler brings up might also have a not-entirely intuitive resolution. Anyone else find any interesting quotes on the topic of explicit tags?

@ssadler
Copy link
Author

ssadler commented Apr 7, 2020

I don't actually know how ASN works; my only thought is, was it tagged in Explicit mode? In this case there's no schema to indicate what mode it was tagged in, the parsing function just parses what it can according to what it knows.

The only other thing that occurrs to me, and again limited by my lack of knowledge of ASN, is that the parser could eagerly descend into the element and parse the children.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants