Skip to content
File

Blob: firmware/platform/crypto_ec.c

c157 lines
1#include "radio_bridge.h"
2#include "esp_err.h"
3#include "esp_random.h"
4#include "mbedtls/ecdh.h"
5#include "mbedtls/platform_util.h"
6#include "mbedtls/md.h"
7#include "mbedtls/pk.h"
8#include "mbedtls/x509_crt.h"
9 
10static int curve_bits(const mbedtls_pk_context *key)
11{
12 if (!mbedtls_pk_can_do(key, MBEDTLS_PK_ECDSA))
13 return 0;
14 mbedtls_ecp_group_id id = mbedtls_pk_ec(*key)->MBEDTLS_PRIVATE(grp).id;
15 if (id == MBEDTLS_ECP_DP_SECP256R1)
16 return 256;
17 if (id == MBEDTLS_ECP_DP_SECP384R1)
18 return 384;
19 return 0;
20}
21 
22static int crypto_random(void *context, unsigned char *bytes, size_t length)
23{
24 (void)context;
25 /* Board initialization starts Wi-Fi, enabling the hardware entropy source. */
26 esp_fill_random(bytes, length);
27 return 0;
28}
29 
30static int load_key(mbedtls_pk_context *key, const uint8_t *der, size_t length)
31{
32 if (!length || length > 4096)
33 return ESP_ERR_INVALID_SIZE;
34 int result = mbedtls_pk_parse_key(key, der, length, NULL, 0, crypto_random, NULL);
35 if (!result && !curve_bits(key))
36 result = ESP_ERR_INVALID_ARG;
37 if (!result) {
38 mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*key);
39 result = mbedtls_ecp_check_privkey(&ec->MBEDTLS_PRIVATE(grp), &ec->MBEDTLS_PRIVATE(d));
40 }
41 return result;
42}
43 
44int32_t radio_crypto_key_info(const uint8_t *der, size_t length, int32_t *bits)
45{
46 *bits = 0;
47 mbedtls_pk_context key;
48 mbedtls_pk_init(&key);
49 int result = load_key(&key, der, length);
50 if (!result)
51 *bits = curve_bits(&key);
52 mbedtls_pk_free(&key);
53 return result;
54}
55 
56int32_t radio_crypto_sign(const uint8_t *der, size_t key_length, const uint8_t *data,
57 size_t data_length, int32_t hash_bits, uint8_t *output, size_t capacity,
58 size_t *used)
59{
60 *used = 0;
61 if (data_length > 65536 || (hash_bits != 256 && hash_bits != 384))
62 return ESP_ERR_INVALID_SIZE;
63 mbedtls_pk_context key;
64 mbedtls_pk_init(&key);
65 uint8_t hash[64] = {0};
66 mbedtls_md_type_t type = hash_bits == 256 ? MBEDTLS_MD_SHA256 : MBEDTLS_MD_SHA384;
67 int result = load_key(&key, der, key_length);
68 if (!result)
69 result = mbedtls_md(mbedtls_md_info_from_type(type), data, data_length, hash);
70 if (!result)
71 result = mbedtls_pk_sign(&key, type, hash, hash_bits / 8, output, capacity, used,
72 crypto_random, NULL);
73 mbedtls_pk_free(&key);
74 if (result) {
75 *used = 0;
76 mbedtls_platform_zeroize(output, capacity);
77 }
78 mbedtls_platform_zeroize(hash, sizeof(hash));
79 return result;
80}
81 
82int32_t radio_crypto_p256_keygen(uint8_t secret[32], uint8_t public_key[65])
83{
84 mbedtls_ecp_keypair key;
85 mbedtls_ecp_keypair_init(&key);
86 int result = mbedtls_ecp_gen_key(MBEDTLS_ECP_DP_SECP256R1, &key, crypto_random, NULL);
87 size_t used = 0;
88 if (!result)
89 result = mbedtls_mpi_write_binary(&key.MBEDTLS_PRIVATE(d), secret, 32);
90 if (!result)
91 result = mbedtls_ecp_point_write_binary(&key.MBEDTLS_PRIVATE(grp), &key.MBEDTLS_PRIVATE(Q),
92 MBEDTLS_ECP_PF_UNCOMPRESSED, &used, public_key, 65);
93 if (!result && used != 65)
94 result = ESP_ERR_INVALID_SIZE;
95 mbedtls_ecp_keypair_free(&key);
96 if (result) {
97 mbedtls_platform_zeroize(secret, 32);
98 mbedtls_platform_zeroize(public_key, 65);
99 }
100 return result;
101}
102 
103int32_t radio_crypto_p256_shared(const uint8_t secret[32], const uint8_t public_key[65],
104 uint8_t shared[32])
105{
106 mbedtls_ecp_group group;
107 mbedtls_ecp_point peer;
108 mbedtls_mpi scalar, value;
109 mbedtls_ecp_group_init(&group);
110 mbedtls_ecp_point_init(&peer);
111 mbedtls_mpi_init(&scalar);
112 mbedtls_mpi_init(&value);
113 int result = mbedtls_ecp_group_load(&group, MBEDTLS_ECP_DP_SECP256R1);
114 if (!result)
115 result = mbedtls_mpi_read_binary(&scalar, secret, 32);
116 if (!result)
117 result = mbedtls_ecp_check_privkey(&group, &scalar);
118 if (!result)
119 result = mbedtls_ecp_point_read_binary(&group, &peer, public_key, 65);
120 if (!result)
121 result = mbedtls_ecp_check_pubkey(&group, &peer);
122 if (!result)
123 result = mbedtls_ecdh_compute_shared(&group, &value, &peer, &scalar, crypto_random, NULL);
124 if (!result)
125 result = mbedtls_mpi_write_binary(&value, shared, 32);
126 mbedtls_mpi_free(&value);
127 mbedtls_mpi_free(&scalar);
128 mbedtls_ecp_point_free(&peer);
129 mbedtls_ecp_group_free(&group);
130 if (result)
131 mbedtls_platform_zeroize(shared, 32);
132 return result;
133}
134 
135int32_t radio_crypto_verify_ec(const uint8_t *certificate, size_t certificate_length,
136 const uint8_t *data, size_t data_length, const uint8_t *signature,
137 size_t signature_length, int32_t hash_bits)
138{
139 if (certificate_length > 65536 || data_length > 65536 || signature_length > 128 ||
140 (hash_bits != 256 && hash_bits != 384))
141 return ESP_ERR_INVALID_SIZE;
142 mbedtls_x509_crt parsed;
143 mbedtls_x509_crt_init(&parsed);
144 uint8_t hash[64] = {0};
145 mbedtls_md_type_t type = hash_bits == 256 ? MBEDTLS_MD_SHA256 : MBEDTLS_MD_SHA384;
146 int result = mbedtls_x509_crt_parse_der(&parsed, certificate, certificate_length);
147 if (!result && !curve_bits(&parsed.pk))
148 result = ESP_ERR_INVALID_ARG;
149 if (!result)
150 result = mbedtls_md(mbedtls_md_info_from_type(type), data, data_length, hash);
151 if (!result)
152 result =
153 mbedtls_pk_verify(&parsed.pk, type, hash, hash_bits / 8, signature, signature_length);
154 mbedtls_x509_crt_free(&parsed);
155 return result;
156}