diff mbox series

[5/7] Permit a per artefact IV to decrypt

Message ID 20200319100529.31509-6-sbabic@denx.de
State Accepted
Headers show
Series Extend IPC to change AES Key | expand

Commit Message

Stefano Babic March 19, 2020, 10:05 a.m. UTC
Reusing the same Initialization Vector (IV) is considered bad practise and
must be avoided. SWUpdate has a global AES key and IV to decrypt
artefact. Change this and add a new attribute ("ivt") that can be
specific for each artefact.

Signed-off-by: Stefano Babic <sbabic@denx.de>
---
 core/cpio_utils.c             | 17 +++++++++++------
 core/installer.c              |  3 ++-
 core/stream_interface.c       |  6 +++---
 corelib/lua_interface.c       |  6 ++++++
 doc/source/sw-description.rst |  7 +++++++
 handlers/raw_handler.c        |  1 +
 handlers/rdiff_handler.c      |  1 +
 handlers/readback_handler.c   |  1 +
 include/swupdate.h            |  1 +
 include/util.h                |  2 +-
 parser/parser.c               |  1 +
 11 files changed, 35 insertions(+), 11 deletions(-)
diff mbox series

Patch

diff --git a/core/cpio_utils.c b/core/cpio_utils.c
index 8cf4713..923c170 100644
--- a/core/cpio_utils.c
+++ b/core/cpio_utils.c
@@ -369,7 +369,7 @@  static int zstd_step(void* state, void* buffer, size_t size)
 
 int copyfile(int fdin, void *out, unsigned int nbytes, unsigned long *offs, unsigned long long seek,
 	int skip_file, int __attribute__ ((__unused__)) compressed,
-	uint32_t *checksum, unsigned char *hash, int encrypted, writeimage callback)
+	uint32_t *checksum, unsigned char *hash, int encrypted, const char *imgivt, writeimage callback)
 {
 	unsigned int percent, prevpercent = 0;
 	int ret = 0;
@@ -381,6 +381,7 @@  int copyfile(int fdin, void *out, unsigned int nbytes, unsigned long *offs, unsi
 	unsigned int md_len = 0;
 	unsigned char *aes_key = NULL;
 	unsigned char *ivt = NULL;
+	unsigned char ivtbuf[32];
 
 	struct InputState input_state = {
 		.fdin = fdin,
@@ -440,7 +441,10 @@  int copyfile(int fdin, void *out, unsigned int nbytes, unsigned long *offs, unsi
 
 	if (encrypted) {
 		aes_key = get_aes_key();
-		ivt = get_aes_ivt();
+		if (imgivt && strlen(imgivt) && !ascii_to_bin(ivtbuf, imgivt, sizeof(ivtbuf))) {
+			ivt = ivtbuf;
+		} else
+			ivt = get_aes_ivt();
 		decrypt_state.dcrypt = swupdate_DECRYPT_init(aes_key, ivt);
 		if (!decrypt_state.dcrypt) {
 			ERROR("decrypt initialization failure, aborting");
@@ -622,6 +626,7 @@  int copyimage(void *out, struct img_type *img, writeimage callback)
 			&img->checksum,
 			img->sha256,
 			img->is_encrypted,
+			img->ivt_ascii,
 			callback);
 }
 
@@ -686,7 +691,7 @@  int extract_sw_description(int fd, const char *descfile, off_t *offs)
 		close(fdout);
 		return -1;
 	}
-	if (copyfile(fd, &fdout, fdh.size, &offset, 0, 0, 0, &checksum, NULL, 0, NULL) < 0) {
+	if (copyfile(fd, &fdout, fdh.size, &offset, 0, 0, 0, &checksum, NULL, 0, NULL, NULL) < 0) {
 		ERROR("%s corrupted or not valid", descfile);
 		close(fdout);
 		return -1;
@@ -732,7 +737,7 @@  int extract_img_from_cpio(int fd, unsigned long offset, struct filehdr *fdh)
 }
 
 off_t extract_next_file(int fd, int fdout, off_t start, int compressed,
-		int encrypted, unsigned char *hash)
+		int encrypted, char *ivt, unsigned char *hash)
 {
 	int ret;
 	struct filehdr fdh;
@@ -758,7 +763,7 @@  off_t extract_next_file(int fd, int fdout, off_t start, int compressed,
 		return ret;
 	}
 
-	ret = copyfile(fd, &fdout, fdh.size, &offset, 0, 0, compressed, &checksum, hash, encrypted, NULL);
+	ret = copyfile(fd, &fdout, fdh.size, &offset, 0, 0, compressed, &checksum, hash, encrypted, ivt, NULL);
 	if (ret < 0) {
 		ERROR("Error copying extracted file");
 		return ret;
@@ -811,7 +816,7 @@  int cpio_scan(int fd, struct swupdate_cfg *cfg, off_t start)
 		 * we do not have to provide fdout
 		 */
 		if (copyfile(fd, NULL, fdh.size, &offset, 0, 1, 0, &checksum, img ? img->sha256 : NULL,
-				0, NULL) != 0) {
+				0, NULL, NULL) != 0) {
 			ERROR("invalid archive");
 			return -1;
 		}
diff --git a/core/installer.c b/core/installer.c
index 61dc06d..879f3c1 100644
--- a/core/installer.c
+++ b/core/installer.c
@@ -120,7 +120,7 @@  static int extract_scripts(int fd, struct imglist *head, int fromfile)
 
 		if (fromfile)
 			ret = extract_next_file(fd, fdout, script->offset, 0,
-						script->is_encrypted, script->sha256);
+						script->is_encrypted, script->ivt_ascii, script->sha256);
 		else {
 			int fdin;
 			char *tmpfile;
@@ -147,6 +147,7 @@  static int extract_scripts(int fd, struct imglist *head, int fromfile)
 					&checksum,
 					script->sha256,
 					script->is_encrypted,
+					script->ivt_ascii,
 					NULL);
 			close(fdin);
 		}
diff --git a/core/stream_interface.c b/core/stream_interface.c
index 824c51a..46a0dc0 100644
--- a/core/stream_interface.c
+++ b/core/stream_interface.c
@@ -99,7 +99,7 @@  static int extract_file_to_tmp(int fd, const char *fname, unsigned long *poffs)
 	if (fdout < 0)
 		return -1;
 
-	if (copyfile(fd, &fdout, fdh.size, poffs, 0, 0, 0, &checksum, NULL, 0, NULL) < 0) {
+	if (copyfile(fd, &fdout, fdh.size, poffs, 0, 0, 0, &checksum, NULL, 0, NULL, NULL) < 0) {
 		close(fdout);
 		return -1;
 	}
@@ -213,7 +213,7 @@  static int extract_files(int fd, struct swupdate_cfg *software)
 				fdout = openfileoutput(img->extract_file);
 				if (fdout < 0)
 					return -1;
-				if (copyfile(fd, &fdout, fdh.size, &offset, 0, 0, 0, &checksum, img->sha256, 0, NULL) < 0) {
+				if (copyfile(fd, &fdout, fdh.size, &offset, 0, 0, 0, &checksum, img->sha256, 0, NULL, NULL) < 0) {
 					close(fdout);
 					return -1;
 				}
@@ -227,7 +227,7 @@  static int extract_files(int fd, struct swupdate_cfg *software)
 				break;
 
 			case SKIP_FILE:
-				if (copyfile(fd, &fdout, fdh.size, &offset, 0, skip, 0, &checksum, NULL, 0, NULL) < 0) {
+				if (copyfile(fd, &fdout, fdh.size, &offset, 0, skip, 0, &checksum, NULL, 0, NULL, NULL) < 0) {
 					return -1;
 				}
 				if (checksum != (unsigned long)fdh.chksum) {
diff --git a/corelib/lua_interface.c b/corelib/lua_interface.c
index 9ead9b8..ca524ed 100644
--- a/corelib/lua_interface.c
+++ b/corelib/lua_interface.c
@@ -292,6 +292,9 @@  static void lua_string_to_img(struct img_type *img, const char *key,
 			sizeof(img->filesystem));
 	if (!strcmp(key, "sha256"))
 		ascii_to_hash(img->sha256, value);
+	if (!strcmp(key, "ivt"))
+		strncpy(img->ivt_ascii, value,
+			sizeof(img->ivt_ascii));
 
 	if (!strncmp(key, offset, sizeof(offset))) {
 		strncpy(seek_str, value,
@@ -364,6 +367,7 @@  static int l_copy2file(lua_State *L)
 				 &checksum,
 				 img.sha256,
 				 img.is_encrypted,
+				 img.ivt_ascii,
 				 NULL);
 	update_table(L, &img);
 	lua_pop(L, 1);
@@ -435,6 +439,7 @@  static int l_istream_read(lua_State* L)
 				 &checksum,
 				 img.sha256,
 				 img.is_encrypted,
+				 img.ivt_ascii,
 				 istream_read_callback);
 
 	lua_pop(L, 1);
@@ -475,6 +480,7 @@  static void update_table(lua_State* L, struct img_type *img)
 		LUA_PUSH_IMG_STRING(img, "mtdname", path);
 		LUA_PUSH_IMG_STRING(img, "data", type_data);
 		LUA_PUSH_IMG_STRING(img, "filesystem", filesystem);
+		LUA_PUSH_IMG_STRING(img, "ivt", ivt_ascii);
 
 		LUA_PUSH_IMG_BOOL(img, "installed_directly", install_directly);
 		LUA_PUSH_IMG_BOOL(img, "install_if_different", id.install_if_different);
diff --git a/doc/source/sw-description.rst b/doc/source/sw-description.rst
index e1950f8..1cfe6e2 100644
--- a/doc/source/sw-description.rst
+++ b/doc/source/sw-description.rst
@@ -1292,6 +1292,13 @@  There are 4 main sections inside sw-description:
    |             |          | scripts    | and must be decrypted before          |
    |             |          |            | installing.                           |
    +-------------+----------+------------+---------------------------------------+
+   | ivt         | string   | images     | IVT in case of encrypted artefact     |
+   |             |          | files      | It has no value if "encrypted" is not |
+   |             |          | scripts    | set. Each artefact can have an own    |
+   |             |          |            | IVT to avoid attacker can guess the   |
+   |             |          |            | the key.                              |
+   |             |          |            | It is a ASCII string of 32 chars      |
+   +-------------+----------+------------+---------------------------------------+
    | data        | string   | images     | This is used to pass arbitrary data   |
    |             |          | files      | to a handler.                         |
    |             |          | scripts    |                                       |
diff --git a/handlers/raw_handler.c b/handlers/raw_handler.c
index fb48170..21bc779 100644
--- a/handlers/raw_handler.c
+++ b/handlers/raw_handler.c
@@ -182,6 +182,7 @@  static int copy_raw_image(struct img_type *img,
 			&checksum,
 			0, /* no sha256 */
 			0, /* no encrypted */
+			NULL, /* no IVT */
 			NULL);
 
 	close(fdout);
diff --git a/handlers/rdiff_handler.c b/handlers/rdiff_handler.c
index d264c48..8d76df2 100644
--- a/handlers/rdiff_handler.c
+++ b/handlers/rdiff_handler.c
@@ -348,6 +348,7 @@  static int apply_rdiff_patch(struct img_type *img,
 			&img->checksum,
 			img->sha256,
 			img->is_encrypted,
+			img->ivt_ascii,
 			apply_rdiff_chunk_cb);
 	if (ret != 0) {
 		ERROR("Error %d running rdiff job, aborting.", ret);
diff --git a/handlers/readback_handler.c b/handlers/readback_handler.c
index a86164f..d67d0f4 100644
--- a/handlers/readback_handler.c
+++ b/handlers/readback_handler.c
@@ -107,6 +107,7 @@  static int readback_postinst(struct img_type *img)
 			NULL,  /* no checksum */
 			hash,
 			0,     /* no encrypted */
+			NULL,     /* no IVT */
 			NULL); /* no callback */
 	if (status == 0) {
 		INFO("Readback verification success");
diff --git a/include/swupdate.h b/include/swupdate.h
index 8cd1574..eccd54a 100644
--- a/include/swupdate.h
+++ b/include/swupdate.h
@@ -74,6 +74,7 @@  struct img_type {
 	int compressed;
 	int preserve_attributes; /* whether to preserve attributes in archives */
 	int is_encrypted;
+	char ivt_ascii[32];
 	int install_directly;
 	int is_script;
 	int is_partitioner;
diff --git a/include/util.h b/include/util.h
index 208b25f..f397113 100644
--- a/include/util.h
+++ b/include/util.h
@@ -176,7 +176,7 @@  int copyfile(int fdin, void *out, unsigned int nbytes, unsigned long *offs,
 int copyimage(void *out, struct img_type *img, writeimage callback);
 int extract_sw_description(int fd, const char *descfile, off_t *offs);
 off_t extract_next_file(int fd, int fdout, off_t start, int compressed,
-			int encrypted, unsigned char *hash);
+			int encrypted, char *ivt, unsigned char *hash);
 int openfileoutput(const char *filename);
 int mkpath(char *dir, mode_t mode);
 int swupdate_file_setnonblock(int fd, bool block);
diff --git a/parser/parser.c b/parser/parser.c
index 8cdbfb4..78f6a01 100644
--- a/parser/parser.c
+++ b/parser/parser.c
@@ -308,6 +308,7 @@  static int parse_common_attributes(parsertype p, void *elem, struct img_type *im
 	get_field(p, elem, "install-if-different", &image->id.install_if_different);
 	get_field(p, elem, "install-if-higher", &image->id.install_if_higher);
 	get_field(p, elem, "encrypted", &image->is_encrypted);
+	GET_FIELD_STRING(p, elem, "ivt", image->ivt_ascii);
 
 	return 0;
 }