From 0cd135545398370513764fd74cd8a8871ef351cc Mon Sep 17 00:00:00 2001 From: jsing <> Date: Sat, 3 Sep 2022 18:52:18 +0000 Subject: Ensure ASN.1 types are appropriately encoded. Per X.690, some ASN.1 types must be primitive encoded, some must be constructed and some may be either. Add this data to our types table and check the encoding against this information when decoding. ok tb@ --- src/lib/libcrypto/asn1/asn1_locl.h | 6 +++++- src/lib/libcrypto/asn1/asn1_types.c | 42 ++++++++++++++++++++++++++++++++++++- src/lib/libcrypto/asn1/tasn_dec.c | 11 +++++----- 3 files changed, 52 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/lib/libcrypto/asn1/asn1_locl.h b/src/lib/libcrypto/asn1/asn1_locl.h index e2c57fd8c4..1eb7ee402e 100644 --- a/src/lib/libcrypto/asn1/asn1_locl.h +++ b/src/lib/libcrypto/asn1/asn1_locl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: asn1_locl.h,v 1.36 2022/09/03 18:45:51 jsing Exp $ */ +/* $OpenBSD: asn1_locl.h,v 1.37 2022/09/03 18:52:18 jsing Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2006. */ @@ -204,6 +204,8 @@ int asn1_get_object_cbs(CBS *cbs, int der_mode, uint8_t *out_class, int asn1_get_primitive(CBS *cbs, int der_mode, uint32_t *out_tag_number, CBS *out_content); +int asn1_must_be_constructed(int tag); +int asn1_must_be_primitive(int tag); int asn1_tag2charwidth(int tag); int asn1_abs_set_unused_bits(ASN1_BIT_STRING *abs, uint8_t unused_bits); @@ -211,6 +213,8 @@ int c2i_ASN1_BIT_STRING_cbs(ASN1_BIT_STRING **out_abs, CBS *cbs); int c2i_ASN1_ENUMERATED_cbs(ASN1_ENUMERATED **out_aenum, CBS *cbs); +int c2i_ASN1_ENUMERATED_cbs(ASN1_ENUMERATED **out_aenum, CBS *cbs); + int asn1_aint_get_uint64(CBS *cbs, uint64_t *out_val); int asn1_aint_set_uint64(uint64_t val, uint8_t **out_data, int *out_len); int asn1_aint_get_int64(CBS *cbs, int negative, int64_t *out_val); diff --git a/src/lib/libcrypto/asn1/asn1_types.c b/src/lib/libcrypto/asn1/asn1_types.c index c8e6b23f4f..d8b7c1e88e 100644 --- a/src/lib/libcrypto/asn1/asn1_types.c +++ b/src/lib/libcrypto/asn1/asn1_types.c @@ -1,4 +1,4 @@ -/* $OpenBSD: asn1_types.c,v 1.1 2021/12/14 17:35:21 jsing Exp $ */ +/* $OpenBSD: asn1_types.c,v 1.2 2022/09/03 18:52:18 jsing Exp $ */ /* * Copyright (c) 2021 Joel Sing * @@ -19,10 +19,14 @@ #include +#define ASN1_ENCODING_CONSTRUCTED_ONLY 1 +#define ASN1_ENCODING_PRIMITIVE_ONLY 2 + struct asn1_type { const char *name; uint32_t bit_value; int char_width; + int encoding; }; /* @@ -40,12 +44,14 @@ static const struct asn1_type asn1_types[31] = { .name = "BOOLEAN", .bit_value = 0, .char_width = -1, + .encoding = ASN1_ENCODING_PRIMITIVE_ONLY, }, [2] = { /* Tag 2 (0x02) - Integer */ .name = "INTEGER", .bit_value = 0, .char_width = -1, + .encoding = ASN1_ENCODING_PRIMITIVE_ONLY, }, [3] = { /* Tag 3 (0x03) - BitString */ @@ -64,12 +70,14 @@ static const struct asn1_type asn1_types[31] = { .name = "NULL", .bit_value = 0, .char_width = -1, + .encoding = ASN1_ENCODING_PRIMITIVE_ONLY, }, [6] = { /* Tag 6 (0x06) - Object Identifier */ .name = "OBJECT", .bit_value = 0, .char_width = -1, + .encoding = ASN1_ENCODING_PRIMITIVE_ONLY, }, [7] = { /* Tag 7 (0x07) - Object Descriptor */ @@ -88,12 +96,14 @@ static const struct asn1_type asn1_types[31] = { .name = "REAL", .bit_value = B_ASN1_UNKNOWN, .char_width = -1, + .encoding = ASN1_ENCODING_PRIMITIVE_ONLY, }, [10] = { /* Tag 10 (0x0a) - Enumerated */ .name = "ENUMERATED", .bit_value = B_ASN1_UNKNOWN, .char_width = -1, + .encoding = ASN1_ENCODING_PRIMITIVE_ONLY, }, [11] = { /* Tag 11 (0x0b) - Embedded PDV */ @@ -112,12 +122,14 @@ static const struct asn1_type asn1_types[31] = { .name = "", .bit_value = B_ASN1_UNKNOWN, .char_width = -1, + .encoding = ASN1_ENCODING_PRIMITIVE_ONLY, }, [14] = { /* Tag 14 (0x0e) - Time */ .name = "", .bit_value = B_ASN1_UNKNOWN, .char_width = -1, + .encoding = ASN1_ENCODING_PRIMITIVE_ONLY, }, [15] = { /* Tag 15 (0x0f) - Reserved */ @@ -130,12 +142,14 @@ static const struct asn1_type asn1_types[31] = { .name = "SEQUENCE", .bit_value = B_ASN1_SEQUENCE, .char_width = -1, + .encoding = ASN1_ENCODING_CONSTRUCTED_ONLY, }, [17] = { /* Tag 17 (0x11) - Set */ .name = "SET", .bit_value = 0, .char_width = -1, + .encoding = ASN1_ENCODING_CONSTRUCTED_ONLY, }, [18] = { /* Tag 18 (0x12) - NumericString */ @@ -226,6 +240,32 @@ asn1_type_by_tag(int tag) return &asn1_types[tag]; } +int +asn1_must_be_constructed(int tag) +{ + const struct asn1_type *at; + + if (tag == V_ASN1_NEG_INTEGER || tag == V_ASN1_NEG_ENUMERATED) + tag &= ~V_ASN1_NEG; + if ((at = asn1_type_by_tag(tag)) != NULL) + return at->encoding == ASN1_ENCODING_CONSTRUCTED_ONLY; + + return 0; +} + +int +asn1_must_be_primitive(int tag) +{ + const struct asn1_type *at; + + if (tag == V_ASN1_NEG_INTEGER || tag == V_ASN1_NEG_ENUMERATED) + tag &= ~V_ASN1_NEG; + if ((at = asn1_type_by_tag(tag)) != NULL) + return at->encoding == ASN1_ENCODING_PRIMITIVE_ONLY; + + return 0; +} + int asn1_tag2charwidth(int tag) { diff --git a/src/lib/libcrypto/asn1/tasn_dec.c b/src/lib/libcrypto/asn1/tasn_dec.c index 22d8006d0a..457f526e71 100644 --- a/src/lib/libcrypto/asn1/tasn_dec.c +++ b/src/lib/libcrypto/asn1/tasn_dec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tasn_dec.c,v 1.79 2022/09/03 18:45:51 jsing Exp $ */ +/* $OpenBSD: tasn_dec.c,v 1.80 2022/09/03 18:52:18 jsing Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2000. */ @@ -467,13 +467,14 @@ asn1_d2i_primitive_content(ASN1_VALUE **pval, CBS *cbs, CBS *cbs_object, CBS_dup(cbs, &cbs_initial); CBS_init(&cbs_content, NULL, 0); - /* XXX - check primitive vs constructed based on utype. */ - - /* SEQUENCE and SET must be constructed. */ - if ((utype == V_ASN1_SEQUENCE || utype == V_ASN1_SET) && !constructed) { + if (asn1_must_be_constructed(utype) && !constructed) { ASN1error(ASN1_R_TYPE_NOT_CONSTRUCTED); goto err; } + if (asn1_must_be_primitive(utype) && constructed) { + ASN1error(ASN1_R_TYPE_NOT_PRIMITIVE); + goto err; + } /* SEQUENCE, SET and "OTHER" are left in encoded form. */ if (utype == V_ASN1_SEQUENCE || utype == V_ASN1_SET || -- cgit v1.2.3-55-g6feb