git: 1b7487592987 - main - heimdal: Add 64-bit integer support to ASN.1 compiler

From: Dimitry Andric <dim_at_FreeBSD.org>
Date: Wed, 17 Apr 2024 17:00:16 UTC
The branch main has been updated by dim:

URL: https://cgit.FreeBSD.org/src/commit/?id=1b7487592987c91020063a311a14dc15b6e58075

commit 1b7487592987c91020063a311a14dc15b6e58075
Author:     Dimitry Andric <dim@FreeBSD.org>
AuthorDate: 2024-04-16 18:56:37 +0000
Commit:     Dimitry Andric <dim@FreeBSD.org>
CommitDate: 2024-04-17 16:12:43 +0000

    heimdal: Add 64-bit integer support to ASN.1 compiler
    
    Import upstream 19d378f44:
    
      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.
    
    Also adjusts the generated files:
    * asn1parse.c, asn1parse.h (not strictly necessary, but nice to have)
    * der-protos.h, which needs a bunch of new prototypes. I copied these
      from a der-protos.h generated by the upstream build system, which
      uses a perl script for this.
    * adjust printf format strings for int64_t. Upstream uses %lld for this,
      but that is not portable, and leads to lots of -Werror warnings.
    
    This should fix target-dependent differences between headers generated
    by asn1_compile. For example, when cross compiling world from amd64 to
    i386, the generated cms_asn1.h header has:
    
      CMSRC2CBCParameter ::= SEQUENCE {
        rc2ParameterVersion   INTEGER (0..-1),
        iv                    OCTET STRING,
      }
    
    while a native build on i386 has:
    
      CMSRC2CBCParameter ::= SEQUENCE {
        rc2ParameterVersion   INTEGER (0..2147483647),
        iv                    OCTET STRING,
      }
    
    These are _both_ wrong, since the source file, cms.asn1, has:
    
      CMSRC2CBCParameter ::= SEQUENCE {
              rc2ParameterVersion   INTEGER (0..4294967295),
              iv                    OCTET STRING -- exactly 8 octets
      }
    
    PR:             276960
    Reviewed by:    cy, emaste
    MFC after:      1 week
    Differential Revision: https://reviews.freebsd.org/D44814
    Differential Revision: https://reviews.freebsd.org/D44815
---
 crypto/heimdal/lib/asn1/Makefile.am     |  12 +++-
 crypto/heimdal/lib/asn1/asn1-template.h |   2 +
 crypto/heimdal/lib/asn1/asn1parse.c     |   6 +-
 crypto/heimdal/lib/asn1/asn1parse.h     |   2 +-
 crypto/heimdal/lib/asn1/asn1parse.y     |   6 +-
 crypto/heimdal/lib/asn1/check-gen.c     | 120 ++++++++++++++++++++++++++++++++
 crypto/heimdal/lib/asn1/der-protos.h    |  50 +++++++++++++
 crypto/heimdal/lib/asn1/der_copy.c      |  14 ++++
 crypto/heimdal/lib/asn1/der_free.c      |  12 ++++
 crypto/heimdal/lib/asn1/der_get.c       |  45 +++++++++++-
 crypto/heimdal/lib/asn1/der_length.c    |  57 +++++++++++++++
 crypto/heimdal/lib/asn1/der_put.c       |  72 +++++++++++++++++++
 crypto/heimdal/lib/asn1/gen.c           |  20 +++---
 crypto/heimdal/lib/asn1/gen_decode.c    |  18 ++---
 crypto/heimdal/lib/asn1/gen_encode.c    |  12 ++--
 crypto/heimdal/lib/asn1/gen_length.c    |  12 ++--
 crypto/heimdal/lib/asn1/gen_template.c  |  22 +++---
 crypto/heimdal/lib/asn1/lex.l           |   2 +-
 crypto/heimdal/lib/asn1/symbol.h        |  10 ++-
 crypto/heimdal/lib/asn1/template.c      |   2 +
 crypto/heimdal/lib/asn1/test.asn1       |   2 +
 21 files changed, 446 insertions(+), 52 deletions(-)

diff --git a/crypto/heimdal/lib/asn1/Makefile.am b/crypto/heimdal/lib/asn1/Makefile.am
index 47158b88aa42..608639aed276 100644
--- a/crypto/heimdal/lib/asn1/Makefile.am
+++ b/crypto/heimdal/lib/asn1/Makefile.am
@@ -37,6 +37,7 @@ gen_files_pkinit = asn1_pkinit_asn1.x
 gen_files_pkcs12 = asn1_pkcs12_asn1.x
 gen_files_pkcs8 = asn1_pkcs8_asn1.x
 gen_files_pkcs9 = asn1_pkcs9_asn1.x
+gen_files_test_template = test_template_asn1-template.c
 gen_files_test = asn1_test_asn1.x
 gen_files_digest = asn1_digest_asn1.x
 gen_files_kx509 = asn1_kx509_asn1.x
@@ -53,7 +54,7 @@ asn1_print_SOURCES = asn1_print.c
 check_der_SOURCES = check-der.c check-common.c check-common.h
 
 check_template_SOURCES = check-template.c check-common.c check-common.h
-nodist_check_template_SOURCES = $(gen_files_test:.x=.c)
+nodist_check_template_SOURCES = $(gen_files_test_template:.x=.c)
 
 dist_check_gen_SOURCES = check-gen.c check-common.c check-common.h
 nodist_check_gen_SOURCES = $(gen_files_test:.x=.c)
@@ -134,6 +135,7 @@ CLEANFILES = \
 	$(gen_files_pkcs12) \
 	$(gen_files_digest) \
 	$(gen_files_kx509) \
+	$(gen_files_test_template) \
 	$(gen_files_test) $(nodist_check_gen_SOURCES) \
 	asn1_err.c asn1_err.h \
 	rfc2459_asn1_files rfc2459_asn1*.h* \
@@ -145,6 +147,7 @@ CLEANFILES = \
 	pkcs12_asn1_files pkcs12_asn1*.h* \
 	digest_asn1_files digest_asn1*.h* \
 	kx509_asn1_files kx509_asn1*.h* \
+	test_template_asn1_files test_template_asn1*.h* \
 	test_asn1_files test_asn1*.h*
 
 dist_include_HEADERS = der.h heim_asn1.h der-protos.h der-private.h
@@ -170,6 +173,7 @@ priv_headers += pkcs9_asn1-priv.h
 priv_headers += pkcs12_asn1-priv.h
 priv_headers += digest_asn1-priv.h
 priv_headers += kx509_asn1-priv.h
+priv_headers += test_template_asn1.h test_template_asn1-priv.h
 priv_headers += test_asn1.h test_asn1-priv.h
 
 
@@ -178,7 +182,7 @@ $(asn1_compile_OBJECTS): asn1parse.h asn1parse.c $(srcdir)/der-protos.h $(srcdir
 $(libasn1_la_OBJECTS): $(nodist_include_HEADERS) $(priv_headers) asn1_err.h $(srcdir)/der-protos.h $(srcdir)/der-private.h
 $(libasn1base_la_OBJECTS): asn1_err.h $(srcdir)/der-protos.h $(srcdir)/der-private.h
 $(check_gen_OBJECTS): test_asn1.h
-$(check_template_OBJECTS): test_asn1_files
+$(check_template_OBJECTS): test_template_asn1.h test_template_asn1_files
 $(asn1_print_OBJECTS): krb5_asn1.h
 
 asn1parse.h: asn1parse.c
@@ -192,6 +196,7 @@ $(gen_files_digest) digest_asn1.hx digest_asn1-priv.hx: digest_asn1_files
 $(gen_files_kx509) kx509_asn1.hx kx509_asn1-priv.hx: kx509_asn1_files
 $(gen_files_rfc2459) rfc2459_asn1.hx rfc2459_asn1-priv.hx: rfc2459_asn1_files
 $(gen_files_cms) cms_asn1.hx cms_asn1-priv.hx: cms_asn1_files
+$(gen_files_test_template) test_template_asn1.hx test_template_asn1-priv.hx: test_template_asn1_files
 $(gen_files_test) test_asn1.hx test_asn1-priv.hx: test_asn1_files
 
 rfc2459_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/rfc2459.asn1
@@ -221,6 +226,9 @@ digest_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/digest.asn1
 kx509_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/kx509.asn1
 	$(ASN1_COMPILE) --one-code-file $(srcdir)/kx509.asn1 kx509_asn1 || (rm -f kx509_asn1_files ; exit 1)
 
+test_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/test.asn1
+	$(ASN1_COMPILE) --template --sequence=TESTSeqOf $(srcdir)/test.asn1 test_template_asn1 || (rm -f test_template_asn1_files ; exit 1)
+
 test_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/test.asn1
 	$(ASN1_COMPILE) --one-code-file --sequence=TESTSeqOf $(srcdir)/test.asn1 test_asn1 || (rm -f test_asn1_files ; exit 1)
 
diff --git a/crypto/heimdal/lib/asn1/asn1-template.h b/crypto/heimdal/lib/asn1/asn1-template.h
index 107706ce8340..5fd6b812630f 100644
--- a/crypto/heimdal/lib/asn1/asn1-template.h
+++ b/crypto/heimdal/lib/asn1/asn1-template.h
@@ -118,7 +118,9 @@ enum template_types {
     A1T_IMEMBER = 0,
     A1T_HEIM_INTEGER,
     A1T_INTEGER,
+    A1T_INTEGER64,
     A1T_UNSIGNED,
+    A1T_UNSIGNED64,
     A1T_GENERAL_STRING,
     A1T_OCTET_STRING,
     A1T_OCTET_STRING_BER,
diff --git a/crypto/heimdal/lib/asn1/asn1parse.c b/crypto/heimdal/lib/asn1/asn1parse.c
index 0e04fabf6296..a305f4b0267b 100644
--- a/crypto/heimdal/lib/asn1/asn1parse.c
+++ b/crypto/heimdal/lib/asn1/asn1parse.c
@@ -304,7 +304,7 @@ struct string_list {
 typedef union YYSTYPE
 #line 71 "asn1parse.y"
 {
-    int constant;
+    int64_t constant;
     struct value *value;
     struct range *range;
     char *name;
@@ -1874,7 +1874,7 @@ yyreduce:
 			lex_error_message("Non-integer in first part of range");
 		    (yyval.range) = ecalloc(1, sizeof(*(yyval.range)));
 		    (yyval.range)->min = (yyvsp[(2) - (5)].value)->u.integervalue;
-		    (yyval.range)->max = (yyvsp[(2) - (5)].value)->u.integervalue - 1;
+		    (yyval.range)->max = INT_MAX;
 		}
     break;
 
@@ -1884,7 +1884,7 @@ yyreduce:
 		    if((yyvsp[(4) - (5)].value)->type != integervalue)
 			lex_error_message("Non-integer in second part of range");
 		    (yyval.range) = ecalloc(1, sizeof(*(yyval.range)));
-		    (yyval.range)->min = (yyvsp[(4) - (5)].value)->u.integervalue + 2;
+		    (yyval.range)->min = INT_MIN;
 		    (yyval.range)->max = (yyvsp[(4) - (5)].value)->u.integervalue;
 		}
     break;
diff --git a/crypto/heimdal/lib/asn1/asn1parse.h b/crypto/heimdal/lib/asn1/asn1parse.h
index 69b7d6dc1a4a..c1ced1df5a44 100644
--- a/crypto/heimdal/lib/asn1/asn1parse.h
+++ b/crypto/heimdal/lib/asn1/asn1parse.h
@@ -224,7 +224,7 @@
 typedef union YYSTYPE
 #line 71 "asn1parse.y"
 {
-    int constant;
+    int64_t constant;
     struct value *value;
     struct range *range;
     char *name;
diff --git a/crypto/heimdal/lib/asn1/asn1parse.y b/crypto/heimdal/lib/asn1/asn1parse.y
index e3bea6ce0ac9..b419676d3429 100644
--- a/crypto/heimdal/lib/asn1/asn1parse.y
+++ b/crypto/heimdal/lib/asn1/asn1parse.y
@@ -69,7 +69,7 @@ struct string_list {
 %}
 
 %union {
-    int constant;
+    int64_t constant;
     struct value *value;
     struct range *range;
     char *name;
@@ -370,14 +370,14 @@ range		: '(' Value RANGE Value ')'
 			lex_error_message("Non-integer in first part of range");
 		    $$ = ecalloc(1, sizeof(*$$));
 		    $$->min = $2->u.integervalue;
-		    $$->max = $2->u.integervalue - 1;
+		    $$->max = INT_MAX;
 		}
 		| '(' kw_MIN RANGE Value ')'
 		{
 		    if($4->type != integervalue)
 			lex_error_message("Non-integer in second part of range");
 		    $$ = ecalloc(1, sizeof(*$$));
-		    $$->min = $4->u.integervalue + 2;
+		    $$->min = INT_MIN;
 		    $$->max = $4->u.integervalue;
 		}
 		| '(' Value ')'
diff --git a/crypto/heimdal/lib/asn1/check-gen.c b/crypto/heimdal/lib/asn1/check-gen.c
index e686f166cfa0..44699cab4356 100644
--- a/crypto/heimdal/lib/asn1/check-gen.c
+++ b/crypto/heimdal/lib/asn1/check-gen.c
@@ -764,6 +764,124 @@ check_tag_length(void)
     return failed;
 }
 
+static int
+check_tag_length64(void)
+{
+    struct test_data td[] = {
+	{ 1, 3, 3, "\x02\x01\x00"},
+	{ 1, 7, 7, "\x02\x05\x01\xff\xff\xff\xff"},
+	{ 1, 7, 7, "\x02\x05\x02\x00\x00\x00\x00"},
+	{ 1, 9, 9, "\x02\x07\x7f\xff\xff\xff\xff\xff\xff"},
+	{ 1, 10, 10, "\x02\x08\x00\x80\x00\x00\x00\x00\x00\x00"},
+	{ 1, 10, 10, "\x02\x08\x7f\xff\xff\xff\xff\xff\xff\xff"},
+	{ 1, 11, 11, "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff"},
+	{ 0, 3, 0, "\x02\x02\x00"},
+	{ 0, 3, 0, "\x02\x7f\x7f"},
+	{ 0, 4, 0, "\x02\x03\x00\x80"},
+	{ 0, 4, 0, "\x02\x7f\x01\x00"},
+	{ 0, 5, 0, "\x02\xff\x7f\x02\x00"}
+    };
+    size_t sz;
+    TESTuint64 values[] = {0, 8589934591LL, 8589934592LL,
+			   36028797018963967LL, 36028797018963968LL,
+			   9223372036854775807LL, 18446744073709551615ULL,
+			   0, 127, 128, 256, 512 };
+    TESTuint64 u;
+    int i, ret, failed = 0;
+    void *buf;
+
+    for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) {
+	struct map_page *page;
+
+	buf = map_alloc(OVERRUN, td[i].data, td[i].len, &page);
+
+	ret = decode_TESTuint64(buf, td[i].len, &u, &sz);
+	if (ret) {
+	    if (td[i].ok) {
+		printf("failed with tag len test %d\n", i);
+		printf("ret = %d\n", ret);
+		failed = 1;
+	    }
+	} else {
+	    if (td[i].ok == 0) {
+		printf("failed with success for tag len test %d\n", i);
+		failed = 1;
+	    }
+	    if (td[i].expected_len != sz) {
+		printf("wrong expected size for tag test %d\n", i);
+		printf("sz = %d\n", sz);
+		failed = 1;
+	    }
+	    if (values[i] != u) {
+		printf("wrong value for tag test %d\n", i);
+		printf("Expected value: %lld\nActual value: %lld\n", values[i], u);
+		failed = 1;
+	    }
+	}
+	map_free(page, "test", "decode");
+    }
+    return failed;
+}
+
+static int
+check_tag_length64s(void)
+{
+    struct test_data td[] = {
+	{ 1, 3, 3, "\x02\x01\x00"},
+	{ 1, 7, 7, "\x02\x05\xfe\x00\x00\x00\x01"},
+	{ 1, 7, 7, "\x02\x05\xfe\x00\x00\x00\x00"},
+	{ 1, 9, 9, "\x02\x07\x80\x00\x00\x00\x00\x00\x01"},
+	{ 1, 9, 9, "\x02\x07\x80\x00\x00\x00\x00\x00\x00"},
+	{ 1, 10, 10, "\x02\x08\x80\x00\x00\x00\x00\x00\x00\x01"},
+	{ 1, 9, 9, "\x02\x07\x80\x00\x00\x00\x00\x00\x01"},
+	{ 0, 3, 0, "\x02\x02\x00"},
+	{ 0, 3, 0, "\x02\x7f\x7f"},
+	{ 0, 4, 0, "\x02\x03\x00\x80"},
+	{ 0, 4, 0, "\x02\x7f\x01\x00"},
+	{ 0, 5, 0, "\x02\xff\x7f\x02\x00"}
+    };
+    size_t sz;
+    TESTint64 values[] = {0, -8589934591LL, -8589934592LL,
+			   -36028797018963967LL, -36028797018963968LL,
+			   -9223372036854775807LL, -36028797018963967LL,
+			   0, 127, 128, 256, 512 };
+    TESTint64 u;
+    int i, ret, failed = 0;
+    void *buf;
+
+    for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) {
+	struct map_page *page;
+
+	buf = map_alloc(OVERRUN, td[i].data, td[i].len, &page);
+
+	ret = decode_TESTint64(buf, td[i].len, &u, &sz);
+	if (ret) {
+	    if (td[i].ok) {
+		printf("failed with tag len test %d\n", i);
+		printf("ret = %d\n", ret);
+		failed = 1;
+	    }
+	} else {
+	    if (td[i].ok == 0) {
+		printf("failed with success for tag len test %d\n", i);
+		failed = 1;
+	    }
+	    if (td[i].expected_len != sz) {
+		printf("wrong expected size for tag test %d\n", i);
+		printf("sz = %d\n", sz);
+		failed = 1;
+	    }
+	    if (values[i] != u) {
+		printf("wrong value for tag test %d\n", i);
+		printf("Expected value: %lld\nActual value: %lld\n", values[i], u);
+		failed = 1;
+	    }
+	}
+	map_free(page, "test", "decode");
+    }
+    return failed;
+}
+
 static int
 cmp_TESTChoice (void *a, void *b)
 {
@@ -1291,6 +1409,8 @@ main(int argc, char **argv)
     ret += test_cert();
 
     ret += check_tag_length();
+    ret += check_tag_length64();
+    ret += check_tag_length64s();
     ret += test_large_tag();
     ret += test_choice();
 
diff --git a/crypto/heimdal/lib/asn1/der-protos.h b/crypto/heimdal/lib/asn1/der-protos.h
index 3b3d81d175fb..9ebc78538a9e 100644
--- a/crypto/heimdal/lib/asn1/der-protos.h
+++ b/crypto/heimdal/lib/asn1/der-protos.h
@@ -67,6 +67,11 @@ der_copy_integer (
 	const int */*from*/,
 	int */*to*/);
 
+int
+der_copy_integer64 (
+	const int64_t */*from*/,
+	int64_t */*to*/);
+
 int
 der_copy_octet_string (
 	const heim_octet_string */*from*/,
@@ -92,6 +97,11 @@ der_copy_unsigned (
 	const unsigned */*from*/,
 	unsigned */*to*/);
 
+int
+der_copy_unsigned64 (
+	const uint64_t */*from*/,
+	uint64_t */*to*/);
+
 int
 der_copy_utctime (
 	const time_t */*from*/,
@@ -128,6 +138,9 @@ der_free_ia5_string (heim_ia5_string */*str*/);
 void
 der_free_integer (int */*i*/);
 
+void
+der_free_integer64 (int64_t */*i*/);
+
 void
 der_free_octet_string (heim_octet_string */*k*/);
 
@@ -143,6 +156,9 @@ der_free_universal_string (heim_universal_string */*k*/);
 void
 der_free_unsigned (unsigned */*u*/);
 
+void
+der_free_unsigned64 (uint64_t */*u*/);
+
 void
 der_free_utctime (time_t */*t*/);
 
@@ -214,6 +230,13 @@ der_get_integer (
 	int */*ret*/,
 	size_t */*size*/);
 
+int
+der_get_integer64 (
+	const unsigned char */*p*/,
+	size_t /*len*/,
+	int64_t */*ret*/,
+	size_t */*size*/);
+
 int
 der_get_length (
 	const unsigned char */*p*/,
@@ -284,6 +307,13 @@ der_get_unsigned (
 	unsigned */*ret*/,
 	size_t */*size*/);
 
+int
+der_get_unsigned64 (
+	const unsigned char */*p*/,
+	size_t /*len*/,
+	uint64_t */*ret*/,
+	size_t */*size*/);
+
 int
 der_get_utctime (
 	const unsigned char */*p*/,
@@ -367,6 +397,9 @@ der_length_ia5_string (const heim_ia5_string */*data*/);
 size_t
 der_length_integer (const int */*data*/);
 
+size_t
+der_length_integer64 (const int64_t */*data*/);
+
 size_t
 der_length_len (size_t /*len*/);
 
@@ -388,6 +421,9 @@ der_length_universal_string (const heim_universal_string */*data*/);
 size_t
 der_length_unsigned (const unsigned */*data*/);
 
+size_t
+der_length_unsigned64 (const uint64_t */*data*/);
+
 size_t
 der_length_utctime (const time_t */*t*/);
 
@@ -508,6 +544,13 @@ der_put_integer (
 	const int */*v*/,
 	size_t */*size*/);
 
+int
+der_put_integer64 (
+	unsigned char */*p*/,
+	size_t /*len*/,
+	const int64_t */*v*/,
+	size_t */*size*/);
+
 int
 der_put_length (
 	unsigned char */*p*/,
@@ -569,6 +612,13 @@ der_put_unsigned (
 	const unsigned */*v*/,
 	size_t */*size*/);
 
+int
+der_put_unsigned64 (
+	unsigned char */*p*/,
+	size_t /*len*/,
+	const uint64_t */*v*/,
+	size_t */*size*/);
+
 int
 der_put_utctime (
 	unsigned char */*p*/,
diff --git a/crypto/heimdal/lib/asn1/der_copy.c b/crypto/heimdal/lib/asn1/der_copy.c
index abaaf8e5d740..4faf87014280 100644
--- a/crypto/heimdal/lib/asn1/der_copy.c
+++ b/crypto/heimdal/lib/asn1/der_copy.c
@@ -54,6 +54,13 @@ der_copy_integer (const int *from, int *to)
     return 0;
 }
 
+int
+der_copy_integer64 (const int64_t *from, int64_t *to)
+{
+    *to = *from;
+    return 0;
+}
+
 int
 der_copy_unsigned (const unsigned *from, unsigned *to)
 {
@@ -61,6 +68,13 @@ der_copy_unsigned (const unsigned *from, unsigned *to)
     return 0;
 }
 
+int
+der_copy_unsigned64 (const uint64_t *from, uint64_t *to)
+{
+    *to = *from;
+    return 0;
+}
+
 int
 der_copy_generalized_time (const time_t *from, time_t *to)
 {
diff --git a/crypto/heimdal/lib/asn1/der_free.c b/crypto/heimdal/lib/asn1/der_free.c
index 4bae5fc2338f..1584cfcb299e 100644
--- a/crypto/heimdal/lib/asn1/der_free.c
+++ b/crypto/heimdal/lib/asn1/der_free.c
@@ -50,12 +50,24 @@ der_free_integer (int *i)
     *i = 0;
 }
 
+void
+der_free_integer64 (int64_t *i)
+{
+    *i = 0;
+}
+
 void
 der_free_unsigned (unsigned *u)
 {
     *u = 0;
 }
 
+void
+der_free_unsigned64 (uint64_t *u)
+{
+    *u = 0;
+}
+
 void
 der_free_generalized_time(time_t *t)
 {
diff --git a/crypto/heimdal/lib/asn1/der_get.c b/crypto/heimdal/lib/asn1/der_get.c
index 3112da86f93b..8a456d4d983d 100644
--- a/crypto/heimdal/lib/asn1/der_get.c
+++ b/crypto/heimdal/lib/asn1/der_get.c
@@ -48,9 +48,28 @@ der_get_unsigned (const unsigned char *p, size_t len,
     unsigned val = 0;
     size_t oldlen = len;
 
-    if (len == sizeof(unsigned) + 1 && p[0] == 0)
+    if (len == sizeof(val) + 1 && p[0] == 0)
 	;
-    else if (len > sizeof(unsigned))
+    else if (len > sizeof(val))
+	return ASN1_OVERRUN;
+
+    while (len--)
+	val = val * 256 + *p++;
+    *ret = val;
+    if(size) *size = oldlen;
+    return 0;
+}
+
+int
+der_get_unsigned64 (const unsigned char *p, size_t len,
+		    uint64_t *ret, size_t *size)
+{
+    uint64_t val = 0;
+    size_t oldlen = len;
+
+    if (len == sizeof(val) + 1 && p[0] == 0)
+	;
+    else if (len > sizeof(val))
 	return ASN1_OVERRUN;
 
     while (len--)
@@ -67,7 +86,27 @@ der_get_integer (const unsigned char *p, size_t len,
     int val = 0;
     size_t oldlen = len;
 
-    if (len > sizeof(int))
+    if (len > sizeof(val))
+	return ASN1_OVERRUN;
+
+    if (len > 0) {
+	val = (signed char)*p++;
+	while (--len)
+	    val = val * 256 + *p++;
+    }
+    *ret = val;
+    if(size) *size = oldlen;
+    return 0;
+}
+
+int
+der_get_integer64 (const unsigned char *p, size_t len,
+		   int64_t *ret, size_t *size)
+{
+    int64_t val = 0;
+    size_t oldlen = len;
+
+    if (len > sizeof(val))
 	return ASN1_OVERRUN;
 
     if (len > 0) {
diff --git a/crypto/heimdal/lib/asn1/der_length.c b/crypto/heimdal/lib/asn1/der_length.c
index db82025861ea..684ba9bc6f32 100644
--- a/crypto/heimdal/lib/asn1/der_length.c
+++ b/crypto/heimdal/lib/asn1/der_length.c
@@ -55,6 +55,24 @@ _heim_len_unsigned (unsigned val)
     return ret;
 }
 
+size_t
+_heim_len_unsigned64 (uint64_t val)
+{
+    size_t ret = 0;
+    int last_val_gt_128;
+
+    do {
+	++ret;
+	last_val_gt_128 = (val >= 128);
+	val /= 256;
+    } while (val);
+
+    if(last_val_gt_128)
+	ret++;
+
+    return ret;
+}
+
 size_t
 _heim_len_int (int val)
 {
@@ -82,6 +100,33 @@ _heim_len_int (int val)
     return ret;
 }
 
+size_t
+_heim_len_int64 (int64_t val)
+{
+    unsigned char q;
+    size_t ret = 0;
+
+    if (val >= 0) {
+	do {
+	    q = val % 256;
+	    ret++;
+	    val /= 256;
+	} while(val);
+	if(q >= 128)
+	    ret++;
+    } else {
+	val = ~val;
+	do {
+	    q = ~(val % 256);
+	    ret++;
+	    val /= 256;
+	} while(val);
+	if(q < 128)
+	    ret++;
+    }
+    return ret;
+}
+
 static size_t
 len_oid (const heim_oid *oid)
 {
@@ -134,12 +179,24 @@ der_length_integer (const int *data)
     return _heim_len_int (*data);
 }
 
+size_t
+der_length_integer64 (const int64_t *data)
+{
+    return _heim_len_int64 (*data);
+}
+
 size_t
 der_length_unsigned (const unsigned *data)
 {
     return _heim_len_unsigned(*data);
 }
 
+size_t
+der_length_unsigned64 (const uint64_t *data)
+{
+    return _heim_len_unsigned64(*data);
+}
+
 size_t
 der_length_enumerated (const unsigned *data)
 {
diff --git a/crypto/heimdal/lib/asn1/der_put.c b/crypto/heimdal/lib/asn1/der_put.c
index 0b276d1ebdce..0ccb181c0b39 100644
--- a/crypto/heimdal/lib/asn1/der_put.c
+++ b/crypto/heimdal/lib/asn1/der_put.c
@@ -75,6 +75,38 @@ der_put_unsigned (unsigned char *p, size_t len, const unsigned *v, size_t *size)
     }
 }
 
+int
+der_put_unsigned64 (unsigned char *p, size_t len, const uint64_t *v, size_t *size)
+{
+    unsigned char *base = p;
+    uint64_t val = *v;
+
+    if (val) {
+	while (len > 0 && val) {
+	    *p-- = val % 256;
+	    val /= 256;
+	    --len;
+	}
+	if (val != 0)
+	    return ASN1_OVERFLOW;
+	else {
+	    if(p[1] >= 128) {
+		if(len < 1)
+		    return ASN1_OVERFLOW;
+		*p-- = 0;
+	    }
+	    *size = base - p;
+	    return 0;
+	}
+    } else if (len < 1)
+	return ASN1_OVERFLOW;
+    else {
+	*p    = 0;
+	*size = 1;
+	return 0;
+    }
+}
+
 int
 der_put_integer (unsigned char *p, size_t len, const int *v, size_t *size)
 {
@@ -115,6 +147,46 @@ der_put_integer (unsigned char *p, size_t len, const int *v, size_t *size)
     return 0;
 }
 
+int
+der_put_integer64 (unsigned char *p, size_t len, const int64_t *v, size_t *size)
+{
+    unsigned char *base = p;
+    int64_t val = *v;
+
+    if(val >= 0) {
+	do {
+	    if(len < 1)
+		return ASN1_OVERFLOW;
+	    *p-- = val % 256;
+	    len--;
+	    val /= 256;
+	} while(val);
+	if(p[1] >= 128) {
+	    if(len < 1)
+		return ASN1_OVERFLOW;
+	    *p-- = 0;
+	    len--;
+	}
+    } else {
+	val = ~val;
+	do {
+	    if(len < 1)
+		return ASN1_OVERFLOW;
+	    *p-- = ~(val % 256);
+	    len--;
+	    val /= 256;
+	} while(val);
+	if(p[1] < 128) {
+	    if(len < 1)
+		return ASN1_OVERFLOW;
+	    *p-- = 0xff;
+	    len--;
+	}
+    }
+    *size = base - p;
+    return 0;
+}
+
 
 int
 der_put_length (unsigned char *p, size_t len, size_t val, size_t *size)
diff --git a/crypto/heimdal/lib/asn1/gen.c b/crypto/heimdal/lib/asn1/gen.c
index 2194b329ce1d..76a893c5ade7 100644
--- a/crypto/heimdal/lib/asn1/gen.c
+++ b/crypto/heimdal/lib/asn1/gen.c
@@ -303,7 +303,7 @@ gen_assign_defval(const char *var, struct value *val)
 	fprintf(codefile, "if((%s = strdup(\"%s\")) == NULL)\nreturn ENOMEM;\n", var, val->u.stringvalue);
 	break;
     case integervalue:
-	fprintf(codefile, "%s = %d;\n", var, val->u.integervalue);
+	fprintf(codefile, "%s = %" PRId64 ";\n", var, val->u.integervalue);
 	break;
     case booleanvalue:
 	if(val->u.booleanvalue)
@@ -324,7 +324,7 @@ gen_compare_defval(const char *var, struct value *val)
 	fprintf(codefile, "if(strcmp(%s, \"%s\") != 0)\n", var, val->u.stringvalue);
 	break;
     case integervalue:
-	fprintf(codefile, "if(%s != %d)\n", var, val->u.integervalue);
+	fprintf(codefile, "if(%s != %" PRId64 ")\n", var, val->u.integervalue);
 	break;
     case booleanvalue:
 	if(val->u.booleanvalue)
@@ -397,7 +397,7 @@ generate_constant (const Symbol *s)
     case booleanvalue:
 	break;
     case integervalue:
-	fprintf (headerfile, "enum { %s = %d };\n\n",
+	fprintf (headerfile, "enum { %s = %" PRId64 " };\n\n",
 		 s->gen_name, s->value->u.integervalue);
 	break;
     case nullvalue:
@@ -540,7 +540,7 @@ define_asn1 (int level, Type *t)
 	if(t->members == NULL) {
             fprintf (headerfile, "INTEGER");
 	    if (t->range)
-		fprintf (headerfile, " (%d..%d)",
+		fprintf (headerfile, " (%" PRId64 "..%" PRId64 ")",
 			 t->range->min, t->range->max);
         } else {
 	    Member *m;
@@ -723,14 +723,16 @@ define_type (int level, const char *name, const char *basename, Type *t, int typ
             fprintf (headerfile, "} %s;\n", name);
 	} else if (t->range == NULL) {
 	    fprintf (headerfile, "heim_integer %s;\n", name);
-	} else if (t->range->min == INT_MIN && t->range->max == INT_MAX) {
+	} else if (t->range->min < INT_MIN && t->range->max <= INT64_MAX) {
+	    fprintf (headerfile, "int64_t %s;\n", name);
+	} else if (t->range->min >= 0 && t->range->max > UINT_MAX) {
+	    fprintf (headerfile, "uint64_t %s;\n", name);
+	} else if (t->range->min >= INT_MIN && t->range->max <= INT_MAX) {
 	    fprintf (headerfile, "int %s;\n", name);
-	} else if (t->range->min == 0 && t->range->max == UINT_MAX) {
-	    fprintf (headerfile, "unsigned int %s;\n", name);
-	} else if (t->range->min == 0 && t->range->max == INT_MAX) {
+	} else if (t->range->min >= 0 && t->range->max <= UINT_MAX) {
 	    fprintf (headerfile, "unsigned int %s;\n", name);
 	} else
-	    errx(1, "%s: unsupported range %d -> %d",
+	    errx(1, "%s: unsupported range %" PRId64 " -> %" PRId64 "",
 		 name, t->range->min, t->range->max);
 	break;
     case TBoolean:
diff --git a/crypto/heimdal/lib/asn1/gen_decode.c b/crypto/heimdal/lib/asn1/gen_decode.c
index bf2d93b806df..c821ee1481a7 100644
--- a/crypto/heimdal/lib/asn1/gen_decode.c
+++ b/crypto/heimdal/lib/asn1/gen_decode.c
@@ -189,19 +189,19 @@ range_check(const char *name,
 {
     if (r->min == r->max + 2 || r->min < r->max)
 	fprintf (codefile,
-		 "if ((%s)->%s > %d) {\n"
+		 "if ((%s)->%s > %" PRId64 ") {\n"
 		 "e = ASN1_MAX_CONSTRAINT; %s;\n"
 		 "}\n",
 		 name, length, r->max, forwstr);
     if (r->min - 1 == r->max || r->min < r->max)
 	fprintf (codefile,
-		 "if ((%s)->%s < %d) {\n"
+		 "if ((%s)->%s < %" PRId64 ") {\n"
 		 "e = ASN1_MIN_CONSTRAINT; %s;\n"
 		 "}\n",
 		 name, length, r->min, forwstr);
     if (r->max == r->min)
 	fprintf (codefile,
-		 "if ((%s)->%s != %d) {\n"
+		 "if ((%s)->%s != %" PRId64 ") {\n"
 		 "e = ASN1_EXACT_CONSTRAINT; %s;\n"
 		 "}\n",
 		 name, length, r->min, forwstr);
@@ -252,14 +252,16 @@ decode_type (const char *name, const Type *t, int optional,
 		    name);
 	} else if (t->range == NULL) {
 	    decode_primitive ("heim_integer", name, forwstr);
-	} else if (t->range->min == INT_MIN && t->range->max == INT_MAX) {
+	} else if (t->range->min < INT_MIN && t->range->max <= INT64_MAX) {
+	    decode_primitive ("integer64", name, forwstr);
+	} else if (t->range->min >= 0 && t->range->max > UINT_MAX) {
+	    decode_primitive ("unsigned64", name, forwstr);
+	} else if (t->range->min >= INT_MIN && t->range->max <= INT_MAX) {
 	    decode_primitive ("integer", name, forwstr);
-	} else if (t->range->min == 0 && t->range->max == UINT_MAX) {
-	    decode_primitive ("unsigned", name, forwstr);
-	} else if (t->range->min == 0 && t->range->max == INT_MAX) {
+	} else if (t->range->min >= 0 && t->range->max <= UINT_MAX) {
 	    decode_primitive ("unsigned", name, forwstr);
 	} else
-	    errx(1, "%s: unsupported range %d -> %d",
+	    errx(1, "%s: unsupported range %" PRId64 " -> %" PRId64,
 		 name, t->range->min, t->range->max);
 	break;
     case TBoolean:
diff --git a/crypto/heimdal/lib/asn1/gen_encode.c b/crypto/heimdal/lib/asn1/gen_encode.c
index 1bd47484d83a..ac43b6a0d364 100644
--- a/crypto/heimdal/lib/asn1/gen_encode.c
+++ b/crypto/heimdal/lib/asn1/gen_encode.c
@@ -129,14 +129,16 @@ encode_type (const char *name, const Type *t, const char *tmpstr)
 	    fprintf(codefile, "}\n;");
 	} else if (t->range == NULL) {
 	    encode_primitive ("heim_integer", name);
-	} else if (t->range->min == INT_MIN && t->range->max == INT_MAX) {
+	} else if (t->range->min < INT_MIN && t->range->max <= INT64_MAX) {
+	    encode_primitive ("integer64", name);
+	} else if (t->range->min >= 0 && t->range->max > UINT_MAX) {
+	    encode_primitive ("unsigned64", name);
+	} else if (t->range->min >= INT_MIN && t->range->max <= INT_MAX) {
 	    encode_primitive ("integer", name);
-	} else if (t->range->min == 0 && t->range->max == UINT_MAX) {
-	    encode_primitive ("unsigned", name);
-	} else if (t->range->min == 0 && t->range->max == INT_MAX) {
+	} else if (t->range->min >= 0 && t->range->max <= UINT_MAX) {
 	    encode_primitive ("unsigned", name);
 	} else
-	    errx(1, "%s: unsupported range %d -> %d",
+	    errx(1, "%s: unsupported range %" PRId64 " -> %" PRId64,
 		 name, t->range->min, t->range->max);
 	constructed = 0;
 	break;
diff --git a/crypto/heimdal/lib/asn1/gen_length.c b/crypto/heimdal/lib/asn1/gen_length.c
index 20b5adfe5d02..f12246e676ec 100644
--- a/crypto/heimdal/lib/asn1/gen_length.c
+++ b/crypto/heimdal/lib/asn1/gen_length.c
@@ -80,14 +80,16 @@ length_type (const char *name, const Type *t,
 	    fprintf(codefile, "}\n");
 	} else if (t->range == NULL) {
 	    length_primitive ("heim_integer", name, variable);
-	} else if (t->range->min == INT_MIN && t->range->max == INT_MAX) {
+	} else if (t->range->min < INT_MIN && t->range->max <= INT64_MAX) {
+	    length_primitive ("integer64", name, variable);
+	} else if (t->range->min >= 0 && t->range->max > UINT_MAX) {
+	    length_primitive ("unsigned64", name, variable);
+	} else if (t->range->min >= INT_MIN && t->range->max <= INT_MAX) {
 	    length_primitive ("integer", name, variable);
-	} else if (t->range->min == 0 && t->range->max == UINT_MAX) {
-	    length_primitive ("unsigned", name, variable);
-	} else if (t->range->min == 0 && t->range->max == INT_MAX) {
+	} else if (t->range->min >= 0 && t->range->max <= UINT_MAX) {
 	    length_primitive ("unsigned", name, variable);
 	} else
-	    errx(1, "%s: unsupported range %d -> %d",
+	    errx(1, "%s: unsupported range %" PRId64 " -> %" PRId64,
 		 name, t->range->min, t->range->max);
 
 	break;
diff --git a/crypto/heimdal/lib/asn1/gen_template.c b/crypto/heimdal/lib/asn1/gen_template.c
index edd68e122380..15bf7d30c498 100644
--- a/crypto/heimdal/lib/asn1/gen_template.c
+++ b/crypto/heimdal/lib/asn1/gen_template.c
@@ -52,11 +52,13 @@ integer_symbol(const char *basename, const Type *t)
 	return "int"; /* XXX enum foo */
     else if (t->range == NULL)
 	return "heim_integer";
-    else if (t->range->min == INT_MIN && t->range->max == INT_MAX)
+    else if (t->range->min < INT_MIN && t->range->max <= INT64_MAX)
+	return "int64_t";
+    else if (t->range->min >= 0 && t->range->max > UINT_MAX)
+	return "uint64_t";
+    else if (t->range->min >= INT_MIN && t->range->max <= INT_MAX)
*** 98 LINES SKIPPED ***