samples: tfm_integration: Extend PSA cryptography demo
This commit extends the psa_level_1 sample's use of the PSA Cryptography 1.0 API to demonstrate the following functionality: - Generate a persistent key (secp256r1) - Display the public key based on the private key above - Calculates the SHA256 hash of a payload - Signs the hash with the persistent key - Verifies the signature using the public key - Destroys the key Signed-off-by: Kevin Townsend <kevin.townsend@linaro.org>
This commit is contained in:
parent
45eca4ce10
commit
0d1fe4a161
|
@ -18,3 +18,10 @@ target_sources(app PRIVATE src/util_sformat.c)
|
|||
target_include_directories(app PRIVATE
|
||||
${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/trusted-firmware-m/interface/include
|
||||
)
|
||||
|
||||
# In TF-M, default value of CRYPTO_ENGINE_BUF_SIZE is 0x2080. It causes
|
||||
# insufficient memory failure while verifying signature. Increase it to 0x2400.
|
||||
set_property(TARGET zephyr_property_target
|
||||
APPEND PROPERTY TFM_CMAKE_OPTIONS
|
||||
-DCRYPTO_ENGINE_BUF_SIZE=0x2400
|
||||
)
|
||||
|
|
|
@ -19,4 +19,20 @@ config PSA_SHELL
|
|||
help
|
||||
Enabling this option will make the 'psa' shell command available.
|
||||
|
||||
choice
|
||||
prompt "Private Key"
|
||||
default PRIVATE_KEY_RANDOM
|
||||
|
||||
config PRIVATE_KEY_STATIC
|
||||
bool "Static"
|
||||
help
|
||||
A static key value will be used for the private key.
|
||||
|
||||
config PRIVATE_KEY_RANDOM
|
||||
bool "Random"
|
||||
help
|
||||
A randomly generated value will be used for the private key.
|
||||
|
||||
endchoice
|
||||
|
||||
source "Kconfig.zephyr"
|
||||
|
|
|
@ -25,6 +25,27 @@ multi-thread application.
|
|||
.. _PSA Certified Level 1:
|
||||
https://www.psacertified.org/security-certification/psa-certified-level-1/
|
||||
|
||||
Key Files
|
||||
*********
|
||||
|
||||
``psa_crypto.c``
|
||||
================
|
||||
|
||||
Demonstrates the following workflow:
|
||||
|
||||
- Generate a persistent key: secp256r1 (usage: ecdsa-with-SHA256)
|
||||
- Display the public key based on the private key data above
|
||||
- Calculates the SHA256 hash of a payload
|
||||
- Signs the hash with the persistent key
|
||||
- Verifies the signature using the public key
|
||||
- Destroys the key
|
||||
|
||||
``psa_attestation.c``
|
||||
=====================
|
||||
|
||||
Demonstrates how to request an initial attestation token (IAT) from the TF-M
|
||||
secure processing environment (SPE).
|
||||
|
||||
Building and Running
|
||||
********************
|
||||
|
||||
|
@ -38,6 +59,14 @@ This sample will only build on a Linux or macOS development system
|
|||
- macOS Mojave with gcc-arm-none-eabi-7-2018-q2-update
|
||||
- Ubuntu 18.04 using Zephyr SDK 0.11.2
|
||||
|
||||
TF-M BL2 logs
|
||||
=============
|
||||
Add the following to ``prj.conf`` to see the logs from TF-M BL2:
|
||||
.. code-block:: bash
|
||||
|
||||
CONFIG_TFM_BL2=y
|
||||
CONFIG_TFM_CMAKE_BUILD_TYPE_DEBUG=y
|
||||
|
||||
On MPS2+ AN521:
|
||||
===============
|
||||
|
||||
|
@ -216,24 +245,24 @@ Sample Output
|
|||
[INF] Swap type: none
|
||||
[INF] Swap type: none
|
||||
[INF] Bootloader chainload address offset: 0x80000
|
||||
|
||||
[INF] Jumping to the first image slot
|
||||
[Sec Thread] Secure image initializing!
|
||||
TF-M isolation level is: 1
|
||||
Booting TFM v1.0
|
||||
*** Booting Zephyr OS build v1.12.0-rc1-19787-g7bf29820769f ***
|
||||
[00:00:00.003,000] <inf> app: app_cfg: Creating new config file with UID 0x155cfda7a
|
||||
[00:00:03.517,000] <inf> app: att: System IAT size is: 545 bytes.
|
||||
[00:00:03.517,000] <inf> app: att: Requesting IAT with 64 byte challenge.
|
||||
[00:00:06.925,000] <inf> app: att: IAT data received: 545 bytes.
|
||||
0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
TF-M isolation level is: 0x00000001
|
||||
Booting TFM v1.3.0
|
||||
Jumping to non-secure code...
|
||||
*** Booting Zephyr OS build v2.6.0-rc2-1-g77259223c716 ***
|
||||
[00:00:00.037,000] <inf> app: app_cfg: Creating new config file with UID 0x1055CFDA7A
|
||||
[00:00:03.968,000] <inf> app: att: System IAT size is: 545 bytes.
|
||||
[00:00:03.968,000] <inf> app: att: Requesting IAT with 64 byte challenge.
|
||||
[00:00:05.961,000] <inf> app: att: IAT data received: 545 bytes.
|
||||
|
||||
0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
00000000 D2 84 43 A1 01 26 A0 59 01 D5 AA 3A 00 01 24 FF ..C..&.Y...:..$.
|
||||
00000010 58 40 00 11 22 33 44 55 66 77 88 99 AA BB CC DD X@.."3DUfw......
|
||||
00000020 EE FF 00 11 22 33 44 55 66 77 88 99 AA BB CC DD ...."3DUfw......
|
||||
00000030 EE FF 00 11 22 33 44 55 66 77 88 99 AA BB CC DD ...."3DUfw......
|
||||
00000040 EE FF 00 11 22 33 44 55 66 77 88 99 AA BB CC DD ...."3DUfw......
|
||||
00000050 EE FF 3A 00 01 24 FB 58 20 A0 A1 A2 A3 A4 A5 A6 ..:..$.X .......
|
||||
|
||||
00000060 A7 A8 A9 AA AB AC AD AE AF B0 B1 B2 B3 B4 B5 B6 ................
|
||||
00000070 B7 B8 B9 BA BB BC BD BE BF 3A 00 01 25 00 58 21 .........:..%.X!
|
||||
00000080 01 FA 58 75 5F 65 86 27 CE 54 60 F2 9B 75 29 67 ..Xu_e.'.T`..u)g
|
||||
|
@ -245,43 +274,74 @@ Sample Output
|
|||
000000E0 50 45 04 65 30 2E 30 2E 30 05 58 20 BF E6 D8 6F PE.e0.0.0.X ...o
|
||||
000000F0 88 26 F4 FF 97 FB 96 C4 E6 FB C4 99 3E 46 19 FC .&..........>F..
|
||||
00000100 56 5D A2 6A DF 34 C3 29 48 9A DC 38 06 66 53 48 V].j.4.)H..8.fSH
|
||||
00000110 41 32 35 36 02 58 20 EF FC 32 08 03 06 CA 5A 8C A256.X ..2....Z.
|
||||
00000120 D2 93 C8 46 04 DD 45 3F CA 41 20 47 A8 F7 D4 09 ...F..E?.A G....
|
||||
00000130 24 16 94 38 05 68 B6 A5 01 64 4E 53 50 45 04 65 $..8.h...dNSPE.e
|
||||
00000110 41 32 35 36 02 58 20 AE AA BE 88 46 21 BA 4F ED A256.X ....F!.O.
|
||||
00000120 E9 68 26 05 08 42 FC D0 1E AE 31 EB A9 47 5B D7 .h&..B....1..G[.
|
||||
00000130 5E C0 7F 75 C8 0A 0A A5 01 64 4E 53 50 45 04 65 ^..u.....dNSPE.e
|
||||
00000140 30 2E 30 2E 30 05 58 20 B3 60 CA F5 C9 8C 6B 94 0.0.0.X .`....k.
|
||||
00000150 2A 48 82 FA 9D 48 23 EF B1 66 A9 EF 6A 6E 4A A3 *H...H#..f..jnJ.
|
||||
00000160 7C 19 19 ED 1F CC C0 49 06 66 53 48 41 32 35 36 |......I.fSHA256
|
||||
00000170 02 58 20 D5 3F 25 8F AA 5A 05 33 36 F4 D9 2C D6 .X .?%..Z.36..,.
|
||||
00000180 11 DF 6E 1B 18 B9 03 09 37 01 9D A7 5E FC 57 32 ..n.....7...^.W2
|
||||
00000190 B3 1A 94 3A 00 01 25 01 77 77 77 77 2E 74 72 75 ...:..%.wwww.tru
|
||||
00000170 02 58 20 FC 36 15 76 EE 01 5C FC 2A 2E 23 C6 43 .X .6.v..\.*.#.C
|
||||
00000180 DD 3C C4 5A 68 A7 1A CC 14 7A BF 3F B1 9B E2 D7 .<.Zh....z.?....
|
||||
00000190 E3 74 88 3A 00 01 25 01 77 77 77 77 2E 74 72 75 .t.:..%.wwww.tru
|
||||
000001A0 73 74 65 64 66 69 72 6D 77 61 72 65 2E 6F 72 67 stedfirmware.org
|
||||
000001B0 3A 00 01 24 F7 71 50 53 41 5F 49 4F 54 5F 50 52 :..$.qPSA_IOT_PR
|
||||
000001C0 4F 46 49 4C 45 5F 31 3A 00 01 24 FC 72 30 36 30 OFILE_1:..$.r060
|
||||
000001D0 34 35 36 35 32 37 32 38 32 39 31 30 30 31 30 58 456527282910010X
|
||||
000001E0 40 51 33 D9 87 96 A9 91 55 18 9E BF 14 7A E1 76 @Q3.....U....z.v
|
||||
000001F0 F5 0F A6 3C 7B F2 3A 1B 59 24 5B 2E 67 A8 F8 AB ...<{.:.Y$[.g...
|
||||
00000200 12 B4 2E 09 13 5B BF 35 1F ED 66 E3 36 CF DA CE .....[.5..f.6...
|
||||
00000210 06 03 69 DF C0 DC 4D 2F 17 33 D7 5E BE 73 B9 0E ..i...M/.3.^.s..
|
||||
00000220 08 .
|
||||
[00:00:06.982,000] <inf> app: Generating 256 bytes of random data.
|
||||
0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
00000000 0C 90 D8 0C FA 0F 97 00 29 B2 AE 5C 90 48 3D 39 ........)..\.H=9
|
||||
00000010 00 14 6C A3 84 E2 C0 C9 82 F5 8B A6 E9 38 66 16 ..l..........8f.
|
||||
00000020 EA B7 E7 78 91 0D 6D 87 5B B8 04 0B 8B E0 74 23 ...x..m.[.....t#
|
||||
00000030 7D 11 E2 17 32 34 1A 01 71 24 29 D5 7C 05 B1 11 }...24..q$).|...
|
||||
00000040 A0 97 20 82 03 FF D6 76 9D 6F D5 52 45 C9 E1 17 .. ....v.o.RE...
|
||||
00000050 69 DF 18 B6 8E 0C AA 3B 74 B4 EF 97 D9 0E 82 25 i......;t......%
|
||||
00000060 E1 97 0E 6E 4F 0F DE B9 20 60 34 A4 EA 0D 9A B3 ...nO... `4.....
|
||||
00000070 3F C4 9A CF F3 5E F2 2C 78 96 6F 0E DD E3 E6 CB ?....^.,x.o.....
|
||||
00000080 DC 19 26 A3 E8 8E 07 0E 1E 5B DB 59 B0 05 41 E2 ..&......[.Y..A.
|
||||
00000090 A4 ED 90 35 8B AB 1C B8 00 7E BB 2D 22 FE 7A EA ...5.....~.-".z.
|
||||
000000A0 CF A0 BB DF 4F 2B 32 55 C9 07 0D 3D CE B8 43 78 ....O+2U...=..Cx
|
||||
000000B0 63 33 6C 79 CA 43 3A 4F 0B 93 33 2B B1 D2 B0 A7 c3ly.C:O..3+....
|
||||
000000C0 44 A0 E9 E8 BF FB FD 89 2A 44 7A 60 2D 9B 0F 9E D.......*Dz`-...
|
||||
000000D0 0D B1 0E 9D 5C 60 5D E6 92 78 36 79 68 37 24 C5 ....\`]..x6yh7$.
|
||||
000000E0 57 7F 2E DF 53 D2 7B 3F EE 56 9B 9E BB 39 2C B6 W...S.{?.V...9,.
|
||||
000000F0 AA FF B5 3B 59 4E 40 1D E0 34 50 05 D0 E0 95 12 ...;YN@..4P.....
|
||||
[00:00:07.004,000] <inf> app: Calculating SHA-256 hash of value.
|
||||
0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
00000000 E3 B0 C4 42 98 FC 1C 14 9A FB F4 C8 99 6F B9 24
|
||||
00000010 27 AE 41 E4 64 9B 93 4C A4 95 99 1B 78 52 B8 55
|
||||
000001E0 40 53 A1 B7 9B 18 45 D4 15 4D 84 8C A6 D6 0C 10 @S....E..M......
|
||||
000001F0 A3 88 17 E7 E7 C9 39 72 DC 32 ED A0 DB FB EA 06 ......9r.2......
|
||||
00000200 19 AF AF 6C 88 55 22 84 4E 1B 2F DF 9E 57 C3 12 ...l.U".N./..W..
|
||||
00000210 7E 96 39 DB DC F8 A3 7F C1 BC 6D C2 9B 42 16 40 ~.9.......m..B.@
|
||||
00000220 49 I
|
||||
|
||||
[00:00:06.025,000] <inf> app: Persisting SECP256R1 key as #1
|
||||
[00:00:06.035,000] <inf> app: Retrieving public key for key #1
|
||||
|
||||
0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
00000000 04 2E 36 AC C3 55 DC 17 A5 D8 0C 9B 70 F5 C6 C2 ..6..U......p...
|
||||
00000010 F0 10 67 8E C5 21 D7 D7 43 79 2C CF 41 32 C1 15 ..g..!..Cy,.A2..
|
||||
00000020 33 CC A8 F4 1E ED FB 45 CA 1C E7 C0 FD 07 B2 85 3......E........
|
||||
00000030 B3 AD CC C3 7C 08 81 9B 44 64 E4 EA 9A 2A 38 46 ....|...Dd...*8F
|
||||
00000040 D5 .
|
||||
|
||||
[00:00:07.935,000] <inf> app: Calculating SHA-256 hash of value
|
||||
|
||||
0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
00000000 50 6C 65 61 73 65 20 68 61 73 68 20 61 6E 64 20 Please hash and
|
||||
00000010 73 69 67 6E 20 74 68 69 73 20 6D 65 73 73 61 67 sign this messag
|
||||
00000020 65 2E e.
|
||||
|
||||
|
||||
0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
00000000 9D 08 E3 E6 DB 1C 12 39 C0 9B 9A 83 84 83 72 7A .......9......rz
|
||||
00000010 EA 96 9E 1D 13 72 1E 4D 35 75 CC D4 C8 01 41 9C .....r.M5u....A.
|
||||
|
||||
[00:00:07.945,000] <inf> app: Signing SHA-256 hash
|
||||
|
||||
0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
00000000 E8 59 8C C1 A1 D7 0C 00 34 60 D7 D7 1D 82 DA 26 .Y......4`.....&
|
||||
00000010 5D EC 2A 40 26 8F 20 A3 4B B8 B4 8D 44 25 1D F1 ].*@&. .K...D%..
|
||||
00000020 78 FF CA CB 96 0B B3 31 F0 68 AB BF F3 57 FF A8 x......1.h...W..
|
||||
00000030 DB E6 02 01 59 22 5D 53 13 81 63 31 3C 75 61 92 ....Y"]S..c1<ua.
|
||||
|
||||
[00:00:09.919,000] <inf> app: Verifying signature for SHA-256 hash
|
||||
[00:00:14.559,000] <inf> app: Signature verified.
|
||||
[00:00:14.570,000] <inf> app: Destroyed persistent key #1
|
||||
[00:00:14.574,000] <inf> app: Generating 256 bytes of random data.
|
||||
|
||||
0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
00000000 30 13 B1 67 10 2E 2B 7A 45 A7 89 32 80 89 DB 05 0..g..+zE..2....
|
||||
00000010 30 93 CF F0 03 9A BA 92 0C A4 54 46 96 A4 C2 A9 0.........TF....
|
||||
00000020 11 A2 0B F6 3A C5 5A FB 55 51 4F CB C5 7D 02 71 ....:.Z.UQO..}.q
|
||||
00000030 19 AA A0 62 36 AA 69 5F 8E 93 A8 9B DB 8C AF 7C ...b6.i_.......|
|
||||
00000040 A0 68 C7 60 48 1C 30 51 20 2E AD B6 91 22 38 14 .h.`H.0Q ...."8.
|
||||
00000050 87 00 F6 59 18 81 DB 6B E0 67 95 0C FF 67 B2 1D ...Y...k.g...g..
|
||||
00000060 9E 15 B6 46 94 F0 08 15 5F C8 B7 61 72 34 28 18 ...F...._..ar4(.
|
||||
00000070 BA D1 41 2B D3 5B C7 72 87 89 70 E4 34 6D 40 B7 ..A+.[.r..p.4m@.
|
||||
00000080 B2 38 77 C9 A9 C3 81 18 3C 67 AD 30 CC B4 CE 77 .8w.....<g.0...w
|
||||
00000090 54 11 D6 8B FC 18 D1 7B 26 D3 45 00 67 23 E7 F2 T......{&.E.g#..
|
||||
000000A0 5C 59 CB 63 8F C5 8C 2F 01 CC 09 CE 06 85 4D DC \Y.c.../......M.
|
||||
000000B0 33 41 48 F8 01 8D DA 39 F9 DB 71 0D 80 E6 53 42 3AH....9..q...SB
|
||||
000000C0 58 B0 A8 50 6D 5E 11 B1 EC 53 5E FA 23 AC 7A 0D X..Pm^...S^.#.z.
|
||||
000000D0 EF AC 98 76 68 82 4C 48 8E B4 51 D4 31 78 AE 52 ...vh.LH..Q.1x.R
|
||||
000000E0 7F F2 19 0D 57 6B C7 5B 77 77 36 E7 87 E2 DA 74 ....Wk.[ww6....t
|
||||
000000F0 BF BB 83 5F 8F 94 83 21 28 3A A6 B9 5A 73 18 E2 ..._...!(:..Zs..
|
||||
|
|
|
@ -12,6 +12,7 @@ tests:
|
|||
harness_config:
|
||||
type: multi_line
|
||||
regex:
|
||||
- "Creating new config file with UID"
|
||||
- "System IAT size is"
|
||||
- "Generating 256 bytes of random data"
|
||||
- "Retrieving public key for key #1"
|
||||
- "Signature verified"
|
||||
- "Destroyed persistent key #1"
|
||||
- "Generating 256 bytes of random data."
|
||||
|
|
|
@ -35,15 +35,9 @@ void main(void)
|
|||
att_test();
|
||||
|
||||
/* Crypto tests */
|
||||
crp_test();
|
||||
crp_test_rng();
|
||||
crp_test_sha256();
|
||||
|
||||
/* Dump any queued log messages, and wait for system events. */
|
||||
while (1) {
|
||||
al_dump_log();
|
||||
}
|
||||
|
||||
while (1) {
|
||||
|
||||
}
|
||||
al_dump_log();
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include <logging/log_ctrl.h>
|
||||
#include <logging/log.h>
|
||||
|
||||
#include "psa/crypto.h"
|
||||
#include "psa_crypto.h"
|
||||
#include "util_app_log.h"
|
||||
#include "util_sformat.h"
|
||||
|
@ -16,6 +15,498 @@
|
|||
/** Declare a reference to the application logging interface. */
|
||||
LOG_MODULE_DECLARE(app, CONFIG_LOG_DEFAULT_LEVEL);
|
||||
|
||||
/* Formatting details for displaying hex dumps. */
|
||||
struct sf_hex_tbl_fmt crp_fmt = {
|
||||
.ascii = true,
|
||||
.addr_label = true,
|
||||
.addr = 0
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Extracts the public key from the specified persistent key id.
|
||||
*
|
||||
* @param key_id The permament identifier for the generated key.
|
||||
* @param key Pointer to the buffer where the public key data
|
||||
* will be written.
|
||||
* @param key_buf_size Size of key buffer in bytes.
|
||||
* @param key_len Number of bytes written into key by this function.
|
||||
*/
|
||||
static psa_status_t crp_get_pub_key(psa_key_id_t key_id,
|
||||
uint8_t *key, size_t key_buf_size,
|
||||
size_t *key_len)
|
||||
{
|
||||
psa_status_t status;
|
||||
psa_key_handle_t key_handle;
|
||||
|
||||
LOG_INF("Retrieving public key for key #%d", key_id);
|
||||
al_dump_log();
|
||||
|
||||
/* Now try to re-open the persisted key based on the key ID. */
|
||||
status = al_psa_status(
|
||||
psa_open_key(key_id, &key_handle),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to open persistent key #%d", key_id);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Export the persistent key's public key part. */
|
||||
status = al_psa_status(
|
||||
psa_export_public_key(key_handle, key, key_buf_size, key_len),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to export public key.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Display the binary key data for debug purposes. */
|
||||
sf_hex_tabulate_16(&crp_fmt, key, *key_len);
|
||||
|
||||
/* Close the key to free up the volatile slot. */
|
||||
status = al_psa_status(
|
||||
psa_close_key(key_handle),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to close persistent key.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
return status;
|
||||
err:
|
||||
al_dump_log();
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stores a new persistent secp256r1 key (usage: ecdsa-with-SHA256)
|
||||
* in ITS, associating it with the specified unique key identifier.
|
||||
*
|
||||
* This function will store a new persistent secp256r1 key in internal trusted
|
||||
* storage. Cryptographic operations can then be performed using the key
|
||||
* identifier (key_id) associated with this persistent key. Only the 32-byte
|
||||
* private key needs to be supplied, the public key can be derived using
|
||||
* the supplied private key value.
|
||||
*
|
||||
* @param key_id The permament identifier for the generated key.
|
||||
* @param key_usage The usage policy for the key.
|
||||
* @param key_data Pointer to the 32-byte private key data.
|
||||
*/
|
||||
static psa_status_t crp_gen_key_secp256r1(psa_key_id_t key_id,
|
||||
psa_key_usage_t key_usage,
|
||||
uint8_t *key_data)
|
||||
{
|
||||
psa_status_t status = PSA_SUCCESS;
|
||||
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
psa_key_type_t key_type =
|
||||
PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1);
|
||||
psa_algorithm_t alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
|
||||
psa_key_handle_t key_handle;
|
||||
size_t key_len = 32;
|
||||
size_t data_len;
|
||||
uint8_t data_out[65] = { 0 }; /* ECDSA public key = 65 bytes. */
|
||||
int comp_result;
|
||||
|
||||
LOG_INF("Persisting SECP256R1 key as #%d", (uint32_t)key_id);
|
||||
al_dump_log();
|
||||
|
||||
/* Setup the key's attributes before the creation request. */
|
||||
psa_set_key_id(&key_attributes, key_id);
|
||||
psa_set_key_usage_flags(&key_attributes, key_usage);
|
||||
psa_set_key_algorithm(&key_attributes, alg);
|
||||
psa_set_key_type(&key_attributes, key_type);
|
||||
|
||||
/* Import the private key, creating the persistent key on success */
|
||||
status = al_psa_status(
|
||||
psa_import_key(&key_attributes, key_data, key_len, &key_handle),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to import key.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Close the key to free up the volatile slot. */
|
||||
status = al_psa_status(
|
||||
psa_close_key(key_handle),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to close persistent key.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Try to retrieve the public key. */
|
||||
status = crp_get_pub_key(key_id, data_out, sizeof(data_out), &data_len);
|
||||
|
||||
/* Export the private key if usage includes PSA_KEY_USAGE_EXPORT. */
|
||||
if (key_usage & PSA_KEY_USAGE_EXPORT) {
|
||||
/* Re-open the persisted key based on the key ID. */
|
||||
status = al_psa_status(
|
||||
psa_open_key(key_id, &key_handle),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to open persistent key #%d", key_id);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Read the original (private) key data back. */
|
||||
status = al_psa_status(
|
||||
psa_export_key(key_handle, data_out,
|
||||
sizeof(data_out), &data_len),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to export key.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Check key len. */
|
||||
if (data_len != key_len) {
|
||||
LOG_ERR("Unexpected number of bytes in exported key.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Verify that the exported private key matches input data. */
|
||||
comp_result = memcmp(data_out, key_data, key_len);
|
||||
if (comp_result != 0) {
|
||||
LOG_ERR("Imported/exported private key mismatch.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Display the private key. */
|
||||
LOG_INF("Private key data:");
|
||||
al_dump_log();
|
||||
sf_hex_tabulate_16(&crp_fmt, data_out, data_len);
|
||||
|
||||
/* Close the key to free up the volatile slot. */
|
||||
status = al_psa_status(
|
||||
psa_close_key(key_handle),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to close persistent key.");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
err:
|
||||
al_dump_log();
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculates the SHA256 hash for the supplied message.
|
||||
*
|
||||
* @param msg Pointer to the buffer to read when generating the hash.
|
||||
* @param msg_len Number of bytes in msg.
|
||||
* @param hash Pointer to the buffer where the hash should be written.
|
||||
* @param hash_buf_size Size of hash in bytes.
|
||||
* @param hash_len Placeholder for the number of hash bytes written.
|
||||
*/
|
||||
static psa_status_t crp_hash_payload(uint8_t *msg, size_t msg_len,
|
||||
uint8_t *hash, size_t hash_buf_size,
|
||||
size_t *hash_len)
|
||||
{
|
||||
psa_status_t status;
|
||||
psa_hash_operation_t hash_handle = psa_hash_operation_init();
|
||||
psa_algorithm_t alg = PSA_ALG_SHA_256;
|
||||
|
||||
LOG_INF("Calculating SHA-256 hash of value");
|
||||
al_dump_log();
|
||||
|
||||
/* Display the input message */
|
||||
sf_hex_tabulate_16(&crp_fmt, msg, msg_len);
|
||||
|
||||
/* Setup the hash object. */
|
||||
status = al_psa_status(psa_hash_setup(&hash_handle, alg),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to setup hash op.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Update object with all the message chunks. */
|
||||
/* For the moment, the message is passed in a single operation, */
|
||||
/* but this can be broken up in chunks for larger messages. */
|
||||
status = al_psa_status(psa_hash_update(&hash_handle, msg, msg_len),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to update hash.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Finalize the hash calculation. */
|
||||
status = al_psa_status(psa_hash_finish(&hash_handle,
|
||||
hash, hash_buf_size, hash_len),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to finalize hash op.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Display the SHA-256 hash for debug purposes */
|
||||
sf_hex_tabulate_16(&crp_fmt, hash, (size_t)(PSA_HASH_SIZE(alg)));
|
||||
|
||||
return status;
|
||||
err:
|
||||
psa_hash_abort(&hash_handle);
|
||||
al_dump_log();
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Signs the supplied hash using the specified persistent key.
|
||||
*
|
||||
* @param key_id The identifier of the key to use when signing.
|
||||
* @param hash Pointer to the buffer where the hash should be written.
|
||||
* @param hash_buf_size Size of hash in bytes.
|
||||
* @param sig Pointer to the buffer to read when generating the sig.
|
||||
* @param sig_buf_size Size of sig buffer in bytes.
|
||||
* @param sig_len Number of bytes written to sig.
|
||||
*/
|
||||
static psa_status_t crp_sign_hash(psa_key_id_t key_id,
|
||||
uint8_t *hash, size_t hash_buf_size,
|
||||
uint8_t *sig, size_t sig_buf_size,
|
||||
size_t *sig_len)
|
||||
{
|
||||
psa_status_t status;
|
||||
psa_key_handle_t key_handle;
|
||||
|
||||
LOG_INF("Signing SHA-256 hash");
|
||||
al_dump_log();
|
||||
|
||||
/* Try to open the persisted key based on the key ID. */
|
||||
status = al_psa_status(
|
||||
psa_open_key(key_id, &key_handle),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to open persistent key #%d", key_id);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Sign using psa_sign_hash. */
|
||||
status = al_psa_status(
|
||||
psa_sign_hash(key_handle,
|
||||
PSA_ALG_ECDSA(PSA_ALG_SHA_256),
|
||||
hash, hash_buf_size,
|
||||
sig, sig_buf_size, sig_len),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to sign hash w/persistent key #%d", key_id);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Display the ECDSA signature for debug purposes */
|
||||
sf_hex_tabulate_16(&crp_fmt, sig, *sig_len);
|
||||
|
||||
/* You can test this same operation with openssl as follows:
|
||||
*
|
||||
* $ openssl dgst -sha256 -sign
|
||||
*/
|
||||
|
||||
/* Close the key to free up the volatile slot. */
|
||||
status = al_psa_status(
|
||||
psa_close_key(key_handle),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to close persistent key.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
return status;
|
||||
err:
|
||||
al_dump_log();
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Verifies the hash signature using the public key associated
|
||||
* with key_id.
|
||||
*
|
||||
* @param key_id The identifier for the persistent key.
|
||||
* @param hash Pointer to the hash data to verify.
|
||||
* @param hash_len Size of the hash buffer in bytes.
|
||||
* @param sig Pointer to the signature buffer.
|
||||
* @param sig_len Size of the signature buffer in bytes.
|
||||
*/
|
||||
static psa_status_t crp_verify_sign(psa_key_id_t key_id,
|
||||
uint8_t *hash, size_t hash_len,
|
||||
uint8_t *sig, size_t sig_len)
|
||||
{
|
||||
psa_status_t status;
|
||||
psa_key_handle_t key_handle;
|
||||
|
||||
LOG_INF("Verifying signature for SHA-256 hash");
|
||||
al_dump_log();
|
||||
|
||||
/* Try to open the persisted key based on the key ID. */
|
||||
status = al_psa_status(
|
||||
psa_open_key(key_id, &key_handle),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to open persistent key #%d", key_id);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Verify the hash signature. */
|
||||
status = al_psa_status(
|
||||
psa_verify_hash(key_handle,
|
||||
PSA_ALG_ECDSA(PSA_ALG_SHA_256),
|
||||
hash, hash_len,
|
||||
sig, sig_len),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Signature verification failed!");
|
||||
goto err;
|
||||
}
|
||||
|
||||
LOG_INF("Signature verified.");
|
||||
al_dump_log();
|
||||
|
||||
/* Close the key to free up the volatile slot. */
|
||||
status = al_psa_status(
|
||||
psa_close_key(key_handle),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to close persistent key.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
return status;
|
||||
err:
|
||||
al_dump_log();
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destroys the specified persistent key.
|
||||
*
|
||||
* @param key_id The identifier for the persistent key.
|
||||
*/
|
||||
static psa_status_t crp_dest_key(psa_key_id_t key_id)
|
||||
{
|
||||
psa_status_t status;
|
||||
psa_key_handle_t key_handle;
|
||||
|
||||
/* Try to open the persisted key based on the key ID. */
|
||||
status = al_psa_status(
|
||||
psa_open_key(key_id, &key_handle),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to open persistent key #%d", key_id);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Destroy the persistent key */
|
||||
status = al_psa_status(
|
||||
psa_destroy_key(key_handle),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to destroy a persistent key");
|
||||
goto err;
|
||||
}
|
||||
|
||||
LOG_INF("Destroyed persistent key #%d", (uint32_t)key_id);
|
||||
al_dump_log();
|
||||
|
||||
return status;
|
||||
err:
|
||||
al_dump_log();
|
||||
return status;
|
||||
}
|
||||
|
||||
void crp_test(void)
|
||||
{
|
||||
psa_status_t status;
|
||||
uint8_t msg[] = "Please hash and sign this message.";
|
||||
uint8_t hash[PSA_HASH_SIZE(PSA_ALG_SHA_256)] = { 0 };
|
||||
size_t hash_len;
|
||||
uint8_t sig[PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE] = { 0 };
|
||||
size_t sig_len;
|
||||
|
||||
/* secp256r1 private key. */
|
||||
#if CONFIG_PRIVATE_KEY_STATIC
|
||||
/* This value is based on the private key in user.pem,
|
||||
* which can be viewed viw the following command:
|
||||
*
|
||||
* $ openssl ec -in user.pem -text -noout
|
||||
*/
|
||||
uint8_t priv_key_data[32] = {
|
||||
0x14, 0xbc, 0xb9, 0x53, 0xa4, 0xee, 0xed, 0x50,
|
||||
0x09, 0x36, 0x92, 0x07, 0x1d, 0xdb, 0x24, 0x2c,
|
||||
0xef, 0xf9, 0x57, 0x92, 0x40, 0x4f, 0x49, 0xaa,
|
||||
0xd0, 0x7c, 0x5b, 0x3f, 0x26, 0xa7, 0x80, 0x48
|
||||
};
|
||||
#else
|
||||
/* Randomly generate the private key. */
|
||||
uint8_t priv_key_data[32] = { 0 };
|
||||
|
||||
psa_generate_random(priv_key_data, sizeof(priv_key_data));
|
||||
#endif
|
||||
|
||||
/* Initialize crypto API. */
|
||||
status = al_psa_status(psa_crypto_init(), __func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Crypto init failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* NOTE: The same key generation, SHA256 hash, sign, and verify
|
||||
* operations performed in this file can be also performed with
|
||||
* openssl using the commands described below.
|
||||
*
|
||||
* Generate a new key:
|
||||
*
|
||||
* The curve `prime256v1` is same as `secp256r1` in OpenSSL
|
||||
* (https://github.com/openssl/openssl/blob/master/apps/ecparam.c#L216)
|
||||
* $ openssl ecparam -name prime256v1 -genkey -out user.pem
|
||||
*
|
||||
* Display the public and private keys in hexadecimal format:
|
||||
*
|
||||
* $ openssl ec -in user.pem -text -noout
|
||||
*
|
||||
* Update the private key value in priv_key_data with the hexadecimal
|
||||
* values from "priv:" to be able to compare the PSA API and openssl
|
||||
* output.
|
||||
*
|
||||
* Generate a PEM file with the public key (which will be used to
|
||||
* verify any data signed with the private key):
|
||||
*
|
||||
* $ openssl ec -in user.pem -pubout -out user_pub.pem
|
||||
*
|
||||
* Hash the message with SHA256, and sign it with the private key:
|
||||
*
|
||||
* $ echo "Please hash and sign this message." > message.txt
|
||||
* $ openssl dgst -sha256 -sign user.pem message.txt > signature.der
|
||||
*
|
||||
* Verify the signature using the public key and message file:
|
||||
*
|
||||
* $ openssl dgst -sha256 -verify user_pub.pem \
|
||||
* -signature signature.der message.txt
|
||||
*
|
||||
* If everything ws OK you should see "Verified OK".
|
||||
*/
|
||||
|
||||
/* Generate persistent secp256r1 key w/ID #1. */
|
||||
/* PSA_KEY_USAGE_EXPORT can be added for debug purposes. */
|
||||
status = crp_gen_key_secp256r1(1,
|
||||
PSA_KEY_USAGE_SIGN_HASH |
|
||||
PSA_KEY_USAGE_VERIFY_HASH,
|
||||
priv_key_data);
|
||||
|
||||
/* Hash some data with the key using SHA256. */
|
||||
status = crp_hash_payload(msg, strlen(msg),
|
||||
hash, sizeof(hash), &hash_len);
|
||||
|
||||
/* Sign the hash using key #1. */
|
||||
status = crp_sign_hash(1,
|
||||
hash, sizeof(hash),
|
||||
sig, sizeof(sig), &sig_len);
|
||||
|
||||
/* Verify the hash signature using the public key. */
|
||||
status = crp_verify_sign(1, hash, hash_len, sig, sig_len);
|
||||
|
||||
/* Destroy the key. */
|
||||
status = crp_dest_key(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generates random values using the TF-M crypto service.
|
||||
*/
|
||||
|
@ -34,65 +525,3 @@ void crp_test_rng(void)
|
|||
al_dump_log();
|
||||
sf_hex_tabulate_16(&fmt, outbuf, 256);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Demonstrates how to calcute the SHA-256 hash of a value in chunks.
|
||||
*/
|
||||
void crp_test_sha256(void)
|
||||
{
|
||||
const psa_algorithm_t alg = PSA_ALG_SHA_256;
|
||||
static const char *const msg[] = { "This is my test message, ",
|
||||
"please generate a hash for this." };
|
||||
const size_t msg_size[] = { 25, 32 };
|
||||
uint8_t hash_val[PSA_HASH_SIZE(PSA_ALG_SHA_256)] = { 0 };
|
||||
size_t hash_len;
|
||||
const uint32_t msg_num = ARRAY_SIZE(msg) / sizeof(msg[0]);
|
||||
uint32_t idx;
|
||||
psa_status_t status;
|
||||
psa_hash_operation_t handle = psa_hash_operation_init();
|
||||
|
||||
LOG_INF("Calculating SHA-256 hash of value.");
|
||||
al_dump_log();
|
||||
|
||||
/* Setup the hash object. */
|
||||
status = al_psa_status(psa_hash_setup(&handle, alg), __func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Update object with all the message chunks. */
|
||||
for (idx = 0; idx < msg_num; idx++) {
|
||||
status = al_psa_status(
|
||||
psa_hash_update(
|
||||
&handle,
|
||||
(const uint8_t *)msg[idx], msg_size[idx]),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Finalize the hash calculation. */
|
||||
status = al_psa_status(
|
||||
psa_hash_finish(&handle,
|
||||
hash_val,
|
||||
sizeof(hash_val),
|
||||
&hash_len),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Display the SHA-256 hash for debug purposes */
|
||||
struct sf_hex_tbl_fmt fmt = {
|
||||
.ascii = false,
|
||||
.addr_label = true,
|
||||
.addr = 0
|
||||
};
|
||||
sf_hex_tabulate_16(&fmt, hash_val, (size_t)(PSA_HASH_SIZE(alg)));
|
||||
|
||||
return;
|
||||
err:
|
||||
psa_hash_abort(&handle);
|
||||
al_dump_log();
|
||||
}
|
||||
|
|
|
@ -6,14 +6,22 @@
|
|||
|
||||
#include <zephyr.h>
|
||||
|
||||
#include "psa/crypto.h"
|
||||
#include "psa/error.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Generates random values using the TF-M crypto service.
|
||||
*/
|
||||
void crp_test_rng(void);
|
||||
void crp_test_sha256(void);
|
||||
|
||||
/**
|
||||
* @brief Runs a series of PSA Cryptography API test functions.
|
||||
*/
|
||||
void crp_test(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ void sf_hex_tabulate_16(struct sf_hex_tbl_fmt *fmt, unsigned char *data,
|
|||
/* Check if we need to render the top address bar. */
|
||||
if (fmt->addr_label) {
|
||||
/* Render the top address bar. */
|
||||
printf("\n");
|
||||
printf(" ");
|
||||
printf("0 1 2 3 4 5 6 7 8 9 ");
|
||||
printf("A B C D E F\n");
|
||||
|
@ -110,4 +111,5 @@ void sf_hex_tabulate_16(struct sf_hex_tbl_fmt *fmt, unsigned char *data,
|
|||
}
|
||||
len--;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
|
8
samples/tfm_integration/psa_level_1/user.pem
Normal file
8
samples/tfm_integration/psa_level_1/user.pem
Normal file
|
@ -0,0 +1,8 @@
|
|||
-----BEGIN EC PARAMETERS-----
|
||||
BggqhkjOPQMBBw==
|
||||
-----END EC PARAMETERS-----
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIBS8uVOk7u1QCTaSBx3bJCzv+VeSQE9JqtB8Wz8mp4BIoAoGCCqGSM49
|
||||
AwEHoUQDQgAER+qu2dZtLh1lBfUE/swhmb5eWlZrTx4MQ+Jbzht9BtezceIKPEft
|
||||
hJ9lDtv5PdIHu4Gmc+Y7FpUZrAECyxz1NQ==
|
||||
-----END EC PRIVATE KEY-----
|
4
samples/tfm_integration/psa_level_1/user_pub.pem
Normal file
4
samples/tfm_integration/psa_level_1/user_pub.pem
Normal file
|
@ -0,0 +1,4 @@
|
|||
-----BEGIN PUBLIC KEY-----
|
||||
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAER+qu2dZtLh1lBfUE/swhmb5eWlZr
|
||||
Tx4MQ+Jbzht9BtezceIKPEfthJ9lDtv5PdIHu4Gmc+Y7FpUZrAECyxz1NQ==
|
||||
-----END PUBLIC KEY-----
|
Loading…
Reference in a new issue