13 #include <linux/random.h>
14 #include <libscrypt.h>
15 #include <sodium/crypto_stream_chacha20.h>
19 char *read_passphrase(const char *prompt)
21 struct termios old, new;
26 fprintf(stderr, "%s", prompt);
29 if (tcgetattr(fileno(stdin), &old))
30 die("error getting terminal attrs");
34 if (tcsetattr(fileno(stdin), TCSAFLUSH, &new))
35 die("error setting terminal attrs");
37 ret = getline(&buf, &buflen, stdin);
39 die("error reading passphrase");
41 tcsetattr(fileno(stdin), TCSAFLUSH, &old);
42 fprintf(stderr, "\n");
46 void derive_passphrase(struct bcache_key *key, const char *passphrase)
48 const unsigned char salt[] = "bcache";
51 ret = libscrypt_scrypt((void *) passphrase, strlen(passphrase),
53 SCRYPT_N, SCRYPT_r, SCRYPT_p,
54 (void *) key, sizeof(*key));
56 die("scrypt error: %i", ret);
59 void disk_key_encrypt(struct bcache_disk_key *disk_key,
60 struct bcache_key *key)
64 ret = crypto_stream_chacha20_xor((void *) disk_key,
65 (void *) disk_key, sizeof(*disk_key),
66 (void *) &bch_master_key_nonce,
69 die("chacha20 error: %i", ret);
72 void disk_key_init(struct bcache_disk_key *disk_key)
76 memcpy(&disk_key->header, bch_key_header, sizeof(bch_key_header));
78 ret = getrandom(disk_key->key, sizeof(disk_key->key), GRND_RANDOM);
79 if (ret != sizeof(disk_key->key))
80 die("error getting random bytes for key");
82 int fd = open("/dev/random", O_RDONLY|O_NONBLOCK);
84 die("error opening /dev/random");
87 struct timespec start;
90 clock_gettime(CLOCK_MONOTONIC, &start);
92 while (n < sizeof(disk_key->key)) {
93 struct timeval timeout = { 1, 0 };
99 if (select(fd + 1, &set, NULL, NULL, &timeout) < 0)
103 (void *) disk_key->key + n,
104 sizeof(disk_key->key) - n);
105 if (ret == -1 && errno != EINTR && errno != EAGAIN)
106 die("error reading from /dev/random");
111 clock_gettime(CLOCK_MONOTONIC, &now);
113 now.tv_sec -= start.tv_sec;
114 now.tv_nsec -= start.tv_nsec;
116 while (now.tv_nsec < 0) {
117 long nsec_per_sec = 1000 * 1000 * 1000;
118 long sec = now.tv_nsec / nsec_per_sec - 1;
119 now.tv_nsec -= sec * nsec_per_sec;
123 if (!printed && now.tv_sec >= 3) {
124 printf("Reading from /dev/random is taking a long time...\n)");