summaryrefslogtreecommitdiff
path: root/scripts/asn1_compiler.c
AgeCommit message (Collapse)Author
2015-08-07ASN.1: Copy string names to tokens in ASN.1 compilerDavid Howells
Copy string names to tokens in ASN.1 compiler rather than storing a pointer into the source text. This means we don't have to use "%*.*s" all over the place. Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: David Woodhouse <David.Woodhouse@intel.com>
2015-08-07ASN.1: Add an ASN.1 compiler option to dump the element treeDavid Howells
Add an ASN.1 compiler option to dump the element tree to stdout. Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-By: David Woodhouse <David.Woodhouse@intel.com>
2015-08-05ASN.1: Handle 'ANY OPTIONAL' in grammarDavid Howells
An ANY object in an ASN.1 grammar that is marked OPTIONAL should be skipped if there is no more data to be had. This can be tested by editing X.509 certificates or PKCS#7 messages to remove the NULL from subobjects that look like the following: SEQUENCE { OBJECT(2a864886f70d01010b); NULL(); } This is an algorithm identifier plus an optional parameter. The modified DER can be passed to one of: keyctl padd asymmetric "" @s </tmp/modified.x509 keyctl padd pkcs7_test foo @s </tmp/modified.pkcs7 It should work okay with the patch and produce EBADMSG without. Signed-off-by: David Howells <dhowells@redhat.com> Tested-by: Marcel Holtmann <marcel@holtmann.org> Reviewed-by: David Woodhouse <David.Woodhouse@intel.com>
2015-08-05ASN.1: Fix actions on CHOICE elements with IMPLICIT tagsDavid Howells
In an ASN.1 description where there is a CHOICE construct that contains elements with IMPLICIT tags that refer to constructed types, actions to be taken on those elements should be conditional on the corresponding element actually being matched. Currently, however, such actions are performed unconditionally in the middle of processing the CHOICE. For example, look at elements 'b' and 'e' here: A ::= SEQUENCE { CHOICE { b [0] IMPLICIT B ({ do_XXXXXXXXXXXX_b }), c [1] EXPLICIT C ({ do_XXXXXXXXXXXX_c }), d [2] EXPLICIT B ({ do_XXXXXXXXXXXX_d }), e [3] IMPLICIT C ({ do_XXXXXXXXXXXX_e }), f [4] IMPLICIT INTEGER ({ do_XXXXXXXXXXXX_f }) } } ({ do_XXXXXXXXXXXX_A }) B ::= SET OF OBJECT IDENTIFIER ({ do_XXXXXXXXXXXX_oid }) C ::= SET OF INTEGER ({ do_XXXXXXXXXXXX_int }) They each have an action (do_XXXXXXXXXXXX_b and do_XXXXXXXXXXXX_e) that should only be processed if that element is matched. The problem is that there's no easy place to hang the action off in the subclause (type B for element 'b' and type C for element 'e') because subclause opcode sequences can be shared. To fix this, introduce a conditional action opcode(ASN1_OP_MAYBE_ACT) that the decoder only processes if the preceding match was successful. This can be seen in an excerpt from the output of the fixed ASN.1 compiler for the above ASN.1 description: [ 13] = ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // e [ 14] = _tagn(CONT, CONS, 3), [ 15] = _jump_target(45), // --> C [ 16] = ASN1_OP_MAYBE_ACT, [ 17] = _action(ACT_do_XXXXXXXXXXXX_e), In this, if the op at [13] is matched (ie. element 'e' above) then the action at [16] will be performed. However, if the op at [13] doesn't match or is skipped because it is conditional and some previous op matched, then the action at [16] will be ignored. Note that to make this work in the decoder, the ASN1_OP_RETURN op must set the flag to indicate that a match happened. This is necessary because the _jump_target() seen above introduces a subclause (in this case an object of type 'C') which is likely to alter the flag. Setting the flag here is okay because to process a subclause, a match must have happened and caused a jump. This cannot be tested with the code as it stands, but rather affects future code. Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: David Woodhouse <David.Woodhouse@intel.com>
2015-08-05ASN.1: Fix handling of CHOICE in ASN.1 compilerDavid Howells
Fix the handling of CHOICE types in the ASN.1 compiler to make SEQUENCE and SET elements in a CHOICE be correctly rendered as skippable and conditional as appropriate. For example, in the following ASN.1: Foo ::= SEQUENCE { w1 INTEGER, w2 Bar, w3 OBJECT IDENTIFIER } Bar ::= CHOICE { x1 Seq1, x2 [0] IMPLICIT OCTET STRING, x3 Seq2, x4 SET OF INTEGER } Seq1 ::= SEQUENCE { y1 INTEGER, y2 INTEGER, y3 INTEGER } Seq2 ::= SEQUENCE { z1 BOOLEAN, z2 BOOLEAN, z3 BOOLEAN } the output in foo.c generated by: ./scripts/asn1_compiler foo.asn1 foo.c foo.h included: // Bar // Seq1 [ 4] = ASN1_OP_MATCH, [ 5] = _tag(UNIV, CONS, SEQ), ... [ 13] = ASN1_OP_COND_MATCH_OR_SKIP, // x2 [ 14] = _tagn(CONT, PRIM, 0), // Seq2 [ 15] = ASN1_OP_MATCH, [ 16] = _tag(UNIV, CONS, SEQ), ... [ 24] = ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // x4 [ 25] = _tag(UNIV, CONS, SET), ... [ 27] = ASN1_OP_COND_FAIL, as a result of the CHOICE - but this is wrong on lines 4 and 15 because both of these should be skippable (one and only one of the four can be picked) and the one on line 15 should also be conditional so that it is ignored if anything before it matches. After the patch, it looks like: // Bar // Seq1 [ 4] = ASN1_OP_MATCH_JUMP_OR_SKIP, // x1 [ 5] = _tag(UNIV, CONS, SEQ), ... [ 7] = ASN1_OP_COND_MATCH_OR_SKIP, // x2 [ 8] = _tagn(CONT, PRIM, 0), // Seq2 [ 9] = ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // x3 [ 10] = _tag(UNIV, CONS, SEQ), ... [ 12] = ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // x4 [ 13] = _tag(UNIV, CONS, SET), ... [ 15] = ASN1_OP_COND_FAIL, where all four options are skippable and the second, third and fourth are all conditional, as is the backstop at the end. This hasn't been a problem so far because in the ASN.1 specs we have are either using primitives or are using SET OF and SEQUENCE OF which are handled correctly. Whilst we're at it, also make sure that element labels get included in comments in the output for elements that have complex types. This cannot be tested with the code as it stands, but rather affects future code. Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-By: David Woodhouse <David.Woodhouse@intel.com>
2015-01-23X.509: silence asn1 compiler debug outputArnd Bergmann
The asn1_compiler process is particularly chatty and produces about the only stdout output for an allmodconfig kernel. In order to follow the general concept of 'no news is good news' for building kernels, this hides all the existing output unless the KBUILD_VERBOSE environment variable is set. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: David Howells <dhowells@redhat.com>
2013-09-25X.509: remove possible code fragility: enumeration values not handledAntonio Alecrim Jr
Signed-off-by: Antonio Alecrim Jr <antonio.alecrim@gmail.com> Signed-off-by: David Howells <dhowells@redhat.com>
2012-10-08X.509: Add simple ASN.1 grammar compilerDavid Howells
Add a simple ASN.1 grammar compiler. This produces a bytecode output that can be fed to a decoder to inform the decoder how to interpret the ASN.1 stream it is trying to parse. Action functions can be specified in the grammar by interpolating: ({ foo }) after a type, for example: SubjectPublicKeyInfo ::= SEQUENCE { algorithm AlgorithmIdentifier, subjectPublicKey BIT STRING ({ do_key_data }) } The decoder is expected to call these after matching this type and parsing the contents if it is a constructed type. The grammar compiler does not currently support the SET type (though it does support SET OF) as I can't see a good way of tracking which members have been encountered yet without using up extra stack space. Currently, the grammar compiler will fail if more than 256 bytes of bytecode would be produced or more than 256 actions have been specified as it uses 8-bit jump values and action indices to keep space usage down. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>