diff options
Diffstat (limited to 'recipes-connectivity/openssl/openssl/CVE-2018-0739-limit-ASN.1-constructed-types-recursive-definition-depth.patch')
-rw-r--r-- | recipes-connectivity/openssl/openssl/CVE-2018-0739-limit-ASN.1-constructed-types-recursive-definition-depth.patch | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/recipes-connectivity/openssl/openssl/CVE-2018-0739-limit-ASN.1-constructed-types-recursive-definition-depth.patch b/recipes-connectivity/openssl/openssl/CVE-2018-0739-limit-ASN.1-constructed-types-recursive-definition-depth.patch new file mode 100644 index 0000000..8062031 --- /dev/null +++ b/recipes-connectivity/openssl/openssl/CVE-2018-0739-limit-ASN.1-constructed-types-recursive-definition-depth.patch | |||
@@ -0,0 +1,237 @@ | |||
1 | From 9310d45087ae546e27e61ddf8f6367f29848220d Mon Sep 17 00:00:00 2001 | ||
2 | From: Matt Caswell <matt@openssl.org> | ||
3 | Date: Thu, 22 Mar 2018 10:05:40 +0000 | ||
4 | Subject: [PATCH] Limit ASN.1 constructed types recursive definition depth | ||
5 | |||
6 | Constructed types with a recursive definition (such as can be found in | ||
7 | PKCS7) could eventually exceed the stack given malicious input with | ||
8 | excessive recursion. Therefore we limit the stack depth. | ||
9 | |||
10 | CVE-2018-0739 | ||
11 | Upstream-Status: Backport [https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff_plain;h=9310d45087ae546e27e61ddf8f6367f29848220d] | ||
12 | |||
13 | Credit to OSSFuzz for finding this issue. | ||
14 | |||
15 | Reviewed-by: Rich Salz <rsalz@openssl.org> | ||
16 | Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com> | ||
17 | --- | ||
18 | crypto/asn1/asn1.h | 1 + | ||
19 | crypto/asn1/asn1_err.c | 3 ++- | ||
20 | crypto/asn1/tasn_dec.c | 62 +++++++++++++++++++++++++++++++++----------------- | ||
21 | 3 files changed, 44 insertions(+), 22 deletions(-) | ||
22 | |||
23 | diff --git a/crypto/asn1/asn1.h b/crypto/asn1/asn1.h | ||
24 | index 68e791f..35a2b2a 100644 | ||
25 | --- a/crypto/asn1/asn1.h | ||
26 | +++ b/crypto/asn1/asn1.h | ||
27 | @@ -1365,6 +1365,7 @@ void ERR_load_ASN1_strings(void); | ||
28 | # define ASN1_R_MSTRING_NOT_UNIVERSAL 139 | ||
29 | # define ASN1_R_MSTRING_WRONG_TAG 140 | ||
30 | # define ASN1_R_NESTED_ASN1_STRING 197 | ||
31 | +# define ASN1_R_NESTED_TOO_DEEP 219 | ||
32 | # define ASN1_R_NON_HEX_CHARACTERS 141 | ||
33 | # define ASN1_R_NOT_ASCII_FORMAT 190 | ||
34 | # define ASN1_R_NOT_ENOUGH_DATA 142 | ||
35 | diff --git a/crypto/asn1/asn1_err.c b/crypto/asn1/asn1_err.c | ||
36 | index fd4ac8d..cfc1512 100644 | ||
37 | --- a/crypto/asn1/asn1_err.c | ||
38 | +++ b/crypto/asn1/asn1_err.c | ||
39 | @@ -1,6 +1,6 @@ | ||
40 | /* crypto/asn1/asn1_err.c */ | ||
41 | /* ==================================================================== | ||
42 | - * Copyright (c) 1999-2014 The OpenSSL Project. All rights reserved. | ||
43 | + * Copyright (c) 1999-2018 The OpenSSL Project. All rights reserved. | ||
44 | * | ||
45 | * Redistribution and use in source and binary forms, with or without | ||
46 | * modification, are permitted provided that the following conditions | ||
47 | @@ -279,6 +279,7 @@ static ERR_STRING_DATA ASN1_str_reasons[] = { | ||
48 | {ERR_REASON(ASN1_R_MSTRING_NOT_UNIVERSAL), "mstring not universal"}, | ||
49 | {ERR_REASON(ASN1_R_MSTRING_WRONG_TAG), "mstring wrong tag"}, | ||
50 | {ERR_REASON(ASN1_R_NESTED_ASN1_STRING), "nested asn1 string"}, | ||
51 | + {ERR_REASON(ASN1_R_NESTED_TOO_DEEP), "nested too deep"}, | ||
52 | {ERR_REASON(ASN1_R_NON_HEX_CHARACTERS), "non hex characters"}, | ||
53 | {ERR_REASON(ASN1_R_NOT_ASCII_FORMAT), "not ascii format"}, | ||
54 | {ERR_REASON(ASN1_R_NOT_ENOUGH_DATA), "not enough data"}, | ||
55 | diff --git a/crypto/asn1/tasn_dec.c b/crypto/asn1/tasn_dec.c | ||
56 | index d49a5d5..78126e9 100644 | ||
57 | --- a/crypto/asn1/tasn_dec.c | ||
58 | +++ b/crypto/asn1/tasn_dec.c | ||
59 | @@ -65,6 +65,14 @@ | ||
60 | #include <openssl/buffer.h> | ||
61 | #include <openssl/err.h> | ||
62 | |||
63 | +/* | ||
64 | + * Constructed types with a recursive definition (such as can be found in PKCS7) | ||
65 | + * could eventually exceed the stack given malicious input with excessive | ||
66 | + * recursion. Therefore we limit the stack depth. This is the maximum number of | ||
67 | + * recursive invocations of asn1_item_embed_d2i(). | ||
68 | + */ | ||
69 | +#define ASN1_MAX_CONSTRUCTED_NEST 30 | ||
70 | + | ||
71 | static int asn1_check_eoc(const unsigned char **in, long len); | ||
72 | static int asn1_find_end(const unsigned char **in, long len, char inf); | ||
73 | |||
74 | @@ -81,11 +89,11 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, | ||
75 | static int asn1_template_ex_d2i(ASN1_VALUE **pval, | ||
76 | const unsigned char **in, long len, | ||
77 | const ASN1_TEMPLATE *tt, char opt, | ||
78 | - ASN1_TLC *ctx); | ||
79 | + ASN1_TLC *ctx, int depth); | ||
80 | static int asn1_template_noexp_d2i(ASN1_VALUE **val, | ||
81 | const unsigned char **in, long len, | ||
82 | const ASN1_TEMPLATE *tt, char opt, | ||
83 | - ASN1_TLC *ctx); | ||
84 | + ASN1_TLC *ctx, int depth); | ||
85 | static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, | ||
86 | const unsigned char **in, long len, | ||
87 | const ASN1_ITEM *it, | ||
88 | @@ -154,17 +162,16 @@ int ASN1_template_d2i(ASN1_VALUE **pval, | ||
89 | { | ||
90 | ASN1_TLC c; | ||
91 | asn1_tlc_clear_nc(&c); | ||
92 | - return asn1_template_ex_d2i(pval, in, len, tt, 0, &c); | ||
93 | + return asn1_template_ex_d2i(pval, in, len, tt, 0, &c, 0); | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * Decode an item, taking care of IMPLICIT tagging, if any. If 'opt' set and | ||
98 | * tag mismatch return -1 to handle OPTIONAL | ||
99 | */ | ||
100 | - | ||
101 | -int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | ||
102 | - const ASN1_ITEM *it, | ||
103 | - int tag, int aclass, char opt, ASN1_TLC *ctx) | ||
104 | +static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, | ||
105 | + long len, const ASN1_ITEM *it, int tag, int aclass, | ||
106 | + char opt, ASN1_TLC *ctx, int depth) | ||
107 | { | ||
108 | const ASN1_TEMPLATE *tt, *errtt = NULL; | ||
109 | const ASN1_COMPAT_FUNCS *cf; | ||
110 | @@ -189,6 +196,11 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | ||
111 | else | ||
112 | asn1_cb = 0; | ||
113 | |||
114 | + if (++depth > ASN1_MAX_CONSTRUCTED_NEST) { | ||
115 | + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_NESTED_TOO_DEEP); | ||
116 | + goto err; | ||
117 | + } | ||
118 | + | ||
119 | switch (it->itype) { | ||
120 | case ASN1_ITYPE_PRIMITIVE: | ||
121 | if (it->templates) { | ||
122 | @@ -204,7 +216,7 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | ||
123 | goto err; | ||
124 | } | ||
125 | return asn1_template_ex_d2i(pval, in, len, | ||
126 | - it->templates, opt, ctx); | ||
127 | + it->templates, opt, ctx, depth); | ||
128 | } | ||
129 | return asn1_d2i_ex_primitive(pval, in, len, it, | ||
130 | tag, aclass, opt, ctx); | ||
131 | @@ -326,7 +338,7 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | ||
132 | /* | ||
133 | * We mark field as OPTIONAL so its absence can be recognised. | ||
134 | */ | ||
135 | - ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx); | ||
136 | + ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx, depth); | ||
137 | /* If field not present, try the next one */ | ||
138 | if (ret == -1) | ||
139 | continue; | ||
140 | @@ -444,7 +456,8 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | ||
141 | * attempt to read in field, allowing each to be OPTIONAL | ||
142 | */ | ||
143 | |||
144 | - ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, ctx); | ||
145 | + ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, ctx, | ||
146 | + depth); | ||
147 | if (!ret) { | ||
148 | errtt = seqtt; | ||
149 | goto err; | ||
150 | @@ -514,6 +527,13 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | ||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | +int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | ||
155 | + const ASN1_ITEM *it, | ||
156 | + int tag, int aclass, char opt, ASN1_TLC *ctx) | ||
157 | +{ | ||
158 | + return asn1_item_ex_d2i(pval, in, len, it, tag, aclass, opt, ctx, 0); | ||
159 | +} | ||
160 | + | ||
161 | /* | ||
162 | * Templates are handled with two separate functions. One handles any | ||
163 | * EXPLICIT tag and the other handles the rest. | ||
164 | @@ -522,7 +542,7 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | ||
165 | static int asn1_template_ex_d2i(ASN1_VALUE **val, | ||
166 | const unsigned char **in, long inlen, | ||
167 | const ASN1_TEMPLATE *tt, char opt, | ||
168 | - ASN1_TLC *ctx) | ||
169 | + ASN1_TLC *ctx, int depth) | ||
170 | { | ||
171 | int flags, aclass; | ||
172 | int ret; | ||
173 | @@ -557,7 +577,7 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val, | ||
174 | return 0; | ||
175 | } | ||
176 | /* We've found the field so it can't be OPTIONAL now */ | ||
177 | - ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx); | ||
178 | + ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx, depth); | ||
179 | if (!ret) { | ||
180 | ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_NESTED_ASN1_ERROR); | ||
181 | return 0; | ||
182 | @@ -581,7 +601,7 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val, | ||
183 | } | ||
184 | } | ||
185 | } else | ||
186 | - return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx); | ||
187 | + return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx, depth); | ||
188 | |||
189 | *in = p; | ||
190 | return 1; | ||
191 | @@ -594,7 +614,7 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val, | ||
192 | static int asn1_template_noexp_d2i(ASN1_VALUE **val, | ||
193 | const unsigned char **in, long len, | ||
194 | const ASN1_TEMPLATE *tt, char opt, | ||
195 | - ASN1_TLC *ctx) | ||
196 | + ASN1_TLC *ctx, int depth) | ||
197 | { | ||
198 | int flags, aclass; | ||
199 | int ret; | ||
200 | @@ -665,8 +685,8 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, | ||
201 | break; | ||
202 | } | ||
203 | skfield = NULL; | ||
204 | - if (!ASN1_item_ex_d2i(&skfield, &p, len, | ||
205 | - ASN1_ITEM_ptr(tt->item), -1, 0, 0, ctx)) { | ||
206 | + if (!asn1_item_ex_d2i(&skfield, &p, len, ASN1_ITEM_ptr(tt->item), | ||
207 | + -1, 0, 0, ctx, depth)) { | ||
208 | ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, | ||
209 | ERR_R_NESTED_ASN1_ERROR); | ||
210 | goto err; | ||
211 | @@ -684,9 +704,8 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, | ||
212 | } | ||
213 | } else if (flags & ASN1_TFLG_IMPTAG) { | ||
214 | /* IMPLICIT tagging */ | ||
215 | - ret = ASN1_item_ex_d2i(val, &p, len, | ||
216 | - ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt, | ||
217 | - ctx); | ||
218 | + ret = asn1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), tt->tag, | ||
219 | + aclass, opt, ctx, depth); | ||
220 | if (!ret) { | ||
221 | ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR); | ||
222 | goto err; | ||
223 | @@ -694,8 +713,9 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, | ||
224 | return -1; | ||
225 | } else { | ||
226 | /* Nothing special */ | ||
227 | - ret = ASN1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), | ||
228 | - -1, tt->flags & ASN1_TFLG_COMBINE, opt, ctx); | ||
229 | + ret = asn1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), | ||
230 | + -1, tt->flags & ASN1_TFLG_COMBINE, opt, ctx, | ||
231 | + depth); | ||
232 | if (!ret) { | ||
233 | ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR); | ||
234 | goto err; | ||
235 | -- | ||
236 | 1.9.1 | ||
237 | |||