diff options
author | tb <> | 2023-05-12 13:56:17 +0000 |
---|---|---|
committer | tb <> | 2023-05-12 13:56:17 +0000 |
commit | b345c57b28722f9d99b4f658837e895ba199555b (patch) | |
tree | 3b81e8e07c4ef4750171db0536d98ab2381ad47c /src/lib | |
parent | c68792ad5f1a5c23b89cce981773d589934ec0f5 (diff) | |
download | openbsd-b345c57b28722f9d99b4f658837e895ba199555b.tar.gz openbsd-b345c57b28722f9d99b4f658837e895ba199555b.tar.bz2 openbsd-b345c57b28722f9d99b4f658837e895ba199555b.zip |
Rewrite string_to_hex() and hex_to_string() using CBB/CBS
These helpers used to contain messy pointer bashing some with weird logic
for NUL termination. This can be written more safely and cleanly using
CBB/CBS, so do that. The result is nearly but not entirely identical to
code used elsewhere due to some strange semantics. Apart from errors pushed
on the stack due to out-of-memory conditions, care was taken to preserve
error codes.
ok jsing
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/libcrypto/x509/x509_utl.c | 194 |
1 files changed, 124 insertions, 70 deletions
diff --git a/src/lib/libcrypto/x509/x509_utl.c b/src/lib/libcrypto/x509/x509_utl.c index 0cc5fb4068..28e9179e95 100644 --- a/src/lib/libcrypto/x509/x509_utl.c +++ b/src/lib/libcrypto/x509/x509_utl.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: x509_utl.c,v 1.14 2023/04/23 11:52:14 tb Exp $ */ | 1 | /* $OpenBSD: x509_utl.c,v 1.15 2023/05/12 13:56:17 tb 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. | 3 | * project. |
4 | */ | 4 | */ |
@@ -55,9 +55,9 @@ | |||
55 | * Hudson (tjh@cryptsoft.com). | 55 | * Hudson (tjh@cryptsoft.com). |
56 | * | 56 | * |
57 | */ | 57 | */ |
58 | /* X509 v3 extension utilities */ | ||
59 | 58 | ||
60 | #include <ctype.h> | 59 | #include <ctype.h> |
60 | #include <limits.h> | ||
61 | #include <stdio.h> | 61 | #include <stdio.h> |
62 | #include <string.h> | 62 | #include <string.h> |
63 | 63 | ||
@@ -67,6 +67,8 @@ | |||
67 | #include <openssl/err.h> | 67 | #include <openssl/err.h> |
68 | #include <openssl/x509v3.h> | 68 | #include <openssl/x509v3.h> |
69 | 69 | ||
70 | #include "bytestring.h" | ||
71 | |||
70 | static char *bn_to_string(const BIGNUM *bn); | 72 | static char *bn_to_string(const BIGNUM *bn); |
71 | static char *strip_spaces(char *name); | 73 | static char *strip_spaces(char *name); |
72 | static int sk_strcmp(const char * const *a, const char * const *b); | 74 | static int sk_strcmp(const char * const *a, const char * const *b); |
@@ -459,97 +461,149 @@ strip_spaces(char *name) | |||
459 | return p; | 461 | return p; |
460 | } | 462 | } |
461 | 463 | ||
462 | /* hex string utilities */ | 464 | static const char hex_digits[] = "0123456789ABCDEF"; |
463 | 465 | ||
464 | /* Given a buffer of length 'len' return a malloc'ed string with its | ||
465 | * hex representation | ||
466 | */ | ||
467 | char * | 466 | char * |
468 | hex_to_string(const unsigned char *buffer, long len) | 467 | hex_to_string(const unsigned char *buffer, long len) |
469 | { | 468 | { |
470 | char *tmp, *q; | 469 | CBB cbb; |
471 | const unsigned char *p; | 470 | CBS cbs; |
472 | int i; | 471 | uint8_t *out = NULL; |
473 | static const char hexdig[] = "0123456789ABCDEF"; | 472 | uint8_t c; |
473 | size_t out_len; | ||
474 | |||
475 | if (!CBB_init(&cbb, 0)) | ||
476 | goto err; | ||
474 | 477 | ||
475 | if (len < 0) | 478 | if (len < 0) |
476 | return NULL; | 479 | goto err; |
477 | if (len == 0) | 480 | |
478 | return calloc(1, 1); | 481 | CBS_init(&cbs, buffer, len); |
479 | if ((tmp = calloc(len, 3)) == NULL) { | 482 | while (CBS_len(&cbs) > 0) { |
480 | X509V3error(ERR_R_MALLOC_FAILURE); | 483 | if (!CBS_get_u8(&cbs, &c)) |
481 | return NULL; | 484 | goto err; |
482 | } | 485 | if (!CBB_add_u8(&cbb, hex_digits[c >> 4])) |
483 | q = tmp; | 486 | goto err; |
484 | for (i = 0, p = buffer; i < len; i++, p++) { | 487 | if (!CBB_add_u8(&cbb, hex_digits[c & 0xf])) |
485 | *q++ = hexdig[(*p >> 4) & 0xf]; | 488 | goto err; |
486 | *q++ = hexdig[*p & 0xf]; | 489 | if (CBS_len(&cbs) > 0) { |
487 | *q++ = ':'; | 490 | if (!CBB_add_u8(&cbb, ':')) |
491 | goto err; | ||
492 | } | ||
488 | } | 493 | } |
489 | q[-1] = 0; | 494 | |
490 | return tmp; | 495 | if (!CBB_add_u8(&cbb, '\0')) |
496 | goto err; | ||
497 | |||
498 | if (!CBB_finish(&cbb, &out, &out_len)) | ||
499 | goto err; | ||
500 | |||
501 | err: | ||
502 | CBB_cleanup(&cbb); | ||
503 | |||
504 | return out; | ||
491 | } | 505 | } |
492 | LCRYPTO_ALIAS(hex_to_string); | 506 | LCRYPTO_ALIAS(hex_to_string); |
493 | 507 | ||
494 | /* Give a string of hex digits convert to | 508 | static int |
495 | * a buffer | 509 | x509_skip_colons_cbs(CBS *cbs) |
496 | */ | 510 | { |
511 | uint8_t c; | ||
512 | |||
513 | while (CBS_len(cbs) > 0) { | ||
514 | if (!CBS_peek_u8(cbs, &c)) | ||
515 | return 0; | ||
516 | if (c != ':') | ||
517 | return 1; | ||
518 | if (!CBS_get_u8(cbs, &c)) | ||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | return 1; | ||
523 | |||
524 | } | ||
525 | |||
526 | static int | ||
527 | x509_get_xdigit_nibble_cbs(CBS *cbs, uint8_t *out_nibble) { | ||
528 | uint8_t c; | ||
529 | |||
530 | if (!CBS_get_u8(cbs, &c)) | ||
531 | return 0; | ||
532 | |||
533 | if (c >= '0' && c <= '9') { | ||
534 | *out_nibble = c - '0'; | ||
535 | return 1; | ||
536 | } | ||
537 | if (c >= 'a' && c <= 'f') { | ||
538 | *out_nibble = c - 'a' + 10; | ||
539 | return 1; | ||
540 | } | ||
541 | if (c >= 'A' && c <= 'F') { | ||
542 | *out_nibble = c - 'A' + 10; | ||
543 | return 1; | ||
544 | } | ||
545 | |||
546 | X509V3error(X509V3_R_ILLEGAL_HEX_DIGIT); | ||
547 | return 0; | ||
548 | |||
549 | } | ||
497 | 550 | ||
498 | unsigned char * | 551 | unsigned char * |
499 | string_to_hex(const char *str, long *len) | 552 | string_to_hex(const char *str, long *len) |
500 | { | 553 | { |
501 | unsigned char *hexbuf, *q; | 554 | CBB cbb; |
502 | unsigned char ch, cl, *p; | 555 | CBS cbs; |
503 | if (!str) { | 556 | uint8_t *out = NULL; |
504 | X509V3error(X509V3_R_INVALID_NULL_ARGUMENT); | 557 | size_t out_len; |
505 | return NULL; | 558 | uint8_t hi, lo; |
506 | } | ||
507 | if (!(hexbuf = malloc(strlen(str) >> 1))) | ||
508 | goto err; | ||
509 | for (p = (unsigned char *)str, q = hexbuf; *p; ) { | ||
510 | ch = *p++; | ||
511 | if (ch == ':') | ||
512 | continue; | ||
513 | cl = *p++; | ||
514 | if (!cl) { | ||
515 | X509V3error(X509V3_R_ODD_NUMBER_OF_DIGITS); | ||
516 | free(hexbuf); | ||
517 | return NULL; | ||
518 | } | ||
519 | ch = tolower(ch); | ||
520 | cl = tolower(cl); | ||
521 | 559 | ||
522 | if ((ch >= '0') && (ch <= '9')) | 560 | *len = 0; |
523 | ch -= '0'; | ||
524 | else if ((ch >= 'a') && (ch <= 'f')) | ||
525 | ch -= 'a' - 10; | ||
526 | else | ||
527 | goto badhex; | ||
528 | 561 | ||
529 | if ((cl >= '0') && (cl <= '9')) | 562 | if (!CBB_init(&cbb, 0)) |
530 | cl -= '0'; | 563 | goto err; |
531 | else if ((cl >= 'a') && (cl <= 'f')) | ||
532 | cl -= 'a' - 10; | ||
533 | else | ||
534 | goto badhex; | ||
535 | 564 | ||
536 | *q++ = (ch << 4) | cl; | 565 | if (str == NULL) { |
566 | X509V3error(X509V3_R_INVALID_NULL_ARGUMENT); | ||
567 | goto err; | ||
568 | } | ||
569 | |||
570 | CBS_init(&cbs, str, strlen(str)); | ||
571 | while (CBS_len(&cbs) > 0) { | ||
572 | /* | ||
573 | * Skipping only a single colon between two pairs of digits | ||
574 | * would make more sense - history... | ||
575 | */ | ||
576 | if (!x509_skip_colons_cbs(&cbs)) | ||
577 | goto err; | ||
578 | /* Another historic idiocy. */ | ||
579 | if (CBS_len(&cbs) == 0) | ||
580 | break; | ||
581 | if (!x509_get_xdigit_nibble_cbs(&cbs, &hi)) | ||
582 | goto err; | ||
583 | if (CBS_len(&cbs) == 0) { | ||
584 | X509error(X509V3_R_ODD_NUMBER_OF_DIGITS); | ||
585 | goto err; | ||
586 | } | ||
587 | if (!x509_get_xdigit_nibble_cbs(&cbs, &lo)) | ||
588 | goto err; | ||
589 | if (!CBB_add_u8(&cbb, hi << 4 | lo)) | ||
590 | goto err; | ||
537 | } | 591 | } |
538 | 592 | ||
539 | if (len) | 593 | if (!CBB_finish(&cbb, &out, &out_len)) |
540 | *len = q - hexbuf; | 594 | goto err; |
595 | if (out_len > LONG_MAX) { | ||
596 | freezero(out, out_len); | ||
597 | out = NULL; | ||
598 | goto err; | ||
599 | } | ||
541 | 600 | ||
542 | return hexbuf; | 601 | *len = out_len; |
543 | 602 | ||
544 | err: | 603 | err: |
545 | free(hexbuf); | 604 | CBB_cleanup(&cbb); |
546 | X509V3error(ERR_R_MALLOC_FAILURE); | ||
547 | return NULL; | ||
548 | 605 | ||
549 | badhex: | 606 | return out; |
550 | free(hexbuf); | ||
551 | X509V3error(X509V3_R_ILLEGAL_HEX_DIGIT); | ||
552 | return NULL; | ||
553 | } | 607 | } |
554 | LCRYPTO_ALIAS(string_to_hex); | 608 | LCRYPTO_ALIAS(string_to_hex); |
555 | 609 | ||