fix one too small
[RRG-proxmark3.git] / client / src / emv / test / cda_test.c
blobeb4a031f4e3c9922da7abc6f54c030783293ce9c
1 //-----------------------------------------------------------------------------
2 // Borrowed initially from https://github.com/lumag/emv-tools/
3 // Copyright (C) 2012, 2015 Dmitry Eremin-Solenikov
4 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
5 //
6 // This program is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // See LICENSE.txt for the text of the license.
17 //-----------------------------------------------------------------------------
18 // emv-tools - a set of tools to work with EMV family of smart cards
19 //-----------------------------------------------------------------------------
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
25 #include <string.h> // memcpy
26 #include <stdlib.h> // calloc
27 #include "cda_test.h"
29 #include "../emv_pk.h"
30 #include "../crypto.h"
31 #include "../tlv.h"
32 #include "../emv_pki.h"
33 #include "ui.h" // printandlog
34 #include "util.h" // print_buffer
36 struct emv_pk c_mchip_05 = {
37 .rid = { 0xa0, 0x00, 0x00, 0x00, 0x04, },
38 .index = 5,
39 .hash_algo = HASH_SHA_1,
40 .pk_algo = PK_RSA,
41 .hash = {
42 0xeb, 0xfa, 0x0d, 0x5d,
43 0x06, 0xd8, 0xce, 0x70,
44 0x2d, 0xa3, 0xea, 0xe8,
45 0x90, 0x70, 0x1d, 0x45,
46 0xe2, 0x74, 0xc8, 0x45,
48 .exp = { 0x03, },
49 .elen = 1,
50 .mlen = 1408 / 8,
51 .modulus = (unsigned char[]) {
52 0xb8, 0x04, 0x8a, 0xbc, 0x30, 0xc9, 0x0d, 0x97, 0x63, 0x36, 0x54, 0x3e, 0x3f, 0xd7, 0x09, 0x1c,
53 0x8f, 0xe4, 0x80, 0x0d, 0xf8, 0x20, 0xed, 0x55, 0xe7, 0xe9, 0x48, 0x13, 0xed, 0x00, 0x55, 0x5b,
54 0x57, 0x3f, 0xec, 0xa3, 0xd8, 0x4a, 0xf6, 0x13, 0x1a, 0x65, 0x1d, 0x66, 0xcf, 0xf4, 0x28, 0x4f,
55 0xb1, 0x3b, 0x63, 0x5e, 0xdd, 0x0e, 0xe4, 0x01, 0x76, 0xd8, 0xbf, 0x04, 0xb7, 0xfd, 0x1c, 0x7b,
56 0xac, 0xf9, 0xac, 0x73, 0x27, 0xdf, 0xaa, 0x8a, 0xa7, 0x2d, 0x10, 0xdb, 0x3b, 0x8e, 0x70, 0xb2,
57 0xdd, 0xd8, 0x11, 0xcb, 0x41, 0x96, 0x52, 0x5e, 0xa3, 0x86, 0xac, 0xc3, 0x3c, 0x0d, 0x9d, 0x45,
58 0x75, 0x91, 0x64, 0x69, 0xc4, 0xe4, 0xf5, 0x3e, 0x8e, 0x1c, 0x91, 0x2c, 0xc6, 0x18, 0xcb, 0x22,
59 0xdd, 0xe7, 0xc3, 0x56, 0x8e, 0x90, 0x02, 0x2e, 0x6b, 0xba, 0x77, 0x02, 0x02, 0xe4, 0x52, 0x2a,
60 0x2d, 0xd6, 0x23, 0xd1, 0x80, 0xe2, 0x15, 0xbd, 0x1d, 0x15, 0x07, 0xfe, 0x3d, 0xc9, 0x0c, 0xa3,
61 0x10, 0xd2, 0x7b, 0x3e, 0xfc, 0xcd, 0x8f, 0x83, 0xde, 0x30, 0x52, 0xca, 0xd1, 0xe4, 0x89, 0x38,
62 0xc6, 0x8d, 0x09, 0x5a, 0xac, 0x91, 0xb5, 0xf3, 0x7e, 0x28, 0xbb, 0x49, 0xec, 0x7e, 0xd5, 0x97,
64 .expire = 0,
67 const unsigned char c_issuer_cert[] = {
68 0x17, 0x14, 0x28, 0x4f, 0x76, 0x3b, 0x85, 0x86, 0xee, 0x6d, 0x31, 0x99, 0x51, 0xf7, 0xe6, 0x3f,
69 0xa2, 0x50, 0x76, 0xe5, 0x0d, 0xc9, 0xd3, 0x20, 0x0b, 0xa9, 0x98, 0xd3, 0xa0, 0x52, 0xad, 0xba,
70 0x9a, 0xb6, 0x9a, 0xc6, 0xad, 0x6a, 0xdd, 0x3c, 0xe0, 0x9f, 0x02, 0x78, 0xf4, 0x07, 0x4e, 0xc4,
71 0xee, 0x9b, 0x1d, 0x22, 0x68, 0xa3, 0xe9, 0x53, 0x57, 0x5e, 0x45, 0x4e, 0x50, 0xcd, 0x86, 0x0b,
72 0xf4, 0x24, 0xc5, 0x1c, 0x59, 0x77, 0x12, 0xd2, 0xaa, 0x05, 0x70, 0x89, 0xdd, 0x86, 0x73, 0xe5,
73 0x1b, 0x1e, 0x1d, 0x71, 0x88, 0x03, 0x48, 0x92, 0x07, 0x7a, 0xc1, 0x8a, 0x6a, 0xe2, 0x34, 0x88,
74 0xbe, 0xa9, 0xdf, 0x3b, 0x1a, 0x83, 0xf2, 0xc0, 0x80, 0x0c, 0xd7, 0xc5, 0xcd, 0xf2, 0xfd, 0xe0,
75 0x49, 0x6f, 0x7b, 0xc3, 0x9f, 0xb4, 0xbf, 0x36, 0x32, 0x99, 0xbf, 0xa6, 0x37, 0xb2, 0xec, 0x33,
76 0xc5, 0x07, 0xe3, 0x68, 0x21, 0xee, 0xc2, 0x07, 0x5f, 0x0e, 0x42, 0x0d, 0x38, 0xa1, 0xc9, 0xf3,
77 0x12, 0x72, 0x61, 0xba, 0x31, 0x6c, 0x98, 0x76, 0x74, 0xfa, 0xdb, 0x20, 0xea, 0x7f, 0xeb, 0x75,
78 0xee, 0x45, 0x5d, 0x12, 0x14, 0x6e, 0xa6, 0xf0, 0x2e, 0x8b, 0x01, 0xec, 0x2f, 0xa7, 0xa1, 0x15,
81 const unsigned char c_issuer_rem[] = {
82 0x6e, 0x63, 0xb7, 0xbc, 0x70, 0xab, 0xdd, 0x09, 0x34, 0x1b, 0x34, 0xc0, 0x32, 0x86, 0xba, 0x9b,
83 0xd8, 0x3b, 0xa7, 0x93, 0x6c, 0x5b, 0x77, 0x98, 0xfb, 0x22, 0xc5, 0xe5, 0x3f, 0xf2, 0x40, 0xa2,
84 0x6d, 0xbd, 0x64, 0x15,
87 const unsigned char c_issuer_exp[] = {
88 0x03,
91 const unsigned char c_icc_cert[] = {
92 0xa4, 0x2f, 0xbe, 0xb1, 0x56, 0xb9, 0x8d, 0xcb, 0x05, 0x54, 0xda, 0x06, 0x2a, 0xdc, 0xa5, 0x30,
93 0x9a, 0x91, 0xf0, 0x4f, 0xa2, 0xc7, 0xbd, 0x71, 0x02, 0xa8, 0xd7, 0x3f, 0x16, 0xa3, 0xcf, 0xad,
94 0xe8, 0xaa, 0xdf, 0x4f, 0x3f, 0xe2, 0xa2, 0x12, 0x5c, 0xcd, 0xd7, 0x7c, 0x6b, 0x9f, 0x78, 0xb5,
95 0xb4, 0x37, 0x1c, 0xe0, 0x80, 0x57, 0x25, 0xb0, 0xf9, 0xc0, 0x27, 0xaf, 0x14, 0x7d, 0x91, 0xe1,
96 0xff, 0xdb, 0x20, 0x1e, 0x9c, 0x17, 0x0c, 0xe7, 0x77, 0x05, 0x3a, 0x17, 0x2a, 0xd5, 0x26, 0xdc,
97 0xaf, 0xd3, 0x38, 0x95, 0xe1, 0xa9, 0x47, 0x30, 0x5c, 0x5b, 0x16, 0x7f, 0x2e, 0x7c, 0x6f, 0x99,
98 0x15, 0x81, 0xa6, 0x52, 0xee, 0x47, 0x31, 0x54, 0x76, 0x0c, 0x2e, 0xd7, 0x74, 0x21, 0x4e, 0x50,
99 0xdf, 0xec, 0xdd, 0x4c, 0xf2, 0x94, 0xc9, 0x74, 0xb8, 0x9e, 0xbc, 0xa2, 0x5b, 0x5a, 0xb3, 0xc0,
100 0xbe, 0xb5, 0x0d, 0xfa, 0xf7, 0x82, 0xaf, 0xde, 0x14, 0x33, 0xd9, 0x0c, 0xa2, 0xa8, 0x9d, 0x65,
101 0x1e, 0x75, 0xd6, 0x7e, 0xbc, 0x7c, 0x3e, 0x36, 0xf5, 0xa1, 0x65, 0xee, 0x61, 0x32, 0x61, 0x29,
102 0x39, 0xc1, 0xec, 0xd3, 0x99, 0xe4, 0x60, 0x74, 0xb9, 0x96, 0xd9, 0x3a, 0x88, 0xe0, 0x1e, 0x0a,
105 const unsigned char c_icc_exp[] = {
106 0x03,
109 const unsigned char c_sdad_cr[] = {
110 0x1c, 0x00, 0x9f, 0xc4, 0x86, 0x79, 0x15, 0x7d, 0xbf, 0xf4, 0x5f, 0x65, 0xd3, 0x3f, 0xf7, 0x8d,
111 0x4f, 0xcb, 0xf0, 0xcf, 0x5e, 0xa4, 0x20, 0x8d, 0x10, 0x7a, 0xe9, 0x5a, 0xa3, 0x8c, 0x54, 0x6d,
112 0x0e, 0x5a, 0x18, 0xb8, 0x74, 0x03, 0xa1, 0x2b, 0xd4, 0x47, 0xa8, 0xbb, 0xfc, 0x1e, 0x49, 0xce,
113 0x0b, 0x2e, 0x25, 0x13, 0x89, 0x20, 0x57, 0x03, 0xc9, 0xbb, 0x1a, 0x88, 0xcc, 0x79, 0xf1, 0xdd,
114 0xc2, 0xf9, 0x84, 0x1e, 0xad, 0xf0, 0x7c, 0xe0, 0x7b, 0x62, 0x51, 0x1d, 0xdc, 0x93, 0xdf, 0x59,
115 0xf2, 0x8f, 0x0e, 0x91, 0xf9, 0x23, 0x32, 0xd2, 0x9c, 0xde, 0xf2, 0xbc, 0xcb, 0x10, 0x08, 0x85,
116 0x05, 0x00, 0xef, 0x3e, 0x47, 0x0a, 0x4c, 0xb1, 0x8c, 0xd9, 0x1a, 0xa5, 0xc1, 0xa1, 0x08, 0xf3,
120 const unsigned char c_ssd1[] = {
121 0x5f, 0x25, 0x03, 0x14, 0x05, 0x01, 0x5f, 0x24, 0x03, 0x15, 0x06, 0x30, 0x5a, 0x08, 0x52, 0x85,
122 0x88, 0x12, 0x54, 0x34, 0x56, 0x53, 0x5f, 0x34, 0x01, 0x01, 0x8e, 0x0c, 0x00, 0x00, 0x00, 0x00,
123 0x00, 0x00, 0x00, 0x00, 0x1e, 0x03, 0x1f, 0x03, 0x9f, 0x07, 0x02, 0xff, 0x00, 0x9f, 0x0d, 0x05,
124 0xbc, 0x50, 0xbc, 0x00, 0x00, 0x9f, 0x0e, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x0f, 0x05,
125 0xbc, 0x70, 0xbc, 0x98, 0x00, 0x9f, 0x4a, 0x01, 0x82, 0x5f, 0x28, 0x02, 0x06, 0x43, 0x8c, 0x21,
126 0x9f, 0x02, 0x06, 0x9f, 0x03, 0x06, 0x9f, 0x1a, 0x02, 0x95, 0x05, 0x5f, 0x2a, 0x02, 0x9a, 0x03,
127 0x9c, 0x01, 0x9f, 0x37, 0x04, 0x9f, 0x35, 0x01, 0x9f, 0x45, 0x02, 0x9f, 0x4c, 0x08, 0x9f, 0x34,
128 0x03, 0x8d, 0x0c, 0x91, 0x0a, 0x8a, 0x02, 0x95, 0x05, 0x9f, 0x37, 0x04, 0x9f, 0x4c, 0x08,
129 0x39, 0x00,
132 static const struct tlv ssd1_tlv = {
133 .len = sizeof(c_ssd1),
134 .value = c_ssd1,
137 const unsigned char c_pan[] = {
138 0x52, 0x85, 0x88, 0x12, 0x54, 0x34, 0x56, 0x53,
141 const unsigned char c_dd1[] = {
142 0x12, 0x34, 0x57, 0x79,
145 const unsigned char c_dd2[] = {
146 0x9f, 0x27, 0x01, 0x40, 0x9f, 0x36, 0x02, 0x00, 0x10, 0x9f, 0x10, 0x12, 0x00, 0x10, 0x90, 0x40,
147 0x01, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
150 const unsigned char c_crm1[] = {
151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x43, 0x00, 0x00,
152 0x00, 0x00, 0x00, 0x06, 0x43, 0x14, 0x09, 0x25, 0x50, 0x12, 0x34, 0x57, 0x79, 0x23, 0x00, 0x00,
153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x03, 0x00,
156 static const struct tlv crm1_tlv = {
157 .len = sizeof(c_crm1),
158 .value = c_crm1,
161 static int cda_test_raw(bool verbose) {
162 const struct emv_pk *pk = &c_mchip_05;
164 struct crypto_pk *kcp = crypto_pk_open(PK_RSA,
165 pk->modulus, pk->mlen,
166 pk->exp, pk->elen);
167 if (!kcp)
168 return 1;
170 unsigned char *ipk_data;
171 size_t ipk_data_len;
172 ipk_data = crypto_pk_encrypt(kcp, c_issuer_cert, sizeof(c_issuer_cert), &ipk_data_len);
173 crypto_pk_close(kcp);
175 if (!ipk_data)
176 return 1;
178 if (verbose) {
179 PrintAndLogEx(INFO, "issuer cert:");
180 print_buffer(ipk_data, ipk_data_len, 1);
183 size_t ipk_pk_len = ipk_data[13];
184 unsigned char *ipk_pk = calloc(1, ipk_pk_len);
185 memcpy(ipk_pk, ipk_data + 15, ipk_data_len - 36);
186 memcpy(ipk_pk + ipk_data_len - 36, c_issuer_rem, sizeof(c_issuer_rem));
188 struct crypto_hash *ch;
189 ch = crypto_hash_open(HASH_SHA_1);
190 if (!ch) {
191 free(ipk_pk);
192 free(ipk_data);
193 return 1;
196 crypto_hash_write(ch, ipk_data + 1, 14);
197 crypto_hash_write(ch, ipk_pk, ipk_pk_len);
198 crypto_hash_write(ch, c_issuer_exp, sizeof(c_issuer_exp));
200 unsigned char *h = crypto_hash_read(ch);
201 if (!h) {
202 crypto_hash_close(ch);
203 free(ipk_pk);
204 free(ipk_data);
205 return 1;
208 if (verbose) {
209 PrintAndLogEx(INFO, "crypto hash:");
210 print_buffer(h, 20, 1);
213 if (memcmp(ipk_data + ipk_data_len - 21, h, 20)) {
214 crypto_hash_close(ch);
215 free(ipk_pk);
216 free(ipk_data);
217 return 1;
220 crypto_hash_close(ch);
221 free(ipk_data);
223 struct crypto_pk *ikcp = crypto_pk_open(PK_RSA, ipk_pk, (int) ipk_pk_len,
224 c_issuer_exp, (int) sizeof(c_issuer_exp));
225 free(ipk_pk);
226 if (!ikcp)
227 return 1;
229 unsigned char *iccpk_data;
230 size_t iccpk_data_len;
231 iccpk_data = crypto_pk_encrypt(ikcp, c_icc_cert, sizeof(c_icc_cert), &iccpk_data_len);
232 crypto_pk_close(ikcp);
234 if (!iccpk_data)
235 return 1;
237 if (verbose) {
238 PrintAndLogEx(INFO, "icc cert:");
239 print_buffer(iccpk_data, iccpk_data_len, 1);
242 size_t iccpk_pk_len = iccpk_data[19];
243 unsigned char *iccpk_pk = calloc(1, iccpk_pk_len);
244 memcpy(iccpk_pk, iccpk_data + 21, /*iccpk_data_len - 36*/iccpk_pk_len);
245 /*memcpy(iccpk_pk + iccpk_data_len - 36, icc_rem, sizeof(icc_rem));*/
247 ch = crypto_hash_open(HASH_SHA_1);
248 if (!ch) {
249 free(iccpk_pk);
250 free(iccpk_data);
251 return 1;
254 crypto_hash_write(ch, iccpk_data + 1, iccpk_data_len - 22);
255 crypto_hash_write(ch, c_icc_exp, sizeof(c_icc_exp));
256 crypto_hash_write(ch, c_ssd1, sizeof(c_ssd1));
258 h = crypto_hash_read(ch);
259 if (!h) {
260 crypto_hash_close(ch);
261 free(iccpk_pk);
262 free(iccpk_data);
263 return 1;
266 if (verbose) {
267 PrintAndLogEx(INFO, "crypto hash1.1:");
268 print_buffer(h, 20, 1);
271 if (memcmp(iccpk_data + iccpk_data_len - 21, h, 20)) {
272 crypto_hash_close(ch);
273 free(iccpk_pk);
274 free(iccpk_data);
275 return 1;
278 crypto_hash_close(ch);
279 free(iccpk_data);
281 struct crypto_pk *icckcp = crypto_pk_open(PK_RSA, iccpk_pk, (int) iccpk_pk_len,
282 c_issuer_exp, (int) sizeof(c_issuer_exp));
283 free(iccpk_pk);
284 if (!icckcp)
285 return 1;
287 size_t sdad_len;
288 unsigned char *sdad = crypto_pk_encrypt(icckcp, c_sdad_cr, sizeof(c_sdad_cr), &sdad_len);
289 crypto_pk_close(icckcp);
290 if (!sdad)
291 return 1;
293 if (verbose) {
294 PrintAndLogEx(INFO, "SDAD:");
295 print_buffer(sdad, sdad_len, 1);
298 ch = crypto_hash_open(HASH_SHA_1);
299 if (!ch) {
300 free(sdad);
301 return 1;
304 crypto_hash_write(ch, sdad + 1, sdad_len - 22);
305 crypto_hash_write(ch, c_dd1, sizeof(c_dd1));
307 unsigned char *h2 = crypto_hash_read(ch);
308 if (!h2) {
309 crypto_hash_close(ch);
310 free(sdad);
311 return 1;
314 if (verbose) {
315 PrintAndLogEx(INFO, "crypto hash2:");
316 print_buffer(h2, 20, 1);
319 crypto_hash_close(ch);
321 ch = crypto_hash_open(HASH_SHA_1);
322 if (!ch) {
323 free(sdad);
324 return 1;
327 crypto_hash_write(ch, c_crm1, sizeof(c_crm1));
328 crypto_hash_write(ch, c_dd2, sizeof(c_dd2));
330 h = crypto_hash_read(ch);
331 if (!h) {
332 crypto_hash_close(ch);
333 free(sdad);
334 return 1;
337 if (verbose) {
338 PrintAndLogEx(INFO, "crypto hash2.1:");
339 print_buffer(h, 20, 1);
342 if (memcmp(sdad + 5 + 8 + 1 + 8, h, 20)) {
343 crypto_hash_close(ch);
344 free(sdad);
345 return 1;
348 crypto_hash_close(ch);
349 free(sdad);
350 return 0;
353 static int cda_test_pk(bool verbose) {
354 const struct emv_pk *pk = &c_mchip_05;
355 struct tlvdb *db;
357 db = tlvdb_external(0x90, sizeof(c_issuer_cert), c_issuer_cert);
358 tlvdb_add(db, tlvdb_external(0x9f32, sizeof(c_issuer_exp), c_issuer_exp));
359 tlvdb_add(db, tlvdb_external(0x92, sizeof(c_issuer_rem), c_issuer_rem));
360 tlvdb_add(db, tlvdb_external(0x5a, sizeof(c_pan), c_pan));
362 struct emv_pk *ipk = emv_pki_recover_issuer_cert(pk, db);
363 if (!ipk) {
364 PrintAndLogEx(WARNING, "Could not recover Issuer certificate!");
365 tlvdb_free(db);
366 return 2;
369 tlvdb_add(db, tlvdb_external(0x9f46, sizeof(c_icc_cert), c_icc_cert));
370 tlvdb_add(db, tlvdb_external(0x9f47, sizeof(c_icc_exp), c_icc_exp));
371 /*tlvdb_add(db, tlvdb_external(0x9f48, sizeof(issuer_rem), issuer_rem));*/
373 struct emv_pk *iccpk = emv_pki_recover_icc_cert(ipk, db, &ssd1_tlv);
374 if (!iccpk) {
375 PrintAndLogEx(WARNING, "Could not recover ICC certificate!");
376 emv_pk_free(ipk);
377 tlvdb_free(db);
378 return 2;
381 tlvdb_add(db, tlvdb_fixed(0x9f37, sizeof(c_dd1), c_dd1));
383 struct tlvdb *cda_db;
384 cda_db = tlvdb_fixed(0x9f27, 1, (unsigned char[]) { 0x40 });
385 tlvdb_add(cda_db, tlvdb_fixed(0x9f36, 2, (unsigned char[]) { 0x00, 0x10 }));
386 tlvdb_add(cda_db, tlvdb_external(0x9f4b, sizeof(c_sdad_cr), c_sdad_cr));
387 tlvdb_add(cda_db, tlvdb_fixed(0x9f10, 0x12,
388 (unsigned char[]) { 0x00, 0x10, 0x90, 0x40, 0x01, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff}));
390 struct tlvdb *idndb = emv_pki_perform_cda(iccpk, db, cda_db,
391 NULL,
392 &crm1_tlv,
393 NULL);
394 if (!idndb) {
395 PrintAndLogEx(WARNING, "Could not recover IDN!");
396 tlvdb_free(cda_db);
397 emv_pk_free(iccpk);
398 emv_pk_free(ipk);
399 tlvdb_free(db);
400 return 2;
403 const struct tlv *idn = tlvdb_get(idndb, 0x9f4c, NULL);
404 if (!idn) {
405 PrintAndLogEx(WARNING, "IDN not found!");
406 tlvdb_free(idndb);
407 tlvdb_free(cda_db);
408 emv_pk_free(iccpk);
409 emv_pk_free(ipk);
410 tlvdb_free(db);
411 return 2;
414 if (verbose) {
415 PrintAndLogEx(INFO, "IDN:");
416 print_buffer(idn->value, idn->len, 1);
419 tlvdb_free(idndb);
420 tlvdb_free(cda_db);
421 emv_pk_free(iccpk);
422 emv_pk_free(ipk);
423 tlvdb_free(db);
424 return 0;
427 int exec_cda_test(bool verbose) {
428 int ret = cda_test_raw(verbose);
429 if (ret) {
430 PrintAndLogEx(WARNING, "CDA raw test ( %s )", _RED_("fail"));
431 return ret;
433 PrintAndLogEx(INFO, "CDA raw test ( %s )", _GREEN_("ok"));
435 ret = cda_test_pk(verbose);
436 if (ret) {
437 PrintAndLogEx(WARNING, "CDA test pk ( %s )", _RED_("fail"));
438 return ret;
440 PrintAndLogEx(INFO, "CDA test pk ( %s )", _GREEN_("ok"));
441 return 0;