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

DER Support #10

Open
masihyeganeh opened this issue Apr 11, 2020 · 12 comments
Open

DER Support #10

masihyeganeh opened this issue Apr 11, 2020 · 12 comments

Comments

@masihyeganeh
Copy link

Hi.
My project heavily depends on parsing DER encoded data.
Your crate is by far the most interesting ASN1 parsers.
Is it hard to implement DER for it too?
I can contribute to that but I'm not sure where to start.

@kellerkindt
Copy link
Owner

kellerkindt commented Apr 14, 2020

Hi there,
I dont know how hard it is to implement DER-serialization. Maybe you can gather useful information from this pdf or directly from ITU / ITU-DER.

I'd suggest the following steps in implementing DER support:

  • create a DER module with Der-, Read- and Write-traits that provide all primitive (de-)serialization types (like for UPER in src/io/uper.rs)
  • add a new GeneratorSupplement impl for DerSerializer, that generates the Rust impl code for the DER-(de-)serialization-trait (see asn1rs-model/src/gen/rust/uper.rs)

Feel free to contribute via PRs whenever you like to :)

kellerkindt added a commit that referenced this issue Apr 22, 2020
…exity

The current approach to generate the (de-)serialization code is to messy,
too hard to understand, too hard to extend and too complex. The new idea is
to introduce a further codegen step.

1) ASN Definition   -- old codegen -->  3) Rust struct with (de-)serializable

   |                                                    A
   | generate                                proc-macro |
   V                                                    |

 2) Rust struct with attributes and that pleasant for human eyes

Instead of writing 3) to the user file, 2) shall now be written instead.
Also, instead of generate comple (de-)serializ code in 3), the Visitor
pattern is being used to walk the types and values on the generated data
types. This hopefully allows to implement UPER, PER, BER, ... #1 #10 #11
@kellerkindt
Copy link
Owner

@masihyeganeh I suggest to await the current refactoring (see #11) which should make it easy-ish to extend this crate with another encoding (DER in your case) and without the need to codegen for it.

@kellerkindt
Copy link
Owner

kellerkindt commented May 8, 2020

Hi there, refactoring is almost complete. I'll get rid of (the) old (uper) code soon/next.

If you want to, you can look into implementing a DerReader and DerWriter, analogue to println and uPER. The showcase demonstrates basic inline-usage. The idea is to only have to swap the UperWriter/-Reader with a DerWriter/-Reader in the uper_proof function to create a der_proof function without further code generation.

I guess some ASN syntax and types you'll need are not parsed or implemented yet. If you show some samples I'll might focus on them next. Otherwise I'll probably keep on trying to get LDAP working next.

I'll gladly accept a PR for a working implementation 😃

@masihyeganeh
Copy link
Author

Fantastic.
Would you please release a version on crates.io so I can play with it?
I couldn't make it work with master branch.

@kellerkindt
Copy link
Owner

kellerkindt commented May 13, 2020

@masihyeganeh I just did, but I would also like to know why it did not work for you. Maybe its and issue with my repository layout? If so, I might be able to fix it, if you are give me a more concrete error description.

@masihyeganeh
Copy link
Author

Thanks.
It was because of my other dependencies.
My old version of reqwest was conflicting with yours.
Can you please implement SET and SET OF before I start to figure out how to implement DER? It is really similar to SEQUENCE I think.
I'm not that familiar with detail of ASN, I should try to implement it somehow based on rfc

@masihyeganeh
Copy link
Author

I just started to implement DER, but I think I'm lost.
I copied src/syn/io/uper.rs to src/syn/io/der.rs and started changing it, but I found out that in other parts of code, like this one, there is direct dependency on Uper*:

impl UperReader for LegacyBitBuffer<'_> {

It is not clear to me how to implement it, what files I need to change and ...
Considering that DER is the simplest implementation of this family, I hope we can do it soon.

And by the way, I tested your experimental-set-setof branch with my asn file and it worked well (almost, there was a minor catch). I hope you merge it soon.

@kellerkindt
Copy link
Owner

kellerkindt commented Sep 18, 2020

I just added the der-support branch where I copied the UPER related modules for DER. Let me explain real quick:

  • io::buf::OctetBuffer is the analogy to io::per::unaligned::buffer::BitBuffer: store and access octets (so in this case it is just a fancy wrapper around a Vec<u8>)
  • io::der::DistinguishedRead and -Write traits shall define read/write functions for the "primitive" types of DER according to the mentions in X.690 (I don't know whether they are the same as for (u)PER, which is why I didn't copy over the function definitions from PackedRead and -Write).
  • io::der::octet_aligned-module implements theses DistinguishedRead/-Write traits for the OctetBuffer (OctetBuffer is probably? re-used with additional impls for other encoding rules like BER? So not putting the impls directly in the io::buff module is just an attempt to keep things separate and organized)
  • syn::io::der::DerReader and -Writer adapt the calls from the generated data structs to the OctetBuffer/to the DistinguishedRead/-Write implementation of the OctetBuffer. Maybe you need to add a similar Scope enum like the one used for the UperRead/-Write implementation. But again, I haven't looked into DER.

Depending on how similar the DER/(u)PER traits are, I will/we can try to unify them later. But I suggest to 'just get it working' for now - even if this means duplicat-ish code/declarations atm. Refactoring working code with proper tests is much easier than trying to get the structure, abstraction and impl right at once.

I hope this helps you to get you going 😄

EDIT: regarding the experimental-set-setof branch, #13 describes the current blocker for merging.
EDIT2: Poke me, if you need access to the tags which aren't yet represented in the type constraints and thus not available in the read/write adapter calls. But I can prioritize this if you need it.

@masihyeganeh
Copy link
Author

Thanks man.
This should make working on it a lot easier.
I looked at the implementation of your uper for hour and I think I know how it works now but not actually sure about it.
I need to confirm it with you.

Look, der (and ber and cer) is way simpler than uper;
There is no difference between types.
Always there is a 2 bit class, 1 bit to tell if it is primitive or constructed and 5 bits tag in first octet.
Second octed is like : 1 bit to tell it's length type and usually next 7 bits tell it's actual length or how many octets should we read as number to know the length.
Next n octets is the value

That's all. Nothing more. No especial case or anything. I'm sure you can implement it in minutes, but I had to read your code for hours to know what is going on.
For example I'm not sure it it is ok to directly call read_bit or not. I'm not sure how ro read 2 bits as a number (or enum). I saw some ranges in there and I think I need to set start and end of buffer, but it's confusing for me.

If you can give some of your time, here is a simple explaiantion of ber implementation (der is just ber, but simpler, always there is length):
https://en.m.wikipedia.org/wiki/X.690#BER_encoding

Or if you don't have time, please guide me through it.
Thanks

kellerkindt added a commit that referenced this issue Oct 9, 2020
…pe, fixes #13

Resolve all tags while augmenting the annotated structs with Constraint impls. It
is neccessary that to this state, the complex-type-references have already resolved
their tags. For this it it might be neccessary from now on to have all *.asn1 files
and their modules in scope while resolving the tags in the RustModel-to-Annotation
stage.

Quite a bit of work went into ensuring that no unncessary tags (meaning default tags)
are present in the annotated representation to prevent unnecessary bloat.

This will probably allow the SET and SET_OF branch to be merged soon #11 #10
@mouse07410
Copy link

@kellerkindt @masihyeganeh Any update on this? It would be great to have Rust code for DER encoding/decoding generated directly from the ASN.1 files.

@kellerkindt
Copy link
Owner

kellerkindt commented Jan 20, 2024

So, I've set up a basic workflow for the (Distinguished) Encoding Rules support, see the very very early boolean example

I noticed the https://asn1.io/asn1playground is now rate limited pretty early, which makes it hard for me to verify my implementations. Does anybody know an alternative for DER?

EDIT: Started to use asn1js as reference

@mouse07410
Copy link

Please consider https://GitHub.com/mouse07410/asn1c, as a cross-testing platform.

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