summaryrefslogtreecommitdiff
path: root/src/lib/libssl/bs_ber.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libssl/bs_ber.c')
-rw-r--r--src/lib/libssl/bs_ber.c26
1 files changed, 19 insertions, 7 deletions
diff --git a/src/lib/libssl/bs_ber.c b/src/lib/libssl/bs_ber.c
index 2ec91fc800..3d39def111 100644
--- a/src/lib/libssl/bs_ber.c
+++ b/src/lib/libssl/bs_ber.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: bs_ber.c,v 1.4 2015/04/29 02:11:09 doug Exp $ */ 1/* $OpenBSD: bs_ber.c,v 1.5 2015/06/15 07:35:49 doug Exp $ */
2/* 2/*
3 * Copyright (c) 2014, Google Inc. 3 * Copyright (c) 2014, Google Inc.
4 * 4 *
@@ -27,6 +27,15 @@
27 */ 27 */
28static const unsigned kMaxDepth = 2048; 28static const unsigned kMaxDepth = 2048;
29 29
30/* Non-strict version that allows a relaxed DER with indefinite form. */
31static int
32cbs_nonstrict_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
33 size_t *out_header_len)
34{
35 return cbs_get_any_asn1_element_internal(cbs, out,
36 out_tag, out_header_len, 0);
37}
38
30/* 39/*
31 * cbs_find_ber walks an ASN.1 structure in |orig_in| and sets |*ber_found| 40 * cbs_find_ber walks an ASN.1 structure in |orig_in| and sets |*ber_found|
32 * depending on whether an indefinite length element was found. The value of 41 * depending on whether an indefinite length element was found. The value of
@@ -49,10 +58,11 @@ cbs_find_ber(CBS *orig_in, char *ber_found, unsigned depth)
49 unsigned tag; 58 unsigned tag;
50 size_t header_len; 59 size_t header_len;
51 60
52 if (!CBS_get_any_asn1_element(&in, &contents, &tag, 61 if (!cbs_nonstrict_get_any_asn1_element(&in, &contents, &tag,
53 &header_len)) 62 &header_len))
54 return 0; 63 return 0;
55 64
65 /* Indefinite form not allowed by DER. */
56 if (CBS_len(&contents) == header_len && header_len > 0 && 66 if (CBS_len(&contents) == header_len && header_len > 0 &&
57 CBS_data(&contents)[header_len - 1] == 0x80) { 67 CBS_data(&contents)[header_len - 1] == 0x80) {
58 *ber_found = 1; 68 *ber_found = 1;
@@ -84,7 +94,8 @@ is_primitive_type(unsigned tag)
84 94
85/* 95/*
86 * is_eoc returns true if |header_len| and |contents|, as returned by 96 * is_eoc returns true if |header_len| and |contents|, as returned by
87 * |CBS_get_any_asn1_element|, indicate an "end of contents" (EOC) value. 97 * |cbs_nonstrict_get_any_asn1_element|, indicate an "end of contents" (EOC)
98 * value.
88 */ 99 */
89static char 100static char
90is_eoc(size_t header_len, CBS *contents) 101is_eoc(size_t header_len, CBS *contents)
@@ -113,7 +124,8 @@ cbs_convert_ber(CBS *in, CBB *out, char squash_header, char looking_for_eoc,
113 size_t header_len; 124 size_t header_len;
114 CBB *out_contents, out_contents_storage; 125 CBB *out_contents, out_contents_storage;
115 126
116 if (!CBS_get_any_asn1_element(in, &contents, &tag, &header_len)) 127 if (!cbs_nonstrict_get_any_asn1_element(in, &contents, &tag,
128 &header_len))
117 return 0; 129 return 0;
118 130
119 out_contents = out; 131 out_contents = out;
@@ -156,9 +168,9 @@ cbs_convert_ber(CBS *in, CBB *out, char squash_header, char looking_for_eoc,
156 168
157 CBS_init(&in_copy, CBS_data(in), 169 CBS_init(&in_copy, CBS_data(in),
158 CBS_len(in)); 170 CBS_len(in));
159 if (!CBS_get_any_asn1_element(&in_copy, 171 if (!cbs_nonstrict_get_any_asn1_element(
160 &inner_contents, &inner_tag, 172 &in_copy, &inner_contents,
161 &inner_header_len)) 173 &inner_tag, &inner_header_len))
162 return 0; 174 return 0;
163 175
164 if (CBS_len(&inner_contents) > 176 if (CBS_len(&inner_contents) >