From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 57F30C433EF for ; Wed, 1 Jun 2022 06:02:59 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id D19E883E3C; Wed, 1 Jun 2022 08:02:56 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=quarantine dis=none) header.from=ti.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=ti.com header.i=@ti.com header.b="k1HC4kWG"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id C679E80179; Wed, 1 Jun 2022 08:02:55 +0200 (CEST) Received: from fllv0016.ext.ti.com (fllv0016.ext.ti.com [198.47.19.142]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 203E182169 for ; Wed, 1 Jun 2022 08:02:51 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=quarantine dis=none) header.from=ti.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=n-francis@ti.com Received: from lelv0266.itg.ti.com ([10.180.67.225]) by fllv0016.ext.ti.com (8.15.2/8.15.2) with ESMTP id 25162jrN028101; Wed, 1 Jun 2022 01:02:45 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1654063365; bh=xT0OGdRegIoT63HlE4ZLMDBkXrBGNO1pYkKrZmF1oqQ=; h=Date:Subject:To:References:From:In-Reply-To; b=k1HC4kWG84oLLt9D7iRdLI3Y8ef+S3Ag3ihA6P4RYyN+HFybciaW331YLOGqei5Ir fimRnWo1sTdNlkkWjblrNwiwjOv8CUnWBztFAH2Yzf316slW5iWbzEM36g88vCpgcU yukk2JJ54GE1MStMdAHa/G8qWGynXUyJpVKhgPQM= Received: from DLEE114.ent.ti.com (dlee114.ent.ti.com [157.170.170.25]) by lelv0266.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 25162jmB116648 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 1 Jun 2022 01:02:45 -0500 Received: from DLEE107.ent.ti.com (157.170.170.37) by DLEE114.ent.ti.com (157.170.170.25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2308.14; Wed, 1 Jun 2022 01:02:45 -0500 Received: from lelv0327.itg.ti.com (10.180.67.183) by DLEE107.ent.ti.com (157.170.170.37) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2308.14 via Frontend Transport; Wed, 1 Jun 2022 01:02:44 -0500 Received: from [172.24.218.149] (ileax41-snat.itg.ti.com [10.172.224.153]) by lelv0327.itg.ti.com (8.15.2/8.15.2) with ESMTP id 25162h2q123639; Wed, 1 Jun 2022 01:02:44 -0500 Message-ID: <388bbf72-49f9-1ec6-1cd2-cd9249ef0b07@ti.com> Date: Wed, 1 Jun 2022 11:32:42 +0530 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.8.1 Subject: Re: [PATCH RFC v2 05/11] ti: etype: x509: Add etype for x509 certificate for K3 devices Content-Language: en-US To: Roger Quadros , References: <20220506043759.8193-1-n-francis@ti.com> <20220506043759.8193-6-n-francis@ti.com> From: Neha Malcom Francis In-Reply-To: Content-Type: text/plain; charset="UTF-8"; format=flowed Content-Transfer-Encoding: 7bit X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.5 at phobos.denx.de X-Virus-Status: Clean Hi Roger, On 31/05/22 14:50, Roger Quadros wrote: > > > On 06/05/2022 07:37, Neha Malcom Francis wrote: >> K3 devices x509 certificate added to certain binaries that allows ROM to > > what binaries? > >> validate the integrity of the image. Etype that generates an x509 >> certificate depending on boot flow added. > > Could you please explain in more detail as to what exactly is happening here. > > What do you mean by "depending on boot flow"? > I will reformat the commit messages accordingly. >> >> Signed-off-by: Neha Malcom Francis >> --- >> tools/binman/entries.rst | 15 ++ >> tools/binman/etype/x509_cert.py | 248 ++++++++++++++++++++++++++++ >> tools/binman/ftest.py | 7 + >> tools/binman/test/232_x509_cert.dts | 18 ++ >> tools/k3_gen_x509_cert.sh | 10 +- >> 5 files changed, 293 insertions(+), 5 deletions(-) >> create mode 100644 tools/binman/etype/x509_cert.py >> create mode 100644 tools/binman/test/232_x509_cert.dts >> >> diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst >> index 0c6d82fce8..dfa281e49f 100644 >> --- a/tools/binman/entries.rst >> +++ b/tools/binman/entries.rst >> @@ -1890,6 +1890,21 @@ and kernel are genuine. >> >> >> >> +Entry: x509cert: x509 certificate for K3 devices >> +------------------------------------------------ >> + > > x509 is a generic standard. Can this be made usable by other vendors as well or > is it very specific to TI? > If this is TI specific then I'd suggest a "ti-" prefix to the entry name. > >> +Properties / Entry arguments: >> + - content: Phandle of binary to sign >> + - output: Name of the final output file > > why do you need output property? > That is not required, I had later changed it to always using certificate.bin. Will make the necessary changes. >> + - key_file: File with key inside it. If not provided, script generates RSA degenerate key >> + - core: Target core ID on which image would be running >> + - load: Target load address of the binary in hex >> + >> + Output files: >> + - certificate.bin: Signed certificate binary >> + >> + >> + >> Entry: x86-reset16: x86 16-bit reset code for U-Boot >> ---------------------------------------------------- >> >> diff --git a/tools/binman/etype/x509_cert.py b/tools/binman/etype/x509_cert.py >> new file mode 100644 >> index 0000000000..0009973155 >> --- /dev/null >> +++ b/tools/binman/etype/x509_cert.py >> @@ -0,0 +1,248 @@ >> +# SPDX-License-Identifier: GPL-2.0+ >> +# Copyright (c) 2018 Google, Inc >> +# Written by Simon Glass >> +# >> + >> +# Support for a x509 certificate for signing K3 devices >> + >> +import os >> +from collections import OrderedDict >> +from subprocess import Popen, PIPE >> +from sys import stderr, stdout >> + >> +import asn1 >> +from Crypto.PublicKey import RSA >> +from cryptography.hazmat.backends import default_backend >> +from cryptography.hazmat.primitives import serialization >> + >> +from binman.etype.collection import Entry_collection >> +from dtoc import fdt_util >> +from patman import tools >> + >> +temp_x509 = "x509-temp.cert" >> +cert = "certificate.bin" >> +rand_key = "eckey.pem" >> +bootcore_opts = 0 >> +bootcore = 0 >> +debug_type = 0 >> + >> + >> +class Entry_x509_cert(Entry_collection): >> + """ An entry which contains a x509 certificate >> + >> + Properties / Entry arguments: >> + - content: Phandle of binary to sign >> + - key_file: File with key inside it. If not provided, script generates RSA degenerate key >> + - core: Target core ID on which image would be running >> + - load: Target load address of the binary in hex >> + >> + Output files: >> + - certificate.bin: Signed certificate binary""" >> + >> + def __init__(self, section, etype, node): >> + super().__init__(section, etype, node) >> + self.key_file = fdt_util.GetString(self._node, 'key-file', "") >> + self.core = fdt_util.GetInt(self._node, 'core', 0) >> + self.load_addr = fdt_util.GetInt(self._node, 'load', 0x41c00000) >> + >> + def ReadNode(self): >> + super().ReadNode() >> + if self.key_file == "": >> + self.degen_key = True >> + else: >> + self.degen_key = False >> + >> + def _CreateCertificate(self): >> + """Create certificate for legacy boot flow""" >> + if self.degen_key == True: >> + gen_degen_key() >> + self.key_file = rand_key >> + >> + sha_val = get_sha_val("intermediate-sysfw.bin") >> + bin_size = get_file_size("intermediate-sysfw.bin") >> + addr = "%08x" % self.load_addr >> + if self.core == 0: >> + cert_type = 2 >> + elif self.core == 16: >> + cert_type = 1 >> + else: >> + cert_type = 2 >> + debug_type = 0 >> + >> + gen_template() >> + gen_cert(bin_size, sha_val, cert_type, bootcore_opts, >> + self.core, addr, debug_type, self.key_file) >> + >> + return tools.read_file("certificate.bin") >> + >> + def ObtainContents(self): >> + self.image = self.GetContents(False) >> + if self.image is None: >> + return False >> + f = open("intermediate-sysfw.bin", "wb") >> + f.write(self.image) >> + f.close() >> + self.SetContents(self._CreateCertificate()) >> + return True >> + >> + def ProcessContents(self): >> + data = self._CreateCertificate() >> + return self.ProcessContentsUpdate(data) > > Why do you need _CreateCertificate() and ProcessContents()? > Just have one ObtainContents() and try to get rid of all the intermediate files. > I used etype/vblock.py as a reference. I will clean up this etype further. >> + >> + >> +def get_sha_val(binary_file): >> + process = Popen(['openssl', 'dgst', '-sha512', '-hex', >> + binary_file], stdout=PIPE, stderr=PIPE) >> + stdout, stderr = process.communicate() >> + sha_val = stdout.split()[1] >> + return sha_val >> + >> + >> +def get_file_size(binary_file): >> + return os.path.getsize(binary_file) >> + >> + >> +def gen_degen_template(): >> + with open("degen-template.txt", 'w+', encoding='utf-8') as f: >> + degen_temp = """ >> +asn1=SEQUENCE:rsa_key >> + >> +[rsa_key] >> +version=INTEGER:0 >> +modulus=INTEGER:0xDEGEN_MODULUS >> +pubExp=INTEGER:1 >> +privExp=INTEGER:1 >> +p=INTEGER:0xDEGEN_P >> +q=INTEGER:0xDEGEN_Q >> +e1=INTEGER:1 >> +e2=INTEGER:1 >> +coeff=INTEGER:0xDEGEN_COEFF""" >> + f.write(degen_temp) >> + >> + >> +def gen_template(): >> + """Generate x509 Template""" >> + with open("x509-template.txt", "w+", encoding='utf-8') as f: >> + x509template = """ >> +[ req ] >> +distinguished_name = req_distinguished_name >> +x509_extensions = v3_ca >> +prompt = no >> +dirstring_type = nobmp >> + >> +[ req_distinguished_name ] >> +C = US >> +ST = TX >> +L = Dallas >> +O = Texas Instruments Incorporated >> +OU = Processors >> +CN = TI support >> +emailAddress = support@ti.com >> + >> +[ v3_ca ] >> +basicConstraints = CA:true >> +1.3.6.1.4.1.294.1.1 = ASN1:SEQUENCE:boot_seq >> +1.3.6.1.4.1.294.1.2 = ASN1:SEQUENCE:image_integrity >> +1.3.6.1.4.1.294.1.3 = ASN1:SEQUENCE:swrv >> +# 1.3.6.1.4.1.294.1.4 = ASN1:SEQUENCE:encryption >> +1.3.6.1.4.1.294.1.8 = ASN1:SEQUENCE:debug >> + >> +[ boot_seq ] >> +certType = INTEGER:TEST_CERT_TYPE >> +bootCore = INTEGER:TEST_BOOT_CORE >> +bootCoreOpts = INTEGER:TEST_BOOT_CORE_OPTS >> +destAddr = FORMAT:HEX,OCT:TEST_BOOT_ADDR >> +imageSize = INTEGER:TEST_IMAGE_LENGTH >> + >> +[ image_integrity ] >> +shaType = OID:2.16.840.1.101.3.4.2.3 >> +shaValue = FORMAT:HEX,OCT:TEST_IMAGE_SHA_VAL >> + >> +[ swrv ] >> +swrv = INTEGER:0 >> + >> +# [ encryption ] >> +# initalVector = FORMAT:HEX,OCT:TEST_IMAGE_ENC_IV >> +# randomString = FORMAT:HEX,OCT:TEST_IMAGE_ENC_RS >> +# iterationCnt = INTEGER:TEST_IMAGE_KEY_DERIVE_INDEX >> +# salt = FORMAT:HEX,OCT:TEST_IMAGE_KEY_DERIVE_SALT >> + >> +[ debug ] >> +debugUID = FORMAT:HEX,OCT:0000000000000000000000000000000000000000000000000000000000000000 >> +debugType = INTEGER:TEST_DEBUG_TYPE >> +coreDbgEn = INTEGER:0 >> +coreDbgSecEn = INTEGER:0""" >> + f.write(x509template) >> + >> + >> +def parse_key(inp_key, section): >> + parsed_key = "" >> + section_true = False >> + with open(inp_key, 'r') as file: >> + for line in file: >> + if section in line: >> + section_true = True >> + elif section_true: >> + if " " not in line: >> + break >> + else: >> + parsed_key += line.replace(":", "").replace(" ", "") >> + return parsed_key.replace("\n", "") >> + >> + >> +def gen_degen_key(): >> + """Generate a 4096 bit RSA key""" >> + try: >> + # generates 1024 bit PEM encoded RSA key in PKCS#1 format >> + private_key = RSA.generate(1024) >> + f = open('key.pem', 'wb') >> + f.write(private_key.exportKey('PEM')) >> + f.close() >> + except: >> + raise(Exception) >> + >> + try: >> + process = Popen(['openssl', 'rsa', '-in', 'key.pem', >> + '-text', '-out', 'key.txt'], stdout=PIPE, stderr=PIPE) >> + stdout, stderr = process.communicate() >> + except: >> + raise(stderr) >> + >> + DEGEN_MODULUS = parse_key("key.txt", "modulus") >> + DEGEN_P = parse_key("key.txt", "prime1") >> + DEGEN_Q = parse_key("key.txt", "prime2") >> + DEGEN_COEFF = parse_key("key.txt", "coefficient") >> + >> + gen_degen_template() >> + >> + with open("degen-template.txt", 'r') as file_input: >> + with open("degenerateKey.txt", 'w') as file_output: >> + for line in file_input: >> + s = line.replace("DEGEN_MODULUS", DEGEN_MODULUS).replace( >> + "DEGEN_P", DEGEN_P).replace("DEGEN_Q", DEGEN_Q).replace("DEGEN_COEFF", DEGEN_COEFF) >> + file_output.write(s) >> + >> + try: >> + process = Popen(['openssl', 'asn1parse', '-genconf', 'degenerateKey.txt', >> + '-out', 'degenerateKey.der'], stdout=PIPE, stderr=PIPE) >> + stdout, stderr = process.communicate() >> + except: >> + raise(stderr) >> + >> + try: >> + process = Popen(['openssl', 'rsa', '-in', 'degenerateKey.der', >> + '-inform', 'DER', '-outform', 'PEM', '-out', rand_key]) >> + stdout, stderr = process.communicate() >> + except: >> + raise(stderr) >> + >> + >> +def gen_cert(bin_size, sha_val, cert_type, bootcore_opts, bootcore, addr, debug_type, key): >> + with open(temp_x509, "w") as output_file: >> + with open("x509-template.txt", "r") as input_file: >> + for line in input_file: >> + output_file.write(line.replace("TEST_IMAGE_LENGTH", str(bin_size)).replace("TEST_IMAGE_SHA_VAL", sha_val.decode("utf-8")).replace("TEST_CERT_TYPE", str(cert_type)).replace( >> + "TEST_BOOT_CORE_OPTS", str(bootcore_opts)).replace("TEST_BOOT_CORE", str(bootcore)).replace("TEST_BOOT_ADDR", str(addr)).replace("TEST_DEBUG_TYPE", str(debug_type))) >> + process = Popen(['openssl', 'req', '-new', '-x509', '-key', key, '-nodes', '-outform', >> + 'DER', '-out', cert, '-config', temp_x509, '-sha512'], stdout=PIPE, stderr=PIPE) >> + stdout, stderr = process.communicate() >> diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py >> index 5ff294a386..d8ee592250 100644 >> --- a/tools/binman/ftest.py >> +++ b/tools/binman/ftest.py >> @@ -96,6 +96,7 @@ ENV_DATA = b'var1=1\nvar2="2"' >> PRE_LOAD_MAGIC = b'UBSH' >> PRE_LOAD_VERSION = 0x11223344.to_bytes(4, 'big') >> PRE_LOAD_HDR_SIZE = 0x00001000.to_bytes(4, 'big') >> +X509_DATA = b'filetobesigned' >> >> # Subdirectory of the input dir to use to put test FDTs >> TEST_FDT_SUBDIR = 'fdts' >> @@ -200,6 +201,7 @@ class TestFunctional(unittest.TestCase): >> TestFunctional._MakeInputFile('fw_dynamic.bin', OPENSBI_DATA) >> TestFunctional._MakeInputFile('sysfw.bin', TI_SYSFW_DATA) >> TestFunctional._MakeInputFile('scp.bin', SCP_DATA) >> + TestFunctional._MakeInputFile('tosign.bin', X509_DATA) >> >> # Add a few .dtb files for testing >> TestFunctional._MakeInputFile('%s/test-fdt1.dtb' % TEST_FDT_SUBDIR, >> @@ -5537,5 +5539,10 @@ fdt fdtmap Extract the devicetree blob from the fdtmap >> data = self._DoReadFile('232_ti_sysfw.dts') >> self.assertEqual(TI_SYSFW_DATA, data[:len(TI_SYSFW_DATA)]) >> >> + def testX509Cert(self): >> + """Test an image with the default x509 certificate header""" >> + data = self._DoReadFile('232_x509_cert.dts') >> + self.assertEqual(X509_DATA, data[938:938 + len(X509_DATA)]) > > what is 938? > > Isn't it easier to just assert that _DoReadFile('232_x509_cert.dts') is greater than len(X509_DATA)? > >> + >> if __name__ == "__main__": >> unittest.main() >> diff --git a/tools/binman/test/232_x509_cert.dts b/tools/binman/test/232_x509_cert.dts >> new file mode 100644 >> index 0000000000..f768568ca7 >> --- /dev/null >> +++ b/tools/binman/test/232_x509_cert.dts >> @@ -0,0 +1,18 @@ >> +// SPDX-License-Identifier: GPL-2.0+ >> + >> +/dts-v1/; >> + >> +/ { >> + #address-cells = <1>; >> + #size-cells = <1>; >> + >> + binman { >> + x509-cert { >> + content = <&image>; >> + }; >> + >> + image: blob-ext { >> + filename = "tosign.bin"; >> + }; >> + }; >> +}; >> diff --git a/tools/k3_gen_x509_cert.sh b/tools/k3_gen_x509_cert.sh >> index 298cec1313..b6ef5a2de3 100755 >> --- a/tools/k3_gen_x509_cert.sh >> +++ b/tools/k3_gen_x509_cert.sh >> @@ -109,7 +109,7 @@ gen_degen_key() { >> openssl asn1parse -genconf degenerateKey.txt -out degenerateKey.der >>/dev/null 2>&1 >> openssl rsa -in degenerateKey.der -inform DER -outform PEM -out $RAND_KEY >>/dev/null 2>&1 >> KEY=$RAND_KEY >> - rm key.pem key.txt degen-template.txt degenerateKey.txt degenerateKey.der >> + #rm key.pem key.txt degen-template.txt degenerateKey.txt degenerateKey.der >> } >> >> declare -A options_help >> @@ -246,7 +246,7 @@ gen_cert >> cat $CERT $BIN > $OUTPUT >> >> # Remove all intermediate files >> -rm $TEMP_X509 $CERT x509-template.txt >> -if [ "$KEY" == "$RAND_KEY" ]; then >> - rm $RAND_KEY >> -fi >> +#rm $TEMP_X509 $CERT x509-template.txt >> +#if [ "$KEY" == "$RAND_KEY" ]; then >> +# rm $RAND_KEY >> +#fi > > Why these changes? > Maybe you should include them within > "ifndef CONFIG_BINMAN ... endif" to avoid breaking platforms not using BINMAN. > > cheers, > -roger -- Thanking You Neha Malcom Francis