summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authortb <>2023-05-12 13:56:17 +0000
committertb <>2023-05-12 13:56:17 +0000
commitb345c57b28722f9d99b4f658837e895ba199555b (patch)
tree3b81e8e07c4ef4750171db0536d98ab2381ad47c /src/lib
parentc68792ad5f1a5c23b89cce981773d589934ec0f5 (diff)
downloadopenbsd-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.c194
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
70static char *bn_to_string(const BIGNUM *bn); 72static char *bn_to_string(const BIGNUM *bn);
71static char *strip_spaces(char *name); 73static char *strip_spaces(char *name);
72static int sk_strcmp(const char * const *a, const char * const *b); 74static 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 */ 464static 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 */
467char * 466char *
468hex_to_string(const unsigned char *buffer, long len) 467hex_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}
492LCRYPTO_ALIAS(hex_to_string); 506LCRYPTO_ALIAS(hex_to_string);
493 507
494/* Give a string of hex digits convert to 508static int
495 * a buffer 509x509_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
526static int
527x509_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
498unsigned char * 551unsigned char *
499string_to_hex(const char *str, long *len) 552string_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}
554LCRYPTO_ALIAS(string_to_hex); 608LCRYPTO_ALIAS(string_to_hex);
555 609