samples: psa_crypto: Create Certificate Signing Request
This is a first step towards demonstrating provisioning of X.509 certificates. The device certificate signing request is created using Mbed TLS X.509 APIs. The elliptic curve key `SECP256R1` used to sign the CSR is generated inside TF-M and Mbed TLS is configured to use TF-M for crypto services. This approach will ensure that private key never leaves secure side. The CSR is encoded in JSON and is printed on the console. Signed-off-by: Devaraj Ranganna <devaraj.ranganna@linaro.org>
This commit is contained in:
parent
d80e480f20
commit
c3e5899658
10 changed files with 510 additions and 72 deletions
|
@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.20.0)
|
|||
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
|
||||
project(tfm_psa_level_1)
|
||||
project(tfm_psa_crypto)
|
||||
|
||||
# Source files in this sample
|
||||
target_sources(app PRIVATE src/main.c)
|
||||
|
@ -25,3 +25,5 @@ set_property(TARGET zephyr_property_target
|
|||
APPEND PROPERTY TFM_CMAKE_OPTIONS
|
||||
-DCRYPTO_ENGINE_BUF_SIZE=0x2400
|
||||
)
|
||||
|
||||
zephyr_include_directories(${APPLICATION_SOURCE_DIR}/src/tls_config)
|
||||
|
|
|
@ -19,18 +19,27 @@ config PSA_SHELL
|
|||
help
|
||||
Enabling this option will make the 'psa' shell command available.
|
||||
|
||||
config PSA_IMPORT_KEY
|
||||
bool "Enable support for importing private key data"
|
||||
help
|
||||
Enable support for importing a pre-generated or randomly generated
|
||||
private key using PSA APIs and PRIVATE_KEY_STATIC or
|
||||
PRIVATE_KEY_RANDOM.
|
||||
|
||||
choice
|
||||
prompt "Private Key"
|
||||
default PRIVATE_KEY_RANDOM
|
||||
|
||||
config PRIVATE_KEY_STATIC
|
||||
bool "Static"
|
||||
depends on PSA_IMPORT_KEY
|
||||
help
|
||||
A static key value will be used for the elliptic curve 'secp256r1'
|
||||
private key.
|
||||
|
||||
config PRIVATE_KEY_RANDOM
|
||||
bool "Random"
|
||||
depends on PSA_IMPORT_KEY
|
||||
help
|
||||
A randomly generated value will be used for the elliptic curve
|
||||
'secp256r1' private key.
|
||||
|
|
|
@ -6,10 +6,11 @@ TF-M PSA crypto
|
|||
Overview
|
||||
********
|
||||
This TF-M integration example demonstrates how to use the PSA crypto API in
|
||||
Zephyr for cryptography. In addition, this example also demonstrates certain
|
||||
TF-M features that are covered as part of the RTOS vendor requirements for a
|
||||
`PSA Certified Level 1`_ product, such as secure storage for config data,
|
||||
initial attestation for device verification.
|
||||
Zephyr for cryptography and device certificate signing request. In addition,
|
||||
this example also demonstrates certain TF-M features that are covered as part
|
||||
of the RTOS vendor requirements for a `PSA Certified Level 1`_ product, such
|
||||
as secure storage for config data, initial attestation for device
|
||||
verification.
|
||||
|
||||
Trusted Firmware (TF-M) Platform Security Architecture (PSA) APIs
|
||||
are used for the secure processing environment, with Zephyr running in the
|
||||
|
@ -30,15 +31,28 @@ Key Files
|
|||
``psa_crypto.c``
|
||||
================
|
||||
|
||||
Demonstrates the following workflow:
|
||||
Demonstrates hash, sign/verify workflow:
|
||||
|
||||
- Generate a persistent key: secp256r1 (usage: ecdsa-with-SHA256)
|
||||
- Generate/import a persistent key: secp256r1 (usage: ecdsa-with-SHA256)
|
||||
- Display the public key based on the private key data above
|
||||
- Calculate the SHA256 hash of a payload
|
||||
- Sign the hash with the persistent key
|
||||
- Verify the signature using the public key
|
||||
- Destroy the key
|
||||
|
||||
Also demonstrates device certificate signing request (CSR) workflow:
|
||||
|
||||
- Generate/import a persistent key: secp256r1 (usage: ecdsa-with-SHA256)
|
||||
- Set subject name in device CSR
|
||||
- Generate device CSR in PEM format
|
||||
- Encode device CSR as JSON
|
||||
|
||||
Importing/generating the persistent key is based on config option
|
||||
``PSA_IMPORT_KEY``. When ``PSA_IMPORT_KEY`` is enabled,
|
||||
the key data can be static if ``PRIVATE_KEY_STATIC`` is set or key data
|
||||
is generated using ``psa_generate_random`` if ``PRIVATE_KEY_RANDOM``
|
||||
is set.
|
||||
|
||||
``psa_attestation.c``
|
||||
=====================
|
||||
|
||||
|
@ -240,20 +254,14 @@ Sample Output
|
|||
|
||||
.. code-block:: console
|
||||
|
||||
[INF] Starting bootloader
|
||||
[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: 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.
|
||||
Booting TFM v1.4.1
|
||||
[Crypto] Dummy Entropy NV Seed is not suitable for production!
|
||||
*** Booting Zephyr OS build v2.7.99-1102-gf503ba9f1ab3 ***
|
||||
[00:00:00.014,000] <inf> app: app_cfg: Creating new config file with UID 0x1055CFDA7A
|
||||
[00:00:01.215,000] <inf> app: att: System IAT size is: 545 bytes.
|
||||
[00:00:01.215,000] <inf> app: att: Requesting IAT with 64 byte challenge.
|
||||
[00:00:01.836,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...:..$.
|
||||
|
@ -273,36 +281,36 @@ 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 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
|
||||
00000110 41 32 35 36 02 58 20 6D E1 0F 82 E0 CF FC 84 5A A256.X m.......Z
|
||||
00000120 24 25 2B EB 70 D7 2C 6B FC 92 CD BE 5B 65 9E C7 $%+.p.,k....[e..
|
||||
00000130 34 1E 1C D2 80 5D A3 A5 01 64 4E 53 50 45 04 65 4....]...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 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
|
||||
00000170 02 58 20 01 4C F2 64 0D 49 F8 23 69 57 FE F3 73 .X .L.d.I.#iW..s
|
||||
00000180 97 7E 73 C2 2C 4F D2 95 25 D8 BE 29 32 14 23 5D .~s.,O..%..)2.#]
|
||||
00000190 A9 22 AD 3A 00 01 25 01 77 77 77 77 2E 74 72 75 .".:..%.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 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
|
||||
000001E0 40 59 23 3E 80 5E E0 9F FA E3 F4 14 62 D3 15 A5 @Y#>.^......b...
|
||||
000001F0 B0 95 B5 E5 CB 79 92 F8 F1 A0 FE 14 0C 6C 84 2A .....y.......l.*
|
||||
00000200 41 97 BC 6F C6 7D 9C A5 21 BB 4C 2C D1 2C F3 66 A..o.}..!.L,.,.f
|
||||
00000210 4E D4 85 D2 57 15 72 11 E8 9E 06 4F C4 46 D0 58 N...W.r....O.F.X
|
||||
00000220 26 &
|
||||
|
||||
[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
|
||||
[00:00:01.905,000] <inf> app: Persisting SECP256R1 key as #1
|
||||
[00:00:02.458,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 .
|
||||
00000000 04 07 93 39 CD 42 53 7B 18 8C 8A F1 05 7F 49 D1 ...9.BS{......I.
|
||||
00000010 6B 30 D5 39 0D 1A 6E 95 BA 0C CD FE DB 59 A3 03 k0.9..n......Y..
|
||||
00000020 02 61 B4 CF 13 CC 70 15 67 30 83 FE A0 D4 2A 19 .a....p.g0....*.
|
||||
00000030 72 82 3E 3F 90 00 91 C6 5E 43 DC E9 B4 C4 0E F3 r.>?....^C......
|
||||
00000040 79 y
|
||||
|
||||
[00:00:07.935,000] <inf> app: Calculating SHA-256 hash of value
|
||||
[00:00:03.020,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
|
||||
|
@ -314,33 +322,67 @@ Sample Output
|
|||
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
|
||||
[00:00:03.032,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.
|
||||
00000000 EE F1 FE A6 A8 41 5F CC A6 3A 73 A7 C1 33 B4 78 .....A_..:s..3.x
|
||||
00000010 BF B7 38 78 2A 91 C8 82 32 F8 73 85 56 08 D2 A0 ..8x*...2.s.V...
|
||||
00000020 A6 22 2C 64 7A C7 E4 0A FB 99 D1 8B 67 37 F7 13 .",dz.......g7..
|
||||
00000030 E6 6C 54 7B 29 1D 3B A2 D8 E3 C4 79 17 BA 34 A8 .lT{).;....y..4.
|
||||
|
||||
[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.
|
||||
[00:00:03.658,000] <inf> app: Verifying signature for SHA-256 hash
|
||||
[00:00:06.339,000] <inf> app: Signature verified.
|
||||
[00:00:06.349,000] <inf> app: Destroyed persistent key #1
|
||||
[00:00:06.354,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..
|
||||
00000000 24 5C B3 EB 88 D2 80 76 23 B3 07 CA 16 92 8F 3D $\.....v#......=
|
||||
00000010 27 AC C2 42 59 15 5E 3C EB 11 20 3C 14 A6 EB 60 '..BY.^<.. <...`
|
||||
00000020 C0 92 12 97 4D D7 62 BC A0 0A 34 A7 CE A8 78 18 ....M.b...4...x.
|
||||
00000030 1B 30 6E 3C DA 80 F2 55 F7 FA 10 8B F5 78 CE 92 .0n<...U.....x..
|
||||
00000040 92 FF F2 A3 22 4D 2D F6 62 39 6D A5 DD E1 E1 C4 ...."M-.b9m.....
|
||||
00000050 67 67 30 19 98 D7 E4 AD A2 6A 27 1C A4 C2 A2 C6 gg0......j'.....
|
||||
00000060 8A B5 98 26 D3 1A 84 75 55 52 4F E1 6D 4B 84 99 ...&...uURO.mK..
|
||||
00000070 0F C2 5E 88 D5 8B E6 AA 2F 61 DC 63 79 5B 69 3F ..^...../a.cy[i?
|
||||
00000080 19 79 5A 78 49 29 22 92 9D F5 F3 FD 16 60 E2 72 .yZxI)"......`.r
|
||||
00000090 EA F8 8E 32 7D 81 A0 21 0C 82 4A A8 4C EE 9C 0E ...2}..!..J.L...
|
||||
000000A0 D7 BF 50 60 6C 65 8A 7C A6 CD C5 98 8B 15 EA F0 ..P`le.|........
|
||||
000000B0 26 D0 15 F4 EB DE A0 FD 88 2F 72 8B ED 07 44 5C &......../r...D\
|
||||
000000C0 91 46 17 8C 26 46 F2 7C BF 6B 45 63 B6 71 E7 51 .F..&F.|.kEc.q.Q
|
||||
000000D0 E4 34 A2 5A 01 F4 6E FF A2 67 82 7B F3 36 34 54 .4.Z..n..g.{.64T
|
||||
000000E0 80 ED 7E 9D 0A 21 09 9C 9C 55 A9 14 AF A2 66 65 ..~..!...U....fe
|
||||
000000F0 DE 8D BE C2 8B 31 B8 ED 06 AE A9 0B 7E 62 75 87 .....1......~bu.
|
||||
|
||||
[00:00:06.385,000] <inf> app: Initialising PSA crypto
|
||||
[00:00:06.386,000] <inf> app: PSA crypto init completed
|
||||
[00:00:06.387,000] <inf> app: Persisting SECP256R1 key as #1
|
||||
[00:00:06.938,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 34 B7 2F D5 EC 41 71 B1 04 D9 BE 1C E7 DD F7 .4./..Aq........
|
||||
00000010 C4 C0 B1 E9 64 CB 45 1F E3 4A 95 52 A8 75 B2 8C ....d.E..J.R.u..
|
||||
00000020 4D F1 CB 4F C2 26 2C 90 C9 05 B2 E4 4C 2A E9 9D M..O.&,.....L*..
|
||||
00000030 11 DF 35 1B 0E 86 D5 9C A1 1F FC FA ED 21 9A B5 ..5..........!..
|
||||
00000040 28 (
|
||||
|
||||
[00:00:07.495,000] <inf> app: Adding subject name to CSR
|
||||
[00:00:07.496,000] <inf> app: Adding subject name to CSR completed
|
||||
[00:00:07.497,000] <inf> app: Adding EC key to PK container
|
||||
[00:00:07.499,000] <inf> app: Adding EC key to PK container completed
|
||||
[00:00:07.500,000] <inf> app: Create device Certificate Signing Request
|
||||
[00:00:08.692,000] <inf> app: Create device Certificate Signing Request completed
|
||||
[00:00:08.693,000] <inf> app: Certificate Signing Request:
|
||||
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIHrMIGQAgEAMC4xDzANBgNVBAoMBkxpbmFybzEbMBkGA1UEAwwSRGV2aWNlIENl
|
||||
cnRpZmljYXRlMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENLcv1exBcbEE2b4c
|
||||
5933xMCx6WTLRR/jSpVSqHWyjE3xy0/CJiyQyQWy5Ewq6Z0R3zUbDobVnKEf/Prt
|
||||
IZq1KKAAMAwGCCqGSM49BAMCBQADSAAwRQIgaAlTPmrIaRO7myM2Qr+LNk9sagdO
|
||||
jPGUqbz4oUWhUsICIQCuHADW6F2l4czv78BO5Nf+FHZEpjbI1+fA2aLzglOaiA==
|
||||
-----END CERTIFICATE REQUEST-----
|
||||
|
||||
[00:00:08.696,000] <inf> app: Encoding CSR as json
|
||||
[00:00:08.699,000] <inf> app: Encoding CSR as json completed
|
||||
[00:00:08.700,000] <inf> app: Certificate Signing Request in JSON:
|
||||
|
||||
{"CSR":"-----BEGIN CERTIFICATE REQUEST-----\nMIHrMIGQAgEAMC4xDzANBgNVBAoMBkxpbmFybzEbMBkGA1UEAwwSRGV2aWNlIENl\ncnRpZmljYXRlMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENLcv1exBcbEE2b4c\n5933xMCx6WTLRR/jSpVSqHWyjE3xy0/CJiyQyQWy5Ewq6Z0R3zUbDobVnKEf/Prt\nIZq1KKAAMAwGCCqGSM49BAMCBQADSAAwRQIgaAlTPmrIaRO7myM2Qr+LNk9sagdO\njPGUqbz4oUWhUsICIQCuHADW6F2l4czv78BO5Nf+FHZEpjbI1+fA2aLzglOaiA==\n-----END CERTIFICATE REQUEST-----\n"}
|
||||
|
|
|
@ -16,5 +16,16 @@ CONFIG_TFM_IPC=y
|
|||
# The Zephyr CMSIS emulation assumes that ticks are ms, currently
|
||||
CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000
|
||||
|
||||
CONFIG_MAIN_STACK_SIZE=4096
|
||||
CONFIG_MAIN_STACK_SIZE=8192
|
||||
CONFIG_HEAP_MEM_POOL_SIZE=4096
|
||||
|
||||
# Mbed TLS
|
||||
CONFIG_MBEDTLS=y
|
||||
CONFIG_MBEDTLS_BUILTIN=y
|
||||
CONFIG_MBEDTLS_ENABLE_HEAP=y
|
||||
CONFIG_MBEDTLS_HEAP_SIZE=32768
|
||||
CONFIG_MBEDTLS_USER_CONFIG_ENABLE=y
|
||||
CONFIG_MBEDTLS_USER_CONFIG_FILE="user-tls.conf"
|
||||
|
||||
# JSON
|
||||
CONFIG_JSON_LIBRARY=y
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
sample:
|
||||
description: This app provides an example of using PSA crypto APIs
|
||||
in Zephyr using IPC mode.
|
||||
to generate device certificate signing request in Zephyr
|
||||
using IPC mode.
|
||||
name: PSA crypto example
|
||||
tests:
|
||||
sample.psa_crypto:
|
||||
tags: introduction tfm crypto
|
||||
tags: introduction tfm crypto csr
|
||||
platform_allow: mps2_an521_ns lpcxpresso55s69_ns nrf5340dk_nrf5340_cpuapp_ns
|
||||
nrf9160dk_nrf9160_ns nucleo_l552ze_q_ns v2m_musca_s1_ns stm32l562e_dk_ns
|
||||
bl5340_dvk_cpuapp_ns
|
||||
|
@ -16,3 +17,6 @@ tests:
|
|||
- "Signature verified"
|
||||
- "Destroyed persistent key #1"
|
||||
- "Generating 256 bytes of random data."
|
||||
- "Create device Certificate Signing Request completed"
|
||||
- "BEGIN CERTIFICATE REQUEST"
|
||||
- "END CERTIFICATE REQUEST"
|
||||
|
|
|
@ -38,6 +38,9 @@ void main(void)
|
|||
crp_test();
|
||||
crp_test_rng();
|
||||
|
||||
/* Generate Certificate Signing Request using Mbed TLS */
|
||||
crp_generate_csr();
|
||||
|
||||
/* Dump any queued log messages, and wait for system events. */
|
||||
al_dump_log();
|
||||
}
|
||||
|
|
|
@ -4,9 +4,16 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <logging/log_ctrl.h>
|
||||
#include <logging/log.h>
|
||||
#include <data/json.h>
|
||||
|
||||
#include "mbedtls/pk.h"
|
||||
#include "mbedtls/x509.h"
|
||||
#include "mbedtls/x509_csr.h"
|
||||
|
||||
#include "psa_crypto.h"
|
||||
#include "util_app_log.h"
|
||||
|
@ -22,6 +29,14 @@ struct sf_hex_tbl_fmt crp_fmt = {
|
|||
.addr = 0
|
||||
};
|
||||
|
||||
struct csr_json_struct {
|
||||
const char *CSR;
|
||||
};
|
||||
|
||||
static const struct json_obj_descr csr_json_descr[] = {
|
||||
JSON_OBJ_DESCR_PRIM(struct csr_json_struct, CSR, JSON_TOK_STRING)
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Extracts the public key from the specified persistent key id.
|
||||
*
|
||||
|
@ -77,6 +92,7 @@ err:
|
|||
return status;
|
||||
}
|
||||
|
||||
#if CONFIG_PSA_IMPORT_KEY
|
||||
/**
|
||||
* @brief Stores a new persistent secp256r1 key (usage: ecdsa-with-SHA256)
|
||||
* in ITS, associating it with the specified unique key identifier.
|
||||
|
@ -91,7 +107,7 @@ err:
|
|||
* @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,
|
||||
static psa_status_t crp_imp_key_secp256r1(psa_key_id_t key_id,
|
||||
psa_key_usage_t key_usage,
|
||||
uint8_t *key_data)
|
||||
{
|
||||
|
@ -112,6 +128,7 @@ static psa_status_t crp_gen_key_secp256r1(psa_key_id_t key_id,
|
|||
/* 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_lifetime(&key_attributes, PSA_KEY_LIFETIME_PERSISTENT);
|
||||
psa_set_key_algorithm(&key_attributes, alg);
|
||||
psa_set_key_type(&key_attributes, key_type);
|
||||
|
||||
|
@ -191,6 +208,325 @@ err:
|
|||
return status;
|
||||
}
|
||||
|
||||
#else /* !CONFIG_PSA_IMPORT_KEY */
|
||||
/**
|
||||
* @brief Generates a new permanent, persistent prime256v1 (ecdsa-with-SHA256)
|
||||
* key in ITS, associating it with the specified unique key identifier.
|
||||
*
|
||||
* This function will generate a new permament prime256v1 key in internal trusted
|
||||
* storage. Cryptographic operations can then be performed using the key
|
||||
* identifier (key_id) associated with this persistent key.
|
||||
*
|
||||
* @param key_id The permament identifier for the generated key.
|
||||
* @param key_usage The usage policy for the key.
|
||||
*/
|
||||
static psa_status_t crp_gen_key_secp256r1(psa_key_id_t key_id,
|
||||
psa_key_usage_t key_usage)
|
||||
{
|
||||
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_FAMILY_SECP_R1);
|
||||
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. */
|
||||
|
||||
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_lifetime(&key_attributes, PSA_KEY_LIFETIME_PERSISTENT);
|
||||
psa_set_key_algorithm(&key_attributes, alg);
|
||||
psa_set_key_type(&key_attributes, key_type);
|
||||
psa_set_key_bits(&key_attributes, 256);
|
||||
|
||||
/* Generate the private key, creating the persistent key on success */
|
||||
status = al_psa_status(
|
||||
psa_generate_key(&key_attributes, &key_handle),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to generate 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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
#endif /* CONFIG_PSA_IMPORT_KEY */
|
||||
|
||||
/**
|
||||
* @brief PSA Random number generator wrapper for Mbed TLS
|
||||
*/
|
||||
static int psa_rng_for_mbedtls(void *p_rng,
|
||||
unsigned char *output, size_t output_len)
|
||||
{
|
||||
(void)p_rng;
|
||||
|
||||
return psa_generate_random(output, output_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generates device certificate signing request (CSR) using Mbed TLS
|
||||
* X.509 and TF-M crypto service.
|
||||
*/
|
||||
void crp_generate_csr(void)
|
||||
{
|
||||
psa_status_t status;
|
||||
psa_key_id_t key_slot = 1;
|
||||
psa_key_handle_t key_handle;
|
||||
|
||||
unsigned char output_buf[1024];
|
||||
unsigned char json_encoded_buf[1024];
|
||||
|
||||
mbedtls_pk_context pk_key_container;
|
||||
mbedtls_x509write_csr req;
|
||||
|
||||
struct csr_json_struct csr_json = {
|
||||
.CSR = output_buf
|
||||
};
|
||||
|
||||
/* Initialize Mbed TLS structures. */
|
||||
mbedtls_x509write_csr_init(&req);
|
||||
mbedtls_pk_init(&pk_key_container);
|
||||
memset(output_buf, 0, sizeof(output_buf));
|
||||
|
||||
/* Initialize crypto API. */
|
||||
LOG_INF("Initialising PSA crypto");
|
||||
al_dump_log();
|
||||
|
||||
status = al_psa_status(psa_crypto_init(), __func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Crypto init failed.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
LOG_INF("PSA crypto init completed");
|
||||
al_dump_log();
|
||||
|
||||
/* prime256v1 (ecdsa-with-SHA256) private key. */
|
||||
#if CONFIG_PSA_IMPORT_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 /* !CONFIG_PRIVATE_KEY_STATIC */
|
||||
/* Randomly generate the private key. */
|
||||
uint8_t priv_key_data[32] = { 0 };
|
||||
|
||||
LOG_INF("Generate rnadom data for private key");
|
||||
al_dump_log();
|
||||
|
||||
psa_generate_random(priv_key_data, sizeof(priv_key_data));
|
||||
LOG_INF("Random data generation for private key completed");
|
||||
al_dump_log();
|
||||
|
||||
#endif /* CONFIG_PRIVATE_KEY_STATIC */
|
||||
|
||||
/* Generate persistent prime256v1 (ecdsa-with-SHA256) key w/ID #1. */
|
||||
/* PSA_KEY_USAGE_EXPORT can be added for debug purposes. */
|
||||
status = al_psa_status(
|
||||
crp_imp_key_secp256r1(key_slot,
|
||||
PSA_KEY_USAGE_SIGN_HASH |
|
||||
PSA_KEY_USAGE_VERIFY_HASH,
|
||||
priv_key_data),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to create persistent key #%d", key_slot);
|
||||
goto err;
|
||||
}
|
||||
#else /* !CONFIG_PSA_IMPORT_KEY */
|
||||
|
||||
/* NOTE: The certificate signing request (CSR) can be generated using
|
||||
* openssl by using following commands:
|
||||
*
|
||||
* Generate a new key:
|
||||
*
|
||||
* $ openssl ecparam -name secp256k1 -genkey -out USER.key
|
||||
*
|
||||
* Generate a certificate signing request, containing the user public key
|
||||
* and required details to be inserted into the user certificate.
|
||||
* openssl req -new -key USER.key -out USER.csr \
|
||||
* -subj "/O=Linaro/CN=$(uuidgen | tr '[:upper:]' '[:lower:]')"
|
||||
*
|
||||
*/
|
||||
|
||||
/* Generate persistent prime256v1 (ecdsa-with-SHA256) key w/ID #1. */
|
||||
/* PSA_KEY_USAGE_EXPORT can be added for debug purposes. */
|
||||
status = al_psa_status(
|
||||
crp_gen_key_secp256r1(key_slot,
|
||||
PSA_KEY_USAGE_SIGN_HASH |
|
||||
PSA_KEY_USAGE_VERIFY_HASH),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to create persistent key #%d", key_slot);
|
||||
goto err;
|
||||
}
|
||||
#endif /* CONFIG_PSA_IMPORT_KEY */
|
||||
|
||||
status = al_psa_status(
|
||||
psa_open_key(key_slot, &key_handle),
|
||||
__func__);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to open persistent key #%d", key_slot);
|
||||
goto err;
|
||||
}
|
||||
|
||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
|
||||
psa_get_key_attributes(key_handle, &attributes);
|
||||
mbedtls_x509write_csr_set_md_alg(&req, MBEDTLS_MD_SHA256);
|
||||
|
||||
LOG_INF("Adding subject name to CSR");
|
||||
al_dump_log();
|
||||
|
||||
status = mbedtls_x509write_csr_set_subject_name(&req, "O=Linaro,CN=Device Certificate");
|
||||
if (status != 0) {
|
||||
LOG_ERR("failed! mbedtls_x509write_csr_set_subject_name returned %d", status);
|
||||
goto err;
|
||||
}
|
||||
|
||||
LOG_INF("Adding subject name to CSR completed");
|
||||
al_dump_log();
|
||||
|
||||
LOG_INF("Adding EC key to PK container");
|
||||
al_dump_log();
|
||||
|
||||
status = mbedtls_pk_setup_opaque(&pk_key_container, key_handle);
|
||||
if (status != 0) {
|
||||
LOG_ERR("failed! mbedtls_pk_setup_opaque returned -0x%04x", (unsigned int) -status);
|
||||
goto err;
|
||||
}
|
||||
|
||||
LOG_INF("Adding EC key to PK container completed");
|
||||
al_dump_log();
|
||||
|
||||
mbedtls_x509write_csr_set_key(&req, &pk_key_container);
|
||||
|
||||
LOG_INF("Create device Certificate Signing Request");
|
||||
al_dump_log();
|
||||
|
||||
status = mbedtls_x509write_csr_pem(&req, output_buf, sizeof(output_buf),
|
||||
psa_rng_for_mbedtls, NULL);
|
||||
if (status < 0) {
|
||||
LOG_ERR("failed! mbedtls_x509write_csr_pem returned -0x%04x",
|
||||
(unsigned int) -status);
|
||||
goto err;
|
||||
}
|
||||
|
||||
LOG_INF("Create device Certificate Signing Request completed");
|
||||
al_dump_log();
|
||||
|
||||
LOG_INF("Certificate Signing Request:\n");
|
||||
al_dump_log();
|
||||
|
||||
printf("%s\n", output_buf);
|
||||
|
||||
/*
|
||||
* 1.3. Encoding CSR as JSON
|
||||
*/
|
||||
LOG_INF("Encoding CSR as json");
|
||||
al_dump_log();
|
||||
|
||||
status = json_obj_encode_buf(csr_json_descr, ARRAY_SIZE(csr_json_descr),
|
||||
&csr_json, json_encoded_buf, sizeof(json_encoded_buf));
|
||||
|
||||
if (status != 0) {
|
||||
LOG_ERR("failed! json_obj_encode_buf returned 0x%04x", status);
|
||||
goto err;
|
||||
}
|
||||
|
||||
LOG_INF("Encoding CSR as json completed");
|
||||
al_dump_log();
|
||||
|
||||
LOG_INF("Certificate Signing Request in JSON:\n");
|
||||
al_dump_log();
|
||||
|
||||
printf("%s\n", json_encoded_buf);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
err:
|
||||
al_dump_log();
|
||||
mbedtls_x509write_csr_free(&req);
|
||||
mbedtls_pk_free(&pk_key_container);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculates the SHA256 hash for the supplied message.
|
||||
*
|
||||
|
@ -422,6 +758,7 @@ void crp_test(void)
|
|||
size_t sig_len;
|
||||
|
||||
/* secp256r1 private key. */
|
||||
#if CONFIG_PSA_IMPORT_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:
|
||||
|
@ -434,12 +771,13 @@ void crp_test(void)
|
|||
0xef, 0xf9, 0x57, 0x92, 0x40, 0x4f, 0x49, 0xaa,
|
||||
0xd0, 0x7c, 0x5b, 0x3f, 0x26, 0xa7, 0x80, 0x48
|
||||
};
|
||||
#else
|
||||
#else /* !CONFIG_PRIVATE_KEY_STATIC */
|
||||
/* Randomly generate the private key. */
|
||||
uint8_t priv_key_data[32] = { 0 };
|
||||
|
||||
psa_generate_random(priv_key_data, sizeof(priv_key_data));
|
||||
#endif
|
||||
#endif /* CONFIG_PRIVATE_KEY_STATIC */
|
||||
#endif /* CONFIG_PSA_IMPORT_KEY */
|
||||
|
||||
/* Initialize crypto API. */
|
||||
status = al_psa_status(psa_crypto_init(), __func__);
|
||||
|
@ -486,10 +824,16 @@ void crp_test(void)
|
|||
|
||||
/* Generate persistent secp256r1 key w/ID #1. */
|
||||
/* PSA_KEY_USAGE_EXPORT can be added for debug purposes. */
|
||||
status = crp_gen_key_secp256r1(1,
|
||||
#if CONFIG_PSA_IMPORT_KEY
|
||||
status = crp_imp_key_secp256r1(1,
|
||||
PSA_KEY_USAGE_SIGN_HASH |
|
||||
PSA_KEY_USAGE_VERIFY_HASH,
|
||||
priv_key_data);
|
||||
#else /* !CONFIG_PSA_IMPORT_KEY */
|
||||
status = crp_gen_key_secp256r1(1,
|
||||
PSA_KEY_USAGE_SIGN_HASH |
|
||||
PSA_KEY_USAGE_VERIFY_HASH);
|
||||
#endif
|
||||
|
||||
/* Hash some data with the key using SHA256. */
|
||||
status = crp_hash_payload(msg, strlen(msg),
|
||||
|
|
|
@ -23,6 +23,12 @@ void crp_test_rng(void);
|
|||
*/
|
||||
void crp_test(void);
|
||||
|
||||
/**
|
||||
* @brief Generates device certificate signing request (CSR) using Mbed TLS
|
||||
* X.509 and TF-M crypto service.
|
||||
*/
|
||||
void crp_generate_csr(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
#define MBEDTLS_USE_PSA_CRYPTO
|
||||
|
||||
#define MBEDTLS_ENTROPY_C
|
||||
#define MBEDTLS_TEST_NULL_ENTROPY
|
||||
|
||||
#define MBEDTLS_ECP_C
|
||||
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
#define MBEDTLS_ECDSA_C
|
||||
|
||||
#define MBEDTLS_X509_CSR_WRITE_C
|
||||
#define MBEDTLS_X509_CREATE_C
|
||||
#define MBEDTLS_PEM_WRITE_C
|
||||
#define MBEDTLS_BASE64_C
|
||||
#define MBEDTLS_OID_C
|
||||
#define MBEDTLS_ASN1_WRITE_C
|
||||
#define MBEDTLS_PK_WRITE_C
|
||||
#define MBEDTLS_PK_C
|
2
west.yml
2
west.yml
|
@ -163,7 +163,7 @@ manifest:
|
|||
revision: 8e303c264fc21c2116dc612658003a22e933124d
|
||||
path: modules/lib/lz4
|
||||
- name: mbedtls
|
||||
revision: bf66e18046a96e83b6ef3bb4bec0ae81bdcefc68
|
||||
revision: 711fd5ea13a5e018cebe1ac1f79c22d897e8b34d
|
||||
path: modules/crypto/mbedtls
|
||||
groups:
|
||||
- crypto
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue