Skip to content
File

Blob: firmware/platform/certificate.c

c82 lines
1#include <string.h>
2#include <time.h>
3#include "radio_bridge.h"
4#include "esp_random.h"
5#include "mbedtls/ctr_drbg.h"
6#include "mbedtls/pk.h"
7#include "mbedtls/platform_util.h"
8#include "mbedtls/x509_crt.h"
9 
10static int entropy(void *context, unsigned char *out, size_t length)
11{
12 (void)context;
13 /* Wi-Fi is running before this call, enabling ESP-IDF's hardware entropy source. */
14 esp_fill_random(out, length);
15 return 0;
16}
17 
18int32_t radio_certificate_generate(uint8_t *cert, size_t cert_capacity, size_t *cert_length,
19 uint8_t *key, size_t key_capacity, size_t *key_length)
20{
21 if (!cert || !key || !cert_length || !key_length)
22 return -1;
23 *cert_length = *key_length = 0;
24 time_t now = time(NULL), before = now - 60, after = now + 30 * 24 * 60 * 60;
25 struct tm tm;
26 char start[15], end[15];
27 if (now < 1700000000 || !gmtime_r(&before, &tm) ||
28 strftime(start, sizeof(start), "%Y%m%d%H%M%S", &tm) != 14 || !gmtime_r(&after, &tm) ||
29 strftime(end, sizeof(end), "%Y%m%d%H%M%S", &tm) != 14)
30 return -1;
31 mbedtls_ctr_drbg_context rng;
32 mbedtls_pk_context pk;
33 mbedtls_x509write_cert crt;
34 mbedtls_ctr_drbg_init(&rng);
35 mbedtls_pk_init(&pk);
36 mbedtls_x509write_crt_init(&crt);
37 const unsigned char purpose[] = "pocket-radio-dtls";
38 int result = mbedtls_ctr_drbg_seed(&rng, entropy, NULL, purpose, sizeof(purpose) - 1);
39 if (result != 0)
40 goto done;
41 result = mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY));
42 if (result != 0)
43 goto done;
44 result = mbedtls_ecp_gen_key(MBEDTLS_ECP_DP_SECP256R1, mbedtls_pk_ec(pk),
45 mbedtls_ctr_drbg_random, &rng);
46 if (result != 0)
47 goto done;
48 mbedtls_x509write_crt_set_version(&crt, MBEDTLS_X509_CRT_VERSION_3);
49 mbedtls_x509write_crt_set_md_alg(&crt, MBEDTLS_MD_SHA256);
50 mbedtls_x509write_crt_set_subject_key(&crt, &pk);
51 mbedtls_x509write_crt_set_issuer_key(&crt, &pk);
52 unsigned char serial[16];
53 esp_fill_random(serial, sizeof(serial));
54 serial[0] = (serial[0] & 0x7f) | 1;
55 if ((result = mbedtls_x509write_crt_set_serial_raw(&crt, serial, sizeof(serial))) != 0 ||
56 (result = mbedtls_x509write_crt_set_subject_name(&crt, "CN=Pocket Radio")) != 0 ||
57 (result = mbedtls_x509write_crt_set_issuer_name(&crt, "CN=Pocket Radio")) != 0 ||
58 (result = mbedtls_x509write_crt_set_validity(&crt, start, end)) != 0)
59 goto done;
60 result = mbedtls_x509write_crt_der(&crt, cert, cert_capacity, mbedtls_ctr_drbg_random, &rng);
61 if (result < 0)
62 goto done;
63 *cert_length = (size_t)result;
64 memmove(cert, cert + cert_capacity - *cert_length, *cert_length);
65 result = mbedtls_pk_write_key_der(&pk, key, key_capacity);
66 if (result < 0)
67 goto done;
68 *key_length = (size_t)result;
69 memmove(key, key + key_capacity - *key_length, *key_length);
70 mbedtls_platform_zeroize(key + *key_length, key_capacity - *key_length);
71 result = 0;
72done:
73 mbedtls_x509write_crt_free(&crt);
74 mbedtls_pk_free(&pk);
75 mbedtls_ctr_drbg_free(&rng);
76 if (result != 0) {
77 mbedtls_platform_zeroize(key, key_capacity);
78 *cert_length = *key_length = 0;
79 }
80 return result;
81}