Line data Source code
1 : /*
2 : * Copyright (C) 2017 sigma star gmbh
3 : *
4 : * This program is free software; you can redistribute it and/or modify it
5 : * under the terms of the GNU General Public License version 2 as published by
6 : * the Free Software Foundation.
7 : *
8 : * This program is distributed in the hope that it will be useful, but WITHOUT
9 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 : * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 : * more details.
12 : *
13 : * You should have received a copy of the GNU General Public License along with
14 : * this program; if not, write to the Free Software Foundation, Inc., 51
15 : * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 : *
17 : * Authors: Richard Weinberger <richard@sigma-star.at>
18 : * David Oberhollenzer <david.oberhollenzer@sigma-star.at>
19 : */
20 :
21 : #include <endian.h>
22 :
23 : #include "linux_types.h"
24 : #include "fscrypt.h"
25 : #include "defs.h"
26 : #include "ubifs.h"
27 :
28 : static __u8 fscrypt_masterkey[FS_MAX_KEY_SIZE];
29 : static struct cipher *fscrypt_cipher;
30 :
31 :
32 351360 : unsigned char *calc_fscrypt_subkey(struct fscrypt_context *fctx)
33 : {
34 : int ret;
35 351360 : unsigned char *new_key = xmalloc(FS_MAX_KEY_SIZE);
36 :
37 351360 : ret = derive_key_aes(fctx->nonce, fscrypt_masterkey, fscrypt_cipher->key_length, new_key);
38 351360 : if (ret < 0) {
39 0 : errmsg("derive_key_aes failed: %i\n", ret);
40 :
41 0 : free(new_key);
42 0 : new_key = NULL;
43 : }
44 :
45 351360 : return new_key;
46 : }
47 :
48 46080 : struct fscrypt_context *inherit_fscrypt_context(struct fscrypt_context *fctx)
49 : {
50 46080 : struct fscrypt_context *new_fctx = NULL;
51 :
52 46080 : if (fctx) {
53 46080 : new_fctx = xmalloc(sizeof(*new_fctx));
54 46080 : new_fctx->format = fctx->format;
55 46080 : new_fctx->contents_encryption_mode = fctx->contents_encryption_mode;
56 46080 : new_fctx->filenames_encryption_mode = fctx->filenames_encryption_mode;
57 46080 : new_fctx->flags = fctx->flags;
58 46080 : memcpy(new_fctx->master_key_descriptor, fctx->master_key_descriptor,
59 : FS_KEY_DESCRIPTOR_SIZE);
60 46080 : RAND_bytes((void *)&new_fctx->nonce, FS_KEY_DERIVATION_NONCE_SIZE);
61 : }
62 :
63 46080 : return new_fctx;
64 : }
65 :
66 46080 : void free_fscrypt_context(struct fscrypt_context *fctx)
67 : {
68 46080 : free(fctx);
69 46080 : }
70 :
71 320 : static void print_fscrypt_master_key_descriptor(__u8 *master_key_descriptor)
72 : {
73 : int i;
74 :
75 320 : normsg_cont("fscrypt master key descriptor: 0x");
76 2880 : for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; i++) {
77 2560 : printf("%02x", master_key_descriptor[i]);
78 : }
79 320 : printf("\n");
80 320 : }
81 :
82 3840 : unsigned int fscrypt_fname_encrypted_size(struct fscrypt_context *fctx,
83 : unsigned int ilen)
84 : {
85 : int padding;
86 :
87 3840 : padding = 4 << (fctx->flags & FS_POLICY_FLAGS_PAD_MASK);
88 3840 : ilen = max_t(unsigned int, ilen, FS_CRYPTO_BLOCK_SIZE);
89 3840 : return round_up(ilen, padding);
90 : }
91 :
92 49920 : int encrypt_path(void **outbuf, const void *data, unsigned int data_len,
93 : unsigned int max_namelen, struct fscrypt_context *fctx)
94 : {
95 : void *inbuf, *crypt_key;
96 49920 : unsigned int padding = 4 << (fctx->flags & FS_POLICY_FLAGS_PAD_MASK);
97 : unsigned int cryptlen;
98 : int ret;
99 :
100 49920 : cryptlen = max_t(unsigned int, data_len, FS_CRYPTO_BLOCK_SIZE);
101 49920 : cryptlen = round_up(cryptlen, padding);
102 49920 : cryptlen = min(cryptlen, max_namelen);
103 :
104 49920 : inbuf = xmalloc(cryptlen);
105 : /* CTS mode needs a block size aligned buffer */
106 49920 : *outbuf = xmalloc(round_up(cryptlen, FS_CRYPTO_BLOCK_SIZE));
107 :
108 49920 : memset(inbuf, 0, cryptlen);
109 49920 : memcpy(inbuf, data, data_len);
110 :
111 49920 : crypt_key = calc_fscrypt_subkey(fctx);
112 49920 : if (!crypt_key) {
113 0 : free(inbuf);
114 0 : free(*outbuf);
115 0 : return errmsg("could not compute subkey");
116 : }
117 :
118 49920 : ret = fscrypt_cipher->encrypt_fname(inbuf, cryptlen,
119 : crypt_key, *outbuf);
120 49920 : if (ret < 0) {
121 0 : free(inbuf);
122 0 : free(*outbuf);
123 0 : return errmsg("could not encrypt filename");
124 : }
125 :
126 49920 : free(crypt_key);
127 49920 : free(inbuf);
128 49920 : return cryptlen;
129 : }
130 :
131 301440 : int encrypt_data_node(struct fscrypt_context *fctx, unsigned int block_no,
132 : struct ubifs_data_node *dn, size_t length)
133 : {
134 : void *inbuf, *outbuf, *crypt_key;
135 301440 : size_t ret, pad_len = round_up(length, FS_CRYPTO_BLOCK_SIZE);
136 :
137 301440 : dn->compr_size = cpu_to_le16(length);
138 :
139 301440 : inbuf = xzalloc(pad_len);
140 301440 : outbuf = xzalloc(pad_len);
141 :
142 301440 : memcpy(inbuf, &dn->data, length);
143 :
144 301440 : crypt_key = calc_fscrypt_subkey(fctx);
145 301440 : if (!crypt_key) {
146 0 : free(inbuf);
147 0 : free(outbuf);
148 0 : return errmsg("could not compute subkey");
149 : }
150 :
151 301440 : ret = fscrypt_cipher->encrypt_block(inbuf, pad_len,
152 : crypt_key, block_no,
153 : outbuf);
154 301440 : if (ret != pad_len) {
155 0 : free(inbuf);
156 0 : free(outbuf);
157 0 : free(crypt_key);
158 0 : return errmsg("encrypt_block returned %zi "
159 : "instead of %zi", ret, pad_len);
160 : }
161 :
162 301440 : memcpy(&dn->data, outbuf, pad_len);
163 :
164 301440 : free(inbuf);
165 301440 : free(outbuf);
166 301440 : free(crypt_key);
167 301440 : return pad_len;
168 : }
169 :
170 0 : static int xdigit(int x)
171 : {
172 0 : if (isupper(x))
173 0 : return x - 'A' + 0x0A;
174 0 : if (islower(x))
175 0 : return x - 'a' + 0x0A;
176 0 : return x - '0';
177 : }
178 :
179 0 : static int parse_key_descriptor(const char *desc, __u8 *dst)
180 : {
181 : int i, hi, lo;
182 :
183 0 : if (desc[0] == '0' && (desc[1] == 'x' || desc[1] == 'X'))
184 0 : desc += 2;
185 :
186 0 : for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; ++i) {
187 0 : if (!desc[i * 2] || !desc[i * 2 + 1]) {
188 0 : errmsg("key descriptor '%s' is too short", desc);
189 0 : return -1;
190 : }
191 0 : if (!isxdigit(desc[i * 2]) || !isxdigit(desc[i * 2 + 1])) {
192 0 : errmsg("invalid key descriptor '%s'", desc);
193 0 : return -1;
194 : }
195 :
196 0 : hi = xdigit(desc[i * 2]);
197 0 : lo = xdigit(desc[i * 2 + 1]);
198 :
199 0 : dst[i] = (hi << 4) | lo;
200 : }
201 :
202 0 : if (desc[i * 2]) {
203 0 : errmsg("key descriptor '%s' is too long", desc);
204 0 : return -1;
205 : }
206 : return 0;
207 : }
208 :
209 320 : static int load_master_key(const char *key_file, struct cipher *fsc)
210 : {
211 : int kf;
212 : ssize_t keysize;
213 :
214 320 : kf = open(key_file, O_RDONLY);
215 320 : if (kf < 0) {
216 0 : sys_errmsg("open '%s'", key_file);
217 : return -1;
218 : }
219 :
220 320 : keysize = read(kf, fscrypt_masterkey, FS_MAX_KEY_SIZE);
221 320 : if (keysize < 0) {
222 0 : sys_errmsg("read '%s'", key_file);
223 : goto fail;
224 : }
225 320 : if (keysize == 0) {
226 0 : errmsg("loading key from '%s': file is empty", key_file);
227 : goto fail;
228 : }
229 320 : if (keysize < fsc->key_length) {
230 0 : errmsg("key '%s' is too short (at least %u bytes required)",
231 : key_file, fsc->key_length);
232 : goto fail;
233 : }
234 :
235 320 : close(kf);
236 : return 0;
237 0 : fail:
238 0 : close(kf);
239 : return -1;
240 : }
241 :
242 320 : struct fscrypt_context *init_fscrypt_context(const char *cipher_name,
243 : unsigned int flags,
244 : const char *key_file,
245 : const char *key_descriptor)
246 : {
247 : __u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
248 : __u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
249 : struct fscrypt_context *new_fctx;
250 :
251 320 : fscrypt_cipher = get_cipher(cipher_name);
252 :
253 320 : if (!fscrypt_cipher) {
254 0 : fprintf(stderr, "Cannot find cipher '%s'\n"
255 : "Try `%s --help' for more information\n",
256 : cipher_name, PROGRAM_NAME);
257 0 : return NULL;
258 : }
259 :
260 320 : if (load_master_key(key_file, fscrypt_cipher))
261 : return NULL;
262 :
263 320 : if (!key_descriptor) {
264 320 : if (derive_key_descriptor(fscrypt_masterkey, master_key_descriptor))
265 : return NULL;
266 320 : print_fscrypt_master_key_descriptor(master_key_descriptor);
267 : } else {
268 0 : if (parse_key_descriptor(key_descriptor, master_key_descriptor))
269 : return NULL;
270 : }
271 :
272 320 : RAND_bytes((void *)nonce, FS_KEY_DERIVATION_NONCE_SIZE);
273 :
274 320 : new_fctx = xmalloc(sizeof(*new_fctx));
275 :
276 320 : new_fctx->format = FS_ENCRYPTION_CONTEXT_FORMAT_V1;
277 320 : new_fctx->contents_encryption_mode = fscrypt_cipher->fscrypt_block_mode;
278 320 : new_fctx->filenames_encryption_mode = fscrypt_cipher->fscrypt_fname_mode;
279 320 : new_fctx->flags = flags;
280 :
281 320 : memcpy(&new_fctx->nonce, nonce, FS_KEY_DERIVATION_NONCE_SIZE);
282 320 : memcpy(&new_fctx->master_key_descriptor, master_key_descriptor,
283 : FS_KEY_DESCRIPTOR_SIZE);
284 320 : return new_fctx;
285 : }
|