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