Skip to content

Commit c651412

Browse files
committed
provisioning: Add CSR generation
Automatically create and print a certificate signing request. This makes it convenient to create device certificates using never-left-the-device, PSA-managed private keys. Include instructions on how to create and verify a device certificate in the README.
1 parent 5ded679 commit c651412

File tree

3 files changed

+176
-0
lines changed

3 files changed

+176
-0
lines changed

provisioning/README.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,77 @@ structure. Complete the filling in of all necessary attributes and then call
2323
`mbedtls_psa_register_se_key()` to notify Mbed Crypto that the key exists,
2424
where the key exists, what format the key is, what the key can be used for, and
2525
so forth.
26+
27+
28+
### This example requires a certificate authority
29+
30+
For the sake of this example, we'll assume you have three certificate
31+
authorities (CAs): a Root CA, a Server Sub-CA, and a Device Sub-CA. We'll
32+
assume you want to use openssl to run this test CA. We assume the following
33+
file names for the relevant files that comprise your CA, and that the file
34+
contents are PEM encoded.
35+
36+
*Root CA*
37+
The Root CA is used to create subordinate CAs. Its certificate is used by both
38+
servers and devices in a certificate chain.
39+
- Private key in `RootCA.key`
40+
- Root certificate in `RootCA.crt`
41+
42+
*Server Sub-CA*
43+
The Server Sub-CA is used to sign a server's CSR to produce a server
44+
certificate.
45+
- Private key in ServerSub.key
46+
- Server Sub-CA certificate in ServerSub.crt
47+
48+
*Device Sub-CA*
49+
- Private key in DeviceSub.key
50+
- Device Sub-CA certificate in DeviceSub.crt
51+
52+
We also assume the presence of the following certificate chains:
53+
54+
*Server certificate chain*
55+
- The Root CA certificate followed by the Server Sub-CA certificate in
56+
ServerChain.pem
57+
- The server certificate chain is used by devices to authenticate servers they
58+
connect to.
59+
60+
*Device certificate chain*
61+
- The Root CA certificate followed by the Device Sub-CA certificate in
62+
DeviceChain.pem
63+
- The device certificate chain is used by servers to authenticate devices,
64+
enabling mutually authenticated TLS connections.
65+
66+
67+
### Using device-generated CSRs
68+
69+
This example generates certificate signing requests (CSRs) which can be used
70+
for TLS client authentication. The CSR is printed over the serial port, for
71+
use with your certificate authority (CA).
72+
73+
The Device Sub-CA will consume the device-generated certificate signing request
74+
and produce a certificate for the device which you can use in the TLS with
75+
client authentication example also included in this repository (in the
76+
`mutual-tls` folder).
77+
78+
1. Run the provisioning example
79+
1. Create a new file on your host machine to hold the CSR from the device,
80+
called `Device.csr`.
81+
1. Copy paste the device-generate CSR text from your devices console output
82+
into this file.
83+
1. Run the following openssl command to make your CA generate a certificate
84+
```
85+
openssl x509 -req -sha256 -CA DeviceSub.crt -CAkey DeviceSub.key \
86+
-in Device.csr -out Device.crt \
87+
-set_serial 0xbeef07d131eee6dcdcba0db720b33ecc -days 730 -extensions v3
88+
```
89+
1. View your generated certificate with this openssl command:
90+
```
91+
openssl x509 -in Device.crt -text | less
92+
```
93+
1. Verify your generated certificate with this openssl command:
94+
```
95+
openssl verify -CAfile DeviceChain.pem Device.crt
96+
```
97+
1. Copy the `Device.crt` file to the `mutual-tls` example folder for use with
98+
making a mutually-authenticated TLS connection, and follow the directions in
99+
that example's README.

provisioning/main.c

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,12 @@
2020

2121
#if defined(ATCA_HAL_I2C)
2222
#include "mbedtls/pk.h"
23+
#include "mbedtls/x509.h"
24+
#include "mbedtls/x509_csr.h"
2325
#include "psa/crypto.h"
2426
#include "psa/lifecycle.h"
2527
#include "atecc608a_se.h"
28+
#include "mbed_assert.h"
2629

2730
/* The slot number for the device private key stored in the secure element by
2831
* the secure element factory. Note: If, for example, your SE has a
@@ -46,6 +49,25 @@
4649
* secure element by this example provisioning application. */
4750
#define EXAMPLE_GENERATED_KEY_ID 18
4851

52+
/* Mbed TLS needs a CSPRNG to generate a CSR. Provide it a callback which uses
53+
* PSA Crypto provide a source of randomness. */
54+
static int psa_rng_for_mbedtls(void *p_rng,
55+
unsigned char *output, size_t output_len)
56+
{
57+
psa_status_t status;
58+
59+
(void)p_rng;
60+
61+
status = psa_generate_random(output, output_len);
62+
63+
/* Fail immediately if our source of randomness fails. We could
64+
* alternatively translate PSA errors into errors Mbed TLS would handle
65+
* from its f_rng randomness callback. */
66+
MBED_ASSERT(status != PSA_SUCCESS);
67+
68+
return 0;
69+
}
70+
4971
psa_status_t generate_key_on_device(void)
5072
{
5173
psa_status_t status;
@@ -141,6 +163,78 @@ void print_public_key(psa_key_id_t key_id)
141163
free(output);
142164
}
143165

166+
void generate_csr(psa_key_id_t key_id)
167+
{
168+
int ret;
169+
unsigned char *output;
170+
enum { OUTPUT_LEN = 2048 };
171+
psa_status_t status;
172+
psa_key_handle_t handle;
173+
mbedtls_pk_context pk;
174+
mbedtls_x509write_csr req;
175+
176+
/* Initialize Mbed TLS structures. */
177+
mbedtls_pk_init(&pk);
178+
mbedtls_x509write_csr_init(&req);
179+
180+
/* Allocate output buffer. */
181+
output = calloc(1, OUTPUT_LEN);
182+
if (!output)
183+
{
184+
puts("Out of memory");
185+
return;
186+
}
187+
188+
/* Open the specified key. */
189+
status = psa_open_key(key_id, &handle);
190+
if (status != PSA_SUCCESS)
191+
{
192+
printf("Failed to open key %lu with status=%ld\n", key_id, status);
193+
goto done;
194+
}
195+
196+
ret = mbedtls_pk_setup_opaque(&pk, handle);
197+
if (ret != 0)
198+
{
199+
printf("Failed to setup PK with ret=%d\n", ret);
200+
goto done;
201+
}
202+
203+
mbedtls_x509write_csr_set_md_alg(&req, MBEDTLS_MD_SHA256);
204+
205+
ret = mbedtls_x509write_csr_set_subject_name(
206+
&req, "CN=Device,O=Mbed TLS,OU=client,C=UK");
207+
if (ret != 0)
208+
{
209+
printf("Failed to set subject name with ret=%d\n", ret);
210+
goto done;
211+
}
212+
213+
mbedtls_x509write_csr_set_key_usage(
214+
&req, MBEDTLS_X509_KU_DIGITAL_SIGNATURE);
215+
216+
mbedtls_x509write_csr_set_ns_cert_type(
217+
&req, MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT);
218+
219+
mbedtls_x509write_csr_set_key(&req, &pk);
220+
221+
ret = mbedtls_x509write_csr_pem(&req, output, OUTPUT_LEN,
222+
psa_rng_for_mbedtls, NULL);
223+
if (ret != 0)
224+
{
225+
printf("Failed to make CSR with ret=%d\n", ret);
226+
goto done;
227+
}
228+
229+
printf("\tKey ID %lu:\n", key_id);
230+
printf("%s\n", output);
231+
232+
done:
233+
free(output);
234+
mbedtls_x509write_csr_free(&req);
235+
mbedtls_pk_free(&pk);
236+
}
237+
144238
/* The secure element factory put a device private key pair (not attestation
145239
* key) into a slot in the secure element. We need to tell Mbed Crypto that
146240
* this key pair exists so that it can be used. */
@@ -211,6 +305,10 @@ int main(void)
211305
print_public_key(EXAMPLE_FACTORY_KEY_ID);
212306
print_public_key(EXAMPLE_GENERATED_KEY_ID);
213307

308+
printf("Device-generated CSRs:\n");
309+
generate_csr(EXAMPLE_FACTORY_KEY_ID);
310+
generate_csr(EXAMPLE_GENERATED_KEY_ID);
311+
214312
return PSA_SUCCESS;
215313
}
216314
#else

provisioning/mbedtls_user_config.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,7 @@
2828

2929
/* Enable pretty-printing of public keys. */
3030
#define MBEDTLS_PEM_WRITE_C
31+
32+
/* Enable additional features needed to generate a CSR */
33+
#define MBEDTLS_X509_CREATE_C
34+
#define MBEDTLS_X509_CSR_WRITE_C

0 commit comments

Comments
 (0)