diff options
author | jsing <> | 2022-05-12 19:52:31 +0000 |
---|---|---|
committer | jsing <> | 2022-05-12 19:52:31 +0000 |
commit | e8199cf293a6f652731639de25892b965772a617 (patch) | |
tree | f765f27513bf7d46fabba489d75f133c5bbcb5bd /src | |
parent | 2990d731be5155c46ccc71772efd2f35d25ff5ee (diff) | |
download | openbsd-e8199cf293a6f652731639de25892b965772a617.tar.gz openbsd-e8199cf293a6f652731639de25892b965772a617.tar.bz2 openbsd-e8199cf293a6f652731639de25892b965772a617.zip |
Rewrite asn1_item_ex_d2i_choice() using CBS.
Now that combine no longer exists, we can also free and reallocate.
ok tb@
Diffstat (limited to 'src')
-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: |