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