diff mbox series

[28/42] mkfs.ubifs: Move fscrypt definitions and functions out of mkfs.ubifs.c

Message ID 20181018143718.26298-29-richard@nod.at
State Accepted
Delegated to: David Oberhollenzer
Headers show
Series mtd-utils: Add fscrypt support to mkfs.ubifs | expand

Commit Message

Richard Weinberger Oct. 18, 2018, 2:37 p.m. UTC
From: David Oberhollenzer <david.oberhollenzer@sigma-star.at>

Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Signed-off-by: Richard Weinberger <richard@nod.at>
---
 ubifs-utils/Makemodule.am           |   2 +
 ubifs-utils/mkfs.ubifs/fscrypt.c    | 256 ++++++++++++++++++++++++
 ubifs-utils/mkfs.ubifs/fscrypt.h    | 112 +++++++++++
 ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 292 +---------------------------
 4 files changed, 376 insertions(+), 286 deletions(-)
 create mode 100644 ubifs-utils/mkfs.ubifs/fscrypt.c
 create mode 100644 ubifs-utils/mkfs.ubifs/fscrypt.h
diff mbox series

Patch

diff --git a/ubifs-utils/Makemodule.am b/ubifs-utils/Makemodule.am
index 3dd299dd20cc..5905a2badbb6 100644
--- a/ubifs-utils/Makemodule.am
+++ b/ubifs-utils/Makemodule.am
@@ -11,6 +11,7 @@  mkfs_ubifs_SOURCES = \
 	ubifs-utils/mkfs.ubifs/lpt.c \
 	ubifs-utils/mkfs.ubifs/compr.c \
 	ubifs-utils/mkfs.ubifs/crypto.c \
+	ubifs-utils/mkfs.ubifs/fscrypt.c \
 	ubifs-utils/mkfs.ubifs/hashtable/hashtable.h \
 	ubifs-utils/mkfs.ubifs/hashtable/hashtable_itr.h \
 	ubifs-utils/mkfs.ubifs/hashtable/hashtable_private.h \
@@ -30,6 +31,7 @@  UBIFS_HEADER = \
 	ubifs-utils/mkfs.ubifs/lpt.h ubifs-utils/mkfs.ubifs/mkfs.ubifs.h \
 	ubifs-utils/mkfs.ubifs/ubifs.h \
 	ubifs-utils/mkfs.ubifs/crypto.h \
+	ubifs-utils/mkfs.ubifs/fscrypt.h \
 	ubifs-utils/mkfs.ubifs/hashtable/hashtable.h \
 	ubifs-utils/mkfs.ubifs/hashtable/hashtable_itr.h \
 	ubifs-utils/mkfs.ubifs/hashtable/hashtable_private.h
diff --git a/ubifs-utils/mkfs.ubifs/fscrypt.c b/ubifs-utils/mkfs.ubifs/fscrypt.c
new file mode 100644
index 000000000000..68001e1d88f4
--- /dev/null
+++ b/ubifs-utils/mkfs.ubifs/fscrypt.c
@@ -0,0 +1,256 @@ 
+/*
+ * Copyright (C) 2017 sigma star gmbh
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Richard Weinberger <richard@sigma-star.at>
+ *          David Oberhollenzer <david.oberhollenzer@sigma-star.at>
+ */
+
+#define PROGRAM_NAME "mkfs.ubifs"
+#include "fscrypt.h"
+
+
+static __u8 fscrypt_masterkey[FS_MAX_KEY_SIZE];
+static struct cipher *fscrypt_cipher;
+
+
+unsigned char *calc_fscrypt_subkey(struct fscrypt_context *fctx)
+{
+	int ret;
+	unsigned char *new_key = xmalloc(FS_MAX_KEY_SIZE);
+
+	ret = derive_key_aes(fctx->nonce, fscrypt_masterkey, FS_MAX_KEY_SIZE, new_key);
+	if (ret < 0) {
+		err_msg("derive_key_aes failed: %i\n", ret);
+
+		free(new_key);
+		new_key = NULL;
+	}
+
+	return new_key;
+}
+
+struct fscrypt_context *inherit_fscrypt_context(struct fscrypt_context *fctx)
+{
+	struct fscrypt_context *new_fctx = NULL;
+
+	if (fctx) {
+		new_fctx = xmalloc(sizeof(*new_fctx));
+		new_fctx->format = fctx->format;
+		new_fctx->contents_encryption_mode = fctx->contents_encryption_mode;
+		new_fctx->filenames_encryption_mode = fctx->filenames_encryption_mode;
+		new_fctx->flags = fctx->flags;
+		memcpy(new_fctx->master_key_descriptor, fctx->master_key_descriptor,
+		       FS_KEY_DESCRIPTOR_SIZE);
+		RAND_bytes((void *)&new_fctx->nonce, FS_KEY_DERIVATION_NONCE_SIZE);
+	}
+
+	return new_fctx;
+}
+
+void free_fscrypt_context(struct fscrypt_context *fctx)
+{
+	free(fctx);
+}
+
+void print_fscrypt_master_key_descriptor(struct fscrypt_context *fctx)
+{
+	int i;
+
+	normsg_cont("fscrypt master key descriptor: ");
+	for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; i++) {
+		normsg_cont("%02x", fctx->master_key_descriptor[i]);
+	}
+	normsg("");
+}
+
+unsigned int fscrypt_fname_encrypted_size(struct fscrypt_context *fctx,
+					  unsigned int ilen)
+{
+	int padding;
+
+	padding = 4 << (fctx->flags & FS_POLICY_FLAGS_PAD_MASK);
+	ilen = max_t(unsigned int, ilen, FS_CRYPTO_BLOCK_SIZE);
+	return round_up(ilen, padding);
+}
+
+int encrypt_path(void **outbuf, void *data, unsigned int data_len,
+		unsigned int max_namelen, struct fscrypt_context *fctx)
+{
+	void *inbuf, *crypt_key;
+	unsigned int padding = 4 << (fctx->flags & FS_POLICY_FLAGS_PAD_MASK);
+	unsigned int cryptlen;
+	int ret;
+
+	cryptlen = max_t(unsigned int, data_len, FS_CRYPTO_BLOCK_SIZE);
+	cryptlen = round_up(cryptlen, padding);
+	cryptlen = min(cryptlen, max_namelen);
+
+	inbuf = xmalloc(cryptlen);
+	/* CTS mode needs a block size aligned buffer */
+	*outbuf = xmalloc(round_up(cryptlen, FS_CRYPTO_BLOCK_SIZE));
+
+	memset(inbuf, 0, cryptlen);
+	memcpy(inbuf, data, data_len);
+
+	crypt_key = calc_fscrypt_subkey(fctx);
+	if (!crypt_key)
+		return err_msg("could not compute subkey");
+
+	ret = fscrypt_cipher->encrypt_fname(inbuf, cryptlen,
+					    crypt_key, *outbuf);
+	if (ret < 0)
+		return err_msg("could not encrypt filename");
+
+	free(crypt_key);
+	free(inbuf);
+	return cryptlen;
+}
+
+int encrypt_data_node(struct fscrypt_context *fctx, unsigned int block_no,
+		      struct ubifs_data_node *dn, size_t length)
+{
+	void *inbuf, *outbuf, *crypt_key;
+	size_t ret, pad_len = round_up(length, FS_CRYPTO_BLOCK_SIZE);
+
+	dn->compr_size = length;
+
+	inbuf = xzalloc(pad_len);
+	outbuf = xzalloc(pad_len);
+
+	memcpy(inbuf, &dn->data, length);
+
+	crypt_key = calc_fscrypt_subkey(fctx);
+	if (!crypt_key)
+		return err_msg("could not compute subkey");
+
+	ret = fscrypt_cipher->encrypt_block(inbuf, pad_len,
+					    crypt_key, block_no,
+					    outbuf);
+	if (ret != pad_len) {
+		return err_msg("encrypt_block returned %zi "
+				"instead of %zi", ret, pad_len);
+	}
+
+	memcpy(&dn->data, outbuf, pad_len);
+
+	free(inbuf);
+	free(outbuf);
+	free(crypt_key);
+	return pad_len;
+}
+
+static int xdigit(int x)
+{
+	if (isupper(x))
+		return x - 'A' + 0x0A;
+	if (islower(x))
+		return x - 'a' + 0x0A;
+	return x - '0';
+}
+
+static int parse_key_descriptor(const char *desc, __u8 *dst)
+{
+	int i, hi, lo;
+
+	for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; ++i) {
+		if (!desc[i * 2] || !desc[i * 2 + 1]) {
+			err_msg("key descriptor '%s' is too short", desc);
+			return -1;
+		}
+		if (!isxdigit(desc[i * 2]) || !isxdigit(desc[i * 2 + 1])) {
+			err_msg("invalid key descriptor '%s'", desc);
+			return -1;
+		}
+
+		hi = xdigit(desc[i * 2]);
+		lo = xdigit(desc[i * 2 + 1]);
+
+		dst[i] = (hi << 4) | lo;
+	}
+
+	if (desc[i * 2]) {
+		err_msg("key descriptor '%s' is too long", desc);
+		return -1;
+	}
+	return 0;
+}
+
+static int load_master_key(const char *key_file)
+{
+	int kf;
+	ssize_t keysize;
+
+	kf = open(key_file, O_RDONLY);
+	if (kf < 0) {
+		sys_errmsg("open '%s'", key_file);
+		return -1;
+	}
+
+	keysize = read(kf, fscrypt_masterkey, sizeof(fscrypt_masterkey));
+	if (keysize < 0) {
+		sys_errmsg("read '%s'", key_file);
+		goto fail;
+	}
+	if (keysize == 0) {
+		err_msg("loading key from '%s': file is empty", key_file);
+		goto fail;
+	}
+
+	close(kf);
+	return 0;
+fail:
+	close(kf);
+	return -1;
+}
+
+struct fscrypt_context *init_fscrypt_context(const char *cipher_name,
+					     unsigned int flags,
+					     const char *key_file,
+					     const char *key_descriptor)
+{
+	__u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
+	__u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
+	struct fscrypt_context *new_fctx;
+
+	fscrypt_cipher = get_cipher(cipher_name);
+
+	if (!fscrypt_cipher) {
+		fprintf(stderr, "Cannot find cipher '%s'\n"
+			"Try `%s --help' for more information\n",
+			cipher_name, PROGRAM_NAME);
+		return NULL;
+	}
+
+	if (parse_key_descriptor(key_descriptor, master_key_descriptor))
+		return NULL;
+
+	if (load_master_key(key_file))
+		return NULL;
+
+	RAND_bytes((void *)nonce, FS_KEY_DERIVATION_NONCE_SIZE);
+
+	new_fctx = xmalloc(sizeof(*new_fctx));
+
+	new_fctx->format = FS_ENCRYPTION_CONTEXT_FORMAT_V1;
+	new_fctx->contents_encryption_mode = FS_ENCRYPTION_MODE_AES_128_CBC;
+	new_fctx->filenames_encryption_mode = FS_ENCRYPTION_MODE_AES_128_CTS;
+	new_fctx->flags = flags;
+
+	memcpy(&new_fctx->nonce, nonce, FS_KEY_DERIVATION_NONCE_SIZE);
+	memcpy(&new_fctx->master_key_descriptor, master_key_descriptor,
+		FS_KEY_DESCRIPTOR_SIZE);
+	return new_fctx;
+}
diff --git a/ubifs-utils/mkfs.ubifs/fscrypt.h b/ubifs-utils/mkfs.ubifs/fscrypt.h
new file mode 100644
index 000000000000..b6fb6d136e58
--- /dev/null
+++ b/ubifs-utils/mkfs.ubifs/fscrypt.h
@@ -0,0 +1,112 @@ 
+/*
+ * Copyright (C) 2017 sigma star gmbh
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Richard Weinberger <richard@sigma-star.at>
+ *          David Oberhollenzer <david.oberhollenzer@sigma-star.at>
+ */
+
+#ifndef FSCRYPT_H
+#define FSCRYPT_H
+
+
+#include "mkfs.ubifs.h"
+#include <sys/types.h>
+#include "crypto.h"
+
+
+#ifndef FS_KEY_DESCRIPTOR_SIZE
+#define FS_KEY_DESCRIPTOR_SIZE  8
+#endif
+#define FS_ENCRYPTION_CONTEXT_FORMAT_V1 1
+#define FS_KEY_DERIVATION_NONCE_SIZE	16
+
+#ifndef FS_ENCRYPTION_MODE_AES_128_CBC
+#define FS_ENCRYPTION_MODE_AES_128_CBC 5
+#endif
+
+#ifndef FS_ENCRYPTION_MODE_AES_128_CTS
+#define FS_ENCRYPTION_MODE_AES_128_CTS 6
+#endif
+
+#ifndef FS_POLICY_FLAGS_VALID
+#define FS_POLICY_FLAGS_PAD_4		0x00
+#define FS_POLICY_FLAGS_PAD_8		0x01
+#define FS_POLICY_FLAGS_PAD_16		0x02
+#define FS_POLICY_FLAGS_PAD_32		0x03
+#define FS_POLICY_FLAGS_PAD_MASK	0x03
+#define FS_POLICY_FLAGS_VALID		0x03
+#endif
+
+#define FS_CRYPTO_BLOCK_SIZE	16
+
+/**
+ * Encryption context for inode
+ *
+ * Protector format:
+ *  1 byte: Protector format (1 = this version)
+ *  1 byte: File contents encryption mode
+ *  1 byte: File names encryption mode
+ *  1 byte: Flags
+ *  8 bytes: Master Key descriptor
+ *  16 bytes: Encryption Key derivation nonce
+ */
+struct fscrypt_context {
+	__u8 format;
+	__u8 contents_encryption_mode;
+	__u8 filenames_encryption_mode;
+	__u8 flags;
+	__u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
+	__u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
+} __attribute__((packed));
+
+/**
+ * For encrypted symlinks, the ciphertext length is stored at the beginning
+ * of the string in little-endian format.
+ */
+struct fscrypt_symlink_data {
+	__le16 len;
+	char encrypted_path[1];
+} __attribute__((packed));
+
+
+#ifndef FS_MAX_KEY_SIZE
+#define FS_MAX_KEY_SIZE	64
+#endif
+
+unsigned char *calc_fscrypt_subkey(struct fscrypt_context *fctx);
+
+struct fscrypt_context *inherit_fscrypt_context(struct fscrypt_context *fctx);
+
+void free_fscrypt_context(struct fscrypt_context *fctx);
+
+void print_fscrypt_master_key_descriptor(struct fscrypt_context *fctx);
+
+unsigned int fscrypt_fname_encrypted_size(struct fscrypt_context *fctx,
+					  unsigned int ilen);
+
+int encrypt_path(void **outbuf, void *data, unsigned int data_len,
+		 unsigned int max_namelen, struct fscrypt_context *fctx);
+
+int encrypt_data_node(struct fscrypt_context *fctx, unsigned int block_no,
+		      struct ubifs_data_node *dn, size_t length);
+
+struct fscrypt_context *init_fscrypt_context(const char *cipher_name,
+					     unsigned int flags,
+					     const char *key_file,
+					     const char *key_descriptor);
+
+#endif /* FSCRYPT_H */
+
diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index 707758a42f4f..1710e25b88ee 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -36,6 +36,7 @@ 
 #endif
 
 #include "crypto.h"
+#include "fscrypt.h"
 
 /* Size (prime number) of hash table for link counting */
 #define HASH_TABLE_SIZE 10099
@@ -110,66 +111,6 @@  struct inum_mapping {
 	struct stat st;
 };
 
-#ifndef FS_KEY_DESCRIPTOR_SIZE
-#define FS_KEY_DESCRIPTOR_SIZE  8
-#endif
-#define FS_ENCRYPTION_CONTEXT_FORMAT_V1 1
-#define FS_KEY_DERIVATION_NONCE_SIZE	16
-
-#ifndef FS_ENCRYPTION_MODE_AES_128_CBC
-#define FS_ENCRYPTION_MODE_AES_128_CBC 5
-#endif
-
-#ifndef FS_ENCRYPTION_MODE_AES_128_CTS
-#define FS_ENCRYPTION_MODE_AES_128_CTS 6
-#endif
-
-#ifndef FS_POLICY_FLAGS_VALID
-#define FS_POLICY_FLAGS_PAD_4		0x00
-#define FS_POLICY_FLAGS_PAD_8		0x01
-#define FS_POLICY_FLAGS_PAD_16		0x02
-#define FS_POLICY_FLAGS_PAD_32		0x03
-#define FS_POLICY_FLAGS_PAD_MASK	0x03
-#define FS_POLICY_FLAGS_VALID		0x03
-#endif
-
-#define FS_CRYPTO_BLOCK_SIZE	16
-
-/**
- * Encryption context for inode
- *
- * Protector format:
- *  1 byte: Protector format (1 = this version)
- *  1 byte: File contents encryption mode
- *  1 byte: File names encryption mode
- *  1 byte: Flags
- *  8 bytes: Master Key descriptor
- *  16 bytes: Encryption Key derivation nonce
- */
-struct fscrypt_context {
-	__u8 format;
-	__u8 contents_encryption_mode;
-	__u8 filenames_encryption_mode;
-	__u8 flags;
-	__u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
-	__u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
-} __attribute__((packed));
-
-/**
- * For encrypted symlinks, the ciphertext length is stored at the beginning
- * of the string in little-endian format.
- */
-struct fscrypt_symlink_data {
-	__le16 len;
-	char encrypted_path[1];
-} __attribute__((packed));
-
-
-#ifndef FS_MAX_KEY_SIZE
-#define FS_MAX_KEY_SIZE	64
-#endif
-static __u8 fscrypt_masterkey[FS_MAX_KEY_SIZE];
-
 /*
  * Because we copy functions from the kernel, we use a subset of the UBIFS
  * file-system description object struct ubifs_info.
@@ -186,7 +127,6 @@  int yes;
 static char *root;
 static int root_len;
 static struct fscrypt_context *root_fctx;
-static struct cipher *fscrypt_cipher;
 static struct stat root_st;
 static char *output;
 static int out_fd;
@@ -541,160 +481,6 @@  static long long get_bytes(const char *str)
 
 	return bytes;
 }
-
-static unsigned char *calc_fscrypt_subkey(struct fscrypt_context *fctx)
-{
-	int ret;
-	unsigned char *new_key = xmalloc(FS_MAX_KEY_SIZE);
-
-	ret = derive_key_aes(fctx->nonce, fscrypt_masterkey, FS_MAX_KEY_SIZE, new_key);
-	if (ret < 0) {
-		err_msg("derive_key_aes failed: %i\n", ret);
-
-		free(new_key);
-		new_key = NULL;
-	}
-
-	return new_key;
-}
-
-static struct fscrypt_context *inherit_fscrypt_context(struct fscrypt_context *fctx)
-{
-	struct fscrypt_context *new_fctx = NULL;
-
-	if (fctx) {
-		new_fctx = xmalloc(sizeof(*new_fctx));
-		new_fctx->format = fctx->format;
-		new_fctx->contents_encryption_mode = fctx->contents_encryption_mode;
-		new_fctx->filenames_encryption_mode = fctx->filenames_encryption_mode;
-		new_fctx->flags = fctx->flags;
-		memcpy(new_fctx->master_key_descriptor, fctx->master_key_descriptor,
-		       FS_KEY_DESCRIPTOR_SIZE);
-		RAND_bytes((void *)&new_fctx->nonce, FS_KEY_DERIVATION_NONCE_SIZE);
-	}
-
-	return new_fctx;
-}
-
-static void free_fscrypt_context(struct fscrypt_context *fctx)
-{
-	free(fctx);
-}
-
-static void print_fscrypt_master_key_descriptor(struct fscrypt_context *fctx)
-{
-	int i;
-
-	normsg_cont("fscrypt master key descriptor: ");
-	for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; i++) {
-		normsg_cont("%02x", fctx->master_key_descriptor[i]);
-	}
-	normsg("");
-}
-
-static int xdigit(int x)
-{
-	if (isupper(x))
-		return x - 'A' + 0x0A;
-	if (islower(x))
-		return x - 'a' + 0x0A;
-	return x - '0';
-}
-
-static int parse_key_descriptor(const char *desc, __u8 *dst)
-{
-	int i, hi, lo;
-
-	for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; ++i) {
-		if (!desc[i * 2] || !desc[i * 2 + 1]) {
-			err_msg("key descriptor '%s' is too short", desc);
-			return -1;
-		}
-		if (!isxdigit(desc[i * 2]) || !isxdigit(desc[i * 2 + 1])) {
-			err_msg("invalid key descriptor '%s'", desc);
-			return -1;
-		}
-
-		hi = xdigit(desc[i * 2]);
-		lo = xdigit(desc[i * 2 + 1]);
-
-		dst[i] = (hi << 4) | lo;
-	}
-
-	if (desc[i * 2]) {
-		err_msg("key descriptor '%s' is too long", desc);
-		return -1;
-	}
-	return 0;
-}
-
-static int load_master_key(const char *key_file)
-{
-	int kf;
-	ssize_t keysize;
-
-	kf = open(key_file, O_RDONLY);
-	if (kf < 0) {
-		sys_errmsg("open '%s'", key_file);
-		return -1;
-	}
-
-	keysize = read(kf, fscrypt_masterkey, sizeof(fscrypt_masterkey));
-	if (keysize < 0) {
-		sys_errmsg("read '%s'", key_file);
-		goto fail;
-	}
-	if (keysize == 0) {
-		err_msg("loading key from '%s': file is empty", key_file);
-		goto fail;
-	}
-
-	close(kf);
-	return 0;
-fail:
-	close(kf);
-	return -1;
-}
-
-static struct fscrypt_context *init_fscrypt_context(unsigned int flags,
-						const char *key_file,
-						const char *key_descriptor)
-{
-	__u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
-	__u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
-	struct fscrypt_context *new_fctx;
-
-	if (parse_key_descriptor(key_descriptor, master_key_descriptor))
-		return NULL;
-
-	if (load_master_key(key_file))
-		return NULL;
-
-	RAND_bytes((void *)nonce, FS_KEY_DERIVATION_NONCE_SIZE);
-
-	new_fctx = xmalloc(sizeof(*new_fctx));
-
-	new_fctx->format = FS_ENCRYPTION_CONTEXT_FORMAT_V1;
-	new_fctx->contents_encryption_mode = FS_ENCRYPTION_MODE_AES_128_CBC;
-	new_fctx->filenames_encryption_mode = FS_ENCRYPTION_MODE_AES_128_CTS;
-	new_fctx->flags = flags;
-
-	memcpy(&new_fctx->nonce, nonce, FS_KEY_DERIVATION_NONCE_SIZE);
-	memcpy(&new_fctx->master_key_descriptor, master_key_descriptor,
-		FS_KEY_DESCRIPTOR_SIZE);
-	return new_fctx;
-}
-
-unsigned int fscrypt_fname_encrypted_size(struct fscrypt_context *fctx, unsigned int ilen)
-{
-	int padding;
-
-	padding = 4 << (fctx->flags & FS_POLICY_FLAGS_PAD_MASK);
-	ilen = max_t(unsigned int, ilen, FS_CRYPTO_BLOCK_SIZE);
-	return round_up(ilen, padding);
-}
-
-
 /**
  * open_ubi - open the UBI volume.
  * @node: name of the UBI volume character device to fetch information about
@@ -972,19 +758,11 @@  static int get_options(int argc, char**argv)
 		c->double_hash = 1;
 		c->encrypted = 1;
 
-		root_fctx = init_fscrypt_context(fscrypt_flags,
+		root_fctx = init_fscrypt_context(cipher_name, fscrypt_flags,
 						key_file, key_desc);
 		if (!root_fctx)
 			return -1;
 
-		fscrypt_cipher = get_cipher(cipher_name);
-		if (!fscrypt_cipher) {
-			fprintf(stderr, "Cannot find cipher '%s'\n"
-				"Try `%s --help' for more information\n",
-				cipher_name, PROGRAM_NAME);
-			return -1;
-		}
-
 		print_fscrypt_master_key_descriptor(root_fctx);
 	}
 
@@ -1616,39 +1394,6 @@  static int set_fscrypt_context(struct ubifs_ino_node *host_ino, ino_t inum,
 			 fctx, sizeof(*fctx));
 }
 
-static int encrypt_path(void **outbuf, void *data, unsigned int data_len,
-			unsigned int max_namelen, struct fscrypt_context *fctx)
-{
-	void *inbuf, *crypt_key;
-	unsigned int padding = 4 << (fctx->flags & FS_POLICY_FLAGS_PAD_MASK);
-	unsigned int cryptlen;
-	int ret;
-
-	cryptlen = max_t(unsigned int, data_len, FS_CRYPTO_BLOCK_SIZE);
-	cryptlen = round_up(cryptlen, padding);
-	cryptlen = min(cryptlen, max_namelen);
-
-	inbuf = xmalloc(cryptlen);
-	/* CTS mode needs a block size aligned buffer */
-	*outbuf = xmalloc(round_up(cryptlen, FS_CRYPTO_BLOCK_SIZE));
-
-	memset(inbuf, 0, cryptlen);
-	memcpy(inbuf, data, data_len);
-
-	crypt_key = calc_fscrypt_subkey(fctx);
-	if (!crypt_key)
-		return err_msg("could not compute subkey");
-
-	ret = fscrypt_cipher->encrypt_fname(inbuf, cryptlen,
-					    crypt_key, *outbuf);
-	if (ret < 0)
-		return err_msg("could not encrypt filename");
-
-	free(crypt_key);
-	free(inbuf);
-	return cryptlen;
-}
-
 static int encrypt_symlink(void *dst, void *data, unsigned int data_len,
 			   struct fscrypt_context *fctx)
 {
@@ -2011,35 +1756,10 @@  static int add_file(const char *path_name, struct stat *st, ino_t inum,
 		if (!fctx) {
 			dn->compr_size = 0;
 		} else {
-			void *inbuf, *outbuf, *crypt_key;
-			size_t ret, pad_len = round_up(out_len, FS_CRYPTO_BLOCK_SIZE);
-
-			dn->compr_size = out_len;
-
-			inbuf = xzalloc(pad_len);
-			outbuf = xzalloc(pad_len);
-
-			memcpy(inbuf, &dn->data, out_len);
-
-			crypt_key = calc_fscrypt_subkey(fctx);
-			if (!crypt_key)
-				return err_msg("could not compute subkey");
-
-			ret = fscrypt_cipher->encrypt_block(inbuf, pad_len,
-							    crypt_key, block_no,
-							    outbuf);
-			if (ret != pad_len) {
-				return err_msg("encrypt_block returned %zi "
-						"instead of %zi", ret, pad_len);
-			}
-
-			memcpy(&dn->data, outbuf, pad_len);
-
-			out_len = pad_len;
-
-			free(inbuf);
-			free(outbuf);
-			free(crypt_key);
+			ret = encrypt_data_node(fctx, block_no, dn, out_len);
+			if (ret < 0)
+				return ret;
+			out_len = ret;
 		}
 
 		dn_len = UBIFS_DATA_NODE_SZ + out_len;