diff options
author | jsing <> | 2022-03-19 17:35:52 +0000 |
---|---|---|
committer | jsing <> | 2022-03-19 17:35:52 +0000 |
commit | 1886782bdfd11c86949b1ea6243e8ffcb02455ea (patch) | |
tree | 72c751aeba9f06d9f06d95487ff72b4b19165a49 | |
parent | affcb4376993774ff70241876bfbf4ce93d38812 (diff) | |
download | openbsd-1886782bdfd11c86949b1ea6243e8ffcb02455ea.tar.gz openbsd-1886782bdfd11c86949b1ea6243e8ffcb02455ea.tar.bz2 openbsd-1886782bdfd11c86949b1ea6243e8ffcb02455ea.zip |
Rewrite ascii/text to ASN.1 object conversion.
Rewrite the ascii/text to ASN.1 object conversion code using CBB/CBS,
while also addressing some of the bizarre behaviour (such as allowing
mixed separators and treating '..' as a zero value).
ok inoguchi@ tb@
-rw-r--r-- | src/lib/libcrypto/asn1/a_object.c | 288 |
1 files changed, 167 insertions, 121 deletions
diff --git a/src/lib/libcrypto/asn1/a_object.c b/src/lib/libcrypto/asn1/a_object.c index 120437bf10..0061ccb880 100644 --- a/src/lib/libcrypto/asn1/a_object.c +++ b/src/lib/libcrypto/asn1/a_object.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: a_object.c,v 1.41 2022/03/15 18:47:22 jsing Exp $ */ | 1 | /* $OpenBSD: a_object.c,v 1.42 2022/03/19 17:35:52 jsing Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -62,7 +62,6 @@ | |||
62 | 62 | ||
63 | #include <openssl/asn1.h> | 63 | #include <openssl/asn1.h> |
64 | #include <openssl/asn1t.h> | 64 | #include <openssl/asn1t.h> |
65 | #include <openssl/bn.h> | ||
66 | #include <openssl/err.h> | 65 | #include <openssl/err.h> |
67 | #include <openssl/buffer.h> | 66 | #include <openssl/buffer.h> |
68 | #include <openssl/objects.h> | 67 | #include <openssl/objects.h> |
@@ -146,128 +145,25 @@ i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp) | |||
146 | return (objsize); | 145 | return (objsize); |
147 | } | 146 | } |
148 | 147 | ||
149 | int | 148 | static int |
150 | a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num) | 149 | oid_add_arc(CBB *cbb, uint64_t arc) |
151 | { | 150 | { |
152 | int i, first, len = 0, c, use_bn; | 151 | int started = 0; |
153 | char ftmp[24], *tmp = ftmp; | 152 | uint8_t val; |
154 | int tmpsize = sizeof ftmp; | 153 | int i; |
155 | const char *p; | 154 | |
156 | unsigned long l; | 155 | for (i = (sizeof(arc) * 8) / 7; i >= 0; i--) { |
157 | BIGNUM *bl = NULL; | 156 | val = (arc >> (i * 7)) & 0x7f; |
158 | 157 | if (!started && i != 0 && val == 0) | |
159 | if (num == 0) | 158 | continue; |
160 | return (0); | 159 | if (i > 0) |
161 | else if (num == -1) | 160 | val |= 0x80; |
162 | num = strlen(buf); | 161 | if (!CBB_add_u8(cbb, val)) |
163 | 162 | return 0; | |
164 | p = buf; | 163 | started = 1; |
165 | c = *(p++); | ||
166 | num--; | ||
167 | if ((c >= '0') && (c <= '2')) { | ||
168 | first= c-'0'; | ||
169 | } else { | ||
170 | ASN1error(ASN1_R_FIRST_NUM_TOO_LARGE); | ||
171 | goto err; | ||
172 | } | ||
173 | |||
174 | if (num <= 0) { | ||
175 | ASN1error(ASN1_R_MISSING_SECOND_NUMBER); | ||
176 | goto err; | ||
177 | } | ||
178 | c = *(p++); | ||
179 | num--; | ||
180 | for (;;) { | ||
181 | if (num <= 0) | ||
182 | break; | ||
183 | if ((c != '.') && (c != ' ')) { | ||
184 | ASN1error(ASN1_R_INVALID_SEPARATOR); | ||
185 | goto err; | ||
186 | } | ||
187 | l = 0; | ||
188 | use_bn = 0; | ||
189 | for (;;) { | ||
190 | if (num <= 0) | ||
191 | break; | ||
192 | num--; | ||
193 | c = *(p++); | ||
194 | if ((c == ' ') || (c == '.')) | ||
195 | break; | ||
196 | if ((c < '0') || (c > '9')) { | ||
197 | ASN1error(ASN1_R_INVALID_DIGIT); | ||
198 | goto err; | ||
199 | } | ||
200 | if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) { | ||
201 | use_bn = 1; | ||
202 | if (!bl) | ||
203 | bl = BN_new(); | ||
204 | if (!bl || !BN_set_word(bl, l)) | ||
205 | goto err; | ||
206 | } | ||
207 | if (use_bn) { | ||
208 | if (!BN_mul_word(bl, 10L) || | ||
209 | !BN_add_word(bl, c-'0')) | ||
210 | goto err; | ||
211 | } else | ||
212 | l = l * 10L + (long)(c - '0'); | ||
213 | } | ||
214 | if (len == 0) { | ||
215 | if ((first < 2) && (l >= 40)) { | ||
216 | ASN1error(ASN1_R_SECOND_NUMBER_TOO_LARGE); | ||
217 | goto err; | ||
218 | } | ||
219 | if (use_bn) { | ||
220 | if (!BN_add_word(bl, first * 40)) | ||
221 | goto err; | ||
222 | } else | ||
223 | l += (long)first * 40; | ||
224 | } | ||
225 | i = 0; | ||
226 | if (use_bn) { | ||
227 | int blsize; | ||
228 | blsize = BN_num_bits(bl); | ||
229 | blsize = (blsize + 6) / 7; | ||
230 | if (blsize > tmpsize) { | ||
231 | if (tmp != ftmp) | ||
232 | free(tmp); | ||
233 | tmpsize = blsize + 32; | ||
234 | tmp = malloc(tmpsize); | ||
235 | if (!tmp) | ||
236 | goto err; | ||
237 | } | ||
238 | while (blsize--) | ||
239 | tmp[i++] = (unsigned char)BN_div_word(bl, 0x80L); | ||
240 | } else { | ||
241 | |||
242 | for (;;) { | ||
243 | tmp[i++] = (unsigned char)l & 0x7f; | ||
244 | l >>= 7L; | ||
245 | if (l == 0L) | ||
246 | break; | ||
247 | } | ||
248 | |||
249 | } | ||
250 | if (out != NULL) { | ||
251 | if (len + i > olen) { | ||
252 | ASN1error(ASN1_R_BUFFER_TOO_SMALL); | ||
253 | goto err; | ||
254 | } | ||
255 | while (--i > 0) | ||
256 | out[len++] = tmp[i]|0x80; | ||
257 | out[len++] = tmp[0]; | ||
258 | } else | ||
259 | len += i; | ||
260 | } | 164 | } |
261 | if (tmp != ftmp) | ||
262 | free(tmp); | ||
263 | BN_free(bl); | ||
264 | return (len); | ||
265 | 165 | ||
266 | err: | 166 | return 1; |
267 | if (tmp != ftmp) | ||
268 | free(tmp); | ||
269 | BN_free(bl); | ||
270 | return (0); | ||
271 | } | 167 | } |
272 | 168 | ||
273 | static int | 169 | static int |
@@ -310,6 +206,111 @@ oid_add_arc_txt(CBB *cbb, uint64_t arc, int first) | |||
310 | } | 206 | } |
311 | 207 | ||
312 | static int | 208 | static int |
209 | oid_parse_arc_txt(CBS *cbs, uint64_t *out_arc, char *separator, int first) | ||
210 | { | ||
211 | uint64_t arc = 0; | ||
212 | int digits = 0; | ||
213 | uint8_t val; | ||
214 | |||
215 | if (!first) { | ||
216 | if (!CBS_get_u8(cbs, &val)) | ||
217 | return 0; | ||
218 | if ((*separator == 0 && val != '.' && val != ' ') || | ||
219 | (*separator != 0 && val != *separator)) { | ||
220 | ASN1error(ASN1_R_INVALID_SEPARATOR); | ||
221 | return 0; | ||
222 | } | ||
223 | *separator = val; | ||
224 | } | ||
225 | |||
226 | while (CBS_len(cbs) > 0) { | ||
227 | if (!CBS_peek_u8(cbs, &val)) | ||
228 | return 0; | ||
229 | if (val == '.' || val == ' ') | ||
230 | break; | ||
231 | |||
232 | if (!CBS_get_u8(cbs, &val)) | ||
233 | return 0; | ||
234 | if (val < '0' || val > '9') { | ||
235 | /* For the first arc we treat this as the separator. */ | ||
236 | if (first) { | ||
237 | ASN1error(ASN1_R_INVALID_SEPARATOR); | ||
238 | return 0; | ||
239 | } | ||
240 | ASN1error(ASN1_R_INVALID_DIGIT); | ||
241 | return 0; | ||
242 | } | ||
243 | val -= '0'; | ||
244 | |||
245 | if (digits > 0 && arc == 0 && val == 0) { | ||
246 | ASN1error(ASN1_R_INVALID_NUMBER); | ||
247 | return 0; | ||
248 | } | ||
249 | digits++; | ||
250 | |||
251 | if (arc > UINT64_MAX / 10) { | ||
252 | ASN1error(ASN1_R_TOO_LONG); | ||
253 | return 0; | ||
254 | } | ||
255 | arc = arc * 10 + val; | ||
256 | } | ||
257 | |||
258 | if (digits < 1) { | ||
259 | ASN1error(ASN1_R_INVALID_NUMBER); | ||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | *out_arc = arc; | ||
264 | |||
265 | return 1; | ||
266 | } | ||
267 | |||
268 | static int | ||
269 | a2c_ASN1_OBJECT_internal(CBB *cbb, CBS *cbs) | ||
270 | { | ||
271 | uint64_t arc, si1, si2; | ||
272 | char separator = 0; | ||
273 | |||
274 | if (!oid_parse_arc_txt(cbs, &si1, &separator, 1)) | ||
275 | return 0; | ||
276 | |||
277 | if (CBS_len(cbs) == 0) { | ||
278 | ASN1error(ASN1_R_MISSING_SECOND_NUMBER); | ||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | if (!oid_parse_arc_txt(cbs, &si2, &separator, 0)) | ||
283 | return 0; | ||
284 | |||
285 | /* | ||
286 | * X.690 section 8.19 - the first two subidentifiers are encoded as | ||
287 | * (x * 40) + y, with x being limited to [0,1,2]. The second | ||
288 | * subidentifier cannot exceed 39 for x < 2. | ||
289 | */ | ||
290 | if (si1 > 2) { | ||
291 | ASN1error(ASN1_R_FIRST_NUM_TOO_LARGE); | ||
292 | return 0; | ||
293 | } | ||
294 | if ((si1 < 2 && si2 >= 40) || si2 > UINT64_MAX - si1 * 40) { | ||
295 | ASN1error(ASN1_R_SECOND_NUMBER_TOO_LARGE); | ||
296 | return 0; | ||
297 | } | ||
298 | arc = si1 * 40 + si2; | ||
299 | |||
300 | if (!oid_add_arc(cbb, arc)) | ||
301 | return 0; | ||
302 | |||
303 | while (CBS_len(cbs) > 0) { | ||
304 | if (!oid_parse_arc_txt(cbs, &arc, &separator, 0)) | ||
305 | return 0; | ||
306 | if (!oid_add_arc(cbb, arc)) | ||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | return 1; | ||
311 | } | ||
312 | |||
313 | static int | ||
313 | c2a_ASN1_OBJECT(CBS *cbs, CBB *cbb) | 314 | c2a_ASN1_OBJECT(CBS *cbs, CBB *cbb) |
314 | { | 315 | { |
315 | uint64_t arc, si1, si2; | 316 | uint64_t arc, si1, si2; |
@@ -343,6 +344,51 @@ c2a_ASN1_OBJECT(CBS *cbs, CBB *cbb) | |||
343 | return 1; | 344 | return 1; |
344 | } | 345 | } |
345 | 346 | ||
347 | int | ||
348 | a2d_ASN1_OBJECT(unsigned char *out, int out_len, const char *in, int in_len) | ||
349 | { | ||
350 | uint8_t *data = NULL; | ||
351 | size_t data_len; | ||
352 | CBS cbs; | ||
353 | CBB cbb; | ||
354 | int ret = 0; | ||
355 | |||
356 | memset(&cbb, 0, sizeof(cbb)); | ||
357 | |||
358 | if (in_len == -1) | ||
359 | in_len = strlen(in); | ||
360 | if (in_len <= 0) | ||
361 | goto err; | ||
362 | |||
363 | CBS_init(&cbs, in, in_len); | ||
364 | |||
365 | if (!CBB_init(&cbb, 0)) | ||
366 | goto err; | ||
367 | if (!a2c_ASN1_OBJECT_internal(&cbb, &cbs)) | ||
368 | goto err; | ||
369 | if (!CBB_finish(&cbb, &data, &data_len)) | ||
370 | goto err; | ||
371 | |||
372 | if (data_len > INT_MAX) | ||
373 | goto err; | ||
374 | |||
375 | if (out != NULL) { | ||
376 | if (out_len <= 0 || (size_t)out_len < data_len) { | ||
377 | ASN1error(ASN1_R_BUFFER_TOO_SMALL); | ||
378 | goto err; | ||
379 | } | ||
380 | memcpy(out, data, data_len); | ||
381 | } | ||
382 | |||
383 | ret = (int)data_len; | ||
384 | |||
385 | err: | ||
386 | CBB_cleanup(&cbb); | ||
387 | free(data); | ||
388 | |||
389 | return ret; | ||
390 | } | ||
391 | |||
346 | static int | 392 | static int |
347 | i2t_ASN1_OBJECT_oid(const ASN1_OBJECT *aobj, CBB *cbb) | 393 | i2t_ASN1_OBJECT_oid(const ASN1_OBJECT *aobj, CBB *cbb) |
348 | { | 394 | { |