| 1342 | } |
| 1343 | |
| 1344 | static char *opt_set_hsm_secret(const char *arg, struct lightningd *ld) |
| 1345 | { |
| 1346 | char *err; |
| 1347 | const struct hsm_secret *hsm_secret; |
| 1348 | |
| 1349 | err = hsm_secret_arg(tmpctx, arg, &hsm_secret); |
| 1350 | if (err) |
| 1351 | return err; |
| 1352 | |
| 1353 | /* Checks if hsm_secret exists */ |
| 1354 | int fd = open("hsm_secret", O_CREAT|O_EXCL|O_WRONLY, 0400); |
| 1355 | if (fd < 0) { |
| 1356 | /* Don't do anything if the file already exists. */ |
| 1357 | if (errno == EEXIST) |
| 1358 | return tal_fmt(tmpctx, "hsm_secret already exists!"); |
| 1359 | |
| 1360 | return tal_fmt(tmpctx, "Creating hsm_secret: %s", |
| 1361 | strerror(errno)); |
| 1362 | } |
| 1363 | |
| 1364 | switch (hsm_secret->type) { |
| 1365 | case HSM_SECRET_PLAIN: |
| 1366 | /* Legacy 32-byte format */ |
| 1367 | if (!write_all(fd, hsm_secret->secret_data, tal_count(hsm_secret->secret_data))) { |
| 1368 | unlink_noerr("hsm_secret"); |
| 1369 | return tal_fmt(tmpctx, "Writing HSM: %s", |
| 1370 | strerror(errno)); |
| 1371 | } |
| 1372 | break; |
| 1373 | case HSM_SECRET_ENCRYPTED: |
| 1374 | case HSM_SECRET_MNEMONIC_WITH_PASS: |
| 1375 | return tal_fmt(tmpctx, "Recovery of encrypted/passworded secrets not supported"); |
| 1376 | case HSM_SECRET_MNEMONIC_NO_PASS: { |
| 1377 | struct sha256 seed_hash; |
| 1378 | if (!derive_seed_hash(hsm_secret->mnemonic, NULL, &seed_hash)) { |
| 1379 | unlink_noerr("hsm_secret"); |
| 1380 | return tal_fmt(tmpctx, "Deriving from mnemonic failed!"); |
| 1381 | } |
| 1382 | /* Write seed hash (32 bytes) + mnemonic */ |
| 1383 | if (!write_all(fd, &seed_hash, sizeof(seed_hash)) |
| 1384 | || !write_all(fd, hsm_secret->mnemonic, strlen(hsm_secret->mnemonic))) { |
| 1385 | unlink_noerr("hsm_secret"); |
| 1386 | return tal_fmt(tmpctx, "Error writing to hsm_secret file: %s", strerror(errno)); |
| 1387 | } |
| 1388 | break; |
| 1389 | } |
| 1390 | case HSM_SECRET_INVALID: |
| 1391 | /* Shouldn't happen? */ |
| 1392 | unlink_noerr("hsm_secret"); |
| 1393 | return tal_fmt(tmpctx, "invalid hsm secret?"); |
| 1394 | } |
| 1395 | |
| 1396 | /*~ fsync (mostly!) ensures that the file has reached the disk. */ |
| 1397 | if (fsync(fd) != 0) { |
| 1398 | unlink_noerr("hsm_secret"); |
| 1399 | return tal_fmt(tmpctx, "fsync: %s", strerror(errno)); |
| 1400 | } |
| 1401 | /*~ This should never fail if fsync succeeded. But paranoia good, and |
nothing calls this directly
no test coverage detected