diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/libcrypto/bn/bn_convert.c | 347 |
1 files changed, 224 insertions, 123 deletions
diff --git a/src/lib/libcrypto/bn/bn_convert.c b/src/lib/libcrypto/bn/bn_convert.c index 65834ffd1e..1a3abbc603 100644 --- a/src/lib/libcrypto/bn/bn_convert.c +++ b/src/lib/libcrypto/bn/bn_convert.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: bn_convert.c,v 1.8 2023/05/09 05:15:55 jsing Exp $ */ | 1 | /* $OpenBSD: bn_convert.c,v 1.9 2023/05/28 10:34:17 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 | * |
| @@ -70,6 +70,9 @@ | |||
| 70 | #include "bn_local.h" | 70 | #include "bn_local.h" |
| 71 | #include "bytestring.h" | 71 | #include "bytestring.h" |
| 72 | 72 | ||
| 73 | static int bn_dec2bn_cbs(BIGNUM **bnp, CBS *cbs); | ||
| 74 | static int bn_hex2bn_cbs(BIGNUM **bnp, CBS *cbs); | ||
| 75 | |||
| 73 | static const char hex_digits[] = "0123456789ABCDEF"; | 76 | static const char hex_digits[] = "0123456789ABCDEF"; |
| 74 | 77 | ||
| 75 | typedef enum { | 78 | typedef enum { |
| @@ -253,21 +256,53 @@ BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret) | |||
| 253 | } | 256 | } |
| 254 | 257 | ||
| 255 | int | 258 | int |
| 256 | BN_asc2bn(BIGNUM **bn, const char *a) | 259 | BN_asc2bn(BIGNUM **bnp, const char *s) |
| 257 | { | 260 | { |
| 258 | const char *p = a; | 261 | CBS cbs, cbs_hex; |
| 259 | if (*p == '-') | 262 | size_t s_len; |
| 260 | p++; | 263 | uint8_t v; |
| 264 | int neg; | ||
| 261 | 265 | ||
| 262 | if (p[0] == '0' && (p[1] == 'X' || p[1] == 'x')) { | 266 | if (bnp != NULL && *bnp != NULL) |
| 263 | if (!BN_hex2bn(bn, p + 2)) | 267 | BN_zero(*bnp); |
| 264 | return 0; | 268 | |
| 265 | } else { | 269 | if (s == NULL) |
| 266 | if (!BN_dec2bn(bn, p)) | 270 | return 0; |
| 271 | if ((s_len = strlen(s)) == 0) | ||
| 272 | return 0; | ||
| 273 | |||
| 274 | CBS_init(&cbs, s, s_len); | ||
| 275 | |||
| 276 | /* Handle negative sign. */ | ||
| 277 | if (!CBS_peek_u8(&cbs, &v)) | ||
| 278 | return 0; | ||
| 279 | if ((neg = (v == '-'))) { | ||
| 280 | if (!CBS_skip(&cbs, 1)) | ||
| 267 | return 0; | 281 | return 0; |
| 268 | } | 282 | } |
| 269 | if (*a == '-') | 283 | |
| 270 | BN_set_negative(*bn, 1); | 284 | /* Try parsing as hexidecimal with a 0x prefix. */ |
| 285 | CBS_dup(&cbs, &cbs_hex); | ||
| 286 | if (!CBS_get_u8(&cbs_hex, &v)) | ||
| 287 | goto decimal; | ||
| 288 | if (v != '0') | ||
| 289 | goto decimal; | ||
| 290 | if (!CBS_get_u8(&cbs_hex, &v)) | ||
| 291 | goto decimal; | ||
| 292 | if (v != 'X' && v != 'x') | ||
| 293 | goto decimal; | ||
| 294 | if (!bn_hex2bn_cbs(bnp, &cbs_hex)) | ||
| 295 | return 0; | ||
| 296 | |||
| 297 | goto done; | ||
| 298 | |||
| 299 | decimal: | ||
| 300 | if (!bn_dec2bn_cbs(bnp, &cbs)) | ||
| 301 | return 0; | ||
| 302 | |||
| 303 | done: | ||
| 304 | BN_set_negative(*bnp, neg); | ||
| 305 | |||
| 271 | return 1; | 306 | return 1; |
| 272 | } | 307 | } |
| 273 | 308 | ||
| @@ -349,73 +384,108 @@ BN_bn2dec(const BIGNUM *bn) | |||
| 349 | return s; | 384 | return s; |
| 350 | } | 385 | } |
| 351 | 386 | ||
| 352 | int | 387 | static int |
| 353 | BN_dec2bn(BIGNUM **bn, const char *a) | 388 | bn_dec2bn_cbs(BIGNUM **bnp, CBS *cbs) |
| 354 | { | 389 | { |
| 355 | BIGNUM *ret = NULL; | 390 | CBS cbs_digits; |
| 356 | BN_ULONG l = 0; | 391 | BIGNUM *bn = NULL; |
| 357 | int neg = 0, i, j; | 392 | int d, neg, num; |
| 358 | int num; | 393 | size_t digits = 0; |
| 394 | BN_ULONG w; | ||
| 395 | uint8_t v; | ||
| 359 | 396 | ||
| 360 | if ((a == NULL) || (*a == '\0')) | 397 | /* Handle negative sign. */ |
| 361 | return (0); | 398 | if (!CBS_peek_u8(cbs, &v)) |
| 362 | if (*a == '-') { | 399 | goto err; |
| 363 | neg = 1; | 400 | if ((neg = (v == '-'))) { |
| 364 | a++; | 401 | if (!CBS_skip(cbs, 1)) |
| 402 | goto err; | ||
| 365 | } | 403 | } |
| 366 | 404 | ||
| 367 | for (i = 0; i <= (INT_MAX / 4) && isdigit((unsigned char)a[i]); i++) | 405 | /* Scan to find last decimal digit. */ |
| 368 | ; | 406 | CBS_dup(cbs, &cbs_digits); |
| 369 | if (i > INT_MAX / 4) | 407 | while (CBS_len(&cbs_digits) > 0) { |
| 370 | return (0); | 408 | if (!CBS_get_u8(&cbs_digits, &v)) |
| 371 | 409 | goto err; | |
| 372 | num = i + neg; | 410 | if (!isdigit(v)) |
| 373 | if (bn == NULL) | 411 | break; |
| 374 | return (num); | 412 | digits++; |
| 375 | |||
| 376 | /* a is the start of the digits, and it is 'i' long. | ||
| 377 | * We chop it into BN_DEC_NUM digits at a time */ | ||
| 378 | if (*bn == NULL) { | ||
| 379 | if ((ret = BN_new()) == NULL) | ||
| 380 | return (0); | ||
| 381 | } else { | ||
| 382 | ret = *bn; | ||
| 383 | BN_zero(ret); | ||
| 384 | } | 413 | } |
| 414 | if (digits > INT_MAX / 4) | ||
| 415 | goto err; | ||
| 385 | 416 | ||
| 386 | /* i is the number of digits, a bit of an over expand */ | 417 | num = digits + neg; |
| 387 | if (!bn_expand(ret, i * 4)) | 418 | |
| 419 | if (bnp == NULL) | ||
| 420 | return num; | ||
| 421 | |||
| 422 | if ((bn = *bnp) == NULL) | ||
| 423 | bn = BN_new(); | ||
| 424 | if (bn == NULL) | ||
| 425 | goto err; | ||
| 426 | if (!bn_expand(bn, digits * 4)) | ||
| 388 | goto err; | 427 | goto err; |
| 389 | 428 | ||
| 390 | j = BN_DEC_NUM - (i % BN_DEC_NUM); | 429 | if ((d = digits % BN_DEC_NUM) == 0) |
| 391 | if (j == BN_DEC_NUM) | 430 | d = BN_DEC_NUM; |
| 392 | j = 0; | 431 | |
| 393 | l = 0; | 432 | w = 0; |
| 394 | while (*a) { | 433 | |
| 395 | l *= 10; | 434 | /* Work forwards from most significant digit. */ |
| 396 | l += *a - '0'; | 435 | while (digits-- > 0) { |
| 397 | a++; | 436 | if (!CBS_get_u8(cbs, &v)) |
| 398 | if (++j == BN_DEC_NUM) { | 437 | goto err; |
| 399 | if (!BN_mul_word(ret, BN_DEC_CONV)) | 438 | |
| 439 | if (v < '0' || v > '9') | ||
| 440 | goto err; | ||
| 441 | |||
| 442 | v -= '0'; | ||
| 443 | w = w * 10 + v; | ||
| 444 | d--; | ||
| 445 | |||
| 446 | if (d == 0) { | ||
| 447 | if (!BN_mul_word(bn, BN_DEC_CONV)) | ||
| 400 | goto err; | 448 | goto err; |
| 401 | if (!BN_add_word(ret, l)) | 449 | if (!BN_add_word(bn, w)) |
| 402 | goto err; | 450 | goto err; |
| 403 | l = 0; | 451 | |
| 404 | j = 0; | 452 | d = BN_DEC_NUM; |
| 453 | w = 0; | ||
| 405 | } | 454 | } |
| 406 | } | 455 | } |
| 407 | 456 | ||
| 408 | bn_correct_top(ret); | 457 | bn_correct_top(bn); |
| 409 | 458 | ||
| 410 | BN_set_negative(ret, neg); | 459 | BN_set_negative(bn, neg); |
| 411 | 460 | ||
| 412 | *bn = ret; | 461 | *bnp = bn; |
| 413 | return (num); | ||
| 414 | 462 | ||
| 415 | err: | 463 | return num; |
| 416 | if (*bn == NULL) | 464 | |
| 417 | BN_free(ret); | 465 | err: |
| 418 | return (0); | 466 | if (bnp != NULL && *bnp == NULL) |
| 467 | BN_free(bn); | ||
| 468 | |||
| 469 | return 0; | ||
| 470 | } | ||
| 471 | |||
| 472 | int | ||
| 473 | BN_dec2bn(BIGNUM **bnp, const char *s) | ||
| 474 | { | ||
| 475 | size_t s_len; | ||
| 476 | CBS cbs; | ||
| 477 | |||
| 478 | if (bnp != NULL && *bnp != NULL) | ||
| 479 | BN_zero(*bnp); | ||
| 480 | |||
| 481 | if (s == NULL) | ||
| 482 | return 0; | ||
| 483 | if ((s_len = strlen(s)) == 0) | ||
| 484 | return 0; | ||
| 485 | |||
| 486 | CBS_init(&cbs, s, s_len); | ||
| 487 | |||
| 488 | return bn_dec2bn_cbs(bnp, &cbs); | ||
| 419 | } | 489 | } |
| 420 | 490 | ||
| 421 | char * | 491 | char * |
| @@ -463,81 +533,112 @@ BN_bn2hex(const BIGNUM *bn) | |||
| 463 | return s; | 533 | return s; |
| 464 | } | 534 | } |
| 465 | 535 | ||
| 466 | int | 536 | static int |
| 467 | BN_hex2bn(BIGNUM **bn, const char *a) | 537 | bn_hex2bn_cbs(BIGNUM **bnp, CBS *cbs) |
| 468 | { | 538 | { |
| 469 | BIGNUM *ret = NULL; | 539 | CBS cbs_digits; |
| 470 | BN_ULONG l = 0; | 540 | BIGNUM *bn = NULL; |
| 471 | int neg = 0, h, m, i,j, k, c; | 541 | int b, i, neg, num; |
| 472 | int num; | 542 | size_t digits = 0; |
| 543 | BN_ULONG w; | ||
| 544 | uint8_t v; | ||
| 473 | 545 | ||
| 474 | if ((a == NULL) || (*a == '\0')) | 546 | /* Handle negative sign. */ |
| 475 | return (0); | 547 | if (!CBS_peek_u8(cbs, &v)) |
| 548 | goto err; | ||
| 549 | if ((neg = (v == '-'))) { | ||
| 550 | if (!CBS_skip(cbs, 1)) | ||
| 551 | goto err; | ||
| 552 | } | ||
| 476 | 553 | ||
| 477 | if (*a == '-') { | 554 | /* Scan to find last hexadecimal digit. */ |
| 478 | neg = 1; | 555 | CBS_dup(cbs, &cbs_digits); |
| 479 | a++; | 556 | while (CBS_len(&cbs_digits) > 0) { |
| 557 | if (!CBS_get_u8(&cbs_digits, &v)) | ||
| 558 | goto err; | ||
| 559 | if (!isxdigit(v)) | ||
| 560 | break; | ||
| 561 | digits++; | ||
| 480 | } | 562 | } |
| 563 | if (digits > INT_MAX / 4) | ||
| 564 | goto err; | ||
| 481 | 565 | ||
| 482 | for (i = 0; i <= (INT_MAX / 4) && isxdigit((unsigned char)a[i]); i++) | 566 | num = digits + neg; |
| 483 | ; | 567 | |
| 484 | if (i > INT_MAX / 4) | 568 | if (bnp == NULL) |
| 485 | return (0); | 569 | return num; |
| 486 | 570 | ||
| 487 | num = i + neg; | 571 | if ((bn = *bnp) == NULL) |
| 572 | bn = BN_new(); | ||
| 488 | if (bn == NULL) | 573 | if (bn == NULL) |
| 489 | return (num); | 574 | goto err; |
| 490 | 575 | if (!bn_expand(bn, digits * 4)) | |
| 491 | /* a is the start of the hex digits, and it is 'i' long */ | 576 | goto err; |
| 492 | if (*bn == NULL) { | ||
| 493 | if ((ret = BN_new()) == NULL) | ||
| 494 | return (0); | ||
| 495 | } else { | ||
| 496 | ret = *bn; | ||
| 497 | BN_zero(ret); | ||
| 498 | } | ||
| 499 | 577 | ||
| 500 | /* i is the number of hex digits */ | 578 | if (!CBS_get_bytes(cbs, cbs, digits)) |
| 501 | if (!bn_expand(ret, i * 4)) | ||
| 502 | goto err; | 579 | goto err; |
| 503 | 580 | ||
| 504 | j = i; /* least significant 'hex' */ | 581 | b = BN_BITS2; |
| 505 | m = 0; | 582 | i = 0; |
| 506 | h = 0; | 583 | w = 0; |
| 507 | while (j > 0) { | 584 | |
| 508 | m = ((BN_BYTES * 2) <= j) ? (BN_BYTES * 2) : j; | 585 | /* Work backwards from least significant digit. */ |
| 509 | l = 0; | 586 | while (digits-- > 0) { |
| 510 | for (;;) { | 587 | if (!CBS_get_last_u8(cbs, &v)) |
| 511 | c = a[j - m]; | 588 | goto err; |
| 512 | if ((c >= '0') && (c <= '9')) | 589 | |
| 513 | k = c - '0'; | 590 | if (v >= '0' && v <= '9') |
| 514 | else if ((c >= 'a') && (c <= 'f')) | 591 | v -= '0'; |
| 515 | k = c - 'a' + 10; | 592 | else if (v >= 'a' && v <= 'f') |
| 516 | else if ((c >= 'A') && (c <= 'F')) | 593 | v -= 'a' - 10; |
| 517 | k = c - 'A' + 10; | 594 | else if (v >= 'A' && v <= 'F') |
| 518 | else | 595 | v -= 'A' - 10; |
| 519 | k = 0; /* paranoia */ | 596 | else |
| 520 | l = (l << 4) | k; | 597 | goto err; |
| 521 | 598 | ||
| 522 | if (--m <= 0) { | 599 | w |= (BN_ULONG)v << (BN_BITS2 - b); |
| 523 | ret->d[h++] = l; | 600 | b -= 4; |
| 524 | break; | 601 | |
| 525 | } | 602 | if (b == 0 || digits == 0) { |
| 603 | b = BN_BITS2; | ||
| 604 | bn->d[i++] = w; | ||
| 605 | w = 0; | ||
| 526 | } | 606 | } |
| 527 | j -= (BN_BYTES * 2); | ||
| 528 | } | 607 | } |
| 529 | ret->top = h; | ||
| 530 | bn_correct_top(ret); | ||
| 531 | 608 | ||
| 532 | BN_set_negative(ret, neg); | 609 | bn->top = i; |
| 610 | bn_correct_top(bn); | ||
| 611 | |||
| 612 | BN_set_negative(bn, neg); | ||
| 613 | |||
| 614 | *bnp = bn; | ||
| 615 | |||
| 616 | return num; | ||
| 617 | |||
| 618 | err: | ||
| 619 | if (bnp != NULL && *bnp == NULL) | ||
| 620 | BN_free(bn); | ||
| 621 | |||
| 622 | return 0; | ||
| 623 | } | ||
| 624 | |||
| 625 | int | ||
| 626 | BN_hex2bn(BIGNUM **bnp, const char *s) | ||
| 627 | { | ||
| 628 | size_t s_len; | ||
| 629 | CBS cbs; | ||
| 630 | |||
| 631 | if (bnp != NULL && *bnp != NULL) | ||
| 632 | BN_zero(*bnp); | ||
| 633 | |||
| 634 | if (s == NULL) | ||
| 635 | return 0; | ||
| 636 | if ((s_len = strlen(s)) == 0) | ||
| 637 | return 0; | ||
| 533 | 638 | ||
| 534 | *bn = ret; | 639 | CBS_init(&cbs, s, s_len); |
| 535 | return (num); | ||
| 536 | 640 | ||
| 537 | err: | 641 | return bn_hex2bn_cbs(bnp, &cbs); |
| 538 | if (*bn == NULL) | ||
| 539 | BN_free(ret); | ||
| 540 | return (0); | ||
| 541 | } | 642 | } |
| 542 | 643 | ||
| 543 | int | 644 | int |
