Discussion:
[PATCH 02/42] common: Add round functions
Richard Weinberger
2018-10-18 14:36:38 UTC
Permalink
Signed-off-by: Richard Weinberger <***@nod.at>
---
include/common.h | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/include/common.h b/include/common.h
index 2f24645fe23b..72707697b170 100644
--- a/include/common.h
+++ b/include/common.h
@@ -65,6 +65,16 @@ extern "C" {
(_x > _y) ? _x : _y; \
})

+/*
+ * This looks more complex than it should be. But we need to
+ * get the type for the ~ right in round_down (it needs to be
+ * as wide as the result!), and we want to evaluate the macro
+ * arguments just once each.
+ */
+#define __round_mask(x, y) ((__typeof__(x))((y)-1))
+#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
+#define round_down(x, y) ((x) & ~__round_mask(x, y))
+
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
--
2.19.1
Richard Weinberger
2018-10-18 14:36:40 UTC
Permalink
From: David Oberhollenzer <***@sigma-star.at>

Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 13 +++++++++++++
ubifs-utils/mkfs.ubifs/mkfs.ubifs.h | 2 ++
ubifs-utils/mkfs.ubifs/ubifs.h | 2 ++
3 files changed, 17 insertions(+)

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index fd6538c6d4e1..e7acf17f6c96 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -1436,6 +1436,14 @@ static int add_symlink_inode(const char *path_name, struct stat *st, ino_t inum,
return add_inode(st, inum, buf, len, flags, path_name);
}

+static void set_dent_cookie(struct ubifs_dent_node *dent)
+{
+ if (c->double_hash)
+ RAND_bytes((void *)&dent->cookie, sizeof(dent->cookie));
+ else
+ dent->cookie = 0;
+}
+
/**
* add_dent_node - write a directory entry node.
* @dir_inum: target inode number of directory
@@ -1469,6 +1477,7 @@ static int add_dent_node(ino_t dir_inum, const char *name, ino_t inum,
dent->nlen = cpu_to_le16(dname.len);
memcpy(dent->name, dname.name, dname.len);
dent->name[dname.len] = '\0';
+ set_dent_cookie(dent);

len = UBIFS_DENT_NODE_SZ + dname.len + 1;

@@ -2268,6 +2277,8 @@ static int write_super(void)
sup.flags |= cpu_to_le32(UBIFS_FLG_BIGLPT);
if (c->space_fixup)
sup.flags |= cpu_to_le32(UBIFS_FLG_SPACE_FIXUP);
+ if (c->double_hash)
+ sup.flags |= cpu_to_le32(UBIFS_FLG_DOUBLE_HASH);

return write_node(&sup, UBIFS_SB_NODE_SZ, UBIFS_SB_LNUM);
}
@@ -2630,6 +2641,8 @@ int main(int argc, char *argv[])
if (crypto_init())
return -1;

+ RAND_poll();
+
err = get_options(argc, argv);
if (err)
return err;
diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.h b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.h
index 132119167fa5..aa032392155b 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.h
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.h
@@ -46,6 +46,8 @@
#include <uuid.h>
#include <sys/file.h>

+#include <openssl/rand.h>
+
#include <mtd/ubifs-media.h>

/* common.h requires the PROGRAM_NAME macro */
diff --git a/ubifs-utils/mkfs.ubifs/ubifs.h b/ubifs-utils/mkfs.ubifs/ubifs.h
index 2f080a8ce708..5a4af997e7bd 100644
--- a/ubifs-utils/mkfs.ubifs/ubifs.h
+++ b/ubifs-utils/mkfs.ubifs/ubifs.h
@@ -330,6 +330,7 @@ struct ubifs_znode
* @nhead_offs: offset of LPT head
* @big_lpt: flag that LPT is too big to write whole during commit
* @space_fixup: flag indicating that free space in LEBs needs to be cleaned up
+ * @double_hash: flag indicating that we can do lookups by hash
* @lpt_sz: LPT size
*
* @ltab_lnum: LEB number of LPT's own lprops table
@@ -408,6 +409,7 @@ struct ubifs_info
int nhead_offs;
int big_lpt;
int space_fixup;
+ int double_hash;
long long lpt_sz;

int ltab_lnum;
--
2.19.1
Richard Weinberger
2018-10-18 14:36:37 UTC
Permalink
Signed-off-by: Richard Weinberger <***@nod.at>
---
include/mtd/ubifs-media.h | 67 +++++++++++++++++++++++++++++++++++----
1 file changed, 60 insertions(+), 7 deletions(-)

diff --git a/include/mtd/ubifs-media.h b/include/mtd/ubifs-media.h
index a324e90a58d7..e69ba1687134 100644
--- a/include/mtd/ubifs-media.h
+++ b/include/mtd/ubifs-media.h
@@ -38,8 +38,30 @@
/* UBIFS node magic number (must not have the padding byte first or last) */
#define UBIFS_NODE_MAGIC 0x06101831

-/* UBIFS on-flash format version */
-#define UBIFS_FORMAT_VERSION 4
+/*
+ * UBIFS on-flash format version. This version is increased when the on-flash
+ * format is changing. If this happens, UBIFS is will support older versions as
+ * well. But older UBIFS code will not support newer formats. Format changes
+ * will be rare and only when absolutely necessary, e.g. to fix a bug or to add
+ * a new feature.
+ *
+ * UBIFS went into mainline kernel with format version 4. The older formats
+ * were development formats.
+ */
+#define UBIFS_FORMAT_VERSION 5
+
+/*
+ * Read-only compatibility version. If the UBIFS format is changed, older UBIFS
+ * implementations will not be able to mount newer formats in read-write mode.
+ * However, depending on the change, it may be possible to mount newer formats
+ * in R/O mode. This is indicated by the R/O compatibility version which is
+ * stored in the super-block.
+ *
+ * This is needed to support boot-loaders which only need R/O mounting. With
+ * this flag it is possible to do UBIFS format changes without a need to update
+ * boot-loaders.
+ */
+#define UBIFS_RO_COMPAT_VERSION 0

/* Minimum logical eraseblock size in bytes */
#define UBIFS_MIN_LEB_SZ (15*1024)
@@ -53,6 +75,13 @@
*/
#define UBIFS_MIN_COMPR_LEN 128

+/*
+ * If compressed data length is less than %UBIFS_MIN_COMPRESS_DIFF bytes
+ * shorter than uncompressed data length, UBIFS prefers to leave this data
+ * node uncompress, because it'll be read faster.
+ */
+#define UBIFS_MIN_COMPRESS_DIFF 64
+
/* Root inode number */
#define UBIFS_ROOT_INO 1

@@ -77,7 +106,6 @@
*/
#define UBIFS_BLOCK_SIZE 4096
#define UBIFS_BLOCK_SHIFT 12
-#define UBIFS_BLOCK_MASK 0x00000FFF

/* UBIFS padding byte pattern (must not be first or last byte of node magic) */
#define UBIFS_PADDING_BYTE 0xCE
@@ -109,6 +137,13 @@
/* The key is always at the same position in all keyed nodes */
#define UBIFS_KEY_OFFSET offsetof(struct ubifs_ino_node, key)

+/* Garbage collector journal head number */
+#define UBIFS_GC_HEAD 0
+/* Base journal head number */
+#define UBIFS_BASE_HEAD 1
+/* Data journal head number */
+#define UBIFS_DATA_HEAD 2
+
/*
* LEB Properties Tree node types.
*
@@ -267,6 +302,13 @@ enum {
/* The largest UBIFS node */
#define UBIFS_MAX_NODE_SZ UBIFS_MAX_INO_NODE_SZ

+/*
+ * xattr name of UBIFS encryption context, we don't use a prefix
+ * nor a long name to not waste space on the flash.
+ */
+#define UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT "c"
+
+
/*
* On-flash inode flags.
*
@@ -276,6 +318,7 @@ enum {
* UBIFS_APPEND_FL: writes to the inode may only append data
* UBIFS_DIRSYNC_FL: I/O on this directory inode has to be synchronous
* UBIFS_XATTR_FL: this inode is the inode for an extended attribute value
+ * UBIFS_CRYPT_FL: use encryption for this inode
*
* Note, these are on-flash flags which correspond to ioctl flags
* (@FS_COMPR_FL, etc). They have the same values now, but generally, do not
@@ -288,6 +331,7 @@ enum {
UBIFS_APPEND_FL = 0x08,
UBIFS_DIRSYNC_FL = 0x10,
UBIFS_XATTR_FL = 0x20,
+ UBIFS_CRYPT_FL = 0x40,
};

/* Inode flag bits used by UBIFS */
@@ -376,12 +420,19 @@ enum {
*
* UBIFS_FLG_BIGLPT: if "big" LPT model is used if set
* UBIFS_FLG_SPACE_FIXUP: first-mount "fixup" of free space within LEBs needed
+ * UBIFS_FLG_DOUBLE_HASH: store a 32bit cookie in directory entry nodes to
+ * support 64bit cookies for lookups by hash
+ * UBIFS_FLG_ENCRYPTION: this filesystem contains encrypted files
*/
enum {
UBIFS_FLG_BIGLPT = 0x02,
UBIFS_FLG_SPACE_FIXUP = 0x04,
+ UBIFS_FLG_DOUBLE_HASH = 0x08,
+ UBIFS_FLG_ENCRYPTION = 0x10,
};

+#define UBIFS_FLG_MASK (UBIFS_FLG_BIGLPT|UBIFS_FLG_SPACE_FIXUP|UBIFS_FLG_DOUBLE_HASH|UBIFS_FLG_ENCRYPTION)
+
/**
* struct ubifs_ch - common header node.
* @magic: UBIFS node magic number (%UBIFS_NODE_MAGIC)
@@ -488,7 +539,8 @@ struct ubifs_ino_node {
* @padding1: reserved for future, zeroes
* @type: type of the target inode (%UBIFS_ITYPE_REG, %UBIFS_ITYPE_DIR, etc)
* @nlen: name length
- * @padding2: reserved for future, zeroes
+ * @cookie: A 32bits random number, used to construct a 64bits
+ * identifier.
* @name: zero-terminated name
*
* Note, do not forget to amend 'zero_dent_node_unused()' function when
@@ -501,7 +553,7 @@ struct ubifs_dent_node {
__u8 padding1;
__u8 type;
__le16 nlen;
- __u8 padding2[4]; /* Watch 'zero_dent_node_unused()' if changing! */
+ __le32 cookie;
__u8 name[];
} __attribute__ ((packed));

@@ -511,7 +563,7 @@ struct ubifs_dent_node {
* @key: node key
* @size: uncompressed data size in bytes
* @compr_type: compression type (%UBIFS_COMPR_NONE, %UBIFS_COMPR_LZO, etc)
- * @padding: reserved for future, zeroes
+ * @compr_size: compressed data size in bytes, only valid when data is encrypted
* @data: data
*
* Note, do not forget to amend 'zero_data_node_unused()' function when
@@ -522,7 +574,7 @@ struct ubifs_data_node {
__u8 key[UBIFS_MAX_KEY_LEN];
__le32 size;
__le16 compr_type;
- __u8 padding[2]; /* Watch 'zero_data_node_unused()' if changing! */
+ __le16 compr_size;
__u8 data[];
} __attribute__ ((packed));

@@ -584,6 +636,7 @@ struct ubifs_pad_node {
* @padding2: reserved for future, zeroes
* @time_gran: time granularity in nanoseconds
* @uuid: UUID generated when the file system image was created
+ * @ro_compat_version: UBIFS R/O compatibility version
*/
struct ubifs_sb_node {
struct ubifs_ch ch;
--
2.19.1
Richard Weinberger
2018-10-18 14:36:39 UTC
Permalink
From: David Oberhollenzer <***@sigma-star.at>

Signed-off-by: David Oberhollenzer <***@sigma-star.at>
Signed-off-by: Richard Weinberger <***@nod.at>
---
configure.ac | 1 +
ubifs-utils/Makemodule.am | 4 +-
ubifs-utils/mkfs.ubifs/crypto.c | 327 ++++++++++++++++++++++++++++
ubifs-utils/mkfs.ubifs/crypto.h | 68 ++++++
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 6 +
5 files changed, 405 insertions(+), 1 deletion(-)
create mode 100644 ubifs-utils/mkfs.ubifs/crypto.c
create mode 100644 ubifs-utils/mkfs.ubifs/crypto.h

diff --git a/configure.ac b/configure.ac
index c596eda4a797..346fcbd26328 100644
--- a/configure.ac
+++ b/configure.ac
@@ -115,6 +115,7 @@ AC_ARG_ENABLE([lsmtd],
esac],
[AM_CONDITIONAL([BUILD_LSMTD], [true])])

+AC_CHECK_HEADER(openssl/rand.h)

AC_ARG_WITH([jffs],
[AS_HELP_STRING([--without-jffs], [Disable jffsX utilities])],
diff --git a/ubifs-utils/Makemodule.am b/ubifs-utils/Makemodule.am
index 879f91a98045..3dd299dd20cc 100644
--- a/ubifs-utils/Makemodule.am
+++ b/ubifs-utils/Makemodule.am
@@ -10,13 +10,14 @@ mkfs_ubifs_SOURCES = \
ubifs-utils/mkfs.ubifs/crc16.c \
ubifs-utils/mkfs.ubifs/lpt.c \
ubifs-utils/mkfs.ubifs/compr.c \
+ ubifs-utils/mkfs.ubifs/crypto.c \
ubifs-utils/mkfs.ubifs/hashtable/hashtable.h \
ubifs-utils/mkfs.ubifs/hashtable/hashtable_itr.h \
ubifs-utils/mkfs.ubifs/hashtable/hashtable_private.h \
ubifs-utils/mkfs.ubifs/hashtable/hashtable.c \
ubifs-utils/mkfs.ubifs/hashtable/hashtable_itr.c \
ubifs-utils/mkfs.ubifs/devtable.c
-mkfs_ubifs_LDADD = libmtd.a libubi.a $(ZLIB_LIBS) $(LZO_LIBS) $(UUID_LIBS) $(LIBSELINUX_LIBS) -lm
+mkfs_ubifs_LDADD = libmtd.a libubi.a $(ZLIB_LIBS) $(LZO_LIBS) $(UUID_LIBS) $(LIBSELINUX_LIBS) -lm -lssl -lcrypto
mkfs_ubifs_CPPFLAGS = $(AM_CPPFLAGS) $(ZLIB_CFLAGS) $(LZO_CFLAGS) $(UUID_CFLAGS) $(LIBSELINUX_CFLAGS)\
-I$(top_srcdir)/ubi-utils/include -I$(top_srcdir)/ubifs-utils/mkfs.ubifs/

@@ -28,6 +29,7 @@ UBIFS_HEADER = \
ubifs-utils/mkfs.ubifs/defs.h ubifs-utils/mkfs.ubifs/key.h \
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/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/crypto.c b/ubifs-utils/mkfs.ubifs/crypto.c
new file mode 100644
index 000000000000..a20bd56ba3db
--- /dev/null
+++ b/ubifs-utils/mkfs.ubifs/crypto.c
@@ -0,0 +1,327 @@
+/*
+ * 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: David Oberhollenzer <***@sigma-star.at>
+ */
+
+#define PROGRAM_NAME "mkfs.ubifs"
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <string.h>
+#include <assert.h>
+
+#include "crypto.h"
+#include "common.h"
+#include "mtd_swab.h"
+
+
+static struct cipher ciphers[] = {
+ {
+ .name = "AES-128-CBC",
+ .encrypt_block = encrypt_block_aes128_cbc,
+ .encrypt_fname = encrypt_aes128_cbc_cts,
+ }, {
+ .name = "AES-256-XTS",
+ .encrypt_block = encrypt_block_aes256_xts,
+ .encrypt_fname = encrypt_aes256_cbc_cts,
+ }
+};
+
+
+
+static int do_sha256(const unsigned char *in, size_t len, unsigned char *out)
+{
+ unsigned int out_len;
+ EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
+
+ if (!mdctx)
+ return -1;
+
+ if (EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL) != 1)
+ return -1;
+
+ if(EVP_DigestUpdate(mdctx, in, len) != 1)
+ return -1;
+
+ if(EVP_DigestFinal_ex(mdctx, out, &out_len) != 1)
+ return -1;
+
+ EVP_MD_CTX_destroy(mdctx);
+
+ return 0;
+}
+
+static int check_iv_key_size(const EVP_CIPHER *cipher, size_t key_len,
+ size_t iv_len)
+{
+ if ((size_t)EVP_CIPHER_key_length(cipher) != key_len) {
+ errmsg("Cipher key length mismatch. Expected %lu, got %d",
+ (unsigned long)key_len, EVP_CIPHER_key_length(cipher));
+ return -1;
+ }
+
+ if (iv_len && (size_t)EVP_CIPHER_iv_length(cipher) != iv_len) {
+ errmsg("Cipher IV length mismatch. Expected %lu, got %d",
+ (unsigned long)iv_len, EVP_CIPHER_key_length(cipher));
+ return -1;
+ }
+
+ return 0;
+}
+
+static ssize_t do_encrypt(const EVP_CIPHER *cipher,
+ const void *plaintext, size_t size,
+ const void *key, size_t key_len,
+ const void *iv, size_t iv_len,
+ void *ciphertext)
+{
+ int ciphertext_len, len;
+ EVP_CIPHER_CTX *ctx;
+
+ if (check_iv_key_size(cipher, key_len, iv_len))
+ return -1;
+
+ if (!(ctx = EVP_CIPHER_CTX_new()))
+ goto fail;
+
+ EVP_CIPHER_CTX_set_padding(ctx, 0);
+
+ if (EVP_EncryptInit_ex(ctx, cipher, NULL, key, iv) != 1)
+ goto fail_ctx;
+
+ if (EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, size) != 1)
+ goto fail_ctx;
+
+ ciphertext_len = len;
+
+ EVP_CIPHER_CTX_free(ctx);
+ return ciphertext_len;
+fail_ctx:
+ ERR_print_errors_fp(stderr);
+ EVP_CIPHER_CTX_free(ctx);
+ return -1;
+fail:
+ ERR_print_errors_fp(stderr);
+ return -1;
+}
+
+static size_t gen_essiv_salt(const void *iv, size_t iv_len, const void *key, size_t key_len, void *salt)
+{
+ size_t ret;
+ const EVP_CIPHER *cipher;
+ void *sha256 = xzalloc(EVP_MD_size(EVP_sha256()));
+
+ cipher = EVP_aes_256_ecb();
+ if (!cipher) {
+ errmsg("OpenSSL: Cipher AES-256-ECB is not supported");
+ return -1;
+ }
+
+ if (do_sha256(key, key_len, sha256) != 0) {
+ errmsg("sha256 failed");
+ return -1;
+ }
+
+ ret = do_encrypt(cipher, iv, iv_len, sha256, EVP_CIPHER_key_length(cipher), NULL, 0, salt);
+ if (ret != iv_len)
+ errmsg("Unable to compute ESSIV salt, return value %zi instead of %zi", ret, iv_len);
+
+ free(sha256);
+
+ return ret;
+}
+
+
+static ssize_t encrypt_block(const void *plaintext, size_t size,
+ const void *key, uint64_t block_index,
+ void *ciphertext, const EVP_CIPHER *cipher)
+{
+ size_t key_len, ret, ivsize;
+ void *essiv_salt, *iv;
+
+ ivsize = EVP_CIPHER_iv_length(cipher);
+ key_len = EVP_CIPHER_key_length(cipher);
+
+ iv = alloca(ivsize);
+ essiv_salt = alloca(ivsize);
+
+ memset(iv, 0, ivsize);
+ *((uint64_t *)iv) = cpu_to_le64(block_index);
+
+ gen_essiv_salt(iv, ivsize, key, key_len, essiv_salt);
+
+ ret = do_encrypt(cipher, plaintext, size, key, key_len,
+ essiv_salt, ivsize, ciphertext);
+ return ret;
+}
+
+ssize_t encrypt_block_aes128_cbc(const void *plaintext, size_t size,
+ const void *key, uint64_t block_index,
+ void *ciphertext)
+{
+ const EVP_CIPHER *cipher = EVP_aes_128_cbc();
+
+ if (!cipher) {
+ errmsg("OpenSSL: Cipher AES-128-CBC is not supported");
+ return -1;
+ }
+ return encrypt_block(plaintext, size, key, block_index,
+ ciphertext, cipher);
+}
+
+ssize_t encrypt_block_aes256_xts(const void *plaintext, size_t size,
+ const void *key, uint64_t block_index,
+ void *ciphertext)
+{
+ const EVP_CIPHER *cipher = EVP_aes_256_xts();
+
+ if (!cipher) {
+ errmsg("OpenSSL: Cipher AES-256-XTS is not supported");
+ return -1;
+ }
+ return encrypt_block(plaintext, size, key, block_index,
+ ciphertext, cipher);
+}
+
+static void block_swap(uint8_t *ciphertext, size_t i0, size_t i1,
+ size_t size)
+{
+ uint8_t temp[size], *p0, *p1;
+
+ p0 = ciphertext + i0 * size;
+ p1 = ciphertext + i1 * size;
+
+ memcpy(temp, p0, size);
+ memcpy(p0, p1, size);
+ memcpy(p1, temp, size);
+}
+
+static ssize_t encrypt_cbc_cts(const void *plaintext, size_t size,
+ const void *key, void *ciphertext,
+ const EVP_CIPHER *cipher)
+{
+ size_t diff, padded_size, count, ivsize;
+ uint8_t iv[EVP_MAX_IV_LENGTH], *padded;
+ ssize_t ret, key_len;
+
+ key_len = EVP_CIPHER_key_length(cipher);
+ ivsize = EVP_CIPHER_iv_length(cipher);
+
+ memset(iv, 0, ivsize);
+
+ diff = size % key_len;
+
+ if (diff) {
+ padded_size = size - diff + key_len;
+ padded = size > 256 ? malloc(padded_size) : alloca(padded_size);
+
+ memcpy(padded, plaintext, size);
+ memset(padded + size, 0, padded_size - size);
+
+ ret = do_encrypt(cipher, padded, padded_size, key, key_len,
+ iv, sizeof(iv), ciphertext);
+
+ if (size > 256)
+ free(padded);
+ } else {
+ ret = do_encrypt(cipher, plaintext, size, key, key_len,
+ iv, sizeof(iv), ciphertext);
+ }
+
+ if (ret < 0)
+ return ret;
+
+ count = ret / key_len;
+
+ if (count > 1)
+ block_swap(ciphertext, count - 2, count - 1, key_len);
+
+ return size;
+}
+
+ssize_t encrypt_aes128_cbc_cts(const void *plaintext, size_t size,
+ const void *key, void *ciphertext)
+{
+ const EVP_CIPHER *cipher = EVP_aes_128_cbc();
+ if (!cipher) {
+ errmsg("OpenSSL: Cipher AES-128-CBC is not supported");
+ return -1;
+ }
+
+ return encrypt_cbc_cts(plaintext, size, key, ciphertext, cipher);
+}
+
+ssize_t encrypt_aes256_cbc_cts(const void *plaintext, size_t size,
+ const void *key, void *ciphertext)
+{
+ const EVP_CIPHER *cipher = EVP_aes_256_cbc();
+ if (!cipher) {
+ errmsg("OpenSSL: Cipher AES-256-CBC is not supported");
+ return -1;
+ }
+
+ return encrypt_cbc_cts(plaintext, size, key, ciphertext, cipher);
+}
+
+ssize_t derive_key_aes(const void *deriving_key, const void *source_key,
+ void *derived_key)
+{
+ const EVP_CIPHER *cipher;
+ size_t aes_key_len;
+
+ cipher = EVP_aes_128_ecb();
+ if (!cipher) {
+ errmsg("OpenSSL: Cipher AES-128-ECB is not supported");
+ return -1;
+ }
+ aes_key_len = EVP_CIPHER_key_length(cipher);
+
+ return do_encrypt(cipher, source_key, aes_key_len, deriving_key,
+ aes_key_len, NULL, 0, derived_key);
+}
+
+int crypto_init(void)
+{
+ ERR_load_crypto_strings();
+ return 0;
+}
+
+void crypto_cleanup(void)
+{
+ EVP_cleanup();
+ ERR_free_strings();
+}
+
+struct cipher *get_cipher(const char *name)
+{
+ size_t i;
+
+ for (i = 0; i < sizeof(ciphers) / sizeof(ciphers[0]); ++i) {
+ if (!strcmp(ciphers[i].name, name))
+ return ciphers + i;
+ }
+
+ return NULL;
+}
+
+void list_ciphers(FILE *fp)
+{
+ size_t i;
+
+ for (i = 0; i < sizeof(ciphers) / sizeof(ciphers[0]); ++i) {
+ fprintf(fp, "\t%s\n", ciphers[i].name);
+ }
+}
diff --git a/ubifs-utils/mkfs.ubifs/crypto.h b/ubifs-utils/mkfs.ubifs/crypto.h
new file mode 100644
index 000000000000..4e597004ec51
--- /dev/null
+++ b/ubifs-utils/mkfs.ubifs/crypto.h
@@ -0,0 +1,68 @@
+/*
+ * 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: David Oberhollenzer <***@sigma-star.at>
+ */
+
+#ifndef UBIFS_CRYPTO_H
+#define UBIFS_CRYPTO_H
+
+#include <sys/types.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+
+
+struct cipher {
+ const char *name;
+
+ ssize_t (*encrypt_block)(const void *plaintext, size_t size,
+ const void *key, uint64_t block_index,
+ void *ciphertext);
+
+ ssize_t (*encrypt_fname)(const void *plaintext, size_t size,
+ const void *key, void *ciphertext);
+};
+
+
+int crypto_init(void);
+
+void crypto_cleanup(void);
+
+ssize_t encrypt_block_aes128_cbc(const void *plaintext, size_t size,
+ const void *key, uint64_t block_index,
+ void *ciphertext);
+
+ssize_t encrypt_block_aes256_xts(const void *plaintext, size_t size,
+ const void *key, uint64_t block_index,
+ void *ciphertext);
+
+ssize_t encrypt_aes128_cbc_cts(const void *plaintext, size_t size,
+ const void *key, void *ciphertext);
+
+ssize_t encrypt_aes256_cbc_cts(const void *plaintext, size_t size,
+ const void *key, void *ciphertext);
+
+ssize_t derive_key_aes(const void *deriving_key, const void *source_key,
+ void *derived_key);
+
+
+struct cipher *get_cipher(const char *name);
+
+void list_ciphers(FILE *fp);
+
+#endif /* UBIFS_CRYPTO_H */
+
diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index c764a237135f..fd6538c6d4e1 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -35,6 +35,8 @@
#include <selinux/label.h>
#endif

+#include "crypto.h"
+
/* Size (prime number) of hash table for link counting */
#define HASH_TABLE_SIZE 10099

@@ -2625,6 +2627,9 @@ int main(int argc, char *argv[])
{
int err;

+ if (crypto_init())
+ return -1;
+
err = get_options(argc, argv);
if (err)
return err;
@@ -2646,5 +2651,6 @@ int main(int argc, char *argv[])
if (verbose)
printf("Success!\n");

+ crypto_cleanup();
return 0;
}
--
2.19.1
Richard Weinberger
2018-10-18 14:36:49 UTC
Permalink
Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index 7deca96e7953..a43b2a1620b1 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -2720,6 +2720,12 @@ static int init(void)
sz = sizeof(struct inum_mapping *) * HASH_TABLE_SIZE;
hash_table = xzalloc(sz);

+ //TODO make this a parameter
+ root_fctx = init_fscrypt_context();
+ print_fscrypt_master_key_descriptor(root_fctx);
+ c->double_hash = 1;
+ c->encrypted = 1;
+
err = init_compression();
if (err)
return err;
--
2.19.1
Richard Weinberger
2018-10-18 14:36:41 UTC
Permalink
As of now all filenames known by UBIFS are strings with a NUL
terminator. With encrypted filenames a filename can be any binary
string and the r5 function cannot search for the NUL terminator.
UBIFS always knows how long a filename is, therefore we can change
the hash function to iterate over the filename length to work
correctly with binary strings.

Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/key.h | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/key.h b/ubifs-utils/mkfs.ubifs/key.h
index c16d0a85418e..0c7922b67687 100644
--- a/ubifs-utils/mkfs.ubifs/key.h
+++ b/ubifs-utils/mkfs.ubifs/key.h
@@ -64,9 +64,8 @@ static inline uint32_t key_r5_hash(const char *s, int len)
{
uint32_t a = 0;
const signed char *str = (const signed char *)s;
- (void)len;

- while (*str) {
+ while (len--) {
a += *str << 4;
a += *str >> 4;
a *= 11;
--
2.19.1
Richard Weinberger
2018-10-18 14:36:42 UTC
Permalink
most of them should be UAPI, therefore check using #ifndef

Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 50 +++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index e7acf17f6c96..2649c34cdd68 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -109,6 +109,56 @@ 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));
+
+#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.
--
2.19.1
Richard Weinberger
2018-10-18 14:36:43 UTC
Permalink
...maybe we should add them to crypto.c?

Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 67 +++++++++++++++++++++++++++++
1 file changed, 67 insertions(+)

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index 2649c34cdd68..fc1b0cb1f6cc 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -518,6 +518,73 @@ 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, 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 struct fscrypt_context *init_fscrypt_context(void)
+{
+ struct fscrypt_context *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;
+ //TODO accept padding via a parameter
+ new_fctx->flags = FS_POLICY_FLAGS_PAD_4;
+ //TODO accept descriptor via a parameter
+ RAND_bytes((void *)&new_fctx->master_key_descriptor, FS_KEY_DESCRIPTOR_SIZE);
+ RAND_bytes((void *)&new_fctx->nonce, FS_KEY_DERIVATION_NONCE_SIZE);
+
+ return new_fctx;
+}
+
/**
* open_ubi - open the UBI volume.
* @node: name of the UBI volume character device to fetch information about
--
2.19.1
Richard Weinberger
2018-10-18 14:36:48 UTC
Permalink
Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/key.h | 4 +-
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 61 +++++++++++++++++++++++------
2 files changed, 52 insertions(+), 13 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/key.h b/ubifs-utils/mkfs.ubifs/key.h
index 0c7922b67687..c18e35e8f0a3 100644
--- a/ubifs-utils/mkfs.ubifs/key.h
+++ b/ubifs-utils/mkfs.ubifs/key.h
@@ -110,9 +110,9 @@ static inline void ino_key_init(union ubifs_key *key, ino_t inum)
*/
static inline void dent_key_init(const struct ubifs_info *c,
union ubifs_key *key, ino_t inum,
- const struct qstr *nm)
+ const void *name, int name_len)
{
- uint32_t hash = c->key_hash(nm->name, nm->len);
+ uint32_t hash = c->key_hash(name, name_len);

assert(!(hash & ~UBIFS_S_KEY_HASH_MASK));
key->u32[0] = inum;
diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index 469d5874eaa2..7deca96e7953 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -1596,6 +1596,7 @@ static int add_dent_node(ino_t dir_inum, const char *name, ino_t inum,
union ubifs_key key;
struct qstr dname;
char *kname;
+ int kname_len;
int len;

dbg_msg(3, "%s ino %lu type %u dir ino %lu", name, (unsigned long)inum,
@@ -1607,23 +1608,61 @@ static int add_dent_node(ino_t dir_inum, const char *name, ino_t inum,

dent->ch.node_type = UBIFS_DENT_NODE;

- dent_key_init(c, &key, dir_inum, &dname);
- key_write(&key, dent->key);
dent->inum = cpu_to_le64(inum);
dent->padding1 = 0;
dent->type = type;
- dent->nlen = cpu_to_le16(dname.len);
- memcpy(dent->name, dname.name, dname.len);
- dent->name[dname.len] = '\0';
set_dent_cookie(dent);

- len = UBIFS_DENT_NODE_SZ + dname.len + 1;
-
- kname = strdup(name);
- if (!kname)
- return err_msg("cannot allocate memory");
+ if (!fctx) {
+ dent_key_init(c, &key, dir_inum, dname.name, dname.len);
+ dent->nlen = cpu_to_le16(dname.len);
+ memcpy(dent->name, dname.name, dname.len);
+ dent->name[dname.len] = '\0';
+ len = UBIFS_DENT_NODE_SZ + dname.len + 1;
+
+ kname_len = dname.len;
+ kname = strdup(name);
+ if (!kname)
+ return err_msg("cannot allocate memory");
+ } else {
+ void *inbuf, *outbuf, *crypt_key;
+ unsigned int max_namelen = type == UBIFS_ITYPE_LNK ? UBIFS_MAX_INO_DATA : UBIFS_MAX_NLEN;
+ unsigned int padding = 4 << (fctx->flags & FS_POLICY_FLAGS_PAD_MASK);
+ unsigned int cryptlen;
+
+ cryptlen = max_t(unsigned int, dname.len, FS_CRYPTO_BLOCK_SIZE);
+ cryptlen = round_up(cryptlen, padding);
+ cryptlen = min(cryptlen, max_namelen);
+
+ inbuf = xmalloc(cryptlen);
+ outbuf = xmalloc(cryptlen + 32);
+
+ memset(inbuf, 0, cryptlen);
+ memcpy(inbuf, dname.name, dname.len);
+
+ crypt_key = calc_fscrypt_subkey(fctx);
+ if (!crypt_key)
+ return err_msg("could not compute subkey");
+ if (encrypt_aes128_cbc_cts(inbuf, cryptlen, crypt_key, outbuf) < 0)
+ return err_msg("could not encrypt filename");
+
+ dent->nlen = cpu_to_le16(cryptlen);
+ memcpy(dent->name, outbuf, cryptlen);
+ dent->name[cryptlen] = '\0';
+ len = UBIFS_DENT_NODE_SZ + cryptlen + 1;
+
+ dent_key_init(c, &key, dir_inum, outbuf, cryptlen);
+
+ kname_len = cryptlen;
+ kname = xmalloc(cryptlen);
+ memcpy(kname, outbuf, cryptlen);
+ free(crypt_key);
+ free(inbuf);
+ free(outbuf);
+ }
+ key_write(&key, dent->key);

- return add_node(&key, kname, dname.len, dent, len);
+ return add_node(&key, kname, kname_len, dent, len);
}

/**
--
2.19.1
Richard Weinberger
2018-10-18 14:36:50 UTC
Permalink
fscrypto is using the max key lenth (64), so we cannot use the
AES-128-ECB len.

Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/crypto.c | 4 ++--
ubifs-utils/mkfs.ubifs/crypto.h | 2 +-
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/crypto.c b/ubifs-utils/mkfs.ubifs/crypto.c
index a20bd56ba3db..f249b49b5b59 100644
--- a/ubifs-utils/mkfs.ubifs/crypto.c
+++ b/ubifs-utils/mkfs.ubifs/crypto.c
@@ -277,7 +277,7 @@ ssize_t encrypt_aes256_cbc_cts(const void *plaintext, size_t size,
}

ssize_t derive_key_aes(const void *deriving_key, const void *source_key,
- void *derived_key)
+ size_t source_key_len, void *derived_key)
{
const EVP_CIPHER *cipher;
size_t aes_key_len;
@@ -289,7 +289,7 @@ ssize_t derive_key_aes(const void *deriving_key, const void *source_key,
}
aes_key_len = EVP_CIPHER_key_length(cipher);

- return do_encrypt(cipher, source_key, aes_key_len, deriving_key,
+ return do_encrypt(cipher, source_key, source_key_len, deriving_key,
aes_key_len, NULL, 0, derived_key);
}

diff --git a/ubifs-utils/mkfs.ubifs/crypto.h b/ubifs-utils/mkfs.ubifs/crypto.h
index 4e597004ec51..5bff70fea29e 100644
--- a/ubifs-utils/mkfs.ubifs/crypto.h
+++ b/ubifs-utils/mkfs.ubifs/crypto.h
@@ -57,7 +57,7 @@ ssize_t encrypt_aes256_cbc_cts(const void *plaintext, size_t size,
const void *key, void *ciphertext);

ssize_t derive_key_aes(const void *deriving_key, const void *source_key,
- void *derived_key);
+ size_t source_key_len, void *derived_key);


struct cipher *get_cipher(const char *name);
diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index a43b2a1620b1..c315e36dd3d3 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -526,7 +526,7 @@ 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, new_key);
+ 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);
--
2.19.1
Richard Weinberger
2018-10-18 14:36:47 UTC
Permalink
since names are no longer strings, we need to know the length.

Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 27 +++++++++++++++------------
1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index e391cdaae35f..469d5874eaa2 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -73,6 +73,7 @@ struct idx_entry {
struct idx_entry *prev;
union ubifs_key key;
char *name;
+ int name_len;
int lnum;
int offs;
int len;
@@ -1069,7 +1070,7 @@ static void set_lprops(int lnum, int offs, int flags)
* @offs: node offset
* @len: node length
*/
-static int add_to_index(union ubifs_key *key, char *name, int lnum, int offs,
+static int add_to_index(union ubifs_key *key, char *name, int name_len, int lnum, int offs,
int len)
{
struct idx_entry *e;
@@ -1080,6 +1081,7 @@ static int add_to_index(union ubifs_key *key, char *name, int lnum, int offs,
e->prev = idx_list_last;
e->key = *key;
e->name = name;
+ e->name_len = name_len;
e->lnum = lnum;
e->offs = offs;
e->len = len;
@@ -1138,7 +1140,7 @@ static int reserve_space(int len, int *lnum, int *offs)
* @node: node
* @len: node length
*/
-static int add_node(union ubifs_key *key, char *name, void *node, int len)
+static int add_node(union ubifs_key *key, char *name, int name_len, void *node, int len)
{
int err, lnum, offs;

@@ -1151,7 +1153,7 @@ static int add_node(union ubifs_key *key, char *name, void *node, int len)
memcpy(leb_buf + offs, node, len);
memset(leb_buf + offs + len, 0xff, ALIGN(len, 8) - len);

- add_to_index(key, name, lnum, offs, len);
+ add_to_index(key, name, name_len, lnum, offs, len);

return 0;
}
@@ -1194,7 +1196,7 @@ static int add_xattr(struct ubifs_ino_node *host_ino, struct stat *st, ino_t inu

xent->inum = cpu_to_le64(inum);

- ret = add_node(&xkey, nm.name, xent, len);
+ ret = add_node(&xkey, nm.name, nm.len, xent, len);
if (ret)
goto out;

@@ -1226,7 +1228,7 @@ static int add_xattr(struct ubifs_ino_node *host_ino, struct stat *st, ino_t inu
if (data_len)
memcpy(&ino->data, data, data_len);

- ret = add_node(&nkey, nm.name, ino, UBIFS_INO_NODE_SZ + data_len) ;
+ ret = add_node(&nkey, nm.name, nm.len, ino, UBIFS_INO_NODE_SZ + data_len) ;

out:
free(xent);
@@ -1499,7 +1501,7 @@ static int add_inode(struct stat *st, ino_t inum, void *data,
return ret;
}

- return add_node(&key, NULL, ino, len);
+ return add_node(&key, NULL, 0, ino, len);
}

/**
@@ -1621,7 +1623,7 @@ static int add_dent_node(ino_t dir_inum, const char *name, ino_t inum,
if (!kname)
return err_msg("cannot allocate memory");

- return add_node(&key, kname, dent, len);
+ return add_node(&key, kname, dname.len, dent, len);
}

/**
@@ -1732,9 +1734,10 @@ static int add_file(const char *path_name, struct stat *st, ino_t inum,
compr_type = compress_data(buf, bytes_read, &dn->data,
&out_len, use_compr);
dn->compr_type = cpu_to_le16(compr_type);
+ //TODO: encrypt
dn_len = UBIFS_DATA_NODE_SZ + out_len;
/* Add data node to file system */
- err = add_node(&key, NULL, dn, dn_len);
+ err = add_node(&key, NULL, 0, dn, dn_len);
if (err) {
close(fd);
return err;
@@ -2121,13 +2124,13 @@ static int write_data(void)
return flush_nodes();
}

-static int namecmp(const char *name1, const char *name2)
+static int namecmp(const struct idx_entry *e1, const struct idx_entry *e2)
{
- size_t len1 = strlen(name1), len2 = strlen(name2);
+ size_t len1 = e1->name_len, len2 = e2->name_len;
size_t clen = (len1 < len2) ? len1 : len2;
int cmp;

- cmp = memcmp(name1, name2, clen);
+ cmp = memcmp(e1->name, e2->name, clen);
if (cmp)
return cmp;
return (len1 < len2) ? -1 : 1;
@@ -2142,7 +2145,7 @@ static int cmp_idx(const void *a, const void *b)
cmp = keys_cmp(&e1->key, &e2->key);
if (cmp)
return cmp;
- return namecmp(e1->name, e2->name);
+ return namecmp(e1, e2);
}

/**
--
2.19.1
Richard Weinberger
2018-10-18 14:36:46 UTC
Permalink
Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 53 ++++++++++++++++++-----------
1 file changed, 34 insertions(+), 19 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index 349f68ab8797..e391cdaae35f 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -1156,36 +1156,45 @@ static int add_node(union ubifs_key *key, char *name, void *node, int len)
return 0;
}

-static int add_xattr(struct stat *st, ino_t inum, const void *data,
- unsigned int data_len, struct qstr *nm)
+static int add_xattr(struct ubifs_ino_node *host_ino, struct stat *st, ino_t inum,
+ char *name, const void *data, unsigned int data_len)
{
struct ubifs_ino_node *ino;
struct ubifs_dent_node *xent;
+ struct qstr nm;
union ubifs_key xkey, nkey;
int len, ret;

- xent = xzalloc(sizeof(*xent) + nm->len + 1);
+ nm.name = name;
+ nm.len = strlen(name);
+
+ host_ino->xattr_cnt++;
+ host_ino->xattr_size += CALC_DENT_SIZE(nm.len);
+ host_ino->xattr_size += CALC_XATTR_BYTES(data_len);
+ host_ino->xattr_names += nm.len;
+
+ xent = xzalloc(sizeof(*xent) + nm.len + 1);
ino = xzalloc(sizeof(*ino) + data_len);

- xent_key_init(c, &xkey, inum, nm);
+ xent_key_init(c, &xkey, inum, &nm);
xent->ch.node_type = UBIFS_XENT_NODE;
key_write(&xkey, &xent->key);

- len = UBIFS_XENT_NODE_SZ + nm->len + 1;
+ len = UBIFS_XENT_NODE_SZ + nm.len + 1;

xent->ch.len = len;
xent->padding1 = 0;
xent->type = UBIFS_ITYPE_DIR;
- xent->nlen = cpu_to_le16(nm->len);
+ xent->nlen = cpu_to_le16(nm.len);

- memcpy(xent->name, nm->name, nm->len + 1);
+ memcpy(xent->name, nm.name, nm.len + 1);

inum = ++c->highest_inum;
creat_sqnum = ++c->max_sqnum;

xent->inum = cpu_to_le64(inum);

- ret = add_node(&xkey, nm->name, xent, len);
+ ret = add_node(&xkey, nm.name, xent, len);
if (ret)
goto out;

@@ -1217,7 +1226,7 @@ static int add_xattr(struct stat *st, ino_t inum, const void *data,
if (data_len)
memcpy(&ino->data, data, data_len);

- ret = add_node(&nkey, nm->name, ino, UBIFS_INO_NODE_SZ + data_len) ;
+ ret = add_node(&nkey, nm.name, ino, UBIFS_INO_NODE_SZ + data_len) ;

out:
free(xent);
@@ -1270,7 +1279,6 @@ static int inode_add_xattr(struct ubifs_ino_node *host_ino,
const char *path_name, struct stat *st, ino_t inum)
{
int ret;
- struct qstr nm;
void *buf = NULL;
ssize_t len;
ssize_t pos = 0;
@@ -1327,15 +1335,7 @@ static int inode_add_xattr(struct ubifs_ino_node *host_ino,
continue;
}

- nm.name = name;
- nm.len = strlen(name);
-
- host_ino->xattr_cnt++;
- host_ino->xattr_size += CALC_DENT_SIZE(nm.len);
- host_ino->xattr_size += CALC_XATTR_BYTES(attrsize);
- host_ino->xattr_names += nm.len;
-
- ret = add_xattr(st, inum, attrbuf, attrsize, &nm);
+ ret = add_xattr(host_ino, st, inum, name, attrbuf, attrsize);
if (ret < 0)
goto out_free;
}
@@ -1415,6 +1415,15 @@ static inline int inode_add_selinux_xattr(struct ubifs_ino_node *host_ino,
}
#endif

+static int set_fscrypt_context(struct ubifs_ino_node *host_ino, ino_t inum,
+ struct stat *host_st,
+ struct fscrypt_context *fctx)
+{
+ return add_xattr(host_ino, host_st, inum,
+ UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT,
+ fctx, sizeof(*fctx));
+}
+
/**
* add_inode - write an inode.
* @st: stat information of source inode
@@ -1484,6 +1493,12 @@ static int add_inode(struct stat *st, ino_t inum, void *data,
return ret;
}

+ if (fctx) {
+ ret = set_fscrypt_context(ino, inum, st, fctx);
+ if (ret < 0)
+ return ret;
+ }
+
return add_node(&key, NULL, ino, len);
}
--
2.19.1
Richard Weinberger
2018-10-18 14:36:45 UTC
Permalink
Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 64 ++++++++++++++++++-----------
1 file changed, 39 insertions(+), 25 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index 09c28ab0b6bd..349f68ab8797 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -174,6 +174,7 @@ int yes;

static char *root;
static int root_len;
+static struct fscrypt_context *root_fctx;
static struct stat root_st;
static char *output;
static int out_fd;
@@ -1423,7 +1424,8 @@ static inline int inode_add_selinux_xattr(struct ubifs_ino_node *host_ino,
* @flags: source inode flags
*/
static int add_inode(struct stat *st, ino_t inum, void *data,
- unsigned int data_len, int flags, const char *xattr_path)
+ unsigned int data_len, int flags, const char *xattr_path,
+ struct fscrypt_context *fctx)
{
struct ubifs_ino_node *ino = node_buf;
union ubifs_key key;
@@ -1441,7 +1443,8 @@ static int add_inode(struct stat *st, ino_t inum, void *data,
use_flags |= UBIFS_APPEND_FL;
if (flags & FS_DIRSYNC_FL && S_ISDIR(st->st_mode))
use_flags |= UBIFS_DIRSYNC_FL;
-
+ if (fctx)
+ use_flags |= UBIFS_CRYPT_FL;
memset(ino, 0, UBIFS_INO_NODE_SZ);

ino_key_init(&key, inum);
@@ -1498,7 +1501,8 @@ static int add_inode(struct stat *st, ino_t inum, void *data,
* the device table.
*/
static int add_dir_inode(const char *path_name, DIR *dir, ino_t inum, loff_t size,
- unsigned int nlink, struct stat *st)
+ unsigned int nlink, struct stat *st,
+ struct fscrypt_context *fctx)
{
int fd, flags = 0;

@@ -1513,7 +1517,7 @@ static int add_dir_inode(const char *path_name, DIR *dir, ino_t inum, loff_t siz
flags = 0;
}

- return add_inode(st, inum, NULL, 0, flags, path_name);
+ return add_inode(st, inum, NULL, 0, flags, path_name, fctx);
}

/**
@@ -1527,7 +1531,7 @@ static int add_dev_inode(const char *path_name, struct stat *st, ino_t inum, int
union ubifs_dev_desc dev;

dev.huge = cpu_to_le64(makedev(major(st->st_rdev), minor(st->st_rdev)));
- return add_inode(st, inum, &dev, 8, flags, path_name);
+ return add_inode(st, inum, &dev, 8, flags, path_name, NULL);
}

/**
@@ -1538,7 +1542,7 @@ static int add_dev_inode(const char *path_name, struct stat *st, ino_t inum, int
* @flags: source inode flags
*/
static int add_symlink_inode(const char *path_name, struct stat *st, ino_t inum,
- int flags)
+ int flags, struct fscrypt_context *fctx)
{
char buf[UBIFS_MAX_INO_DATA + 2];
ssize_t len;
@@ -1550,7 +1554,7 @@ static int add_symlink_inode(const char *path_name, struct stat *st, ino_t inum,
if (len > UBIFS_MAX_INO_DATA)
return err_msg("symlink too long for %s", path_name);

- return add_inode(st, inum, buf, len, flags, path_name);
+ return add_inode(st, inum, buf, len, flags, path_name, fctx);
}

static void set_dent_cookie(struct ubifs_dent_node *dent)
@@ -1569,7 +1573,7 @@ static void set_dent_cookie(struct ubifs_dent_node *dent)
* @type: type of the target inode
*/
static int add_dent_node(ino_t dir_inum, const char *name, ino_t inum,
- unsigned char type)
+ unsigned char type, struct fscrypt_context *fctx)
{
struct ubifs_dent_node *dent = node_buf;
union ubifs_key key;
@@ -1658,7 +1662,7 @@ static int all_zero(void *buf, int len)
* @flags: source inode flags
*/
static int add_file(const char *path_name, struct stat *st, ino_t inum,
- int flags)
+ int flags, struct fscrypt_context *fctx)
{
struct ubifs_data_node *dn = node_buf;
void *buf = block_buf;
@@ -1728,7 +1732,7 @@ static int add_file(const char *path_name, struct stat *st, ino_t inum,
return err_msg("file size changed during writing file '%s'",
path_name);

- return add_inode(st, inum, NULL, 0, flags, path_name);
+ return add_inode(st, inum, NULL, 0, flags, path_name, fctx);
}

/**
@@ -1741,7 +1745,8 @@ static int add_file(const char *path_name, struct stat *st, ino_t inum,
* creating the UBIFS inode
*/
static int add_non_dir(const char *path_name, ino_t *inum, unsigned int nlink,
- unsigned char *type, struct stat *st)
+ unsigned char *type, struct stat *st,
+ struct fscrypt_context *fctx)
{
int fd, flags = 0;

@@ -1806,17 +1811,17 @@ static int add_non_dir(const char *path_name, ino_t *inum, unsigned int nlink,
creat_sqnum = ++c->max_sqnum;

if (S_ISREG(st->st_mode))
- return add_file(path_name, st, *inum, flags);
+ return add_file(path_name, st, *inum, flags, fctx);
if (S_ISCHR(st->st_mode))
return add_dev_inode(path_name, st, *inum, flags);
if (S_ISBLK(st->st_mode))
return add_dev_inode(path_name, st, *inum, flags);
if (S_ISLNK(st->st_mode))
- return add_symlink_inode(path_name, st, *inum, flags);
+ return add_symlink_inode(path_name, st, *inum, flags, fctx);
if (S_ISSOCK(st->st_mode))
- return add_inode(st, *inum, NULL, 0, flags, NULL);
+ return add_inode(st, *inum, NULL, 0, flags, NULL, NULL);
if (S_ISFIFO(st->st_mode))
- return add_inode(st, *inum, NULL, 0, flags, NULL);
+ return add_inode(st, *inum, NULL, 0, flags, NULL, NULL);

return err_msg("file '%s' has unknown inode type", path_name);
}
@@ -1831,7 +1836,7 @@ static int add_non_dir(const char *path_name, ino_t *inum, unsigned int nlink,
* created because it is defined in the device table file.
*/
static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,
- int existing)
+ int existing, struct fscrypt_context *fctx)
{
struct dirent *entry;
DIR *dir = NULL;
@@ -1867,6 +1872,7 @@ static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,
*/
for (; existing;) {
struct stat dent_st;
+ struct fscrypt_context *new_fctx = NULL;

errno = 0;
entry = readdir(dir);
@@ -1922,14 +1928,16 @@ static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,

inum = ++c->highest_inum;

+ new_fctx = inherit_fscrypt_context(fctx);
+
if (S_ISDIR(dent_st.st_mode)) {
- err = add_directory(name, inum, &dent_st, 1);
+ err = add_directory(name, inum, &dent_st, 1, new_fctx);
if (err)
goto out_free;
nlink += 1;
type = UBIFS_ITYPE_DIR;
} else {
- err = add_non_dir(name, &inum, 0, &type, &dent_st);
+ err = add_non_dir(name, &inum, 0, &type, &dent_st, new_fctx);
if (err)
goto out_free;
}
@@ -1938,11 +1946,13 @@ static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,
if (err)
goto out_free;

- err = add_dent_node(dir_inum, entry->d_name, inum, type);
+ err = add_dent_node(dir_inum, entry->d_name, inum, type, fctx);
if (err)
goto out_free;
size += ALIGN(UBIFS_DENT_NODE_SZ + strlen(entry->d_name) + 1,
8);
+
+ free_fscrypt_context(new_fctx);
}

/*
@@ -1952,6 +1962,7 @@ static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,
nh_elt = first_name_htbl_element(ph_elt, &itr);
while (nh_elt) {
struct stat fake_st;
+ struct fscrypt_context *new_fctx = NULL;

/*
* We prohibit creating regular files using the device table,
@@ -1978,14 +1989,16 @@ static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,
name = make_path(dir_name, nh_elt->name);
inum = ++c->highest_inum;

+ new_fctx = inherit_fscrypt_context(fctx);
+
if (S_ISDIR(nh_elt->mode)) {
- err = add_directory(name, inum, &fake_st, 0);
+ err = add_directory(name, inum, &fake_st, 0, new_fctx);
if (err)
goto out_free;
nlink += 1;
type = UBIFS_ITYPE_DIR;
} else {
- err = add_non_dir(name, &inum, 0, &type, &fake_st);
+ err = add_non_dir(name, &inum, 0, &type, &fake_st, new_fctx);
if (err)
goto out_free;
}
@@ -1994,17 +2007,18 @@ static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,
if (err)
goto out_free;

- err = add_dent_node(dir_inum, nh_elt->name, inum, type);
+ err = add_dent_node(dir_inum, nh_elt->name, inum, type, fctx);
if (err)
goto out_free;
size += ALIGN(UBIFS_DENT_NODE_SZ + strlen(nh_elt->name) + 1, 8);

nh_elt = next_name_htbl_element(ph_elt, &itr);
+ free_fscrypt_context(new_fctx);
}

creat_sqnum = dir_creat_sqnum;

- err = add_dir_inode(dir ? dir_name : NULL, dir, dir_inum, size, nlink, st);
+ err = add_dir_inode(dir ? dir_name : NULL, dir, dir_inum, size, nlink, st, fctx);
if (err)
goto out_free;

@@ -2035,7 +2049,7 @@ static int add_multi_linked_files(void)
for (im = hash_table[i]; im; im = im->next) {
dbg_msg(2, "%s", im->path_name);
err = add_non_dir(im->path_name, &im->use_inum,
- im->use_nlink, &type, &im->st);
+ im->use_nlink, &type, &im->st, NULL);
if (err)
return err;
}
@@ -2083,7 +2097,7 @@ static int write_data(void)
if (err)
return err;

- err = add_directory(root, UBIFS_ROOT_INO, &root_st, !!root);
+ err = add_directory(root, UBIFS_ROOT_INO, &root_st, !!root, root_fctx);
if (err)
return err;
err = add_multi_linked_files();
--
2.19.1
Richard Weinberger
2018-10-18 14:36:52 UTC
Permalink
Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 39 ++++++++++++++++++++++++++---
1 file changed, 36 insertions(+), 3 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index 4ffd8fd51e41..b7d68c60d481 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -1817,10 +1817,9 @@ static int add_file(const char *path_name, struct stat *st, ino_t inum,
}
/* Make data node */
memset(dn, 0, UBIFS_DATA_NODE_SZ);
- data_key_init(&key, inum, block_no++);
+ data_key_init(&key, inum, block_no);
dn->ch.node_type = UBIFS_DATA_NODE;
key_write(&key, &dn->key);
- dn->size = cpu_to_le32(bytes_read);
out_len = NODE_BUFFER_SIZE - UBIFS_DATA_NODE_SZ;
if (c->default_compr == UBIFS_COMPR_NONE &&
(flags & FS_COMPR_FL))
@@ -1834,7 +1833,39 @@ static int add_file(const char *path_name, struct stat *st, ino_t inum,
compr_type = compress_data(buf, bytes_read, &dn->data,
&out_len, use_compr);
dn->compr_type = cpu_to_le16(compr_type);
- //TODO: encrypt
+ dn->size = cpu_to_le32(bytes_read);
+
+ 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 = encrypt_block_aes128_cbc(inbuf, pad_len, crypt_key, block_no,
+ outbuf);
+ if (ret != pad_len)
+ return err_msg("encrypt_block_aes128_cbc 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);
+ }
+
dn_len = UBIFS_DATA_NODE_SZ + out_len;
/* Add data node to file system */
err = add_node(&key, NULL, 0, dn, dn_len);
@@ -1842,6 +1873,8 @@ static int add_file(const char *path_name, struct stat *st, ino_t inum,
close(fd);
return err;
}
+
+ block_no++;
} while (ret != 0);

if (close(fd) == -1)
--
2.19.1
Richard Weinberger
2018-10-18 14:36:51 UTC
Permalink
Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 75 ++++++++++++++++++++++++++---
1 file changed, 68 insertions(+), 7 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index c315e36dd3d3..4ffd8fd51e41 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -155,6 +155,16 @@ struct fscrypt_context {
__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
@@ -578,15 +588,22 @@ static struct fscrypt_context *init_fscrypt_context(void)
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;
- //TODO accept padding via a parameter
new_fctx->flags = FS_POLICY_FLAGS_PAD_4;
- //TODO accept descriptor via a parameter
- RAND_bytes((void *)&new_fctx->master_key_descriptor, FS_KEY_DESCRIPTOR_SIZE);
RAND_bytes((void *)&new_fctx->nonce, FS_KEY_DERIVATION_NONCE_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
@@ -1478,11 +1495,54 @@ static int add_inode(struct stat *st, ino_t inum, void *data,
ino->gid = cpu_to_le32(st->st_gid);
ino->mode = cpu_to_le32(st->st_mode);
ino->flags = cpu_to_le32(use_flags);
- ino->data_len = cpu_to_le32(data_len);
ino->compr_type = cpu_to_le16(c->default_compr);
- if (data_len)
- memcpy(&ino->data, data, data_len);
+ if (data_len) {
+ if (!S_ISLNK(st->st_mode))
+ return err_msg("Expected symlink");

+ if (!fctx) {
+ memcpy(&ino->data, data, data_len);
+ } else {
+ //TODO turn this into a common helper
+ struct fscrypt_symlink_data *sd;
+ void *inbuf, *outbuf, *crypt_key;
+ unsigned int max_namelen = UBIFS_MAX_INO_DATA;
+ unsigned int padding = 4 << (fctx->flags & FS_POLICY_FLAGS_PAD_MASK);
+ unsigned int cryptlen;
+ unsigned int link_disk_len = fscrypt_fname_encrypted_size(fctx, data_len) + sizeof(struct fscrypt_symlink_data);
+
+ cryptlen = max_t(unsigned int, data_len, FS_CRYPTO_BLOCK_SIZE);
+ cryptlen = round_up(cryptlen, padding);
+ cryptlen = min(cryptlen, max_namelen);
+
+ sd = xzalloc(link_disk_len);
+ 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");
+ if (encrypt_aes128_cbc_cts(inbuf, cryptlen, crypt_key, outbuf) < 0)
+ return err_msg("could not encrypt filename");
+
+ memcpy(sd->encrypted_path, outbuf, cryptlen);
+ sd->len = cpu_to_le16(cryptlen);
+ memcpy(&ino->data, sd, link_disk_len);
+ ((char *)&ino->data)[link_disk_len - 1] = '\0';
+
+ data_len = link_disk_len;
+
+ free(crypt_key);
+ free(inbuf);
+ free(outbuf);
+ free(sd);
+ }
+ }
+ ino->data_len = cpu_to_le32(data_len);
len = UBIFS_INO_NODE_SZ + data_len;

if (xattr_path) {
@@ -1635,7 +1695,8 @@ static int add_dent_node(ino_t dir_inum, const char *name, ino_t inum,
cryptlen = min(cryptlen, max_namelen);

inbuf = xmalloc(cryptlen);
- outbuf = xmalloc(cryptlen + 32);
+ /* CTS mode needs a block size aligned buffer */
+ outbuf = xmalloc(round_up(cryptlen, FS_CRYPTO_BLOCK_SIZE));

memset(inbuf, 0, cryptlen);
memcpy(inbuf, dname.name, dname.len);
--
2.19.1
Richard Weinberger
2018-10-18 14:36:53 UTC
Permalink
From: David Oberhollenzer <***@sigma-star.at>

Signed-off-by: David Oberhollenzer <***@sigma-star.at>
Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 81 ++++++++++++++++-------------
1 file changed, 44 insertions(+), 37 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index b7d68c60d481..b402945924ac 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -1443,6 +1443,46 @@ static int set_fscrypt_context(struct ubifs_ino_node *host_ino, ino_t inum,
fctx, sizeof(*fctx));
}

+static int encrypt_symlink(void *dst, void *data, unsigned int data_len,
+ struct fscrypt_context *fctx)
+{
+ struct fscrypt_symlink_data *sd;
+ void *inbuf, *outbuf, *crypt_key;
+ unsigned int max_namelen = UBIFS_MAX_INO_DATA;
+ unsigned int padding = 4 << (fctx->flags & FS_POLICY_FLAGS_PAD_MASK);
+ unsigned int cryptlen;
+ unsigned int link_disk_len = fscrypt_fname_encrypted_size(fctx, data_len) + sizeof(struct fscrypt_symlink_data);
+
+ cryptlen = max_t(unsigned int, data_len, FS_CRYPTO_BLOCK_SIZE);
+ cryptlen = round_up(cryptlen, padding);
+ cryptlen = min(cryptlen, max_namelen);
+
+ sd = xzalloc(link_disk_len);
+ 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");
+ if (encrypt_aes128_cbc_cts(inbuf, cryptlen, crypt_key, outbuf) < 0)
+ return err_msg("could not encrypt filename");
+
+ memcpy(sd->encrypted_path, outbuf, cryptlen);
+ sd->len = cpu_to_le16(cryptlen);
+ memcpy(dst, sd, link_disk_len);
+ ((char *)dst)[link_disk_len - 1] = '\0';
+
+ free(crypt_key);
+ free(inbuf);
+ free(outbuf);
+ free(sd);
+ return link_disk_len;
+}
+
/**
* add_inode - write an inode.
* @st: stat information of source inode
@@ -1503,43 +1543,10 @@ static int add_inode(struct stat *st, ino_t inum, void *data,
if (!fctx) {
memcpy(&ino->data, data, data_len);
} else {
- //TODO turn this into a common helper
- struct fscrypt_symlink_data *sd;
- void *inbuf, *outbuf, *crypt_key;
- unsigned int max_namelen = UBIFS_MAX_INO_DATA;
- unsigned int padding = 4 << (fctx->flags & FS_POLICY_FLAGS_PAD_MASK);
- unsigned int cryptlen;
- unsigned int link_disk_len = fscrypt_fname_encrypted_size(fctx, data_len) + sizeof(struct fscrypt_symlink_data);
-
- cryptlen = max_t(unsigned int, data_len, FS_CRYPTO_BLOCK_SIZE);
- cryptlen = round_up(cryptlen, padding);
- cryptlen = min(cryptlen, max_namelen);
-
- sd = xzalloc(link_disk_len);
- 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");
- if (encrypt_aes128_cbc_cts(inbuf, cryptlen, crypt_key, outbuf) < 0)
- return err_msg("could not encrypt filename");
-
- memcpy(sd->encrypted_path, outbuf, cryptlen);
- sd->len = cpu_to_le16(cryptlen);
- memcpy(&ino->data, sd, link_disk_len);
- ((char *)&ino->data)[link_disk_len - 1] = '\0';
-
- data_len = link_disk_len;
-
- free(crypt_key);
- free(inbuf);
- free(outbuf);
- free(sd);
+ ret = encrypt_symlink(&ino->data, data, data_len, fctx);
+ if (ret < 0)
+ return ret;
+ data_len = ret;
}
}
ino->data_len = cpu_to_le32(data_len);
--
2.19.1
Richard Weinberger
2018-10-18 14:37:14 UTC
Permalink
fscryptctl reads up to FS_MAX_KEY_SIZE bytes from the source key
to compute the descriptor.

Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/fscrypt.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ubifs-utils/mkfs.ubifs/fscrypt.c b/ubifs-utils/mkfs.ubifs/fscrypt.c
index 29dad1b039e7..3d4bff618050 100644
--- a/ubifs-utils/mkfs.ubifs/fscrypt.c
+++ b/ubifs-utils/mkfs.ubifs/fscrypt.c
@@ -202,7 +202,7 @@ static int load_master_key(const char *key_file, struct cipher *fsc)
return -1;
}

- keysize = read(kf, fscrypt_masterkey, fsc->key_length);
+ keysize = read(kf, fscrypt_masterkey, FS_MAX_KEY_SIZE);
if (keysize < 0) {
sys_errmsg("read '%s'", key_file);
goto fail;
--
2.19.1
Richard Weinberger
2018-10-18 14:37:09 UTC
Permalink
No longer hard code AES-128-CBC, we support AES-256-XTS too.

Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/crypto.c | 7 +++++--
ubifs-utils/mkfs.ubifs/crypto.h | 3 +++
ubifs-utils/mkfs.ubifs/fscrypt.c | 4 ++--
ubifs-utils/mkfs.ubifs/fscrypt.h | 9 ++++++++-
4 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/crypto.c b/ubifs-utils/mkfs.ubifs/crypto.c
index 8d113f198bb2..ec414531e94a 100644
--- a/ubifs-utils/mkfs.ubifs/crypto.c
+++ b/ubifs-utils/mkfs.ubifs/crypto.c
@@ -23,9 +23,8 @@
#include <string.h>
#include <assert.h>

-#include "crypto.h"
+#include "fscrypt.h"
#include "common.h"
-#include "mtd_swab.h"

static int do_sha256(const unsigned char *in, size_t len, unsigned char *out)
{
@@ -284,11 +283,15 @@ static struct cipher ciphers[] = {
.key_length = 16,
.encrypt_block = encrypt_block_aes128_cbc,
.encrypt_fname = encrypt_aes128_cbc_cts,
+ .fscrypt_block_mode = FS_ENCRYPTION_MODE_AES_128_CBC,
+ .fscrypt_fname_mode = FS_ENCRYPTION_MODE_AES_128_CTS,
}, {
.name = "AES-256-XTS",
.key_length = 64,
.encrypt_block = encrypt_block_aes256_xts,
.encrypt_fname = encrypt_aes256_cbc_cts,
+ .fscrypt_block_mode = FS_ENCRYPTION_MODE_AES_256_XTS,
+ .fscrypt_fname_mode = FS_ENCRYPTION_MODE_AES_256_CTS,
}
};

diff --git a/ubifs-utils/mkfs.ubifs/crypto.h b/ubifs-utils/mkfs.ubifs/crypto.h
index 7fb2d3b8d005..c2631dd0fd89 100644
--- a/ubifs-utils/mkfs.ubifs/crypto.h
+++ b/ubifs-utils/mkfs.ubifs/crypto.h
@@ -36,6 +36,9 @@ struct cipher {

ssize_t (*encrypt_fname)(const void *plaintext, size_t size,
const void *key, void *ciphertext);
+
+ unsigned int fscrypt_block_mode;
+ unsigned int fscrypt_fname_mode;
};


diff --git a/ubifs-utils/mkfs.ubifs/fscrypt.c b/ubifs-utils/mkfs.ubifs/fscrypt.c
index 02132e205a35..2fc0ae8b3509 100644
--- a/ubifs-utils/mkfs.ubifs/fscrypt.c
+++ b/ubifs-utils/mkfs.ubifs/fscrypt.c
@@ -253,8 +253,8 @@ struct fscrypt_context *init_fscrypt_context(const char *cipher_name,
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->contents_encryption_mode = fscrypt_cipher->fscrypt_block_mode;
+ new_fctx->filenames_encryption_mode = fscrypt_cipher->fscrypt_fname_mode;
new_fctx->flags = flags;

memcpy(&new_fctx->nonce, nonce, FS_KEY_DERIVATION_NONCE_SIZE);
diff --git a/ubifs-utils/mkfs.ubifs/fscrypt.h b/ubifs-utils/mkfs.ubifs/fscrypt.h
index b6fb6d136e58..e39d7e105fda 100644
--- a/ubifs-utils/mkfs.ubifs/fscrypt.h
+++ b/ubifs-utils/mkfs.ubifs/fscrypt.h
@@ -26,13 +26,20 @@
#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_256_XTS
+#define FS_ENCRYPTION_MODE_AES_256_XTS 1
+#endif
+
+#ifndef FS_ENCRYPTION_MODE_AES_256_CTS
+#define FS_ENCRYPTION_MODE_AES_256_CTS 4
+#endif
+
#ifndef FS_ENCRYPTION_MODE_AES_128_CBC
#define FS_ENCRYPTION_MODE_AES_128_CBC 5
#endif
--
2.19.1
Richard Weinberger
2018-10-18 14:37:13 UTC
Permalink
normsg() sucks.

Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/fscrypt.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/fscrypt.c b/ubifs-utils/mkfs.ubifs/fscrypt.c
index ce6e2fc29ce0..29dad1b039e7 100644
--- a/ubifs-utils/mkfs.ubifs/fscrypt.c
+++ b/ubifs-utils/mkfs.ubifs/fscrypt.c
@@ -69,11 +69,11 @@ void print_fscrypt_master_key_descriptor(struct fscrypt_context *fctx)
{
int i;

- normsg_cont("fscrypt master key descriptor: ");
+ normsg_cont("fscrypt master key descriptor: 0x");
for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; i++) {
- normsg_cont("%02x", fctx->master_key_descriptor[i]);
+ printf("%02x", fctx->master_key_descriptor[i]);
}
- normsg("");
+ printf("\n");
}

unsigned int fscrypt_fname_encrypted_size(struct fscrypt_context *fctx,
--
2.19.1
Richard Weinberger
2018-10-18 14:37:11 UTC
Permalink
In XTS mode we don't need ESSIV, just use the block number
as tweak.
Also apply EVP_EncryptFinal().

Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/crypto.c | 35 +++++++++++++++++++++-----------
ubifs-utils/mkfs.ubifs/fscrypt.h | 4 ++++
2 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/crypto.c b/ubifs-utils/mkfs.ubifs/crypto.c
index 7d35ae7473ba..d0f24e1a5f6f 100644
--- a/ubifs-utils/mkfs.ubifs/crypto.c
+++ b/ubifs-utils/mkfs.ubifs/crypto.c
@@ -91,6 +91,13 @@ static ssize_t do_encrypt(const EVP_CIPHER *cipher,

ciphertext_len = len;

+ if (cipher == EVP_aes_256_xts()) {
+ if (EVP_EncryptFinal(ctx, ciphertext + ciphertext_len, &len) != 1)
+ goto fail_ctx;
+
+ ciphertext_len += len;
+ }
+
EVP_CIPHER_CTX_free(ctx);
return ciphertext_len;
fail_ctx:
@@ -128,28 +135,32 @@ static size_t gen_essiv_salt(const void *iv, size_t iv_len, const void *key, siz
return ret;
}

-
static ssize_t encrypt_block(const void *plaintext, size_t size,
const void *key, uint64_t block_index,
void *ciphertext, const EVP_CIPHER *cipher)
{
- size_t key_len, ret, ivsize;
- void *essiv_salt, *iv;
+ size_t key_len, ivsize;
+ void *tweak;
+ struct {
+ uint64_t index;
+ uint8_t padding[FS_IV_SIZE - sizeof(uint64_t)];
+ } iv;

ivsize = EVP_CIPHER_iv_length(cipher);
key_len = EVP_CIPHER_key_length(cipher);

- iv = alloca(ivsize);
- essiv_salt = alloca(ivsize);
+ iv.index = cpu_to_le64(block_index);
+ memset(iv.padding, 0, sizeof(iv.padding));

- memset(iv, 0, ivsize);
- *((uint64_t *)iv) = cpu_to_le64(block_index);
-
- gen_essiv_salt(iv, ivsize, key, key_len, essiv_salt);
+ if (cipher == EVP_aes_256_cbc()) {
+ tweak = alloca(ivsize);
+ gen_essiv_salt(&iv, FS_IV_SIZE, key, key_len, tweak);
+ } else {
+ tweak = &iv;
+ }

- ret = do_encrypt(cipher, plaintext, size, key, key_len,
- essiv_salt, ivsize, ciphertext);
- return ret;
+ return do_encrypt(cipher, plaintext, size, key, key_len, tweak,
+ ivsize, ciphertext);
}

static ssize_t encrypt_block_aes128_cbc(const void *plaintext, size_t size,
diff --git a/ubifs-utils/mkfs.ubifs/fscrypt.h b/ubifs-utils/mkfs.ubifs/fscrypt.h
index e39d7e105fda..e3cfee50290a 100644
--- a/ubifs-utils/mkfs.ubifs/fscrypt.h
+++ b/ubifs-utils/mkfs.ubifs/fscrypt.h
@@ -93,6 +93,10 @@ struct fscrypt_symlink_data {
#define FS_MAX_KEY_SIZE 64
#endif

+#ifndef FS_IV_SIZE
+#define FS_IV_SIZE 16
+#endif
+
unsigned char *calc_fscrypt_subkey(struct fscrypt_context *fctx);

struct fscrypt_context *inherit_fscrypt_context(struct fscrypt_context *fctx);
--
2.19.1
Richard Weinberger
2018-10-18 14:37:04 UTC
Permalink
From: David Oberhollenzer <***@sigma-star.at>

Signed-off-by: David Oberhollenzer <***@sigma-star.at>
Signed-off-by: Richard Weinberger <***@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 --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 <***@sigma-star.at>
+ * 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 <***@sigma-star.at>
+ * 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;
--
2.19.1
Richard Weinberger
2018-10-18 14:37:05 UTC
Permalink
From: David Oberhollenzer <***@sigma-star.at>

Signed-off-by: David Oberhollenzer <***@sigma-star.at>
Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 35 +++++++++++++++++++----------
1 file changed, 23 insertions(+), 12 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index 1710e25b88ee..9bd15a2f047a 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -1030,8 +1030,8 @@ static void set_lprops(int lnum, int offs, int flags)
* @offs: node offset
* @len: node length
*/
-static int add_to_index(union ubifs_key *key, char *name, int name_len, int lnum, int offs,
- int len)
+static int add_to_index(union ubifs_key *key, char *name, int name_len,
+ int lnum, int offs, int len)
{
struct idx_entry *e;

@@ -1102,11 +1102,12 @@ static int reserve_space(int len, int *lnum, int *offs)
*/
static int add_node(union ubifs_key *key, char *name, int name_len, void *node, int len)
{
- int err, lnum, offs;
+ int err, lnum, offs, type = key_type(key);

- if (key_type(key) == UBIFS_DENT_KEY || key_type(key) == UBIFS_XENT_KEY) {
+ if (type == UBIFS_DENT_KEY || type == UBIFS_XENT_KEY) {
if (!name)
- return err_msg("Directory entry or xattr without name!");
+ return err_msg("Directory entry or xattr "
+ "without name!");
} else {
if (name)
return err_msg("Name given for non dir/xattr node!");
@@ -1126,8 +1127,9 @@ static int add_node(union ubifs_key *key, char *name, int name_len, void *node,
return 0;
}

-static int add_xattr(struct ubifs_ino_node *host_ino, struct stat *st, ino_t inum,
- char *name, const void *data, unsigned int data_len)
+static int add_xattr(struct ubifs_ino_node *host_ino, struct stat *st,
+ ino_t inum, char *name, const void *data,
+ unsigned int data_len)
{
struct ubifs_ino_node *ino;
struct ubifs_dent_node *xent;
@@ -1399,10 +1401,13 @@ static int encrypt_symlink(void *dst, void *data, unsigned int data_len,
{
struct fscrypt_symlink_data *sd;
void *outbuf;
- unsigned int link_disk_len = fscrypt_fname_encrypted_size(fctx, data_len) + sizeof(struct fscrypt_symlink_data);
+ unsigned int link_disk_len;
unsigned int cryptlen;
int ret;

+ link_disk_len = sizeof(struct fscrypt_symlink_data);
+ link_disk_len += fscrypt_fname_encrypted_size(fctx, data_len);
+
ret = encrypt_path(&outbuf, data, data_len, UBIFS_MAX_INO_DATA, fctx);
if (ret < 0)
return ret;
@@ -1622,9 +1627,12 @@ static int add_dent_node(ino_t dir_inum, const char *name, ino_t inum,
if (!kname)
return err_msg("cannot allocate memory");
} else {
- unsigned int max_namelen = type == UBIFS_ITYPE_LNK ? UBIFS_MAX_INO_DATA : UBIFS_MAX_NLEN;
+ unsigned int max_namelen = UBIFS_MAX_NLEN;
int ret;

+ if (type == UBIFS_ITYPE_LNK)
+ max_namelen = UBIFS_MAX_INO_DATA;
+
ret = encrypt_path((void **)&kname, dname.name, dname.len,
max_namelen, fctx);
if (ret < 0)
@@ -1984,7 +1992,8 @@ static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,
nlink += 1;
type = UBIFS_ITYPE_DIR;
} else {
- err = add_non_dir(name, &inum, 0, &type, &dent_st, new_fctx);
+ err = add_non_dir(name, &inum, 0, &type,
+ &dent_st, new_fctx);
if (err)
goto out_free;
}
@@ -2045,7 +2054,8 @@ static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,
nlink += 1;
type = UBIFS_ITYPE_DIR;
} else {
- err = add_non_dir(name, &inum, 0, &type, &fake_st, new_fctx);
+ err = add_non_dir(name, &inum, 0, &type,
+ &fake_st, new_fctx);
if (err)
goto out_free;
}
@@ -2065,7 +2075,8 @@ static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,

creat_sqnum = dir_creat_sqnum;

- err = add_dir_inode(dir ? dir_name : NULL, dir, dir_inum, size, nlink, st, fctx);
+ err = add_dir_inode(dir ? dir_name : NULL, dir, dir_inum, size,
+ nlink, st, fctx);
if (err)
goto out_free;
--
2.19.1
Richard Weinberger
2018-10-18 14:36:55 UTC
Permalink
...and make valgrind memcheck happy

Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index 8aba668f8e28..66ca061cc225 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -1253,7 +1253,7 @@ static int add_xattr(struct ubifs_ino_node *host_ino, struct stat *st, ino_t inu
if (data_len)
memcpy(&ino->data, data, data_len);

- ret = add_node(&nkey, nm.name, nm.len, ino, UBIFS_INO_NODE_SZ + data_len) ;
+ ret = add_node(&nkey, NULL, 0, ino, UBIFS_INO_NODE_SZ + data_len);

out:
free(xent);
@@ -1447,7 +1447,7 @@ static int set_fscrypt_context(struct ubifs_ino_node *host_ino, ino_t inum,
struct fscrypt_context *fctx)
{
return add_xattr(host_ino, host_st, inum,
- UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT,
+ xstrdup(UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT),
fctx, sizeof(*fctx));
}

@@ -2470,8 +2470,10 @@ static int write_index(void)
}

/* Free stuff */
- for (i = 0; i < idx_cnt; i++)
+ for (i = 0; i < idx_cnt; i++) {
+ free(idx_ptr[i]->name);
free(idx_ptr[i]);
+ }
free(idx_ptr);
free(idx);
--
2.19.1
Richard Weinberger
2018-10-18 14:37:06 UTC
Permalink
From: David Oberhollenzer <***@sigma-star.at>

Signed-off-by: David Oberhollenzer <***@sigma-star.at>
Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/crypto.c | 2 ++
ubifs-utils/mkfs.ubifs/crypto.h | 1 +
ubifs-utils/mkfs.ubifs/fscrypt.c | 9 +++++++--
3 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/crypto.c b/ubifs-utils/mkfs.ubifs/crypto.c
index f7b51357c04a..bd3273767a5b 100644
--- a/ubifs-utils/mkfs.ubifs/crypto.c
+++ b/ubifs-utils/mkfs.ubifs/crypto.c
@@ -281,10 +281,12 @@ ssize_t derive_key_aes(const void *deriving_key, const void *source_key,
static struct cipher ciphers[] = {
{
.name = "AES-128-CBC",
+ .key_length = 16,
.encrypt_block = encrypt_block_aes128_cbc,
.encrypt_fname = encrypt_aes128_cbc_cts,
}, {
.name = "AES-256-XTS",
+ .key_length = 64,
.encrypt_block = encrypt_block_aes256_xts,
.encrypt_fname = encrypt_aes256_cbc_cts,
}
diff --git a/ubifs-utils/mkfs.ubifs/crypto.h b/ubifs-utils/mkfs.ubifs/crypto.h
index b6a1e004f46d..7fb2d3b8d005 100644
--- a/ubifs-utils/mkfs.ubifs/crypto.h
+++ b/ubifs-utils/mkfs.ubifs/crypto.h
@@ -28,6 +28,7 @@

struct cipher {
const char *name;
+ unsigned int key_length;

ssize_t (*encrypt_block)(const void *plaintext, size_t size,
const void *key, uint64_t block_index,
diff --git a/ubifs-utils/mkfs.ubifs/fscrypt.c b/ubifs-utils/mkfs.ubifs/fscrypt.c
index 68001e1d88f4..6d1fa4ba9d3f 100644
--- a/ubifs-utils/mkfs.ubifs/fscrypt.c
+++ b/ubifs-utils/mkfs.ubifs/fscrypt.c
@@ -188,7 +188,7 @@ static int parse_key_descriptor(const char *desc, __u8 *dst)
return 0;
}

-static int load_master_key(const char *key_file)
+static int load_master_key(const char *key_file, struct cipher *fsc)
{
int kf;
ssize_t keysize;
@@ -208,6 +208,11 @@ static int load_master_key(const char *key_file)
err_msg("loading key from '%s': file is empty", key_file);
goto fail;
}
+ if (keysize < fsc->key_length) {
+ err_msg("key '%s' is too short (at least %u bytes required)",
+ key_file, fsc->key_length);
+ goto fail;
+ }

close(kf);
return 0;
@@ -237,7 +242,7 @@ struct fscrypt_context *init_fscrypt_context(const char *cipher_name,
if (parse_key_descriptor(key_descriptor, master_key_descriptor))
return NULL;

- if (load_master_key(key_file))
+ if (load_master_key(key_file, fscrypt_cipher))
return NULL;

RAND_bytes((void *)nonce, FS_KEY_DERIVATION_NONCE_SIZE);
--
2.19.1
Richard Weinberger
2018-10-18 14:36:58 UTC
Permalink
From: David Oberhollenzer <***@sigma-star.at>

Signed-off-by: David Oberhollenzer <***@sigma-star.at>
Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index ae1d26726deb..8be84ca1e99c 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -581,16 +581,20 @@ static void print_fscrypt_master_key_descriptor(struct fscrypt_context *fctx)
normsg("");
}

-static struct fscrypt_context *init_fscrypt_context(void)
+static struct fscrypt_context *init_fscrypt_context(unsigned int flags,
+ void *master_key_descriptor,
+ void *nonce)
{
struct fscrypt_context *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 = FS_POLICY_FLAGS_PAD_4;
- RAND_bytes((void *)&new_fctx->nonce, FS_KEY_DERIVATION_NONCE_SIZE);
+ 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;
}

@@ -2779,6 +2783,8 @@ static int close_target(void)
*/
static int init(void)
{
+ __u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
+ __u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
int err, i, main_lebs, big_lpt = 0, sz;

c->highest_inum = UBIFS_FIRST_INO;
@@ -2821,7 +2827,11 @@ static int init(void)
hash_table = xzalloc(sz);

//TODO make this a parameter
- root_fctx = init_fscrypt_context();
+ RAND_bytes((void *)master_key_descriptor, FS_KEY_DESCRIPTOR_SIZE);
+ RAND_bytes((void *)nonce, FS_KEY_DERIVATION_NONCE_SIZE);
+
+ root_fctx = init_fscrypt_context(FS_POLICY_FLAGS_PAD_4,
+ master_key_descriptor, nonce);
print_fscrypt_master_key_descriptor(root_fctx);
c->double_hash = 1;
c->encrypted = 1;
--
2.19.1
Richard Weinberger
2018-10-18 14:36:56 UTC
Permalink
From: David Oberhollenzer <***@sigma-star.at>

Signed-off-by: David Oberhollenzer <***@sigma-star.at>
Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 36 ++++++++++++++++++++---------
1 file changed, 25 insertions(+), 11 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index 66ca061cc225..49a895ae3682 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -1451,24 +1451,20 @@ static int set_fscrypt_context(struct ubifs_ino_node *host_ino, ino_t inum,
fctx, sizeof(*fctx));
}

-static int encrypt_symlink(void *dst, void *data, unsigned int data_len,
- struct fscrypt_context *fctx)
+static int encrypt_path(void **outbuf, void *data, unsigned int data_len,
+ unsigned int max_namelen, struct fscrypt_context *fctx)
{
- struct fscrypt_symlink_data *sd;
- void *inbuf, *outbuf, *crypt_key;
- unsigned int max_namelen = UBIFS_MAX_INO_DATA;
+ void *inbuf, *crypt_key;
unsigned int padding = 4 << (fctx->flags & FS_POLICY_FLAGS_PAD_MASK);
unsigned int cryptlen;
- unsigned int link_disk_len = fscrypt_fname_encrypted_size(fctx, data_len) + sizeof(struct fscrypt_symlink_data);

cryptlen = max_t(unsigned int, data_len, FS_CRYPTO_BLOCK_SIZE);
cryptlen = round_up(cryptlen, padding);
cryptlen = min(cryptlen, max_namelen);

- sd = xzalloc(link_disk_len);
inbuf = xmalloc(cryptlen);
/* CTS mode needs a block size aligned buffer */
- outbuf = xmalloc(round_up(cryptlen, FS_CRYPTO_BLOCK_SIZE));
+ *outbuf = xmalloc(round_up(cryptlen, FS_CRYPTO_BLOCK_SIZE));

memset(inbuf, 0, cryptlen);
memcpy(inbuf, data, data_len);
@@ -1476,16 +1472,34 @@ static int encrypt_symlink(void *dst, void *data, unsigned int data_len,
crypt_key = calc_fscrypt_subkey(fctx);
if (!crypt_key)
return err_msg("could not compute subkey");
- if (encrypt_aes128_cbc_cts(inbuf, cryptlen, crypt_key, outbuf) < 0)
+ if (encrypt_aes128_cbc_cts(inbuf, cryptlen, crypt_key, *outbuf) < 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)
+{
+ struct fscrypt_symlink_data *sd;
+ void *outbuf;
+ unsigned int link_disk_len = fscrypt_fname_encrypted_size(fctx, data_len) + sizeof(struct fscrypt_symlink_data);
+ unsigned int cryptlen;
+ int ret;
+
+ ret = encrypt_path(&outbuf, data, data_len, UBIFS_MAX_INO_DATA, fctx);
+ if (ret < 0)
+ return ret;
+ cryptlen = ret;
+
+ sd = xzalloc(link_disk_len);
memcpy(sd->encrypted_path, outbuf, cryptlen);
sd->len = cpu_to_le16(cryptlen);
memcpy(dst, sd, link_disk_len);
((char *)dst)[link_disk_len - 1] = '\0';

- free(crypt_key);
- free(inbuf);
free(outbuf);
free(sd);
return link_disk_len;
--
2.19.1
Richard Weinberger
2018-10-18 14:36:59 UTC
Permalink
From: David Oberhollenzer <***@sigma-star.at>

Signed-off-by: David Oberhollenzer <***@sigma-star.at>
Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index 8be84ca1e99c..5be390e93da9 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -217,6 +217,7 @@ static struct inum_mapping **hash_table;
/* Inode creation sequence number */
static unsigned long long creat_sqnum;

+//TODO: add options for double hash and encryption
static const char *optstring = "d:r:m:o:D:yh?vVe:c:g:f:Fp:k:x:X:j:R:l:j:UQqa";

static const struct option longopts[] = {
@@ -654,6 +655,8 @@ static int get_options(int argc, char**argv)
c->max_leb_cnt = -1;
c->max_bud_bytes = -1;
c->log_lebs = -1;
+ c->double_hash = 0;
+ c->encrypted = 0;

while (1) {
opt = getopt_long(argc, argv, optstring, longopts, &i);
@@ -2826,15 +2829,16 @@ static int init(void)
sz = sizeof(struct inum_mapping *) * HASH_TABLE_SIZE;
hash_table = xzalloc(sz);

- //TODO make this a parameter
- RAND_bytes((void *)master_key_descriptor, FS_KEY_DESCRIPTOR_SIZE);
- RAND_bytes((void *)nonce, FS_KEY_DERIVATION_NONCE_SIZE);
+ if (c->encrypted) {
+ RAND_bytes((void *)master_key_descriptor,
+ FS_KEY_DESCRIPTOR_SIZE);
+ RAND_bytes((void *)nonce, FS_KEY_DERIVATION_NONCE_SIZE);

- root_fctx = init_fscrypt_context(FS_POLICY_FLAGS_PAD_4,
- master_key_descriptor, nonce);
- print_fscrypt_master_key_descriptor(root_fctx);
- c->double_hash = 1;
- c->encrypted = 1;
+ root_fctx = init_fscrypt_context(FS_POLICY_FLAGS_PAD_4,
+ master_key_descriptor, nonce);
+ print_fscrypt_master_key_descriptor(root_fctx);
+ c->double_hash = 1;
+ }

err = init_compression();
if (err)
--
2.19.1
Richard Weinberger
2018-10-18 14:37:07 UTC
Permalink
From: David Oberhollenzer <***@sigma-star.at>

Signed-off-by: David Oberhollenzer <***@sigma-star.at>
Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/fscrypt.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/ubifs-utils/mkfs.ubifs/fscrypt.c b/ubifs-utils/mkfs.ubifs/fscrypt.c
index 6d1fa4ba9d3f..02132e205a35 100644
--- a/ubifs-utils/mkfs.ubifs/fscrypt.c
+++ b/ubifs-utils/mkfs.ubifs/fscrypt.c
@@ -165,6 +165,9 @@ static int parse_key_descriptor(const char *desc, __u8 *dst)
{
int i, hi, lo;

+ if (desc[0] == '0' && (desc[1] == 'x' || desc[1] == 'X'))
+ desc += 2;
+
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);
--
2.19.1
Richard Weinberger
2018-10-18 14:37:00 UTC
Permalink
From: David Oberhollenzer <***@sigma-star.at>

Signed-off-by: David Oberhollenzer <***@sigma-star.at>
Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 131 ++++++++++++++++++++++++----
1 file changed, 113 insertions(+), 18 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index 5be390e93da9..70c306bdf94e 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -217,8 +217,7 @@ static struct inum_mapping **hash_table;
/* Inode creation sequence number */
static unsigned long long creat_sqnum;

-//TODO: add options for double hash and encryption
-static const char *optstring = "d:r:m:o:D:yh?vVe:c:g:f:Fp:k:x:X:j:R:l:j:UQqa";
+static const char *optstring = "d:r:m:o:D:yh?vVe:c:g:f:Fp:k:x:X:j:R:l:j:UQqaK:b:";

static const struct option longopts[] = {
{"root", 1, NULL, 'r'},
@@ -244,6 +243,8 @@ static const struct option longopts[] = {
{"squash-uids" , 0, NULL, 'U'},
{"set-inode-attr", 0, NULL, 'a'},
{"selinux", 1, NULL, 's'},
+ {"key", 1, NULL, 'K'},
+ {"key-descriptor", 1, NULL, 'b'},
{NULL, 0, NULL, 0}
};

@@ -288,6 +289,8 @@ static const char *helptext =
" added to the image. The attribute will contain the inode\n"
" number the file has in the generated image.\n"
"-s, --selinux=FILE Selinux context file\n"
+"-K, --key=FILE load an encryption key from a specified file.\n"
+"-b, --key-descriptor=HEX specify the key descriptor as a hex string.\n"
"-h, --help display this help text\n\n"
"Note, SIZE is specified in bytes, but it may also be specified in Kilobytes,\n"
"Megabytes, and Gigabytes if a KiB, MiB, or GiB suffix is used.\n\n"
@@ -582,11 +585,87 @@ static void print_fscrypt_master_key_descriptor(struct fscrypt_context *fctx)
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,
- void *master_key_descriptor,
- void *nonce)
+ const char *key_file,
+ const char *key_descriptor)
{
- struct fscrypt_context *new_fctx = xmalloc(sizeof(*new_fctx));
+ __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;
@@ -635,6 +714,7 @@ static int open_ubi(const char *node)
static int get_options(int argc, char**argv)
{
int opt, i;
+ const char *key_file = NULL, *key_desc = NULL;
const char *tbl_file = NULL;
struct stat st;
char *endp;
@@ -812,6 +892,18 @@ static int get_options(int argc, char**argv)
return sys_err_msg("bad file context %s\n",
context);
break;
+ case 'K':
+ if (key_file) {
+ return err_msg("key file specified more than once");
+ }
+ key_file = optarg;
+ break;
+ case 'b':
+ if (key_desc) {
+ return err_msg("key descriptor specified more than once");
+ }
+ key_desc = optarg;
+ break;
}
}

@@ -830,6 +922,22 @@ static int get_options(int argc, char**argv)
c->max_leb_cnt = c->vi.rsvd_lebs;
}

+ if (key_file || key_desc) {
+ if (!key_file)
+ return err_msg("no key file specified");
+ if (!key_desc)
+ return err_msg("no key descriptor specified");
+
+ c->double_hash = 1;
+ c->encrypted = 1;
+
+ root_fctx = init_fscrypt_context(FS_POLICY_FLAGS_PAD_4,
+ key_file, key_desc);
+ if (!root_fctx)
+ return -1;
+ print_fscrypt_master_key_descriptor(root_fctx);
+ }
+
if (c->min_io_size == -1)
return err_msg("min. I/O unit was not specified "
"(use -h for help)");
@@ -2786,8 +2894,6 @@ static int close_target(void)
*/
static int init(void)
{
- __u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
- __u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
int err, i, main_lebs, big_lpt = 0, sz;

c->highest_inum = UBIFS_FIRST_INO;
@@ -2829,17 +2935,6 @@ static int init(void)
sz = sizeof(struct inum_mapping *) * HASH_TABLE_SIZE;
hash_table = xzalloc(sz);

- if (c->encrypted) {
- RAND_bytes((void *)master_key_descriptor,
- FS_KEY_DESCRIPTOR_SIZE);
- RAND_bytes((void *)nonce, FS_KEY_DERIVATION_NONCE_SIZE);
-
- root_fctx = init_fscrypt_context(FS_POLICY_FLAGS_PAD_4,
- master_key_descriptor, nonce);
- print_fscrypt_master_key_descriptor(root_fctx);
- c->double_hash = 1;
- }
-
err = init_compression();
if (err)
return err;
--
2.19.1
Richard Weinberger
2018-10-18 14:37:16 UTC
Permalink
Signed-off-by: Richard Weinberger <***@nod.at>
---
Makefile.am | 4 ++
configure.ac | 27 ++++++++++--
ubifs-utils/Makemodule.am | 10 +++--
ubifs-utils/mkfs.ubifs/crypto.h | 11 +++--
ubifs-utils/mkfs.ubifs/fscrypt.h | 65 +++++++++++++++++++++++++----
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 56 ++++++++++++++++++++++---
6 files changed, 148 insertions(+), 25 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 391edef4ee31..1bc4684b191d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -14,6 +14,10 @@ if WITH_SELINUX
AM_CPPFLAGS += -DWITH_SELINUX
endif

+if WITH_CRYPTO
+AM_CPPFLAGS += -DWITH_CRYPTO
+endif
+
sbin_PROGRAMS =
sbin_SCRIPTS =
check_PROGRAMS =
diff --git a/configure.ac b/configure.ac
index 346fcbd26328..d5abb14263b5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -69,7 +69,7 @@ need_lzo="no"
need_xattr="no"
need_cmocka="no"
need_selinux="no"
-
+need_openssl="no"

AM_COND_IF([UNIT_TESTS], [
need_cmocka="yes"
@@ -115,8 +115,6 @@ AC_ARG_ENABLE([lsmtd],
esac],
[AM_CONDITIONAL([BUILD_LSMTD], [true])])

-AC_CHECK_HEADER(openssl/rand.h)
-
AC_ARG_WITH([jffs],
[AS_HELP_STRING([--without-jffs], [Disable jffsX utilities])],
[case "${withval}" in
@@ -140,6 +138,7 @@ AM_COND_IF([BUILD_UBIFS], [
need_xattr="yes"
need_zlib="yes"
need_lzo="yes"
+ need_openssl="yes"
])

AM_COND_IF([BUILD_JFFSX], [
@@ -174,6 +173,15 @@ AC_ARG_WITH([selinux],
*) AC_MSG_ERROR([bad value ${withval} for --with-selinux]) ;;
esac])

+AC_ARG_WITH([crypto],
+ [AS_HELP_STRING([--without-crypto],
+ [Disable support for UBIFS crypto features])],
+ [case "${withval}" in
+ yes) ;;
+ no) need_openssl="no";;
+ *) AC_MSG_ERROR([bad value ${withval} for --without-crypto]) ;;
+ esac])
+
##### search for dependencies #####

clock_gettime_missing="no"
@@ -184,6 +192,7 @@ lzo_missing="no"
xattr_missing="no"
cmocka_missing="no"
selinux_missing="no"
+openssl_missing="no"

if test "x$need_zlib" = "xyes"; then
PKG_CHECK_MODULES(ZLIB, [zlib], [], [zlib_missing="yes"])
@@ -226,6 +235,11 @@ if test "x$need_selinux" = "xyes"; then
AC_CHECK_HEADERS([selinux/label.h], [], [selinux_missing="yes"])
fi

+if test "x$need_openssl" = "xyes"; then
+ AC_CHECK_HEADER(openssl/rand.h)
+ PKG_CHECK_MODULES(OPENSSL, [openssl], [], [openssl_missing="yes"])
+fi
+
if test "x$need_cmocka" = "xyes"; then
PKG_CHECK_MODULES(CMOCKA, [cmocka], [], [cmocka_missing="yes"])
fi
@@ -281,6 +295,12 @@ if test "x$selinux_missing" = "xyes"; then
need_selinux="no"
fi

+if test "x$openssl_missing" = "xyes"; then
+ AC_MSG_WARN([cannot find headers for OpenSSL library])
+ AC_MSG_WARN([disabling OpenSSL support])
+ need_openssl="no"
+fi
+
if test "x$cmocka_missing" = "xyes"; then
AC_MSG_WARN([cannot find CMocka library required for unit tests])
AC_MSG_NOTICE([unit tests can optionally be disabled])
@@ -296,6 +316,7 @@ fi
AM_CONDITIONAL([WITHOUT_LZO], [test "x$need_lzo" != "xyes"])
AM_CONDITIONAL([WITHOUT_XATTR], [test "x$need_xattr" != "xyes"])
AM_CONDITIONAL([WITH_SELINUX], [test "x$need_selinux" == "xyes"])
+AM_CONDITIONAL([WITH_CRYPTO], [test "x$need_openssl" == "xyes"])

AC_CHECK_SIZEOF([off_t])
AC_CHECK_SIZEOF([loff_t])
diff --git a/ubifs-utils/Makemodule.am b/ubifs-utils/Makemodule.am
index 5905a2badbb6..b8e4075c9d2a 100644
--- a/ubifs-utils/Makemodule.am
+++ b/ubifs-utils/Makemodule.am
@@ -10,15 +10,19 @@ mkfs_ubifs_SOURCES = \
ubifs-utils/mkfs.ubifs/crc16.c \
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 \
ubifs-utils/mkfs.ubifs/hashtable/hashtable.c \
ubifs-utils/mkfs.ubifs/hashtable/hashtable_itr.c \
ubifs-utils/mkfs.ubifs/devtable.c
-mkfs_ubifs_LDADD = libmtd.a libubi.a $(ZLIB_LIBS) $(LZO_LIBS) $(UUID_LIBS) $(LIBSELINUX_LIBS) -lm -lssl -lcrypto
+
+if WITH_CRYPTO
+mkfs_ubifs_SOURCES += ubifs-utils/mkfs.ubifs/crypto.c \
+ ubifs-utils/mkfs.ubifs/fscrypt.c
+endif
+
+mkfs_ubifs_LDADD = libmtd.a libubi.a $(ZLIB_LIBS) $(LZO_LIBS) $(UUID_LIBS) $(LIBSELINUX_LIBS) $(OPENSSL_LIBS) -lm
mkfs_ubifs_CPPFLAGS = $(AM_CPPFLAGS) $(ZLIB_CFLAGS) $(LZO_CFLAGS) $(UUID_CFLAGS) $(LIBSELINUX_CFLAGS)\
-I$(top_srcdir)/ubi-utils/include -I$(top_srcdir)/ubifs-utils/mkfs.ubifs/

diff --git a/ubifs-utils/mkfs.ubifs/crypto.h b/ubifs-utils/mkfs.ubifs/crypto.h
index f275839aa77d..b6ffad19b72d 100644
--- a/ubifs-utils/mkfs.ubifs/crypto.h
+++ b/ubifs-utils/mkfs.ubifs/crypto.h
@@ -41,19 +41,18 @@ struct cipher {
unsigned int fscrypt_fname_mode;
};

-
+#ifdef WITH_CRYPTO
int crypto_init(void);
-
void crypto_cleanup(void);
-
ssize_t derive_key_aes(const void *deriving_key, const void *source_key,
size_t source_key_len, void *derived_key);
-
int derive_key_descriptor(const void *source_key, void *descriptor);
-
struct cipher *get_cipher(const char *name);
-
void list_ciphers(FILE *fp);
+#else
+static inline int crypto_init(void) { return 0;}
+static inline void crypto_cleanup(void) {}
+#endif /* WITH_CRYPTO */

#endif /* UBIFS_CRYPTO_H */

diff --git a/ubifs-utils/mkfs.ubifs/fscrypt.h b/ubifs-utils/mkfs.ubifs/fscrypt.h
index e3cfee50290a..3b717b4359c6 100644
--- a/ubifs-utils/mkfs.ubifs/fscrypt.h
+++ b/ubifs-utils/mkfs.ubifs/fscrypt.h
@@ -97,27 +97,76 @@ struct fscrypt_symlink_data {
#define FS_IV_SIZE 16
#endif

+#ifdef WITH_CRYPTO
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);
-
+#else
+static inline struct fscrypt_context *init_fscrypt_context(
+ const char *cipher_name,
+ unsigned int flags,
+ const char *key_file,
+ const char *key_descriptor)
+{
+ (void)cipher_name;
+ (void)flags;
+ (void)key_file;
+ (void)key_descriptor;
+
+ assert(0);
+ return NULL;
+}
+
+static inline void free_fscrypt_context(struct fscrypt_context *fctx)
+{
+ (void)fctx;
+
+ assert(0);
+}
+
+static inline int encrypt_path(void **outbuf, void *data, unsigned int data_len,
+ unsigned int max_namelen, struct fscrypt_context *fctx)
+{
+ (void)outbuf;
+ (void)data;
+ (void)data_len;
+ (void)max_namelen;
+ (void)fctx;
+
+ assert(0);
+ return -1;
+}
+
+static inline int encrypt_data_node(struct fscrypt_context *fctx, unsigned int block_no,
+ struct ubifs_data_node *dn, size_t length)
+{
+ (void)fctx;
+ (void)block_no;
+ (void)dn;
+ (void)length;
+
+ assert(0);
+ return -1;
+}
+
+static inline struct fscrypt_context *inherit_fscrypt_context(struct fscrypt_context *fctx)
+{
+ (void)fctx;
+
+ assert(0);
+ return NULL;
+}
+#endif /* WITH_CRYPTO */
#endif /* FSCRYPT_H */

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index e4204dae07cb..7073bf052688 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -508,9 +508,12 @@ static int get_options(int argc, char**argv)
{
int opt, i, fscrypt_flags = FS_POLICY_FLAGS_PAD_4;
const char *key_file = NULL, *key_desc = NULL;
- const char *tbl_file = NULL, *cipher_name = "AES-128-CBC";
+ const char *tbl_file = NULL;
struct stat st;
char *endp;
+#ifdef WITH_CRYPTO
+ const char *cipher_name;
+#endif

c->fanout = 8;
c->orph_lebs = 1;
@@ -587,8 +590,10 @@ static int get_options(int argc, char**argv)
exit(EXIT_SUCCESS);
case '?':
printf("%s", helptext);
+#ifdef WITH_CRYPTO
printf("\n\nSupported ciphers:\n");
list_ciphers(stdout);
+#endif
exit(-1);
case 'v':
verbose = 1;
@@ -729,7 +734,11 @@ static int get_options(int argc, char**argv)
break;
}
case 'C':
+#ifdef WITH_CRYPTO
cipher_name = optarg;
+#else
+ return err_msg("mkfs.ubifs was built without crypto support.");
+#endif
break;
}
}
@@ -748,20 +757,26 @@ static int get_options(int argc, char**argv)
if (c->max_leb_cnt == -1)
c->max_leb_cnt = c->vi.rsvd_lebs;
}
-
if (key_file || key_desc) {
+#ifdef WITH_CRYPTO
if (!key_file)
return err_msg("no key file specified");

c->double_hash = 1;
c->encrypted = 1;

+ if (cipher_name == NULL)
+ cipher_name = "AES-128-CBC";
+
root_fctx = init_fscrypt_context(cipher_name, fscrypt_flags,
key_file, key_desc);
if (!root_fctx)
return -1;

print_fscrypt_master_key_descriptor(root_fctx);
+#else
+ return err_msg("mkfs.ubifs was built without crypto support.");
+#endif
}

if (c->min_io_size == -1)
@@ -1385,6 +1400,7 @@ static inline int inode_add_selinux_xattr(struct ubifs_ino_node *host_ino,
}
#endif

+#ifdef WITH_CRYPTO
static int set_fscrypt_context(struct ubifs_ino_node *host_ino, ino_t inum,
struct stat *host_st,
struct fscrypt_context *fctx)
@@ -1421,6 +1437,31 @@ static int encrypt_symlink(void *dst, void *data, unsigned int data_len,
free(sd);
return link_disk_len;
}
+#else
+static int set_fscrypt_context(struct ubifs_ino_node *host_ino, ino_t inum,
+ struct stat *host_st,
+ struct fscrypt_context *fctx)
+{
+ (void)host_ino;
+ (void)inum;
+ (void)host_st;
+ (void)fctx;
+
+ assert(0);
+ return -1;
+}
+static int encrypt_symlink(void *dst, void *data, unsigned int data_len,
+ struct fscrypt_context *fctx)
+{
+ (void)dst;
+ (void)data;
+ (void)data_len;
+ (void)fctx;
+
+ assert(0);
+ return -1;
+}
+#endif

/**
* add_inode - write an inode.
@@ -1582,9 +1623,11 @@ static int add_symlink_inode(const char *path_name, struct stat *st, ino_t inum,

static void set_dent_cookie(struct ubifs_dent_node *dent)
{
+#ifdef WITH_CRYPTO
if (c->double_hash)
RAND_bytes((void *)&dent->cookie, sizeof(dent->cookie));
else
+#endif
dent->cookie = 0;
}

@@ -1981,7 +2024,8 @@ static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,

inum = ++c->highest_inum;

- new_fctx = inherit_fscrypt_context(fctx);
+ if (fctx)
+ new_fctx = inherit_fscrypt_context(fctx);

if (S_ISDIR(dent_st.st_mode)) {
err = add_directory(name, inum, &dent_st, 1, new_fctx);
@@ -2006,7 +2050,8 @@ static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,
size += ALIGN(UBIFS_DENT_NODE_SZ + strlen(entry->d_name) + 1,
8);

- free_fscrypt_context(new_fctx);
+ if (new_fctx)
+ free_fscrypt_context(new_fctx);
}

/*
@@ -2068,7 +2113,8 @@ static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,
size += ALIGN(UBIFS_DENT_NODE_SZ + strlen(nh_elt->name) + 1, 8);

nh_elt = next_name_htbl_element(ph_elt, &itr);
- free_fscrypt_context(new_fctx);
+ if (new_fctx)
+ free_fscrypt_context(new_fctx);
}

creat_sqnum = dir_creat_sqnum;
--
2.19.1
Richard Weinberger
2018-10-18 14:36:44 UTC
Permalink
...and set UBIFS format version

Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 13 ++++++++++++-
ubifs-utils/mkfs.ubifs/ubifs.h | 1 +
2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index fc1b0cb1f6cc..09c28ab0b6bd 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -2357,6 +2357,15 @@ static int finalize_leb_cnt(void)
return 0;
}

+static int ubifs_format_version(void)
+{
+ if (c->double_hash || c->encrypted)
+ return 5;
+
+ /* Default */
+ return 4;
+}
+
/**
* write_super - write the super block.
*/
@@ -2379,7 +2388,7 @@ static int write_super(void)
sup.jhead_cnt = cpu_to_le32(c->jhead_cnt);
sup.fanout = cpu_to_le32(c->fanout);
sup.lsave_cnt = cpu_to_le32(c->lsave_cnt);
- sup.fmt_version = cpu_to_le32(UBIFS_FORMAT_VERSION);
+ sup.fmt_version = cpu_to_le32(ubifs_format_version());
sup.default_compr = cpu_to_le16(c->default_compr);
sup.rp_size = cpu_to_le64(c->rp_size);
sup.time_gran = cpu_to_le32(DEFAULT_TIME_GRAN);
@@ -2396,6 +2405,8 @@ static int write_super(void)
sup.flags |= cpu_to_le32(UBIFS_FLG_SPACE_FIXUP);
if (c->double_hash)
sup.flags |= cpu_to_le32(UBIFS_FLG_DOUBLE_HASH);
+ if (c->encrypted)
+ sup.flags |= cpu_to_le32(UBIFS_FLG_ENCRYPTION);

return write_node(&sup, UBIFS_SB_NODE_SZ, UBIFS_SB_LNUM);
}
diff --git a/ubifs-utils/mkfs.ubifs/ubifs.h b/ubifs-utils/mkfs.ubifs/ubifs.h
index 5a4af997e7bd..c26d0944ac50 100644
--- a/ubifs-utils/mkfs.ubifs/ubifs.h
+++ b/ubifs-utils/mkfs.ubifs/ubifs.h
@@ -410,6 +410,7 @@ struct ubifs_info
int big_lpt;
int space_fixup;
int double_hash;
+ int encrypted;
long long lpt_sz;

int ltab_lnum;
--
2.19.1
Richard Weinberger
2018-10-18 14:37:08 UTC
Permalink
The key length can be very long, for example in xts mode.
So we have to use the right sizes for block and iv lengths.

Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/crypto.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/crypto.c b/ubifs-utils/mkfs.ubifs/crypto.c
index bd3273767a5b..8d113f198bb2 100644
--- a/ubifs-utils/mkfs.ubifs/crypto.c
+++ b/ubifs-utils/mkfs.ubifs/crypto.c
@@ -207,32 +207,32 @@ static ssize_t encrypt_cbc_cts(const void *plaintext, size_t size,

memset(iv, 0, ivsize);

- diff = size % key_len;
+ diff = size % ivsize;

if (diff) {
- padded_size = size - diff + key_len;
+ padded_size = size - diff + ivsize;
padded = size > 256 ? malloc(padded_size) : alloca(padded_size);

memcpy(padded, plaintext, size);
memset(padded + size, 0, padded_size - size);

ret = do_encrypt(cipher, padded, padded_size, key, key_len,
- iv, sizeof(iv), ciphertext);
+ iv, ivsize, ciphertext);

if (size > 256)
free(padded);
} else {
ret = do_encrypt(cipher, plaintext, size, key, key_len,
- iv, sizeof(iv), ciphertext);
+ iv, ivsize, ciphertext);
}

if (ret < 0)
return ret;

- count = ret / key_len;
+ count = ret / ivsize;

if (count > 1)
- block_swap(ciphertext, count - 2, count - 1, key_len);
+ block_swap(ciphertext, count - 2, count - 1, ivsize);

return size;
}
--
2.19.1
Richard Weinberger
2018-10-18 14:37:02 UTC
Permalink
From: David Oberhollenzer <***@sigma-star.at>

Signed-off-by: David Oberhollenzer <***@sigma-star.at>
Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 39 +++++++++++++++++++++++------
1 file changed, 32 insertions(+), 7 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index 9935fceafb77..707758a42f4f 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -186,6 +186,7 @@ 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;
@@ -217,7 +218,7 @@ static struct inum_mapping **hash_table;
/* Inode creation sequence number */
static unsigned long long creat_sqnum;

-static const char *optstring = "d:r:m:o:D:yh?vVe:c:g:f:Fp:k:x:X:j:R:l:j:UQqaK:b:P:";
+static const char *optstring = "d:r:m:o:D:yh?vVe:c:g:f:Fp:k:x:X:j:R:l:j:UQqaK:b:P:C:";

static const struct option longopts[] = {
{"root", 1, NULL, 'r'},
@@ -246,6 +247,7 @@ static const struct option longopts[] = {
{"key", 1, NULL, 'K'},
{"key-descriptor", 1, NULL, 'b'},
{"padding", 1, NULL, 'P'},
+ {"cipher", 1, NULL, 'C'},
{NULL, 0, NULL, 0}
};

@@ -294,6 +296,8 @@ static const char *helptext =
"-b, --key-descriptor=HEX specify the key descriptor as a hex string.\n"
"-P, --padding=NUM specify padding policy for encrypting filenames\n"
" (default = 4).\n"
+"-C, --cipher=NAME Specify cipher to use for file level encryption\n"
+" (default is \"AES-128-CBC\").\n"
"-h, --help display this help text\n\n"
"Note, SIZE is specified in bytes, but it may also be specified in Kilobytes,\n"
"Megabytes, and Gigabytes if a KiB, MiB, or GiB suffix is used.\n\n"
@@ -718,7 +722,7 @@ static int get_options(int argc, char**argv)
{
int opt, i, fscrypt_flags = FS_POLICY_FLAGS_PAD_4;
const char *key_file = NULL, *key_desc = NULL;
- const char *tbl_file = NULL;
+ const char *tbl_file = NULL, *cipher_name = "AES-128-CBC";
struct stat st;
char *endp;

@@ -797,6 +801,8 @@ static int get_options(int argc, char**argv)
exit(EXIT_SUCCESS);
case '?':
printf("%s", helptext);
+ printf("\n\nSupported ciphers:\n");
+ list_ciphers(stdout);
exit(-1);
case 'v':
verbose = 1;
@@ -936,6 +942,9 @@ static int get_options(int argc, char**argv)
}
break;
}
+ case 'C':
+ cipher_name = optarg;
+ break;
}
}

@@ -967,6 +976,15 @@ static int get_options(int argc, char**argv)
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);
}

@@ -1604,6 +1622,7 @@ static int encrypt_path(void **outbuf, void *data, unsigned int data_len,
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);
@@ -1619,7 +1638,10 @@ static int encrypt_path(void **outbuf, void *data, unsigned int data_len,
crypt_key = calc_fscrypt_subkey(fctx);
if (!crypt_key)
return err_msg("could not compute subkey");
- if (encrypt_aes128_cbc_cts(inbuf, cryptlen, crypt_key, *outbuf) < 0)
+
+ ret = fscrypt_cipher->encrypt_fname(inbuf, cryptlen,
+ crypt_key, *outbuf);
+ if (ret < 0)
return err_msg("could not encrypt filename");

free(crypt_key);
@@ -2003,10 +2025,13 @@ static int add_file(const char *path_name, struct stat *st, ino_t inum,
if (!crypt_key)
return err_msg("could not compute subkey");

- ret = encrypt_block_aes128_cbc(inbuf, pad_len, crypt_key, block_no,
- outbuf);
- if (ret != pad_len)
- return err_msg("encrypt_block_aes128_cbc returned %zi instead of %zi", ret, pad_len);
+ 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);
--
2.19.1
Richard Weinberger
2018-10-18 14:36:57 UTC
Permalink
From: David Oberhollenzer <***@sigma-star.at>

Signed-off-by: David Oberhollenzer <***@sigma-star.at>
Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 55 ++++++++---------------------
1 file changed, 15 insertions(+), 40 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index 49a895ae3682..ae1d26726deb 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -1703,53 +1703,28 @@ static int add_dent_node(ino_t dir_inum, const char *name, ino_t inum,
set_dent_cookie(dent);

if (!fctx) {
- dent_key_init(c, &key, dir_inum, dname.name, dname.len);
- dent->nlen = cpu_to_le16(dname.len);
- memcpy(dent->name, dname.name, dname.len);
- dent->name[dname.len] = '\0';
- len = UBIFS_DENT_NODE_SZ + dname.len + 1;
-
kname_len = dname.len;
kname = strdup(name);
if (!kname)
return err_msg("cannot allocate memory");
} else {
- void *inbuf, *outbuf, *crypt_key;
unsigned int max_namelen = type == UBIFS_ITYPE_LNK ? UBIFS_MAX_INO_DATA : UBIFS_MAX_NLEN;
- unsigned int padding = 4 << (fctx->flags & FS_POLICY_FLAGS_PAD_MASK);
- unsigned int cryptlen;
-
- cryptlen = max_t(unsigned int, dname.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, dname.name, dname.len);
-
- crypt_key = calc_fscrypt_subkey(fctx);
- if (!crypt_key)
- return err_msg("could not compute subkey");
- if (encrypt_aes128_cbc_cts(inbuf, cryptlen, crypt_key, outbuf) < 0)
- return err_msg("could not encrypt filename");
-
- dent->nlen = cpu_to_le16(cryptlen);
- memcpy(dent->name, outbuf, cryptlen);
- dent->name[cryptlen] = '\0';
- len = UBIFS_DENT_NODE_SZ + cryptlen + 1;
-
- dent_key_init(c, &key, dir_inum, outbuf, cryptlen);
-
- kname_len = cryptlen;
- kname = xmalloc(cryptlen);
- memcpy(kname, outbuf, cryptlen);
- free(crypt_key);
- free(inbuf);
- free(outbuf);
+ int ret;
+
+ ret = encrypt_path((void **)&kname, dname.name, dname.len,
+ max_namelen, fctx);
+ if (ret < 0)
+ return ret;
+
+ kname_len = ret;
}
+
+ dent_key_init(c, &key, dir_inum, kname, kname_len);
+ dent->nlen = cpu_to_le16(kname_len);
+ memcpy(dent->name, kname, kname_len);
+ dent->name[kname_len] = '\0';
+ len = UBIFS_DENT_NODE_SZ + kname_len + 1;
+
key_write(&key, dent->key);

return add_node(&key, kname, kname_len, dent, len);
--
2.19.1
Richard Weinberger
2018-10-18 14:37:10 UTC
Permalink
This works currently by chance since the sizes match, but
that might change with different cipher setups.

Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/crypto.c | 2 +-
ubifs-utils/mkfs.ubifs/fscrypt.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/crypto.c b/ubifs-utils/mkfs.ubifs/crypto.c
index ec414531e94a..7d35ae7473ba 100644
--- a/ubifs-utils/mkfs.ubifs/crypto.c
+++ b/ubifs-utils/mkfs.ubifs/crypto.c
@@ -119,7 +119,7 @@ static size_t gen_essiv_salt(const void *iv, size_t iv_len, const void *key, siz
return -1;
}

- ret = do_encrypt(cipher, iv, iv_len, sha256, EVP_CIPHER_key_length(cipher), NULL, 0, salt);
+ ret = do_encrypt(cipher, iv, iv_len, sha256, EVP_MD_size(EVP_sha256()), NULL, 0, salt);
if (ret != iv_len)
errmsg("Unable to compute ESSIV salt, return value %zi instead of %zi", ret, iv_len);

diff --git a/ubifs-utils/mkfs.ubifs/fscrypt.c b/ubifs-utils/mkfs.ubifs/fscrypt.c
index 2fc0ae8b3509..b9f9acc17c17 100644
--- a/ubifs-utils/mkfs.ubifs/fscrypt.c
+++ b/ubifs-utils/mkfs.ubifs/fscrypt.c
@@ -31,7 +31,7 @@ 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);
+ ret = derive_key_aes(fctx->nonce, fscrypt_masterkey, fscrypt_cipher->key_length, new_key);
if (ret < 0) {
err_msg("derive_key_aes failed: %i\n", ret);

@@ -202,7 +202,7 @@ static int load_master_key(const char *key_file, struct cipher *fsc)
return -1;
}

- keysize = read(kf, fscrypt_masterkey, sizeof(fscrypt_masterkey));
+ keysize = read(kf, fscrypt_masterkey, fsc->key_length);
if (keysize < 0) {
sys_errmsg("read '%s'", key_file);
goto fail;
--
2.19.1
Richard Weinberger
2018-10-18 14:37:03 UTC
Permalink
From: David Oberhollenzer <***@sigma-star.at>

Signed-off-by: David Oberhollenzer <***@sigma-star.at>
Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/crypto.c | 47 +++++++++++++++------------------
ubifs-utils/mkfs.ubifs/crypto.h | 14 ----------
2 files changed, 22 insertions(+), 39 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/crypto.c b/ubifs-utils/mkfs.ubifs/crypto.c
index f249b49b5b59..f7b51357c04a 100644
--- a/ubifs-utils/mkfs.ubifs/crypto.c
+++ b/ubifs-utils/mkfs.ubifs/crypto.c
@@ -27,21 +27,6 @@
#include "common.h"
#include "mtd_swab.h"

-
-static struct cipher ciphers[] = {
- {
- .name = "AES-128-CBC",
- .encrypt_block = encrypt_block_aes128_cbc,
- .encrypt_fname = encrypt_aes128_cbc_cts,
- }, {
- .name = "AES-256-XTS",
- .encrypt_block = encrypt_block_aes256_xts,
- .encrypt_fname = encrypt_aes256_cbc_cts,
- }
-};
-
-
-
static int do_sha256(const unsigned char *in, size_t len, unsigned char *out)
{
unsigned int out_len;
@@ -168,9 +153,9 @@ static ssize_t encrypt_block(const void *plaintext, size_t size,
return ret;
}

-ssize_t encrypt_block_aes128_cbc(const void *plaintext, size_t size,
- const void *key, uint64_t block_index,
- void *ciphertext)
+static ssize_t encrypt_block_aes128_cbc(const void *plaintext, size_t size,
+ const void *key, uint64_t block_index,
+ void *ciphertext)
{
const EVP_CIPHER *cipher = EVP_aes_128_cbc();

@@ -182,9 +167,9 @@ ssize_t encrypt_block_aes128_cbc(const void *plaintext, size_t size,
ciphertext, cipher);
}

-ssize_t encrypt_block_aes256_xts(const void *plaintext, size_t size,
- const void *key, uint64_t block_index,
- void *ciphertext)
+static ssize_t encrypt_block_aes256_xts(const void *plaintext, size_t size,
+ const void *key, uint64_t block_index,
+ void *ciphertext)
{
const EVP_CIPHER *cipher = EVP_aes_256_xts();

@@ -252,8 +237,8 @@ static ssize_t encrypt_cbc_cts(const void *plaintext, size_t size,
return size;
}

-ssize_t encrypt_aes128_cbc_cts(const void *plaintext, size_t size,
- const void *key, void *ciphertext)
+static ssize_t encrypt_aes128_cbc_cts(const void *plaintext, size_t size,
+ const void *key, void *ciphertext)
{
const EVP_CIPHER *cipher = EVP_aes_128_cbc();
if (!cipher) {
@@ -264,8 +249,8 @@ ssize_t encrypt_aes128_cbc_cts(const void *plaintext, size_t size,
return encrypt_cbc_cts(plaintext, size, key, ciphertext, cipher);
}

-ssize_t encrypt_aes256_cbc_cts(const void *plaintext, size_t size,
- const void *key, void *ciphertext)
+static ssize_t encrypt_aes256_cbc_cts(const void *plaintext, size_t size,
+ const void *key, void *ciphertext)
{
const EVP_CIPHER *cipher = EVP_aes_256_cbc();
if (!cipher) {
@@ -293,6 +278,18 @@ ssize_t derive_key_aes(const void *deriving_key, const void *source_key,
aes_key_len, NULL, 0, derived_key);
}

+static struct cipher ciphers[] = {
+ {
+ .name = "AES-128-CBC",
+ .encrypt_block = encrypt_block_aes128_cbc,
+ .encrypt_fname = encrypt_aes128_cbc_cts,
+ }, {
+ .name = "AES-256-XTS",
+ .encrypt_block = encrypt_block_aes256_xts,
+ .encrypt_fname = encrypt_aes256_cbc_cts,
+ }
+};
+
int crypto_init(void)
{
ERR_load_crypto_strings();
diff --git a/ubifs-utils/mkfs.ubifs/crypto.h b/ubifs-utils/mkfs.ubifs/crypto.h
index 5bff70fea29e..b6a1e004f46d 100644
--- a/ubifs-utils/mkfs.ubifs/crypto.h
+++ b/ubifs-utils/mkfs.ubifs/crypto.h
@@ -42,20 +42,6 @@ int crypto_init(void);

void crypto_cleanup(void);

-ssize_t encrypt_block_aes128_cbc(const void *plaintext, size_t size,
- const void *key, uint64_t block_index,
- void *ciphertext);
-
-ssize_t encrypt_block_aes256_xts(const void *plaintext, size_t size,
- const void *key, uint64_t block_index,
- void *ciphertext);
-
-ssize_t encrypt_aes128_cbc_cts(const void *plaintext, size_t size,
- const void *key, void *ciphertext);
-
-ssize_t encrypt_aes256_cbc_cts(const void *plaintext, size_t size,
- const void *key, void *ciphertext);
-
ssize_t derive_key_aes(const void *deriving_key, const void *source_key,
size_t source_key_len, void *derived_key);
--
2.19.1
Richard Weinberger
2018-10-18 14:37:15 UTC
Permalink
Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/crypto.c | 1 +
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 2 --
2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/crypto.c b/ubifs-utils/mkfs.ubifs/crypto.c
index 50a09b53ebfe..9c6073ec00f9 100644
--- a/ubifs-utils/mkfs.ubifs/crypto.c
+++ b/ubifs-utils/mkfs.ubifs/crypto.c
@@ -330,6 +330,7 @@ static struct cipher ciphers[] = {
int crypto_init(void)
{
ERR_load_crypto_strings();
+ RAND_poll();
return 0;
}

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index f8d8e52f1bae..e4204dae07cb 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -2841,8 +2841,6 @@ int main(int argc, char *argv[])
if (crypto_init())
return -1;

- RAND_poll();
-
err = get_options(argc, argv);
if (err)
return err;
--
2.19.1
Richard Weinberger
2018-10-18 14:36:54 UTC
Permalink
Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/key.h | 10 ++++++++++
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 8 ++++++++
2 files changed, 18 insertions(+)

diff --git a/ubifs-utils/mkfs.ubifs/key.h b/ubifs-utils/mkfs.ubifs/key.h
index c18e35e8f0a3..2de530b813a2 100644
--- a/ubifs-utils/mkfs.ubifs/key.h
+++ b/ubifs-utils/mkfs.ubifs/key.h
@@ -209,4 +209,14 @@ static inline int keys_cmp(const union ubifs_key *key1,
return 0;
}

+/**
+ * key_type - get key type.
+ * @c: UBIFS file-system description object
+ * @key: key to get type of
+ */
+static inline int key_type(const union ubifs_key *key)
+{
+ return key->u32[1] >> UBIFS_S_KEY_BLOCK_BITS;
+}
+
#endif /* !__UBIFS_KEY_H__ */
diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index b402945924ac..8aba668f8e28 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -1161,6 +1161,14 @@ static int add_node(union ubifs_key *key, char *name, int name_len, void *node,
{
int err, lnum, offs;

+ if (key_type(key) == UBIFS_DENT_KEY || key_type(key) == UBIFS_XENT_KEY) {
+ if (!name)
+ return err_msg("Directory entry or xattr without name!");
+ } else {
+ if (name)
+ return err_msg("Name given for non dir/xattr node!");
+ }
+
prepare_node(node, len);

err = reserve_space(len, &lnum, &offs);
--
2.19.1
Richard Weinberger
2018-10-18 14:37:12 UTC
Permalink
...if none is given. To be compatible with fscryptctl.

Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/crypto.c | 27 ++++++++++++++++++++++++---
ubifs-utils/mkfs.ubifs/crypto.h | 1 +
ubifs-utils/mkfs.ubifs/fscrypt.c | 11 ++++++++---
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 2 --
4 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/crypto.c b/ubifs-utils/mkfs.ubifs/crypto.c
index d0f24e1a5f6f..50a09b53ebfe 100644
--- a/ubifs-utils/mkfs.ubifs/crypto.c
+++ b/ubifs-utils/mkfs.ubifs/crypto.c
@@ -26,7 +26,7 @@
#include "fscrypt.h"
#include "common.h"

-static int do_sha256(const unsigned char *in, size_t len, unsigned char *out)
+static int do_hash(const EVP_MD *md, const unsigned char *in, size_t len, unsigned char *out)
{
unsigned int out_len;
EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
@@ -34,7 +34,7 @@ static int do_sha256(const unsigned char *in, size_t len, unsigned char *out)
if (!mdctx)
return -1;

- if (EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL) != 1)
+ if (EVP_DigestInit_ex(mdctx, md, NULL) != 1)
return -1;

if(EVP_DigestUpdate(mdctx, in, len) != 1)
@@ -121,7 +121,7 @@ static size_t gen_essiv_salt(const void *iv, size_t iv_len, const void *key, siz
return -1;
}

- if (do_sha256(key, key_len, sha256) != 0) {
+ if (do_hash(EVP_sha256(), key, key_len, sha256) != 0) {
errmsg("sha256 failed");
return -1;
}
@@ -288,6 +288,27 @@ ssize_t derive_key_aes(const void *deriving_key, const void *source_key,
aes_key_len, NULL, 0, derived_key);
}

+int derive_key_descriptor(const void *source_key, void *descriptor)
+{
+ int ret = -1;
+ void *hash1 = xzalloc(EVP_MD_size(EVP_sha512()));
+ void *hash2 = xzalloc(EVP_MD_size(EVP_sha512()));
+
+ if (do_hash(EVP_sha512(), source_key, FS_MAX_KEY_SIZE, hash1) != 0)
+ goto out;
+
+ if (do_hash(EVP_sha512(), hash1, EVP_MD_size(EVP_sha512()), hash2) != 0)
+ goto out;
+
+ memcpy(descriptor, hash2, FS_KEY_DESCRIPTOR_SIZE);
+
+ ret = 0;
+out:
+ free(hash1);
+ free(hash2);
+ return ret;
+}
+
static struct cipher ciphers[] = {
{
.name = "AES-128-CBC",
diff --git a/ubifs-utils/mkfs.ubifs/crypto.h b/ubifs-utils/mkfs.ubifs/crypto.h
index c2631dd0fd89..f275839aa77d 100644
--- a/ubifs-utils/mkfs.ubifs/crypto.h
+++ b/ubifs-utils/mkfs.ubifs/crypto.h
@@ -49,6 +49,7 @@ void crypto_cleanup(void);
ssize_t derive_key_aes(const void *deriving_key, const void *source_key,
size_t source_key_len, void *derived_key);

+int derive_key_descriptor(const void *source_key, void *descriptor);

struct cipher *get_cipher(const char *name);

diff --git a/ubifs-utils/mkfs.ubifs/fscrypt.c b/ubifs-utils/mkfs.ubifs/fscrypt.c
index b9f9acc17c17..ce6e2fc29ce0 100644
--- a/ubifs-utils/mkfs.ubifs/fscrypt.c
+++ b/ubifs-utils/mkfs.ubifs/fscrypt.c
@@ -242,12 +242,17 @@ struct fscrypt_context *init_fscrypt_context(const char *cipher_name,
return NULL;
}

- if (parse_key_descriptor(key_descriptor, master_key_descriptor))
- return NULL;
-
if (load_master_key(key_file, fscrypt_cipher))
return NULL;

+ if (!key_descriptor) {
+ if (derive_key_descriptor(fscrypt_masterkey, master_key_descriptor))
+ return NULL;
+ } else {
+ if (parse_key_descriptor(key_descriptor, master_key_descriptor))
+ return NULL;
+ }
+
RAND_bytes((void *)nonce, FS_KEY_DERIVATION_NONCE_SIZE);

new_fctx = xmalloc(sizeof(*new_fctx));
diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index 9bd15a2f047a..f8d8e52f1bae 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -752,8 +752,6 @@ static int get_options(int argc, char**argv)
if (key_file || key_desc) {
if (!key_file)
return err_msg("no key file specified");
- if (!key_desc)
- return err_msg("no key descriptor specified");

c->double_hash = 1;
c->encrypted = 1;
--
2.19.1
Richard Weinberger
2018-10-18 14:37:01 UTC
Permalink
From: David Oberhollenzer <***@sigma-star.at>

Signed-off-by: David Oberhollenzer <***@sigma-star.at>
Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 38 ++++++++++++++++++++++++++---
1 file changed, 35 insertions(+), 3 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index 70c306bdf94e..9935fceafb77 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -217,7 +217,7 @@ static struct inum_mapping **hash_table;
/* Inode creation sequence number */
static unsigned long long creat_sqnum;

-static const char *optstring = "d:r:m:o:D:yh?vVe:c:g:f:Fp:k:x:X:j:R:l:j:UQqaK:b:";
+static const char *optstring = "d:r:m:o:D:yh?vVe:c:g:f:Fp:k:x:X:j:R:l:j:UQqaK:b:P:";

static const struct option longopts[] = {
{"root", 1, NULL, 'r'},
@@ -245,6 +245,7 @@ static const struct option longopts[] = {
{"selinux", 1, NULL, 's'},
{"key", 1, NULL, 'K'},
{"key-descriptor", 1, NULL, 'b'},
+ {"padding", 1, NULL, 'P'},
{NULL, 0, NULL, 0}
};

@@ -291,6 +292,8 @@ static const char *helptext =
"-s, --selinux=FILE Selinux context file\n"
"-K, --key=FILE load an encryption key from a specified file.\n"
"-b, --key-descriptor=HEX specify the key descriptor as a hex string.\n"
+"-P, --padding=NUM specify padding policy for encrypting filenames\n"
+" (default = 4).\n"
"-h, --help display this help text\n\n"
"Note, SIZE is specified in bytes, but it may also be specified in Kilobytes,\n"
"Megabytes, and Gigabytes if a KiB, MiB, or GiB suffix is used.\n\n"
@@ -713,7 +716,7 @@ static int open_ubi(const char *node)

static int get_options(int argc, char**argv)
{
- int opt, i;
+ int opt, i, fscrypt_flags = FS_POLICY_FLAGS_PAD_4;
const char *key_file = NULL, *key_desc = NULL;
const char *tbl_file = NULL;
struct stat st;
@@ -904,6 +907,35 @@ static int get_options(int argc, char**argv)
}
key_desc = optarg;
break;
+ case 'P': {
+ int error = 0;
+ unsigned long num;
+
+ num = simple_strtoul(optarg, &error);
+ if (error)
+ num = -1;
+
+ fscrypt_flags &= ~FS_POLICY_FLAGS_PAD_MASK;
+
+ switch (num) {
+ case 4:
+ fscrypt_flags |= FS_POLICY_FLAGS_PAD_4;
+ break;
+ case 8:
+ fscrypt_flags |= FS_POLICY_FLAGS_PAD_8;
+ break;
+ case 16:
+ fscrypt_flags |= FS_POLICY_FLAGS_PAD_16;
+ break;
+ case 32:
+ fscrypt_flags |= FS_POLICY_FLAGS_PAD_32;
+ break;
+ default:
+ return errmsg("invalid padding policy '%s'",
+ optarg);
+ }
+ break;
+ }
}
}

@@ -931,7 +963,7 @@ static int get_options(int argc, char**argv)
c->double_hash = 1;
c->encrypted = 1;

- root_fctx = init_fscrypt_context(FS_POLICY_FLAGS_PAD_4,
+ root_fctx = init_fscrypt_context(fscrypt_flags,
key_file, key_desc);
if (!root_fctx)
return -1;
--
2.19.1
Richard Weinberger
2018-10-18 14:37:18 UTC
Permalink
AES-128-CBC should only being used when 256-XTS is too slow
on low end hardware.

Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index a60d392bbc81..5847b352038a 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -766,7 +766,7 @@ static int get_options(int argc, char**argv)
c->encrypted = 1;

if (cipher_name == NULL)
- cipher_name = "AES-128-CBC";
+ cipher_name = "AES-256-XTS";

root_fctx = init_fscrypt_context(cipher_name, fscrypt_flags,
key_file, key_desc);
--
2.19.1
Richard Weinberger
2018-10-18 14:37:17 UTC
Permalink
Signed-off-by: Richard Weinberger <***@nod.at>
---
ubifs-utils/mkfs.ubifs/fscrypt.c | 5 +++--
ubifs-utils/mkfs.ubifs/fscrypt.h | 1 -
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 2 --
3 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/fscrypt.c b/ubifs-utils/mkfs.ubifs/fscrypt.c
index 3d4bff618050..6d2b650d626d 100644
--- a/ubifs-utils/mkfs.ubifs/fscrypt.c
+++ b/ubifs-utils/mkfs.ubifs/fscrypt.c
@@ -65,13 +65,13 @@ void free_fscrypt_context(struct fscrypt_context *fctx)
free(fctx);
}

-void print_fscrypt_master_key_descriptor(struct fscrypt_context *fctx)
+static void print_fscrypt_master_key_descriptor(__u8 *master_key_descriptor)
{
int i;

normsg_cont("fscrypt master key descriptor: 0x");
for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; i++) {
- printf("%02x", fctx->master_key_descriptor[i]);
+ printf("%02x", master_key_descriptor[i]);
}
printf("\n");
}
@@ -248,6 +248,7 @@ struct fscrypt_context *init_fscrypt_context(const char *cipher_name,
if (!key_descriptor) {
if (derive_key_descriptor(fscrypt_masterkey, master_key_descriptor))
return NULL;
+ print_fscrypt_master_key_descriptor(master_key_descriptor);
} else {
if (parse_key_descriptor(key_descriptor, master_key_descriptor))
return NULL;
diff --git a/ubifs-utils/mkfs.ubifs/fscrypt.h b/ubifs-utils/mkfs.ubifs/fscrypt.h
index 3b717b4359c6..34b799c94c2b 100644
--- a/ubifs-utils/mkfs.ubifs/fscrypt.h
+++ b/ubifs-utils/mkfs.ubifs/fscrypt.h
@@ -101,7 +101,6 @@ struct fscrypt_symlink_data {
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,
diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index 7073bf052688..a60d392bbc81 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -772,8 +772,6 @@ static int get_options(int argc, char**argv)
key_file, key_desc);
if (!root_fctx)
return -1;
-
- print_fscrypt_master_key_descriptor(root_fctx);
#else
return err_msg("mkfs.ubifs was built without crypto support.");
#endif
--
2.19.1
David Oberhollenzer
2018-11-02 16:41:44 UTC
Permalink
Hi!

This patch set has been sitting on the ML for more than two weeks now, with no
one commenting/complaining/nit-picking/bike-shedding/etc, so I'll push it to
mtd-utils.git master.

Since I authored some of those commits and already stared at the whole patch
set for quite some time before it's been submitted, I'm not sure how helpful
it is for me to try and review it now. Nevertheless, I've looked through the
patch set again over the last few days, compared it against the latest version
I have locally and did some quick tests and it still looks good to me.

Thanks,

David
Richard Weinberger
2018-11-02 16:43:30 UTC
Permalink
David,
Post by David Oberhollenzer
Hi!
This patch set has been sitting on the ML for more than two weeks now, with no
one commenting/complaining/nit-picking/bike-shedding/etc, so I'll push it to
mtd-utils.git master.
Since I authored some of those commits and already stared at the whole patch
set for quite some time before it's been submitted, I'm not sure how helpful
it is for me to try and review it now. Nevertheless, I've looked through the
patch set again over the last few days, compared it against the latest version
I have locally and did some quick tests and it still looks good to me.
one thing is to consider, Sascha's UBIFS auth patches for mkfs.ubifs.
Not that there are some subtle merge issues.

Thanks,
//richard

Continue reading on narkive:
Loading...