meta-phosphor: npcm8xx.bbclass: support sign images feature

Add sign images feature according customer's requirement.
Set "SECURED_IMAGE" to "True" and enable sign images feature.
When sign images feature be enabled. Use default keys to sign
images if customer didn't point their own local keys path.

Note: "SECURED_IMAGE" default is "True".

Tested:
Use default keys sign:
That will use default path and keys from igps to sign.

Use local keys sign:
That will use local path and keys to sign.
When KEY_FOLDER and KEY definition both are valid.

However, when KEY_FOLDER and KEY definition are invalid either,
that will output sign images failed then stop build full images.

Tested: build pass and boot up successfully with signed

Signed-off-by: Tim Lee <timlee660101@gmail.com>
Change-Id: If2b793906ab338aec391062d9bfeae2b1e790078
diff --git a/meta-phosphor/classes/image_types_phosphor_nuvoton_npcm8xx.bbclass b/meta-phosphor/classes/image_types_phosphor_nuvoton_npcm8xx.bbclass
index 913286e..eb78494 100644
--- a/meta-phosphor/classes/image_types_phosphor_nuvoton_npcm8xx.bbclass
+++ b/meta-phosphor/classes/image_types_phosphor_nuvoton_npcm8xx.bbclass
@@ -1,15 +1,21 @@
 UBOOT_BINARY := "u-boot.${UBOOT_SUFFIX}"
-BOOTBLOCK = "BootBlockAndHeader.bin"
-ATF_BINARY := "bl31AndHeader.bin"
-OPTEE_BINARY := "teeAndHeader.bin"
+BB_HEADER_BINARY := "BootBlockAndHeader.bin"
+BL31_HEADER_BINARY := "bl31AndHeader.bin"
+OPTEE_HEADER_BINARY := "teeAndHeader.bin"
 KMT_TIPFW_BINARY := "Kmt_TipFwL0_Skmt_TipFwL1.bin"
 KMT_TIPFW_BB_BINARY = "Kmt_TipFw_BootBlock.bin"
 KMT_TIPFW_BB_BL31_BINARY = "Kmt_TipFw_BootBlock_BL31.bin"
 KMT_TIPFW_BB_BL31_TEE_BINARY = "Kmt_TipFw_BootBlock_BL31_Tee.bin"
 KMT_TIPFW_BB_UBOOT_BINARY = "u-boot.bin.merged"
+
+BB_BL31_BINARY = "BootBlock_BL31_no_tip.bin"
+BB_BL31_TEE_BINARY = "BootBlock_BL31_Tee_no_tip.bin"
+BB_BL31_TEE_UBOOT_BINARY = "u-boot.bin.merged"
+
 FULL_SUFFIX = "full"
 MERGED_SUFFIX = "merged"
 UBOOT_SUFFIX:append = ".${MERGED_SUFFIX}"
+UBOOT_HEADER_BINARY := "${UBOOT_BINARY}.${FULL_SUFFIX}"
 
 IGPS_DIR = "${STAGING_DIR_NATIVE}/${datadir}/npcm8xx-igps"
 
@@ -17,9 +23,11 @@
 BL31_BIN = "bl31.bin"
 OPTEE_BIN = "tee.bin"
 UBOOT_BIN = "u-boot.bin"
+BB_NO_TIP_BIN = "arbel_a35_bootblock_no_tip.bin"
 
 # Align images if needed
 python do_pad_binary() {
+    TIP_IMAGE = d.getVar('TIP_IMAGE', True)
     def Pad_bin_file_inplace(inF, align):
         padding_size = 0
         padding_size_end = 0
@@ -33,14 +41,18 @@
         infile.write(b'\x00' * padding_size)
         infile.close()
 
-    Pad_bin_file_inplace(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True),
+    if TIP_IMAGE == "True":
+        Pad_bin_file_inplace(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True),
         '%s' % d.getVar('BB_BIN',True)), int(d.getVar('PAD_ALIGN', True)))
+    else:
+        Pad_bin_file_inplace(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True),
+        '%s' % d.getVar('BB_NO_TIP_BIN',True)), int(d.getVar('PAD_ALIGN', True)))
 
     Pad_bin_file_inplace(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True),
-        '%s' % d.getVar('BL31_BIN',True)), int(d.getVar('PAD_ALIGN', True)))
+    '%s' % d.getVar('BL31_BIN',True)), int(d.getVar('PAD_ALIGN', True)))
 
     Pad_bin_file_inplace(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True),
-        '%s' % d.getVar('OPTEE_BIN',True)), int(d.getVar('PAD_ALIGN', True)))
+    '%s' % d.getVar('OPTEE_BIN',True)), int(d.getVar('PAD_ALIGN', True)))
 
     Pad_bin_file_inplace(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True),
         '%s' % d.getVar('UBOOT_BIN',True)), int(d.getVar('PAD_ALIGN', True)))
@@ -52,22 +64,97 @@
     cd ${DEPLOY_DIR_IMAGE}
 
     bingo ${IGPS_DIR}/BL31_AndHeader.xml \
-            -o ${DEPLOY_DIR_IMAGE}/${ATF_BINARY}
+            -o ${BL31_HEADER_BINARY}
 
     bingo ${IGPS_DIR}/OpTeeAndHeader.xml \
-            -o ${DEPLOY_DIR_IMAGE}/${OPTEE_BINARY}
+            -o ${OPTEE_HEADER_BINARY}
 
+    if [ "${TIP_IMAGE}" = "True" ]; then
     bingo ${IGPS_DIR}/BootBlockAndHeader_${DEVICE_GEN}_${IGPS_MACHINE}.xml \
-            -o ${DEPLOY_DIR_IMAGE}/${BOOTBLOCK}
+            -o ${BB_HEADER_BINARY}
+    else
+    bingo ${IGPS_DIR}/BootBlockAndHeader_${DEVICE_GEN}_${IGPS_MACHINE}_NoTip.xml \
+            -o ${BB_HEADER_BINARY}
+    fi
 
     bingo ${IGPS_DIR}/UbootHeader_${DEVICE_GEN}.xml \
-            -o ${UBOOT_BINARY}.${FULL_SUFFIX}
+            -o ${UBOOT_HEADER_BINARY}
 
     cd "$olddir"
 }
 
-python do_merge_bootloaders() {
+check_keys() {
+    if [ -n "${KEY_FOLDER}" ]; then
+        echo "local"
+    else
+        echo "default"
+    fi
+}
 
+# Sign images for secure os be enabled
+do_sign_binary() {
+    if [ "${SECURED_IMAGE}" != "True" ]; then
+       return
+    fi
+    checked=`check_keys`
+    if [ "${checked}" = "local" ]; then
+        bbnote "Sign image with local keys"
+        key_bb=${KEY_FOLDER}/${KEY_BB}
+        key_bl31=${KEY_FOLDER}/${KEY_BL31}
+        key_optee=${KEY_FOLDER}/${KEY_OPTEE}
+        key_uboot=${KEY_FOLDER}/${KEY_UBOOT}
+    else
+        bbnote "Sign image with default keys"
+        key_bb=${KEY_FOLDER_DEFAULT}/${KEY_BB}
+        key_bl31=${KEY_FOLDER_DEFAULT}/${KEY_BL31}
+        key_optee=${KEY_FOLDER_DEFAULT}/${KEY_OPTEE}
+        key_uboot=${KEY_FOLDER_DEFAULT}/${KEY_UBOOT}
+    fi
+    bbnote "BB sign key from ${checked}: ${key_bb}"
+    bbnote "BL31 sign key from ${checked}: ${key_bl31}"
+    bbnote "OPTEE sign key from ${checked}: ${key_optee}"
+    bbnote "UBOOT sign key from ${checked}: ${key_uboot}"
+    # Used to embed the key index inside the image, usually at offset 0x140
+    python3 ${IGPS_DIR}/BinarySignatureGenerator.py Replace_binary_single_byte \
+        ${DEPLOY_DIR_IMAGE}/${BB_HEADER_BINARY} 140 ${KEY_BB_INDEX}
+
+    python3 ${IGPS_DIR}/BinarySignatureGenerator.py Replace_binary_single_byte \
+        ${DEPLOY_DIR_IMAGE}/${BL31_HEADER_BINARY} 140 ${SKMT_BL31_KEY_INDEX}
+
+    python3 ${IGPS_DIR}/BinarySignatureGenerator.py Replace_binary_single_byte \
+        ${DEPLOY_DIR_IMAGE}/${OPTEE_HEADER_BINARY} 140 ${SKMT_BL32_KEY_INDEX}
+
+    python3 ${IGPS_DIR}/BinarySignatureGenerator.py Replace_binary_single_byte \
+        ${DEPLOY_DIR_IMAGE}/${UBOOT_HEADER_BINARY} 140 ${SKMT_BL33_KEY_INDEX}
+
+    # Sign specific image with specific key
+    res=`python3 ${IGPS_DIR}/BinarySignatureGenerator.py Sign_binary \
+        ${DEPLOY_DIR_IMAGE}/${BB_HEADER_BINARY} 112 ${key_bb} 16 \
+        ${DEPLOY_DIR_IMAGE}/${BB_HEADER_BINARY} ${SIGN_TYPE} 0 ${KEY_BB_ID}
+
+        python3 ${IGPS_DIR}/BinarySignatureGenerator.py Sign_binary \
+        ${DEPLOY_DIR_IMAGE}/${BL31_HEADER_BINARY} 112 ${key_bl31} 16 \
+        ${DEPLOY_DIR_IMAGE}/${BL31_HEADER_BINARY} ${SIGN_TYPE} 0 ${KEY_BL31_ID}
+
+        python3 ${IGPS_DIR}/BinarySignatureGenerator.py Sign_binary \
+        ${DEPLOY_DIR_IMAGE}/${OPTEE_HEADER_BINARY} 112 ${key_optee} 16 \
+        ${DEPLOY_DIR_IMAGE}/${OPTEE_HEADER_BINARY} ${SIGN_TYPE} 0 ${KEY_OPTEE_ID}
+
+        python3 ${IGPS_DIR}/BinarySignatureGenerator.py Sign_binary \
+        ${DEPLOY_DIR_IMAGE}/${UBOOT_HEADER_BINARY} 112 ${key_uboot} 16 \
+        ${DEPLOY_DIR_IMAGE}/${UBOOT_HEADER_BINARY} ${SIGN_TYPE} 0 ${KEY_UBOOT_ID}`
+
+    # Stop full image build process when sign binary got failed
+    set +e
+    err=`echo $res | grep -E "missing|Invalid|failed"`
+    if [ -n "${err}" ]; then
+        bbfatal "Sign binary failed: keys are not found or invalid. Please check your KEY_FOLDER and KEY definition."
+    fi
+    set -e
+}
+
+python do_merge_bootloaders() {
+    TIP_IMAGE = d.getVar('TIP_IMAGE', True)
     def Merge_bin_files_and_pad(inF1, inF2, outF, align, align_end):
         padding_size = 0
         padding_size_end = 0
@@ -93,25 +180,41 @@
 
             file3.write(b'\xFF' * padding_size_end)
 
-    Merge_bin_files_and_pad(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BINARY',True)),
-        os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('BOOTBLOCK',True)),
+    if TIP_IMAGE == "True":
+        Merge_bin_files_and_pad(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BINARY',True)),
+        os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('BB_HEADER_BINARY',True)),
         os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_BINARY',True)),
         int(d.getVar('BB_ALIGN', True)), int(d.getVar('ALIGN_END', True)))
 
-    Merge_bin_files_and_pad(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_BINARY',True)),
-        os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('ATF_BINARY',True)),
+        Merge_bin_files_and_pad(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_BINARY',True)),
+        os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('BL31_HEADER_BINARY',True)),
         os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_BL31_BINARY',True)),
         int(d.getVar('ATF_ALIGN', True)), int(d.getVar('ALIGN_END', True)))
 
-    Merge_bin_files_and_pad(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_BL31_BINARY',True)),
-        os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('OPTEE_BINARY',True)),
+        Merge_bin_files_and_pad(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_BL31_BINARY',True)),
+        os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('OPTEE_HEADER_BINARY',True)),
         os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_BL31_TEE_BINARY',True)),
         int(d.getVar('OPTEE_ALIGN', True)), int(d.getVar('ALIGN_END', True)))
 
-    Merge_bin_files_and_pad(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_BL31_TEE_BINARY',True)),
-        os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s.full' % d.getVar('UBOOT_BINARY',True)),
+        Merge_bin_files_and_pad(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_BL31_TEE_BINARY',True)),
+        os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('UBOOT_HEADER_BINARY',True)),
         os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_UBOOT_BINARY',True)),
         int(d.getVar('UBOOT_ALIGN', True)), int(d.getVar('ALIGN_END', True)))
+    else:
+        Merge_bin_files_and_pad(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('BB_HEADER_BINARY',True)),
+        os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('BL31_HEADER_BINARY',True)),
+        os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('BB_BL31_BINARY',True)),
+        int(d.getVar('ATF_ALIGN', True)), int(d.getVar('ALIGN_END', True)))
+
+        Merge_bin_files_and_pad(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('BB_BL31_BINARY',True)),
+        os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('OPTEE_HEADER_BINARY',True)),
+        os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('BB_BL31_TEE_BINARY',True)),
+        int(d.getVar('OPTEE_ALIGN', True)), int(d.getVar('ALIGN_END', True)))
+
+        Merge_bin_files_and_pad(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('BB_BL31_TEE_BINARY',True)),
+        os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('UBOOT_HEADER_BINARY',True)),
+        os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('BB_BL31_TEE_UBOOT_BINARY',True)),
+        int(d.getVar('UBOOT_ALIGN', True)), int(d.getVar('ALIGN_END', True)))
 }
 
 do_pad_binary[depends] += " \
@@ -135,8 +238,9 @@
 }
 
 addtask do_pad_binary before do_prepare_bootloaders
+addtask do_sign_binary before do_merge_bootloaders after do_prepare_bootloaders
 addtask do_prepare_bootloaders before do_generate_static after do_generate_rwfs_static
-addtask do_merge_bootloaders before do_generate_static after do_prepare_bootloaders
+addtask do_merge_bootloaders before do_generate_static after do_sign_binary
 addtask do_merge_bootloaders before do_generate_ext4_tar after do_prepare_bootloaders
 
 # Include the full bootblock and u-boot in the final static image