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:
Devaraj Ranganna 2021-11-08 10:16:08 +00:00 committed by Christopher Friedt
commit c3e5899658
10 changed files with 510 additions and 72 deletions

View file

@ -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)

View file

@ -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.

View file

@ -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"}

View file

@ -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

View file

@ -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"

View file

@ -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();
}

View file

@ -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),

View file

@ -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

View file

@ -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

View file

@ -163,7 +163,7 @@ manifest:
revision: 8e303c264fc21c2116dc612658003a22e933124d
path: modules/lib/lz4
- name: mbedtls
revision: bf66e18046a96e83b6ef3bb4bec0ae81bdcefc68
revision: 711fd5ea13a5e018cebe1ac1f79c22d897e8b34d
path: modules/crypto/mbedtls
groups:
- crypto