1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2018 Merlok
3 // Copyright (C) 2018 drHatson
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
8 //-----------------------------------------------------------------------------
10 //-----------------------------------------------------------------------------
12 #include "crypto/libpcrypto.h"
13 #include "crypto/asn1utils.h"
17 #include <mbedtls/asn1.h>
18 #include <mbedtls/aes.h>
19 #include <mbedtls/cmac.h>
20 #include <mbedtls/pk.h>
21 #include <mbedtls/ecdsa.h>
22 #include <mbedtls/sha1.h>
23 #include <mbedtls/sha256.h>
24 #include <mbedtls/sha512.h>
25 #include <mbedtls/ctr_drbg.h>
26 #include <mbedtls/entropy.h>
27 #include <mbedtls/error.h>
30 // NIST Special Publication 800-38A — Recommendation for block cipher modes of operation: methods and techniques, 2001.
31 int aes_encode(uint8_t *iv
, uint8_t *key
, uint8_t *input
, uint8_t *output
, int length
) {
32 uint8_t iiv
[16] = {0};
36 mbedtls_aes_context aes
;
37 mbedtls_aes_init(&aes
);
38 if (mbedtls_aes_setkey_enc(&aes
, key
, 128))
40 if (mbedtls_aes_crypt_cbc(&aes
, MBEDTLS_AES_ENCRYPT
, length
, iiv
, input
, output
))
42 mbedtls_aes_free(&aes
);
47 int aes_decode(uint8_t *iv
, uint8_t *key
, uint8_t *input
, uint8_t *output
, int length
) {
48 uint8_t iiv
[16] = {0};
52 mbedtls_aes_context aes
;
53 mbedtls_aes_init(&aes
);
54 if (mbedtls_aes_setkey_dec(&aes
, key
, 128))
56 if (mbedtls_aes_crypt_cbc(&aes
, MBEDTLS_AES_DECRYPT
, length
, iiv
, input
, output
))
58 mbedtls_aes_free(&aes
);
63 // NIST Special Publication 800-38B — Recommendation for block cipher modes of operation: The CMAC mode for authentication.
64 // https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/AES_CMAC.pdf
65 int aes_cmac(uint8_t *iv
, uint8_t *key
, uint8_t *input
, uint8_t *mac
, int length
) {
66 memset(mac
, 0x00, 16);
69 return mbedtls_aes_cmac_prf_128(key
, MBEDTLS_AES_BLOCK_SIZE
, input
, length
, mac
);
72 int aes_cmac8(uint8_t *iv
, uint8_t *key
, uint8_t *input
, uint8_t *mac
, int length
) {
73 uint8_t cmac_tmp
[16] = {0};
76 int res
= aes_cmac(iv
, key
, input
, cmac_tmp
, length
);
80 for (int i
= 0; i
< 8; i
++)
81 mac
[i
] = cmac_tmp
[i
* 2 + 1];
86 static uint8_t fixed_rand_value
[250] = {0};
87 static int fixed_rand(void *rng_state
, unsigned char *output
, size_t len
) {
89 memcpy(output
, fixed_rand_value
, len
);
91 memset(output
, 0x00, len
);
97 int sha1hash(uint8_t *input
, int length
, uint8_t *hash
) {
101 mbedtls_sha1(input
, length
, hash
);
106 int sha256hash(uint8_t *input
, int length
, uint8_t *hash
) {
110 mbedtls_sha256_context sctx
;
111 mbedtls_sha256_init(&sctx
);
112 mbedtls_sha256_starts(&sctx
, 0); // SHA-256, not 224
113 mbedtls_sha256_update(&sctx
, input
, length
);
114 mbedtls_sha256_finish(&sctx
, hash
);
115 mbedtls_sha256_free(&sctx
);
120 int sha512hash(uint8_t *input
, int length
, uint8_t *hash
) {
124 mbedtls_sha512_context sctx
;
125 mbedtls_sha512_init(&sctx
);
126 mbedtls_sha512_starts(&sctx
, 0); //SHA-512, not 384
127 mbedtls_sha512_update(&sctx
, input
, length
);
128 mbedtls_sha512_finish(&sctx
, hash
);
129 mbedtls_sha512_free(&sctx
);
134 static int ecdsa_init_str(mbedtls_ecdsa_context
*ctx
, mbedtls_ecp_group_id curveid
, const char *key_d
, const char *key_x
, const char *key_y
) {
140 mbedtls_ecdsa_init(ctx
);
141 res
= mbedtls_ecp_group_load(&ctx
->grp
, curveid
);
146 res
= mbedtls_mpi_read_string(&ctx
->d
, 16, key_d
);
151 if (key_x
&& key_y
) {
152 res
= mbedtls_ecp_point_read_string(&ctx
->Q
, 16, key_x
, key_y
);
160 static int ecdsa_init(mbedtls_ecdsa_context
*ctx
, mbedtls_ecp_group_id curveid
, uint8_t *key_d
, uint8_t *key_xy
) {
166 mbedtls_ecdsa_init(ctx
);
167 res
= mbedtls_ecp_group_load(&ctx
->grp
, curveid
);
171 size_t keylen
= (ctx
->grp
.nbits
+ 7) / 8;
173 res
= mbedtls_mpi_read_binary(&ctx
->d
, key_d
, keylen
);
179 res
= mbedtls_ecp_point_read_binary(&ctx
->grp
, &ctx
->Q
, key_xy
, keylen
* 2 + 1);
187 int ecdsa_key_create(mbedtls_ecp_group_id curveid
, uint8_t *key_d
, uint8_t *key_xy
) {
189 mbedtls_ecdsa_context ctx
;
190 res
= ecdsa_init(&ctx
, curveid
, NULL
, NULL
);
194 mbedtls_entropy_context entropy
;
195 mbedtls_ctr_drbg_context ctr_drbg
;
196 const char *pers
= "ecdsaproxmark";
198 mbedtls_entropy_init(&entropy
);
199 mbedtls_ctr_drbg_init(&ctr_drbg
);
201 res
= mbedtls_ctr_drbg_seed(&ctr_drbg
, mbedtls_entropy_func
, &entropy
, (const unsigned char *)pers
, strlen(pers
));
205 res
= mbedtls_ecdsa_genkey(&ctx
, curveid
, mbedtls_ctr_drbg_random
, &ctr_drbg
);
209 size_t keylen
= (ctx
.grp
.nbits
+ 7) / 8;
210 res
= mbedtls_mpi_write_binary(&ctx
.d
, key_d
, keylen
);
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
));
220 if (public_keylen
!= 1 + 2 * keylen
) { // 0x04 <key x><key y>
224 memcpy(key_xy
, public_key
, public_keylen
);
227 mbedtls_entropy_free(&entropy
);
228 mbedtls_ctr_drbg_free(&ctr_drbg
);
229 mbedtls_ecdsa_free(&ctx
);
233 char *ecdsa_get_error(int ret
) {
234 static char retstr
[300];
235 memset(retstr
, 0x00, sizeof(retstr
));
236 mbedtls_strerror(ret
, retstr
, sizeof(retstr
));
240 int ecdsa_public_key_from_pk(mbedtls_pk_context
*pk
, mbedtls_ecp_group_id curveid
, uint8_t *key
, size_t keylen
) {
242 size_t realkeylen
= 0;
244 mbedtls_ecdsa_context ctx
;
245 mbedtls_ecdsa_init(&ctx
);
247 res
= mbedtls_ecp_group_load(&ctx
.grp
, curveid
);
251 size_t private_keylen
= (ctx
.grp
.nbits
+ 7) / 8;
252 if (keylen
< 1 + 2 * private_keylen
) {
257 res
= mbedtls_ecdsa_from_keypair(&ctx
, mbedtls_pk_ec(*pk
));
261 res
= mbedtls_ecp_point_write_binary(&ctx
.grp
, &ctx
.Q
, MBEDTLS_ECP_PF_UNCOMPRESSED
, &realkeylen
, key
, keylen
);
262 if (realkeylen
!= 1 + 2 * private_keylen
)
265 mbedtls_ecdsa_free(&ctx
);
269 int 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 uint8_t shahash
[32] = {0};
274 res
= sha256hash(input
, length
, shahash
);
278 mbedtls_entropy_context entropy
;
279 mbedtls_ctr_drbg_context ctr_drbg
;
280 const char *pers
= "ecdsaproxmark";
282 mbedtls_entropy_init(&entropy
);
283 mbedtls_ctr_drbg_init(&ctr_drbg
);
285 res
= mbedtls_ctr_drbg_seed(&ctr_drbg
, mbedtls_entropy_func
, &entropy
, (const unsigned char *)pers
, strlen(pers
));
289 mbedtls_ecdsa_context ctx
;
290 res
= ecdsa_init(&ctx
, curveid
, key_d
, key_xy
);
294 res
= mbedtls_ecdsa_write_signature(
297 hash
? shahash
: input
,
298 hash
? sizeof(shahash
) : length
,
301 mbedtls_ctr_drbg_random
,
307 mbedtls_ctr_drbg_free(&ctr_drbg
);
308 mbedtls_ecdsa_free(&ctx
);
312 static int ecdsa_signature_create_test(mbedtls_ecp_group_id curveid
, const char *key_d
, const char *key_x
, const char *key_y
, const char *random
, uint8_t *input
, int length
, uint8_t *signature
, size_t *signaturelen
) {
316 uint8_t shahash
[32] = {0};
317 res
= sha256hash(input
, length
, shahash
);
322 param_gethex_to_eol(random
, 0, fixed_rand_value
, sizeof(fixed_rand_value
), &rndlen
);
324 mbedtls_ecdsa_context ctx
;
325 res
= ecdsa_init_str(&ctx
, curveid
, key_d
, key_x
, key_y
);
329 res
= mbedtls_ecdsa_write_signature(&ctx
, MBEDTLS_MD_SHA256
, shahash
, sizeof(shahash
), signature
, signaturelen
, fixed_rand
, NULL
);
331 mbedtls_ecdsa_free(&ctx
);
335 static int ecdsa_signature_verify_keystr(mbedtls_ecp_group_id curveid
, const char *key_x
, const char *key_y
, uint8_t *input
, int length
, uint8_t *signature
, size_t signaturelen
, bool hash
) {
337 uint8_t shahash
[32] = {0};
338 res
= sha256hash(input
, length
, shahash
);
342 mbedtls_ecdsa_context ctx
;
343 res
= ecdsa_init_str(&ctx
, curveid
, NULL
, key_x
, key_y
);
347 res
= mbedtls_ecdsa_read_signature(
349 hash
? shahash
: input
,
350 hash
? sizeof(shahash
) : length
,
355 mbedtls_ecdsa_free(&ctx
);
359 int 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
) {
361 uint8_t shahash
[32] = {0};
363 res
= sha256hash(input
, length
, shahash
);
368 mbedtls_ecdsa_context ctx
;
369 res
= ecdsa_init(&ctx
, curveid
, NULL
, key_xy
);
373 res
= mbedtls_ecdsa_read_signature(
375 hash
? shahash
: input
,
376 hash
? sizeof(shahash
) : length
,
381 mbedtls_ecdsa_free(&ctx
);
385 // take signature bytes, converts to ASN1 signature and tries to verify
386 int 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
) {
387 uint8_t signature
[MBEDTLS_ECDSA_MAX_LEN
] = {0};
388 size_t signature_len
= 0;
390 // convert r & s to ASN.1 signature
392 mbedtls_mpi_init(&r
);
393 mbedtls_mpi_init(&s
);
394 mbedtls_mpi_read_binary(&r
, r_s
, r_s_len
/ 2);
395 mbedtls_mpi_read_binary(&s
, r_s
+ r_s_len
/ 2, r_s_len
/ 2);
397 int res
= ecdsa_signature_to_asn1(&r
, &s
, signature
, &signature_len
);
402 res
= ecdsa_signature_verify(curveid
, key_xy
, input
, length
, signature
, signature_len
, hash
);
403 mbedtls_mpi_free(&r
);
404 mbedtls_mpi_free(&s
);
409 #define T_PRIVATE_KEY "C477F9F65C22CCE20657FAA5B2D1D8122336F851A508A1ED04E479C34985BF96"
410 #define T_Q_X "B7E08AFDFE94BAD3F1DC8C734798BA1C62B3A0AD1E9EA2A38201CD0889BC7A19"
411 #define T_Q_Y "3603F747959DBF7A4BB226E41928729063ADC7AE43529E61B563BBC606CC5E09"
412 #define T_K "7A1A7E52797FC8CAAA435D2A4DACE39158504BF204FBE19F14DBB427FAEE50AE"
413 #define T_R "2B42F576D07F4165FF65D1F3B1500F81E44C316F1F0B3EF57325B69ACA46104F"
414 #define T_S "DC42C2122D6392CD3E3A993A89502A8198C1886FE69D262C4B329BDB6B63FAF1"
416 int ecdsa_nist_test(bool verbose
) {
418 uint8_t input
[] = "Example of ECDSA with P-256";
419 mbedtls_ecp_group_id curveid
= MBEDTLS_ECP_DP_SECP256R1
;
420 int length
= strlen((char *)input
);
421 uint8_t signature
[300] = {0};
426 PrintAndLogEx(INFO
, " ECDSA NIST test: " NOLF
);
428 res
= ecdsa_signature_create_test(curveid
, T_PRIVATE_KEY
, T_Q_X
, T_Q_Y
, T_K
, input
, length
, signature
, &siglen
);
429 // PrintAndLogEx(INFO, "res: %x signature[%x]: %s", (res < 0)? -res : res, siglen, sprint_hex(signature, siglen));
430 if (res
!= PM3_SUCCESS
)
434 uint8_t rval
[300] = {0};
435 uint8_t sval
[300] = {0};
436 res
= ecdsa_asn1_get_signature(signature
, siglen
, rval
, sval
);
441 uint8_t rval_s
[33] = {0};
442 param_gethex_to_eol(T_R
, 0, rval_s
, sizeof(rval_s
), &slen
);
443 uint8_t sval_s
[33] = {0};
444 param_gethex_to_eol(T_S
, 0, sval_s
, sizeof(sval_s
), &slen
);
445 if (strncmp((char *)rval
, (char *)rval_s
, 32) || strncmp((char *)sval
, (char *)sval_s
, 32)) {
446 PrintAndLogEx(INFO
, "R or S check error");
452 res
= ecdsa_signature_verify_keystr(curveid
, T_Q_X
, T_Q_Y
, input
, length
, signature
, siglen
, true);
456 // verify wrong signature
458 res
= ecdsa_signature_verify_keystr(curveid
, T_Q_X
, T_Q_Y
, input
, length
, signature
, siglen
, true);
465 PrintAndLogEx(NORMAL
, _GREEN_("passed"));
466 PrintAndLogEx(INFO
, " ECDSA binary signature create/check test: " NOLF
);
470 uint8_t key_d
[32] = {0};
471 uint8_t key_xy
[32 * 2 + 2] = {0};
472 memset(signature
, 0x00, sizeof(signature
));
475 res
= ecdsa_key_create(curveid
, key_d
, key_xy
);
479 res
= ecdsa_signature_create(curveid
, key_d
, key_xy
, input
, length
, signature
, &siglen
, true);
483 res
= ecdsa_signature_verify(curveid
, key_xy
, input
, length
, signature
, siglen
, true);
488 res
= ecdsa_signature_verify(curveid
, key_xy
, input
, length
, signature
, siglen
, true);
493 PrintAndLogEx(NORMAL
, _GREEN_("passed\n"));
498 PrintAndLogEx(NORMAL
, _RED_("failed\n"));