1bdcc259dSMatthias Ringwald /* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
2bdcc259dSMatthias Ringwald
3bdcc259dSMatthias Ringwald #include "uECC.h"
4bdcc259dSMatthias Ringwald
5bdcc259dSMatthias Ringwald #include <stdio.h>
6bdcc259dSMatthias Ringwald #include <string.h>
7bdcc259dSMatthias Ringwald
8bdcc259dSMatthias Ringwald #include <stdio.h>
9bdcc259dSMatthias Ringwald #include <string.h>
10bdcc259dSMatthias Ringwald #include <stdint.h>
11bdcc259dSMatthias Ringwald #include <stdlib.h>
12bdcc259dSMatthias Ringwald
13*80dcb211SMatthias Ringwald #include "btstack_debug.h"
14*80dcb211SMatthias Ringwald
15bdcc259dSMatthias Ringwald typedef uint8_t sm_key24_t[3];
16bdcc259dSMatthias Ringwald typedef uint8_t sm_key56_t[7];
17bdcc259dSMatthias Ringwald typedef uint8_t sm_key_t[16];
18bdcc259dSMatthias Ringwald typedef uint8_t sm_key256_t[32];
19bdcc259dSMatthias Ringwald
20bdcc259dSMatthias Ringwald // P256 Set 1
21bdcc259dSMatthias Ringwald static const char * set1_private_a_string = "3f49f6d4a3c55f3874c9b3e3d2103f504aff607beb40b7995899b8a6cd3c1abd";
22bdcc259dSMatthias Ringwald static const char * set1_private_b_string = "55188b3d32f6bb9a900afcfbeed4e72a59cb9ac2f19d7cfb6b4fdd49f47fc5fd";
23bdcc259dSMatthias Ringwald static const char * set1_public_a_string = \
24bdcc259dSMatthias Ringwald "20b003d2f297be2c5e2c83a7e9f9a5b9eff49111acf4fddbcc0301480e359de6" \
25bdcc259dSMatthias Ringwald "dc809c49652aeb6d63329abf5a52155c766345c28fed3024741c8ed01589d28b";
26bdcc259dSMatthias Ringwald static const char * set1_public_b_string = \
27bdcc259dSMatthias Ringwald "1ea1f0f01faf1d9609592284f19e4c0047b58afd8615a69f559077b22faaa190" \
28bdcc259dSMatthias Ringwald "4c55f33e429dad377356703a9ab85160472d1130e28e36765f89aff915b1214a";
29bdcc259dSMatthias Ringwald static const char * set1_dh_key_string = "ec0234a357c8ad05341010a60a397d9b99796b13b4f866f1868d34f373bfa698";
30bdcc259dSMatthias Ringwald
31bdcc259dSMatthias Ringwald // P256 Set 1
32bdcc259dSMatthias Ringwald static const char * set2_private_a_string = "06a516693c9aa31a6084545d0c5db641b48572b97203ddffb7ac73f7d0457663";
33bdcc259dSMatthias Ringwald static const char * set2_private_b_string = "529aa0670d72cd6497502ed473502b037e8803b5c60829a5a3caa219505530ba";
34bdcc259dSMatthias Ringwald static const char * set2_public_a_string = \
35bdcc259dSMatthias Ringwald "2c31a47b5779809ef44cb5eaaf5c3e43d5f8faad4a8794cb987e9b03745c78dd" \
36bdcc259dSMatthias Ringwald "919512183898dfbecd52e2408e43871fd021109117bd3ed4eaf8437743715d4f";
37bdcc259dSMatthias Ringwald static const char * set2_public_b_string = \
38bdcc259dSMatthias Ringwald "f465e43ff23d3f1b9dc7dfc04da8758184dbc966204796eccf0d6cf5e16500cc" \
39bdcc259dSMatthias Ringwald "0201d048bcbbd899eeefc424164e33c201c2b010ca6b4d43a8a155cad8ecb279";
40bdcc259dSMatthias Ringwald static const char * set2_dh_key_string = "ab85843a2f6d883f62e5684b38e307335fe6e1945ecd19604105c6f23221eb69";
41bdcc259dSMatthias Ringwald
big_endian_read_32(const uint8_t * buffer,int pos)42bdcc259dSMatthias Ringwald uint32_t big_endian_read_32( const uint8_t * buffer, int pos) {
43bdcc259dSMatthias Ringwald return ((uint32_t) buffer[(pos)+3]) | (((uint32_t)buffer[(pos)+2]) << 8) | (((uint32_t)buffer[(pos)+1]) << 16) | (((uint32_t) buffer[pos]) << 24);
44bdcc259dSMatthias Ringwald }
45bdcc259dSMatthias Ringwald
big_endian_store_32(uint8_t * buffer,uint16_t pos,uint32_t value)46bdcc259dSMatthias Ringwald void big_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value){
47bdcc259dSMatthias Ringwald buffer[pos++] = value >> 24;
48bdcc259dSMatthias Ringwald buffer[pos++] = value >> 16;
49bdcc259dSMatthias Ringwald buffer[pos++] = value >> 8;
50bdcc259dSMatthias Ringwald buffer[pos++] = value;
51bdcc259dSMatthias Ringwald }
52bdcc259dSMatthias Ringwald
hexdump_key(void * data,int size)53bdcc259dSMatthias Ringwald static void hexdump_key(void *data, int size){
54bdcc259dSMatthias Ringwald if (size <= 0) return;
55bdcc259dSMatthias Ringwald int i;
56bdcc259dSMatthias Ringwald for (i=0; i<size;i++){
57bdcc259dSMatthias Ringwald printf("%02X", ((uint8_t *)data)[i]);
58bdcc259dSMatthias Ringwald }
59bdcc259dSMatthias Ringwald printf("\n");
60bdcc259dSMatthias Ringwald }
61bdcc259dSMatthias Ringwald
nibble_for_char(char c)62bdcc259dSMatthias Ringwald static int nibble_for_char(char c){
63bdcc259dSMatthias Ringwald if (c >= '0' && c <= '9') return c - '0';
64bdcc259dSMatthias Ringwald if (c >= 'a' && c <= 'f') return c - 'a' + 10;
65bdcc259dSMatthias Ringwald if (c >= 'A' && c <= 'F') return c - 'F' + 10;
66bdcc259dSMatthias Ringwald return -1;
67bdcc259dSMatthias Ringwald }
68bdcc259dSMatthias Ringwald
parse_hex(uint8_t * buffer,const char * hex_string)69bdcc259dSMatthias Ringwald static int parse_hex(uint8_t * buffer, const char * hex_string){
70bdcc259dSMatthias Ringwald int len = 0;
71bdcc259dSMatthias Ringwald while (*hex_string){
72bdcc259dSMatthias Ringwald if (*hex_string == ' '){
73bdcc259dSMatthias Ringwald hex_string++;
74bdcc259dSMatthias Ringwald continue;
75bdcc259dSMatthias Ringwald }
76bdcc259dSMatthias Ringwald int high_nibble = nibble_for_char(*hex_string++);
77bdcc259dSMatthias Ringwald int low_nibble = nibble_for_char(*hex_string++);
78bdcc259dSMatthias Ringwald int value = (high_nibble << 4) | low_nibble;
79bdcc259dSMatthias Ringwald buffer[len++] = value;
80bdcc259dSMatthias Ringwald }
81bdcc259dSMatthias Ringwald return len;
82bdcc259dSMatthias Ringwald }
83bdcc259dSMatthias Ringwald
84bdcc259dSMatthias Ringwald
test_generate_f_rng(uint8_t * buffer,unsigned size)85bdcc259dSMatthias Ringwald static int test_generate_f_rng(uint8_t * buffer, unsigned size){
86bdcc259dSMatthias Ringwald // printf("test_generate_f_rng: size %u\n", (int)size);
87bdcc259dSMatthias Ringwald while (size) {
88bdcc259dSMatthias Ringwald *buffer++ = rand() & 0xff;
89bdcc259dSMatthias Ringwald size--;
90bdcc259dSMatthias Ringwald }
91bdcc259dSMatthias Ringwald return 1;
92bdcc259dSMatthias Ringwald }
93bdcc259dSMatthias Ringwald
test_set1(void)94bdcc259dSMatthias Ringwald int test_set1(void){
95bdcc259dSMatthias Ringwald uint8_t private1[uECC_BYTES];
96bdcc259dSMatthias Ringwald uint8_t private2[uECC_BYTES];
97bdcc259dSMatthias Ringwald uint8_t public1[uECC_BYTES * 2];
98bdcc259dSMatthias Ringwald uint8_t public1_computed[uECC_BYTES * 2];
99bdcc259dSMatthias Ringwald uint8_t public2[uECC_BYTES * 2];
100bdcc259dSMatthias Ringwald uint8_t secret1[uECC_BYTES];
101bdcc259dSMatthias Ringwald uint8_t secret2[uECC_BYTES];
102bdcc259dSMatthias Ringwald uint8_t secret[uECC_BYTES];
103bdcc259dSMatthias Ringwald
104bdcc259dSMatthias Ringwald parse_hex(private1, set1_private_a_string);
105bdcc259dSMatthias Ringwald parse_hex(public1, set1_public_a_string);
106bdcc259dSMatthias Ringwald parse_hex(private2, set1_private_b_string);
107bdcc259dSMatthias Ringwald parse_hex(public2, set1_public_b_string);
108bdcc259dSMatthias Ringwald parse_hex(secret, set1_dh_key_string);
109bdcc259dSMatthias Ringwald
110bdcc259dSMatthias Ringwald if (!uECC_compute_public_key(private1, public1_computed)){
111bdcc259dSMatthias Ringwald printf("uECC_compute_public_key() failed\n");
112bdcc259dSMatthias Ringwald }
113bdcc259dSMatthias Ringwald if (memcmp(public1, public1_computed, sizeof(public1_computed)) != 0) {
114bdcc259dSMatthias Ringwald printf("Computed public key differs from test data!\n");
115bdcc259dSMatthias Ringwald printf("Computed key = ");
116bdcc259dSMatthias Ringwald hexdump_key(public1_computed, uECC_BYTES * 2);
117bdcc259dSMatthias Ringwald printf("Expected ke = ");
118bdcc259dSMatthias Ringwald hexdump_key(public1, uECC_BYTES * 2);
119bdcc259dSMatthias Ringwald return 0;
120bdcc259dSMatthias Ringwald }
121bdcc259dSMatthias Ringwald
122bdcc259dSMatthias Ringwald if (!uECC_shared_secret(public2, private1, secret1)) {
123bdcc259dSMatthias Ringwald printf("shared_secret() failed (1)\n");
124bdcc259dSMatthias Ringwald return 0;
125bdcc259dSMatthias Ringwald }
126bdcc259dSMatthias Ringwald
127bdcc259dSMatthias Ringwald if (!uECC_shared_secret(public1, private2, secret2)) {
128bdcc259dSMatthias Ringwald printf("shared_secret() failed (2)\n");
129bdcc259dSMatthias Ringwald return 0;
130bdcc259dSMatthias Ringwald }
131bdcc259dSMatthias Ringwald
132bdcc259dSMatthias Ringwald if (memcmp(secret1, secret2, sizeof(secret1)) != 0) {
133bdcc259dSMatthias Ringwald printf("Shared secrets are not identical!\n");
134bdcc259dSMatthias Ringwald printf("Shared secret 1 = ");
135bdcc259dSMatthias Ringwald hexdump_key(secret1, uECC_BYTES);
136bdcc259dSMatthias Ringwald printf("Shared secret 2 = ");
137bdcc259dSMatthias Ringwald hexdump_key(secret2, uECC_BYTES);
138bdcc259dSMatthias Ringwald printf("Expected secret = "); hexdump_key(secret1, uECC_BYTES);
139bdcc259dSMatthias Ringwald return 0;
140bdcc259dSMatthias Ringwald }
141bdcc259dSMatthias Ringwald // printf("Shared secret = "); hexdump_key(secret1, uECC_BYTES);
142bdcc259dSMatthias Ringwald return 1;
143bdcc259dSMatthias Ringwald }
144bdcc259dSMatthias Ringwald
test_set2(void)145bdcc259dSMatthias Ringwald int test_set2(void){
146bdcc259dSMatthias Ringwald uint8_t private1[uECC_BYTES];
147bdcc259dSMatthias Ringwald uint8_t private2[uECC_BYTES];
148bdcc259dSMatthias Ringwald uint8_t public1[uECC_BYTES * 2];
149bdcc259dSMatthias Ringwald uint8_t public1_computed[uECC_BYTES * 2];
150bdcc259dSMatthias Ringwald uint8_t public2[uECC_BYTES * 2];
151bdcc259dSMatthias Ringwald uint8_t secret1[uECC_BYTES];
152bdcc259dSMatthias Ringwald uint8_t secret2[uECC_BYTES];
153bdcc259dSMatthias Ringwald uint8_t secret[uECC_BYTES];
154bdcc259dSMatthias Ringwald
155bdcc259dSMatthias Ringwald parse_hex(private1, set2_private_a_string);
156bdcc259dSMatthias Ringwald parse_hex(public1, set2_public_a_string);
157bdcc259dSMatthias Ringwald parse_hex(private2, set2_private_b_string);
158bdcc259dSMatthias Ringwald parse_hex(public2, set2_public_b_string);
159bdcc259dSMatthias Ringwald parse_hex(secret, set2_dh_key_string);
160bdcc259dSMatthias Ringwald
161bdcc259dSMatthias Ringwald if (!uECC_compute_public_key(private1, public1_computed)){
162bdcc259dSMatthias Ringwald printf("uECC_compute_public_key() failed\n");
163bdcc259dSMatthias Ringwald }
164bdcc259dSMatthias Ringwald
165bdcc259dSMatthias Ringwald if (memcmp(public1, public1_computed, sizeof(public1_computed)) != 0) {
166bdcc259dSMatthias Ringwald printf("Computed public key differs from test data!\n");
167bdcc259dSMatthias Ringwald printf("Computed key = ");
168bdcc259dSMatthias Ringwald hexdump_key(public1_computed, uECC_BYTES * 2);
169bdcc259dSMatthias Ringwald printf("Expected key = ");
170bdcc259dSMatthias Ringwald hexdump_key(public1, uECC_BYTES * 2);
171bdcc259dSMatthias Ringwald return 0;
172bdcc259dSMatthias Ringwald }
173bdcc259dSMatthias Ringwald
174bdcc259dSMatthias Ringwald if (!uECC_shared_secret(public2, private1, secret1)) {
175bdcc259dSMatthias Ringwald printf("shared_secret() failed (1)\n");
176bdcc259dSMatthias Ringwald return 0;
177bdcc259dSMatthias Ringwald }
178bdcc259dSMatthias Ringwald
179bdcc259dSMatthias Ringwald if (!uECC_shared_secret(public1, private2, secret2)) {
180bdcc259dSMatthias Ringwald printf("shared_secret() failed (2)\n");
181bdcc259dSMatthias Ringwald return 0;
182bdcc259dSMatthias Ringwald }
183bdcc259dSMatthias Ringwald
184bdcc259dSMatthias Ringwald if (memcmp(secret1, secret2, sizeof(secret1)) != 0) {
185bdcc259dSMatthias Ringwald printf("Shared secrets are not identical!\n");
186bdcc259dSMatthias Ringwald printf("Shared secret 1 = ");
187bdcc259dSMatthias Ringwald hexdump_key(secret1, uECC_BYTES);
188bdcc259dSMatthias Ringwald printf("Shared secret 2 = ");
189bdcc259dSMatthias Ringwald hexdump_key(secret2, uECC_BYTES);
190bdcc259dSMatthias Ringwald printf("Expected secret = "); hexdump_key(secret1, uECC_BYTES);
191bdcc259dSMatthias Ringwald return 0;
192bdcc259dSMatthias Ringwald }
193bdcc259dSMatthias Ringwald // printf("Shared secret = "); hexdump_key(secret1, uECC_BYTES);
194bdcc259dSMatthias Ringwald return 1;
195bdcc259dSMatthias Ringwald }
196bdcc259dSMatthias Ringwald
test_generate(void)197bdcc259dSMatthias Ringwald int test_generate(void){
198bdcc259dSMatthias Ringwald // use stdlib rand with fixed seed for testing
199bdcc259dSMatthias Ringwald srand(0);
200bdcc259dSMatthias Ringwald
201bdcc259dSMatthias Ringwald uint8_t d[uECC_BYTES];
202bdcc259dSMatthias Ringwald uint8_t q[uECC_BYTES * 2];
203bdcc259dSMatthias Ringwald
204bdcc259dSMatthias Ringwald if (!uECC_make_key(q, d)) {
205bdcc259dSMatthias Ringwald printf("uECC_make_key() failed\n");
206bdcc259dSMatthias Ringwald return 1;
207bdcc259dSMatthias Ringwald }
208bdcc259dSMatthias Ringwald
209bdcc259dSMatthias Ringwald // print keypair
210bdcc259dSMatthias Ringwald printf("d: "); hexdump_key(d, uECC_BYTES);
211bdcc259dSMatthias Ringwald printf("X: "); hexdump_key(&q[00], uECC_BYTES);
212bdcc259dSMatthias Ringwald printf("Y: "); hexdump_key(&q[16], uECC_BYTES);
213bdcc259dSMatthias Ringwald
214bdcc259dSMatthias Ringwald // verify public key
215bdcc259dSMatthias Ringwald if (!uECC_valid_public_key(q)){
216bdcc259dSMatthias Ringwald printf("uECC_valid_public_key() == 0 -> generated public key invalid\n");
217bdcc259dSMatthias Ringwald return 1;
218bdcc259dSMatthias Ringwald }
219bdcc259dSMatthias Ringwald
220bdcc259dSMatthias Ringwald // verify private key?
221bdcc259dSMatthias Ringwald // TODO:
222bdcc259dSMatthias Ringwald
223bdcc259dSMatthias Ringwald return 0;
224bdcc259dSMatthias Ringwald }
225bdcc259dSMatthias Ringwald
main(void)226bdcc259dSMatthias Ringwald int main(void){
227*80dcb211SMatthias Ringwald // check configuration
228*80dcb211SMatthias Ringwald btstack_assert(uECC_curve() == uECC_secp256r1);
229*80dcb211SMatthias Ringwald btstack_assert(uECC_bytes() == 32);
230*80dcb211SMatthias Ringwald
231*80dcb211SMatthias Ringwald // check zero key is invalid
232*80dcb211SMatthias Ringwald uint8_t q[uECC_BYTES * 2];
233*80dcb211SMatthias Ringwald memset(q, 0, sizeof(q));
234*80dcb211SMatthias Ringwald btstack_assert(uECC_valid_public_key(q) == 0);
235*80dcb211SMatthias Ringwald
236*80dcb211SMatthias Ringwald // check key genration without rng
237*80dcb211SMatthias Ringwald uint8_t d[uECC_BYTES];
238*80dcb211SMatthias Ringwald btstack_assert(uECC_make_key(q, d) == 0);
239*80dcb211SMatthias Ringwald
240bdcc259dSMatthias Ringwald uECC_set_rng(&test_generate_f_rng);
241bdcc259dSMatthias Ringwald test_set1();
242bdcc259dSMatthias Ringwald test_set2();
243bdcc259dSMatthias Ringwald test_generate();
244bdcc259dSMatthias Ringwald return 0;
245bdcc259dSMatthias Ringwald }
246