Skip to content

Commit 023e36e

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 023e36e

File tree

6 files changed

+856
-0
lines changed

6 files changed

+856
-0
lines changed

UNOR4USBBridge/SSE.cpp

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

0 commit comments

Comments
 (0)