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