]> git.zerfleddert.de Git - proxmark3-svn/blob - client/crypto/libpcrypto.c
Code improved for less memory
[proxmark3-svn] / client / crypto / libpcrypto.c
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2018 Merlok
3 // Copyright (C) 2018 drHatson
4 //
5 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
6 // at your option, any later version. See the LICENSE.txt file for the text of
7 // the license.
8 //-----------------------------------------------------------------------------
9 // crypto commands
10 //-----------------------------------------------------------------------------
11
12 #include "crypto/libpcrypto.h"
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <string.h>
16 #include <mbedtls/asn1.h>
17 #include <mbedtls/aes.h>
18 #include <mbedtls/cmac.h>
19 #include <mbedtls/pk.h>
20 #include <mbedtls/ecdsa.h>
21 #include <mbedtls/sha256.h>
22 #include <mbedtls/sha512.h>
23 #include <mbedtls/ctr_drbg.h>
24 #include <mbedtls/entropy.h>
25 #include <mbedtls/error.h>
26 #include <crypto/asn1utils.h>
27 #include <util.h>
28
29 // NIST Special Publication 800-38A — Recommendation for block cipher modes of operation: methods and techniques, 2001.
30 int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length){
31 uint8_t iiv[16] = {0};
32 if (iv)
33 memcpy(iiv, iv, 16);
34
35 mbedtls_aes_context aes;
36 mbedtls_aes_init(&aes);
37 if (mbedtls_aes_setkey_enc(&aes, key, 128))
38 return 1;
39 if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, length, iiv, input, output))
40 return 2;
41 mbedtls_aes_free(&aes);
42
43 return 0;
44 }
45
46 int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length){
47 uint8_t iiv[16] = {0};
48 if (iv)
49 memcpy(iiv, iv, 16);
50
51 mbedtls_aes_context aes;
52 mbedtls_aes_init(&aes);
53 if (mbedtls_aes_setkey_dec(&aes, key, 128))
54 return 1;
55 if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, length, iiv, input, output))
56 return 2;
57 mbedtls_aes_free(&aes);
58
59 return 0;
60 }
61
62 // NIST Special Publication 800-38B — Recommendation for block cipher modes of operation: The CMAC mode for authentication.
63 // https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/AES_CMAC.pdf
64 int aes_cmac(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length) {
65 memset(mac, 0x00, 16);
66
67 // NIST 800-38B
68 return mbedtls_aes_cmac_prf_128(key, MBEDTLS_AES_BLOCK_SIZE, input, length, mac);
69 }
70
71 int aes_cmac8(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length) {
72 uint8_t cmac[16] = {0};
73 memset(mac, 0x00, 8);
74
75 int res = aes_cmac(iv, key, input, cmac, length);
76 if (res)
77 return res;
78
79 for(int i = 0; i < 8; i++)
80 mac[i] = cmac[i * 2 + 1];
81
82 return 0;
83 }
84
85 static uint8_t fixed_rand_value[250] = {0};
86 static int fixed_rand(void *rng_state, unsigned char *output, size_t len) {
87 if (len <= 250) {
88 memcpy(output, fixed_rand_value, len);
89 } else {
90 memset(output, 0x00, len);
91 }
92
93 return 0;
94 }
95
96 int sha256hash(uint8_t *input, int length, uint8_t *hash) {
97 if (!hash || !input)
98 return 1;
99
100 mbedtls_sha256_context sctx;
101 mbedtls_sha256_init(&sctx);
102 mbedtls_sha256_starts(&sctx, 0); // SHA-256, not 224
103 mbedtls_sha256_update(&sctx, input, length);
104 mbedtls_sha256_finish(&sctx, hash);
105 mbedtls_sha256_free(&sctx);
106
107 return 0;
108 }
109
110 int sha512hash(uint8_t *input, int length, uint8_t *hash) {
111 if (!hash || !input)
112 return 1;
113
114 mbedtls_sha512_context sctx;
115 mbedtls_sha512_init(&sctx);
116 mbedtls_sha512_starts(&sctx, 0); //SHA-512, not 384
117 mbedtls_sha512_update(&sctx, input, length);
118 mbedtls_sha512_finish(&sctx, hash);
119 mbedtls_sha512_free(&sctx);
120
121 return 0;
122 }
123
124 int ecdsa_init_str(mbedtls_ecdsa_context *ctx, char * key_d, char *key_x, char *key_y) {
125 if (!ctx)
126 return 1;
127
128 int res;
129
130 mbedtls_ecdsa_init(ctx);
131 res = mbedtls_ecp_group_load(&ctx->grp, MBEDTLS_ECP_DP_SECP256R1); // secp256r1
132 if (res)
133 return res;
134
135 if (key_d) {
136 res = mbedtls_mpi_read_string(&ctx->d, 16, key_d);
137 if (res)
138 return res;
139 }
140
141 if (key_x && key_y) {
142 res = mbedtls_ecp_point_read_string(&ctx->Q, 16, key_x, key_y);
143 if (res)
144 return res;
145 }
146
147 return 0;
148 }
149
150 int ecdsa_init(mbedtls_ecdsa_context *ctx, uint8_t * key_d, uint8_t *key_xy) {
151 if (!ctx)
152 return 1;
153
154 int res;
155
156 mbedtls_ecdsa_init(ctx);
157 res = mbedtls_ecp_group_load(&ctx->grp, MBEDTLS_ECP_DP_SECP256R1); // secp256r1
158 if (res)
159 return res;
160
161 if (key_d) {
162 res = mbedtls_mpi_read_binary(&ctx->d, key_d, 32);
163 if (res)
164 return res;
165 }
166
167 if (key_xy) {
168 res = mbedtls_ecp_point_read_binary(&ctx->grp, &ctx->Q, key_xy, 32 * 2 + 1);
169 if (res)
170 return res;
171 }
172
173 return 0;
174 }
175
176 int ecdsa_key_create(uint8_t * key_d, uint8_t *key_xy) {
177 int res;
178 mbedtls_ecdsa_context ctx;
179 ecdsa_init(&ctx, NULL, NULL);
180
181
182 mbedtls_entropy_context entropy;
183 mbedtls_ctr_drbg_context ctr_drbg;
184 const char *pers = "ecdsaproxmark";
185
186 mbedtls_entropy_init(&entropy);
187 mbedtls_ctr_drbg_init(&ctr_drbg);
188
189 res = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *)pers, strlen(pers));
190 if (res)
191 goto exit;
192
193 res = mbedtls_ecdsa_genkey(&ctx, MBEDTLS_ECP_DP_SECP256R1, mbedtls_ctr_drbg_random, &ctr_drbg);
194 if (res)
195 goto exit;
196
197 res = mbedtls_mpi_write_binary(&ctx.d, key_d, 32);
198 if (res)
199 goto exit;
200
201 size_t keylen = 0;
202 uint8_t public_key[200] = {0};
203 res = mbedtls_ecp_point_write_binary(&ctx.grp, &ctx.Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &keylen, public_key, sizeof(public_key));
204 if (res)
205 goto exit;
206
207 if (keylen != 65) { // 0x04 <key x 32b><key y 32b>
208 res = 1;
209 goto exit;
210 }
211 memcpy(key_xy, public_key, 65);
212
213 exit:
214 mbedtls_entropy_free(&entropy);
215 mbedtls_ctr_drbg_free(&ctr_drbg);
216 mbedtls_ecdsa_free(&ctx);
217 return res;
218 }
219
220 char *ecdsa_get_error(int ret) {
221 static char retstr[300];
222 memset(retstr, 0x00, sizeof(retstr));
223 mbedtls_strerror(ret, retstr, sizeof(retstr));
224 return retstr;
225 }
226
227 int ecdsa_public_key_from_pk(mbedtls_pk_context *pk, uint8_t *key, size_t keylen) {
228 int res = 0;
229 size_t realkeylen = 0;
230 if (keylen < 65)
231 return 1;
232
233 mbedtls_ecdsa_context ctx;
234 mbedtls_ecdsa_init(&ctx);
235
236 res = mbedtls_ecp_group_load(&ctx.grp, MBEDTLS_ECP_DP_SECP256R1); // secp256r1
237 if (res)
238 goto exit;
239
240 res = mbedtls_ecdsa_from_keypair(&ctx, mbedtls_pk_ec(*pk) );
241 if (res)
242 goto exit;
243
244 res = mbedtls_ecp_point_write_binary(&ctx.grp, &ctx.Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &realkeylen, key, keylen);
245 if (realkeylen != 65)
246 res = 2;
247 exit:
248 mbedtls_ecdsa_free(&ctx);
249 return res;
250 }
251
252 int ecdsa_signature_create(uint8_t *key_d, uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t *signaturelen) {
253 int res;
254 *signaturelen = 0;
255
256 uint8_t shahash[32] = {0};
257 res = sha256hash(input, length, shahash);
258 if (res)
259 return res;
260
261 mbedtls_entropy_context entropy;
262 mbedtls_ctr_drbg_context ctr_drbg;
263 const char *pers = "ecdsaproxmark";
264
265 mbedtls_entropy_init(&entropy);
266 mbedtls_ctr_drbg_init(&ctr_drbg);
267
268 res = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *)pers, strlen(pers));
269 if (res)
270 goto exit;
271
272 mbedtls_ecdsa_context ctx;
273 ecdsa_init(&ctx, key_d, key_xy);
274 res = mbedtls_ecdsa_write_signature(&ctx, MBEDTLS_MD_SHA256, shahash, sizeof(shahash), signature, signaturelen, mbedtls_ctr_drbg_random, &ctr_drbg);
275
276 exit:
277 mbedtls_ctr_drbg_free(&ctr_drbg);
278 mbedtls_ecdsa_free(&ctx);
279 return res;
280 }
281
282 int ecdsa_signature_create_test(char * key_d, char *key_x, char *key_y, char *random, uint8_t *input, int length, uint8_t *signature, size_t *signaturelen) {
283 int res;
284 *signaturelen = 0;
285
286 uint8_t shahash[32] = {0};
287 res = sha256hash(input, length, shahash);
288 if (res)
289 return res;
290
291 int rndlen = 0;
292 param_gethex_to_eol(random, 0, fixed_rand_value, sizeof(fixed_rand_value), &rndlen);
293
294 mbedtls_ecdsa_context ctx;
295 ecdsa_init_str(&ctx, key_d, key_x, key_y);
296 res = mbedtls_ecdsa_write_signature(&ctx, MBEDTLS_MD_SHA256, shahash, sizeof(shahash), signature, signaturelen, fixed_rand, NULL);
297
298 mbedtls_ecdsa_free(&ctx);
299 return res;
300 }
301
302 int ecdsa_signature_verify_keystr(char *key_x, char *key_y, uint8_t *input, int length, uint8_t *signature, size_t signaturelen) {
303 int res;
304 uint8_t shahash[32] = {0};
305 res = sha256hash(input, length, shahash);
306 if (res)
307 return res;
308
309 mbedtls_ecdsa_context ctx;
310 ecdsa_init_str(&ctx, NULL, key_x, key_y);
311 res = mbedtls_ecdsa_read_signature(&ctx, shahash, sizeof(shahash), signature, signaturelen);
312
313 mbedtls_ecdsa_free(&ctx);
314 return res;
315 }
316
317 int ecdsa_signature_verify(uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t signaturelen) {
318 int res;
319 uint8_t shahash[32] = {0};
320 res = sha256hash(input, length, shahash);
321 if (res)
322 return res;
323
324 mbedtls_ecdsa_context ctx;
325 ecdsa_init(&ctx, NULL, key_xy);
326 res = mbedtls_ecdsa_read_signature(&ctx, shahash, sizeof(shahash), signature, signaturelen);
327
328 mbedtls_ecdsa_free(&ctx);
329 return res;
330 }
331
332 #define T_PRIVATE_KEY "C477F9F65C22CCE20657FAA5B2D1D8122336F851A508A1ED04E479C34985BF96"
333 #define T_Q_X "B7E08AFDFE94BAD3F1DC8C734798BA1C62B3A0AD1E9EA2A38201CD0889BC7A19"
334 #define T_Q_Y "3603F747959DBF7A4BB226E41928729063ADC7AE43529E61B563BBC606CC5E09"
335 #define T_K "7A1A7E52797FC8CAAA435D2A4DACE39158504BF204FBE19F14DBB427FAEE50AE"
336 #define T_R "2B42F576D07F4165FF65D1F3B1500F81E44C316F1F0B3EF57325B69ACA46104F"
337 #define T_S "DC42C2122D6392CD3E3A993A89502A8198C1886FE69D262C4B329BDB6B63FAF1"
338
339 int ecdsa_nist_test(bool verbose) {
340 int res;
341 uint8_t input[] = "Example of ECDSA with P-256";
342 int length = strlen((char *)input);
343 uint8_t signature[300] = {0};
344 size_t siglen = 0;
345
346 // NIST ecdsa test
347 if (verbose)
348 printf(" ECDSA NIST test: ");
349 // make signature
350 res = ecdsa_signature_create_test(T_PRIVATE_KEY, T_Q_X, T_Q_Y, T_K, input, length, signature, &siglen);
351 // printf("res: %x signature[%x]: %s\n", (res<0)?-res:res, siglen, sprint_hex(signature, siglen));
352 if (res)
353 goto exit;
354
355 // check vectors
356 uint8_t rval[300] = {0};
357 uint8_t sval[300] = {0};
358 res = ecdsa_asn1_get_signature(signature, siglen, rval, sval);
359 if (res)
360 goto exit;
361
362 int slen = 0;
363 uint8_t rval_s[33] = {0};
364 param_gethex_to_eol(T_R, 0, rval_s, sizeof(rval_s), &slen);
365 uint8_t sval_s[33] = {0};
366 param_gethex_to_eol(T_S, 0, sval_s, sizeof(sval_s), &slen);
367 if (strncmp((char *)rval, (char *)rval_s, 32) || strncmp((char *)sval, (char *)sval_s, 32)) {
368 printf("R or S check error\n");
369 res = 100;
370 goto exit;
371 }
372
373 // verify signature
374 res = ecdsa_signature_verify_keystr(T_Q_X, T_Q_Y, input, length, signature, siglen);
375 if (res)
376 goto exit;
377
378 // verify wrong signature
379 input[0] ^= 0xFF;
380 res = ecdsa_signature_verify_keystr(T_Q_X, T_Q_Y, input, length, signature, siglen);
381 if (!res) {
382 res = 1;
383 goto exit;
384 }
385 if (verbose)
386 printf("passed\n");
387
388 // random ecdsa test
389 if (verbose)
390 printf(" ECDSA binary signature create/check test: ");
391
392 uint8_t key_d[32] = {0};
393 uint8_t key_xy[32 * 2 + 2] = {0};
394 memset(signature, 0x00, sizeof(signature));
395 siglen = 0;
396
397 res = ecdsa_key_create(key_d, key_xy);
398 if (res)
399 goto exit;
400
401 res = ecdsa_signature_create(key_d, key_xy, input, length, signature, &siglen);
402 if (res)
403 goto exit;
404
405 res = ecdsa_signature_verify(key_xy, input, length, signature, siglen);
406 if (res)
407 goto exit;
408
409 input[0] ^= 0xFF;
410 res = ecdsa_signature_verify(key_xy, input, length, signature, siglen);
411 if (!res)
412 goto exit;
413
414 if (verbose)
415 printf("passed\n\n");
416
417 return 0;
418 exit:
419 if (verbose)
420 printf("failed\n\n");
421 return res;
422 }
Impressum, Datenschutz