Check HSM secret by comparing with backup mnemonic */
| 567 | |
| 568 | /* Check HSM secret by comparing with backup mnemonic */ |
| 569 | static void check_hsm(const char *hsm_secret_path) |
| 570 | { |
| 571 | struct secret file_secret, derived_secret; |
| 572 | u8 bip32_seed[BIP39_SEED_LEN_512]; |
| 573 | size_t bip32_seed_len; |
| 574 | const char *mnemonic_passphrase, *mnemonic; |
| 575 | enum hsm_secret_error err; |
| 576 | |
| 577 | /* Load the hsm_secret (handles decryption automatically if needed) */ |
| 578 | struct hsm_secret *hsms = load_hsm_secret(tmpctx, hsm_secret_path); |
| 579 | /* Extract first 32 bytes for legacy compatibility */ |
| 580 | memcpy(file_secret.data, hsms->secret_data, 32); |
| 581 | |
| 582 | /* Ask user for their backup mnemonic passphrase */ |
| 583 | printf("Warning: remember that different passphrases yield different " |
| 584 | "bitcoin wallets.\n"); |
| 585 | printf("If left empty, no password is used (echo is disabled).\n"); |
| 586 | printf("Enter your mnemonic passphrase: \n"); |
| 587 | fflush(stdout); |
| 588 | mnemonic_passphrase = read_stdin_pass(tmpctx, &err); |
| 589 | if (!mnemonic_passphrase) |
| 590 | errx(EXITCODE_ERROR_HSM_FILE, "Could not read passphrase: %s", hsm_secret_error_str(err)); |
| 591 | if (streq(mnemonic_passphrase, "")) { |
| 592 | mnemonic_passphrase = NULL; |
| 593 | } |
| 594 | |
| 595 | /* Ask user for their backup mnemonic using consistent interface */ |
| 596 | mnemonic = read_stdin_mnemonic(tmpctx, &err); |
| 597 | if (!mnemonic) |
| 598 | errx(EXITCODE_ERROR_HSM_FILE, "Could not read mnemonic: %s", hsm_secret_error_str(err)); |
| 599 | |
| 600 | /* Derive seed from user's backup mnemonic + passphrase */ |
| 601 | if (bip39_mnemonic_to_seed(mnemonic, mnemonic_passphrase, bip32_seed, sizeof(bip32_seed), &bip32_seed_len) != WALLY_OK) |
| 602 | errx(ERROR_LIBWALLY, "Unable to derive BIP32 seed from BIP39 mnemonic"); |
| 603 | |
| 604 | /* Copy first 32 bytes to our secret for comparison */ |
| 605 | memcpy(derived_secret.data, bip32_seed, sizeof(derived_secret.data)); |
| 606 | |
| 607 | /* Compare the seeds */ |
| 608 | if (memcmp(derived_secret.data, file_secret.data, sizeof(file_secret.data)) != 0) |
| 609 | errx(ERROR_KEYDERIV, "resulting hsm_secret did not match"); |
| 610 | |
| 611 | printf("OK\n"); |
| 612 | } |
| 613 | |
| 614 | static void make_rune(const char *hsm_secret_path) |
| 615 | { |
no test coverage detected