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