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 cache_sb *sb,
60 struct bcache_disk_key *disk_key,
61 struct bcache_key *key)
66 memcpy(nonce, &sb->set_magic, sizeof(sb->set_magic));
68 ret = crypto_stream_chacha20_xor((void *) disk_key,
69 (void *) disk_key, sizeof(*disk_key),
73 die("chacha20 error: %i", ret);
76 void disk_key_init(struct bcache_disk_key *disk_key)
80 memcpy(&disk_key->header, bch_key_header, sizeof(bch_key_header));
82 ret = getrandom(disk_key->key, sizeof(disk_key->key), GRND_RANDOM);
83 if (ret != sizeof(disk_key->key))
84 die("error getting random bytes for key");
86 int fd = open("/dev/random", O_RDONLY|O_NONBLOCK);
88 die("error opening /dev/random");
91 struct timespec start;
94 clock_gettime(CLOCK_MONOTONIC, &start);
96 while (n < sizeof(disk_key->key)) {
97 struct timeval timeout = { 1, 0 };
103 if (select(fd + 1, &set, NULL, NULL, &timeout) < 0)
107 (void *) disk_key->key + n,
108 sizeof(disk_key->key) - n);
109 if (ret == -1 && errno != EINTR && errno != EAGAIN)
110 die("error reading from /dev/random");
115 clock_gettime(CLOCK_MONOTONIC, &now);
117 now.tv_sec -= start.tv_sec;
118 now.tv_nsec -= start.tv_nsec;
120 while (now.tv_nsec < 0) {
121 long nsec_per_sec = 1000 * 1000 * 1000;
122 long sec = now.tv_nsec / nsec_per_sec - 1;
123 now.tv_nsec -= sec * nsec_per_sec;
127 if (!printed && now.tv_sec >= 3) {
128 printf("Reading from /dev/random is taking a long time...\n)");