From: jsing Date: Sat, 3 Sep 2022 18:52:18 +0000 (+0000) Subject: Ensure ASN.1 types are appropriately encoded. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=98a0616a27a817d08e2243f4d72decdefe8f0ace;p=openbsd 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@ --- diff --git a/lib/libcrypto/asn1/asn1_locl.h b/lib/libcrypto/asn1/asn1_locl.h index e2c57fd8c49..1eb7ee402ec 100644 --- a/lib/libcrypto/asn1/asn1_locl.h +++ b/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/lib/libcrypto/asn1/asn1_types.c b/lib/libcrypto/asn1/asn1_types.c index c8e6b23f4fb..d8b7c1e88e2 100644 --- a/lib/libcrypto/asn1/asn1_types.c +++ b/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/lib/libcrypto/asn1/tasn_dec.c b/lib/libcrypto/asn1/tasn_dec.c index 22d8006d0af..457f526e710 100644 --- a/lib/libcrypto/asn1/tasn_dec.c +++ b/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 ||