]> git.zerfleddert.de Git - proxmark3-svn/blame - client/crypto/libpcrypto.c
'hf iclass loclass': fix error handling (#865)
[proxmark3-svn] / client / crypto / libpcrypto.c
CommitLineData
700d8687
OM
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>
6b882a39 19#include <mbedtls/pk.h>
700d8687
OM
20#include <mbedtls/ecdsa.h>
21#include <mbedtls/sha256.h>
9f596ec7 22#include <mbedtls/sha512.h>
700d8687
OM
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
3a5ffba7 29
700d8687
OM
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);
3a5ffba7 35
700d8687
OM
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
3a5ffba7 47
700d8687
OM
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);
3a5ffba7 52
700d8687
OM
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
3a5ffba7 64
700d8687
OM
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);
3a5ffba7 69
70 // NIST 800-38B
700d8687
OM
71 return mbedtls_aes_cmac_prf_128(key, MBEDTLS_AES_BLOCK_SIZE, input, length, mac);
72}
73
3a5ffba7 74
700d8687
OM
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);
3a5ffba7 78
700d8687
OM
79 int res = aes_cmac(iv, key, input, cmac, length);
80 if (res)
81 return res;
3a5ffba7 82
83 for(int i = 0; i < 8; i++)
700d8687
OM
84 mac[i] = cmac[i * 2 + 1];
85
86 return 0;
87}
88
3a5ffba7 89
700d8687 90static uint8_t fixed_rand_value[250] = {0};
3a5ffba7 91
700d8687
OM
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 }
3a5ffba7 98
700d8687
OM
99 return 0;
100}
101
3a5ffba7 102
700d8687
OM
103int sha256hash(uint8_t *input, int length, uint8_t *hash) {
104 if (!hash || !input)
105 return 1;
3a5ffba7 106
700d8687
OM
107 mbedtls_sha256_context sctx;
108 mbedtls_sha256_init(&sctx);
3a5ffba7 109 mbedtls_sha256_starts(&sctx, 0); // SHA-256, not 224
700d8687 110 mbedtls_sha256_update(&sctx, input, length);
3a5ffba7 111 mbedtls_sha256_finish(&sctx, hash);
700d8687 112 mbedtls_sha256_free(&sctx);
3a5ffba7 113
700d8687
OM
114 return 0;
115}
116
3a5ffba7 117
9f596ec7 118int sha512hash(uint8_t *input, int length, uint8_t *hash) {
119 if (!hash || !input)
120 return 1;
3a5ffba7 121
9f596ec7 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);
3a5ffba7 126 mbedtls_sha512_finish(&sctx, hash);
9f596ec7 127 mbedtls_sha512_free(&sctx);
3a5ffba7 128
9f596ec7 129 return 0;
130}
131
3a5ffba7 132
133int ecdsa_init_str(mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id curveID, char *key_d, char *key_x, char *key_y) {
700d8687
OM
134 if (!ctx)
135 return 1;
3a5ffba7 136
700d8687
OM
137 int res;
138
139 mbedtls_ecdsa_init(ctx);
3a5ffba7 140 res = mbedtls_ecp_group_load(&ctx->grp, curveID);
141 if (res)
700d8687 142 return res;
3a5ffba7 143
700d8687
OM
144 if (key_d) {
145 res = mbedtls_mpi_read_string(&ctx->d, 16, key_d);
3a5ffba7 146 if (res)
700d8687
OM
147 return res;
148 }
3a5ffba7 149
700d8687
OM
150 if (key_x && key_y) {
151 res = mbedtls_ecp_point_read_string(&ctx->Q, 16, key_x, key_y);
3a5ffba7 152 if (res)
700d8687
OM
153 return res;
154 }
3a5ffba7 155
700d8687
OM
156 return 0;
157}
158
3a5ffba7 159
160int ecdsa_init(mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id curveID, uint8_t *key_d, uint8_t *key_xy) {
700d8687
OM
161 if (!ctx)
162 return 1;
3a5ffba7 163
700d8687
OM
164 int res;
165
166 mbedtls_ecdsa_init(ctx);
3a5ffba7 167 res = mbedtls_ecp_group_load(&ctx->grp, curveID);
168 if (res)
700d8687 169 return res;
3a5ffba7 170
171 size_t keylen = (ctx->grp.nbits + 7 ) / 8;
700d8687 172 if (key_d) {
3a5ffba7 173 res = mbedtls_mpi_read_binary(&ctx->d, key_d, keylen);
174 if (res)
700d8687
OM
175 return res;
176 }
3a5ffba7 177
700d8687 178 if (key_xy) {
3a5ffba7 179 res = mbedtls_ecp_point_read_binary(&ctx->grp, &ctx->Q, key_xy, keylen * 2 + 1);
180 if (res)
700d8687
OM
181 return res;
182 }
3a5ffba7 183
700d8687
OM
184 return 0;
185}
186
3a5ffba7 187
188int ecdsa_key_create(mbedtls_ecp_group_id curveID, uint8_t *key_d, uint8_t *key_xy) {
700d8687
OM
189 int res;
190 mbedtls_ecdsa_context ctx;
3a5ffba7 191 ecdsa_init(&ctx, curveID, NULL, NULL);
700d8687
OM
192
193
3a5ffba7 194 mbedtls_entropy_context entropy;
195 mbedtls_ctr_drbg_context ctr_drbg;
700d8687
OM
196 const char *pers = "ecdsaproxmark";
197
3a5ffba7 198 mbedtls_entropy_init(&entropy);
199 mbedtls_ctr_drbg_init(&ctr_drbg);
700d8687 200
3a5ffba7 201 res = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *)pers, strlen(pers));
700d8687 202 if (res)
3a5ffba7 203 goto exit;
700d8687 204
3a5ffba7 205 res = mbedtls_ecdsa_genkey(&ctx, curveID, mbedtls_ctr_drbg_random, &ctr_drbg);
700d8687
OM
206 if (res)
207 goto exit;
208
3a5ffba7 209 size_t keylen = (ctx.grp.nbits + 7) / 8;
210 res = mbedtls_mpi_write_binary(&ctx.d, key_d, keylen);
700d8687
OM
211 if (res)
212 goto exit;
213
3a5ffba7 214 size_t public_keylen = 0;
700d8687 215 uint8_t public_key[200] = {0};
3a5ffba7 216 res = mbedtls_ecp_point_write_binary(&ctx.grp, &ctx.Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &public_keylen, public_key, sizeof(public_key));
700d8687
OM
217 if (res)
218 goto exit;
3a5ffba7 219
220 if (public_keylen != 1 + 2 * keylen) { // 0x04 <key x><key y>
700d8687
OM
221 res = 1;
222 goto exit;
223 }
3a5ffba7 224 memcpy(key_xy, public_key, public_keylen);
700d8687
OM
225
226exit:
3a5ffba7 227 mbedtls_entropy_free(&entropy);
228 mbedtls_ctr_drbg_free(&ctr_drbg);
700d8687
OM
229 mbedtls_ecdsa_free(&ctx);
230 return res;
231}
232
3a5ffba7 233
700d8687
OM
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
3a5ffba7 241
242int ecdsa_public_key_from_pk(mbedtls_pk_context *pk, mbedtls_ecp_group_id curveID, uint8_t *key, size_t keylen) {
6b882a39
OM
243 int res = 0;
244 size_t realkeylen = 0;
3a5ffba7 245
6b882a39
OM
246 mbedtls_ecdsa_context ctx;
247 mbedtls_ecdsa_init(&ctx);
3a5ffba7 248
249 res = mbedtls_ecp_group_load(&ctx.grp, curveID);
6b882a39
OM
250 if (res)
251 goto exit;
3a5ffba7 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
6b882a39
OM
259 res = mbedtls_ecdsa_from_keypair(&ctx, mbedtls_pk_ec(*pk) );
260 if (res)
261 goto exit;
3a5ffba7 262
6b882a39 263 res = mbedtls_ecp_point_write_binary(&ctx.grp, &ctx.Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &realkeylen, key, keylen);
3a5ffba7 264 if (realkeylen != 1 + 2 * private_keylen)
6b882a39
OM
265 res = 2;
266exit:
267 mbedtls_ecdsa_free(&ctx);
268 return res;
269}
270
3a5ffba7 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) {
700d8687
OM
273 int res;
274 *signaturelen = 0;
3a5ffba7 275
276 uint8_t shahash[32] = {0};
700d8687
OM
277 res = sha256hash(input, length, shahash);
278 if (res)
279 return res;
280
3a5ffba7 281 mbedtls_entropy_context entropy;
282 mbedtls_ctr_drbg_context ctr_drbg;
700d8687
OM
283 const char *pers = "ecdsaproxmark";
284
3a5ffba7 285 mbedtls_entropy_init(&entropy);
286 mbedtls_ctr_drbg_init(&ctr_drbg);
700d8687 287
3a5ffba7 288 res = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *)pers, strlen(pers));
700d8687 289 if (res)
3a5ffba7 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);
700d8687 295
700d8687 296exit:
3a5ffba7 297 mbedtls_ctr_drbg_free(&ctr_drbg);
700d8687
OM
298 mbedtls_ecdsa_free(&ctx);
299 return res;
300}
301
3a5ffba7 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) {
700d8687
OM
304 int res;
305 *signaturelen = 0;
3a5ffba7 306
307 uint8_t shahash[32] = {0};
700d8687
OM
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);
3a5ffba7 314
315 mbedtls_ecdsa_context ctx;
316 ecdsa_init_str(&ctx, curveID, key_d, key_x, key_y);
700d8687 317 res = mbedtls_ecdsa_write_signature(&ctx, MBEDTLS_MD_SHA256, shahash, sizeof(shahash), signature, signaturelen, fixed_rand, NULL);
3a5ffba7 318
700d8687
OM
319 mbedtls_ecdsa_free(&ctx);
320 return res;
321}
322
3a5ffba7 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) {
700d8687 325 int res;
3a5ffba7 326 uint8_t shahash[32] = {0};
700d8687
OM
327 res = sha256hash(input, length, shahash);
328 if (res)
329 return res;
330
3a5ffba7 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
700d8687
OM
335 mbedtls_ecdsa_free(&ctx);
336 return res;
337}
338
3a5ffba7 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) {
700d8687 341 int res;
3a5ffba7 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);
700d8687 352
700d8687
OM
353 mbedtls_ecdsa_free(&ctx);
354 return res;
355}
356
3a5ffba7 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
700d8687
OM
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";
3a5ffba7 394 mbedtls_ecp_group_id curveID = MBEDTLS_ECP_DP_SECP256R1;
700d8687 395 int length = strlen((char *)input);
3a5ffba7 396 uint8_t signature[300] = {0};
397 size_t siglen = 0;
700d8687
OM
398
399 // NIST ecdsa test
400 if (verbose)
401 printf(" ECDSA NIST test: ");
402 // make signature
3a5ffba7 403 res = ecdsa_signature_create_test(curveID, T_PRIVATE_KEY, T_Q_X, T_Q_Y, T_K, input, length, signature, &siglen);
700d8687 404// printf("res: %x signature[%x]: %s\n", (res<0)?-res:res, siglen, sprint_hex(signature, siglen));
3a5ffba7 405 if (res)
700d8687
OM
406 goto exit;
407
408 // check vectors
3a5ffba7 409 uint8_t rval[300] = {0};
410 uint8_t sval[300] = {0};
700d8687
OM
411 res = ecdsa_asn1_get_signature(signature, siglen, rval, sval);
412 if (res)
413 goto exit;
3a5ffba7 414
700d8687
OM
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);
3a5ffba7 418 uint8_t sval_s[33] = {0};
700d8687
OM
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 }
3a5ffba7 425
700d8687 426 // verify signature
3a5ffba7 427 res = ecdsa_signature_verify_keystr(curveID, T_Q_X, T_Q_Y, input, length, signature, siglen, true);
428 if (res)
700d8687 429 goto exit;
3a5ffba7 430
700d8687
OM
431 // verify wrong signature
432 input[0] ^= 0xFF;
3a5ffba7 433 res = ecdsa_signature_verify_keystr(curveID, T_Q_X, T_Q_Y, input, length, signature, siglen, true);
700d8687
OM
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;
3a5ffba7 449
450 res = ecdsa_key_create(curveID, key_d, key_xy);
451 if (res)
700d8687
OM
452 goto exit;
453
3a5ffba7 454 res = ecdsa_signature_create(curveID, key_d, key_xy, input, length, signature, &siglen, true);
455 if (res)
700d8687
OM
456 goto exit;
457
3a5ffba7 458 res = ecdsa_signature_verify(curveID, key_xy, input, length, signature, siglen, true);
459 if (res)
700d8687
OM
460 goto exit;
461
462 input[0] ^= 0xFF;
3a5ffba7 463 res = ecdsa_signature_verify(curveID, key_xy, input, length, signature, siglen, true);
464 if (!res)
700d8687 465 goto exit;
3a5ffba7 466
700d8687
OM
467 if (verbose)
468 printf("passed\n\n");
3a5ffba7 469
700d8687
OM
470 return 0;
471exit:
472 if (verbose)
473 printf("failed\n\n");
474 return res;
475}
Impressum, Datenschutz