summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorinoguchi <>2018-03-29 02:29:24 +0000
committerinoguchi <>2018-03-29 02:29:24 +0000
commit85b83d75a71cd280d1ffd7aa6bbbbb7154a8ffc4 (patch)
treef9b6bdd41ab07ed56e7beeeb034e6db74420d3ea
parent46b5d933b38b75b127fede5f1fa076d84c7714a1 (diff)
downloadopenbsd-85b83d75a71cd280d1ffd7aa6bbbbb7154a8ffc4.tar.gz
openbsd-85b83d75a71cd280d1ffd7aa6bbbbb7154a8ffc4.tar.bz2
openbsd-85b83d75a71cd280d1ffd7aa6bbbbb7154a8ffc4.zip
Limit ASN.1 constructed types recursive definition depth
Fixes for CVE-2018-0739. Copied from commit below, and modified for adaption to our code. https://github.com/openssl/openssl/commit/9310d45087ae546e27e61ddf8f6367f29848220d ok bcook@ beck@ jsing@
-rw-r--r--src/lib/libcrypto/asn1/asn1.h3
-rw-r--r--src/lib/libcrypto/asn1/asn1_err.c3
-rw-r--r--src/lib/libcrypto/asn1/tasn_dec.c61
3 files changed, 45 insertions, 22 deletions
diff --git a/src/lib/libcrypto/asn1/asn1.h b/src/lib/libcrypto/asn1/asn1.h
index 6fc4cd7527..3a2da6463e 100644
--- a/src/lib/libcrypto/asn1/asn1.h
+++ b/src/lib/libcrypto/asn1/asn1.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: asn1.h,v 1.44 2018/02/14 16:46:04 jsing Exp $ */ 1/* $OpenBSD: asn1.h,v 1.45 2018/03/29 02:29:24 inoguchi Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -1405,6 +1405,7 @@ void ERR_load_ASN1_strings(void);
1405#define ASN1_R_MSTRING_NOT_UNIVERSAL 139 1405#define ASN1_R_MSTRING_NOT_UNIVERSAL 139
1406#define ASN1_R_MSTRING_WRONG_TAG 140 1406#define ASN1_R_MSTRING_WRONG_TAG 140
1407#define ASN1_R_NESTED_ASN1_STRING 197 1407#define ASN1_R_NESTED_ASN1_STRING 197
1408#define ASN1_R_NESTED_TOO_DEEP 219
1408#define ASN1_R_NON_HEX_CHARACTERS 141 1409#define ASN1_R_NON_HEX_CHARACTERS 141
1409#define ASN1_R_NOT_ASCII_FORMAT 190 1410#define ASN1_R_NOT_ASCII_FORMAT 190
1410#define ASN1_R_NOT_ENOUGH_DATA 142 1411#define ASN1_R_NOT_ENOUGH_DATA 142
diff --git a/src/lib/libcrypto/asn1/asn1_err.c b/src/lib/libcrypto/asn1/asn1_err.c
index 0c827a9236..5cc355084f 100644
--- a/src/lib/libcrypto/asn1/asn1_err.c
+++ b/src/lib/libcrypto/asn1/asn1_err.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: asn1_err.c,v 1.20 2017/01/29 17:49:22 beck Exp $ */ 1/* $OpenBSD: asn1_err.c,v 1.21 2018/03/29 02:29:24 inoguchi Exp $ */
2/* ==================================================================== 2/* ====================================================================
3 * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved. 3 * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved.
4 * 4 *
@@ -150,6 +150,7 @@ static ERR_STRING_DATA ASN1_str_reasons[] = {
150 {ERR_REASON(ASN1_R_MSTRING_NOT_UNIVERSAL), "mstring not universal"}, 150 {ERR_REASON(ASN1_R_MSTRING_NOT_UNIVERSAL), "mstring not universal"},
151 {ERR_REASON(ASN1_R_MSTRING_WRONG_TAG) , "mstring wrong tag"}, 151 {ERR_REASON(ASN1_R_MSTRING_WRONG_TAG) , "mstring wrong tag"},
152 {ERR_REASON(ASN1_R_NESTED_ASN1_STRING) , "nested asn1 string"}, 152 {ERR_REASON(ASN1_R_NESTED_ASN1_STRING) , "nested asn1 string"},
153 {ERR_REASON(ASN1_R_NESTED_TOO_DEEP) , "nested too deep"},
153 {ERR_REASON(ASN1_R_NON_HEX_CHARACTERS) , "non hex characters"}, 154 {ERR_REASON(ASN1_R_NON_HEX_CHARACTERS) , "non hex characters"},
154 {ERR_REASON(ASN1_R_NOT_ASCII_FORMAT) , "not ascii format"}, 155 {ERR_REASON(ASN1_R_NOT_ASCII_FORMAT) , "not ascii format"},
155 {ERR_REASON(ASN1_R_NOT_ENOUGH_DATA) , "not enough data"}, 156 {ERR_REASON(ASN1_R_NOT_ENOUGH_DATA) , "not enough data"},
diff --git a/src/lib/libcrypto/asn1/tasn_dec.c b/src/lib/libcrypto/asn1/tasn_dec.c
index 3f680c60fd..bf536cb667 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.34 2017/01/29 17:49:22 beck Exp $ */ 1/* $OpenBSD: tasn_dec.c,v 1.35 2018/03/29 02:29:24 inoguchi 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 */
@@ -65,6 +65,12 @@
65#include <openssl/buffer.h> 65#include <openssl/buffer.h>
66#include <openssl/err.h> 66#include <openssl/err.h>
67 67
68/* Constructed types with a recursive definition (such as can be found in PKCS7)
69 * could eventually exceed the stack given malicious input with excessive
70 * recursion. Therefore we limit the stack depth.
71 */
72#define ASN1_MAX_CONSTRUCTED_NEST 30
73
68static int asn1_check_eoc(const unsigned char **in, long len); 74static int asn1_check_eoc(const unsigned char **in, long len);
69static int asn1_find_end(const unsigned char **in, long len, char inf); 75static int asn1_find_end(const unsigned char **in, long len, char inf);
70 76
@@ -78,9 +84,9 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
78 int expclass, char opt, ASN1_TLC *ctx); 84 int expclass, char opt, ASN1_TLC *ctx);
79 85
80static int asn1_template_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, 86static int asn1_template_ex_d2i(ASN1_VALUE **pval, const unsigned char **in,
81 long len, const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx); 87 long len, const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx, int depth);
82static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, 88static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in,
83 long len, const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx); 89 long len, const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx, int depth);
84static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, 90static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in,
85 long len, const ASN1_ITEM *it, int tag, int aclass, char opt, 91 long len, const ASN1_ITEM *it, int tag, int aclass, char opt,
86 ASN1_TLC *ctx); 92 ASN1_TLC *ctx);
@@ -142,7 +148,7 @@ ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
142 ASN1_TLC c; 148 ASN1_TLC c;
143 149
144 asn1_tlc_clear_nc(&c); 150 asn1_tlc_clear_nc(&c);
145 return asn1_template_ex_d2i(pval, in, len, tt, 0, &c); 151 return asn1_template_ex_d2i(pval, in, len, tt, 0, &c, 0);
146} 152}
147 153
148 154
@@ -150,9 +156,10 @@ ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
150 * If 'opt' set and tag mismatch return -1 to handle OPTIONAL 156 * If 'opt' set and tag mismatch return -1 to handle OPTIONAL
151 */ 157 */
152 158
153int 159static int
154ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, 160asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
155 const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx) 161 const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx,
162 int depth)
156{ 163{
157 const ASN1_TEMPLATE *tt, *errtt = NULL; 164 const ASN1_TEMPLATE *tt, *errtt = NULL;
158 const ASN1_EXTERN_FUNCS *ef; 165 const ASN1_EXTERN_FUNCS *ef;
@@ -179,6 +186,11 @@ ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
179 else 186 else
180 asn1_cb = 0; 187 asn1_cb = 0;
181 188
189 if (++depth > ASN1_MAX_CONSTRUCTED_NEST) {
190 ASN1error(ASN1_R_NESTED_TOO_DEEP);
191 goto err;
192 }
193
182 switch (it->itype) { 194 switch (it->itype) {
183 case ASN1_ITYPE_PRIMITIVE: 195 case ASN1_ITYPE_PRIMITIVE:
184 if (it->templates) { 196 if (it->templates) {
@@ -193,7 +205,7 @@ ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
193 goto err; 205 goto err;
194 } 206 }
195 return asn1_template_ex_d2i(pval, in, len, 207 return asn1_template_ex_d2i(pval, in, len,
196 it->templates, opt, ctx); 208 it->templates, opt, ctx, depth);
197 } 209 }
198 return asn1_d2i_ex_primitive(pval, in, len, it, 210 return asn1_d2i_ex_primitive(pval, in, len, it,
199 tag, aclass, opt, ctx); 211 tag, aclass, opt, ctx);
@@ -258,7 +270,8 @@ ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
258 /* We mark field as OPTIONAL so its absence 270 /* We mark field as OPTIONAL so its absence
259 * can be recognised. 271 * can be recognised.
260 */ 272 */
261 ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx); 273 ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx,
274 depth);
262 /* If field not present, try the next one */ 275 /* If field not present, try the next one */
263 if (ret == -1) 276 if (ret == -1)
264 continue; 277 continue;
@@ -376,7 +389,7 @@ ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
376 * OPTIONAL */ 389 * OPTIONAL */
377 390
378 ret = asn1_template_ex_d2i(pseqval, &p, len, 391 ret = asn1_template_ex_d2i(pseqval, &p, len,
379 seqtt, isopt, ctx); 392 seqtt, isopt, ctx, depth);
380 if (!ret) { 393 if (!ret) {
381 errtt = seqtt; 394 errtt = seqtt;
382 goto err; 395 goto err;
@@ -448,13 +461,20 @@ err:
448 return 0; 461 return 0;
449} 462}
450 463
464int
465ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
466 const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx)
467{
468 return asn1_item_ex_d2i(pval, in, len, it, tag, aclass, opt, ctx, 0);
469}
470
451/* Templates are handled with two separate functions. 471/* Templates are handled with two separate functions.
452 * One handles any EXPLICIT tag and the other handles the rest. 472 * One handles any EXPLICIT tag and the other handles the rest.
453 */ 473 */
454 474
455static int 475static int
456asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen, 476asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen,
457 const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx) 477 const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx, int depth)
458{ 478{
459 int flags, aclass; 479 int flags, aclass;
460 int ret; 480 int ret;
@@ -489,7 +509,7 @@ asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen,
489 return 0; 509 return 0;
490 } 510 }
491 /* We've found the field so it can't be OPTIONAL now */ 511 /* We've found the field so it can't be OPTIONAL now */
492 ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx); 512 ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx, depth);
493 if (!ret) { 513 if (!ret) {
494 ASN1error(ERR_R_NESTED_ASN1_ERROR); 514 ASN1error(ERR_R_NESTED_ASN1_ERROR);
495 return 0; 515 return 0;
@@ -511,7 +531,8 @@ asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen,
511 } 531 }
512 } 532 }
513 } else 533 } else
514 return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx); 534 return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx,
535 depth);
515 536
516 *in = p; 537 *in = p;
517 return 1; 538 return 1;
@@ -523,7 +544,7 @@ err:
523 544
524static int 545static int
525asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, 546asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len,
526 const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx) 547 const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx, int depth)
527{ 548{
528 int flags, aclass; 549 int flags, aclass;
529 int ret; 550 int ret;
@@ -594,8 +615,8 @@ asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len,
594 break; 615 break;
595 } 616 }
596 skfield = NULL; 617 skfield = NULL;
597 if (!ASN1_item_ex_d2i(&skfield, &p, len, 618 if (!asn1_item_ex_d2i(&skfield, &p, len,
598 tt->item, -1, 0, 0, ctx)) { 619 tt->item, -1, 0, 0, ctx, depth)) {
599 ASN1error(ERR_R_NESTED_ASN1_ERROR); 620 ASN1error(ERR_R_NESTED_ASN1_ERROR);
600 goto err; 621 goto err;
601 } 622 }
@@ -612,8 +633,8 @@ asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len,
612 } 633 }
613 } else if (flags & ASN1_TFLG_IMPTAG) { 634 } else if (flags & ASN1_TFLG_IMPTAG) {
614 /* IMPLICIT tagging */ 635 /* IMPLICIT tagging */
615 ret = ASN1_item_ex_d2i(val, &p, len, 636 ret = asn1_item_ex_d2i(val, &p, len,
616 tt->item, tt->tag, aclass, opt, ctx); 637 tt->item, tt->tag, aclass, opt, ctx, depth);
617 if (!ret) { 638 if (!ret) {
618 ASN1error(ERR_R_NESTED_ASN1_ERROR); 639 ASN1error(ERR_R_NESTED_ASN1_ERROR);
619 goto err; 640 goto err;
@@ -621,8 +642,8 @@ asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len,
621 return -1; 642 return -1;
622 } else { 643 } else {
623 /* Nothing special */ 644 /* Nothing special */
624 ret = ASN1_item_ex_d2i(val, &p, len, tt->item, 645 ret = asn1_item_ex_d2i(val, &p, len, tt->item,
625 -1, tt->flags & ASN1_TFLG_COMBINE, opt, ctx); 646 -1, tt->flags & ASN1_TFLG_COMBINE, opt, ctx, depth);
626 if (!ret) { 647 if (!ret) {
627 ASN1error(ERR_R_NESTED_ASN1_ERROR); 648 ASN1error(ERR_R_NESTED_ASN1_ERROR);
628 goto err; 649 goto err;