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;
25 fprintf(stderr, "%s", prompt);
28 if (tcgetattr(fileno(stdin), &old))
29 die("error getting terminal attrs");
33 if (tcsetattr(fileno(stdin), TCSAFLUSH, &new))
34 die("error setting terminal attrs");
36 if (getline(&buf, &buflen, stdin) <= 0)
37 die("error reading passphrase");
39 tcsetattr(fileno(stdin), TCSAFLUSH, &old);
40 fprintf(stderr, "\n");
44 void derive_passphrase(struct bcache_key *key, const char *passphrase)
46 const unsigned char salt[] = "bcache";
49 ret = libscrypt_scrypt((void *) passphrase, strlen(passphrase),
51 SCRYPT_N, SCRYPT_r, SCRYPT_p,
52 (void *) key, sizeof(*key));
54 die("scrypt error: %i", ret);
57 void disk_key_encrypt(struct cache_sb *sb,
58 struct bcache_disk_key *disk_key,
59 struct bcache_key *key)
64 memcpy(nonce, &sb->set_magic, sizeof(sb->set_magic));
66 ret = crypto_stream_chacha20_xor((void *) disk_key,
67 (void *) disk_key, sizeof(*disk_key),
71 die("chacha20 error: %i", ret);
74 void disk_key_init(struct bcache_disk_key *disk_key)
78 memcpy(&disk_key->header, bch_key_header, sizeof(bch_key_header));
80 ret = getrandom(disk_key->key, sizeof(disk_key->key), GRND_RANDOM);
81 if (ret != sizeof(disk_key->key))
82 die("error getting random bytes for key");
84 int fd = open("/dev/random", O_RDONLY|O_NONBLOCK);
86 die("error opening /dev/random");
89 struct timespec start;
92 clock_gettime(CLOCK_MONOTONIC, &start);
94 while (n < sizeof(disk_key->key)) {
95 struct timeval timeout = { 1, 0 };
101 if (select(fd + 1, &set, NULL, NULL, &timeout) < 0)
105 (void *) disk_key->key + n,
106 sizeof(disk_key->key) - n);
107 if (ret == -1 && errno != EINTR && errno != EAGAIN)
108 die("error reading from /dev/random");
113 clock_gettime(CLOCK_MONOTONIC, &now);
115 now.tv_sec -= start.tv_sec;
116 now.tv_nsec -= start.tv_nsec;
118 while (now.tv_nsec < 0) {
119 long nsec_per_sec = 1000 * 1000 * 1000;
120 long sec = now.tv_nsec / nsec_per_sec - 1;
121 now.tv_nsec -= sec * nsec_per_sec;
125 if (!printed && now.tv_sec >= 3) {
126 printf("Reading from /dev/random is taking a long time...\n)");