summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjsing <>2022-05-12 19:52:31 +0000
committerjsing <>2022-05-12 19:52:31 +0000
commite8199cf293a6f652731639de25892b965772a617 (patch)
treef765f27513bf7d46fabba489d75f133c5bbcb5bd /src
parent2990d731be5155c46ccc71772efd2f35d25ff5ee (diff)
downloadopenbsd-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.c127
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
127static int 127static int
128asn1_item_ex_d2i_choice(ASN1_VALUE **pval, const unsigned char **in, long len, 128asn1_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
223static int 221 return 0;
224asn1_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
243static int 224static 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: