Skip to content

Commit 3eb5a8e

Browse files
committed
Add hardware signing and key exporting
1 parent 39392d5 commit 3eb5a8e

File tree

3 files changed

+323
-299
lines changed

3 files changed

+323
-299
lines changed

atecc608a_se.c

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
#include "atecc608a_se.h"
2+
3+
static ATCAIfaceCfg atca_iface_config = {
4+
.iface_type = ATCA_I2C_IFACE,
5+
.devtype = ATECC608A,
6+
.atcai2c.slave_address = 0xC0,
7+
.atcai2c.bus = 2,
8+
.atcai2c.baud = 400000,
9+
.wake_delay = 1500,
10+
.rx_retries = 20,
11+
};
12+
13+
int hash_sha256(const uint8_t *input, size_t input_size,
14+
const uint8_t *expected_hash, size_t expected_hash_size)
15+
{
16+
uint8_t actual_hash[ATCA_SHA_DIGEST_SIZE] = {0};
17+
18+
printf("**********************************************\n");
19+
printf("SHA-256:\n\n");
20+
atcab_printbin_label("Input: ", (uint8_t *)input, input_size);
21+
atcab_printbin_label("Expected Hash: ", (uint8_t *)expected_hash, expected_hash_size);
22+
ASSERT_STATUS(atcab_init(&atca_iface_config), ATCA_SUCCESS);
23+
ASSERT_STATUS(atcab_hw_sha2_256(input, input_size, actual_hash), ATCA_SUCCESS);
24+
ASSERT_STATUS(atcab_release(), ATCA_SUCCESS);
25+
atcab_printbin_label("Actual Hash: ", actual_hash, ATCA_SHA_DIGEST_SIZE);
26+
ASSERT_STATUS(memcmp(actual_hash, expected_hash, sizeof(actual_hash)), 0);
27+
printf("Success!\n\n");
28+
29+
return 0;
30+
}
31+
32+
int read_serial_number(void)
33+
{
34+
uint8_t serial[ATCA_SERIAL_NUM_SIZE];
35+
36+
printf("**********************************************\n");
37+
ASSERT_STATUS(atcab_init(&atca_iface_config), ATCA_SUCCESS);
38+
ASSERT_STATUS(atcab_read_serial_number(serial), ATCA_SUCCESS);
39+
ASSERT_STATUS(atcab_release(), ATCA_SUCCESS);
40+
printf("Serial Number:\n");
41+
atcab_printbin_sp(serial, ATCA_SERIAL_NUM_SIZE);
42+
printf("\n");
43+
44+
return 0;
45+
}
46+
47+
psa_status_t atecc608a_to_psa_error(ATCA_STATUS ret)
48+
{
49+
switch (ret)
50+
{
51+
case ATCA_SUCCESS:
52+
case ATCA_RX_NO_RESPONSE:
53+
case ATCA_WAKE_SUCCESS:
54+
return PSA_SUCCESS;
55+
case ATCA_BAD_PARAM:
56+
case ATCA_INVALID_ID:
57+
case ATCA_INVALID_SIZE:
58+
case ATCA_SMALL_BUFFER:
59+
case ATCA_BAD_OPCODE:
60+
case ATCA_ASSERT_FAILURE:
61+
return PSA_ERROR_INVALID_ARGUMENT;
62+
case ATCA_RX_CRC_ERROR:
63+
case ATCA_RX_FAIL:
64+
case ATCA_STATUS_CRC:
65+
case ATCA_RESYNC_WITH_WAKEUP:
66+
case ATCA_PARITY_ERROR:
67+
case ATCA_TX_TIMEOUT:
68+
case ATCA_RX_TIMEOUT:
69+
case ATCA_TOO_MANY_COMM_RETRIES:
70+
case ATCA_COMM_FAIL:
71+
case ATCA_TIMEOUT:
72+
case ATCA_TX_FAIL:
73+
case ATCA_NO_DEVICES:
74+
return PSA_ERROR_COMMUNICATION_FAILURE;
75+
case ATCA_UNIMPLEMENTED:
76+
return PSA_ERROR_NOT_SUPPORTED;
77+
case ATCA_ALLOC_FAILURE:
78+
return PSA_ERROR_INSUFFICIENT_MEMORY;
79+
case ATCA_CONFIG_ZONE_LOCKED:
80+
case ATCA_DATA_ZONE_LOCKED:
81+
case ATCA_NOT_LOCKED:
82+
case ATCA_WAKE_FAILED:
83+
case ATCA_STATUS_UNKNOWN:
84+
case ATCA_STATUS_ECC:
85+
case ATCA_STATUS_SELFTEST_ERROR:
86+
case ATCA_CHECKMAC_VERIFY_FAILED:
87+
case ATCA_PARSE_ERROR:
88+
case ATCA_FUNC_FAIL:
89+
case ATCA_GEN_FAIL:
90+
case ATCA_EXECUTION_ERROR:
91+
case ATCA_HEALTH_TEST_ERROR:
92+
default:
93+
return PSA_ERROR_HARDWARE_FAILURE;
94+
}
95+
}
96+
97+
ATCA_STATUS checkLockedZones()
98+
{
99+
bool locked;
100+
bool config_locked;
101+
printf("--- Device locks information ---\n");
102+
ASSERT_STATUS(atcab_init(&atca_iface_config), ATCA_SUCCESS);
103+
ASSERT_STATUS(atcab_is_locked(LOCK_ZONE_CONFIG, &config_locked), ATCA_SUCCESS);
104+
printf(" - Config locked: %d\n", config_locked);
105+
ASSERT_STATUS(atcab_is_locked(LOCK_ZONE_DATA, &locked), ATCA_SUCCESS);
106+
printf(" - Data locked: %d\n", locked);
107+
for(uint8_t i=0; i < 16; i++)
108+
{
109+
ASSERT_STATUS(atcab_is_slot_locked(i, &locked), ATCA_SUCCESS);
110+
printf(" - Slot %d locked: %d\n", i, locked);
111+
}
112+
ASSERT_STATUS(atcab_release(), ATCA_SUCCESS);
113+
printf("--------------------------------\n");
114+
if(!config_locked)
115+
{
116+
printf("Config is not locked! Cannot use private keys.\n");
117+
return ATCA_NOT_LOCKED;
118+
}
119+
return ATCA_CONFIG_ZONE_LOCKED;
120+
}
121+
122+
psa_status_t atecc608a_export_key(psa_key_slot_number_t key,
123+
uint8_t *p_data,
124+
size_t data_size,
125+
size_t *p_data_length)
126+
{
127+
ATCA_STATUS ret = ATCA_SUCCESS;
128+
uint16_t slot = key;
129+
size_t key_data_len = 65;
130+
if(data_size < key_data_len)
131+
{
132+
printf("FAILED! Key buffer too small.\n");
133+
return PSA_ERROR_INVALID_ARGUMENT;
134+
}
135+
ASSERT_STATUS(atcab_init(&atca_iface_config), ATCA_SUCCESS);
136+
137+
ret = atcab_get_pubkey(slot, &p_data[1]);
138+
if (ret != ATCA_SUCCESS)
139+
{
140+
printf("FAILED! atcab_get_pubkey: %d\n", ret);
141+
return atecc608a_to_psa_error(ret);
142+
}
143+
p_data[0] = 4;
144+
*p_data_length = key_data_len;
145+
printf("atecc608a_export_key - pubkey size %d:\n", *p_data_length);
146+
atcab_printbin_sp(p_data, *p_data_length);
147+
ASSERT_STATUS(atcab_release(), ATCA_SUCCESS);
148+
}
149+
150+
psa_status_t atecc608a_asymmetric_sign(psa_key_slot_number_t key_slot,
151+
psa_algorithm_t alg,
152+
const uint8_t *p_hash,
153+
size_t hash_length,
154+
uint8_t *p_signature,
155+
size_t signature_size,
156+
size_t *p_signature_length)
157+
{
158+
ATCA_STATUS ret = ATCA_SUCCESS;
159+
uint16_t key_id = key_slot;
160+
161+
/* We can only do ECDSA on SHA-256 */
162+
/* PSA_ALG_ECDSA(PSA_ALG_SHA_256) */
163+
if(!PSA_ALG_IS_ECDSA(alg))
164+
{
165+
printf("FAILED! PSA_ALG_IS_ECDSA:\n");
166+
return PSA_ERROR_NOT_SUPPORTED;
167+
}
168+
169+
if (hash_length != 32)
170+
{
171+
printf("FAILED! hash_length:\n");
172+
/* The driver only supports signing things of length 32. */
173+
return PSA_ERROR_NOT_SUPPORTED;
174+
}
175+
176+
if (!PSA_ALG_IS_RANDOMIZED_ECDSA(alg))
177+
{
178+
printf("FAILED! PSA_ALG_IS_RANDOMIZED_ECDSA:\n");
179+
/* The hardware only supports randomized ECDSA */
180+
return PSA_ERROR_NOT_SUPPORTED;
181+
}
182+
183+
/* XXX how to check the curve? */
184+
//PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1);
185+
//PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256K1);
186+
187+
ASSERT_STATUS(atcab_init(&atca_iface_config), ATCA_SUCCESS);
188+
189+
/* Signature will be returned here. Format is R and S integers in
190+
* big-endian format. 64 bytes for P256 curve. */
191+
ret = atcab_sign(key_id, p_hash, p_signature);
192+
if (ret != ATCA_SUCCESS)
193+
{
194+
printf("FAILED! atcab_sign: %d\n", ret);
195+
return atecc608a_to_psa_error(ret);
196+
}
197+
198+
*p_signature_length = 64;
199+
ASSERT_STATUS(atcab_release(), ATCA_SUCCESS);
200+
201+
printf("atecc608a_asymmetric_sign - signature size %d:\n", *p_signature_length);
202+
atcab_printbin_sp(p_signature, *p_signature_length);
203+
return atecc608a_to_psa_error(ret);
204+
}
205+
206+
psa_drv_se_asymmetric_t atecc608a_asymmetric =
207+
{
208+
.p_sign = atecc608a_asymmetric_sign,
209+
.p_verify = 0,
210+
.p_encrypt = 0,
211+
.p_decrypt = 0,
212+
};
213+
214+
psa_drv_se_key_management_t atecc608a_key_management = {
215+
.p_export = &atecc608a_export_key,
216+
};
217+
218+
psa_drv_se_info_t atecc608a_drv_info = {
219+
.lifetime = PSA_ATECC608A_LIFETIME,
220+
.p_asym = &atecc608a_asymmetric,
221+
.p_key_management = &atecc608a_key_management,
222+
.slot_min = 0,
223+
.slot_max = 0,
224+
};

atecc608a_se.h

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/**
2+
* \file atecc508a_se
3+
* \brief Secure element 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+
23+
#ifndef ATECC608A_SE_H
24+
#define ATECC608A_SE_H
25+
26+
#include "psa/crypto.h"
27+
28+
#include "atca_status.h"
29+
#include "atca_devtypes.h"
30+
#include "atca_iface.h"
31+
#include "atca_command.h"
32+
#include "atca_basic.h"
33+
#include "atca_helpers.h"
34+
35+
#define ASSERT_STATUS(actual, expected) \
36+
do \
37+
{ \
38+
if ((actual) != (expected)) \
39+
{ \
40+
printf("assertion failed at %s:%d " \
41+
"(actual=%d expected=%d)\n", __FILE__, __LINE__, \
42+
(int)actual, (int)expected); \
43+
return -1; \
44+
} \
45+
} while(0)
46+
#define USE_SE_DIRECTLY 0
47+
48+
#define PSA_ATECC608A_LIFETIME 0xdeadbeefU
49+
50+
int hash_sha256(const uint8_t *input, size_t input_size,
51+
const uint8_t *expected_hash, size_t expected_hash_size);
52+
53+
int read_serial_number(void);
54+
55+
psa_status_t atecc608a_to_psa_error(ATCA_STATUS ret);
56+
57+
ATCA_STATUS checkLockedZones();
58+
59+
psa_status_t atecc608a_export_key(psa_key_slot_number_t key,
60+
uint8_t *p_data,
61+
size_t data_size,
62+
size_t *p_data_length);
63+
64+
psa_status_t atecc608a_asymmetric_sign(psa_key_slot_number_t key_slot,
65+
psa_algorithm_t alg,
66+
const uint8_t *p_hash,
67+
size_t hash_length,
68+
uint8_t *p_signature,
69+
size_t signature_size,
70+
size_t *p_signature_length);
71+
72+
#endif /* ATECC608A_SE_H */

0 commit comments

Comments
 (0)