]> git.cryptolib.org Git - avr-crypto-lib.git/blob - test_src/main-rsa_pkcs15-test.c
added rsa pkcs#1 v1.5 encryption
[avr-crypto-lib.git] / test_src / main-rsa_pkcs15-test.c
1 /* main-dsa-test.c */
2 /*
3     This file is part of the ARM-Crypto-Lib.
4     Copyright (C) 2010 Daniel Otte (daniel.otte@rub.de)
5
6     This program is free software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 /*
20  * RSA test-suit
21  *
22 */
23 #include "main-test-common.h"
24
25 #include "noekeon.h"
26 #include "noekeon_prng.h"
27 #include "bigint.h"
28 #include "bigint_io.h"
29 #include "random_dummy.h"
30 #include "rsa_basic.h"
31 #include "rsa_pkcs15.h"
32
33 #include "performance_test.h"
34
35 const char* algo_name = "RSA-PKCS15";
36
37 #define BIGINT_CEIL(x) ((((x) + sizeof(bigint_word_t) - 1) / sizeof(bigint_word_t)) *  sizeof(bigint_word_t))
38 #define BIGINT_OFF(x) ((sizeof(bigint_word_t) - (x) % sizeof(bigint_word_t)) % sizeof(bigint_word_t))
39
40 /*****************************************************************************
41  *  additional validation-functions                                                                                      *
42  *****************************************************************************/
43
44 /* Modulus: */
45 const uint8_t modulus[] PROGMEM = {
46 0xa8, 0xb3, 0xb2, 0x84, 0xaf, 0x8e, 0xb5, 0x0b, 0x38, 0x70, 0x34, 0xa8, 0x60, 0xf1, 0x46, 0xc4,
47 0x91, 0x9f, 0x31, 0x87, 0x63, 0xcd, 0x6c, 0x55, 0x98, 0xc8, 0xae, 0x48, 0x11, 0xa1, 0xe0, 0xab,
48 0xc4, 0xc7, 0xe0, 0xb0, 0x82, 0xd6, 0x93, 0xa5, 0xe7, 0xfc, 0xed, 0x67, 0x5c, 0xf4, 0x66, 0x85,
49 0x12, 0x77, 0x2c, 0x0c, 0xbc, 0x64, 0xa7, 0x42, 0xc6, 0xc6, 0x30, 0xf5, 0x33, 0xc8, 0xcc, 0x72,
50 0xf6, 0x2a, 0xe8, 0x33, 0xc4, 0x0b, 0xf2, 0x58, 0x42, 0xe9, 0x84, 0xbb, 0x78, 0xbd, 0xbf, 0x97,
51 0xc0, 0x10, 0x7d, 0x55, 0xbd, 0xb6, 0x62, 0xf5, 0xc4, 0xe0, 0xfa, 0xb9, 0x84, 0x5c, 0xb5, 0x14,
52 0x8e, 0xf7, 0x39, 0x2d, 0xd3, 0xaa, 0xff, 0x93, 0xae, 0x1e, 0x6b, 0x66, 0x7b, 0xb3, 0xd4, 0x24,
53 0x76, 0x16, 0xd4, 0xf5, 0xba, 0x10, 0xd4, 0xcf, 0xd2, 0x26, 0xde, 0x88, 0xd3, 0x9f, 0x16, 0xfb
54 };
55
56 /* Public exponent: */
57 const uint8_t pub_exponent[] PROGMEM = { 0x01, 0x00, 0x01 };
58
59 /* Exponent: */
60 const uint8_t priv_exponent[] PROGMEM = {
61 0x53, 0x33, 0x9c, 0xfd, 0xb7, 0x9f, 0xc8, 0x46, 0x6a, 0x65, 0x5c, 0x73, 0x16, 0xac, 0xa8, 0x5c,
62 0x55, 0xfd, 0x8f, 0x6d, 0xd8, 0x98, 0xfd, 0xaf, 0x11, 0x95, 0x17, 0xef, 0x4f, 0x52, 0xe8, 0xfd,
63 0x8e, 0x25, 0x8d, 0xf9, 0x3f, 0xee, 0x18, 0x0f, 0xa0, 0xe4, 0xab, 0x29, 0x69, 0x3c, 0xd8, 0x3b,
64 0x15, 0x2a, 0x55, 0x3d, 0x4a, 0xc4, 0xd1, 0x81, 0x2b, 0x8b, 0x9f, 0xa5, 0xaf, 0x0e, 0x7f, 0x55,
65 0xfe, 0x73, 0x04, 0xdf, 0x41, 0x57, 0x09, 0x26, 0xf3, 0x31, 0x1f, 0x15, 0xc4, 0xd6, 0x5a, 0x73,
66 0x2c, 0x48, 0x31, 0x16, 0xee, 0x3d, 0x3d, 0x2d, 0x0a, 0xf3, 0x54, 0x9a, 0xd9, 0xbf, 0x7c, 0xbf,
67 0xb7, 0x8a, 0xd8, 0x84, 0xf8, 0x4d, 0x5b, 0xeb, 0x04, 0x72, 0x4d, 0xc7, 0x36, 0x9b, 0x31, 0xde,
68 0xf3, 0x7d, 0x0c, 0xf5, 0x39, 0xe9, 0xcf, 0xcd, 0xd3, 0xde, 0x65, 0x37, 0x29, 0xea, 0xd5, 0xd1
69 };
70
71 /* Prime 1: */
72 const uint8_t p[] PROGMEM = {
73 0xd3, 0x27, 0x37, 0xe7, 0x26, 0x7f, 0xfe, 0x13, 0x41, 0xb2, 0xd5, 0xc0, 0xd1, 0x50, 0xa8, 0x1b,
74 0x58, 0x6f, 0xb3, 0x13, 0x2b, 0xed, 0x2f, 0x8d, 0x52, 0x62, 0x86, 0x4a, 0x9c, 0xb9, 0xf3, 0x0a,
75 0xf3, 0x8b, 0xe4, 0x48, 0x59, 0x8d, 0x41, 0x3a, 0x17, 0x2e, 0xfb, 0x80, 0x2c, 0x21, 0xac, 0xf1,
76 0xc1, 0x1c, 0x52, 0x0c, 0x2f, 0x26, 0xa4, 0x71, 0xdc, 0xad, 0x21, 0x2e, 0xac, 0x7c, 0xa3, 0x9d
77 };
78
79 /* Prime 2: */
80 const uint8_t q[] PROGMEM = {
81 0xcc, 0x88, 0x53, 0xd1, 0xd5, 0x4d, 0xa6, 0x30, 0xfa, 0xc0, 0x04, 0xf4, 0x71, 0xf2, 0x81, 0xc7,
82 0xb8, 0x98, 0x2d, 0x82, 0x24, 0xa4, 0x90, 0xed, 0xbe, 0xb3, 0x3d, 0x3e, 0x3d, 0x5c, 0xc9, 0x3c,
83 0x47, 0x65, 0x70, 0x3d, 0x1d, 0xd7, 0x91, 0x64, 0x2f, 0x1f, 0x11, 0x6a, 0x0d, 0xd8, 0x52, 0xbe,
84 0x24, 0x19, 0xb2, 0xaf, 0x72, 0xbf, 0xe9, 0xa0, 0x30, 0xe8, 0x60, 0xb0, 0x28, 0x8b, 0x5d, 0x77
85 };
86
87 /* Prime exponent 1: */
88 const uint8_t dp[] PROGMEM = {
89 0x0e, 0x12, 0xbf, 0x17, 0x18, 0xe9, 0xce, 0xf5, 0x59, 0x9b, 0xa1, 0xc3, 0x88, 0x2f, 0xe8, 0x04,
90 0x6a, 0x90, 0x87, 0x4e, 0xef, 0xce, 0x8f, 0x2c, 0xcc, 0x20, 0xe4, 0xf2, 0x74, 0x1f, 0xb0, 0xa3,
91 0x3a, 0x38, 0x48, 0xae, 0xc9, 0xc9, 0x30, 0x5f, 0xbe, 0xcb, 0xd2, 0xd7, 0x68, 0x19, 0x96, 0x7d,
92 0x46, 0x71, 0xac, 0xc6, 0x43, 0x1e, 0x40, 0x37, 0x96, 0x8d, 0xb3, 0x78, 0x78, 0xe6, 0x95, 0xc1
93 };
94
95 /* Prime exponent 2: */
96 const uint8_t dq[] PROGMEM = {
97 0x95, 0x29, 0x7b, 0x0f, 0x95, 0xa2, 0xfa, 0x67, 0xd0, 0x07, 0x07, 0xd6, 0x09, 0xdf, 0xd4, 0xfc,
98 0x05, 0xc8, 0x9d, 0xaf, 0xc2, 0xef, 0x6d, 0x6e, 0xa5, 0x5b, 0xec, 0x77, 0x1e, 0xa3, 0x33, 0x73,
99 0x4d, 0x92, 0x51, 0xe7, 0x90, 0x82, 0xec, 0xda, 0x86, 0x6e, 0xfe, 0xf1, 0x3c, 0x45, 0x9e, 0x1a,
100 0x63, 0x13, 0x86, 0xb7, 0xe3, 0x54, 0xc8, 0x99, 0xf5, 0xf1, 0x12, 0xca, 0x85, 0xd7, 0x15, 0x83
101 };
102
103 /* Coefficient: */
104 const uint8_t qinv[] PROGMEM = {
105 0x4f, 0x45, 0x6c, 0x50, 0x24, 0x93, 0xbd, 0xc0, 0xed, 0x2a, 0xb7, 0x56, 0xa3, 0xa6, 0xed, 0x4d,
106 0x67, 0x35, 0x2a, 0x69, 0x7d, 0x42, 0x16, 0xe9, 0x32, 0x12, 0xb1, 0x27, 0xa6, 0x3d, 0x54, 0x11,
107 0xce, 0x6f, 0xa9, 0x8d, 0x5d, 0xbe, 0xfd, 0x73, 0x26, 0x3e, 0x37, 0x28, 0x14, 0x27, 0x43, 0x81,
108 0x81, 0x66, 0xed, 0x7d, 0xd6, 0x36, 0x87, 0xdd, 0x2a, 0x8c, 0xa1, 0xd2, 0xf4, 0xfb, 0xd8, 0xe1
109 };
110
111 /* PKCS#1 v1.5 encryption of 0x20, random messages with random s0xee,ds
112  *  ---------------------------------------------------------------------------
113  */
114
115 /* Message: */
116 const uint8_t message_x[] PROGMEM = {
117 0x66, 0x28, 0x19, 0x4e, 0x12, 0x07, 0x3d, 0xb0, 0x3b, 0xa9, 0x4c, 0xda, 0x9e, 0xf9, 0x53, 0x23,
118 0x97, 0xd5, 0x0d, 0xba, 0x79, 0xb9, 0x87, 0x00, 0x4a, 0xfe, 0xfe, 0x34
119 };
120
121 /* Seed: */
122 const uint8_t seed_x[] PROGMEM = {
123 0x01, 0x73, 0x41, 0xae, 0x38, 0x75, 0xd5, 0xf8, 0x71, 0x01, 0xf8, 0xcc, 0x4f, 0xa9, 0xb9, 0xbc,
124 0x15, 0x6b, 0xb0, 0x46, 0x28, 0xfc, 0xcd, 0xb2, 0xf4, 0xf1, 0x1e, 0x90, 0x5b, 0xd3, 0xa1, 0x55,
125 0xd3, 0x76, 0xf5, 0x93, 0xbd, 0x73, 0x04, 0x21, 0x08, 0x74, 0xeb, 0xa0, 0x8a, 0x5e, 0x22, 0xbc,
126 0xcc, 0xb4, 0xc9, 0xd3, 0x88, 0x2a, 0x93, 0xa5, 0x4d, 0xb0, 0x22, 0xf5, 0x03, 0xd1, 0x63, 0x38,
127 0xb6, 0xb7, 0xce, 0x16, 0xdc, 0x7f, 0x4b, 0xbf, 0x9a, 0x96, 0xb5, 0x97, 0x72, 0xd6, 0x60, 0x6e,
128 0x97, 0x47, 0xc7, 0x64, 0x9b, 0xf9, 0xe0, 0x83, 0xdb, 0x98, 0x18, 0x84, 0xa9, 0x54, 0xab, 0x3c,
129 0x6f };
130
131 /* Encryption: */
132 const uint8_t encrypted_x[] PROGMEM = {
133 0x50, 0xb4, 0xc1, 0x41, 0x36, 0xbd, 0x19, 0x8c, 0x2f, 0x3c, 0x3e, 0xd2, 0x43, 0xfc, 0xe0, 0x36,
134 0xe1, 0x68, 0xd5, 0x65, 0x17, 0x98, 0x4a, 0x26, 0x3c, 0xd6, 0x64, 0x92, 0xb8, 0x08, 0x04, 0xf1,
135 0x69, 0xd2, 0x10, 0xf2, 0xb9, 0xbd, 0xfb, 0x48, 0xb1, 0x2f, 0x9e, 0xa0, 0x50, 0x09, 0xc7, 0x7d,
136 0xa2, 0x57, 0xcc, 0x60, 0x0c, 0xce, 0xfe, 0x3a, 0x62, 0x83, 0x78, 0x9d, 0x8e, 0xa0, 0xe6, 0x07,
137 0xac, 0x58, 0xe2, 0x69, 0x0e, 0xc4, 0xeb, 0xc1, 0x01, 0x46, 0xe8, 0xcb, 0xaa, 0x5e, 0xd4, 0xd5,
138 0xcc, 0xe6, 0xfe, 0x7b, 0x0f, 0xf9, 0xef, 0xc1, 0xea, 0xbb, 0x56, 0x4d, 0xbf, 0x49, 0x82, 0x85,
139 0xf4, 0x49, 0xee, 0x61, 0xdd, 0x7b, 0x42, 0xee, 0x5b, 0x58, 0x92, 0xcb, 0x90, 0x60, 0x1f, 0x30,
140 0xcd, 0xa0, 0x7b, 0xf2, 0x64, 0x89, 0x31, 0x0b, 0xcd, 0x23, 0xb5, 0x28, 0xce, 0xab, 0x3c, 0x31
141 };
142
143 uint8_t keys_allocated = 0;
144 rsa_publickey_t pub_key;
145 rsa_privatekey_t priv_key;
146
147 #if 1
148   #define MSG       message_x
149   #define SEED      seed_x
150   #define ENCRYPTED encrypted_x
151   #define MODULUS modulus
152   #define PUB_EXPONENT pub_exponent
153   #define PRIV_EXPONENT priv_exponent
154   #define P p
155   #define Q q
156   #define DP dp
157   #define DQ dq
158   #define QINV qinv
159 #endif
160
161
162 uint8_t convert_nibble(uint8_t c){
163         if(c>='0' && c<='9'){
164                 return c - '0';
165         }
166         c |= 'A' ^ 'a';
167         if(c>='a' && c<='f'){
168                 return c - 'a' + 10;
169         }
170         return 0xff;
171 }
172
173 const char *block_ignore_string=" \t\r\n,;";
174 #define BUFFER_LIMIT 120
175 uint16_t read_os(void* dst, uint16_t length, const char* ignore_string){
176         uint16_t counter = 0;
177         uint16_t c;
178         uint8_t v, tmp = 0, idx = 0;
179         if(!ignore_string){
180                 ignore_string = block_ignore_string;
181         }
182         while(counter < length){
183                 c = cli_getc();
184                 if(c > 0xff){
185                         return counter;
186                 }
187                 if(strchr(ignore_string, c)){
188                         continue;
189                 }
190                 v = convert_nibble(c);
191                 if(v > 0x0f){
192                         return counter;
193                 }
194                 if(idx){
195                         ((uint8_t*)dst)[counter++] = (tmp << 4) | v;
196                         idx = 0;
197                         if(counter % (BUFFER_LIMIT/2) == 0){
198                                 cli_putc('.');
199                         }
200                 }else{
201                         tmp = v;
202                         idx = 1;
203                 }
204         }
205         return counter;
206 }
207
208 uint16_t own_atou(const char* str){
209         uint16_t r=0;
210         while(*str && *str >= '0' && *str <= '9'){
211                 r *= 10;
212                 r += *str++ - '0';
213         }
214         return r;
215 }
216
217 uint8_t read_bigint(bigint_t* a, char* prompt){
218         uint16_t read_length, actual_length;
219         uint8_t off;
220         uint8_t *buffer;
221         char read_int_str[18];
222         cli_putstr(prompt);
223         cli_putstr_P(PSTR("\r\n  length: "));
224         cli_getsn(read_int_str, 16);
225         read_length = own_atou(read_int_str);
226         off = (sizeof(bigint_word_t) - (read_length % sizeof(bigint_word_t))) % sizeof(bigint_word_t);
227         buffer = malloc(((read_length + sizeof(bigint_word_t) - 1) / sizeof(bigint_word_t)) * sizeof(bigint_word_t));
228         if(!buffer){
229                 cli_putstr_P(PSTR("\r\nERROR: OOM!"));
230                 return 2;
231         }
232         cli_putstr_P(PSTR("\r\n  data: "));
233         memset(buffer, 0, sizeof(bigint_word_t));
234         actual_length = read_os(buffer + off, read_length, NULL);
235         if(actual_length != read_length){
236                 cli_putstr_P(PSTR("\r\nERROR: unexpected end of data!"));
237                 free(buffer);
238                 return 1;
239         }
240         a->wordv = (bigint_word_t*)buffer;
241         a->length_B = (read_length + sizeof(bigint_word_t) - 1) / sizeof(bigint_word_t);
242         bigint_changeendianess(a);
243         bigint_adjust(a);
244         return 0;
245 }
246
247 uint8_t pre_alloc_key_crt(void){
248         uint8_t c;
249         pub_key.modulus = malloc(sizeof(bigint_t));
250         if(!pub_key.modulus){
251                 cli_putstr_P(PSTR("\r\nERROR: OOM!"));
252                 return 2;
253         }
254         priv_key.modulus = pub_key.modulus;
255         priv_key.n = 5;
256         priv_key.components = malloc(5 * sizeof(bigint_t*));
257         if(!priv_key.components){
258                 cli_putstr_P(PSTR("\r\nERROR: OOM!"));
259                 return 2;
260         }
261         pub_key.exponent = malloc(sizeof(bigint_t));
262         if(!pub_key.exponent){
263                 cli_putstr_P(PSTR("\r\nERROR: OOM!"));
264                 return 2;
265         }
266         for(c=0; c<5; ++c){
267                 priv_key.components[c] = malloc(sizeof(bigint_t));
268                 if(!priv_key.components[c]){
269                         cli_putstr_P(PSTR("\r\nERROR: OOM!"));
270                         return 2;
271                 }
272         }
273         return 0;
274 }
275
276 void free_key(void){
277         uint8_t c;
278         free(pub_key.modulus->wordv);
279         free(pub_key.exponent->wordv);
280         free(pub_key.modulus);
281         pub_key.modulus = priv_key.modulus = NULL;
282         free(pub_key.exponent);
283         pub_key.exponent = NULL;
284         for(c = 0; c < priv_key.n; ++c){
285                 free(priv_key.components[c]->wordv);
286                 free(priv_key.components[c]);
287         }
288         free(priv_key.components);
289         priv_key.components = NULL;
290 }
291
292 uint8_t read_key_crt(void){
293         uint8_t r;
294         cli_putstr_P(PSTR("\r\n== reading key (crt) =="));
295         r = pre_alloc_key_crt();
296         if(r) return r;
297         r = read_bigint(pub_key.modulus,"\r\n = module =");
298         if(r) return r;
299         r = read_bigint(pub_key.exponent,"\r\n = public exponent =");
300         if(r) return r;
301         r = read_bigint(priv_key.components[0],"\r\n = p (first prime) =");
302         if(r) return r;
303         r = read_bigint(priv_key.components[1],"\r\n = q (second prime) =");
304         if(r) return r;
305         r = read_bigint(priv_key.components[2],"\r\n = dp (p's exponent) =");
306         if(r) return r;
307         r = read_bigint(priv_key.components[3],"\r\n = dq (q's exponent) =");
308         if(r) return r;
309         r = read_bigint(priv_key.components[4],"\r\n = qInv (q' coefficient) =");
310 /*
311         cli_putstr_P(PSTR("\r\nmodulus:"));
312         bigint_print_hex(pub_key.modulus);
313         cli_putstr_P(PSTR("\r\npublic exponent:"));
314         bigint_print_hex(pub_key.exponent);
315         cli_putstr_P(PSTR("\r\np:"));
316         bigint_print_hex(priv_key.components[0]);
317         cli_putstr_P(PSTR("\r\nq:"));
318         bigint_print_hex(priv_key.components[1]);
319         cli_putstr_P(PSTR("\r\ndP:"));
320         bigint_print_hex(priv_key.components[2]);
321         cli_putstr_P(PSTR("\r\ndQ:"));
322         bigint_print_hex(priv_key.components[3]);
323         cli_putstr_P(PSTR("\r\nqInv:"));
324         bigint_print_hex(priv_key.components[4]);
325 */
326         return r;
327 }
328
329 uint8_t read_key_conv(void){
330         uint8_t r;
331         cli_putstr_P(PSTR("\r\n== reading key (crt) =="));
332         pub_key.modulus = malloc(sizeof(bigint_t));
333         if(!pub_key.modulus){
334                 cli_putstr_P(PSTR("\r\nERROR: OOM!"));
335                 return 2;
336         }
337         r = read_bigint(pub_key.modulus,"\r\n = module =");
338         if(r) return r;
339         priv_key.modulus = pub_key.modulus;
340         priv_key.n = 1;
341         pub_key.exponent = malloc(sizeof(bigint_t));
342         if(!pub_key.exponent){
343                 cli_putstr_P(PSTR("\r\nERROR: OOM!"));
344                 return 2;
345         }
346         priv_key.components = malloc(sizeof(bigint_t*));
347         if(!priv_key.components){
348                 cli_putstr_P(PSTR("\r\nERROR: OOM!"));
349                 return 2;
350         }
351         priv_key.components[0] = malloc(sizeof(bigint_t));
352         if(!priv_key.components[0]){
353                 cli_putstr_P(PSTR("\r\nERROR: OOM!"));
354                 return 2;
355         }
356         r = read_bigint(pub_key.exponent,"\r\n = public exponent =");
357         if(r) return r;
358         r = read_bigint(priv_key.components[0],"\r\n = private exponent =");
359         return r;
360 }
361
362 void load_priv_conventional(void){
363         bigint_t *epriv;
364         epriv = malloc(sizeof(bigint_t));
365         if(!epriv){
366                 cli_putstr_P(PSTR("\r\nERROR: OOM!"));
367                 return;
368         }
369         epriv->length_B = (sizeof(PRIV_EXPONENT) + sizeof(bigint_word_t) - 1) / sizeof(bigint_word_t);
370         epriv->wordv =  malloc(epriv->length_B * sizeof(bigint_word_t));
371         if(!epriv->wordv){
372                 cli_putstr_P(PSTR("\r\nERROR: OOM!"));
373                 return;
374         }
375         memcpy(epriv->wordv, PRIV_EXPONENT, sizeof(PRIV_EXPONENT));
376         priv_key.components = malloc(sizeof(bigint_t*));
377         priv_key.components[0] = epriv;
378         priv_key.n = 1;
379         bigint_changeendianess(epriv);
380         bigint_adjust(epriv);
381 }
382
383
384 void load_priv_crt_mono(void){
385         bigint_t **v;
386         const uint8_t *bv[5] = {P,Q,DP,DQ,QINV};
387         uint16_t sv[5] = {sizeof(P), sizeof(Q), sizeof(DP), sizeof(DQ), sizeof(QINV)};
388         uint8_t i;
389         v = malloc(5 * sizeof(bigint_t));
390         if(!v){
391                 cli_putstr_P(PSTR("\r\nERROR: OOM!"));
392                 return;
393         }
394         priv_key.components = malloc(5*sizeof(bigint_t*));
395         if(!priv_key.components){
396                 cli_putstr_P(PSTR("\r\nERROR: OOM!"));
397                 return;
398         }
399         priv_key.n = 5;
400         for(i=0; i<5; ++i){
401                 v[i] = malloc(sizeof(bigint_t));
402                 v[i]->info = 0;
403                 v[i]->length_B = (sv[i] + sizeof(bigint_word_t) - 1) / sizeof(bigint_word_t);
404                 v[i]->wordv = calloc(v[i]->length_B , sizeof(bigint_word_t));
405                 if(!v[i]->wordv){
406                         cli_putstr_P(PSTR("\r\nERROR: OOM!"));
407                         return;
408                 }
409                 memcpy(v[i]->wordv, bv[i], sv[i]);
410                 bigint_changeendianess(v[i]);
411                 bigint_adjust(v[i]);
412                 priv_key.components[i] = v[i];
413         }
414 }
415
416 uint8_t load_bigint_from_os(bigint_t* a, PGM_VOID_P os, uint16_t length_B){
417         a->length_B = BIGINT_CEIL(length_B) / sizeof(bigint_word_t);
418         a->wordv = malloc(BIGINT_CEIL(length_B));
419         if(!a->wordv){
420                 cli_putstr_P(PSTR("\r\nOOM!\r\n"));
421                 return 1;
422         }
423         memset(a->wordv, 0, sizeof(bigint_word_t));
424         memcpy_P((uint8_t*)a->wordv + BIGINT_OFF(length_B), os, length_B);
425         a->info = 0;
426         bigint_changeendianess(a);
427         bigint_adjust(a);
428         return 0;
429 }
430
431 void load_fix_rsa(void){
432         if(keys_allocated){
433                 free_key();
434         }
435         keys_allocated = 1;
436
437         if(pre_alloc_key_crt()){
438                 cli_putstr_P(PSTR("\r\nOOM!\r\n"));
439                 return;
440         }
441
442         load_bigint_from_os(pub_key.modulus, MODULUS, sizeof(MODULUS));
443         load_bigint_from_os(pub_key.exponent, PUB_EXPONENT, sizeof(PUB_EXPONENT));
444         priv_key.n = 5;
445         load_bigint_from_os(priv_key.components[0], P, sizeof(P));
446         load_bigint_from_os(priv_key.components[1], Q, sizeof(Q));
447         load_bigint_from_os(priv_key.components[2], DP, sizeof(DP));
448         load_bigint_from_os(priv_key.components[3], DQ, sizeof(DQ));
449         load_bigint_from_os(priv_key.components[4], QINV, sizeof(QINV));
450
451 //      load_priv_conventional();
452 //      load_priv_crt_mono();
453 }
454
455 void quick_test(void){
456         uint8_t *ciphertext, *plaintext, rc;
457         uint8_t seed[sizeof(SEED)], seed_out[sizeof(SEED)];
458         uint16_t clen, plen;
459         if(!keys_allocated){
460                 load_fix_rsa();
461         }
462         ciphertext = malloc(clen = pub_key.modulus->length_B * sizeof(bigint_word_t));
463         plaintext = malloc(pub_key.modulus->length_B * sizeof(bigint_word_t));
464         memcpy_P(plaintext, MSG, sizeof(MSG));
465         memcpy_P(seed, SEED, sizeof(SEED));
466         cli_putstr_P(PSTR("\r\nplaintext:"));
467         cli_hexdump_block(plaintext, sizeof(MSG), 4, 16);
468         cli_putstr_P(PSTR("\r\nseed:"));
469         cli_hexdump_block(seed, sizeof(SEED), 4, 16);
470         cli_putstr_P(PSTR("\r\nencrypting: ..."));
471
472         rc = rsa_encrypt_pkcs15(ciphertext, &clen, plaintext, sizeof(MSG), &pub_key, seed);
473         if(rc){
474                 cli_putstr_P(PSTR("\r\nERROR: rsa_encrypt_pkcs15 returned: "));
475                 cli_hexdump_byte(rc);
476                 return;
477
478         }
479
480         cli_putstr_P(PSTR("\r\n\r\nciphertext:"));
481         cli_hexdump_block(ciphertext, clen, 4, 16);
482         if(clen!=sizeof(ENCRYPTED)){
483                         cli_putstr_P(PSTR("\r\n>>FAIL (no size match)<<"));
484         }else{
485                 if(memcmp_P(ciphertext, ENCRYPTED, clen)){
486                         cli_putstr_P(PSTR("\r\n>>FAIL (no content match)<<"));
487                 }else{
488                         cli_putstr_P(PSTR("\r\n>>OK<<"));
489                 }
490         }
491
492         cli_putstr_P(PSTR("\r\ndecrypting: ..."));
493         rc = rsa_decrypt_pkcs15(plaintext, &plen, ciphertext, clen, &priv_key, seed_out);
494         if(rc){
495                 cli_putstr_P(PSTR("\r\nERROR: rsa_decrypt_pkcs15 returned: "));
496                 cli_hexdump_byte(rc);
497                 return;
498         }
499         cli_putstr_P(PSTR("\r\n\r\nplaintext:"));
500         cli_hexdump_block(plaintext, plen, 4, 16);
501         cli_putstr_P(PSTR("\r\n\r\nseed (out):"));
502         cli_hexdump_block(seed_out, sizeof(SEED), 4, 16);
503
504         free(ciphertext);
505         free(plaintext);
506 }
507
508 void run_seed_test(void){
509         uint8_t *msg, *ciph, *msg_;
510         uint16_t msg_len, ciph_len, msg_len_;
511         uint16_t seed_len;
512         uint8_t *seed, *seed_out;
513         char read_int_str[18];
514         cli_putstr_P(PSTR("\r\n== test with given seed =="));
515         cli_putstr_P(PSTR("\r\n = message ="));
516         cli_putstr_P(PSTR("\r\n  length: "));
517         cli_getsn(read_int_str, 16);
518         msg_len = own_atou(read_int_str);
519         seed_len = rsa_pkcs15_compute_padlength_B(pub_key.modulus, msg_len);
520         seed = malloc(seed_len);
521         if(!seed){
522                 cli_putstr_P(PSTR("\r\nERROR: OOM!"));
523                 return;
524         }
525         seed_out = malloc(seed_len);
526         if(!seed_out){
527                 cli_putstr_P(PSTR("\r\nERROR: OOM!"));
528                 return;
529         }
530         msg = malloc(msg_len);
531         if(!msg){
532                 cli_putstr_P(PSTR("\r\nERROR: OOM!"));
533                 return;
534         }
535         ciph = malloc(bigint_length_B(pub_key.modulus));
536         if(!ciph){
537                 cli_putstr_P(PSTR("\r\nERROR: OOM!"));
538                 return;
539         }
540         msg_ = malloc(bigint_length_B(pub_key.modulus));
541         if(!msg_){
542                 cli_putstr_P(PSTR("\r\nERROR: OOM!"));
543                 return;
544         }
545         cli_putstr_P(PSTR("\r\n  data: "));
546         read_os(msg, msg_len, NULL);
547         cli_putstr_P(PSTR("\r\n  seed (0x"));
548         cli_hexdump_rev(&seed_len, 2);
549         cli_putstr_P(PSTR(" bytes): "));
550         read_os(seed, seed_len, NULL);
551
552         cli_putstr_P(PSTR("\r\n  encrypting ..."));
553 /*
554         cli_putstr_P(PSTR("\r\n plaintext:"));
555         cli_hexdump_block(msg, msg_len, 4, 16);
556         cli_putstr_P(PSTR("\r\n seed:"));
557         cli_hexdump_block(seed, seed_len, 4, 16);
558 */
559         rsa_encrypt_pkcs15(ciph, &ciph_len, msg, msg_len, &pub_key, seed);
560         cli_putstr_P(PSTR("\r\n  ciphertext:"));
561         cli_hexdump_block(ciph, ciph_len, 4, 16);
562         cli_putstr_P(PSTR("\r\n  decrypting ... "));
563         rsa_decrypt_pkcs15(msg_, &msg_len_, ciph, ciph_len, &priv_key, seed_out);
564         cli_putstr_P(PSTR("[done]"));
565         if(msg_len != msg_len_){
566                 char tstr[16];
567                 cli_putstr_P(PSTR("\r\nERROR: wrong decrypted message length ("));
568                 itoa(msg_len_, tstr, 10);
569                 cli_putstr(tstr);
570                 cli_putstr_P(PSTR(" instead of "));
571                 itoa(msg_len, tstr, 10);
572                 cli_putstr(tstr);
573                 cli_putc(')');
574                 goto end;
575         }
576         if(memcmp(msg, msg_, msg_len)){
577                 cli_putstr_P(PSTR("\r\nERROR: wrong decrypted message:"));
578                 cli_hexdump_block(msg_, msg_len_, 4, 16);
579                 cli_putstr_P(PSTR("\r\nreference:"));
580                 cli_hexdump_block(msg, msg_len, 4, 16);
581                 goto end;
582         }
583
584         if(memcmp(seed, seed_out, seed_len)){
585                 cli_putstr_P(PSTR("\r\nERROR: wrong decrypted seed:"));
586                 cli_hexdump_block(seed_out, seed_len, 4, 16);
587                 cli_putstr_P(PSTR("\r\nreference:"));
588                 cli_hexdump_block(seed, seed_len, 4, 16);
589                 goto end;
590         }
591         cli_putstr_P(PSTR("\r\n  >>OK<<"));
592 end:
593         free(ciph);
594         free(msg_);
595         free(msg);
596         free(seed_out);
597         free(seed);
598 }
599
600 void reset_prng(void){
601         uint8_t buf[16];
602         memset(buf, 0, 16);
603         random_seed(buf);
604         cli_putstr_P(PSTR("\r\nPRNG reset"));
605 }
606
607 void rsa_init(void){
608         prng_get_byte = random8;
609 }
610
611 void load_key(void){
612         if(keys_allocated){
613                 free_key();
614         }
615         keys_allocated = 1;
616         read_key_crt();
617 }
618
619 void test_dump(void){
620         char lstr[16];
621         int len;
622         cli_putstr_P(PSTR("\r\nenter dump length: "));
623         cli_getsn_cecho(lstr, 15);
624         len = own_atou(lstr);
625         cli_putstr_P(PSTR("\r\ndumping 0x"));
626         cli_hexdump_rev(&len, 2);
627         cli_putstr_P(PSTR(" byte:"));
628         cli_hexdump_block(pub_key.modulus->wordv, len, 4, 8);
629 }
630
631 /*****************************************************************************
632  *  main                                                                                                                                         *
633  *****************************************************************************/
634
635 const char echo_test_str[]    PROGMEM = "echo-test";
636 const char reset_prng_str[]   PROGMEM = "reset-prng";
637 const char load_key_str[]     PROGMEM = "load-key";
638 const char load_fix_key_str[] PROGMEM = "load-fix-key";
639 const char quick_test_str[]   PROGMEM = "quick-test";
640 const char seed_test_str[]    PROGMEM = "seed-test";
641 const char dump_test_str[]    PROGMEM = "dump-test";
642 const char performance_str[]  PROGMEM = "performance";
643 const char echo_str[]         PROGMEM = "echo";
644
645 const cmdlist_entry_t cmdlist[] PROGMEM = {
646         { reset_prng_str,       NULL, reset_prng                    },
647         { load_key_str,         NULL, load_key                      },
648         { load_fix_key_str,     NULL, load_fix_rsa                  },
649         { quick_test_str,       NULL, quick_test                    },
650         { seed_test_str,        NULL, run_seed_test                 },
651         { dump_test_str,        NULL, test_dump                     },
652 //      { performance_str,      NULL, testrun_performance_bigint    },
653         { echo_str,         (void*)1, (void_fpt)echo_ctrl           },
654         { NULL,                 NULL, NULL                          }
655 };
656
657 void dump_sp(void){
658         uint8_t x;
659         uint8_t *xa = &x;
660         cli_putstr_P(PSTR("\r\nstack pointer: ~"));
661         cli_hexdump_rev(&xa, 4);
662 }
663
664 int main (void){
665         main_setup();
666
667         for(;;){
668                 welcome_msg(algo_name);
669                 rsa_init();
670                 cmd_interface(cmdlist);
671         }
672 }