diff options
Diffstat (limited to 'src/lib/libcrypto')
| -rw-r--r-- | src/lib/libcrypto/asn1/tasn_dec.c | 127 |
1 files changed, 54 insertions, 73 deletions
diff --git a/src/lib/libcrypto/asn1/tasn_dec.c b/src/lib/libcrypto/asn1/tasn_dec.c index 69e27a9f0f..db4424b6be 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.65 2022/05/12 19:33:19 jsing Exp $ */ | 1 | /* $OpenBSD: tasn_dec.c,v 1.66 2022/05/12 19:52:31 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 | */ |
| @@ -125,119 +125,100 @@ ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | |||
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | static int | 127 | static int |
| 128 | asn1_item_ex_d2i_choice(ASN1_VALUE **pval, const unsigned char **in, long len, | 128 | asn1_item_ex_d2i_choice(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, |
| 129 | const ASN1_ITEM *it, int tag, int aclass, char opt, 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 = it->funcs; |
| 133 | ASN1_aux_cb *asn1_cb = NULL; | 133 | ASN1_aux_cb *asn1_cb = NULL; |
| 134 | ASN1_VALUE *achoice = NULL; | ||
| 134 | ASN1_VALUE **pchptr; | 135 | ASN1_VALUE **pchptr; |
| 135 | const unsigned char *p = NULL; | 136 | int i, ret; |
| 136 | int i; | ||
| 137 | int ret = 0; | ||
| 138 | 137 | ||
| 139 | if (it->itype != ASN1_ITYPE_CHOICE) | 138 | if (it->itype != ASN1_ITYPE_CHOICE) |
| 140 | goto err; | 139 | goto err; |
| 141 | 140 | ||
| 142 | if (aux && aux->asn1_cb) | ||
| 143 | asn1_cb = aux->asn1_cb; | ||
| 144 | |||
| 145 | /* | 141 | /* |
| 146 | * It never makes sense for CHOICE types to have implicit | 142 | * It never makes sense for CHOICE types to have implicit tagging, so |
| 147 | * tagging, so if tag != -1, then this looks like an error in | 143 | * if tag_number != -1, then this looks like an error in the template. |
| 148 | * the template. | ||
| 149 | */ | 144 | */ |
| 150 | if (tag != -1) { | 145 | if (tag_number != -1) { |
| 151 | ASN1error(ASN1_R_BAD_TEMPLATE); | 146 | ASN1error(ASN1_R_BAD_TEMPLATE); |
| 152 | goto err; | 147 | goto err; |
| 153 | } | 148 | } |
| 154 | 149 | ||
| 155 | if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) | 150 | if (*pval != NULL) { |
| 156 | goto auxerr; | 151 | ASN1_item_ex_free(pval, it); |
| 152 | *pval = NULL; | ||
| 153 | } | ||
| 157 | 154 | ||
| 158 | if (*pval) { | 155 | if (aux != NULL) |
| 159 | /* Free up and zero CHOICE value if initialised */ | 156 | asn1_cb = aux->asn1_cb; |
| 160 | i = asn1_get_choice_selector(pval, it); | 157 | |
| 161 | if ((i >= 0) && (i < it->tcount)) { | 158 | if (asn1_cb != NULL && !asn1_cb(ASN1_OP_D2I_PRE, &achoice, it, NULL)) { |
| 162 | tt = it->templates + i; | 159 | ASN1error(ASN1_R_AUX_ERROR); |
| 163 | pchptr = asn1_get_field_ptr(pval, tt); | ||
| 164 | ASN1_template_free(pchptr, tt); | ||
| 165 | asn1_set_choice_selector(pval, -1, it); | ||
| 166 | } | ||
| 167 | } else if (!ASN1_item_ex_new(pval, it)) { | ||
| 168 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
| 169 | goto err; | 160 | goto err; |
| 170 | } | 161 | } |
| 171 | /* CHOICE type, try each possibility in turn */ | 162 | |
| 172 | p = *in; | 163 | if (achoice == NULL) { |
| 164 | if (!ASN1_item_ex_new(&achoice, it)) { | ||
| 165 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
| 166 | goto err; | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 170 | /* Try each possible CHOICE in turn. */ | ||
| 173 | for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { | 171 | for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { |
| 174 | pchptr = asn1_get_field_ptr(pval, tt); | 172 | pchptr = asn1_get_field_ptr(&achoice, tt); |
| 175 | /* We mark field as OPTIONAL so its absence | 173 | |
| 176 | * can be recognised. | 174 | /* Mark field as OPTIONAL so its absence can be identified. */ |
| 177 | */ | 175 | ret = asn1_template_ex_d2i_cbs(pchptr, cbs, tt, 1, depth); |
| 178 | ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, | 176 | |
| 179 | depth); | ||
| 180 | /* If field not present, try the next one */ | 177 | /* If field not present, try the next one */ |
| 181 | if (ret == -1) | 178 | if (ret == -1) |
| 182 | continue; | 179 | continue; |
| 183 | /* If positive return, read OK, break loop */ | 180 | |
| 184 | if (ret > 0) | 181 | if (ret != 1) { |
| 185 | break; | 182 | ASN1error(ERR_R_NESTED_ASN1_ERROR); |
| 186 | /* Otherwise must be an ASN1 parsing error */ | 183 | errtt = tt; |
| 187 | errtt = tt; | 184 | goto err; |
| 188 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | 185 | } |
| 189 | goto err; | 186 | |
| 187 | /* We've successfully decoded an ASN.1 object. */ | ||
| 188 | asn1_set_choice_selector(&achoice, i, it); | ||
| 189 | break; | ||
| 190 | } | 190 | } |
| 191 | 191 | ||
| 192 | /* Did we fall off the end without reading anything? */ | 192 | /* Did we fall off the end without reading anything? */ |
| 193 | if (i == it->tcount) { | 193 | if (i == it->tcount) { |
| 194 | /* If OPTIONAL, this is OK */ | 194 | if (optional) { |
| 195 | if (opt) { | 195 | ASN1_item_ex_free(&achoice, it); |
| 196 | /* Free and zero it */ | ||
| 197 | ASN1_item_ex_free(pval, it); | ||
| 198 | return -1; | 196 | return -1; |
| 199 | } | 197 | } |
| 200 | ASN1error(ASN1_R_NO_MATCHING_CHOICE_TYPE); | 198 | ASN1error(ASN1_R_NO_MATCHING_CHOICE_TYPE); |
| 201 | goto err; | 199 | goto err; |
| 202 | } | 200 | } |
| 203 | 201 | ||
| 204 | asn1_set_choice_selector(pval, i, it); | 202 | if (asn1_cb != NULL && !asn1_cb(ASN1_OP_D2I_POST, &achoice, it, NULL)) { |
| 205 | *in = p; | 203 | ASN1error(ASN1_R_AUX_ERROR); |
| 206 | if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) | 204 | goto err; |
| 207 | goto auxerr; | 205 | } |
| 206 | |||
| 207 | *pval = achoice; | ||
| 208 | achoice = NULL; | ||
| 209 | |||
| 208 | return 1; | 210 | return 1; |
| 209 | 211 | ||
| 210 | auxerr: | ||
| 211 | ASN1error(ASN1_R_AUX_ERROR); | ||
| 212 | err: | 212 | err: |
| 213 | ASN1_item_ex_free(pval, it); | 213 | ASN1_item_ex_free(&achoice, it); |
| 214 | 214 | ||
| 215 | if (errtt) | 215 | if (errtt) |
| 216 | ERR_asprintf_error_data("Field=%s, Type=%s", errtt->field_name, | 216 | ERR_asprintf_error_data("Field=%s, Type=%s", errtt->field_name, |
| 217 | it->sname); | 217 | it->sname); |
| 218 | else | 218 | else |
| 219 | ERR_asprintf_error_data("Type=%s", it->sname); | 219 | ERR_asprintf_error_data("Type=%s", it->sname); |
| 220 | return 0; | ||
| 221 | } | ||
| 222 | 220 | ||
| 223 | static int | 221 | return 0; |
| 224 | asn1_item_ex_d2i_choice_cbs(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, | ||
| 225 | int tag_number, int tag_class, char optional, int depth) | ||
| 226 | { | ||
| 227 | const unsigned char *p; | ||
| 228 | int ret; | ||
| 229 | |||
| 230 | if (CBS_len(cbs) > LONG_MAX) | ||
| 231 | return 0; | ||
| 232 | |||
| 233 | p = CBS_data(cbs); | ||
| 234 | ret = asn1_item_ex_d2i_choice(pval, &p, (long)CBS_len(cbs), it, | ||
| 235 | tag_number, tag_class, optional, depth); | ||
| 236 | if (ret == 1) { | ||
| 237 | if (!CBS_skip(cbs, p - CBS_data(cbs))) | ||
| 238 | return 0; | ||
| 239 | } | ||
| 240 | return ret; | ||
| 241 | } | 222 | } |
| 242 | 223 | ||
| 243 | static int | 224 | static int |
| @@ -518,7 +499,7 @@ asn1_item_ex_d2i_cbs(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, | |||
| 518 | return ret; | 499 | return ret; |
| 519 | 500 | ||
| 520 | case ASN1_ITYPE_CHOICE: | 501 | case ASN1_ITYPE_CHOICE: |
| 521 | return asn1_item_ex_d2i_choice_cbs(pval, cbs, it, tag_number, | 502 | return asn1_item_ex_d2i_choice(pval, cbs, it, tag_number, |
| 522 | tag_class, optional, depth); | 503 | tag_class, optional, depth); |
| 523 | 504 | ||
| 524 | case ASN1_ITYPE_NDEF_SEQUENCE: | 505 | case ASN1_ITYPE_NDEF_SEQUENCE: |
