| 301 | } |
| 302 | |
| 303 | static void create_hsm(int fd, const char *passphrase) |
| 304 | { |
| 305 | u8 *hsm_secret_data; |
| 306 | int ret; |
| 307 | /* Always create a mnemonic-based hsm_secret */ |
| 308 | u8 entropy[BIP39_ENTROPY_LEN_128]; |
| 309 | char *mnemonic = NULL; |
| 310 | struct sha256 seed_hash; |
| 311 | |
| 312 | /* Initialize wally tal context for libwally operations */ |
| 313 | |
| 314 | /* Generate random entropy for new mnemonic */ |
| 315 | randbytes(entropy, sizeof(entropy)); |
| 316 | |
| 317 | /* Generate mnemonic from entropy */ |
| 318 | tal_wally_start(); |
| 319 | ret = bip39_mnemonic_from_bytes(NULL, entropy, sizeof(entropy), &mnemonic); |
| 320 | tal_wally_end(tmpctx); |
| 321 | |
| 322 | if (ret != WALLY_OK) { |
| 323 | unlink_noerr("hsm_secret"); |
| 324 | hsmd_send_init_reply_failure(HSM_SECRET_ERR_SEED_DERIVATION_FAILED, STATUS_FAIL_INTERNAL_ERROR, |
| 325 | "Failed to generate mnemonic from entropy"); |
| 326 | } |
| 327 | |
| 328 | if (!mnemonic) { |
| 329 | unlink_noerr("hsm_secret"); |
| 330 | hsmd_send_init_reply_failure(HSM_SECRET_ERR_SEED_DERIVATION_FAILED, STATUS_FAIL_INTERNAL_ERROR, |
| 331 | "Failed to get generated mnemonic"); |
| 332 | } |
| 333 | |
| 334 | /* Derive seed hash from mnemonic + passphrase (or zero if no passphrase) */ |
| 335 | if (!derive_seed_hash(mnemonic, passphrase, &seed_hash)) { |
| 336 | unlink_noerr("hsm_secret"); |
| 337 | hsmd_send_init_reply_failure(HSM_SECRET_ERR_SEED_DERIVATION_FAILED, STATUS_FAIL_INTERNAL_ERROR, |
| 338 | "Failed to derive seed hash from mnemonic"); |
| 339 | } |
| 340 | |
| 341 | /* Create hsm_secret format: seed_hash (32 bytes) + mnemonic */ |
| 342 | hsm_secret_data = tal_arr(tmpctx, u8, 0); |
| 343 | towire_sha256(&hsm_secret_data, &seed_hash); |
| 344 | towire(&hsm_secret_data, mnemonic, strlen(mnemonic)); |
| 345 | |
| 346 | /* Derive the actual secret from mnemonic + passphrase for our global hsm_secret */ |
| 347 | u8 bip32_seed[BIP39_SEED_LEN_512]; |
| 348 | size_t bip32_seed_len; |
| 349 | |
| 350 | tal_wally_start(); |
| 351 | ret = bip39_mnemonic_to_seed(mnemonic, passphrase, bip32_seed, sizeof(bip32_seed), &bip32_seed_len); |
| 352 | tal_wally_end(tmpctx); |
| 353 | if (ret != WALLY_OK) { |
| 354 | unlink_noerr("hsm_secret"); |
| 355 | hsmd_send_init_reply_failure(HSM_SECRET_ERR_SEED_DERIVATION_FAILED, STATUS_FAIL_INTERNAL_ERROR, |
| 356 | "Failed to derive seed from mnemonic"); |
| 357 | } |
| 358 | |
| 359 | /* Write the hsm_secret data to file */ |
| 360 | if (!write_all(fd, hsm_secret_data, tal_count(hsm_secret_data))) { |
no test coverage detected