gbarr / perl-Convert-ASN1

encode/decode data using ASN.1 description
http://search.cpan.org/dist/Convert-ASN1/
13 stars 21 forks source link

Problems with default EXPLICIT tagging #3

Closed peter-mogensen closed 12 years ago

peter-mogensen commented 12 years ago

Hi,

I can't get Convert::ASN1 to generate the correct DER explicit tagging.

Looking at the example in the DER spec section 8.14.3 it says:

With ASN.1 type definitions (in an explicit tagging environment) of: Type1 ::= VisibleString Type2 ::= [APPLICATION 3] IMPLICIT Type1 Type3 ::= [2] Type2 ... a value of: "Jones" is encoded as follows:

For Type1: VisibleString 1A Length Contents 05 4A6F6E6573

For Type2: [Application 3] 43 Length Contents 05 4A6F6E6573

For Type3: [2] A2 Length 07 Contents [APPLICATION 3] 43 Length Contents 05 4A6F6E6573

...

However. Convert ASN1 encodes the 3 examples as: Type1: 1a 05 4a 6f 6e 65 73 Type2: 43 05 4a 6f 6e 65 73 Type3: 82 05 4a 6f 6e 65 73

Type3 should have been: a2 07 43 05 4a 6f 6e 65 73 ... which Convert::ASN1 will do correctly if the definition of Type3 is changed to: Type3 ::= [2] EXPLICIT Type2

But isn't "EXPLICIT" tagging default?

The problem seems to be due to this statement in parser.y:

plicit : { $$ = undef; } | EXPLICIT { $$ = 1; } | IMPLICIT { $$ = 0; } ;

Where the default tagging gets the undef value, so when there tested for truthness in rules like below it ends up being implicit tagging:

aitem : class plicit anyelem postrb { $3->[cTAG] = $1; $$ = $2 ? explicit($3) : $3; } | celem ;

peter-mogensen commented 12 years ago

Sorry... I actually can't find the place right now where the spec says EXPLICIT tagging is default, but anyway - this is a problem for ASN.1 modules which have declared EXPLICIT tagging default. To get Convert::ASN.1 to output the correct encoding, you'd have to insert EXPLICIT statements in the entire spec.

gbarr commented 12 years ago

Convert::ASN1 is not a complete ASN.1 converter. It has evolved as peoples needs have arisen. Due to this it defaults to an implicit tagging environment.

Currently Convert::ASN1 does not support the module header to declare an explicit tagging environment so it does require that EXPLICIT be placed where required.

X.680 does specify

ModuleDefinition ::=
  ModuleIdentifier
  DEFINITIONS
  EncodingReferenceDefault TagDefault ExtensionDefault
  "::="
  BEGIN
  ModuleBody EncodingControlSections
  END

13.2 The "TagDefault" is taken as EXPLICIT TAGS if it is "empty".

We could add support for the DEFINITIONS header, or at least the TagDefault part, and when we see that default to explicit tags unless TagDefault is given.

The TagDefault would replace the $$ = undef in the plicit rule

peter-mogensen commented 12 years ago

On 2012-05-30 15:22, Graham Barr wrote:

We could add support for the DEFINITIONS header, or at least the TagDefault part, and when we see that default to explicit tags unless TagDefault is given.

The TagDefault would replace the $$ = undef in the plicit rule

Yes - I'm trying to put together a patch which does that. Actually I've just added a config option for default_tagging, which I pass along to the parser. (so it's set at the parser stage and not encoding stage).

It's a simple change, but - unfortunately - it's not enough to simply replace $$=undef in the plicit rule. That will result in correct encoded primitive values, but duplication of a lot of SEQENCEs.

/Peter

gbarr commented 12 years ago

I had a feeling that replacing just $$=undef might not be enough, but it has been a long time since I worked on this.

I look forward to your patch

peter-mogensen commented 12 years ago

I was trying not to change the basic grammar en parser.y, but it seems that a part of the problem is the many places the productions "class plicit" appears. The problem is that and undef plicit should only be resolved as TagDefault if class is also defined. unless I'm mistaken. So it might end up not being a simple patch. :(

gbarr commented 12 years ago

I do not think you can avoid having to modify parser.y, but if you are simply adding a constructor option, then you can probably avoid having to run byacc if you don't have it.

You will need to look for all calls to explicit() in parser.y and predicate them. then make the same changes in lib/Convert/ASN1/parser.pm so you can test. I can run byacc before merging if you cannot get it to work

peter-mogensen commented 12 years ago

Ok... I have a patch to parser.pm which works - at least for my ASN.1 module. I've applied the changes in a more readable way to parser.y and I though I had byacc. At least Debian has a perl-byacc package. However it must be a different version from the one you use. I can't get mkparse to work. Which version of byacc is needed?

gbarr commented 12 years ago

The version line in parser.pm shows

#$yysccsid = "@(#)yaccpar 1.8 (Berkeley) 01/20/91 (Perl 2.0 12/31/92)";

the source is on CPAN at http://www.cpan.org/src/misc/perl-byacc1.8.2.tar.gz

peter-mogensen commented 12 years ago

On 2012-05-30 21:51, Graham Barr wrote:

The version line in parser.pm shows

#$yysccsid = "@(#)yaccpar 1.8 (Berkeley) 01/20/91 (Perl 2.0 12/31/92)";

Ahh ... :) Debian ships 2.0 now. Interface is quite different.

Anyway... I got it working enough to test my patch a bit. I applied the logic to every call to sub explicit() (which all had class/plicit non-terminals in their grammar rule) - except one regaring SET, which I understand always should be EXPLICIT? (I have no SET in my ASN.1 module).

I've let the parser default to EXPLICIT tagging as per ASN.1 spec, but let Convert::ASN1::configure() default to IMPLICIT tagging to be backward compatible.

I've written some tests and doc also. There's some decode tests I can't figure out why is not working. Maybe you have an idea?

Please use the patch as you like or tell me if you have any questions,

/Peter

peter-mogensen commented 12 years ago

Argh... sorry... Forgot to run the old test suite... I messed up the defaulting to IMPLICIT in the parser, so I broke a lot of tests. Fixed now - at least I know now, that defaulting to IMPLICIT is really needed.

Please disregard the old version of the patch.

/Peter

gbarr commented 12 years ago

I have not seen any patch?

Could you push to github and issue a pull request