|
20 | 20 | #include <CCryptoBoringSSL_bytestring.h> |
21 | 21 | #include <CCryptoBoringSSL_err.h> |
22 | 22 | #include <CCryptoBoringSSL_mem.h> |
| 23 | +#include <CCryptoBoringSSL_span.h> |
23 | 24 |
|
24 | 25 | #include "../internal.h" |
25 | 26 | #include "internal.h" |
@@ -110,76 +111,96 @@ int asn1_marshal_bit_string(CBB *out, const ASN1_BIT_STRING *in, |
110 | 111 | CBB_flush(out); |
111 | 112 | } |
112 | 113 |
|
113 | | -ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, |
114 | | - const unsigned char **pp, long len) { |
115 | | - ASN1_BIT_STRING *ret = NULL; |
116 | | - const unsigned char *p; |
117 | | - unsigned char *s; |
118 | | - int padding; |
119 | | - uint8_t padding_mask; |
120 | | - |
121 | | - if (len < 1) { |
| 114 | +static int asn1_parse_bit_string_contents(bssl::Span<const uint8_t> in, |
| 115 | + ASN1_BIT_STRING *out) { |
| 116 | + CBS cbs = in; |
| 117 | + uint8_t padding; |
| 118 | + if (!CBS_get_u8(&cbs, &padding)) { |
122 | 119 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT); |
123 | | - goto err; |
| 120 | + return 0; |
124 | 121 | } |
125 | 122 |
|
126 | | - if (len > INT_MAX) { |
127 | | - OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG); |
128 | | - goto err; |
| 123 | + if (padding > 7) { |
| 124 | + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT); |
| 125 | + return 0; |
129 | 126 | } |
130 | 127 |
|
131 | | - if ((a == NULL) || ((*a) == NULL)) { |
132 | | - if ((ret = ASN1_BIT_STRING_new()) == NULL) { |
133 | | - return NULL; |
| 128 | + // Unused bits in a BIT STRING must be zero. |
| 129 | + uint8_t padding_mask = (1 << padding) - 1; |
| 130 | + if (padding != 0) { |
| 131 | + CBS copy = cbs; |
| 132 | + uint8_t last; |
| 133 | + if (!CBS_get_last_u8(©, &last) || (last & padding_mask) != 0) { |
| 134 | + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_PADDING); |
| 135 | + return 0; |
134 | 136 | } |
135 | | - } else { |
136 | | - ret = (*a); |
137 | 137 | } |
138 | 138 |
|
139 | | - p = *pp; |
140 | | - padding = *(p++); |
141 | | - len--; |
142 | | - if (padding > 7) { |
143 | | - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT); |
144 | | - goto err; |
| 139 | + if (!ASN1_STRING_set(out, CBS_data(&cbs), CBS_len(&cbs))) { |
| 140 | + return 0; |
145 | 141 | } |
146 | 142 |
|
147 | | - // Unused bits in a BIT STRING must be zero. |
148 | | - padding_mask = (1 << padding) - 1; |
149 | | - if (padding != 0 && (len < 1 || (p[len - 1] & padding_mask) != 0)) { |
150 | | - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_PADDING); |
151 | | - goto err; |
152 | | - } |
| 143 | + out->type = V_ASN1_BIT_STRING; |
| 144 | + // |ASN1_STRING_FLAG_BITS_LEFT| and the bottom 3 bits encode |padding|. |
| 145 | + out->flags &= ~0x07; |
| 146 | + out->flags |= ASN1_STRING_FLAG_BITS_LEFT | padding; |
| 147 | + return 1; |
| 148 | +} |
153 | 149 |
|
154 | | - // We do this to preserve the settings. If we modify the settings, via |
155 | | - // the _set_bit function, we will recalculate on output |
156 | | - ret->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); // clear |
157 | | - ret->flags |= (ASN1_STRING_FLAG_BITS_LEFT | padding); // set |
| 150 | +ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, |
| 151 | + const unsigned char **pp, long len) { |
| 152 | + if (len < 0) { |
| 153 | + OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT); |
| 154 | + return nullptr; |
| 155 | + } |
158 | 156 |
|
159 | | - if (len > 0) { |
160 | | - s = reinterpret_cast<uint8_t *>(OPENSSL_memdup(p, len)); |
161 | | - if (s == NULL) { |
162 | | - goto err; |
| 157 | + ASN1_BIT_STRING *ret = nullptr; |
| 158 | + if (a == nullptr || *a == nullptr) { |
| 159 | + if ((ret = ASN1_BIT_STRING_new()) == nullptr) { |
| 160 | + return nullptr; |
163 | 161 | } |
164 | | - p += len; |
165 | 162 | } else { |
166 | | - s = NULL; |
| 163 | + ret = *a; |
167 | 164 | } |
168 | 165 |
|
169 | | - ret->length = (int)len; |
170 | | - OPENSSL_free(ret->data); |
171 | | - ret->data = s; |
172 | | - ret->type = V_ASN1_BIT_STRING; |
173 | | - if (a != NULL) { |
174 | | - (*a) = ret; |
| 166 | + if (!asn1_parse_bit_string_contents(bssl::Span(*pp, len), ret)) { |
| 167 | + if (ret != nullptr && (a == nullptr || *a != ret)) { |
| 168 | + ASN1_BIT_STRING_free(ret); |
| 169 | + } |
| 170 | + return nullptr; |
175 | 171 | } |
176 | | - *pp = p; |
| 172 | + |
| 173 | + if (a != nullptr) { |
| 174 | + *a = ret; |
| 175 | + } |
| 176 | + *pp += len; |
177 | 177 | return ret; |
178 | | -err: |
179 | | - if ((ret != NULL) && ((a == NULL) || (*a != ret))) { |
180 | | - ASN1_BIT_STRING_free(ret); |
| 178 | +} |
| 179 | + |
| 180 | +int asn1_parse_bit_string(CBS *cbs, ASN1_BIT_STRING *out, CBS_ASN1_TAG tag) { |
| 181 | + tag = tag == 0 ? CBS_ASN1_BITSTRING : tag; |
| 182 | + CBS child; |
| 183 | + if (!CBS_get_asn1(cbs, &child, tag)) { |
| 184 | + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); |
| 185 | + return 0; |
| 186 | + } |
| 187 | + return asn1_parse_bit_string_contents(child, out); |
| 188 | +} |
| 189 | + |
| 190 | +int asn1_parse_bit_string_with_bad_length(CBS *cbs, ASN1_BIT_STRING *out) { |
| 191 | + CBS child; |
| 192 | + CBS_ASN1_TAG tag; |
| 193 | + size_t header_len; |
| 194 | + int indefinite; |
| 195 | + if (!CBS_get_any_ber_asn1_element(cbs, &child, &tag, &header_len, |
| 196 | + /*out_ber_found=*/nullptr, |
| 197 | + &indefinite) || |
| 198 | + tag != CBS_ASN1_BITSTRING || indefinite || // |
| 199 | + !CBS_skip(&child, header_len)) { |
| 200 | + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); |
| 201 | + return 0; |
181 | 202 | } |
182 | | - return NULL; |
| 203 | + return asn1_parse_bit_string_contents(child, out); |
183 | 204 | } |
184 | 205 |
|
185 | 206 | // These next 2 functions from Goetz Babin-Ebell <babinebell@trustcenter.de> |
|
0 commit comments