diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libcrypto/asn1/tasn_dec.c | 510 |
1 files changed, 287 insertions, 223 deletions
diff --git a/src/lib/libcrypto/asn1/tasn_dec.c b/src/lib/libcrypto/asn1/tasn_dec.c index 3cc2146e45..f9c5fa81b8 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.60 2022/05/07 10:13:56 jsing Exp $ */ | 1 | /* $OpenBSD: tasn_dec.c,v 1.61 2022/05/07 15:50:25 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 | */ |
@@ -121,38 +121,305 @@ ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | |||
121 | return asn1_template_ex_d2i(pval, in, len, tt, 0, 0); | 121 | return asn1_template_ex_d2i(pval, in, len, tt, 0, 0); |
122 | } | 122 | } |
123 | 123 | ||
124 | /* Decode an item, taking care of IMPLICIT tagging, if any. | 124 | static int |
125 | * If 'opt' set and tag mismatch return -1 to handle OPTIONAL | 125 | asn1_item_ex_d2i_choice(ASN1_VALUE **pval, const unsigned char **in, long len, |
126 | */ | 126 | const ASN1_ITEM *it, int tag, int aclass, char opt, int depth) |
127 | { | ||
128 | const ASN1_TEMPLATE *tt, *errtt = NULL; | ||
129 | const ASN1_AUX *aux = it->funcs; | ||
130 | ASN1_aux_cb *asn1_cb = NULL; | ||
131 | ASN1_VALUE **pchptr; | ||
132 | const unsigned char *p = NULL; | ||
133 | int i; | ||
134 | int ret = 0; | ||
135 | int combine; | ||
136 | |||
137 | combine = aclass & ASN1_TFLG_COMBINE; | ||
138 | aclass &= ~ASN1_TFLG_COMBINE; | ||
139 | |||
140 | if (it->itype != ASN1_ITYPE_CHOICE) | ||
141 | goto err; | ||
142 | |||
143 | if (aux && aux->asn1_cb) | ||
144 | asn1_cb = aux->asn1_cb; | ||
145 | |||
146 | /* | ||
147 | * It never makes sense for CHOICE types to have implicit | ||
148 | * tagging, so if tag != -1, then this looks like an error in | ||
149 | * the template. | ||
150 | */ | ||
151 | if (tag != -1) { | ||
152 | ASN1error(ASN1_R_BAD_TEMPLATE); | ||
153 | goto err; | ||
154 | } | ||
155 | |||
156 | if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) | ||
157 | goto auxerr; | ||
158 | |||
159 | if (*pval) { | ||
160 | /* Free up and zero CHOICE value if initialised */ | ||
161 | i = asn1_get_choice_selector(pval, it); | ||
162 | if ((i >= 0) && (i < it->tcount)) { | ||
163 | tt = it->templates + i; | ||
164 | pchptr = asn1_get_field_ptr(pval, tt); | ||
165 | ASN1_template_free(pchptr, tt); | ||
166 | asn1_set_choice_selector(pval, -1, it); | ||
167 | } | ||
168 | } else if (!ASN1_item_ex_new(pval, it)) { | ||
169 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
170 | goto err; | ||
171 | } | ||
172 | /* CHOICE type, try each possibility in turn */ | ||
173 | p = *in; | ||
174 | for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { | ||
175 | pchptr = asn1_get_field_ptr(pval, tt); | ||
176 | /* We mark field as OPTIONAL so its absence | ||
177 | * can be recognised. | ||
178 | */ | ||
179 | ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, | ||
180 | depth); | ||
181 | /* If field not present, try the next one */ | ||
182 | if (ret == -1) | ||
183 | continue; | ||
184 | /* If positive return, read OK, break loop */ | ||
185 | if (ret > 0) | ||
186 | break; | ||
187 | /* Otherwise must be an ASN1 parsing error */ | ||
188 | errtt = tt; | ||
189 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
190 | goto err; | ||
191 | } | ||
192 | |||
193 | /* Did we fall off the end without reading anything? */ | ||
194 | if (i == it->tcount) { | ||
195 | /* If OPTIONAL, this is OK */ | ||
196 | if (opt) { | ||
197 | /* Free and zero it */ | ||
198 | ASN1_item_ex_free(pval, it); | ||
199 | return -1; | ||
200 | } | ||
201 | ASN1error(ASN1_R_NO_MATCHING_CHOICE_TYPE); | ||
202 | goto err; | ||
203 | } | ||
204 | |||
205 | asn1_set_choice_selector(pval, i, it); | ||
206 | *in = p; | ||
207 | if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) | ||
208 | goto auxerr; | ||
209 | return 1; | ||
210 | |||
211 | auxerr: | ||
212 | ASN1error(ASN1_R_AUX_ERROR); | ||
213 | err: | ||
214 | if (combine == 0) | ||
215 | ASN1_item_ex_free(pval, it); | ||
216 | if (errtt) | ||
217 | ERR_asprintf_error_data("Field=%s, Type=%s", errtt->field_name, | ||
218 | it->sname); | ||
219 | else | ||
220 | ERR_asprintf_error_data("Type=%s", it->sname); | ||
221 | return 0; | ||
222 | } | ||
127 | 223 | ||
128 | static int | 224 | static int |
129 | asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | 225 | asn1_item_ex_d2i_sequence(ASN1_VALUE **pval, const unsigned char **in, long len, |
130 | const ASN1_ITEM *it, int tag, int aclass, char opt, int depth) | 226 | const ASN1_ITEM *it, int tag, int aclass, char opt, int depth) |
131 | { | 227 | { |
132 | const ASN1_TEMPLATE *tt, *errtt = NULL; | 228 | const ASN1_TEMPLATE *tt, *errtt = NULL; |
133 | const ASN1_EXTERN_FUNCS *ef; | ||
134 | const ASN1_AUX *aux = it->funcs; | 229 | const ASN1_AUX *aux = it->funcs; |
135 | ASN1_aux_cb *asn1_cb = NULL; | 230 | ASN1_aux_cb *asn1_cb = NULL; |
136 | ASN1_TLC ctx = { 0 }; | ||
137 | const unsigned char *p = NULL, *q; | ||
138 | unsigned char oclass; | ||
139 | char seq_eoc, seq_nolen, cst, isopt; | 231 | char seq_eoc, seq_nolen, cst, isopt; |
232 | const unsigned char *p = NULL, *q; | ||
140 | long tmplen; | 233 | long tmplen; |
141 | int i; | 234 | int i; |
142 | int otag; | ||
143 | int ret = 0; | 235 | int ret = 0; |
144 | ASN1_VALUE **pchptr; | ||
145 | int combine; | 236 | int combine; |
146 | 237 | ||
147 | combine = aclass & ASN1_TFLG_COMBINE; | 238 | combine = aclass & ASN1_TFLG_COMBINE; |
148 | aclass &= ~ASN1_TFLG_COMBINE; | 239 | aclass &= ~ASN1_TFLG_COMBINE; |
149 | 240 | ||
150 | if (!pval) | 241 | if (it->itype != ASN1_ITYPE_NDEF_SEQUENCE && |
151 | return 0; | 242 | it->itype != ASN1_ITYPE_SEQUENCE) |
243 | goto err; | ||
152 | 244 | ||
153 | if (aux && aux->asn1_cb) | 245 | if (aux && aux->asn1_cb) |
154 | asn1_cb = aux->asn1_cb; | 246 | asn1_cb = aux->asn1_cb; |
155 | 247 | ||
248 | p = *in; | ||
249 | tmplen = len; | ||
250 | |||
251 | /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ | ||
252 | if (tag == -1) { | ||
253 | tag = V_ASN1_SEQUENCE; | ||
254 | aclass = V_ASN1_UNIVERSAL; | ||
255 | } | ||
256 | /* Get SEQUENCE length and update len, p */ | ||
257 | ret = asn1_check_tag(&len, NULL, NULL, &seq_eoc, &cst, &p, len, | ||
258 | tag, aclass, opt); | ||
259 | if (!ret) { | ||
260 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
261 | goto err; | ||
262 | } else if (ret == -1) | ||
263 | return -1; | ||
264 | if (aux && (aux->flags & ASN1_AFLG_BROKEN)) { | ||
265 | len = tmplen - (p - *in); | ||
266 | seq_nolen = 1; | ||
267 | } | ||
268 | /* If indefinite we don't do a length check */ | ||
269 | else | ||
270 | seq_nolen = seq_eoc; | ||
271 | if (!cst) { | ||
272 | ASN1error(ASN1_R_SEQUENCE_NOT_CONSTRUCTED); | ||
273 | goto err; | ||
274 | } | ||
275 | |||
276 | if (!*pval && !ASN1_item_ex_new(pval, it)) { | ||
277 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
278 | goto err; | ||
279 | } | ||
280 | |||
281 | if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) | ||
282 | goto auxerr; | ||
283 | |||
284 | /* Free up and zero any ADB found */ | ||
285 | for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { | ||
286 | if (tt->flags & ASN1_TFLG_ADB_MASK) { | ||
287 | const ASN1_TEMPLATE *seqtt; | ||
288 | ASN1_VALUE **pseqval; | ||
289 | seqtt = asn1_do_adb(pval, tt, 1); | ||
290 | if (!seqtt) | ||
291 | goto err; | ||
292 | pseqval = asn1_get_field_ptr(pval, seqtt); | ||
293 | ASN1_template_free(pseqval, seqtt); | ||
294 | } | ||
295 | } | ||
296 | |||
297 | /* Get each field entry */ | ||
298 | for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { | ||
299 | const ASN1_TEMPLATE *seqtt; | ||
300 | ASN1_VALUE **pseqval; | ||
301 | seqtt = asn1_do_adb(pval, tt, 1); | ||
302 | if (!seqtt) | ||
303 | goto err; | ||
304 | pseqval = asn1_get_field_ptr(pval, seqtt); | ||
305 | /* Have we ran out of data? */ | ||
306 | if (!len) | ||
307 | break; | ||
308 | q = p; | ||
309 | if (asn1_check_eoc(&p, len)) { | ||
310 | if (!seq_eoc) { | ||
311 | ASN1error(ASN1_R_UNEXPECTED_EOC); | ||
312 | goto err; | ||
313 | } | ||
314 | len -= p - q; | ||
315 | seq_eoc = 0; | ||
316 | q = p; | ||
317 | break; | ||
318 | } | ||
319 | /* This determines the OPTIONAL flag value. The field | ||
320 | * cannot be omitted if it is the last of a SEQUENCE | ||
321 | * and there is still data to be read. This isn't | ||
322 | * strictly necessary but it increases efficiency in | ||
323 | * some cases. | ||
324 | */ | ||
325 | if (i == (it->tcount - 1)) | ||
326 | isopt = 0; | ||
327 | else | ||
328 | isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL); | ||
329 | /* attempt to read in field, allowing each to be | ||
330 | * OPTIONAL */ | ||
331 | |||
332 | ret = asn1_template_ex_d2i(pseqval, &p, len, | ||
333 | seqtt, isopt, depth); | ||
334 | if (!ret) { | ||
335 | errtt = seqtt; | ||
336 | goto err; | ||
337 | } else if (ret == -1) { | ||
338 | /* OPTIONAL component absent. | ||
339 | * Free and zero the field. | ||
340 | */ | ||
341 | ASN1_template_free(pseqval, seqtt); | ||
342 | continue; | ||
343 | } | ||
344 | /* Update length */ | ||
345 | len -= p - q; | ||
346 | } | ||
347 | |||
348 | /* Check for EOC if expecting one */ | ||
349 | if (seq_eoc && !asn1_check_eoc(&p, len)) { | ||
350 | ASN1error(ASN1_R_MISSING_EOC); | ||
351 | goto err; | ||
352 | } | ||
353 | /* Check all data read */ | ||
354 | if (!seq_nolen && len) { | ||
355 | ASN1error(ASN1_R_SEQUENCE_LENGTH_MISMATCH); | ||
356 | goto err; | ||
357 | } | ||
358 | |||
359 | /* If we get here we've got no more data in the SEQUENCE, | ||
360 | * however we may not have read all fields so check all | ||
361 | * remaining are OPTIONAL and clear any that are. | ||
362 | */ | ||
363 | for (; i < it->tcount; tt++, i++) { | ||
364 | const ASN1_TEMPLATE *seqtt; | ||
365 | seqtt = asn1_do_adb(pval, tt, 1); | ||
366 | if (!seqtt) | ||
367 | goto err; | ||
368 | if (seqtt->flags & ASN1_TFLG_OPTIONAL) { | ||
369 | ASN1_VALUE **pseqval; | ||
370 | pseqval = asn1_get_field_ptr(pval, seqtt); | ||
371 | ASN1_template_free(pseqval, seqtt); | ||
372 | } else { | ||
373 | errtt = seqtt; | ||
374 | ASN1error(ASN1_R_FIELD_MISSING); | ||
375 | goto err; | ||
376 | } | ||
377 | } | ||
378 | /* Save encoding */ | ||
379 | if (!asn1_enc_save(pval, *in, p - *in, it)) { | ||
380 | ASN1error(ERR_R_MALLOC_FAILURE); | ||
381 | goto auxerr; | ||
382 | } | ||
383 | *in = p; | ||
384 | if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) | ||
385 | goto auxerr; | ||
386 | return 1; | ||
387 | |||
388 | auxerr: | ||
389 | ASN1error(ASN1_R_AUX_ERROR); | ||
390 | err: | ||
391 | if (combine == 0) | ||
392 | ASN1_item_ex_free(pval, it); | ||
393 | if (errtt) | ||
394 | ERR_asprintf_error_data("Field=%s, Type=%s", errtt->field_name, | ||
395 | it->sname); | ||
396 | else | ||
397 | ERR_asprintf_error_data("Type=%s", it->sname); | ||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | /* | ||
402 | * Decode an item, taking care of IMPLICIT tagging, if any. | ||
403 | * If 'opt' set and tag mismatch return -1 to handle OPTIONAL | ||
404 | */ | ||
405 | static int | ||
406 | asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | ||
407 | const ASN1_ITEM *it, int tag, int aclass, char opt, int depth) | ||
408 | { | ||
409 | const ASN1_EXTERN_FUNCS *ef; | ||
410 | ASN1_TLC ctx = { 0 }; | ||
411 | const unsigned char *p = NULL; | ||
412 | unsigned char oclass; | ||
413 | int otag; | ||
414 | int ret = 0; | ||
415 | int combine; | ||
416 | |||
417 | combine = aclass & ASN1_TFLG_COMBINE; | ||
418 | aclass &= ~ASN1_TFLG_COMBINE; | ||
419 | |||
420 | if (!pval) | ||
421 | return 0; | ||
422 | |||
156 | if (++depth > ASN1_MAX_CONSTRUCTED_NEST) { | 423 | if (++depth > ASN1_MAX_CONSTRUCTED_NEST) { |
157 | ASN1error(ASN1_R_NESTED_TOO_DEEP); | 424 | ASN1error(ASN1_R_NESTED_TOO_DEEP); |
158 | goto err; | 425 | goto err; |
@@ -223,227 +490,24 @@ asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | |||
223 | return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, &ctx); | 490 | return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, &ctx); |
224 | 491 | ||
225 | case ASN1_ITYPE_CHOICE: | 492 | case ASN1_ITYPE_CHOICE: |
226 | /* | 493 | return asn1_item_ex_d2i_choice(pval, in, len, it, tag, |
227 | * It never makes sense for CHOICE types to have implicit | 494 | aclass | combine, opt, depth); |
228 | * tagging, so if tag != -1, then this looks like an error in | ||
229 | * the template. | ||
230 | */ | ||
231 | if (tag != -1) { | ||
232 | ASN1error(ASN1_R_BAD_TEMPLATE); | ||
233 | goto err; | ||
234 | } | ||
235 | |||
236 | if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) | ||
237 | goto auxerr; | ||
238 | |||
239 | if (*pval) { | ||
240 | /* Free up and zero CHOICE value if initialised */ | ||
241 | i = asn1_get_choice_selector(pval, it); | ||
242 | if ((i >= 0) && (i < it->tcount)) { | ||
243 | tt = it->templates + i; | ||
244 | pchptr = asn1_get_field_ptr(pval, tt); | ||
245 | ASN1_template_free(pchptr, tt); | ||
246 | asn1_set_choice_selector(pval, -1, it); | ||
247 | } | ||
248 | } else if (!ASN1_item_ex_new(pval, it)) { | ||
249 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
250 | goto err; | ||
251 | } | ||
252 | /* CHOICE type, try each possibility in turn */ | ||
253 | p = *in; | ||
254 | for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { | ||
255 | pchptr = asn1_get_field_ptr(pval, tt); | ||
256 | /* We mark field as OPTIONAL so its absence | ||
257 | * can be recognised. | ||
258 | */ | ||
259 | ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, | ||
260 | depth); | ||
261 | /* If field not present, try the next one */ | ||
262 | if (ret == -1) | ||
263 | continue; | ||
264 | /* If positive return, read OK, break loop */ | ||
265 | if (ret > 0) | ||
266 | break; | ||
267 | /* Otherwise must be an ASN1 parsing error */ | ||
268 | errtt = tt; | ||
269 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
270 | goto err; | ||
271 | } | ||
272 | |||
273 | /* Did we fall off the end without reading anything? */ | ||
274 | if (i == it->tcount) { | ||
275 | /* If OPTIONAL, this is OK */ | ||
276 | if (opt) { | ||
277 | /* Free and zero it */ | ||
278 | ASN1_item_ex_free(pval, it); | ||
279 | return -1; | ||
280 | } | ||
281 | ASN1error(ASN1_R_NO_MATCHING_CHOICE_TYPE); | ||
282 | goto err; | ||
283 | } | ||
284 | |||
285 | asn1_set_choice_selector(pval, i, it); | ||
286 | *in = p; | ||
287 | if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) | ||
288 | goto auxerr; | ||
289 | return 1; | ||
290 | 495 | ||
291 | case ASN1_ITYPE_NDEF_SEQUENCE: | 496 | case ASN1_ITYPE_NDEF_SEQUENCE: |
292 | case ASN1_ITYPE_SEQUENCE: | 497 | case ASN1_ITYPE_SEQUENCE: |
293 | p = *in; | 498 | return asn1_item_ex_d2i_sequence(pval, in, len, it, tag, |
294 | tmplen = len; | 499 | aclass | combine, opt, depth); |
295 | |||
296 | /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ | ||
297 | if (tag == -1) { | ||
298 | tag = V_ASN1_SEQUENCE; | ||
299 | aclass = V_ASN1_UNIVERSAL; | ||
300 | } | ||
301 | /* Get SEQUENCE length and update len, p */ | ||
302 | ret = asn1_check_tag(&len, NULL, NULL, &seq_eoc, &cst, &p, len, | ||
303 | tag, aclass, opt); | ||
304 | if (!ret) { | ||
305 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
306 | goto err; | ||
307 | } else if (ret == -1) | ||
308 | return -1; | ||
309 | if (aux && (aux->flags & ASN1_AFLG_BROKEN)) { | ||
310 | len = tmplen - (p - *in); | ||
311 | seq_nolen = 1; | ||
312 | } | ||
313 | /* If indefinite we don't do a length check */ | ||
314 | else | ||
315 | seq_nolen = seq_eoc; | ||
316 | if (!cst) { | ||
317 | ASN1error(ASN1_R_SEQUENCE_NOT_CONSTRUCTED); | ||
318 | goto err; | ||
319 | } | ||
320 | |||
321 | if (!*pval && !ASN1_item_ex_new(pval, it)) { | ||
322 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
323 | goto err; | ||
324 | } | ||
325 | |||
326 | if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) | ||
327 | goto auxerr; | ||
328 | |||
329 | /* Free up and zero any ADB found */ | ||
330 | for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { | ||
331 | if (tt->flags & ASN1_TFLG_ADB_MASK) { | ||
332 | const ASN1_TEMPLATE *seqtt; | ||
333 | ASN1_VALUE **pseqval; | ||
334 | seqtt = asn1_do_adb(pval, tt, 1); | ||
335 | if (!seqtt) | ||
336 | goto err; | ||
337 | pseqval = asn1_get_field_ptr(pval, seqtt); | ||
338 | ASN1_template_free(pseqval, seqtt); | ||
339 | } | ||
340 | } | ||
341 | |||
342 | /* Get each field entry */ | ||
343 | for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { | ||
344 | const ASN1_TEMPLATE *seqtt; | ||
345 | ASN1_VALUE **pseqval; | ||
346 | seqtt = asn1_do_adb(pval, tt, 1); | ||
347 | if (!seqtt) | ||
348 | goto err; | ||
349 | pseqval = asn1_get_field_ptr(pval, seqtt); | ||
350 | /* Have we ran out of data? */ | ||
351 | if (!len) | ||
352 | break; | ||
353 | q = p; | ||
354 | if (asn1_check_eoc(&p, len)) { | ||
355 | if (!seq_eoc) { | ||
356 | ASN1error(ASN1_R_UNEXPECTED_EOC); | ||
357 | goto err; | ||
358 | } | ||
359 | len -= p - q; | ||
360 | seq_eoc = 0; | ||
361 | q = p; | ||
362 | break; | ||
363 | } | ||
364 | /* This determines the OPTIONAL flag value. The field | ||
365 | * cannot be omitted if it is the last of a SEQUENCE | ||
366 | * and there is still data to be read. This isn't | ||
367 | * strictly necessary but it increases efficiency in | ||
368 | * some cases. | ||
369 | */ | ||
370 | if (i == (it->tcount - 1)) | ||
371 | isopt = 0; | ||
372 | else | ||
373 | isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL); | ||
374 | /* attempt to read in field, allowing each to be | ||
375 | * OPTIONAL */ | ||
376 | |||
377 | ret = asn1_template_ex_d2i(pseqval, &p, len, | ||
378 | seqtt, isopt, depth); | ||
379 | if (!ret) { | ||
380 | errtt = seqtt; | ||
381 | goto err; | ||
382 | } else if (ret == -1) { | ||
383 | /* OPTIONAL component absent. | ||
384 | * Free and zero the field. | ||
385 | */ | ||
386 | ASN1_template_free(pseqval, seqtt); | ||
387 | continue; | ||
388 | } | ||
389 | /* Update length */ | ||
390 | len -= p - q; | ||
391 | } | ||
392 | |||
393 | /* Check for EOC if expecting one */ | ||
394 | if (seq_eoc && !asn1_check_eoc(&p, len)) { | ||
395 | ASN1error(ASN1_R_MISSING_EOC); | ||
396 | goto err; | ||
397 | } | ||
398 | /* Check all data read */ | ||
399 | if (!seq_nolen && len) { | ||
400 | ASN1error(ASN1_R_SEQUENCE_LENGTH_MISMATCH); | ||
401 | goto err; | ||
402 | } | ||
403 | |||
404 | /* If we get here we've got no more data in the SEQUENCE, | ||
405 | * however we may not have read all fields so check all | ||
406 | * remaining are OPTIONAL and clear any that are. | ||
407 | */ | ||
408 | for (; i < it->tcount; tt++, i++) { | ||
409 | const ASN1_TEMPLATE *seqtt; | ||
410 | seqtt = asn1_do_adb(pval, tt, 1); | ||
411 | if (!seqtt) | ||
412 | goto err; | ||
413 | if (seqtt->flags & ASN1_TFLG_OPTIONAL) { | ||
414 | ASN1_VALUE **pseqval; | ||
415 | pseqval = asn1_get_field_ptr(pval, seqtt); | ||
416 | ASN1_template_free(pseqval, seqtt); | ||
417 | } else { | ||
418 | errtt = seqtt; | ||
419 | ASN1error(ASN1_R_FIELD_MISSING); | ||
420 | goto err; | ||
421 | } | ||
422 | } | ||
423 | /* Save encoding */ | ||
424 | if (!asn1_enc_save(pval, *in, p - *in, it)) { | ||
425 | ASN1error(ERR_R_MALLOC_FAILURE); | ||
426 | goto auxerr; | ||
427 | } | ||
428 | *in = p; | ||
429 | if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) | ||
430 | goto auxerr; | ||
431 | return 1; | ||
432 | 500 | ||
433 | default: | 501 | default: |
434 | return 0; | 502 | return 0; |
435 | } | 503 | } |
436 | 504 | ||
437 | auxerr: | ||
438 | ASN1error(ASN1_R_AUX_ERROR); | ||
439 | err: | 505 | err: |
440 | if (combine == 0) | 506 | if (combine == 0) |
441 | ASN1_item_ex_free(pval, it); | 507 | ASN1_item_ex_free(pval, it); |
442 | if (errtt) | 508 | |
443 | ERR_asprintf_error_data("Field=%s, Type=%s", errtt->field_name, | 509 | ERR_asprintf_error_data("Type=%s", it->sname); |
444 | it->sname); | 510 | |
445 | else | ||
446 | ERR_asprintf_error_data("Type=%s", it->sname); | ||
447 | return 0; | 511 | return 0; |
448 | } | 512 | } |
449 | 513 | ||