]> git.sesse.net Git - bcachefs-tools-debian/blob - crypto.c
New on disk format - encryption
[bcachefs-tools-debian] / crypto.c
1 #include <errno.h>
2 #include <stdbool.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <termios.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10 #include <time.h>
11 #include <unistd.h>
12
13 #include <linux/random.h>
14 #include <libscrypt.h>
15
16 #include "checksum.h"
17 #include "crypto.h"
18
19 char *read_passphrase(const char *prompt)
20 {
21         char *buf = NULL;
22         size_t buflen = 0;
23         ssize_t len;
24
25         if (isatty(STDIN_FILENO)) {
26                 struct termios old, new;
27
28                 fprintf(stderr, "%s", prompt);
29                 fflush(stderr);
30
31                 if (tcgetattr(STDIN_FILENO, &old))
32                         die("error getting terminal attrs");
33
34                 new = old;
35                 new.c_lflag &= ~ECHO;
36                 if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &new))
37                         die("error setting terminal attrs");
38
39                 len = getline(&buf, &buflen, stdin);
40
41                 tcsetattr(STDIN_FILENO, TCSAFLUSH, &old);
42                 fprintf(stderr, "\n");
43         } else {
44                 len = getline(&buf, &buflen, stdin);
45         }
46
47         if (len < 0)
48                 die("error reading passphrase");
49         if (len && buf[len - 1] == '\n')
50                 buf[len - 1] = '\0';
51
52         return buf;
53 }
54
55 void derive_passphrase(struct bch_sb_field_crypt *crypt,
56                        struct bch_key *key,
57                        const char *passphrase)
58 {
59         const unsigned char salt[] = "bcache";
60         int ret;
61
62         switch (BCH_CRYPT_KDF_TYPE(crypt)) {
63         case BCH_KDF_SCRYPT:
64                 ret = libscrypt_scrypt((void *) passphrase, strlen(passphrase),
65                                        salt, sizeof(salt),
66                                        1ULL << BCH_KDF_SCRYPT_N(crypt),
67                                        1ULL << BCH_KDF_SCRYPT_R(crypt),
68                                        1ULL << BCH_KDF_SCRYPT_P(crypt),
69                                        (void *) key, sizeof(*key));
70                 if (ret)
71                         die("scrypt error: %i", ret);
72                 break;
73         default:
74                 die("unknown kdf type %llu", BCH_CRYPT_KDF_TYPE(crypt));
75         }
76 }
77
78 void bch_sb_crypt_init(struct bch_sb *sb,
79                        struct bch_sb_field_crypt *crypt,
80                        const char *passphrase)
81 {
82         struct bch_key passphrase_key;
83
84         SET_BCH_CRYPT_KDF_TYPE(crypt, BCH_KDF_SCRYPT);
85         SET_BCH_KDF_SCRYPT_N(crypt, ilog2(SCRYPT_N));
86         SET_BCH_KDF_SCRYPT_R(crypt, ilog2(SCRYPT_r));
87         SET_BCH_KDF_SCRYPT_P(crypt, ilog2(SCRYPT_p));
88
89         derive_passphrase(crypt, &passphrase_key, passphrase);
90
91         crypt->key.magic = BCH_KEY_MAGIC;
92         get_random_bytes(&crypt->key.key, sizeof(crypt->key.key));
93
94         assert(!bch_key_is_encrypted(&crypt->key));
95
96         if (bch_chacha_encrypt_key(&passphrase_key, __bch_sb_key_nonce(sb),
97                                    &crypt->key, sizeof(crypt->key)))
98                 die("error encrypting key");
99
100         assert(bch_key_is_encrypted(&crypt->key));
101
102         memzero_explicit(&passphrase_key, sizeof(passphrase_key));
103 }