From fefe5915b06a1121d885fba3680dd1b90027fd5d Mon Sep 17 00:00:00 2001 From: Ethan Yonker Date: Sat, 30 Sep 2017 22:22:13 -0500 Subject: FBE for Pixel 2 Includes various minor fixes for building in Android 8 trees with r23+ tag Update FBE extended header in libtar to version 2 and include the entire ext4_encryption_policy structure now after translating the policy. See this post for more details: https://plus.google.com/u/1/+DeesTroy/posts/i33ygUi7tiu Change-Id: I2af981e51f459b17fcd895fb8c2d3f6c8200e24b --- libtar/append.c | 32 +++++++++++++++++--------- libtar/block.c | 68 +++++++++++++++++++++++++++++++++++++++----------------- libtar/compat.h | 1 + libtar/encode.c | 1 + libtar/extract.c | 17 +++++++------- libtar/libtar.h | 5 ++--- libtar/output.c | 12 ++++++++-- 7 files changed, 93 insertions(+), 43 deletions(-) (limited to 'libtar') diff --git a/libtar/append.c b/libtar/append.c index 8896764f2..66e3aa1e7 100644 --- a/libtar/append.c +++ b/libtar/append.c @@ -131,27 +131,39 @@ tar_append_file(TAR *t, const char *realname, const char *savename) #ifdef HAVE_EXT4_CRYPT if (TH_ISDIR(t) && t->options & TAR_STORE_EXT4_POL) { - if (t->th_buf.e4crypt_policy != NULL) + if (t->th_buf.eep != NULL) { - free(t->th_buf.e4crypt_policy); - t->th_buf.e4crypt_policy = NULL; + free(t->th_buf.eep); + t->th_buf.eep = NULL; } - char e4crypt_policy[EXT4_KEY_DESCRIPTOR_SIZE]; - if (e4crypt_policy_get(realname, e4crypt_policy, EXT4_KEY_DESCRIPTOR_SIZE, 0)) + t->th_buf.eep = (struct ext4_encryption_policy*)malloc(sizeof(struct ext4_encryption_policy)); + if (!t->th_buf.eep) { + printf("malloc ext4_encryption_policy\n"); + return -1; + } + if (e4crypt_policy_get_struct(realname, t->th_buf.eep)) { char tar_policy[EXT4_KEY_DESCRIPTOR_SIZE]; memset(tar_policy, 0, sizeof(tar_policy)); - char policy_hex[EXT4_KEY_DESCRIPTOR_HEX]; - policy_to_hex(e4crypt_policy, policy_hex); - if (lookup_ref_key(e4crypt_policy, &tar_policy)) { + char policy_hex[EXT4_KEY_DESCRIPTOR_SIZE_HEX]; + policy_to_hex(t->th_buf.eep->master_key_descriptor, policy_hex); + if (lookup_ref_key(t->th_buf.eep->master_key_descriptor, &tar_policy[0])) { printf("found policy '%s' - '%s' - '%s'\n", realname, tar_policy, policy_hex); - t->th_buf.e4crypt_policy = strdup(tar_policy); + memcpy(t->th_buf.eep->master_key_descriptor, tar_policy, EXT4_KEY_DESCRIPTOR_SIZE); } else { printf("failed to lookup tar policy for '%s' - '%s'\n", realname, policy_hex); + free(t->th_buf.eep); + t->th_buf.eep = NULL; return -1; } - } // else no policy found, but this is not an error as not all dirs will have a policy + } + else + { + // no policy found, but this is not an error as not all dirs will have a policy + free(t->th_buf.eep); + t->th_buf.eep = NULL; + } } #endif diff --git a/libtar/block.c b/libtar/block.c index 8b2205933..d0adb2bcd 100644 --- a/libtar/block.c +++ b/libtar/block.c @@ -18,6 +18,10 @@ # include #endif +#ifdef HAVE_EXT4_CRYPT +# include "ext4crypt_tar.h" +#endif + #define BIT_ISSET(bitmask, bit) ((bitmask) & (bit)) // Used to identify selinux_context in extended ('x') @@ -138,9 +142,8 @@ th_read(TAR *t) if (t->th_buf.selinux_context != NULL) free(t->th_buf.selinux_context); #ifdef HAVE_EXT4_CRYPT - if (t->th_buf.e4crypt_policy != NULL) { - free(t->th_buf.e4crypt_policy); - } + if (t->th_buf.eep != NULL) + free(t->th_buf.eep); #endif if (t->th_buf.has_cap_data) { @@ -345,16 +348,40 @@ th_read(TAR *t) start = strstr(buf, E4CRYPT_TAG); if (start && start+E4CRYPT_TAG_LEN < buf+len) { + t->th_buf.eep = (struct ext4_encryption_policy*)malloc(sizeof(struct ext4_encryption_policy)); + if (!t->th_buf.eep) { + printf("malloc ext4_encryption_policy\n"); + return -1; + } start += E4CRYPT_TAG_LEN; - char *end = strchr(start, '\n'); - if(!end) - end = strchr(start, '\0'); - if(end) + if (*start == '2') + { + start++; + if (start + sizeof(struct ext4_encryption_policy) != '\n') + printf("did not find newline char in expected location, continuing anyway...\n"); + memcpy(t->th_buf.eep, start, sizeof(struct ext4_encryption_policy)); +#ifdef DEBUG + printf(" th_read(): E4Crypt policy v2 detected: %i %i %i %i %s\n", + (int)t->th_buf.eep->version, + (int)t->th_buf.eep->contents_encryption_mode, + (int)t->th_buf.eep->filenames_encryption_mode, + (int)t->th_buf.eep->flags, + t->th_buf.eep->master_key_descriptor); +#endif + } + else { - t->th_buf.e4crypt_policy = strndup(start, end-start); + e4crypt_policy_fill_default_struct(t->th_buf.eep); + char *end = strchr(start, '\n'); + if(!end) + end = strchr(start, '\0'); + if(end) + { + strncpy(t->th_buf.eep->master_key_descriptor, start, end-start); #ifdef DEBUG - printf(" th_read(): E4Crypt policy detected: %s\n", t->th_buf.e4crypt_policy); + printf(" th_read(): E4Crypt policy v1 detected: %s\n", t->th_buf.eep->master_key_descriptor); #endif + } } } #endif // HAVE_EXT4_CRYPT @@ -557,22 +584,22 @@ th_write(TAR *t) } #ifdef HAVE_EXT4_CRYPT - if((t->options & TAR_STORE_EXT4_POL) && t->th_buf.e4crypt_policy != NULL) + if((t->options & TAR_STORE_EXT4_POL) && t->th_buf.eep != NULL) { #ifdef DEBUG printf("th_write(): using e4crypt_policy %s\n", - t->th_buf.e4crypt_policy); + t->th_buf.eep->master_key_descriptor); #endif - /* setup size - EXT header has format "*size of this whole tag as ascii numbers* *space* *content* *newline* */ + /* setup size - EXT header has format "*size of this whole tag as ascii numbers* *space* *version code* *content* *newline* */ // size newline - sz = E4CRYPT_TAG_LEN + strlen(t->th_buf.e4crypt_policy) + 3 + 1; + sz = E4CRYPT_TAG_LEN + sizeof(struct ext4_encryption_policy) + 1 + 3 + 1; if(sz >= 100) // another ascci digit for size ++sz; if (total_sz + sz >= T_BLOCKSIZE) { - if (th_write_extended(t, &buf, total_sz)) + if (th_write_extended(t, &buf[0], total_sz)) return -1; ptr = buf; total_sz = sz; @@ -580,7 +607,8 @@ th_write(TAR *t) else total_sz += sz; - snprintf(ptr, T_BLOCKSIZE, "%d "E4CRYPT_TAG"%s", (int)sz, t->th_buf.e4crypt_policy); + snprintf(ptr, T_BLOCKSIZE, "%d "E4CRYPT_TAG"2", (int)sz); + memcpy(ptr + sz - sizeof(struct ext4_encryption_policy) - 1, t->th_buf.eep, sizeof(struct ext4_encryption_policy)); char *nlptr = ptr + sz - 1; *nlptr = '\n'; ptr += sz; @@ -599,7 +627,7 @@ th_write(TAR *t) if (total_sz + sz >= T_BLOCKSIZE) { - if (th_write_extended(t, &buf, total_sz)) + if (th_write_extended(t, &buf[0], total_sz)) return -1; ptr = buf; total_sz = sz; @@ -623,7 +651,7 @@ th_write(TAR *t) if (total_sz + sz >= T_BLOCKSIZE) { - if (th_write_extended(t, &buf, total_sz)) + if (th_write_extended(t, &buf[0], total_sz)) return -1; ptr = buf; total_sz = sz; @@ -644,7 +672,7 @@ th_write(TAR *t) if (total_sz + sz >= T_BLOCKSIZE) { - if (th_write_extended(t, &buf, total_sz)) + if (th_write_extended(t, &buf[0], total_sz)) return -1; ptr = buf; total_sz = sz; @@ -665,7 +693,7 @@ th_write(TAR *t) if (total_sz + sz >= T_BLOCKSIZE) { - if (th_write_extended(t, &buf, total_sz)) + if (th_write_extended(t, &buf[0], total_sz)) return -1; ptr = buf; total_sz = sz; @@ -679,7 +707,7 @@ th_write(TAR *t) ptr += sz; } } - if (total_sz > 0 && th_write_extended(t, &buf, total_sz)) // write any outstanding tar extended header + if (total_sz > 0 && th_write_extended(t, &buf[0], total_sz)) // write any outstanding tar extended header return -1; th_finish(t); diff --git a/libtar/compat.h b/libtar/compat.h index 70ac2f435..16b3c3b7c 100644 --- a/libtar/compat.h +++ b/libtar/compat.h @@ -4,6 +4,7 @@ #include #include +#include #include #include diff --git a/libtar/encode.c b/libtar/encode.c index c9371527b..1e679d81e 100644 --- a/libtar/encode.c +++ b/libtar/encode.c @@ -16,6 +16,7 @@ #include #include #include +#include #ifdef STDC_HEADERS # include diff --git a/libtar/extract.c b/libtar/extract.c index 82ed766b2..fcd403a04 100644 --- a/libtar/extract.c +++ b/libtar/extract.c @@ -549,22 +549,23 @@ tar_extract_dir(TAR *t, const char *realname) } #ifdef HAVE_EXT4_CRYPT - if(t->th_buf.e4crypt_policy != NULL) + if(t->th_buf.eep != NULL) { #ifdef DEBUG - printf("tar_extract_file(): restoring EXT4 crypt policy %s to dir %s\n", t->th_buf.e4crypt_policy, realname); + printf("tar_extract_file(): restoring EXT4 crypt policy %s to dir %s\n", t->th_buf.eep->master_key_descriptor, realname); #endif char binary_policy[EXT4_KEY_DESCRIPTOR_SIZE]; - if (!lookup_ref_tar(t->th_buf.e4crypt_policy, &binary_policy)) { - printf("error looking up proper e4crypt policy for '%s' - %s\n", realname, t->th_buf.e4crypt_policy); + if (!lookup_ref_tar(t->th_buf.eep->master_key_descriptor, &binary_policy[0])) { + printf("error looking up proper e4crypt policy for '%s' - %s\n", realname, t->th_buf.eep->master_key_descriptor); return -1; } - char policy_hex[EXT4_KEY_DESCRIPTOR_HEX]; + char policy_hex[EXT4_KEY_DESCRIPTOR_SIZE_HEX]; policy_to_hex(binary_policy, policy_hex); - printf("restoring policy %s > '%s' to '%s'\n", t->th_buf.e4crypt_policy, policy_hex, realname); - if (!e4crypt_policy_set(realname, binary_policy, EXT4_KEY_DESCRIPTOR_SIZE, 0)) + printf("restoring policy %s > '%s' to '%s'\n", t->th_buf.eep->master_key_descriptor, policy_hex, realname); + memcpy(&t->th_buf.eep->master_key_descriptor, binary_policy, EXT4_KEY_DESCRIPTOR_SIZE); + if (!e4crypt_policy_set_struct(realname, t->th_buf.eep)) { - printf("tar_extract_file(): failed to restore EXT4 crypt policy %s to dir '%s' '%s'!!!\n", t->th_buf.e4crypt_policy, realname, policy_hex); + printf("tar_extract_file(): failed to restore EXT4 crypt policy to dir '%s' '%s'!!!\n", realname, policy_hex); //return -1; // This may not be an error in some cases, so log and ignore } } diff --git a/libtar/libtar.h b/libtar/libtar.h index 2d0a3d3fc..aa637b13a 100644 --- a/libtar/libtar.h +++ b/libtar/libtar.h @@ -21,8 +21,7 @@ #include "libtar_listhash.h" #ifdef HAVE_EXT4_CRYPT -#define EXT4_KEY_DESCRIPTOR_SIZE 8 -#define EXT4_KEY_DESCRIPTOR_HEX 17 +# include "ext4crypt_tar.h" #endif #ifdef __cplusplus @@ -70,7 +69,7 @@ struct tar_header char *gnu_longlink; char *selinux_context; #ifdef HAVE_EXT4_CRYPT - char *e4crypt_policy; + struct ext4_encryption_policy *eep; #endif int has_cap_data; struct vfs_cap_data cap_data; diff --git a/libtar/output.c b/libtar/output.c index d2bf8bb0c..f5431b6a7 100644 --- a/libtar/output.c +++ b/libtar/output.c @@ -24,6 +24,10 @@ # include #endif +#ifdef HAVE_EXT4_CRYPT +# include "ext4crypt_tar.h" +#endif + #ifndef _POSIX_LOGIN_NAME_MAX # define _POSIX_LOGIN_NAME_MAX 9 @@ -45,8 +49,8 @@ th_print(TAR *t) printf(" linkname = \"%.100s\"\n", t->th_buf.linkname); printf(" magic = \"%.6s\"\n", t->th_buf.magic); /*printf(" version = \"%.2s\"\n", t->th_buf.version); */ - printf(" version[0] = \'%c\',version[1] = \'%c\'\n", - t->th_buf.version[0], t->th_buf.version[1]); + /*printf(" version[0] = \'%c\',version[1] = \'%c\'\n", + t->th_buf.version[0], t->th_buf.version[1]);*/ printf(" uname = \"%.32s\"\n", t->th_buf.uname); printf(" gname = \"%.32s\"\n", t->th_buf.gname); printf(" devmajor = \"%.8s\"\n", t->th_buf.devmajor); @@ -57,6 +61,10 @@ th_print(TAR *t) (t->th_buf.gnu_longname ? t->th_buf.gnu_longname : "[NULL]")); printf(" gnu_longlink = \"%s\"\n", (t->th_buf.gnu_longlink ? t->th_buf.gnu_longlink : "[NULL]")); +#ifdef HAVE_EXT4_CRYPT + printf(" eep = \"%s\"\n", + (t->th_buf.eep ? t->th_buf.eep->master_key_descriptor : "[NULL]")); +#endif } -- cgit v1.2.3