Skip to content

Commit 98089e1

Browse files
authored
Merge pull request #3 from AndrzejKurek/mbed-cryptoauthlib
Add hardware signing and key exporting
2 parents 745ef77 + ad2e8b7 commit 98089e1

File tree

2 files changed

+279
-0
lines changed

2 files changed

+279
-0
lines changed

atecc608a_se.c

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
/**
2+
* \file atecc608a_se.c
3+
* \brief Secure element driver implementation for ATECC508A and ATECC509A.
4+
*/
5+
6+
/*
7+
* Copyright (C) 2019, ARM Limited, All Rights Reserved
8+
* SPDX-License-Identifier: Apache-2.0
9+
*
10+
* Licensed under the Apache License, Version 2.0 (the "License"); you may
11+
* not use this file except in compliance with the License.
12+
* You may obtain a copy of the License at
13+
*
14+
* http://www.apache.org/licenses/LICENSE-2.0
15+
*
16+
* Unless required by applicable law or agreed to in writing, software
17+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
18+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19+
* See the License for the specific language governing permissions and
20+
* limitations under the License.
21+
*/
22+
#include "atecc608a_se.h"
23+
#include "atca_helpers.h"
24+
25+
#ifdef DEBUG_PRINT
26+
#include <stdio.h>
27+
#endif
28+
29+
#include <stdbool.h>
30+
#include <stdint.h>
31+
32+
/* Uncomment to print results on success */
33+
//#define DEBUG_PRINT
34+
35+
/** This macro checks if the result of an `expression` is equal to an
36+
* `expected` value and sets a `status` variable of type `psa_status_t` to
37+
* `PSA_SUCCESS`. If they are not equal, the `status` is set to
38+
* `psa_error instead`, and the code jumps to the `exit` label. */
39+
#define ASSERT_STATUS(expression, expected, psa_error) \
40+
do \
41+
{ \
42+
ATCA_STATUS ASSERT_result = (expression); \
43+
ATCA_STATUS ASSERT_expected = (expected); \
44+
if ((ASSERT_result) != (ASSERT_expected)) \
45+
{ \
46+
status = (psa_error); \
47+
goto exit; \
48+
} \
49+
status = PSA_SUCCESS; \
50+
} while(0)
51+
52+
/** Check if an ATCA operation is successful, translate the error otherwise. */
53+
#define ASSERT_SUCCESS(expression) ASSERT_STATUS(expression, ATCA_SUCCESS, \
54+
atecc608a_to_psa_error(ASSERT_result))
55+
56+
/** Does the same as the macro above, but without the error translation and for
57+
* the PSA return code - PSA_SUCCESS.*/
58+
#define ASSERT_SUCCESS_PSA(expression) ASSERT_STATUS(expression, PSA_SUCCESS, \
59+
ASSERT_result)
60+
61+
static ATCAIfaceCfg atca_iface_config = {
62+
.iface_type = ATCA_I2C_IFACE,
63+
.devtype = ATECC608A,
64+
.atcai2c.slave_address = 0xC0,
65+
.atcai2c.bus = 2,
66+
.atcai2c.baud = 400000,
67+
.wake_delay = 1500,
68+
.rx_retries = 20,
69+
};
70+
71+
psa_status_t atecc608a_to_psa_error(ATCA_STATUS ret)
72+
{
73+
switch (ret)
74+
{
75+
case ATCA_SUCCESS:
76+
case ATCA_RX_NO_RESPONSE:
77+
case ATCA_WAKE_SUCCESS:
78+
return PSA_SUCCESS;
79+
case ATCA_BAD_PARAM:
80+
case ATCA_INVALID_ID:
81+
return PSA_ERROR_INVALID_ARGUMENT;
82+
case ATCA_ASSERT_FAILURE:
83+
return PSA_ERROR_TAMPERING_DETECTED;
84+
case ATCA_SMALL_BUFFER:
85+
return PSA_ERROR_BUFFER_TOO_SMALL;
86+
case ATCA_RX_CRC_ERROR:
87+
case ATCA_RX_FAIL:
88+
case ATCA_STATUS_CRC:
89+
case ATCA_RESYNC_WITH_WAKEUP:
90+
case ATCA_PARITY_ERROR:
91+
case ATCA_TX_TIMEOUT:
92+
case ATCA_RX_TIMEOUT:
93+
case ATCA_TOO_MANY_COMM_RETRIES:
94+
case ATCA_COMM_FAIL:
95+
case ATCA_TIMEOUT:
96+
case ATCA_TX_FAIL:
97+
case ATCA_NO_DEVICES:
98+
return PSA_ERROR_COMMUNICATION_FAILURE;
99+
case ATCA_UNIMPLEMENTED:
100+
return PSA_ERROR_NOT_SUPPORTED;
101+
case ATCA_ALLOC_FAILURE:
102+
return PSA_ERROR_INSUFFICIENT_MEMORY;
103+
case ATCA_BAD_OPCODE:
104+
case ATCA_CONFIG_ZONE_LOCKED:
105+
case ATCA_DATA_ZONE_LOCKED:
106+
case ATCA_NOT_LOCKED:
107+
case ATCA_WAKE_FAILED:
108+
case ATCA_STATUS_UNKNOWN:
109+
case ATCA_STATUS_ECC:
110+
case ATCA_STATUS_SELFTEST_ERROR:
111+
case ATCA_CHECKMAC_VERIFY_FAILED:
112+
case ATCA_PARSE_ERROR:
113+
case ATCA_FUNC_FAIL:
114+
case ATCA_GEN_FAIL:
115+
case ATCA_EXECUTION_ERROR:
116+
case ATCA_HEALTH_TEST_ERROR:
117+
case ATCA_INVALID_SIZE:
118+
default:
119+
return PSA_ERROR_HARDWARE_FAILURE;
120+
}
121+
}
122+
123+
psa_status_t atecc608a_init()
124+
{
125+
return atecc608a_to_psa_error(atcab_init(&atca_iface_config));
126+
}
127+
128+
psa_status_t atecc608a_deinit()
129+
{
130+
return atecc608a_to_psa_error(atcab_release());
131+
}
132+
133+
static psa_status_t atecc608a_export_public_key(psa_key_slot_number_t key,
134+
uint8_t *p_data, size_t data_size,
135+
size_t *p_data_length)
136+
{
137+
const size_t key_data_len = 65;
138+
const uint16_t slot = key;
139+
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
140+
141+
if (data_size < key_data_len)
142+
{
143+
return PSA_ERROR_BUFFER_TOO_SMALL;
144+
}
145+
146+
ASSERT_SUCCESS_PSA(atecc608a_init());
147+
148+
/* atcab_get_pubkey returns concatenated x and y values, and the desired
149+
format is 0x04 + x + y. We start at &p_data[1] and add a 0x04 at p_data[0]. */
150+
ASSERT_SUCCESS(atcab_get_pubkey(slot, &p_data[1]));
151+
152+
p_data[0] = 4;
153+
*p_data_length = key_data_len;
154+
155+
#ifdef DEBUG_PRINT
156+
printf("atecc608a_export_key - pubkey size %d:\n", *p_data_length);
157+
atcab_printbin_sp(p_data, *p_data_length);
158+
#endif
159+
160+
exit:
161+
atecc608a_deinit();
162+
return status;
163+
}
164+
165+
static psa_status_t atecc608a_asymmetric_sign(psa_key_slot_number_t key_slot,
166+
psa_algorithm_t alg,
167+
const uint8_t *p_hash,
168+
size_t hash_length,
169+
uint8_t *p_signature,
170+
size_t signature_size,
171+
size_t *p_signature_length)
172+
{
173+
const uint16_t key_id = key_slot;
174+
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
175+
176+
/* We can only do ECDSA on SHA-256 */
177+
if (alg != PSA_ALG_ECDSA(PSA_ALG_SHA_256) && alg != PSA_ALG_ECDSA_ANY)
178+
{
179+
return PSA_ERROR_NOT_SUPPORTED;
180+
}
181+
182+
if (hash_length != 32)
183+
{
184+
/* The driver only supports signing things of length 32. */
185+
return PSA_ERROR_NOT_SUPPORTED;
186+
}
187+
188+
if (signature_size < ATCA_SIG_SIZE)
189+
{
190+
return PSA_ERROR_BUFFER_TOO_SMALL;
191+
}
192+
193+
ASSERT_SUCCESS_PSA(atecc608a_init());
194+
195+
/* Signature will be returned here. Format is R and S integers in
196+
* big-endian format. 64 bytes for P256 curve. */
197+
ASSERT_SUCCESS(atcab_sign(key_id, p_hash, p_signature));
198+
199+
*p_signature_length = ATCA_SIG_SIZE;
200+
201+
#ifdef DEBUG_PRINT
202+
printf("atecc608a_asymmetric_sign - signature size %d:\n", *p_signature_length);
203+
atcab_printbin_sp(p_signature, *p_signature_length);
204+
#endif
205+
206+
exit:
207+
atecc608a_deinit();
208+
return status;
209+
}
210+
211+
212+
#define PSA_ATECC608A_LIFETIME 0xdeadbeefU
213+
214+
static psa_drv_se_asymmetric_t atecc608a_asymmetric =
215+
{
216+
.p_sign = &atecc608a_asymmetric_sign,
217+
.p_verify = 0,
218+
.p_encrypt = 0,
219+
.p_decrypt = 0,
220+
};
221+
222+
static psa_drv_se_key_management_t atecc608a_key_management =
223+
{
224+
.p_import = 0,
225+
.p_generate = 0,
226+
.p_destroy = 0,
227+
/* So far there is no public key export function in the API, so use this instead */
228+
.p_export = &atecc608a_export_public_key,
229+
};
230+
231+
psa_drv_se_info_t atecc608a_drv_info =
232+
{
233+
.lifetime = PSA_ATECC608A_LIFETIME,
234+
.p_key_management = &atecc608a_key_management,
235+
.p_mac = 0,
236+
.p_cipher = 0,
237+
.p_asym = &atecc608a_asymmetric,
238+
.p_aead = 0,
239+
.p_derive = 0,
240+
.slot_min = 0,
241+
.slot_max = 0,
242+
};

atecc608a_se.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* \file atecc608a_se.h
3+
* \brief Secure element driver structure for ATECC508A and ATECC509A.
4+
*/
5+
6+
/*
7+
* Copyright (C) 2019, ARM Limited, All Rights Reserved
8+
* SPDX-License-Identifier: Apache-2.0
9+
*
10+
* Licensed under the Apache License, Version 2.0 (the "License"); you may
11+
* not use this file except in compliance with the License.
12+
* You may obtain a copy of the License at
13+
*
14+
* http://www.apache.org/licenses/LICENSE-2.0
15+
*
16+
* Unless required by applicable law or agreed to in writing, software
17+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
18+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19+
* See the License for the specific language governing permissions and
20+
* limitations under the License.
21+
*/
22+
23+
#ifndef ATECC608A_SE_H
24+
#define ATECC608A_SE_H
25+
26+
#include "psa/crypto_se_driver.h"
27+
#include "atca_basic.h"
28+
29+
extern psa_drv_se_info_t atecc608a_drv_info;
30+
31+
psa_status_t atecc608a_to_psa_error(ATCA_STATUS ret);
32+
33+
psa_status_t atecc608a_init();
34+
35+
psa_status_t atecc608a_deinit();
36+
37+
#endif /* ATECC608A_SE_H */

0 commit comments

Comments
 (0)