RSS: Align SIC tools to specification

As it uses a non-standard AES counter mode to decrypt

Change-Id: Ic274c2084ba3405d123717fc9e674c8c69751ace
Signed-off-by: Raef Coles <raef.coles@arm.com>
diff --git a/docs/platform/arm/rss/readme.rst b/docs/platform/arm/rss/readme.rst
index 3ca5639..5d0f373 100644
--- a/docs/platform/arm/rss/readme.rst
+++ b/docs/platform/arm/rss/readme.rst
@@ -110,8 +110,8 @@
 
     fiptool create \
         --align 8192 --rss-bl2           bl2_signed.bin \
-        --align 8192 --rss-ns            tfm_ns.bin \
-        --align 8192 --rss-s             tfm_s.bin \
+        --align 8192 --rss-ns            tfm_ns_encrypted.bin \
+        --align 8192 --rss-s             tfm_s_encrypted.bin \
         --align 8192 --rss-sic-tables-ns tfm_ns_sic_tables_signed.bin \
         --align 8192 --rss-sic-tables-s  tfm_s_sic_tables_signed.bin \
         --align 8192 --rss-scp-bl1       <signed Host SCP BL1 image> \
diff --git a/platform/ext/target/arm/rss/common/bl2/create_xip_tables.py b/platform/ext/target/arm/rss/common/bl2/create_xip_tables.py
index 192cc6d..ceabb7f 100644
--- a/platform/ext/target/arm/rss/common/bl2/create_xip_tables.py
+++ b/platform/ext/target/arm/rss/common/bl2/create_xip_tables.py
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2022, Arm Limited. All rights reserved.
+# Copyright (c) 2022-2023, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -14,6 +14,7 @@
 import secrets
 
 sic_page_size = 1024
+sic_line_size = 16
 
 def struct_pack(objects, pad_to=0):
     defstring = "<"
@@ -40,8 +41,6 @@
 with open(args.input_image, "rb") as in_file:
     image = in_file.read()
 
-# TODO derive a key from the main key based on the security counter / fw
-# version, as we do for BL2. This requires tweaks to crypto in BL2 first.
 if args.encrypt_key_file is not None:
     with open(args.encrypt_key, "rb") as in_file:
         encrypt_key = in_file.read()
@@ -55,12 +54,16 @@
 fw_version_bytes = int(args.image_version, 0).to_bytes(4, 'little')
 nonce_bytes = secrets.token_bytes(8)
 
-# Provided the image starts at the beginning of the DR, we can start the line
-# index at 0.
-counter_val = struct_pack([nonce_bytes, fw_version_bytes], pad_to=16)
-
-cipher = Cipher(algorithms.AES(encrypt_key), modes.CTR(counter_val))
-enc_image = cipher.encryptor().update(image)
+# The SIC uses a non-standard counter construction, so we need to do this
+# manually
+enc_image = []
+line_idx = 0
+for chunk in chunk_bytes(image, sic_line_size):
+    counter_val = struct_pack([line_idx.to_bytes(4, 'little'), fw_version_bytes, nonce_bytes[4:], nonce_bytes[:4]], pad_to=16)
+    line_idx += 1
+    cipher = Cipher(algorithms.AES(encrypt_key), modes.CTR(counter_val))
+    enc_image.append(cipher.encryptor().update(chunk))
+enc_image = reduce(add, enc_image, b"")
 
 htr = reduce(add, map(lambda x:hashlib.sha256(x).digest(), chunk_bytes(enc_image, sic_page_size)), b"")
 
diff --git a/platform/ext/target/arm/rss/common/bl2/sic_boot.c b/platform/ext/target/arm/rss/common/bl2/sic_boot.c
index be0d786..0968372 100644
--- a/platform/ext/target/arm/rss/common/bl2/sic_boot.c
+++ b/platform/ext/target/arm/rss/common/bl2/sic_boot.c
@@ -13,6 +13,7 @@
 #include "tfm_plat_otp.h"
 #include "host_flash_atu.h"
 #include "plat_def_fip_uuid.h"
+#include "rss_kmu_slot_ids.h"
 
 #include <string.h>
 
@@ -57,14 +58,15 @@
 int sic_boot_post_load(uint32_t image_id, uint32_t image_load_offset)
 {
     enum sic_error_t sic_err;
+    enum kmu_error_t kmu_err;
     struct rss_xip_htr_table *table;
-    uint32_t key[8];
     enum tfm_plat_err_t plat_err;
     size_t sic_page_size;
-    enum tfm_otp_element_id_t decrypt_key_otp_id;
+    enum rss_kmu_slot_id_t decrypt_key_slot;
     uint32_t decrypt_region;
     uint32_t xip_region_base_addr;
-    uint32_t xip_region_size;
+    size_t xip_region_size;
+    size_t max_region_size;
     uint64_t fip_offsets[2];
     bool fip_found[2];
     uint64_t fip_offset;
@@ -105,11 +107,11 @@
             return 1;
         }
 
-        decrypt_key_otp_id = PLAT_OTP_ID_KEY_NON_SECURE_ENCRYPTION;
+        decrypt_key_slot = RSS_KMU_SLOT_NON_SECURE_ENCRYPTION_KEY;
         atu_region = RSS_ATU_NS_IMAGE_XIP_REGION;
         decrypt_region = RSS_SIC_NS_IMAGE_DECRYPT_REGION;
         xip_region_base_addr = RSS_RUNTIME_NS_XIP_BASE_S;
-        xip_region_size      = NS_CODE_SIZE;
+        max_region_size = NS_CODE_SIZE;
         image_uuid = UUID_RSS_FIRMWARE_NS;
         image_offset = &ns_image_offset;
 
@@ -127,11 +129,11 @@
             return 1;
         }
 
-        decrypt_key_otp_id = PLAT_OTP_ID_KEY_SECURE_ENCRYPTION;
+        decrypt_key_slot = RSS_KMU_SLOT_SECURE_ENCRYPTION_KEY;
         atu_region = RSS_ATU_S_IMAGE_XIP_REGION;
         decrypt_region = RSS_SIC_S_IMAGE_DECRYPT_REGION;
         xip_region_base_addr = RSS_RUNTIME_S_XIP_BASE_S;
-        xip_region_size      = S_CODE_SIZE;
+        max_region_size = S_CODE_SIZE;
         image_uuid = UUID_RSS_FIRMWARE_S;
         image_offset = &s_image_offset;
 
@@ -148,7 +150,8 @@
                                                          atu_region,
                                                          xip_region_base_addr,
                                                          image_uuid,
-                                                         image_offset);
+                                                         image_offset,
+                                                         &xip_region_size);
     if (rc) {
         return rc;
     }
@@ -162,6 +165,9 @@
         return 1;
     }
 
+    if (xip_region_size > max_region_size) {
+        return 1;
+    }
 
     sic_err = sic_auth_table_set(&SIC_DEV_S, (uint32_t*)(table->htr),
                                  table->htr_size, (xip_region_base_addr
@@ -171,23 +177,20 @@
         return 1;
     }
 
-    plat_err = tfm_plat_otp_read(decrypt_key_otp_id, sizeof(key), (uint8_t*)key);
-    if (plat_err != TFM_PLAT_ERR_SUCCESS) {
-        return 1;
-    }
-
     sic_err = sic_decrypt_region_enable(&SIC_DEV_S,
                                         decrypt_region, xip_region_base_addr,
                                         xip_region_size,
-                                        image_load_offset, table->nonce,
-                                        key);
+                                        table->fw_revision, table->nonce,
+                                        NULL);
     if (sic_err != SIC_ERROR_NONE) {
-        memset(key, 0, sizeof(key));
         return 1;
     }
 
-
-    memset(key, 0, sizeof(key));
+    kmu_err = kmu_export_key(&KMU_DEV_S, decrypt_key_slot);
+    if (kmu_err != KMU_ERROR_NONE) {
+        while(1){}
+        return 1;
+    }
 
     return 0;
 }
diff --git a/platform/ext/target/arm/rss/common/fip_parser/host_flash_atu.c b/platform/ext/target/arm/rss/common/fip_parser/host_flash_atu.c
index b4f8dbc..0fdc026 100644
--- a/platform/ext/target/arm/rss/common/fip_parser/host_flash_atu.c
+++ b/platform/ext/target/arm/rss/common/fip_parser/host_flash_atu.c
@@ -74,7 +74,8 @@
                                                     uint32_t slot,
                                                     uintptr_t logical_address,
                                                     uuid_t image_uuid,
-                                                    uint32_t *logical_address_offset)
+                                                    uint32_t *logical_address_offset,
+                                                    size_t *slot_size)
 {
     enum atu_error_t err;
     int rc;
@@ -116,7 +117,12 @@
         return rc;
     }
 
-    *logical_address_offset = alignment_offset;
+    if (logical_address_offset != NULL) {
+        *logical_address_offset = alignment_offset;
+    }
+    if (slot_size != NULL) {
+        *slot_size = atu_slot_size;
+    }
 
     return 0;
 }
@@ -232,7 +238,7 @@
     rc = host_flash_atu_setup_image_input_slots_from_fip(fip_offsets[0],
                                           RSS_ATU_REGION_INPUT_IMAGE_SLOT_0,
                                           HOST_FLASH0_IMAGE0_BASE_S, image_uuid,
-                                          &offsets[0]);
+                                          &offsets[0], NULL);
     if (rc == 0) {
         fip_mapped[0] = true;
     }
@@ -240,7 +246,7 @@
     rc = host_flash_atu_setup_image_input_slots_from_fip(fip_offsets[1],
                                           RSS_ATU_REGION_INPUT_IMAGE_SLOT_1,
                                           HOST_FLASH0_IMAGE1_BASE_S, image_uuid,
-                                          &offsets[1]);
+                                          &offsets[1], NULL);
     if (rc == 0) {
         fip_mapped[1] = true;
     }
@@ -256,7 +262,7 @@
         rc = host_flash_atu_setup_image_input_slots_from_fip(fip_offsets[0],
                                               RSS_ATU_REGION_INPUT_IMAGE_SLOT_1,
                                               HOST_FLASH0_IMAGE1_BASE_S,
-                                              image_uuid, &offsets[1]);
+                                              image_uuid, &offsets[1], NULL);
         if (rc) {
             return rc;
         }
@@ -264,7 +270,7 @@
         rc = host_flash_atu_setup_image_input_slots_from_fip(fip_offsets[1],
                                               RSS_ATU_REGION_INPUT_IMAGE_SLOT_0,
                                               HOST_FLASH0_IMAGE0_BASE_S,
-                                              image_uuid, &offsets[0]);
+                                              image_uuid, &offsets[0], NULL);
         if (rc) {
             return rc;
         }
diff --git a/platform/ext/target/arm/rss/common/fip_parser/host_flash_atu.h b/platform/ext/target/arm/rss/common/fip_parser/host_flash_atu.h
index 62d65fe..7a11da0 100644
--- a/platform/ext/target/arm/rss/common/fip_parser/host_flash_atu.h
+++ b/platform/ext/target/arm/rss/common/fip_parser/host_flash_atu.h
@@ -56,13 +56,16 @@
  *                                    This is required because images may not be
  *                                    aligned to the ATU page size.
  *
+ * \param[out] atu_slot_size          The size of the mapped image.
+ *
  * \return                            0 on success, non-zero on failure.
  */
 int host_flash_atu_setup_image_input_slots_from_fip(uint64_t fip_offset,
                                                     uint32_t slot,
                                                     uintptr_t logical_address,
                                                     uuid_t image_uuid,
-                                                    uint32_t *logical_address_offset);
+                                                    uint32_t *logical_address_offset,
+                                                    size_t *atu_slot_size);
 
 /**
  * \brief                             Setup the input and output slots for a
diff --git a/platform/ext/target/arm/rss/common/native_drivers/sic_drv.c b/platform/ext/target/arm/rss/common/native_drivers/sic_drv.c
index 69ab33d..4886da0 100644
--- a/platform/ext/target/arm/rss/common/native_drivers/sic_drv.c
+++ b/platform/ext/target/arm/rss/common/native_drivers/sic_drv.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2023 Arm Limited. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -470,11 +470,13 @@
     }
 
     /* The key is 4 words, plus another 4 if the 256-bit key bit is set in the
-     * CCR
+     * CCR. If it is NULL, assume it is set in another way (e.g. by KMU export)
      */
-    key_len = 4 + (((p_sic->ccr >> 3) & 0x1) * 4);
-    for (idx = 0; idx < key_len; idx++) {
-        p_sic->dr[region_idx].dkw[idx] = key[idx];
+    if (key != NULL) {
+        key_len = 4 + (((p_sic->ccr >> 3) & 0x1) * 4);
+        for (idx = 0; idx < key_len; idx++) {
+            p_sic->dr[region_idx].dkw[idx] = key[idx];
+        }
     }
 
     return SIC_ERROR_NONE;
diff --git a/platform/ext/target/arm/rss/kronos/flash_layout.h b/platform/ext/target/arm/rss/kronos/flash_layout.h
index 595a21b..a40de3a 100644
--- a/platform/ext/target/arm/rss/kronos/flash_layout.h
+++ b/platform/ext/target/arm/rss/kronos/flash_layout.h
@@ -53,13 +53,6 @@
 
 #define HOST_IMAGE_HEADER_SIZE          (0x2000)
 
-#ifdef RSS_XIP
-/* Each table contains a bit less that 8KiB of HTR and 2KiB of mcuboot headers.
- * The spare space in the 8KiB is used for decryption IVs.
- */
-#define FLASH_SIC_TABLE_SIZE            (0x2800) /* 10KiB */
-#endif /* RSS_XIP */
-
 /* Sector size of the flash hardware; same as FLASH0_SECTOR_SIZE */
 #define FLASH_AREA_IMAGE_SECTOR_SIZE    (0x1000)    /* 512 KiB */
 /* Same as FLASH0_SIZE */
diff --git a/platform/ext/target/arm/rss/tc/flash_layout.h b/platform/ext/target/arm/rss/tc/flash_layout.h
index fcacb64..dcfaa0f 100644
--- a/platform/ext/target/arm/rss/tc/flash_layout.h
+++ b/platform/ext/target/arm/rss/tc/flash_layout.h
@@ -50,10 +50,10 @@
 #define HOST_IMAGE_HEADER_SIZE          (0x2000)
 
 #ifdef RSS_XIP
-/* Each table contains a bit less that 8KiB of HTR and 2KiB of mcuboot headers.
+/* Each table contains a bit less that 12KiB of HTR and 2KiB of mcuboot headers.
  * The spare space in the 8KiB is used for decryption IVs.
  */
-#define FLASH_SIC_TABLE_SIZE            (0x2800) /* 10KiB */
+#define FLASH_SIC_TABLE_SIZE            (0x3800) /* 10KiB */
 #endif /* RSS_XIP */
 
 /* Sector size of the flash hardware; same as FLASH0_SECTOR_SIZE */