Date: Wed, 24 Apr 2024 21:28:07 GMT From: Dimitry Andric <dim@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: 164f125311a6 - stable/14 - heimdal: Add 64-bit integer support to ASN.1 compiler Message-ID: <202404242128.43OLS7qN086244@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch stable/14 has been updated by dim: URL: https://cgit.FreeBSD.org/src/commit/?id=164f125311a6cc0217ce9103aaefcfd31fb796bf commit 164f125311a6cc0217ce9103aaefcfd31fb796bf Author: Dimitry Andric <dim@FreeBSD.org> AuthorDate: 2024-04-16 18:56:37 +0000 Commit: Dimitry Andric <dim@FreeBSD.org> CommitDate: 2024-04-24 21:26:52 +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 (cherry picked from commit 1b7487592987c91020063a311a14dc15b6e58075) --- 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) *** 100 LINES SKIPPED ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202404242128.43OLS7qN086244>