summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjsing <>2022-05-16 20:06:15 +0000
committerjsing <>2022-05-16 20:06:15 +0000
commit4d98507bd8898b13bbd0d1ab339f3d35695e06a9 (patch)
tree95f318cdce39ad662a17e93c2e5311a2d519b9ff
parent45cb2e5d0a0ac3d63c3bf889071871b8de1f414e (diff)
downloadopenbsd-4d98507bd8898b13bbd0d1ab339f3d35695e06a9.tar.gz
openbsd-4d98507bd8898b13bbd0d1ab339f3d35695e06a9.tar.bz2
openbsd-4d98507bd8898b13bbd0d1ab339f3d35695e06a9.zip
Rewrite asn1_item_ex_d2i_sequence() using CBS and readable variable names.
Now that combine no longer exists, we can also free and reallocate. ok tb@
-rw-r--r--src/lib/libcrypto/asn1/tasn_dec.c244
1 files changed, 113 insertions, 131 deletions
diff --git a/src/lib/libcrypto/asn1/tasn_dec.c b/src/lib/libcrypto/asn1/tasn_dec.c
index 48ac38a883..744dde23c0 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.67 2022/05/12 20:06:46 jsing Exp $ */ 1/* $OpenBSD: tasn_dec.c,v 1.68 2022/05/16 20:06:15 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 */
@@ -129,13 +129,13 @@ asn1_item_ex_d2i_choice(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
129 int tag_number, int tag_class, char optional, int depth) 129 int tag_number, int tag_class, char optional, int depth)
130{ 130{
131 const ASN1_TEMPLATE *tt, *errtt = NULL; 131 const ASN1_TEMPLATE *tt, *errtt = NULL;
132 const ASN1_AUX *aux = it->funcs; 132 const ASN1_AUX *aux;
133 ASN1_aux_cb *asn1_cb = NULL; 133 ASN1_aux_cb *asn1_cb = NULL;
134 ASN1_VALUE *achoice = NULL; 134 ASN1_VALUE *achoice = NULL;
135 ASN1_VALUE **pchptr; 135 ASN1_VALUE **pchptr;
136 int i, ret; 136 int i, ret;
137 137
138 if (aux != NULL) 138 if ((aux = it->funcs) != NULL)
139 asn1_cb = aux->asn1_cb; 139 asn1_cb = aux->asn1_cb;
140 140
141 if (it->itype != ASN1_ITYPE_CHOICE) 141 if (it->itype != ASN1_ITYPE_CHOICE)
@@ -171,11 +171,8 @@ asn1_item_ex_d2i_choice(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
171 171
172 /* Mark field as OPTIONAL so its absence can be identified. */ 172 /* Mark field as OPTIONAL so its absence can be identified. */
173 ret = asn1_template_ex_d2i_cbs(pchptr, cbs, tt, 1, depth); 173 ret = asn1_template_ex_d2i_cbs(pchptr, cbs, tt, 1, depth);
174
175 /* If field not present, try the next one */
176 if (ret == -1) 174 if (ret == -1)
177 continue; 175 continue;
178
179 if (ret != 1) { 176 if (ret != 1) {
180 ASN1error(ERR_R_NESTED_ASN1_ERROR); 177 ASN1error(ERR_R_NESTED_ASN1_ERROR);
181 errtt = tt; 178 errtt = tt;
@@ -220,190 +217,175 @@ asn1_item_ex_d2i_choice(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
220} 217}
221 218
222static int 219static int
223asn1_item_ex_d2i_sequence(ASN1_VALUE **pval, const unsigned char **in, long len, 220asn1_item_ex_d2i_sequence(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
224 const ASN1_ITEM *it, int tag, int aclass, char opt, int depth) 221 int tag_number, int tag_class, char optional, int depth)
225{ 222{
226 const ASN1_TEMPLATE *tt, *errtt = NULL; 223 CBS cbs_seq, cbs_seq_content, cbs_object;
227 const ASN1_AUX *aux = it->funcs; 224 char constructed, indefinite, optional_field;
225 const ASN1_TEMPLATE *errtt = NULL;
226 const ASN1_TEMPLATE *seqtt, *tt;
228 ASN1_aux_cb *asn1_cb = NULL; 227 ASN1_aux_cb *asn1_cb = NULL;
229 char seq_eoc, seq_nolen, cst, isopt; 228 const ASN1_AUX *aux;
230 const unsigned char *p = NULL, *q; 229 ASN1_VALUE *aseq = NULL;
231 CBS cbs; 230 ASN1_VALUE **pseqval;
232 int i; 231 int eoc_needed, i;
232 size_t length;
233 int ret = 0; 233 int ret = 0;
234 234
235 CBS_init(&cbs_seq, CBS_data(cbs), CBS_len(cbs));
236
237 if ((aux = it->funcs) != NULL)
238 asn1_cb = aux->asn1_cb;
239
235 if (it->itype != ASN1_ITYPE_NDEF_SEQUENCE && 240 if (it->itype != ASN1_ITYPE_NDEF_SEQUENCE &&
236 it->itype != ASN1_ITYPE_SEQUENCE) 241 it->itype != ASN1_ITYPE_SEQUENCE)
237 goto err; 242 goto err;
238 243
239 if (aux && aux->asn1_cb) 244 if (*pval != NULL) {
240 asn1_cb = aux->asn1_cb; 245 ASN1_item_ex_free(pval, it);
241 246 *pval = NULL;
242 p = *in; 247 }
243 248
244 /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ 249 /* If no IMPLICIT tagging use UNIVERSAL/SEQUENCE. */
245 if (tag == -1) { 250 if (tag_number == -1) {
246 tag = V_ASN1_SEQUENCE; 251 tag_class = V_ASN1_UNIVERSAL;
247 aclass = V_ASN1_UNIVERSAL; 252 tag_number = V_ASN1_SEQUENCE;
248 } 253 }
249 /* Get SEQUENCE length and update len, p */ 254
250 ret = asn1_check_tag(&len, NULL, NULL, &seq_eoc, &cst, &p, len, 255 /* Read ASN.1 SEQUENCE header. */
251 tag, aclass, opt); 256 ret = asn1_check_tag_cbs(&cbs_seq, &length, NULL, NULL, &indefinite,
252 if (!ret) { 257 &constructed, tag_number, tag_class, optional);
258 if (ret == -1)
259 return -1;
260 if (ret != 1) {
253 ASN1error(ERR_R_NESTED_ASN1_ERROR); 261 ASN1error(ERR_R_NESTED_ASN1_ERROR);
254 goto err; 262 goto err;
255 } else if (ret == -1) 263 }
256 return -1; 264
257 seq_nolen = seq_eoc; 265 if (!constructed) {
258 if (!cst) {
259 ASN1error(ASN1_R_SEQUENCE_NOT_CONSTRUCTED); 266 ASN1error(ASN1_R_SEQUENCE_NOT_CONSTRUCTED);
260 goto err; 267 goto err;
261 } 268 }
262 269
263 if (!*pval && !ASN1_item_ex_new(pval, it)) { 270 if (indefinite) {
271 eoc_needed = 1;
272 CBS_init(&cbs_seq_content, CBS_data(&cbs_seq), CBS_len(&cbs_seq));
273 } else {
274 eoc_needed = 0;
275 if (!CBS_get_bytes(&cbs_seq, &cbs_seq_content, length))
276 goto err;
277 }
278
279 if (!ASN1_item_ex_new(&aseq, it)) {
264 ASN1error(ERR_R_NESTED_ASN1_ERROR); 280 ASN1error(ERR_R_NESTED_ASN1_ERROR);
265 goto err; 281 goto err;
266 } 282 }
267 283
268 if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) 284 if (asn1_cb != NULL && !asn1_cb(ASN1_OP_D2I_PRE, &aseq, it, NULL)) {
269 goto auxerr; 285 ASN1error(ASN1_R_AUX_ERROR);
270 286 goto err;
271 /* Free up and zero any ADB found */
272 for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
273 if (tt->flags & ASN1_TFLG_ADB_MASK) {
274 const ASN1_TEMPLATE *seqtt;
275 ASN1_VALUE **pseqval;
276 seqtt = asn1_do_adb(pval, tt, 1);
277 if (!seqtt)
278 goto err;
279 pseqval = asn1_get_field_ptr(pval, seqtt);
280 ASN1_template_free(pseqval, seqtt);
281 }
282 } 287 }
283 288
284 /* Get each field entry */
285 for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { 289 for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
286 const ASN1_TEMPLATE *seqtt; 290 if (asn1_check_eoc_cbs(&cbs_seq_content)) {
287 ASN1_VALUE **pseqval; 291 if (!indefinite) {
288 seqtt = asn1_do_adb(pval, tt, 1);
289 if (!seqtt)
290 goto err;
291 pseqval = asn1_get_field_ptr(pval, seqtt);
292 /* Have we ran out of data? */
293 if (!len)
294 break;
295 q = p;
296 if (asn1_check_eoc(&p, len)) {
297 if (!seq_eoc) {
298 ASN1error(ASN1_R_UNEXPECTED_EOC); 292 ASN1error(ASN1_R_UNEXPECTED_EOC);
299 goto err; 293 goto err;
300 } 294 }
301 len -= p - q; 295 eoc_needed = 0;
302 seq_eoc = 0;
303 q = p;
304 break; 296 break;
305 } 297 }
306 /* This determines the OPTIONAL flag value. The field 298 if (CBS_len(&cbs_seq_content) == 0)
307 * cannot be omitted if it is the last of a SEQUENCE 299 break;
308 * and there is still data to be read. This isn't 300
309 * strictly necessary but it increases efficiency in 301 if ((seqtt = asn1_do_adb(&aseq, tt, 1)) == NULL)
310 * some cases.
311 */
312 if (i == (it->tcount - 1))
313 isopt = 0;
314 else
315 isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL);
316 /* attempt to read in field, allowing each to be
317 * OPTIONAL */
318
319 ret = asn1_template_ex_d2i(pseqval, &p, len,
320 seqtt, isopt, depth);
321 if (!ret) {
322 errtt = seqtt;
323 goto err; 302 goto err;
324 } else if (ret == -1) { 303
325 /* OPTIONAL component absent. 304 pseqval = asn1_get_field_ptr(&aseq, seqtt);
326 * Free and zero the field. 305
327 */ 306 /*
307 * This was originally implemented to "increase efficiency",
308 * however it currently needs to remain since it papers over
309 * the use of ASN.1 ANY with OPTIONAL in SEQUENCEs (which
310 * asn1_d2i_ex_primitive() currently rejects).
311 */
312 optional_field = (seqtt->flags & ASN1_TFLG_OPTIONAL) != 0;
313 if (i == it->tcount - 1)
314 optional_field = 0;
315
316 ret = asn1_template_ex_d2i_cbs(pseqval, &cbs_seq_content,
317 seqtt, optional_field, depth);
318 if (ret == -1) {
319 /* Absent OPTIONAL component. */
328 ASN1_template_free(pseqval, seqtt); 320 ASN1_template_free(pseqval, seqtt);
329 continue; 321 continue;
330 } 322 }
331 /* Update length */ 323 if (ret != 1) {
332 len -= p - q; 324 errtt = seqtt;
325 goto err;
326 }
333 } 327 }
334 328
335 /* Check for EOC if expecting one */ 329 if (eoc_needed && !asn1_check_eoc_cbs(&cbs_seq_content)) {
336 if (seq_eoc && !asn1_check_eoc(&p, len)) {
337 ASN1error(ASN1_R_MISSING_EOC); 330 ASN1error(ASN1_R_MISSING_EOC);
338 goto err; 331 goto err;
339 } 332 }
340 /* Check all data read */ 333
341 if (!seq_nolen && len) { 334 if (indefinite) {
335 if (!CBS_skip(&cbs_seq, CBS_offset(&cbs_seq_content)))
336 goto err;
337 } else if (CBS_len(&cbs_seq_content) != 0) {
342 ASN1error(ASN1_R_SEQUENCE_LENGTH_MISMATCH); 338 ASN1error(ASN1_R_SEQUENCE_LENGTH_MISMATCH);
343 goto err; 339 goto err;
344 } 340 }
345 341
346 /* If we get here we've got no more data in the SEQUENCE, 342 /*
347 * however we may not have read all fields so check all 343 * There is no more data in the ASN.1 SEQUENCE, however we may not have
348 * remaining are OPTIONAL and clear any that are. 344 * populated all fields - check that any remaining are OPTIONAL.
349 */ 345 */
350 for (; i < it->tcount; tt++, i++) { 346 for (; i < it->tcount; tt++, i++) {
351 const ASN1_TEMPLATE *seqtt; 347 if ((seqtt = asn1_do_adb(&aseq, tt, 1)) == NULL)
352 seqtt = asn1_do_adb(pval, tt, 1);
353 if (!seqtt)
354 goto err; 348 goto err;
355 if (seqtt->flags & ASN1_TFLG_OPTIONAL) { 349
356 ASN1_VALUE **pseqval; 350 if ((seqtt->flags & ASN1_TFLG_OPTIONAL) == 0) {
357 pseqval = asn1_get_field_ptr(pval, seqtt);
358 ASN1_template_free(pseqval, seqtt);
359 } else {
360 errtt = seqtt;
361 ASN1error(ASN1_R_FIELD_MISSING); 351 ASN1error(ASN1_R_FIELD_MISSING);
352 errtt = seqtt;
362 goto err; 353 goto err;
363 } 354 }
355
356 /* XXX - this is probably unnecessary with earlier free. */
357 pseqval = asn1_get_field_ptr(&aseq, seqtt);
358 ASN1_template_free(pseqval, seqtt);
364 } 359 }
365 /* Save encoding */ 360
366 CBS_init(&cbs, *in, p - *in); 361 if (!CBS_get_bytes(cbs, &cbs_object, CBS_offset(&cbs_seq)))
367 if (!asn1_enc_save(pval, &cbs, it)) { 362 goto err;
363
364 if (!asn1_enc_save(&aseq, &cbs_object, it)) {
368 ASN1error(ERR_R_MALLOC_FAILURE); 365 ASN1error(ERR_R_MALLOC_FAILURE);
369 goto err; 366 goto err;
370 } 367 }
371 *in = p; 368
372 if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) 369 if (asn1_cb != NULL && !asn1_cb(ASN1_OP_D2I_POST, &aseq, it, NULL)) {
373 goto auxerr; 370 ASN1error(ASN1_R_AUX_ERROR);
371 goto err;
372 }
373
374 *pval = aseq;
375 aseq = NULL;
376
374 return 1; 377 return 1;
375 378
376 auxerr:
377 ASN1error(ASN1_R_AUX_ERROR);
378 err: 379 err:
379 ASN1_item_ex_free(pval, it); 380 ASN1_item_ex_free(&aseq, it);
380 381
381 if (errtt) 382 if (errtt != NULL)
382 ERR_asprintf_error_data("Field=%s, Type=%s", errtt->field_name, 383 ERR_asprintf_error_data("Field=%s, Type=%s", errtt->field_name,
383 it->sname); 384 it->sname);
384 else 385 else
385 ERR_asprintf_error_data("Type=%s", it->sname); 386 ERR_asprintf_error_data("Type=%s", it->sname);
386 return 0;
387}
388 387
389static int 388 return 0;
390asn1_item_ex_d2i_sequence_cbs(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
391 int tag_number, int tag_class, char optional, int depth)
392{
393 const unsigned char *p;
394 int ret;
395
396 if (CBS_len(cbs) > LONG_MAX)
397 return 0;
398
399 p = CBS_data(cbs);
400 ret = asn1_item_ex_d2i_sequence(pval, &p, (long)CBS_len(cbs), it,
401 tag_number, tag_class, optional, depth);
402 if (ret == 1) {
403 if (!CBS_skip(cbs, p - CBS_data(cbs)))
404 return 0;
405 }
406 return ret;
407} 389}
408 390
409/* 391/*
@@ -502,7 +484,7 @@ asn1_item_ex_d2i_cbs(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
502 484
503 case ASN1_ITYPE_NDEF_SEQUENCE: 485 case ASN1_ITYPE_NDEF_SEQUENCE:
504 case ASN1_ITYPE_SEQUENCE: 486 case ASN1_ITYPE_SEQUENCE:
505 return asn1_item_ex_d2i_sequence_cbs(pval, cbs, it, tag_number, 487 return asn1_item_ex_d2i_sequence(pval, cbs, it, tag_number,
506 tag_class, optional, depth); 488 tag_class, optional, depth);
507 489
508 default: 490 default: