Skip to content

Commit 2acf3be

Browse files
authored
Merge pull request #2 from AndrzejKurek/psa-crypto-driver
ECDSA signing & public key exporting
2 parents f87219b + 9ee704d commit 2acf3be

11 files changed

+429
-113
lines changed

ATCRYPTOAUTH-XPRO-B-K64F2.jpg

605 KB
Loading

ATCRYPTOAUTH-XPRO-B-Shield.jpg

701 KB
Loading

atecc608a_utils.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**
2+
* \file atecc608a_utils.c
3+
* \brief ATECC508A and ATECC509A utility functions.
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_utils.h"
23+
24+
#include "atca_basic.h"
25+
26+
psa_status_t atecc608a_get_serial_number(uint8_t* buffer,
27+
size_t buffer_size,
28+
size_t *buffer_length)
29+
{
30+
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
31+
32+
if (buffer_size < ATCA_SERIAL_NUM_SIZE)
33+
{
34+
return PSA_ERROR_BUFFER_TOO_SMALL;
35+
}
36+
37+
ASSERT_SUCCESS_PSA(atecc608a_init());
38+
39+
ASSERT_SUCCESS(atcab_read_serial_number(buffer));
40+
*buffer_length = ATCA_SERIAL_NUM_SIZE;
41+
42+
exit:
43+
atecc608a_deinit();
44+
return status;
45+
}
46+
47+
psa_status_t atecc608a_check_config_locked()
48+
{
49+
bool config_locked;
50+
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
51+
52+
ASSERT_SUCCESS_PSA(atecc608a_init());
53+
54+
ASSERT_SUCCESS(atcab_is_locked(LOCK_ZONE_CONFIG, &config_locked));
55+
56+
exit:
57+
atecc608a_deinit();
58+
if (status == PSA_SUCCESS)
59+
{
60+
status = config_locked? PSA_SUCCESS : PSA_ERROR_HARDWARE_FAILURE;
61+
}
62+
return status;
63+
}

atecc608a_utils.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/**
2+
* \file atecc608a_utils.h
3+
* \brief ATECC508A and ATECC509A utility functions.
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_UTILS_H
24+
#define ATECC608A_UTILS_H
25+
26+
#include "psa/crypto.h"
27+
#include "atecc608a_se.h"
28+
29+
/** This macro checks if the result of an `expression` is equal to an
30+
* `expected` value and sets a `status` variable of type `psa_status_t` to
31+
* `PSA_SUCCESS`. If they are not equal, the `status` is set to
32+
* `psa_error instead`, the error details are printed, and the code jumps
33+
* to the `exit` label. */
34+
#define ASSERT_STATUS(expression, expected, psa_error) \
35+
do \
36+
{ \
37+
ATCA_STATUS ASSERT_result = (expression); \
38+
ATCA_STATUS ASSERT_expected = (expected); \
39+
if ((ASSERT_result) != (ASSERT_expected)) \
40+
{ \
41+
printf("assertion failed at %s:%d " \
42+
"(actual=%d expected=%d)\n", __FILE__, __LINE__, \
43+
ASSERT_result, ASSERT_expected); \
44+
status = (psa_error); \
45+
goto exit; \
46+
} \
47+
status = PSA_SUCCESS; \
48+
} while(0)
49+
50+
/** Check if an ATCA operation is successful, translate the error otherwise. */
51+
#define ASSERT_SUCCESS(expression) ASSERT_STATUS(expression, ATCA_SUCCESS, \
52+
atecc608a_to_psa_error(ASSERT_result))
53+
54+
/** Does the same as the macro above, but without the error translation and for
55+
* the PSA return code - PSA_SUCCESS.*/
56+
#define ASSERT_SUCCESS_PSA(expression) ASSERT_STATUS(expression, PSA_SUCCESS, \
57+
ASSERT_result)
58+
59+
psa_status_t atecc608a_get_serial_number(uint8_t* buffer, size_t buffer_size,
60+
size_t *buffer_length);
61+
62+
psa_status_t atecc608a_check_config_locked();
63+
64+
#endif /* ATECC608A_SE_H */

main.c

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
/*
2+
* Copyright (c) 2019, Arm Limited and affiliates
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#include <stdio.h>
19+
#include <inttypes.h>
20+
#include <string.h>
21+
22+
#if defined(ATCA_HAL_I2C)
23+
#include "psa/crypto.h"
24+
#include "atecc608a_se.h"
25+
#include "atecc608a_utils.h"
26+
#include "atca_helpers.h"
27+
28+
static const uint8_t hash_input1[] = "abc";
29+
/* SHA-256 hash of ['a','b','c'] */
30+
static const uint8_t sha256_expected_hash1[] = {
31+
0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
32+
0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
33+
0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
34+
0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD
35+
};
36+
37+
static const uint8_t hash_input2[] = "";
38+
/* SHA-256 hash of an empty string */
39+
static const uint8_t sha256_expected_hash2[] = {
40+
0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
41+
0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
42+
0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
43+
0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55
44+
};
45+
46+
47+
psa_status_t atecc608a_hash_sha256(const uint8_t *input, size_t input_size,
48+
const uint8_t *expected_hash,
49+
size_t expected_hash_size)
50+
{
51+
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
52+
uint8_t actual_hash[ATCA_SHA_DIGEST_SIZE] = {0};
53+
54+
printf("SHA-256:\n\n");
55+
atcab_printbin_label("Input: ", (uint8_t *)input, input_size);
56+
atcab_printbin_label("Expected Hash: ", (uint8_t *)expected_hash,
57+
expected_hash_size);
58+
ASSERT_SUCCESS_PSA(atecc608a_init());
59+
ASSERT_SUCCESS(atcab_hw_sha2_256(input, input_size, actual_hash));
60+
atcab_printbin_label("Actual Hash: ", actual_hash, ATCA_SHA_DIGEST_SIZE);
61+
ASSERT_STATUS(memcmp(actual_hash, expected_hash, sizeof(actual_hash)), 0,
62+
PSA_ERROR_HARDWARE_FAILURE);
63+
printf("Success!\n\n");
64+
65+
exit:
66+
atecc608a_deinit();
67+
return status;
68+
}
69+
70+
psa_status_t atecc608a_print_locked_zones()
71+
{
72+
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
73+
bool locked;
74+
printf("--- Device locks information ---\n");
75+
ASSERT_SUCCESS_PSA(atecc608a_init());
76+
ASSERT_SUCCESS(atcab_is_locked(LOCK_ZONE_CONFIG, &locked));
77+
printf(" - Config locked: %d\n", locked);
78+
ASSERT_SUCCESS(atcab_is_locked(LOCK_ZONE_DATA, &locked));
79+
printf(" - Data locked: %d\n", locked);
80+
for(uint8_t i=0; i < 16; i++)
81+
{
82+
ASSERT_SUCCESS(atcab_is_slot_locked(i, &locked));
83+
printf(" - Slot %d locked: %d\n", i, locked);
84+
}
85+
printf("--------------------------------\n");
86+
87+
exit:
88+
atecc608a_deinit();
89+
return status;
90+
}
91+
92+
psa_status_t atecc608a_print_serial_number()
93+
{
94+
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
95+
uint8_t serial[ATCA_SERIAL_NUM_SIZE];
96+
size_t buffer_length;
97+
98+
ASSERT_SUCCESS_PSA(atecc608a_get_serial_number(serial,
99+
ATCA_SERIAL_NUM_SIZE,
100+
&buffer_length));
101+
printf("Serial Number:\n");
102+
atcab_printbin_sp(serial, buffer_length);
103+
printf("\n");
104+
exit:
105+
return status;
106+
}
107+
108+
int main(void)
109+
{
110+
enum {
111+
key_type = PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_CURVE_SECP256R1),
112+
keypair_type = PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1),
113+
key_bits = 256,
114+
hash_alg = PSA_ALG_SHA_256,
115+
alg = PSA_ALG_ECDSA(hash_alg),
116+
sig_size = PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE(key_type, key_bits, alg),
117+
pubkey_size = PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits),
118+
hash_size = PSA_HASH_SIZE(hash_alg),
119+
};
120+
psa_status_t status;
121+
psa_key_handle_t verify_handle;
122+
uint8_t signature[sig_size];
123+
size_t signature_length = 0;
124+
const uint8_t hash[hash_size] = {
125+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
129+
};
130+
psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
131+
static uint8_t pubkey[pubkey_size];
132+
size_t pubkey_len = 0;
133+
psa_key_slot_number_t atecc608a_key_slot_device = 0;
134+
135+
atecc608a_print_serial_number();
136+
137+
ASSERT_SUCCESS_PSA(atecc608a_hash_sha256(hash_input1,
138+
sizeof(hash_input1) - 1,
139+
sha256_expected_hash1,
140+
sizeof(sha256_expected_hash1)));
141+
142+
ASSERT_SUCCESS_PSA(atecc608a_hash_sha256(hash_input2,
143+
sizeof(hash_input2) - 1,
144+
sha256_expected_hash2,
145+
sizeof(sha256_expected_hash2)));
146+
147+
ASSERT_SUCCESS_PSA(psa_crypto_init());
148+
149+
atecc608a_print_locked_zones();
150+
/* Verify that the device has a locked config before doing anything */
151+
ASSERT_SUCCESS_PSA(atecc608a_check_config_locked());
152+
153+
ASSERT_SUCCESS_PSA(atecc608a_drv_info.p_key_management->p_export(
154+
atecc608a_key_slot_device, pubkey, sizeof(pubkey),
155+
&pubkey_len));
156+
157+
ASSERT_SUCCESS_PSA(atecc608a_drv_info.p_asym->p_sign(
158+
atecc608a_key_slot_device, alg, hash, sizeof(hash),
159+
signature, sizeof(signature), &signature_length));
160+
161+
/*
162+
* Import the secure element's public key into a volatile key slot.
163+
*/
164+
ASSERT_SUCCESS_PSA(psa_allocate_key(&verify_handle));
165+
166+
psa_key_policy_set_usage(&policy, PSA_KEY_USAGE_VERIFY, alg);
167+
ASSERT_SUCCESS_PSA(psa_set_key_policy(verify_handle, &policy));
168+
169+
ASSERT_SUCCESS_PSA(psa_import_key(verify_handle, key_type, pubkey,
170+
pubkey_len));
171+
172+
/* Verify that the signature produced by the secure element is valid. */
173+
ASSERT_SUCCESS_PSA(psa_asymmetric_verify(verify_handle, alg, hash,
174+
sizeof(hash), signature,
175+
signature_length));
176+
177+
printf("Verification successful!\n");
178+
exit:
179+
return status;
180+
}
181+
#else
182+
int main(void)
183+
{
184+
printf("Not all of the required options are defined:\n"
185+
" - ATCA_HAL_I2C\n");
186+
return 0;
187+
}
188+
#endif

0 commit comments

Comments
 (0)