Merge lp:~wlxing/ecryptfs/lp342398 into lp:ecryptfs

Proposed by Jason Xing
Status: Needs review
Proposed branch: lp:~wlxing/ecryptfs/lp342398
Merge into: lp:ecryptfs
Diff against target: 449 lines (+354/-1)
4 files modified
debian/changelog (+2/-0)
src/include/ecryptfs.h (+20/-0)
src/libecryptfs/ecryptfs-stat.c (+322/-1)
src/utils/ecryptfs-stat.c (+10/-0)
To merge this branch: bzr merge lp:~wlxing/ecryptfs/lp342398
Reviewer Review Type Date Requested Status
Colin Ian King Pending
Tyler Hicks Pending
Review via email: mp+325438@code.launchpad.net

Description of the change

Add ecryptfs-stat support for encrypted filenames (LP: #342398). The main process has three parts: decoding filename, parsing filename and printing information.
Test output samples:
Case 1):
[...]
Filename encryption enabled
FNEK sig is [8f9887d2339cafb0]
Filename encrytion cipher is [aes]
Case 2):
[...]
Filename encryption disabled
Case 3):
[...]
Filename encryption enabled
ecryptfs_parse_tag_70_packet: max_packet_size is [42]; real packet size is [35]
ecryptfs_parse_filename: Could not parse tag 70 packet from filename

To post a comment you must log in.

Unmerged revisions

895. By Jason Xing

src/utils/ecryptfs-stat.c, src/libecryptfs/ecryptfs-stat.c, src/include/ecryptfs.h: Add ecryptfs-stat support for encrypted filenames (LP: #342398)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/changelog'
--- debian/changelog 2017-06-08 23:29:22 +0000
+++ debian/changelog 2017-06-10 01:37:57 +0000
@@ -36,6 +36,8 @@
36 users that even though the mount was successful, their data may not be36 users that even though the mount was successful, their data may not be
37 decrypted when a mount passphrase was used for recovery37 decrypted when a mount passphrase was used for recovery
38 (LP: #1694272, LP: #1439825)38 (LP: #1694272, LP: #1439825)
39 * src/utils/ecryptfs-stat.c, src/libecryptfs/ecryptfs-stat.c, src/include/ecryptfs.h:
40 Add ecryptfs-stat support for encrypted filenames. (LP: #342398)
3941
40 [ Jelle van der Waa ]42 [ Jelle van der Waa ]
41 * src/key_mod/ecryptfs_key_mod_openssl.c,43 * src/key_mod/ecryptfs_key_mod_openssl.c,
4244
=== modified file 'src/include/ecryptfs.h'
--- src/include/ecryptfs.h 2015-02-14 22:11:29 +0000
+++ src/include/ecryptfs.h 2017-06-10 01:37:57 +0000
@@ -94,6 +94,7 @@
94#define MAGIC_ECRYPTFS_MARKER 0x3c81b7f594#define MAGIC_ECRYPTFS_MARKER 0x3c81b7f5
95#define MAGIC_ECRYPTFS_MARKER_SIZE_BYTES 8 /* 4*2 */95#define MAGIC_ECRYPTFS_MARKER_SIZE_BYTES 8 /* 4*2 */
96#endif96#endif
97#define ECRYPTFS_MAX_CIPHER_NAME_SIZE 32
97#define MAX_NAME_SIZE 12898#define MAX_NAME_SIZE 128
98#define MAX_KEY_MOD_VALUE_SIZE 409699#define MAX_KEY_MOD_VALUE_SIZE 4096
99#define ECRYPTFS_TAG_1_PACKET_TYPE 0x01100#define ECRYPTFS_TAG_1_PACKET_TYPE 0x01
@@ -103,6 +104,7 @@
103#define ECRYPTFS_TAG_65_PACKET_TYPE 0x41104#define ECRYPTFS_TAG_65_PACKET_TYPE 0x41
104#define ECRYPTFS_TAG_66_PACKET_TYPE 0x42105#define ECRYPTFS_TAG_66_PACKET_TYPE 0x42
105#define ECRYPTFS_TAG_67_PACKET_TYPE 0x43106#define ECRYPTFS_TAG_67_PACKET_TYPE 0x43
107#define ECRYPTFS_TAG_70_PACKET_TYPE 0x46
106#define ECRYPTFS_MSG_HELO 100108#define ECRYPTFS_MSG_HELO 100
107#define ECRYPTFS_MSG_QUIT 101109#define ECRYPTFS_MSG_QUIT 101
108#define ECRYPTFS_MSG_REQUEST 102110#define ECRYPTFS_MSG_REQUEST 102
@@ -143,6 +145,21 @@
143#define ECRYPTFS_ECHO_ON 1145#define ECRYPTFS_ECHO_ON 1
144#define ECRYPTFS_ECHO_OFF 0146#define ECRYPTFS_ECHO_OFF 0
145147
148#define ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX "ECRYPTFS_FNEK_ENCRYPTED."
149#define ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE 24
150#define ECRYPTFS_MIN_PKT_LEN_SIZE 1
151#define ECRYPTFS_TAG_70_MIN_METADATA_SIZE (1 + ECRYPTFS_MIN_PKT_LEN_SIZE \
152 + ECRYPTFS_SIG_SIZE + 1 + 1)
153
154#define RFC2440_CIPHER_DES3_EDE 0x02
155#define RFC2440_CIPHER_CAST_5 0x03
156#define RFC2440_CIPHER_BLOWFISH 0x04
157#define RFC2440_CIPHER_AES_128 0x07
158#define RFC2440_CIPHER_AES_192 0x08
159#define RFC2440_CIPHER_AES_256 0x09
160#define RFC2440_CIPHER_TWOFISH 0x0a
161#define RFC2440_CIPHER_CAST_6 0x0b
162
146#define ECRYPTFS_AES_BLOCK_SIZE 16163#define ECRYPTFS_AES_BLOCK_SIZE 16
147#define ECRYPTFS_AES_KEY_BYTES 16164#define ECRYPTFS_AES_KEY_BYTES 16
148165
@@ -437,6 +454,7 @@
437#define ECRYPTFS_METADATA_IN_XATTR 0x00000100454#define ECRYPTFS_METADATA_IN_XATTR 0x00000100
438#define ECRYPTFS_VIEW_AS_ENCRYPTED 0x00000200455#define ECRYPTFS_VIEW_AS_ENCRYPTED 0x00000200
439#define ECRYPTFS_KEY_SET 0x00000400456#define ECRYPTFS_KEY_SET 0x00000400
457#define ECRYPTFS_ENCRYPT_FILENAMES 0x00000800
440 uint32_t flags;458 uint32_t flags;
441 unsigned int file_version;459 unsigned int file_version;
442 uint64_t file_size;460 uint64_t file_size;
@@ -580,4 +598,6 @@
580char *ecryptfs_fetch_private_mnt(char *pw_dir);598char *ecryptfs_fetch_private_mnt(char *pw_dir);
581int ecryptfs_private_is_mounted(char *dev, char *mnt, char *sig, int mounting);599int ecryptfs_private_is_mounted(char *dev, char *mnt, char *sig, int mounting);
582600
601int ecryptfs_parse_filename(const char *path, size_t path_len);
602
583#endif603#endif
584604
=== modified file 'src/libecryptfs/ecryptfs-stat.c'
--- src/libecryptfs/ecryptfs-stat.c 2013-10-27 22:21:20 +0000
+++ src/libecryptfs/ecryptfs-stat.c 2017-06-10 01:37:57 +0000
@@ -65,7 +65,8 @@
65static struct ecryptfs_flag_map_elem ecryptfs_flag_map[] = {65static struct ecryptfs_flag_map_elem ecryptfs_flag_map[] = {
66 {0x00000001, ECRYPTFS_ENABLE_HMAC},66 {0x00000001, ECRYPTFS_ENABLE_HMAC},
67 {0x00000002, ECRYPTFS_ENCRYPTED},67 {0x00000002, ECRYPTFS_ENCRYPTED},
68 {0x00000004, ECRYPTFS_METADATA_IN_XATTR}68 {0x00000004, ECRYPTFS_METADATA_IN_XATTR},
69 {0x00000008, ECRYPTFS_ENCRYPT_FILENAMES}
69};70};
7071
71/**72/**
@@ -186,3 +187,323 @@
186out:187out:
187 return rc;188 return rc;
188}189}
190
191/* We could either offset on every reverse map or just pad some 0x00's
192 * at the front here */
193static const unsigned char filename_rev_map[256] = {
194 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 7 */
195 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 15 */
196 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 23 */
197 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 31 */
198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 39 */
199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, /* 47 */
200 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, /* 55 */
201 0x0A, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 63 */
202 0x00, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, /* 71 */
203 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, /* 79 */
204 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, /* 87 */
205 0x23, 0x24, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, /* 95 */
206 0x00, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, /* 103 */
207 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, /* 111 */
208 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, /* 119 */
209 0x3D, 0x3E, 0x3F /* 123 - 255 initialized to 0x00 */
210};
211
212static size_t ecryptfs_max_decoded_size(size_t encoded_size)
213{
214 /* Not exact; conservatively long. Every block of 4
215 * encoded characters decodes into a block of 3
216 * decoded characters. This segment of code provides
217 * the caller with the maximum amount of allocated
218 * space that @dst will need to point to in a
219 * subsequent call. */
220 return ((encoded_size + 1) * 3) / 4;
221}
222
223/**
224 * ecryptfs_decode_from_filename
225 * @dst: If NULL, this function only sets @dst_size and returns. If
226 * non-NULL, this function decodes the encoded octets in @src
227 * into the memory that @dst points to.
228 * @dst_size: Set to the size of the decoded string.
229 * @src: The encoded set of octets to decode.
230 * @src_size: The size of the encoded set of octets to decode.
231 */
232static void
233ecryptfs_decode_from_filename(unsigned char *dst, size_t *dst_size,
234 const unsigned char *src, size_t src_size)
235{
236 unsigned char current_bit_offset = 0;
237 size_t src_byte_offset = 0;
238 size_t dst_byte_offset = 0;
239
240 if (dst == NULL) {
241 (*dst_size) = ecryptfs_max_decoded_size(src_size);
242 goto out;
243 }
244 while (src_byte_offset < src_size) {
245 unsigned char src_byte =
246 filename_rev_map[(int)src[src_byte_offset]];
247
248 switch (current_bit_offset) {
249 case 0:
250 dst[dst_byte_offset] = (src_byte << 2);
251 current_bit_offset = 6;
252 break;
253 case 6:
254 dst[dst_byte_offset++] |= (src_byte >> 4);
255 dst[dst_byte_offset] = ((src_byte & 0xF)
256 << 4);
257 current_bit_offset = 4;
258 break;
259 case 4:
260 dst[dst_byte_offset++] |= (src_byte >> 2);
261 dst[dst_byte_offset] = (src_byte << 6);
262 current_bit_offset = 2;
263 break;
264 case 2:
265 dst[dst_byte_offset++] |= (src_byte);
266 dst[dst_byte_offset] = 0;
267 current_bit_offset = 0;
268 break;
269 }
270 src_byte_offset++;
271 }
272 (*dst_size) = dst_byte_offset;
273out:
274 return;
275}
276
277static int ecryptfs_decode_filename(const char *name, size_t name_size,
278 char **decoded_name, size_t *decoded_name_size)
279{
280 int rc = 0;
281
282 if ((name_size > ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE)
283 && (strncmp(name, ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX,
284 ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE) == 0)) {
285 name += ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE;
286 name_size -= ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE;
287 ecryptfs_decode_from_filename(NULL, decoded_name_size,
288 name, name_size);
289 (*decoded_name) = (char *)malloc(*decoded_name_size);
290 if (!(*decoded_name)) {
291 printf("%s: Out of memory whilst attempting "
292 "to malloc [%zd] bytes\n", __func__,
293 *decoded_name_size);
294 rc = -ENOMEM;
295 goto out;
296 }
297 ecryptfs_decode_from_filename(*decoded_name, decoded_name_size,
298 name, name_size);
299 } else {
300 rc = -EINVAL;
301 }
302out:
303 return rc;
304}
305
306struct ecryptfs_parse_tag_70_packet_stack {
307 unsigned char cipher_code;
308 size_t max_packet_size;
309 size_t packet_size_len;
310 size_t parsed_tag_70_packet_size;
311 size_t block_aligned_filename_size;
312 char fnek_sig_hex[ECRYPTFS_SIG_SIZE_HEX + 1];
313 char cipher_string[ECRYPTFS_MAX_CIPHER_NAME_SIZE];
314};
315
316struct ecryptfs_cipher_code_str_map_elem {
317 char cipher_str[16];
318 unsigned char cipher_code;
319};
320
321/* For now eCryptfs doesn't support public-key type for
322 * filename encrytion/decrption*/
323static struct ecryptfs_cipher_code_str_map_elem
324ecryptfs_cipher_code_str_map[] = {
325 {"aes",RFC2440_CIPHER_AES_128 },
326 {"blowfish", RFC2440_CIPHER_BLOWFISH},
327 {"des3_ede", RFC2440_CIPHER_DES3_EDE},
328 {"cast5", RFC2440_CIPHER_CAST_5},
329 {"twofish", RFC2440_CIPHER_TWOFISH},
330 {"cast6", RFC2440_CIPHER_CAST_6},
331 {"aes", RFC2440_CIPHER_AES_192},
332 {"aes", RFC2440_CIPHER_AES_256}
333};
334
335/**
336 * ecryptfs_cipher_code_to_string
337 * @str: Destination to write out the cipher name
338 * @cipher_code: The code to convert to cipher name string
339 *
340 * Returns zero on success
341 */
342static int ecryptfs_cipher_code_to_string(char *str, unsigned char cipher_code)
343{
344 int rc = 0;
345 int i;
346
347 str[0] = '\0';
348 for (i = 0; i < (sizeof(ecryptfs_cipher_code_str_map) / sizeof(ecryptfs_cipher_code_str_map[0])); i++)
349 if (cipher_code == ecryptfs_cipher_code_str_map[i].cipher_code)
350 strcpy(str, ecryptfs_cipher_code_str_map[i].cipher_str);
351 if (str[0] == '\0') {
352 printf("Cipher code not recognized: [%d]\n", cipher_code);
353 rc = -EINVAL;
354 }
355 return rc;
356}
357
358/**
359 * ecryptfs_to_hex
360 * @dst: Buffer to take hex character representation of contents of
361 * src; must be at least of size (src_size * 2)
362 * @src: Buffer to be converted to a hex string respresentation
363 * @src_size: number of bytes to convert
364 */
365static void ecryptfs_to_hex(char *dst, char *src, size_t src_size)
366{
367 int x;
368
369 for (x = 0; x < src_size; x++)
370 sprintf(&dst[x * 2], "%.2x", (unsigned char)src[x]);
371}
372
373/**
374 * parse_tag_70_packet - Parse and process FNEK-encrypted passphrase packet
375 * Tag 70 packet format:
376 * Octet 0: Tag 70 identifier
377 * Octets 1-N1: Tag 70 packet size (includes cipher identifier
378 * and block-aligned encrypted filename size)
379 * Octets N1-N2: FNEK sig (ECRYPTFS_SIG_SIZE)
380 * Octet N2-N3: Cipher identifier (1 octet)
381 * Octets N3-N4: Block-aligned encrypted filename
382 *
383 * @s: Parse tag 70 packet into this structure and print its members one by
384 * one later
385 * @packet_size: This function sets this to the the number of octets
386 * in the packet parsed
387 * @data: The memory location containing the start of the tag 70
388 * packet
389 * @max_packet_size: The maximum legal size of the packet to be parsed
390 * from @data
391 *
392 * Returns zero on success; non-zero otherwise
393 */
394static int ecryptfs_parse_tag_70_packet(struct ecryptfs_parse_tag_70_packet_stack **s, size_t *packet_size,
395 char *data, size_t max_packet_size)
396{
397 int rc = 0;
398
399 (*packet_size) = 0;
400 *s = (struct ecryptfs_parse_tag_70_packet_stack *)malloc(sizeof(**s));
401 if (!(*s)) {
402 printf("%s: Out of memory whilst trying to malloc "
403 "[%zd] bytes of memory\n", __func__, sizeof(**s));
404 rc = -ENOMEM;
405 goto out;
406 }
407 if (max_packet_size < ECRYPTFS_TAG_70_MIN_METADATA_SIZE) {
408 printf("%s: max_packet_size is [%zd]; it must be "
409 "at least [%d]\n", __func__, max_packet_size,
410 ECRYPTFS_TAG_70_MIN_METADATA_SIZE);
411 rc = -EINVAL;
412 goto out;
413 }
414 /* Tag 70 identifier */
415 if (data[(*packet_size)++] != ECRYPTFS_TAG_70_PACKET_TYPE) {
416 printf("%s: Invalid packet tag [0x%.2x]; must be "
417 "tag [0x%.2x]\n", __func__,
418 data[((*packet_size) - 1)], ECRYPTFS_TAG_70_PACKET_TYPE);
419 rc = -EINVAL;
420 goto out;
421 }
422 /* Tag 70 packet size */
423 rc = ecryptfs_parse_packet_length(&data[(*packet_size)],
424 &(*s)->parsed_tag_70_packet_size,
425 &(*s)->packet_size_len);
426 if (rc) {
427 printf("%s: Error parsing packet length; "
428 "rc = [%d]\n", __func__, rc);
429 goto out;
430 }
431 (*s)->block_aligned_filename_size = ((*s)->parsed_tag_70_packet_size
432 - ECRYPTFS_SIG_SIZE - 1);
433 if ((1 + (*s)->packet_size_len + (*s)->parsed_tag_70_packet_size)
434 > max_packet_size) {
435 printf("%s: max_packet_size is [%zd]; real packet "
436 "size is [%zd]\n", __func__, max_packet_size,
437 (1 + (*s)->packet_size_len + 1
438 + (*s)->block_aligned_filename_size));
439 rc = -EINVAL;
440 goto out;
441 }
442 (*packet_size) += (*s)->packet_size_len;
443 /* FNEK sig */
444 ecryptfs_to_hex((*s)->fnek_sig_hex, &data[(*packet_size)],
445 ECRYPTFS_SIG_SIZE);
446 (*s)->fnek_sig_hex[ECRYPTFS_SIG_SIZE_HEX] = '\0';
447 (*packet_size) += ECRYPTFS_SIG_SIZE;
448 /* Cipher identifier */
449 (*s)->cipher_code = data[(*packet_size)++];
450 rc = ecryptfs_cipher_code_to_string((*s)->cipher_string, (*s)->cipher_code);
451 if (rc) {
452 printf("%s: Cipher code [%d] is invalid\n",
453 __func__, (*s)->cipher_code);
454 goto out;
455 }
456out:
457 return rc;
458}
459
460static void ecryptfs_print_stack(struct ecryptfs_parse_tag_70_packet_stack *s)
461{
462 printf("FNEK sig is [%s]\n", s->fnek_sig_hex);
463 printf("Filename encrytion cipher is [%s]\n", s->cipher_string);
464 return;
465}
466
467/*
468 * find filename portion of a path (/foo/bar -> baz)
469 */
470static char *ecryptfs_get_filename(const char *s, int len)
471{
472 const char *e = s + len;
473
474 while (e != s && *(e-1) != '/')
475 e--;
476 return (char *)e;
477}
478
479int ecryptfs_parse_filename(const char *path, size_t path_len)
480{
481 const char *name;
482 char *decoded_name = NULL;
483 struct ecryptfs_parse_tag_70_packet_stack *s = NULL;
484 size_t name_size, decoded_name_size, packet_size;
485 int rc = 0;
486
487 name = ecryptfs_get_filename(path, path_len);
488 name_size = strlen(name);
489 rc = ecryptfs_decode_filename(name, name_size,
490 &decoded_name, &decoded_name_size);
491 if (rc) {
492 printf("%s: Could not decode filename\n", __func__);
493 goto out;
494 }
495 rc = ecryptfs_parse_tag_70_packet(&s,
496 &packet_size,
497 decoded_name,
498 decoded_name_size);
499 if (rc) {
500 goto out;
501 }
502 ecryptfs_print_stack(s);
503out:
504 if (s)
505 free(s);
506 if (decoded_name)
507 free(decoded_name);
508 return rc;
509}
189510
=== modified file 'src/utils/ecryptfs-stat.c'
--- src/utils/ecryptfs-stat.c 2009-02-03 08:50:36 +0000
+++ src/utils/ecryptfs-stat.c 2017-06-10 01:37:57 +0000
@@ -3,6 +3,7 @@
3 */3 */
44
5#include <stdio.h>5#include <stdio.h>
6#include <string.h>
6#include <fcntl.h>7#include <fcntl.h>
7#include <unistd.h>8#include <unistd.h>
8#include <errno.h>9#include <errno.h>
@@ -19,6 +20,7 @@
19int main(int argc, const char *argv[])20int main(int argc, const char *argv[])
20{21{
21 const char *filename;22 const char *filename;
23 size_t filename_size;
22 int fd = -1;24 int fd = -1;
23 ssize_t quant_read;25 ssize_t quant_read;
24 struct ecryptfs_crypt_stat_user crypt_stat;26 struct ecryptfs_crypt_stat_user crypt_stat;
@@ -30,6 +32,7 @@
30 goto out;32 goto out;
31 }33 }
32 filename = argv[1];34 filename = argv[1];
35 filename_size = strlen(filename);
33 fd = open(filename, O_RDONLY);36 fd = open(filename, O_RDONLY);
34 if (fd == -1) {37 if (fd == -1) {
35 printf("Error opening file [%s] for RD_ONLY access; errno msg "38 printf("Error opening file [%s] for RD_ONLY access; errno msg "
@@ -68,6 +71,13 @@
68 printf("HMAC enabled\n");71 printf("HMAC enabled\n");
69 else72 else
70 printf("HMAC disabled\n");73 printf("HMAC disabled\n");
74 if (crypt_stat.flags & ECRYPTFS_ENCRYPT_FILENAMES) {
75 printf("Filename encryption enabled\n");
76 rc = ecryptfs_parse_filename(filename, filename_size);
77 }
78 else
79 printf("Filename encryption disabled\n");
80
71out:81out:
72 if (fd != -1)82 if (fd != -1)
73 close(fd);83 close(fd);

Subscribers

People subscribed via source and target branches