Skip to contentSkip to conversation

eCryptfs: Extend file headers to store cipher mode.

RFC New Will Morrison 1 participant 1 message Jun 21, 2013 Ecrypt file system

lore
Share & tools
lore
#0 lore raw

RFC 2/2 eCryptfs: Extend file headers to store cipher mode.

This patch changes the way eCryptfs headers use tag 3 (symmetric key) and tag 1 (asymmetric key) packets, adding fields to store cipher mode while keeping the format byte compatible with older version of eCryptfs when CBC mode is used.

For tag 1 packets, the 1 byte cipher identifier field used to always contain a constant value that was ignored when reading in the header. This has been repurposed to hold the cipher mode code. For tag 3 packets, an extra cipher mode field has been added, which will only be present if the cipher mode used is other than CBC.

In both cases, the tag version number is incremented when a packet is written that is not byte compatible with older versions of eCryptfs. This happens whenever CBC mode is not used.

---
 fs/ecryptfs/crypto.c          |   61 +++++++++++++++
 fs/ecryptfs/ecryptfs_kernel.h |    2 +
 fs/ecryptfs/keystore.c        |  164 +++++++++++++++++++++++++++++++++++------
 include/linux/ecryptfs.h      |    2 +
 4 files changed, 208 insertions(+), 21 deletions(-)
fs/ecryptfs/crypto.c +60 -0
index b97bcc8..929b4d2 100644
@@ -969,6 +969,67 @@ void ecryptfs_write_crypt_stat_flags(char *page_virt,
 	(*written) = 4;
 }
 +struct ecryptfs_cipher_mode_code_str_map_elem {
+	char mode_str[ECRYPTFS_MAX_CIPHER_MODE_NAME_SIZE];
+	u8 mode_code;
+};
+
+static struct ecryptfs_cipher_mode_code_str_map_elem
+ecryptfs_cipher_mode_code_str_map[] = {
+	{"cbc", ECRYPTFS_CIPHER_MODE_CBC},
+};
+
+/**
+ * ecryptfs_code_for_cipher_mode_string
+ * @mode_name: The string alias for the cipher mode
+ *
+ * Retruns zero on no match, or the cipher code on match
+ */
+u8 ecryptfs_code_for_cipher_mode_string(char *mode_name)
+{
+	int i;
+	u8 code = 0;
+	struct ecryptfs_cipher_mode_code_str_map_elem *map =
+		ecryptfs_cipher_mode_code_str_map;
+
+	for (i = 0; i < ARRAY_SIZE(ecryptfs_cipher_mode_code_str_map); i++)
+		if (strcmp(mode_name, map[i].mode_str) == 0) {
+			code = map[i].mode_code;
+			break;
+		}
+
+	return code;
+}
+
+/**
+ * ecryptfs_cipher_mode_code_to_string
+ * @str: Destination to write out the cipher mode name
+ * @cipher_code: The code to conver to cipher mode name string
+ *
+ * Retruns zero in success
+ */
+int ecryptfs_cipher_mode_code_to_string(char *str, u8 mode_code)
+{
+	int rc = 0;
+	int i;
+	struct ecryptfs_cipher_mode_code_str_map_elem *map =
+		ecryptfs_cipher_mode_code_str_map;
+
+	str[0] = '\0';
+	for (i = 0; i < ARRAY_SIZE(ecryptfs_cipher_mode_code_str_map); i++)
+		if (mode_code == map[i].mode_code) {
+			strcpy(str, map[i].mode_str);
+			break;
+		}
+	if (str[0] == '\0') {
+		ecryptfs_printk(KERN_WARNING, "Cipher mode not recognized: "
+				"[%d]\n", mode_code);
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
 struct ecryptfs_cipher_code_str_map_elem {
 	char cipher_str[16];
 	u8 cipher_code;
fs/ecryptfs/ecryptfs_kernel.h +2 -0
index 8b039af..a9327d7 100644
@@ -615,6 +615,8 @@ int ecryptfs_read_and_validate_xattr_region(struct dentry *dentry,
 					    struct inode *inode);
 u8 ecryptfs_code_for_cipher_string(char *cipher_name, size_t key_bytes);
 int ecryptfs_cipher_code_to_string(char *str, u8 cipher_code);
+u8 ecryptfs_code_for_cipher_mode_string(char *mode_name);
+int ecryptfs_cipher_mode_code_to_string(char *str, u8 mode_code);
 void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat);
 int ecryptfs_generate_key_packet_set(char *dest_base,
 				     struct ecryptfs_crypt_stat *crypt_stat,
fs/ecryptfs/keystore.c +143 -21

284 lines not on this page · raw message

include/linux/ecryptfs.h +1 -0
index 8d5ab99..8244e03 100644
@@ -44,6 +44,8 @@
  #define RFC2440_CIPHER_RSA 0x01
 +#define ECRYPTFS_CIPHER_MODE_CBC 0x01
+
 /**
  * For convenience, we may need to pass around the encrypted session
  * key between kernel and userspace because the authentication token
Signature · 1 line
1.7.10.4