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