libtomcrypt
libtomcrypt copied to clipboard
How to encode [0] IMPLICIT SET OF?
Prerequisites
- [x] Checked the developer manual
- [x] Checked that your issue isn't already filed: https://github.com/issues?utf8=✓&q=repo%3Alibtom%2Flibtomcrypt
- [x] Checked that your issue isn't due to the fact that you're using asymmetric cryptography and you forgot linking in and/or setting an MPI provider (usually this causes either random crashes or runtime errors like
LTC_ARGCHK 'ltc_mp.name != NULL' failure ...). c.f. Ch. "Math Descriptors" of the developer manual. - [x] Checked that your issue isn't related to TomsFastMath's limitation that PK operations can by default only be done with max. 2048bit keys
Description
How can I construct, using libtomcrypt release 1.18.2, a struct of type ltc_asn1_list that, when nested inside a SEQUENCE and encoded, will produce an encoded DER SET OF with an IMPLICIT CONTEXT SENSITIVE [0] tag (as in CMS SignedData certificates, for example)?
If I set list.type = LTC_ASN1_SETOF, I get a properly encoded SET but the tag is 0x31 (UNIVERSAL SET). I can manually change the tag after encoding to 0xA0, except that the SET is nested inside layers of ASN.1 data. If I use list.type = LTC_ASN1_CUSTOM_TYPE, I can get the tag I want, but the function der_encode_custom_type() encodes the items like a SEQUENCE, not in sorted order like a DER SET. If I use the macro LTC_SET_ASN1_CUSTOM_CONSTRUCTED, I can nest a SET inside a custom typed SEQUENCE, creating an EXPLICIT tag.
Am I missing something? Is there a solution in the latest developer version? It seems that I must either change the tag manually after encoding, or else pre-sort the items manually within the array list.data. A fix would be to look during der_encode_custom_type() for list.used=LTC_ASN1_SETOF.
Steps to Reproduce
Version
Release 1.18.2
Additional Information
It's possible that this currently can't be done with any ltc version.
Can you provide an example "CMS SignedData certificate" in encoded format (i.e. the expected output)?
The CMS spec RFC 5652 uses a CONTEXT SENSITIVE [0] IMPLICIT SET OF for the certificates member of a SignedData structure. A second example in CMS is the signedAttrs member of a SignerInfo structure.
But, maybe a toy example will be more useful here. In the example below, the integers are sorted by their DER encoding. This is implemented in der_encode_setof() but it isn't called from der_encode_custom_type().
Toy ::= SEQUENCE {
hello UTF8String,
numbers [0] IMPLICIT SET OF Number }
Number ::= INTEGER { zero(0), one(1) }
30 0F
0C 02 68 69
A0 09
02 01 00
02 01 00
02 01 01
When the data type LTC_ASN1_CUSTOM_TYPE represents a primitive ASN.1 data type, the member used indicates the structure of the data member. Maybe that API could work also for a constructed ASN.1 data type, to distinguish SEQUENCE, SET and SET OF.
The function der_encode_set() overwrites the member ltc_asn1_list.used, then passes the list to the function der_encode_sequence_ex(). Maybe der_encode_set() should use the member ltc_asn1_list.optional instead for set ordering.
It wouldn't be a bad idea to modify ltc_asn1_list to use an anonymous union to rename the members used and optional (for decoding) to custom_type and set_order (for encoding).
I just had a look at #624, and it does appear to answer this issue.