From 85b6e0d91bb5e88e1e2ddef892116737d2650730 Mon Sep 17 00:00:00 2001 From: Marek Vitula Date: Thu, 4 May 2023 13:27:50 +0200 Subject: [PATCH] Add missing signature provider example --- examples/signature_provider/.gitignore | 1 + examples/signature_provider/README.md | 92 ++++++++++++++ examples/signature_provider/dat/dck.pub | 8 ++ .../signature_provider/dat/dck_rsa_2048.yml | 119 ++++++++++++++++++ .../signature_provider/dat/p0_cert0_2048.pub | 8 ++ .../signature_provider/dat/p1_cert0_2048.pub | 8 ++ .../hsm/hsm_k0_cert0_2048.pem | 28 +++++ .../hsm/hsm_k1_cert0_2048.pem | 28 +++++ examples/signature_provider/hsm/sahsm.py | 79 ++++++++++++ examples/signature_provider/hsm/sasp.py | 59 +++++++++ .../mbimg/mbimg_rsa_2048.yml | 36 ++++++ .../mbimg/my_application.bin | Bin 0 -> 16704 bytes .../mbimg/root_k0_signed_cert0_noca.der.cert | Bin 0 -> 1117 bytes 13 files changed, 466 insertions(+) create mode 100644 examples/signature_provider/.gitignore create mode 100644 examples/signature_provider/README.md create mode 100644 examples/signature_provider/dat/dck.pub create mode 100644 examples/signature_provider/dat/dck_rsa_2048.yml create mode 100644 examples/signature_provider/dat/p0_cert0_2048.pub create mode 100644 examples/signature_provider/dat/p1_cert0_2048.pub create mode 100644 examples/signature_provider/hsm/hsm_k0_cert0_2048.pem create mode 100644 examples/signature_provider/hsm/hsm_k1_cert0_2048.pem create mode 100644 examples/signature_provider/hsm/sahsm.py create mode 100644 examples/signature_provider/hsm/sasp.py create mode 100644 examples/signature_provider/mbimg/mbimg_rsa_2048.yml create mode 100644 examples/signature_provider/mbimg/my_application.bin create mode 100644 examples/signature_provider/mbimg/root_k0_signed_cert0_noca.der.cert 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 0000000000000000000000000000000000000000..9170e7618a9cad864d15171946f5385b31b0cc5c GIT binary patch literal 16704 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 GUi)|PZ}7GN literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..6bc01ebc68512d7358aef6f0e09778c6949c9e1c GIT binary patch literal 1117 zcmXqLVu>_pVs>1>%*4pV#9?!ofnnFKd$$aD**LY@JlekVGBR?rG8i;=7;+nMvN4CU zun99c`@uLIJWO7}Fb+EpQ*e|ap8*d@85a+$uXAW{xFL@L7l_Zz!yM%AYbapA2jVgF zu;*12=q2ap8tNP9!mZ+D6jR8~OiId0jW0DG5~T7pxnXa)FwtH+9pBs zMQ2{UZ2w?!b;`HY6L#6JbKWOpY~c((aPt9+pPfNaAG*RmwMA0)u$5+l+VxkD%eOQ