keygeneration: add ability to generate GSC RW signing key pairs

GSC RW signing requires an 3070 bit RSA key. The codesigner tool when
invoked expects the public key in .pem format, the same format is used
by the RO codebase when incorporating the public key in the RO image.

This patch introduces a new key option, RSA3070_NOSIG_ALGOID. The keys
of this kind are not going to be processed by futility, hence no need
to specify the signing algorithm.

BUG=b:221423468
BRANCH=none
TEST=ran ./create_new_keys.sh and observed two gsc keys generated:
    $ ls *gsc*
    gsc_rw_3070.pem  gsc_rw_3070.pem.pub

    in the FPGA setup confirmed that Ti50 RW can be signed and
    verified using the generated key pair.

Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Change-Id: Ie676ba8043c34900388372270329a4903656d499
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/3591642
Reviewed-by: Mike Frysinger <vapier@chromium.org>
Commit-Queue: Mike Frysinger <vapier@chromium.org>
diff --git a/scripts/keygeneration/common.sh b/scripts/keygeneration/common.sh
index af6cd71..4ec445a 100644
--- a/scripts/keygeneration/common.sh
+++ b/scripts/keygeneration/common.sh
@@ -43,8 +43,15 @@
 RSA8192_SHA1_ALGOID=9
 RSA8192_SHA256_ALGOID=10
 RSA8192_SHA512_ALGOID=11
+RSA3070_NOSIG_ALGOID=12
 alg_to_keylen() {
-  echo $(( 1 << (10 + ($1 / 3)) ))
+  local alg="$1"
+
+  # GSC RW signing key does not fit the pattern, return its size explicitly.
+  case ${alg} in
+    (${RSA3070_NOSIG_ALGOID}) echo 3070;;
+    (*) echo $(( 1 << (10 + (alg / 3)) ));;
+  esac
 }
 
 # Default algorithms.
@@ -67,6 +74,9 @@
 ARV_ROOT_ALGOID=${RSA4096_SHA256_ALGOID}
 ARV_PLATFORM_ALGOID=${RSA4096_SHA256_ALGOID}
 
+# GSC signing.
+GSC_RW_KEY_ALGOID=${RSA3070_NOSIG_ALGOID}
+
 # Keyblock modes determine which boot modes a signing key is valid for use
 # in verification.
 #    !DEV 0x1      DEV 0x2
@@ -128,6 +138,27 @@
   rm -f "${base}_${len}.pem" "${base}_${len}.crt" "${base}_${len}.keyb"
 }
 
+# Emit .pem and .pem.pub using given basename and algorithm
+# This is a special case for GSC signing where vboot reference format keys are
+# not being used.
+make_gsc_pair() {
+  local base=$1
+  local alg=$2
+  local key_version=${3:-1}
+  local len="$(alg_to_keylen "${alg}")"
+  local base_name="${base}_${len}"
+
+  echo "creating ${base} key pair (version = ${key_version})..."
+
+  # Make the RSA key pair.
+  openssl genrsa -F4 -out "${base_name}.pem" "${len}"
+
+  echo "skipping wrapping of ${base_name} keys"
+  echo "Preserving ${base_name}.pem and generating ${base_name}.pem.pub"
+  openssl rsa -in "${base_name}.pem" -outform PEM \
+    -pubout -out "${base_name}.pem.pub"
+}
+
 # Used to generate keys for signing update payloads.
 make_au_payload_key() {
   local dir=$1
diff --git a/scripts/keygeneration/create_new_keys.sh b/scripts/keygeneration/create_new_keys.sh
index 2e1fd22..7c036fa 100755
--- a/scripts/keygeneration/create_new_keys.sh
+++ b/scripts/keygeneration/create_new_keys.sh
@@ -172,6 +172,8 @@
   make_pair arv_root ${ARV_ROOT_ALGOID}
   make_pair arv_platform ${ARV_PLATFORM_ALGOID}
 
+  make_gsc_pair gsc_rw ${GSC_RW_KEY_ALGOID}
+
   # Create the firmware keyblock for use only in Normal mode. This is redundant,
   # since it's never even checked during Recovery mode.
   make_keyblock firmware ${FIRMWARE_KEYBLOCK_MODE} firmware_data_key root_key