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
diff --git a/libtar/block.c b/libtar/block.c
index 8b22059..d0adb2b 100644
--- a/libtar/block.c
+++ b/libtar/block.c
@@ -18,6 +18,10 @@
 # include <stdlib.h>
 #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 @@
 	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,17 +348,41 @@
 			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')
 				{
-					t->th_buf.e4crypt_policy = strndup(start, end-start);
+					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 detected: %s\n", t->th_buf.e4crypt_policy);
+					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
+				{
+					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 v1 detected: %s\n", t->th_buf.eep->master_key_descriptor);
+#endif
+					}
+				}
 			}
 #endif // HAVE_EXT4_CRYPT
 		}
@@ -557,22 +584,22 @@
 	}
 
 #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 @@
 		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 @@
 
 		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 @@
 
 			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 @@
 
 			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 @@
 
 			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 @@
 			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);