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