diff options
author | jsing <> | 2022-09-03 18:52:18 +0000 |
---|---|---|
committer | jsing <> | 2022-09-03 18:52:18 +0000 |
commit | 0cd135545398370513764fd74cd8a8871ef351cc (patch) | |
tree | c2f7e3d1627ccbe7aba894c618c04cb4d876e4dc /src/lib | |
parent | 5bb948dd8541248e1d3ad5dc62cd87323e2df812 (diff) | |
download | openbsd-0cd135545398370513764fd74cd8a8871ef351cc.tar.gz openbsd-0cd135545398370513764fd74cd8a8871ef351cc.tar.bz2 openbsd-0cd135545398370513764fd74cd8a8871ef351cc.zip |
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@
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/libcrypto/asn1/asn1_locl.h | 6 | ||||
-rw-r--r-- | src/lib/libcrypto/asn1/asn1_types.c | 42 | ||||
-rw-r--r-- | src/lib/libcrypto/asn1/tasn_dec.c | 11 |
3 files changed, 52 insertions, 7 deletions
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 @@ | |||
1 | /* $OpenBSD: asn1_locl.h,v 1.36 2022/09/03 18:45:51 jsing Exp $ */ | 1 | /* $OpenBSD: asn1_locl.h,v 1.37 2022/09/03 18:52:18 jsing Exp $ */ |
2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | 2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
3 | * project 2006. | 3 | * project 2006. |
4 | */ | 4 | */ |
@@ -204,6 +204,8 @@ int asn1_get_object_cbs(CBS *cbs, int der_mode, uint8_t *out_class, | |||
204 | int asn1_get_primitive(CBS *cbs, int der_mode, uint32_t *out_tag_number, | 204 | int asn1_get_primitive(CBS *cbs, int der_mode, uint32_t *out_tag_number, |
205 | CBS *out_content); | 205 | CBS *out_content); |
206 | 206 | ||
207 | int asn1_must_be_constructed(int tag); | ||
208 | int asn1_must_be_primitive(int tag); | ||
207 | int asn1_tag2charwidth(int tag); | 209 | int asn1_tag2charwidth(int tag); |
208 | 210 | ||
209 | int asn1_abs_set_unused_bits(ASN1_BIT_STRING *abs, uint8_t unused_bits); | 211 | 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); | |||
211 | 213 | ||
212 | int c2i_ASN1_ENUMERATED_cbs(ASN1_ENUMERATED **out_aenum, CBS *cbs); | 214 | int c2i_ASN1_ENUMERATED_cbs(ASN1_ENUMERATED **out_aenum, CBS *cbs); |
213 | 215 | ||
216 | int c2i_ASN1_ENUMERATED_cbs(ASN1_ENUMERATED **out_aenum, CBS *cbs); | ||
217 | |||
214 | int asn1_aint_get_uint64(CBS *cbs, uint64_t *out_val); | 218 | int asn1_aint_get_uint64(CBS *cbs, uint64_t *out_val); |
215 | int asn1_aint_set_uint64(uint64_t val, uint8_t **out_data, int *out_len); | 219 | int asn1_aint_set_uint64(uint64_t val, uint8_t **out_data, int *out_len); |
216 | int asn1_aint_get_int64(CBS *cbs, int negative, int64_t *out_val); | 220 | 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 @@ | |||
1 | /* $OpenBSD: asn1_types.c,v 1.1 2021/12/14 17:35:21 jsing Exp $ */ | 1 | /* $OpenBSD: asn1_types.c,v 1.2 2022/09/03 18:52:18 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2021 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2021 Joel Sing <jsing@openbsd.org> |
4 | * | 4 | * |
@@ -19,10 +19,14 @@ | |||
19 | 19 | ||
20 | #include <openssl/asn1.h> | 20 | #include <openssl/asn1.h> |
21 | 21 | ||
22 | #define ASN1_ENCODING_CONSTRUCTED_ONLY 1 | ||
23 | #define ASN1_ENCODING_PRIMITIVE_ONLY 2 | ||
24 | |||
22 | struct asn1_type { | 25 | struct asn1_type { |
23 | const char *name; | 26 | const char *name; |
24 | uint32_t bit_value; | 27 | uint32_t bit_value; |
25 | int char_width; | 28 | int char_width; |
29 | int encoding; | ||
26 | }; | 30 | }; |
27 | 31 | ||
28 | /* | 32 | /* |
@@ -40,12 +44,14 @@ static const struct asn1_type asn1_types[31] = { | |||
40 | .name = "BOOLEAN", | 44 | .name = "BOOLEAN", |
41 | .bit_value = 0, | 45 | .bit_value = 0, |
42 | .char_width = -1, | 46 | .char_width = -1, |
47 | .encoding = ASN1_ENCODING_PRIMITIVE_ONLY, | ||
43 | }, | 48 | }, |
44 | [2] = { | 49 | [2] = { |
45 | /* Tag 2 (0x02) - Integer */ | 50 | /* Tag 2 (0x02) - Integer */ |
46 | .name = "INTEGER", | 51 | .name = "INTEGER", |
47 | .bit_value = 0, | 52 | .bit_value = 0, |
48 | .char_width = -1, | 53 | .char_width = -1, |
54 | .encoding = ASN1_ENCODING_PRIMITIVE_ONLY, | ||
49 | }, | 55 | }, |
50 | [3] = { | 56 | [3] = { |
51 | /* Tag 3 (0x03) - BitString */ | 57 | /* Tag 3 (0x03) - BitString */ |
@@ -64,12 +70,14 @@ static const struct asn1_type asn1_types[31] = { | |||
64 | .name = "NULL", | 70 | .name = "NULL", |
65 | .bit_value = 0, | 71 | .bit_value = 0, |
66 | .char_width = -1, | 72 | .char_width = -1, |
73 | .encoding = ASN1_ENCODING_PRIMITIVE_ONLY, | ||
67 | }, | 74 | }, |
68 | [6] = { | 75 | [6] = { |
69 | /* Tag 6 (0x06) - Object Identifier */ | 76 | /* Tag 6 (0x06) - Object Identifier */ |
70 | .name = "OBJECT", | 77 | .name = "OBJECT", |
71 | .bit_value = 0, | 78 | .bit_value = 0, |
72 | .char_width = -1, | 79 | .char_width = -1, |
80 | .encoding = ASN1_ENCODING_PRIMITIVE_ONLY, | ||
73 | }, | 81 | }, |
74 | [7] = { | 82 | [7] = { |
75 | /* Tag 7 (0x07) - Object Descriptor */ | 83 | /* Tag 7 (0x07) - Object Descriptor */ |
@@ -88,12 +96,14 @@ static const struct asn1_type asn1_types[31] = { | |||
88 | .name = "REAL", | 96 | .name = "REAL", |
89 | .bit_value = B_ASN1_UNKNOWN, | 97 | .bit_value = B_ASN1_UNKNOWN, |
90 | .char_width = -1, | 98 | .char_width = -1, |
99 | .encoding = ASN1_ENCODING_PRIMITIVE_ONLY, | ||
91 | }, | 100 | }, |
92 | [10] = { | 101 | [10] = { |
93 | /* Tag 10 (0x0a) - Enumerated */ | 102 | /* Tag 10 (0x0a) - Enumerated */ |
94 | .name = "ENUMERATED", | 103 | .name = "ENUMERATED", |
95 | .bit_value = B_ASN1_UNKNOWN, | 104 | .bit_value = B_ASN1_UNKNOWN, |
96 | .char_width = -1, | 105 | .char_width = -1, |
106 | .encoding = ASN1_ENCODING_PRIMITIVE_ONLY, | ||
97 | }, | 107 | }, |
98 | [11] = { | 108 | [11] = { |
99 | /* Tag 11 (0x0b) - Embedded PDV */ | 109 | /* Tag 11 (0x0b) - Embedded PDV */ |
@@ -112,12 +122,14 @@ static const struct asn1_type asn1_types[31] = { | |||
112 | .name = "<ASN1 13 RELATIVE OID>", | 122 | .name = "<ASN1 13 RELATIVE OID>", |
113 | .bit_value = B_ASN1_UNKNOWN, | 123 | .bit_value = B_ASN1_UNKNOWN, |
114 | .char_width = -1, | 124 | .char_width = -1, |
125 | .encoding = ASN1_ENCODING_PRIMITIVE_ONLY, | ||
115 | }, | 126 | }, |
116 | [14] = { | 127 | [14] = { |
117 | /* Tag 14 (0x0e) - Time */ | 128 | /* Tag 14 (0x0e) - Time */ |
118 | .name = "<ASN1 14 TIME>", | 129 | .name = "<ASN1 14 TIME>", |
119 | .bit_value = B_ASN1_UNKNOWN, | 130 | .bit_value = B_ASN1_UNKNOWN, |
120 | .char_width = -1, | 131 | .char_width = -1, |
132 | .encoding = ASN1_ENCODING_PRIMITIVE_ONLY, | ||
121 | }, | 133 | }, |
122 | [15] = { | 134 | [15] = { |
123 | /* Tag 15 (0x0f) - Reserved */ | 135 | /* Tag 15 (0x0f) - Reserved */ |
@@ -130,12 +142,14 @@ static const struct asn1_type asn1_types[31] = { | |||
130 | .name = "SEQUENCE", | 142 | .name = "SEQUENCE", |
131 | .bit_value = B_ASN1_SEQUENCE, | 143 | .bit_value = B_ASN1_SEQUENCE, |
132 | .char_width = -1, | 144 | .char_width = -1, |
145 | .encoding = ASN1_ENCODING_CONSTRUCTED_ONLY, | ||
133 | }, | 146 | }, |
134 | [17] = { | 147 | [17] = { |
135 | /* Tag 17 (0x11) - Set */ | 148 | /* Tag 17 (0x11) - Set */ |
136 | .name = "SET", | 149 | .name = "SET", |
137 | .bit_value = 0, | 150 | .bit_value = 0, |
138 | .char_width = -1, | 151 | .char_width = -1, |
152 | .encoding = ASN1_ENCODING_CONSTRUCTED_ONLY, | ||
139 | }, | 153 | }, |
140 | [18] = { | 154 | [18] = { |
141 | /* Tag 18 (0x12) - NumericString */ | 155 | /* Tag 18 (0x12) - NumericString */ |
@@ -227,6 +241,32 @@ asn1_type_by_tag(int tag) | |||
227 | } | 241 | } |
228 | 242 | ||
229 | int | 243 | int |
244 | asn1_must_be_constructed(int tag) | ||
245 | { | ||
246 | const struct asn1_type *at; | ||
247 | |||
248 | if (tag == V_ASN1_NEG_INTEGER || tag == V_ASN1_NEG_ENUMERATED) | ||
249 | tag &= ~V_ASN1_NEG; | ||
250 | if ((at = asn1_type_by_tag(tag)) != NULL) | ||
251 | return at->encoding == ASN1_ENCODING_CONSTRUCTED_ONLY; | ||
252 | |||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | int | ||
257 | asn1_must_be_primitive(int tag) | ||
258 | { | ||
259 | const struct asn1_type *at; | ||
260 | |||
261 | if (tag == V_ASN1_NEG_INTEGER || tag == V_ASN1_NEG_ENUMERATED) | ||
262 | tag &= ~V_ASN1_NEG; | ||
263 | if ((at = asn1_type_by_tag(tag)) != NULL) | ||
264 | return at->encoding == ASN1_ENCODING_PRIMITIVE_ONLY; | ||
265 | |||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | int | ||
230 | asn1_tag2charwidth(int tag) | 270 | asn1_tag2charwidth(int tag) |
231 | { | 271 | { |
232 | const struct asn1_type *at; | 272 | const struct asn1_type *at; |
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 @@ | |||
1 | /* $OpenBSD: tasn_dec.c,v 1.79 2022/09/03 18:45:51 jsing Exp $ */ | 1 | /* $OpenBSD: tasn_dec.c,v 1.80 2022/09/03 18:52:18 jsing Exp $ */ |
2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | 2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
3 | * project 2000. | 3 | * project 2000. |
4 | */ | 4 | */ |
@@ -467,13 +467,14 @@ asn1_d2i_primitive_content(ASN1_VALUE **pval, CBS *cbs, CBS *cbs_object, | |||
467 | CBS_dup(cbs, &cbs_initial); | 467 | CBS_dup(cbs, &cbs_initial); |
468 | CBS_init(&cbs_content, NULL, 0); | 468 | CBS_init(&cbs_content, NULL, 0); |
469 | 469 | ||
470 | /* XXX - check primitive vs constructed based on utype. */ | 470 | if (asn1_must_be_constructed(utype) && !constructed) { |
471 | |||
472 | /* SEQUENCE and SET must be constructed. */ | ||
473 | if ((utype == V_ASN1_SEQUENCE || utype == V_ASN1_SET) && !constructed) { | ||
474 | ASN1error(ASN1_R_TYPE_NOT_CONSTRUCTED); | 471 | ASN1error(ASN1_R_TYPE_NOT_CONSTRUCTED); |
475 | goto err; | 472 | goto err; |
476 | } | 473 | } |
474 | if (asn1_must_be_primitive(utype) && constructed) { | ||
475 | ASN1error(ASN1_R_TYPE_NOT_PRIMITIVE); | ||
476 | goto err; | ||
477 | } | ||
477 | 478 | ||
478 | /* SEQUENCE, SET and "OTHER" are left in encoded form. */ | 479 | /* SEQUENCE, SET and "OTHER" are left in encoded form. */ |
479 | if (utype == V_ASN1_SEQUENCE || utype == V_ASN1_SET || | 480 | if (utype == V_ASN1_SEQUENCE || utype == V_ASN1_SET || |