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