Commit Graph

47 Commits

Author SHA1 Message Date
Nicolas Williams
fb5ae095e9 asn1: Fix warnings 2021-03-03 10:15:18 -06:00
Nicolas Williams
81195acafa asn1: Further IMPLICIT tagging fixes
Commit 89389bc7a (asn1: Fix long-standing IMPLICIT tagging brokenness)
was incomplete.  Removing the hacks in lib/asn1/cms.asn1 revealed this.

Now the ASN.1 compiler generates enums to indicate what is the class and
tag of each type.  This is needed so the decoder functions generated by
the compiler can know what tag to restore.

Now, too, the compiler does handle IMPLICIT tags whose encoded length is
different from that of the underlying type.

However, we now don't handle indefinite BER and non-DER definite lengths
(DCE) following IMPLICIT tags.  This would affect only CMS in-tree.
2021-01-20 21:04:34 -06:00
Nicolas Williams
89389bc7a0 asn1: Fix long-standing IMPLICIT tagging brokenness
This commit _mostly_ fixes the Heimdal ASN.1 compiler to properly
support IMPLICIT tagging in most if not all the many cases where it
didn't already, as you could see in lib/asn1/canthandle.asn1 prior to
this commit.

This fix is a bit of a hack in that a proper fix would change the
function prototypes of the encode/decode/length functions generated by
the compiler to take an optional IMPLICIT tag to tag with instead of the
type they code.  That fix would not be localized to lib/asn1/ however,
and would change the API and ABI of generated code (which is mostly not
an ABI for Heimdal, but still, some external projects would have to make
changes).

Instead, for IMPLICIT tags we currently depend on the IMPLICIT tag and
the sub-type's tag having the same size -- this can be fixed with extra
allocation on the encoder side as we do on the decoder side, but we
might leave it for later.

The issue we're fixing manifested as:

  -- The [CONTEXT 0] tag in Bar below was turned into an EXPLICIT tag
  -- instead of an IMPLICIT one, netting the DER encoding for the `foo`
  -- member as:
  --    [CONTEXT 0] [UNIVERSAL Seq] [UNIVERSAL Int] <encoding of i>
  -- instead of the correct:
  --    [CONTEXT 0] [UNIVERSAL Int] <encoding of i>
  Foo ::= SEQUENCE { i INTEGER }
  Bar ::= SEQUENCE { foo [0] IMPLICIT Foo }

or

  Foo ::= INTEGER
  Bar ::= SEQUENCE { foo [0] IMPLICIT Foo } -- tag context 0 marked
                                            -- constructed!

I've reviewed this in part by reviewing the output of the compiler
before and after this change using this procedure:

 - Run an earlier version of the ASN.1 compiler output for all
   modules in lib/asn1/.  Save these in a different location.

 - Run this (or later) version of the ASN.1 compiler output for
   the same modules, adding --original-order for modules that
   have been manually sorted already (e.g., rfc2459.asn1).

 - Run clang-format on the saved and newest generated C source
   and header files.

 - Diff the generated output.  Substantial differences will
   relate to handling of IMPLICIT tagging.  These are
   particularly evident in the tcg.asn1 module, which uses a lot
   of those.

Later commits add test data (certificates with extensions that use
IMPLICIT tagging) taken from external specifications as well, which
exercise this fix.

Non-urgent brokenness yet to be fixed:

 - When the IMPLICIT tag and the tag of the underlying type require
   differing numbers of bytes to encode, the encoding and decoding will
   fail.  The prototypes of generated length_*() functions make it
   impossible to do much better.

 - SET OF <primitive> still crashes the compiler (not a new bug).

Futures:

 - Unwind hackery in cms.asn1 that worked around our lack of proper
   IMPLICIT tagging support.

Here are some of the generated code deltas one expects to see around
this commit:

$ git checkout $earlier_version
$ ./autogen.sh
$ mkdir build
$ cd build
$ ../configure ...
$ make -j4
$ make check
$ cd lib/asn1
$ for i in *.c; do
      [[ $i = asn1parse.? || $i = lex.? || $i = *.h ]] && continue
      clang-format -i $i $i
      cmp /tmp/save/$i $i && echo NO DIFFS: $i && continue; echo DIFF: $i
  done
NO DIFFS: asn1_cms_asn1.c
NO DIFFS: asn1_digest_asn1.c
NO DIFFS: asn1_err.c
NO DIFFS: asn1_krb5_asn1.c
/tmp/save/asn1_kx509_asn1.c asn1_kx509_asn1.c differ: byte 6433, line 264
DIFF: asn1_kx509_asn1.c
NO DIFFS: asn1_ocsp_asn1.c
NO DIFFS: asn1_pkcs10_asn1.c
/tmp/save/asn1_pkcs12_asn1.c asn1_pkcs12_asn1.c differ: byte 12934, line 455
DIFF: asn1_pkcs12_asn1.c
NO DIFFS: asn1_pkcs8_asn1.c
NO DIFFS: asn1_pkcs9_asn1.c
NO DIFFS: asn1_pkinit_asn1.c
/tmp/save/asn1_rfc2459_asn1.c asn1_rfc2459_asn1.c differ: byte 20193, line 532
DIFF: asn1_rfc2459_asn1.c
NO DIFFS: asn1_rfc4043_asn1.c
/tmp/save/asn1_rfc4108_asn1.c asn1_rfc4108_asn1.c differ: byte 595, line 26
DIFF: asn1_rfc4108_asn1.c
/tmp/save/asn1_tcg_asn1.c asn1_tcg_asn1.c differ: byte 31835, line 1229
DIFF: asn1_tcg_asn1.c
/tmp/save/asn1_test_asn1.c asn1_test_asn1.c differ: byte 384, line 21
DIFF: asn1_test_asn1.c
/tmp/save/test_template_asn1-template.c test_template_asn1-template.c differ: byte 650, line 20
DIFF: test_template_asn1-template.c
$
$ cd ../..
$ git checkout $newer_version
$ make -j4 && make check
$ cd lib/asn1
$ for i in *.[ch]; do
    [[ $i = asn1parse.? || $i = lex.? || $i = *.h ]] && continue
    clang-format -i $i $i
    cmp /tmp/save/$i $i && echo NO DIFFS: $i && continue
    diff -ubw /tmp/save/$i $i
  done | $PAGER

and one should see deltas such as the following:

 - a small enhancement to handling of OPTIONAL members:

     (data)->macData = calloc(1, sizeof(*(data)->macData));
     if ((data)->macData == NULL)
       goto fail;
     e = decode_PKCS12_MacData(p, len, (data)->macData, &l);
-    if (e) {
+    if (e == ASN1_MISSING_FIELD) {
       free((data)->macData);
       (data)->macData = NULL;
+    } else if (e) {
+      goto fail;
     } else {
       p += l;
       len -= l;
       ret += l;

 - more complete handling of DEFAULTed members:

     e = decode_FWReceiptVersion(p, len, &(data)->version, &l);
-    if (e)
+    if (e == ASN1_MISSING_FIELD) {
+      (data)->version = 1;
+    } else if (e) {
       goto fail;
-    p += l;
-    len -= l;
-    ret += l;
+    } else {
+      p += l;
+      len -= l;
+      ret += l;
+    }
     {

 - replacement of tags with implicit tags (encode side):

   /* targetUri */
   if ((data)->targetUri) {
     size_t Top_tag_oldret HEIMDAL_UNUSED_ATTRIBUTE = ret;
     ret = 0;
     e = encode_URIReference(p, len, (data)->targetUri, &l);
     if (e)
       return e;
     p -= l;
     len -= l;
     ret += l;

-    e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, PRIM, 4, &l);
+    e = der_replace_tag(p, len, ASN1_C_CONTEXT, CONS, 4);
     if (e)
       return e;
     p -= l;
     len -= l;
     ret += l;

     ret += Top_tag_oldret;
   }

 - replacement of tags with implicit tags (decode side):

         strengthOfFunction_oldlen = len;
         if (strengthOfFunction_datalen > len) {
           e = ASN1_OVERRUN;
           goto fail;
         }
         len = strengthOfFunction_datalen;
-        e = decode_StrengthOfFunction(p, len, (data)->strengthOfFunction, &l);
-        if (e)
-          goto fail;
-        p += l;
-        len -= l;
-        ret += l;
+        {
+          unsigned char *pcopy;
+          pcopy = calloc(1, len);
+          if (pcopy == 0) {
+            e = ENOMEM;
+            goto fail;
+          }
+          memcpy(pcopy, p, len);
+          e = der_replace_tag(pcopy, len, ASN1_C_UNIV, PRIM, 0);
+          if (e)
+            goto fail;
+          e = decode_StrengthOfFunction(p, len, (data)->strengthOfFunction, &l);
+          if (e)
+            goto fail;
+          p += l;
+          len -= l;
+          ret += l;
+          free(pcopy);
+        }
         len = strengthOfFunction_oldlen - strengthOfFunction_datalen;
       }
     }
     {
       size_t profileOid_datalen, profileOid_oldlen;

 - correct determination of implicit tag constructed vs no for IMPLICT-
   tagged named primitive types:

     {
       size_t profileUri_datalen, profileUri_oldlen;
       Der_type profileUri_type;
       e = der_match_tag_and_length(p, len, ASN1_C_CONTEXT, &profileUri_type, 2,
                                    &profileUri_datalen, &l);
-      if (e == 0 && profileUri_type != PRIM) {
+      if (e == 0 && profileUri_type != CONS) {
         e = ASN1_BAD_ID;
       }
       if (e) {
         (data)->profileUri = NULL;
       } else {
         (data)->profileUri = calloc(1, sizeof(*(data)->profileUri));
         if ((data)->profileUri == NULL) {
           e = ENOMEM;
           goto fail;
         }

 - correct determination of length of IMPLICT-tagged OIDs:

   if ((data)->profileOid) {
     size_t Top_tag_oldret = ret;
     ret = 0;
     ret += der_length_oid((data)->profileOid);
+    ret += 1 + der_length_len(ret);
     ret += Top_tag_oldret;
   }

These deltas should be examined with the corresponding ASN.1 module at
hand, cross-referencing the source code to the ASN.1 type definitions
and manually applying X.690 rules to double-check the choices of
primitive vs. constructed tag, and the choices of when to replace tags
and when not.
2021-01-13 20:17:58 -06:00
Nicolas Williams
1c81ddf4e2 Round #2 of scan-build warnings cleanup 2016-11-16 17:03:14 -06:00
Love Hornquist Astrand
060474df16 quel 64bit warnings, fixup implicit encoding for template, fix spelling 2013-06-03 21:46:20 -07:00
Nicolas Williams
19d378f44d Add 64-bit integer support to ASN.1 compiler
ASN.1 INTEGERs will now compile to C int64_t or uint64_t, depending
    on whether the constraint ranges include numbers that cannot be
    represented in 32-bit ints and whether they include negative
    numbers.

    Template backend support included.  check-template is now built with
    --template, so we know we're testing it.

    Tests included.
2011-12-12 20:01:20 -06:00
Love Hornquist Astrand
b507bdb54f if _der_gmtime() failes (which is can't right now but eventially will) return ASN1_BAD_TIMEFORMAT 2011-04-23 19:42:02 -07:00
Love Hornquist Astrand
5fc132d888 add _der_gmtime, use and test it 2010-09-29 13:32:39 -07:00
Love Hornquist Astrand
fa4c84e6d6 make printablestring and ia5string octetstrings 2010-08-08 15:51:33 -07:00
Love Hornquist Astrand
9b710bed81 store is never read again 2009-07-29 22:37:58 +02:00
Love Hörnquist Åstrand
0e6b5c5c22 remove trailing whitespace
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@25232 ec53bebd-3082-4978-b11e-865c3cabbd6b
2009-05-28 01:17:17 +00:00
Love Hörnquist Åstrand
6937d41a02 remove trailing whitespace
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@23815 ec53bebd-3082-4978-b11e-865c3cabbd6b
2008-09-13 09:21:03 +00:00
Love Hörnquist Åstrand
e172367898 switch to utf8 encoding of all files
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@23814 ec53bebd-3082-4978-b11e-865c3cabbd6b
2008-09-13 08:53:55 +00:00
Love Hörnquist Åstrand
983b89b811 Add VisibleString parsing
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@19539 ec53bebd-3082-4978-b11e-865c3cabbd6b
2006-12-28 17:15:05 +00:00
Love Hörnquist Åstrand
b838707d0e Commit much improved ASN.1 compiler from joda-choice-branch.
Highlighs for the compiler is support for CHOICE and in general better
support for tags. This compiler support most of what is needed for
PK-INIT, LDAP, X.509, PKCS-12 and many other protocols.


git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@15617 ec53bebd-3082-4978-b11e-865c3cabbd6b
2005-07-12 06:27:42 +00:00
Love Hörnquist Åstrand
8e78ed6e48 prefix Der_class with ASN1_C_ to avoid problems with system headerfiles that pollute the name space
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@15255 ec53bebd-3082-4978-b11e-865c3cabbd6b
2005-05-29 14:23:01 +00:00
Love Hörnquist Åstrand
8b8bcb8c9b add boolan support
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@12944 ec53bebd-3082-4978-b11e-865c3cabbd6b
2003-10-03 00:28:29 +00:00
Love Hörnquist Åstrand
939b444ca3 prefix typedef\'s and structs with heim_
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@12438 ec53bebd-3082-4978-b11e-865c3cabbd6b
2003-07-15 13:57:32 +00:00
Johan Danielsson
5ce268bf83 Fix encoding of "unsigned" integers. If MSB is set, we need to pad
with a zero byte.


git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@12337 ec53bebd-3082-4978-b11e-865c3cabbd6b
2003-05-27 21:59:52 +00:00
Love Hörnquist Åstrand
bdef0a4d2b remove sprintf
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@12086 ec53bebd-3082-4978-b11e-865c3cabbd6b
2003-04-17 07:12:24 +00:00
Assar Westerlund
f0f9087c01 make comment reality-compliant
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@10744 ec53bebd-3082-4978-b11e-865c3cabbd6b
2001-09-25 23:37:25 +00:00
Assar Westerlund
2bcae56ac3 add ENUMERATED and OBJECT IDENTIFIER
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@10741 ec53bebd-3082-4978-b11e-865c3cabbd6b
2001-09-25 13:39:27 +00:00
Assar Westerlund
f5c990600c (der_put_length): do not even try writing anything when len == 1
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@10730 ec53bebd-3082-4978-b11e-865c3cabbd6b
2001-09-20 09:15:27 +00:00
Assar Westerlund
9fcb1a0934 make time2generalizedtime return an error code
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@9576 ec53bebd-3082-4978-b11e-865c3cabbd6b
2001-01-29 08:31:27 +00:00
Assar Westerlund
33a90723e0 (encode_unsigned): add
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@8128 ec53bebd-3082-4978-b11e-865c3cabbd6b
2000-04-06 17:20:55 +00:00
Johan Danielsson
c5b916ca6f remove advertising clause
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@7464 ec53bebd-3082-4978-b11e-865c3cabbd6b
1999-12-02 17:05:13 +00:00
Assar Westerlund
a74d27d3d7 const-ize
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@7130 ec53bebd-3082-4978-b11e-865c3cabbd6b
1999-10-10 04:55:28 +00:00
Assar Westerlund
fe897df66a simplify by using der_put_length_and_tag
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@7054 ec53bebd-3082-4978-b11e-865c3cabbd6b
1999-09-28 03:08:24 +00:00
Johan Danielsson
7ccd6d79cc (encode_generalized_time): encode length
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@7038 ec53bebd-3082-4978-b11e-865c3cabbd6b
1999-09-27 15:57:56 +00:00
Assar Westerlund
01959cb376 make functions more consistent
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@6994 ec53bebd-3082-4978-b11e-865c3cabbd6b
1999-09-20 22:37:43 +00:00
Johan Danielsson
3fb7ea421c typo
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@5425 ec53bebd-3082-4978-b11e-865c3cabbd6b
1999-02-26 16:37:08 +00:00
Johan Danielsson
044e371dae fix der_put_int
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@5419 ec53bebd-3082-4978-b11e-865c3cabbd6b
1999-02-25 10:05:20 +00:00
Assar Westerlund
65ffbd5e29 (der_put_unsigned): new function
(der_put_int): handle signed integers


git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@5348 ec53bebd-3082-4978-b11e-865c3cabbd6b
1999-02-13 16:14:53 +00:00
Johan Danielsson
5a32a5c8e7 Add copyright notice.
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@2389 ec53bebd-3082-4978-b11e-865c3cabbd6b
1997-07-16 21:40:05 +00:00
Assar Westerlund
c1439d2cd8 changed asn1_locl.h to gen_locl.h and der_locl.h
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@2328 ec53bebd-3082-4978-b11e-865c3cabbd6b
1997-07-15 20:02:05 +00:00
Johan Danielsson
42241b0dcf Return size in correct manner.
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@1954 ec53bebd-3082-4978-b11e-865c3cabbd6b
1997-07-02 15:47:56 +00:00
Johan Danielsson
372881f5ef Now all decode_* and encode_* functions now take a final size_t*
argument, that they return the size in. Return values are zero for
success, and anything else (such as some ASN1_* constant) for error.


git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@1951 ec53bebd-3082-4978-b11e-865c3cabbd6b
1997-07-01 23:52:30 +00:00
Johan Danielsson
f13518ca8f krb5_data -> octet_string, char * -> general_string
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@1873 ec53bebd-3082-4978-b11e-865c3cabbd6b
1997-06-09 22:43:04 +00:00
Johan Danielsson
555cd16dd1 Move fix_dce to der_get (where is belongs).
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@1451 ec53bebd-3082-4978-b11e-865c3cabbd6b
1997-03-17 10:38:56 +00:00
Johan Danielsson
1caf3885e6 Fix include files. Add fix_dce().
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@1450 ec53bebd-3082-4978-b11e-865c3cabbd6b
1997-03-17 10:37:01 +00:00
Assar Westerlund
6c103aa107 time2generalizedtime is used in der_length
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@1412 ec53bebd-3082-4978-b11e-865c3cabbd6b
1997-03-14 03:15:49 +00:00
Assar Westerlund
619ad4a702 (der_put_length_and_tag): new function
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@1346 ec53bebd-3082-4978-b11e-865c3cabbd6b
1997-03-10 00:43:55 +00:00
Assar Westerlund
78ca419366 correct types
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@1337 ec53bebd-3082-4978-b11e-865c3cabbd6b
1997-03-09 21:30:53 +00:00
Assar Westerlund
e814ab807a A DER integer should really be a `unsigned'
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@1227 ec53bebd-3082-4978-b11e-865c3cabbd6b
1997-02-11 02:54:45 +00:00
Johan Danielsson
fad81ed299 Lots of random changes.
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@1107 ec53bebd-3082-4978-b11e-865c3cabbd6b
1996-12-15 21:30:34 +00:00
Johan Danielsson
dbdb412ba0 Ugh
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@864 ec53bebd-3082-4978-b11e-865c3cabbd6b
1996-10-20 16:47:54 +00:00
Assar Westerlund
b55aed018f Now uses generated ASN1-code.
kinit should be able to get a initial message from FOO.SE.


git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@844 ec53bebd-3082-4978-b11e-865c3cabbd6b
1996-10-13 21:13:38 +00:00