diff --git a/examples/signature_provider/.gitignore b/examples/signature_provider/.gitignore new file mode 100644 index 00000000..f59ec20a --- /dev/null +++ b/examples/signature_provider/.gitignore @@ -0,0 +1 @@ +* \ No newline at end of file diff --git a/examples/signature_provider/README.md b/examples/signature_provider/README.md new file mode 100644 index 00000000..c27d67fb --- /dev/null +++ b/examples/signature_provider/README.md @@ -0,0 +1,92 @@ +# Signature Provider Integration + +This example demonstrates how to use a custom remote signing service for signing data such as Debug Credential file or Masterboot image. + +## 1. Content +This chapter describes the content of this directory + +### 1.1 Signature Provider +Content of the `hsm` directory represents the remote side of things + +`hsm/sahsm.py` represents a remote signing service + +`hsm/sasp.py` is the custom Signature Provider, an interface to the signing service. +It contains a class derived from `spsdk.crypto.SignatureProvider` + +- the derived class has to implement: + - `sp_type: str`: class attribute that identifies the concrete implementation of SignatureProvider + - `sign(bytes) -> bytes`: method which performs the actual signing + - `signature_length -> str`: property which returns a length of a signature +- the derived class can also optionally implement: + - `info() -> str`: method which returns information about the signature provider (for debugging purposes). The default implementation returns a class name as a string + - `verify_public_key(bytes) -> bool`: method which verifies if a given public key matches a private key. If not implemented, the `SPSDKUnsupportedOperation` exceptipon is raised. + +> Omitting the implementation of optional methods such as `info()` or `verify(bytes)` does not break the functionality of application. + +### 1.2 Debug Credentials +Content of the `dat` directory holds the files required for running the example for Debug Credentials application + + `dat/dck_rsa_2048.yml` +- configuration file for `nxpdebugmbox gendc` command +- new configuration field `sign_provider`/`signProvider`(both accepted) has been introduced +- new configuration field `rot_id`: + - due to the nature of creating Debug Credential file we need to know in advance which of the private keys will be used to perform the actual signing + - `rot_id` is a 0-based index representing the private key that will be used with respect to `rot_meta` + - e.g.: if we want to use a private key that corresponds to the public key `p1_cert0_2048.pub`, `rot_id` has to be set to `1` + +### 1.3 Masterboot Image +Content of the `mbimg` directory holds the files required for running the example for Masterboot Image application + + `mbimg/mbimg_rsa_2048.yml` + - configuration file for `nxpimage mbi export` command + - new configuration field `sign_provider`/`signProvider`(both accepted) has been introduced + - the `sign_provider`/`signProvider` and `mainCertPrivateKeyFile` configuration fields are mutually exclusive as they have the same purpose + + +## 2. How to run this example +### 2.1 Remote signature service + +- install two additional dependencies: + - `pip install flask requests` +- run the custom HSM (a flask application) in a separate shell: + - `python hsm\sahsm.py` + +### 2.2 Debug Cedentials +The steps required for signing generated debug certificate with remote signing service: + + - Check the configuration file + - `dat/dck_rsa_2048.yml` config file is preconfigured to use `sasp` signature provider + - see the [next chapter](#3-signature-provider-config-values) for better understanding of the configuration values + > For comparison, you may try to use signing a local file, to do so, comment out line 115 in `dat/dck_rsa_2048.yml` file and uncomment line 114 or 118 (the have the same effect) + - Generate signed debug certificate + - `nxpdebugmbox gendc --config dat/dck_rsa_2048.yml --plugin hsm/sasp.py my.dc` + + > Use `--plugin` parameter in order to integrate custom signature provider + + > Use `--force` flag if you run the example multiple times + + +### 2.2 Masterboot image +The steps required for signing generated masteboot image with remote signing service: + + - Check the configuration file + - `mbimg/mbimg_rsa_2048.yml` config file is preconfigured to use `sasp` signature provider + - see the [next chapter](#3-signature-provider-config-values) for better understanding of the configuration values + > For comparison, you may try to use signing a local file, to do so, comment out line 34 in `mbimg/mbimg_rsa_2048.yml` file and uncomment line 32 or 33 (the have the same effect) + - Generate signed masterboot image + - `nxpimage mbi export --plugin hsm/sasp.py mbimg/mbimg_rsa_2048.yml` + + > Use `--plugin` parameter in order to integrate custom signature provider + + +## 3 Signature provider config values +The signature provider configuration must meet following rules: + - Configuration key + - key names `sign_provider` or `signProvider` are allowed + + - Configuration value + - format `"type=;=;=;..."` + - the `sp_type` has to match the sp_type class attribute defined in the custom signature provider(`hsm/sasp.py`) + - the remaining key-value pairs are passed to the `__init__` method of the concrete Signature Provider + - e.g.: `"type=file;file_path=private_key.pem"` will instantiate `spsdk.crypto.PlainFileSP(file_path='private_key.pem')` + diff --git a/examples/signature_provider/dat/dck.pub b/examples/signature_provider/dat/dck.pub new file mode 100644 index 00000000..50ead93f --- /dev/null +++ b/examples/signature_provider/dat/dck.pub @@ -0,0 +1,8 @@ +-----BEGIN RSA PUBLIC KEY----- +MIIBCgKCAQEA1he46CuxkrKa+P+Nu4t796KAyDJLQDQHRCDK2GoOZPjxpKfBTfZL +cDA94hYyLD3WNKkXauz2rN1YpYxyXuSeSow1IfxW5HtZyIq4aOtlURDie0kR35Gw +H9B0wpmgj/Ms3+8plGbtUHmjs50GSXP5LHU+BzxyCosLG7+YJusYfUcRisalox55 +e56F7MFxvA6XVgDWe7Nk2Ydrh0svN7Pzj1lm6yzkxogQ7yyRgLcXdTunzIN0HBta +RZZY05PTX3Li2tCTPeFB0cARr8qS/gtKB7G1kuj2utO5ZBGQ84kE1m45fsbEyOP1 +aNpT5y9OpSy3oIJCNfzHi5JiOqWrlpDeyQIDAQAB +-----END RSA PUBLIC KEY----- diff --git a/examples/signature_provider/dat/dck_rsa_2048.yml b/examples/signature_provider/dat/dck_rsa_2048.yml new file mode 100644 index 00000000..0456d842 --- /dev/null +++ b/examples/signature_provider/dat/dck_rsa_2048.yml @@ -0,0 +1,119 @@ +# DC Block structure +# ============================================ +# ============================================ +# ============================================ +# === Version === +# ============================================ +# === Soc Class === +# ============================================ +# === UUID === +# ============================================ +# === RoT Meta SHA256 of following: === +# === RoT Key0 SHA256 === +# === RoT Key1 SHA256 === +# === RoT Key2 SHA256 === +# === RoT Key3 SHA256 === +# ============================================ +# === Debugger Key DCK (Pub): === +# === Mod: 2048 Exp: 32 === +# ============================================ +# === CC SOCU === +# ============================================ +# === CC VU === +# ============================================ +# === CB === +# ============================================ +# === RoT Key (pub) === +# === Mod: 2048 Exp: 32 === +# ============================================ +# ============================================ +# === Signature of all block === +# === SHA256 of whole block => RSA(RoTK) === +# ============================================ +# ============================================ +# ============================================ + +# ============ SoC Class ============ +# A unique identifier for a set of SoCs that require no SoC-specific differentiation in +# their debug authentication. The main usage is to allow a different set of debug +# domains and options to be negotiated between the device configuration and +# credentials. A class can contain just a single revision of a single SoC model, if the +# granularity of debug control warrants it. +# Examples list of possible settings: +# 0x0001: LPC550x, LPC55s0x, LPC551x, LPC55s1x, LPC552x, LPC55s2x, LPC55s3x, LPC55s6x + +socc: 0x0001 + +# ============ Device UUID ============ +# 128-bit IETF RFC4122 compliant non-sequential Universally Unique Identifier (UUID) +uuid: "E004090E6BDD2155BBCE9E0665805BE3" + +# ============ SoC Usage ============ +# A CC (constraint) value that is a bit mask, and whose bits are used in an +# SoCC-specific manner. These bits are typically used for controlling which debug +# domains are accessed via the authentication protocol, but device-specific debug +# options can be managed in this way also. +cc_socu: 0x03FF + +# ============ Vendor Usage ============ +# A CC (constraint) value that is opaque to the debug authentication protocol itself but +# which can be leveraged by vendors in product-specific ways. +cc_vu: 0x5678 + +# ============ Credential Beacon & Authentication beacon ============ +# A value that is passed through the authentication protocol, which is not interpreted +# by the protocol but is instead made visible to the application being debugged. A +# credential beacon is associated with a DC and is therefore vendor/RoT-signed. An +# authentication beacon is provided and signed by the debugger during the +# authentication process. +cc_beacon: 0 + +# ============ RoT meta-data ============ +# The RoT meta-data required by the device to corroborate; the ROTID sent in the +# DAC, the field in this DC, and any additional RoT state that is not stored within the +# device. This allows different RoT identification, management and revocation +# solutions to be handled. +rot_meta: + - ./p0_cert0_2048.pub + - ./p1_cert0_2048.pub + +# ============ RoT Identifier ============ +# RoTID allows the debugger to infer which RoT public key(s) are acceptable to the +# device. If the debugger cannot or does not provide such a credential, the +# authentication process will fail. +rot_id: 0 + +# ============ Debug Credential Key ============ +# Copyright 2023 NXP +# +# SPDX-License-Identifier: BSD-3-Clause + +# A user-owned key pair. The public part of the key is associated with a DC, the +# private part is held by the user and used to produce signatures during +# authentication. +dck: ./dck.pub + +# ================================================================================================== +# Signature configuration area +# ================================================================================================== +# There are two ways how sign the final DC data blob. +# +# 1. In case that you have available private pair for rot_meta with index rot_id just use first simple style +# to use it by rotk key. As a second way to do same is use sign_provider option with 'type=file'. +# +# 2. For case that Debug Credential files are generated in untrusted environment (without access to RoT private keys), +# there is option to use plugin (example how to create own plugin is in: ./SPSDK/examples/dat/hsm/). The plugin +# has simple interface that allows handle DC data blob into plugin with index of RoT meta public key to get back signed +# DC image. +# +# Those options are exclusive, so only one option could be used to sign the DC. + +# ============ Signature Provider ============ +# To use signing provider examples +# +# sign_provider: 'type=file;file_path=./../hsm/hsm_k0_cert0_2048.pem' +sign_provider: "type=sasp;key_number=0" +# ============ RoT signature private key ============ +# Private key for for the RoT meta chosen by rot_id to sign the image. +# rotk: rotk0.pem + diff --git a/examples/signature_provider/dat/p0_cert0_2048.pub b/examples/signature_provider/dat/p0_cert0_2048.pub new file mode 100644 index 00000000..39d52639 --- /dev/null +++ b/examples/signature_provider/dat/p0_cert0_2048.pub @@ -0,0 +1,8 @@ +-----BEGIN RSA PUBLIC KEY----- +MIIBCgKCAQEApLuDyNSAV8iId3Jb5KE1mKloQ/d2hwxpG6Ek3Kp5EEHCjfQ4PqBY +mSfIeDSJZ4uUfn9mshE3oszq6YfwONWU9mXIPmvrbO9gaLQJU8DZ4AROERiZAdoZ +ND7aQCowAH/G165k010A8+AYNM7XjT43ofxbsKrOgZq0I0FHJzVR3fqU4ePRL+25 +ebyMxXbCaq6LZOnOGkJxarbDtGbaOQhu8BGp7kWKzjIQXMNF6qnc6Tvtb214JN/q +O4qAYDBNT533tXHupAYeZf38r/CnTrbQHZaqsz64w2QK0K/YgFu2c0qHEmT8bJgt +ldrWx162x9blU/x/PMn+lBR2EANl9ex5fwIDAQAB +-----END RSA PUBLIC KEY----- diff --git a/examples/signature_provider/dat/p1_cert0_2048.pub b/examples/signature_provider/dat/p1_cert0_2048.pub new file mode 100644 index 00000000..f509bc33 --- /dev/null +++ b/examples/signature_provider/dat/p1_cert0_2048.pub @@ -0,0 +1,8 @@ +-----BEGIN RSA PUBLIC KEY----- +MIIBCgKCAQEAvraadhXvAoa41bJQp07yGRz4pzy3BIg/kVO/Ypp2gQvw7uSPnLxz +6UhHUZjB3uaer7XTQy2PKMJ+yZ/Qj9pPcnJhz8w5WVVKjzGN3c6OH8nDOvJkt+Qe +AXLqkxtqa/rhZTxN0d1KwFjOJONqrhrBSzSsEKPbpik7jDJwAcUbwY+e+eBukEA+ +KxH4s9h0SUiRbeUDgRVCXkA4ISVQjtL79HW4bghl0FwQ+JE6z4Hk1Xo2B9RA7lbY +E48a3I7HyGhV6vYrIA8RrPCT/vdR6VE+8N79YjoVLo3aLZNBywKMlRF9gIMOBDVT +lR8f77+tj16yJC1ItfvruijkbWswsKYqSQIDAQAB +-----END RSA PUBLIC KEY----- diff --git a/examples/signature_provider/hsm/hsm_k0_cert0_2048.pem b/examples/signature_provider/hsm/hsm_k0_cert0_2048.pem new file mode 100644 index 00000000..5889d045 --- /dev/null +++ b/examples/signature_provider/hsm/hsm_k0_cert0_2048.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCku4PI1IBXyIh3 +clvkoTWYqWhD93aHDGkboSTcqnkQQcKN9Dg+oFiZJ8h4NIlni5R+f2ayETeizOrp +h/A41ZT2Zcg+a+ts72BotAlTwNngBE4RGJkB2hk0PtpAKjAAf8bXrmTTXQDz4Bg0 +zteNPjeh/Fuwqs6BmrQjQUcnNVHd+pTh49Ev7bl5vIzFdsJqrotk6c4aQnFqtsO0 +Zto5CG7wEanuRYrOMhBcw0XqqdzpO+1vbXgk3+o7ioBgME1Pnfe1ce6kBh5l/fyv +8KdOttAdlqqzPrjDZArQr9iAW7ZzSocSZPxsmC2V2tbHXrbH1uVT/H88yf6UFHYQ +A2X17Hl/AgMBAAECggEAbB/IOCGCvBubtwsQ1dgaXcGT9kiPO8UhmEkE8PHT1J/V +G2eZI0IL5Tr/kiapqZUsOntU5Lv4UJs/9ViMjEFkLPZRoOck97OHDDJfjOGgIDGz +K/WBOH323RwEFOmb6Df2Q8rr0u/QmEIWoVLCmKqlyWTiqery8I6ifiFymoGc4p1w +6Y6+PkGjFxrK93EIIx1Jp9iz//tHooPQ8R9uU9A53KutsQe0MquYTfZi92rTwQvr +BhuPIpBN7yDZP244/o31NOzQjfomNlluGjnPLmNofJE8zi8SJfoGn0/f95safCRQ +nQuQUcOptOrVVGA9vKrmRvrFbgHU4DRWscNYrNp+AQKBgQDZO6I+hJOEgMkGnrSm +SUifuZl+e1pZAyRscx2bJhKIEjoayWVJUC8e3usl5E44eZnHVGbscE9mp085p/AX +jmvCXy6Ccemz4V9XZ4eBf7cFOFm1RcE2P6B5ZCsvT15Y6GrsoEnJ5oUk99nkzAq8 +zw1STawWTNIkAjyzBsgTuqAHnwKBgQDCIWDOcCBB3tNsJJeMg3FdwqDwljLAGc28 +35Z5L9IpEC4+Rh+YCI7ye2yFQdYTrZOCH79WWHEu+qX37Fbq4g2rQBCjN21gR2Un +VQcoVKxWrdtx4lmoSYMHZNymGYwWm5d+QJ1Iudm86d4Ime6aDkF8ov41XvOxzaJN +Wt79lFvCIQKBgQCIDpCcpX6bc+n0inxM1gN1ftKDZJD+xTgP8L2vSdY7gWcBFfip +RV5t8GLJNchEGO1W6icYmXMxsUKust9ucZZOhDzmGKCuOE71uHMnia1AyL1vCsRr +zMgen71ogUZvWwp1MCNnIEluEQpZAe8LuIb4cIuC4BSR1xDbdDjmGnJWswKBgGbB +Bh2fCePzztLB95l/hYUMXOWbitdVkSm060/P+RyVHPUHZvexKAC/RayvMWIPETHi +HgPVImusbibxaPxAlN2dNnE+CF3azHbqMbSuRN5IfgwktDI4XuuN/qDIivb4elJw +XxA8lzzASS8iU0Il45HWMFoNnU3yu0LYo4lzerIhAoGAdc7Op5SNGJdzLo6ynUab +HAIzaYcEw2uUU+GGjNnzflxko0tTcbj35D/xtXBMG036JwfbK5t6A1JLE1XPt2op +kzFj/QN4CyUG7Twjt+CKGmSgPb+qYZ6IKjoiOOh1bN9ozdjbaf6cgK6Nwrwgfmu7 +VJhEBdSKjs9m0yMF8YIVSs4= +-----END PRIVATE KEY----- diff --git a/examples/signature_provider/hsm/hsm_k1_cert0_2048.pem b/examples/signature_provider/hsm/hsm_k1_cert0_2048.pem new file mode 100644 index 00000000..6ffd8c42 --- /dev/null +++ b/examples/signature_provider/hsm/hsm_k1_cert0_2048.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC+tpp2Fe8ChrjV +slCnTvIZHPinPLcEiD+RU79imnaBC/Du5I+cvHPpSEdRmMHe5p6vtdNDLY8own7J +n9CP2k9ycmHPzDlZVUqPMY3dzo4fycM68mS35B4BcuqTG2pr+uFlPE3R3UrAWM4k +42quGsFLNKwQo9umKTuMMnABxRvBj5754G6QQD4rEfiz2HRJSJFt5QOBFUJeQDgh +JVCO0vv0dbhuCGXQXBD4kTrPgeTVejYH1EDuVtgTjxrcjsfIaFXq9isgDxGs8JP+ +91HpUT7w3v1iOhUujdotk0HLAoyVEX2Agw4ENVOVHx/vv62PXrIkLUi1++u6KORt +azCwpipJAgMBAAECggEBAIdSPktnyM38Fg7blcsBg1s6aV0RAbPfkWtnBzfJ7igm +9vArkZNfTMfMl35Ya8fjz9lRpPPX0erUBu69zVklSJYmfyzY9iBjGqJ8QPOP6ty3 +ZyXedITfAkN47OUw4NR5kZEptvYglTfiS3N1Qm8DYQAiAa1U9zfxreUOrNc0qzst +mSJ2nZKkoFaXK1D2HHIJjpfj8vYY+TPSqHkhnlWEwBcW0054OU4xkAnISvlfMWbs +6Y/n7rqXHNPs3jFi1Z+DjUwry26xtXBs7OkwEb6QLDpaExGHdviUAgYRNG/l+kqv +GIQZJaaFZkKzaJFm7IUStE7vyasmk7S3jC1PILhNdZkCgYEA66RhucsqRE8rP+Os +6+bly7hJ6cse7UmpdKHQmoDQRr9XF3ybnq2u716SIGNQrx0LVtsIr6mdKMr6i5Vs +mPo2vwlYlR8fAc/SxUOl/U/BWbkAVxVVlNFIY2oP1tUW04+EJ0z95k5BpjPT6JV1 +C9eHqwf/sqYjOAOknq9naHO2gVMCgYEAzzCLuyjv3TFJ5y0+O0Gpy8/oC+z4Tpoc +gP8X+zywLUwou+OcDqfq/Firsjki+vU66V2x0mnUsjTfo1v1le0BSGbNCAuiKdu3 +U9hpl4zEwyvsAh4E1frjnLzeDTlbQX2OdtRC1KEGzD3GxxC+48H+5j8RsZ2O9iF/ +JdGYSeXxZnMCgYEA5D/o7WfO/DXXhd5KbILOykMrTUwUG/LDMpdfEZl+pVjHypdH +wi8oiPKJBthMmiK/DhXCVy0rbw0WHUjS1WdgyjEKXf+0MDQXTD7XtQOhHQCnRLME +n88MmEdvKkBkCO82Kj9YnNHmo1AGjn7ezmaqIk/wLSLicGqO9aqftryG5sMCgYBB +kvXGiJBSC3V+az1U99VLokOo8pksF26KDTKD25NO4tnJjaIoqVCgCVheEeNWViMN +FRBgrgoZVM6rH0G878QGLDMcJsJuSRHewZG5212y/8W0bdfN+ZfsVYJZ4RtWwOxE +A64bKdPC9JJjEpO39gA80x1Af8NtdvCNAacXTGV4rQKBgE6QRKaI7gv14qK081di +XsAorBz9ST9MBTjsmrp1pvOksmFD/8lXoINXNUPQLFDm+W0tkYF0RAcvAa2mv4lE +j9Hb5/sJgfaXB+r8IbIEZG+Sslve96FJ0tprH5Jw1n7wnrq1JH+/Ejb932Lok7dB +LJecj7/NyWIc1LX08JBqrDpX +-----END PRIVATE KEY----- diff --git a/examples/signature_provider/hsm/sahsm.py b/examples/signature_provider/hsm/sahsm.py new file mode 100644 index 00000000..604248d7 --- /dev/null +++ b/examples/signature_provider/hsm/sahsm.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# Copyright 2020-2023 NXP +# +# SPDX-License-Identifier: BSD-3-Clause + +"""Module represent a customer-specific HSM system.""" +import base64 +import os + +from flask import Flask, Response, jsonify, request + +from spsdk import crypto + +APP = Flask(__name__) +THIS_DIR = os.path.dirname(__file__) + + +@APP.route("/signer/", methods=["GET"]) +def signer(num: int) -> Response: + """Route (API) that performing the signing. + + :param num: Index of the key to use (rot_id) + :return: Signature wrapped in json, encoded in base64 + """ + private_key = load_private_key(num) + data_to_sign = base64.b64decode(request.args["data"]) + + signature = sign_data(private_key, data_to_sign) + data = base64.b64encode(signature) + return jsonify({"signature": data.decode("utf-8")}) + + +@APP.route("/verifier/", methods=["GET"]) +def verifier(num: int) -> Response: + """Route (API) that performing the verification. + + :param num: Index of the key to use (rot_id) + :return: Verification status(true/false) wrapped in json + """ + private_key = load_private_key(num) + public_key = private_key.public_key() + + public_key_bytes = base64.b64decode(request.args["public_key"]) + request_public_key = crypto.loaders.load_public_key_from_data(public_key_bytes) + assert isinstance(request_public_key, crypto.RSAPublicKey) + is_matching = public_key.public_numbers().n == request_public_key.public_numbers().n + return jsonify({"is_matching": is_matching}) + + +def sign_data(private_key: crypto.RSAPrivateKey, data: bytes) -> bytes: + """Sign given data with private key. + + :param private_key: Private key to be used for signing + :param data: Data to be signed + :return: Signature as bytes + """ + return private_key.sign( + data=data, + padding=crypto.padding.PKCS1v15(), + algorithm=crypto.hashes.SHA256(), + ) + + +def load_private_key(num: int) -> crypto.RSAPrivateKey: + """Create an instance of RSAPrivateKey by its index. + + :param num: Index of the key to use (rot_id) + """ + private_key_file = os.path.join(THIS_DIR, f"hsm_k{num}_cert0_2048.pem") + private_key = crypto.load_private_key(private_key_file) + # in this example we assume RSA keys + assert isinstance(private_key, crypto.RSAPrivateKey) + return private_key + + +if __name__ == "__main__": + APP.run(debug=True) diff --git a/examples/signature_provider/hsm/sasp.py b/examples/signature_provider/hsm/sasp.py new file mode 100644 index 00000000..e75f4ec5 --- /dev/null +++ b/examples/signature_provider/hsm/sasp.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# Copyright 2020-2023 NXP +# +# SPDX-License-Identifier: BSD-3-Clause + +"""Customer-specific Signature Provider.""" + +import base64 + +import requests # type: ignore + +from spsdk.crypto.signature_provider import SignatureProvider + + +class SuperAwesomeSP(SignatureProvider): + """Signature Provider based on a remote signing service.""" + + # identifier of this signature provider; used in yaml configuration file + sp_type = "sasp" + + def __init__(self, key_number: int) -> None: + """Initialize the Super Awesome SignatureProvider. + + :param key_number: index of the key to use (rot_id from yaml config) + """ + self.url = f"http://127.0.0.1:5000" + self.key_number = key_number + + def sign(self, data: bytes) -> bytes: + """Perform the signing. + + :param data: Data to sign + :return: Signature + """ + endpoint = f"{self.url}/signer/{self.key_number}" + params = {"data": base64.b64encode(data)} + response = requests.get(endpoint, params=params) + signature = response.json()["signature"] + data = base64.b64decode(signature) + return data.zfill(256) + + def verify_public_key(self, public_key: bytes) -> bool: + """Verify if given public key matches private key. + + :param data: Public key to verify + :return: True if public_key is matching private_key, False otherwise + """ + endpoint = f"{self.url}/verifier/{self.key_number}" + params = {"public_key": base64.b64encode(public_key)} + response = requests.get(endpoint, params=params) + is_matching = response.json()["is_matching"] + return is_matching + + @property + def signature_length(self) -> int: + """Return length of the signature.""" + return 256 diff --git a/examples/signature_provider/mbimg/mbimg_rsa_2048.yml b/examples/signature_provider/mbimg/mbimg_rsa_2048.yml new file mode 100644 index 00000000..65af5292 --- /dev/null +++ b/examples/signature_provider/mbimg/mbimg_rsa_2048.yml @@ -0,0 +1,36 @@ +# Copyright 2023 NXP +# +# SPDX-License-Identifier: BSD-3-Clause + +family: rt5xx +outputImageExecutionTarget: External flash (XIP) +outputImageAuthenticationType: Signed +masterBootOutputFile: my_mbi.bin +inputImageFile: my_application.bin +outputImageExecutionAddress: 0 +enableHwUserModeKeys: false +enableTrustZone: false +trustZonePresetFile: "" +mainRootCertId: 0 + +# ---------------------------------------------------------------------------------------------------- +# Signature configuration area +# ---------------------------------------------------------------------------------------------------- +# There are two ways how sign the final masterboot image. +# +# 1. In case that you have available private key, specify in mainCertPrivateKeyFile key +# As a second way to do same is use signProvider option with 'type=file'. +# +# 2. For case that Masterboot image is generated in untrusted environment (without access to RoT private keys), +# there is option to use plugin (example how to create own plugin is in: SPSDK/examples/signature_providerdat/hsm/). The plugin +# has simple interface that allows handle masterboot image binary into plugin with index of RoT private key to get back signed +# masterboot image. +# +# Those options are exclusive, so only one option could be used to sign the masterboot image. + + +#mainCertPrivateKeyFile: .\..\hsm\hsm_k0_cert0_2048.pem +#signProvider: type=file;file_path=.\..\hsm\hsm_k0_cert0_2048.pem +signProvider: type=sasp;key_number=0 # Signature Provider, A signature provider definition. It can be either path to local private key or signature provider string. Caution This is a replacement for mainCertPrivateKeyFile. +rootCertificate0File: root_k0_signed_cert0_noca.der.cert # Root Certificate File 0, Root certificate file index 0. + diff --git a/examples/signature_provider/mbimg/my_application.bin b/examples/signature_provider/mbimg/my_application.bin new file mode 100644 index 00000000..9170e761 Binary files /dev/null and b/examples/signature_provider/mbimg/my_application.bin differ diff --git a/examples/signature_provider/mbimg/root_k0_signed_cert0_noca.der.cert b/examples/signature_provider/mbimg/root_k0_signed_cert0_noca.der.cert new file mode 100644 index 00000000..6bc01ebc Binary files /dev/null and b/examples/signature_provider/mbimg/root_k0_signed_cert0_noca.der.cert differ