Skip to content

Commit 45bc131

Browse files
committed
Add Software Secure Element module
- This module emulates what an hardware secure element does. It is not really secure. Data is stored in plaintext
1 parent aefbe0f commit 45bc131

File tree

6 files changed

+964
-0
lines changed

6 files changed

+964
-0
lines changed

UNOR4USBBridge/SSE.cpp

Lines changed: 381 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,381 @@
1+
/*
2+
This file is part of the UNOR4USBBridge project.
3+
4+
Copyright (c) 2024 Arduino SA
5+
6+
This Source Code Form is subject to the terms of the Mozilla Public
7+
License, v. 2.0. If a copy of the MPL was not distributed with this
8+
file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
11+
/******************************************************************************
12+
INCLUDE
13+
******************************************************************************/
14+
#include <Arduino_DebugUtils.h>
15+
16+
#include "mbedtls/pk.h"
17+
#include "mbedtls/ctr_drbg.h"
18+
#include "mbedtls/entropy.h"
19+
20+
#include "mbedtls/error.h"
21+
#include "mbedtls/asn1.h"
22+
#include "mbedtls/asn1write.h"
23+
#include "mbedtls/sha256.h"
24+
25+
#include "SSE.h"
26+
27+
/******************************************************************************
28+
LOCAL MODULE FUNCTIONS
29+
******************************************************************************/
30+
31+
/*
32+
* Keep an eye on this new implementation from mbedtls not yet merged
33+
* https://github.com/Mbed-TLS/mbedtls/pull/8703/files
34+
*/
35+
36+
/*
37+
* https://github.com/Mbed-TLS/mbedtls/blob/aa3fa98bc4a99d21a973b891bf7bda9a27647068/library/pk_wrap.c#L543
38+
* An ASN.1 encoded signature is a sequence of two ASN.1 integers. Parse one of
39+
* those integers and convert it to the fixed-length encoding expected by PSA.
40+
*/
41+
static int extract_ecdsa_sig_int(unsigned char **from, const unsigned char *end,
42+
unsigned char *to, size_t to_len)
43+
{
44+
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
45+
size_t unpadded_len, padding_len;
46+
47+
if ((ret = mbedtls_asn1_get_tag(from, end, &unpadded_len,
48+
MBEDTLS_ASN1_INTEGER)) != 0) {
49+
return ret;
50+
}
51+
52+
while (unpadded_len > 0 && **from == 0x00) {
53+
(*from)++;
54+
unpadded_len--;
55+
}
56+
57+
if (unpadded_len > to_len || unpadded_len == 0) {
58+
return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
59+
}
60+
61+
padding_len = to_len - unpadded_len;
62+
memset(to, 0x00, padding_len);
63+
memcpy(to + padding_len, *from, unpadded_len);
64+
(*from) += unpadded_len;
65+
66+
return 0;
67+
}
68+
69+
/*
70+
* https://github.com/Mbed-TLS/mbedtls/blob/aa3fa98bc4a99d21a973b891bf7bda9a27647068/library/pk_wrap.c#L576
71+
* Convert a signature from an ASN.1 sequence of two integers
72+
* to a raw {r,s} buffer. Note: the provided sig buffer must be at least
73+
* twice as big as int_size.
74+
*/
75+
static int extract_ecdsa_sig(unsigned char **p, const unsigned char *end,
76+
unsigned char *sig, size_t int_size)
77+
{
78+
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
79+
size_t tmp_size;
80+
81+
if ((ret = mbedtls_asn1_get_tag(p, end, &tmp_size,
82+
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
83+
return ret;
84+
}
85+
86+
/* Extract r */
87+
if ((ret = extract_ecdsa_sig_int(p, end, sig, int_size)) != 0) {
88+
return ret;
89+
}
90+
/* Extract s */
91+
if ((ret = extract_ecdsa_sig_int(p, end, sig + int_size, int_size)) != 0) {
92+
return ret;
93+
}
94+
95+
return 0;
96+
}
97+
98+
/*
99+
* https://github.com/Mbed-TLS/mbedtls/blob/47c74a477378ec3f0d1ba80547db836e078fa3a0/library/ecdsa.c#L609
100+
* Convert a signature (given by context) to ASN.1
101+
*/
102+
static int ecdsa_signature_to_asn1(const mbedtls_mpi *r, const mbedtls_mpi *s,
103+
unsigned char *sig, size_t sig_size,
104+
size_t *slen)
105+
{
106+
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
107+
unsigned char buf[MBEDTLS_ECDSA_MAX_LEN] = { 0 };
108+
unsigned char *p = buf + sizeof(buf);
109+
size_t len = 0;
110+
111+
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, s));
112+
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, r));
113+
114+
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, buf, len));
115+
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, buf,
116+
MBEDTLS_ASN1_CONSTRUCTED |
117+
MBEDTLS_ASN1_SEQUENCE));
118+
119+
if (len > sig_size) {
120+
return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
121+
}
122+
123+
memcpy(sig, p, len);
124+
*slen = len;
125+
126+
return 0;
127+
}
128+
129+
130+
/******************************************************************************
131+
PUBLIC MEMBER FUNCTIONS
132+
******************************************************************************/
133+
134+
int Arduino_UNOWIFIR4_SSE::generateECKeyPair(unsigned char* derKey, int maxLen)
135+
{
136+
int ret = 1;
137+
mbedtls_pk_context key;
138+
mbedtls_ctr_drbg_context ctr_drbg;
139+
mbedtls_entropy_context entropy;
140+
const char *pers = "gen_key";
141+
unsigned char mbedtls_buf[SSE_EC256_DER_PRI_KEY_LENGTH] = { 0 };
142+
143+
mbedtls_pk_init(&key);
144+
mbedtls_entropy_init(&entropy);
145+
mbedtls_ctr_drbg_init(&ctr_drbg);
146+
147+
if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen(pers))) != 0) {
148+
DEBUG_ERROR(" failed\n ! mbedtls_ctr_drbg_seed returned -0x%04x\n", (unsigned int) -ret);
149+
goto exit;
150+
}
151+
152+
if ((ret = mbedtls_pk_setup(&key, mbedtls_pk_info_from_type((mbedtls_pk_type_t) MBEDTLS_PK_ECKEY))) != 0) {
153+
DEBUG_ERROR(" failed\n ! mbedtls_pk_setup returned -0x%04x", (unsigned int) -ret);
154+
goto exit;
155+
}
156+
157+
if ((ret = mbedtls_ecp_gen_key((mbedtls_ecp_group_id) MBEDTLS_ECP_DP_SECP256R1, mbedtls_pk_ec(key), mbedtls_ctr_drbg_random, &ctr_drbg)) != 0) {
158+
DEBUG_ERROR(" failed\n ! mbedtls_ecp_gen_key returned -0x%04x", (unsigned int) -ret);
159+
goto exit;
160+
}
161+
162+
if ((ret = mbedtls_pk_write_key_der(&key, mbedtls_buf, sizeof(mbedtls_buf))) < 0) {
163+
DEBUG_ERROR(" failed\n ! mbedtls_pk_write_key_der returned -0x%04x", (unsigned int) -ret);
164+
goto exit;
165+
}
166+
167+
if (ret > maxLen) {
168+
DEBUG_ERROR(" failed\n ! output buffer too small operation needs 0x%04x bytes", (unsigned int) ret);
169+
ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
170+
goto exit;
171+
}
172+
173+
/* Copy data from the end of mbedtls_buf buffer to der output */
174+
memcpy(derKey, &mbedtls_buf[sizeof(mbedtls_buf) - ret], ret);
175+
176+
exit:
177+
mbedtls_ctr_drbg_free(&ctr_drbg);
178+
mbedtls_entropy_free(&entropy);
179+
mbedtls_pk_free(&key);
180+
181+
return ret;
182+
}
183+
184+
int Arduino_UNOWIFIR4_SSE::exportECKeyXY(const unsigned char* derKey, int derLen, unsigned char* pubXY)
185+
{
186+
int ret = 1;
187+
mbedtls_pk_context key;
188+
mbedtls_ecp_keypair *ecp;
189+
190+
mbedtls_pk_init(&key);
191+
192+
/* Check if we can use parse public key */
193+
if ((ret = mbedtls_pk_parse_key(&key, derKey, derLen, NULL, 0)) != 0) {
194+
DEBUG_ERROR(" failed\n ! mbedtls_pk_parse_key returned -0x%04x", (unsigned int) -ret);
195+
goto exit;
196+
}
197+
198+
if (mbedtls_pk_get_type(&key) != MBEDTLS_PK_ECKEY) {
199+
DEBUG_ERROR(" failed\n ! Not an EC KEY");
200+
goto exit;
201+
}
202+
203+
/* Get elliptic curve point */
204+
ecp = mbedtls_pk_ec(key);
205+
if ((ret = mbedtls_mpi_write_binary(&ecp->Q.X, &pubXY[0], SSE_EC256_X_LENGTH)) != 0) {
206+
DEBUG_ERROR(" failed\n ! mbedtls_mpi_write_binary Q.X returned -0x%04x", (unsigned int) -ret);
207+
goto exit;
208+
}
209+
210+
if ((ret = mbedtls_mpi_write_binary(&ecp->Q.Y, &pubXY[SSE_EC256_X_LENGTH], SSE_EC256_Y_LENGTH)) != 0) {
211+
DEBUG_ERROR(" failed\n ! mbedtls_mpi_write_binary Q.XYreturned -0x%04x", (unsigned int) -ret);
212+
goto exit;
213+
}
214+
215+
/* Success */
216+
ret = SSE_EC256_PUB_KEY_LENGTH;
217+
218+
exit:
219+
mbedtls_pk_free(&key);
220+
return ret;
221+
}
222+
223+
int Arduino_UNOWIFIR4_SSE::importECKeyXY(const unsigned char* pubXY, unsigned char* derKey, int maxLen)
224+
{
225+
int ret = 1;
226+
mbedtls_pk_context key;
227+
unsigned char mbedtls_buf[SSE_EC256_DER_PUB_KEY_LENGTH] = { 0 };
228+
mbedtls_ecp_keypair* ecp;
229+
230+
mbedtls_pk_init(&key);
231+
232+
if ((ret = mbedtls_pk_setup(&key, mbedtls_pk_info_from_type((mbedtls_pk_type_t) MBEDTLS_PK_ECKEY))) != 0) {
233+
DEBUG_ERROR(" failed\n ! mbedtls_pk_setup returned -0x%04x", (unsigned int) -ret);
234+
goto exit;
235+
}
236+
237+
if (mbedtls_pk_get_type(&key) != MBEDTLS_PK_ECKEY) {
238+
DEBUG_ERROR(" failed\n ! Not an EC KEY");
239+
goto exit;
240+
}
241+
242+
ecp = mbedtls_pk_ec(key);
243+
244+
if (( ret = mbedtls_ecp_group_load(&ecp->grp, MBEDTLS_ECP_DP_SECP256R1)) != 0) {
245+
DEBUG_ERROR(" failed\n ! mbedtls_ecp_group_load returned -0x%04x", (unsigned int) -ret);
246+
goto exit;
247+
}
248+
249+
/*
250+
* Add uncompressed flag {0x04 | X | Y }
251+
* https://github.com/Mbed-TLS/mbedtls/blob/f660c7c92308b6080f8ca97fa1739370d1b2fab5/include/psa/crypto.h#L783
252+
*/
253+
mbedtls_buf[0] = 0x04; memcpy(&mbedtls_buf[1], pubXY, SSE_EC256_PUB_KEY_LENGTH);
254+
255+
if (( ret = mbedtls_ecp_point_read_binary(&ecp->grp, &ecp->Q, mbedtls_buf, SSE_EC256_PUB_KEY_LENGTH + 1)) != 0) {
256+
DEBUG_ERROR(" failed\n ! mbedtls_ecp_point_read_binary returned -0x%04x", (unsigned int) -ret);
257+
goto exit;
258+
}
259+
260+
if ((ret = mbedtls_pk_write_pubkey_der(&key, mbedtls_buf, sizeof(mbedtls_buf))) < 0) {
261+
DEBUG_ERROR(" failed\n ! mbedtls_pk_write_pubkey_der returned -0x%04x", (unsigned int) -ret);
262+
goto exit;
263+
}
264+
265+
if (ret > maxLen) {
266+
DEBUG_ERROR(" failed\n ! output buffer too small operation needs 0x%04x bytes", (unsigned int) ret);
267+
ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
268+
goto exit;
269+
}
270+
271+
/* Copy data from the end of mbedtls_buf buffer to der output */
272+
memcpy(derKey, &mbedtls_buf[sizeof(mbedtls_buf) - ret], ret);
273+
274+
exit:
275+
mbedtls_pk_free(&key);
276+
return ret;
277+
}
278+
279+
int Arduino_UNOWIFIR4_SSE::sha256(const unsigned char* message, int len, unsigned char* sha256)
280+
{
281+
int ret = 1;
282+
283+
if((ret = mbedtls_sha256_ret(message, len, sha256, 0)) != 0) {
284+
DEBUG_ERROR(" failed\n ! mbedtls_sha256_ret returned -0x%04x\n", (unsigned int) -ret);
285+
return ret;
286+
}
287+
return SSE_SHA256_LENGTH;
288+
}
289+
290+
int Arduino_UNOWIFIR4_SSE::sign(const unsigned char* derKey, int derLen, const unsigned char* sha256, unsigned char* sigRS)
291+
{
292+
int ret = 1;
293+
mbedtls_pk_context key;
294+
mbedtls_ctr_drbg_context ctr_drbg;
295+
mbedtls_entropy_context entropy;
296+
unsigned char mbedtls_buf[MBEDTLS_PK_SIGNATURE_MAX_SIZE] = { 0 };
297+
unsigned char *p = (unsigned char *)&mbedtls_buf[0];
298+
const char *pers = "gen_key";
299+
size_t sig_size = 0;
300+
301+
mbedtls_pk_init(&key);
302+
mbedtls_entropy_init(&entropy);
303+
mbedtls_ctr_drbg_init(&ctr_drbg);
304+
305+
if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char*)pers, strlen(pers))) != 0) {
306+
DEBUG_ERROR(" failed\n ! mbedtls_ctr_drbg_seed returned -0x%04x\n", (unsigned int) -ret);
307+
goto exit;
308+
}
309+
310+
/* verify if work using only private key*/
311+
if ((ret = mbedtls_pk_parse_key(&key, derKey, derLen, NULL, 0)) != 0) {
312+
DEBUG_ERROR(" failed\n ! mbedtls_pk_parse_key returned -0x%04x", (unsigned int) -ret);
313+
goto exit;
314+
}
315+
316+
if ((ret = mbedtls_pk_sign(&key, MBEDTLS_MD_SHA256, sha256, 0, mbedtls_buf, &sig_size, mbedtls_ctr_drbg_random, &ctr_drbg)) != 0) {
317+
DEBUG_ERROR(" failed\n ! mbedtls_pk_sign returned -0x%04x", (unsigned int) -ret);
318+
goto exit;
319+
}
320+
321+
#if SSE_DEBUG_ENABLED
322+
log_v("SSE::sign: der signature");
323+
log_buf_v(mbedtls_buf, sig_size);
324+
#endif
325+
326+
/* Extract {r,s} values from DER signature */
327+
extract_ecdsa_sig(&p, &mbedtls_buf[sig_size], sigRS, SSE_EC256_R_LENGTH);
328+
ret = SSE_EC256_SIGNATURE_LENGTH;
329+
330+
exit:
331+
mbedtls_ctr_drbg_free(&ctr_drbg);
332+
mbedtls_pk_free(&key);
333+
return ret;
334+
}
335+
336+
int Arduino_UNOWIFIR4_SSE::verify(const unsigned char* derKey, int derLen, const unsigned char* sha256, const unsigned char* sigRS)
337+
{
338+
int ret = 1;
339+
mbedtls_pk_context key;
340+
unsigned char mbedtls_buf[MBEDTLS_PK_SIGNATURE_MAX_SIZE] = { 0 };
341+
mbedtls_mpi r,s;
342+
size_t sig_size = 0;
343+
344+
mbedtls_mpi_init(&r);
345+
mbedtls_mpi_init(&s);
346+
mbedtls_pk_init(&key);
347+
348+
/* Verify is only public key is needed */
349+
if ((ret = mbedtls_pk_parse_public_key(&key, derKey, derLen)) != 0) {
350+
DEBUG_ERROR(" failed\n ! mbedtls_pk_parse_public_key returned -0x%04x", (unsigned int) -ret);
351+
goto exit;
352+
}
353+
354+
#if SSE_DEBUG_ENABLED
355+
log_v("SSE::verify: sha256");
356+
log_buf_v((const uint8_t *)sha256, SSE_SHA256_LENGTH);
357+
log_v("SSE::verify: compressed signature");
358+
log_buf_v((const uint8_t *)sigRS, SSE_EC256_SIGNATURE_LENGTH);
359+
#endif
360+
361+
/* Convert signature {r,s} values to DER */
362+
mbedtls_mpi_read_binary( &r, sigRS, SSE_EC256_R_LENGTH );
363+
mbedtls_mpi_read_binary( &s, sigRS + SSE_EC256_R_LENGTH, SSE_EC256_S_LENGTH );
364+
ecdsa_signature_to_asn1(&r, &s, mbedtls_buf, MBEDTLS_PK_SIGNATURE_MAX_SIZE, &sig_size);
365+
366+
#if SSE_DEBUG_ENABLED
367+
log_v("SSE::verify: der signature");
368+
log_buf_v((const uint8_t *)mbedtls_buf, sig_size);
369+
#endif
370+
371+
if ((ret = mbedtls_pk_verify(&key, MBEDTLS_MD_SHA256, sha256, SSE_SHA256_LENGTH, mbedtls_buf, sig_size)) != 0) {
372+
DEBUG_ERROR(" failed\n ! mbedtls_pk_verify returned -0x%04x", (unsigned int) -ret);
373+
goto exit;
374+
}
375+
376+
exit:
377+
mbedtls_pk_free(&key);
378+
return ret;
379+
}
380+
381+
Preferences sse;

0 commit comments

Comments
 (0)