| 224 | } |
| 225 | |
| 226 | static int encrypt_hsm(const char *hsm_secret_path) |
| 227 | { |
| 228 | int fd; |
| 229 | struct secret key, hsm_secret; |
| 230 | struct encrypted_hsm_secret encrypted_hsm_secret; |
| 231 | char *passwd, *passwd_confirmation, *err; |
| 232 | const char *dir, *backup; |
| 233 | int exit_code = 0; |
| 234 | |
| 235 | /* This checks the file existence, too. */ |
| 236 | if (hsm_secret_is_encrypted(hsm_secret_path)) |
| 237 | errx(ERROR_USAGE, "hsm_secret is already encrypted"); |
| 238 | |
| 239 | printf("Enter hsm_secret password:\n"); |
| 240 | fflush(stdout); |
| 241 | passwd = read_stdin_pass_with_exit_code(&err, &exit_code); |
| 242 | if (!passwd) |
| 243 | errx(exit_code, "%s", err); |
| 244 | printf("Confirm hsm_secret password:\n"); |
| 245 | fflush(stdout); |
| 246 | passwd_confirmation = read_stdin_pass_with_exit_code(&err, &exit_code); |
| 247 | if (!passwd_confirmation) |
| 248 | errx(exit_code, "%s", err); |
| 249 | if (!streq(passwd, passwd_confirmation)) |
| 250 | errx(ERROR_USAGE, "Passwords confirmation mismatch."); |
| 251 | get_hsm_secret(&hsm_secret, hsm_secret_path); |
| 252 | |
| 253 | dir = path_dirname(NULL, hsm_secret_path); |
| 254 | backup = path_join(dir, dir, "hsm_secret.backup"); |
| 255 | |
| 256 | if (sodium_init() == -1) |
| 257 | errx(ERROR_LIBSODIUM, |
| 258 | "Could not initialize libsodium. Not enough entropy ?"); |
| 259 | |
| 260 | /* Derive the encryption key from the password provided, and try to encrypt |
| 261 | * the seed. */ |
| 262 | exit_code = hsm_secret_encryption_key_with_exitcode(passwd, &key, &err); |
| 263 | if (exit_code > 0) |
| 264 | errx(exit_code, "%s", err); |
| 265 | if (!encrypt_hsm_secret(&key, &hsm_secret, &encrypted_hsm_secret)) |
| 266 | errx(ERROR_LIBSODIUM, "Could not encrypt the hsm_secret seed."); |
| 267 | |
| 268 | /* Once the encryption key derived, we don't need it anymore. */ |
| 269 | free(passwd); |
| 270 | free(passwd_confirmation); |
| 271 | |
| 272 | /* Create a backup file, "just in case". */ |
| 273 | rename(hsm_secret_path, backup); |
| 274 | fd = open(hsm_secret_path, O_CREAT|O_EXCL|O_WRONLY, 0400); |
| 275 | if (fd < 0) |
| 276 | errx(EXITCODE_ERROR_HSM_FILE, "Could not open new hsm_secret"); |
| 277 | |
| 278 | /* Write the encrypted hsm_secret. */ |
| 279 | if (!write_all(fd, encrypted_hsm_secret.data, |
| 280 | sizeof(encrypted_hsm_secret.data))) { |
| 281 | unlink_noerr(hsm_secret_path); |
| 282 | close(fd); |
| 283 | rename(backup, hsm_secret_path); |
no test coverage detected