summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorjsing <>2022-03-02 11:28:00 +0000
committerjsing <>2022-03-02 11:28:00 +0000
commit3c3fcd217ad6d444723416dd9eca5e1dc42f4bed (patch)
treeef22bb60da9100fb77f57965fd90ea63a5b3733b /src/lib
parent4d809bb98b2046d02a7447203478b3d9d0846702 (diff)
downloadopenbsd-3c3fcd217ad6d444723416dd9eca5e1dc42f4bed.tar.gz
openbsd-3c3fcd217ad6d444723416dd9eca5e1dc42f4bed.tar.bz2
openbsd-3c3fcd217ad6d444723416dd9eca5e1dc42f4bed.zip
Rewrite ASN1_OBJECT content to ascii/text conversion.
Rewrite the ASN1_OBJECT content to ascii/text conversion code using CBB and CBS. Currently there is a strange split with i2t_ASN1_OBJECT() calling OBJ_obj2txt() which implements the conversion, while OBJ_txt2obj() calls back into the misnamed a2d_ASN1_OBJECT() function. Move the conversion code into asn1/a_object.c and have OBJ_txt2obj() call that instead. ok inoguchi@ tb@
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libcrypto/asn1/a_object.c201
-rw-r--r--src/lib/libcrypto/asn1/asn1_locl.h5
-rw-r--r--src/lib/libcrypto/objects/obj_dat.c81
3 files changed, 186 insertions, 101 deletions
diff --git a/src/lib/libcrypto/asn1/a_object.c b/src/lib/libcrypto/asn1/a_object.c
index 1407f7df1c..f26026e6aa 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.37 2022/01/07 11:13:54 tb Exp $ */ 1/* $OpenBSD: a_object.c,v 1.38 2022/03/02 11:28:00 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 *
@@ -270,37 +270,190 @@ a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
270 return (0); 270 return (0);
271} 271}
272 272
273static int
274oid_parse_arc(CBS *cbs, uint64_t *out_arc)
275{
276 uint64_t arc = 0;
277 uint8_t val;
278
279 do {
280 if (!CBS_get_u8(cbs, &val))
281 return 0;
282 if (arc == 0 && val == 0x80)
283 return 0;
284 if (arc > (UINT64_MAX >> 7))
285 return 0;
286 arc = (arc << 7) | (val & 0x7f);
287 } while (val & 0x80);
288
289 *out_arc = arc;
290
291 return 1;
292}
293
294static int
295oid_add_arc_txt(CBB *cbb, uint64_t arc, int first)
296{
297 const char *fmt = ".%llu";
298 char s[22]; /* Digits in decimal representation of 2^64-1, plus '.' and NUL. */
299 int n;
300
301 if (first)
302 fmt = "%llu";
303 n = snprintf(s, sizeof(s), fmt, (unsigned long long)arc);
304 if (n < 0 || (size_t)n >= sizeof(s))
305 return 0;
306 if (!CBB_add_bytes(cbb, s, n))
307 return 0;
308
309 return 1;
310}
311
312static int
313c2a_ASN1_OBJECT(CBS *cbs, CBB *cbb)
314{
315 uint64_t arc, si1, si2;
316
317 /*
318 * X.690 section 8.19 - the first two subidentifiers are encoded as
319 * (x * 40) + y, with x being limited to [0,1,2].
320 */
321 if (!oid_parse_arc(cbs, &arc))
322 return 0;
323 if ((si1 = arc / 40) > 2)
324 si1 = 2;
325 si2 = arc - si1 * 40;
326
327 if (!oid_add_arc_txt(cbb, si1, 1))
328 return 0;
329 if (!oid_add_arc_txt(cbb, si2, 0))
330 return 0;
331
332 while (CBS_len(cbs) > 0) {
333 if (!oid_parse_arc(cbs, &arc))
334 return 0;
335 if (!oid_add_arc_txt(cbb, arc, 0))
336 return 0;
337 }
338
339 /* NUL terminate. */
340 if (!CBB_add_u8(cbb, 0))
341 return 0;
342
343 return 1;
344}
345
346static int
347i2t_ASN1_OBJECT_oid(const ASN1_OBJECT *aobj, CBB *cbb)
348{
349 CBS cbs;
350
351 CBS_init(&cbs, aobj->data, aobj->length);
352
353 return c2a_ASN1_OBJECT(&cbs, cbb);
354}
355
356static int
357i2t_ASN1_OBJECT_name(const ASN1_OBJECT *aobj, CBB *cbb, const char **out_name)
358{
359 const char *name;
360 int nid;
361
362 if ((nid = OBJ_obj2nid(aobj)) == NID_undef)
363 return 0;
364
365 if ((name = OBJ_nid2ln(nid)) == NULL)
366 name = OBJ_nid2sn(nid);
367 if (name == NULL)
368 return 0;
369
370 *out_name = name;
371
372 if (!CBB_add_bytes(cbb, name, strlen(name)))
373 return 0;
374
375 /* NUL terminate. */
376 if (!CBB_add_u8(cbb, 0))
377 return 0;
378
379 return 1;
380}
381
382static int
383i2t_ASN1_OBJECT_cbb(const ASN1_OBJECT *aobj, CBB *cbb, int no_name)
384{
385 const char *name;
386
387 if (!no_name) {
388 if (i2t_ASN1_OBJECT_name(aobj, cbb, &name))
389 return 1;
390 if (name != NULL)
391 return 0;
392 }
393 return i2t_ASN1_OBJECT_oid(aobj, cbb);
394}
395
396int
397i2t_ASN1_OBJECT_internal(const ASN1_OBJECT *aobj, char *buf, int buf_len, int no_name)
398{
399 uint8_t *data = NULL;
400 size_t data_len;
401 CBB cbb;
402 int ret = 0;
403
404 if (buf_len < 0)
405 return 0;
406 if (buf_len > 0)
407 buf[0] = '\0';
408
409 if (!CBB_init(&cbb, 0))
410 goto err;
411 if (!i2t_ASN1_OBJECT_cbb(aobj, &cbb, no_name))
412 goto err;
413 if (!CBB_finish(&cbb, &data, &data_len))
414 goto err;
415
416 ret = strlcpy(buf, data, buf_len);
417 err:
418 CBB_cleanup(&cbb);
419 free(data);
420
421 return ret;
422}
423
273int 424int
274i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a) 425i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *aobj)
275{ 426{
276 return OBJ_obj2txt(buf, buf_len, a, 0); 427 return i2t_ASN1_OBJECT_internal(aobj, buf, buf_len, 0);
277} 428}
278 429
279int 430int
280i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a) 431i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *aobj)
281{ 432{
282 char *tmp = NULL; 433 uint8_t *data = NULL;
283 size_t tlen = 256; 434 size_t data_len;
284 int i = -1; 435 CBB cbb;
436 int ret = -1;
285 437
286 if ((a == NULL) || (a->data == NULL)) 438 if (aobj == NULL || aobj->data == NULL)
287 return(BIO_write(bp, "NULL", 4)); 439 return BIO_write(bp, "NULL", 4);
288 if ((tmp = malloc(tlen)) == NULL) 440
289 return -1; 441 if (!CBB_init(&cbb, 0))
290 i = i2t_ASN1_OBJECT(tmp, tlen, a); 442 goto err;
291 if (i > (int)(tlen - 1)) { 443 if (!i2t_ASN1_OBJECT_cbb(aobj, &cbb, 0)) {
292 freezero(tmp, tlen); 444 ret = BIO_write(bp, "<INVALID>", 9);
293 if ((tmp = malloc(i + 1)) == NULL) 445 goto err;
294 return -1;
295 tlen = i + 1;
296 i = i2t_ASN1_OBJECT(tmp, tlen, a);
297 } 446 }
298 if (i <= 0) 447 if (!CBB_finish(&cbb, &data, &data_len))
299 i = BIO_write(bp, "<INVALID>", 9); 448 goto err;
300 else 449
301 i = BIO_write(bp, tmp, i); 450 ret = BIO_write(bp, data, data_len);
302 freezero(tmp, tlen); 451
303 return (i); 452 err:
453 CBB_cleanup(&cbb);
454 free(data);
455
456 return ret;
304} 457}
305 458
306ASN1_OBJECT * 459ASN1_OBJECT *
diff --git a/src/lib/libcrypto/asn1/asn1_locl.h b/src/lib/libcrypto/asn1/asn1_locl.h
index 7d34d7c17a..bb6a9fc91a 100644
--- a/src/lib/libcrypto/asn1/asn1_locl.h
+++ b/src/lib/libcrypto/asn1/asn1_locl.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: asn1_locl.h,v 1.20 2022/01/14 08:53:53 tb Exp $ */ 1/* $OpenBSD: asn1_locl.h,v 1.21 2022/03/02 11:28:00 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 2006. 3 * project 2006.
4 */ 4 */
@@ -201,4 +201,7 @@ int asn1_get_object_cbs(CBS *cbs, int der_mode, uint8_t *out_class,
201 201
202int asn1_tag2charwidth(int tag); 202int asn1_tag2charwidth(int tag);
203 203
204int i2t_ASN1_OBJECT_internal(const ASN1_OBJECT *aobj, char *buf, int buf_len,
205 int no_name);
206
204__END_HIDDEN_DECLS 207__END_HIDDEN_DECLS
diff --git a/src/lib/libcrypto/objects/obj_dat.c b/src/lib/libcrypto/objects/obj_dat.c
index 03e65f1dfe..786bed6c7a 100644
--- a/src/lib/libcrypto/objects/obj_dat.c
+++ b/src/lib/libcrypto/objects/obj_dat.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: obj_dat.c,v 1.47 2022/02/12 03:01:59 jsing Exp $ */ 1/* $OpenBSD: obj_dat.c,v 1.48 2022/03/02 11:28:00 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 *
@@ -524,83 +524,12 @@ OBJ_txt2obj(const char *s, int no_name)
524} 524}
525 525
526int 526int
527OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name) 527OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *aobj, int no_name)
528{ 528{
529 int i, ret = 0, len, nid, first = 1; 529 if (aobj == NULL || aobj->data == NULL)
530 const unsigned char *p; 530 return 0;
531 uint64_t l;
532
533 /* Ensure that, at every state, |buf| is NUL-terminated. */
534 if (buf_len > 0)
535 buf[0] = '\0';
536
537 if ((a == NULL) || (a->data == NULL))
538 goto err;
539
540 if (!no_name && (nid = OBJ_obj2nid(a)) != NID_undef) {
541 const char *s;
542 s = OBJ_nid2ln(nid);
543 if (s == NULL)
544 s = OBJ_nid2sn(nid);
545 if (s) {
546 ret = strlcpy(buf, s, buf_len);
547 goto out;
548 }
549 }
550
551 len = a->length;
552 p = a->data;
553
554 while (len > 0) {
555 l = 0;
556 for (;;) {
557 unsigned char c = *p++;
558 len--;
559 if ((len == 0) && (c & 0x80))
560 goto err;
561 l |= c & 0x7f;
562 if (!(c & 0x80))
563 break;
564 if (l > (UINT64_MAX >> 7L))
565 goto err;
566 l <<= 7L;
567 }
568
569 if (first) {
570 first = 0;
571 if (l >= 80) {
572 i = 2;
573 l -= 80;
574 } else {
575 i = (int)(l / 40);
576 l -= (long)(i * 40);
577 }
578 if (buf_len > 1) {
579 *buf++ = i + '0';
580 *buf = '\0';
581 buf_len--;
582 }
583 ret++;
584 }
585
586 i = snprintf(buf, buf_len, ".%llu", l);
587 if (i < 0)
588 goto err;
589 if (i >= buf_len) {
590 buf_len = 0;
591 } else {
592 buf += i;
593 buf_len -= i;
594 }
595 ret += i;
596 }
597
598 out:
599 return ret;
600 531
601 err: 532 return i2t_ASN1_OBJECT_internal(aobj, buf, buf_len, no_name);
602 ret = 0;
603 goto out;
604} 533}
605 534
606int 535int