fit_image_setup_cipher() only consumes iv-name-hint: without the hint a
fresh random IV is generated for every image, and any iv property the
cipher node already carries is ignored and later overwritten. The FIT
specification defines iv as the raw initialisation vector carried in
the FIT and requires at least one of iv-name-hint or iv to be present,
so an .its author who supplies an explicit iv reasonably expects it to
be used.

Use the iv property when no iv-name-hint is given, after checking that
its length matches the cipher's IV length, and only fall back to a
random IV when the node provides neither. Besides matching the
specification this makes encryption reproducible, since the same
source, key and IV now produce the same ciphertext on every run. It
also allows images that share data through the image-data property,
added later in this series, to be encrypted consistently without
relying on an IV file in the key directory.

Signed-off-by: Aristo Chen <[email protected]>
---
 tools/image-host.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/tools/image-host.c b/tools/image-host.c
index 46036673050..bb042b73446 100644
--- a/tools/image-host.c
+++ b/tools/image-host.c
@@ -421,7 +421,9 @@ static int fit_image_setup_cipher(struct image_cipher_info 
*info,
                                  const char *image_name, int image_noffset,
                                  int noffset)
 {
+       const void *iv;
        char *algo_name;
+       int ivlen;
        int ret = -1;
 
        if (fit_image_cipher_get_algo(fit, noffset, &algo_name)) {
@@ -443,8 +445,9 @@ static int fit_image_setup_cipher(struct image_cipher_info 
*info,
        /*
         * Read the IV name
         *
-        * If this property is not provided then mkimage will generate
-        * a random IV and store it in the FIT image
+        * If this property is not provided then mkimage will use the iv
+        * property of the cipher node, if present, or generate a random
+        * IV and store it in the FIT image
         */
        info->ivname = fdt_getprop(fit, noffset, "iv-name-hint", NULL);
 
@@ -479,6 +482,7 @@ static int fit_image_setup_cipher(struct image_cipher_info 
*info,
                goto out;
        }
 
+       iv = fdt_getprop(fit, noffset, "iv", &ivlen);
        if (info->ivname) {
                /* Read the IV in the file */
                ret = fit_image_read_key_iv_data(info->keydir, info->ivname,
@@ -486,6 +490,16 @@ static int fit_image_setup_cipher(struct image_cipher_info 
*info,
                                                 info->cipher->iv_len);
                if (ret < 0)
                        goto out;
+       } else if (iv) {
+               /* Use the explicit IV from the cipher node */
+               if (ivlen != info->cipher->iv_len) {
+                       fprintf(stderr,
+                               "Wrong iv length for cipher in image '%s' 
(expected %d bytes, got %d)\n",
+                               image_name, info->cipher->iv_len, ivlen);
+                       ret = -1;
+                       goto out;
+               }
+               memcpy((void *)info->iv, iv, ivlen);
        } else {
                /* Generate an ramdom IV */
                ret = get_random_data((void *)info->iv, info->cipher->iv_len);
-- 
2.43.0

Reply via email to