Cleanup armsrc/string.c and string.h (#964)
[legacy-proxmark3.git] / client / emv / test / cda_test.c
blob536a5862b81b329027f0c9157ed5c6eedced9042
1 /*
2 * emv-tools - a set of tools to work with EMV family of smart cards
3 * Copyright (C) 2012, 2015 Dmitry Eremin-Solenikov
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
16 #ifdef HAVE_CONFIG_H
17 #include <config.h>
18 #endif
20 #include "../emv_pk.h"
21 #include "../crypto.h"
22 #include "../dump.h"
23 #include "../tlv.h"
24 #include "../emv_pki.h"
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdlib.h>
30 struct emv_pk c_mchip_05 = {
31 .rid = { 0xa0, 0x00, 0x00, 0x00, 0x04, },
32 .index = 5,
33 .hash_algo = HASH_SHA_1,
34 .pk_algo = PK_RSA,
35 .hash = {
36 0xeb, 0xfa, 0x0d, 0x5d,
37 0x06, 0xd8, 0xce, 0x70,
38 0x2d, 0xa3, 0xea, 0xe8,
39 0x90, 0x70, 0x1d, 0x45,
40 0xe2, 0x74, 0xc8, 0x45, },
41 .exp = { 0x03, },
42 .elen = 1,
43 .mlen = 1408 / 8,
44 .modulus = (unsigned char[]){
45 0xb8, 0x04, 0x8a, 0xbc, 0x30, 0xc9, 0x0d, 0x97, 0x63, 0x36, 0x54, 0x3e, 0x3f, 0xd7, 0x09, 0x1c,
46 0x8f, 0xe4, 0x80, 0x0d, 0xf8, 0x20, 0xed, 0x55, 0xe7, 0xe9, 0x48, 0x13, 0xed, 0x00, 0x55, 0x5b,
47 0x57, 0x3f, 0xec, 0xa3, 0xd8, 0x4a, 0xf6, 0x13, 0x1a, 0x65, 0x1d, 0x66, 0xcf, 0xf4, 0x28, 0x4f,
48 0xb1, 0x3b, 0x63, 0x5e, 0xdd, 0x0e, 0xe4, 0x01, 0x76, 0xd8, 0xbf, 0x04, 0xb7, 0xfd, 0x1c, 0x7b,
49 0xac, 0xf9, 0xac, 0x73, 0x27, 0xdf, 0xaa, 0x8a, 0xa7, 0x2d, 0x10, 0xdb, 0x3b, 0x8e, 0x70, 0xb2,
50 0xdd, 0xd8, 0x11, 0xcb, 0x41, 0x96, 0x52, 0x5e, 0xa3, 0x86, 0xac, 0xc3, 0x3c, 0x0d, 0x9d, 0x45,
51 0x75, 0x91, 0x64, 0x69, 0xc4, 0xe4, 0xf5, 0x3e, 0x8e, 0x1c, 0x91, 0x2c, 0xc6, 0x18, 0xcb, 0x22,
52 0xdd, 0xe7, 0xc3, 0x56, 0x8e, 0x90, 0x02, 0x2e, 0x6b, 0xba, 0x77, 0x02, 0x02, 0xe4, 0x52, 0x2a,
53 0x2d, 0xd6, 0x23, 0xd1, 0x80, 0xe2, 0x15, 0xbd, 0x1d, 0x15, 0x07, 0xfe, 0x3d, 0xc9, 0x0c, 0xa3,
54 0x10, 0xd2, 0x7b, 0x3e, 0xfc, 0xcd, 0x8f, 0x83, 0xde, 0x30, 0x52, 0xca, 0xd1, 0xe4, 0x89, 0x38,
55 0xc6, 0x8d, 0x09, 0x5a, 0xac, 0x91, 0xb5, 0xf3, 0x7e, 0x28, 0xbb, 0x49, 0xec, 0x7e, 0xd5, 0x97,
59 const unsigned char c_issuer_cert[] = {
60 0x17, 0x14, 0x28, 0x4f, 0x76, 0x3b, 0x85, 0x86, 0xee, 0x6d, 0x31, 0x99, 0x51, 0xf7, 0xe6, 0x3f,
61 0xa2, 0x50, 0x76, 0xe5, 0x0d, 0xc9, 0xd3, 0x20, 0x0b, 0xa9, 0x98, 0xd3, 0xa0, 0x52, 0xad, 0xba,
62 0x9a, 0xb6, 0x9a, 0xc6, 0xad, 0x6a, 0xdd, 0x3c, 0xe0, 0x9f, 0x02, 0x78, 0xf4, 0x07, 0x4e, 0xc4,
63 0xee, 0x9b, 0x1d, 0x22, 0x68, 0xa3, 0xe9, 0x53, 0x57, 0x5e, 0x45, 0x4e, 0x50, 0xcd, 0x86, 0x0b,
64 0xf4, 0x24, 0xc5, 0x1c, 0x59, 0x77, 0x12, 0xd2, 0xaa, 0x05, 0x70, 0x89, 0xdd, 0x86, 0x73, 0xe5,
65 0x1b, 0x1e, 0x1d, 0x71, 0x88, 0x03, 0x48, 0x92, 0x07, 0x7a, 0xc1, 0x8a, 0x6a, 0xe2, 0x34, 0x88,
66 0xbe, 0xa9, 0xdf, 0x3b, 0x1a, 0x83, 0xf2, 0xc0, 0x80, 0x0c, 0xd7, 0xc5, 0xcd, 0xf2, 0xfd, 0xe0,
67 0x49, 0x6f, 0x7b, 0xc3, 0x9f, 0xb4, 0xbf, 0x36, 0x32, 0x99, 0xbf, 0xa6, 0x37, 0xb2, 0xec, 0x33,
68 0xc5, 0x07, 0xe3, 0x68, 0x21, 0xee, 0xc2, 0x07, 0x5f, 0x0e, 0x42, 0x0d, 0x38, 0xa1, 0xc9, 0xf3,
69 0x12, 0x72, 0x61, 0xba, 0x31, 0x6c, 0x98, 0x76, 0x74, 0xfa, 0xdb, 0x20, 0xea, 0x7f, 0xeb, 0x75,
70 0xee, 0x45, 0x5d, 0x12, 0x14, 0x6e, 0xa6, 0xf0, 0x2e, 0x8b, 0x01, 0xec, 0x2f, 0xa7, 0xa1, 0x15,
73 const unsigned char c_issuer_rem[] = {
74 0x6e, 0x63, 0xb7, 0xbc, 0x70, 0xab, 0xdd, 0x09, 0x34, 0x1b, 0x34, 0xc0, 0x32, 0x86, 0xba, 0x9b,
75 0xd8, 0x3b, 0xa7, 0x93, 0x6c, 0x5b, 0x77, 0x98, 0xfb, 0x22, 0xc5, 0xe5, 0x3f, 0xf2, 0x40, 0xa2,
76 0x6d, 0xbd, 0x64, 0x15,
79 const unsigned char c_issuer_exp[] = {
80 0x03,
83 const unsigned char c_icc_cert[] = {
84 0xa4, 0x2f, 0xbe, 0xb1, 0x56, 0xb9, 0x8d, 0xcb, 0x05, 0x54, 0xda, 0x06, 0x2a, 0xdc, 0xa5, 0x30,
85 0x9a, 0x91, 0xf0, 0x4f, 0xa2, 0xc7, 0xbd, 0x71, 0x02, 0xa8, 0xd7, 0x3f, 0x16, 0xa3, 0xcf, 0xad,
86 0xe8, 0xaa, 0xdf, 0x4f, 0x3f, 0xe2, 0xa2, 0x12, 0x5c, 0xcd, 0xd7, 0x7c, 0x6b, 0x9f, 0x78, 0xb5,
87 0xb4, 0x37, 0x1c, 0xe0, 0x80, 0x57, 0x25, 0xb0, 0xf9, 0xc0, 0x27, 0xaf, 0x14, 0x7d, 0x91, 0xe1,
88 0xff, 0xdb, 0x20, 0x1e, 0x9c, 0x17, 0x0c, 0xe7, 0x77, 0x05, 0x3a, 0x17, 0x2a, 0xd5, 0x26, 0xdc,
89 0xaf, 0xd3, 0x38, 0x95, 0xe1, 0xa9, 0x47, 0x30, 0x5c, 0x5b, 0x16, 0x7f, 0x2e, 0x7c, 0x6f, 0x99,
90 0x15, 0x81, 0xa6, 0x52, 0xee, 0x47, 0x31, 0x54, 0x76, 0x0c, 0x2e, 0xd7, 0x74, 0x21, 0x4e, 0x50,
91 0xdf, 0xec, 0xdd, 0x4c, 0xf2, 0x94, 0xc9, 0x74, 0xb8, 0x9e, 0xbc, 0xa2, 0x5b, 0x5a, 0xb3, 0xc0,
92 0xbe, 0xb5, 0x0d, 0xfa, 0xf7, 0x82, 0xaf, 0xde, 0x14, 0x33, 0xd9, 0x0c, 0xa2, 0xa8, 0x9d, 0x65,
93 0x1e, 0x75, 0xd6, 0x7e, 0xbc, 0x7c, 0x3e, 0x36, 0xf5, 0xa1, 0x65, 0xee, 0x61, 0x32, 0x61, 0x29,
94 0x39, 0xc1, 0xec, 0xd3, 0x99, 0xe4, 0x60, 0x74, 0xb9, 0x96, 0xd9, 0x3a, 0x88, 0xe0, 0x1e, 0x0a,
97 const unsigned char c_icc_exp[] = {
98 0x03,
101 const unsigned char c_sdad_cr[] = {
102 0x1c, 0x00, 0x9f, 0xc4, 0x86, 0x79, 0x15, 0x7d, 0xbf, 0xf4, 0x5f, 0x65, 0xd3, 0x3f, 0xf7, 0x8d,
103 0x4f, 0xcb, 0xf0, 0xcf, 0x5e, 0xa4, 0x20, 0x8d, 0x10, 0x7a, 0xe9, 0x5a, 0xa3, 0x8c, 0x54, 0x6d,
104 0x0e, 0x5a, 0x18, 0xb8, 0x74, 0x03, 0xa1, 0x2b, 0xd4, 0x47, 0xa8, 0xbb, 0xfc, 0x1e, 0x49, 0xce,
105 0x0b, 0x2e, 0x25, 0x13, 0x89, 0x20, 0x57, 0x03, 0xc9, 0xbb, 0x1a, 0x88, 0xcc, 0x79, 0xf1, 0xdd,
106 0xc2, 0xf9, 0x84, 0x1e, 0xad, 0xf0, 0x7c, 0xe0, 0x7b, 0x62, 0x51, 0x1d, 0xdc, 0x93, 0xdf, 0x59,
107 0xf2, 0x8f, 0x0e, 0x91, 0xf9, 0x23, 0x32, 0xd2, 0x9c, 0xde, 0xf2, 0xbc, 0xcb, 0x10, 0x08, 0x85,
108 0x05, 0x00, 0xef, 0x3e, 0x47, 0x0a, 0x4c, 0xb1, 0x8c, 0xd9, 0x1a, 0xa5, 0xc1, 0xa1, 0x08, 0xf3,
112 const unsigned char c_ssd1[] = {
113 0x5f, 0x25, 0x03, 0x14, 0x05, 0x01, 0x5f, 0x24, 0x03, 0x15, 0x06, 0x30, 0x5a, 0x08, 0x52, 0x85,
114 0x88, 0x12, 0x54, 0x34, 0x56, 0x53, 0x5f, 0x34, 0x01, 0x01, 0x8e, 0x0c, 0x00, 0x00, 0x00, 0x00,
115 0x00, 0x00, 0x00, 0x00, 0x1e, 0x03, 0x1f, 0x03, 0x9f, 0x07, 0x02, 0xff, 0x00, 0x9f, 0x0d, 0x05,
116 0xbc, 0x50, 0xbc, 0x00, 0x00, 0x9f, 0x0e, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x0f, 0x05,
117 0xbc, 0x70, 0xbc, 0x98, 0x00, 0x9f, 0x4a, 0x01, 0x82, 0x5f, 0x28, 0x02, 0x06, 0x43, 0x8c, 0x21,
118 0x9f, 0x02, 0x06, 0x9f, 0x03, 0x06, 0x9f, 0x1a, 0x02, 0x95, 0x05, 0x5f, 0x2a, 0x02, 0x9a, 0x03,
119 0x9c, 0x01, 0x9f, 0x37, 0x04, 0x9f, 0x35, 0x01, 0x9f, 0x45, 0x02, 0x9f, 0x4c, 0x08, 0x9f, 0x34,
120 0x03, 0x8d, 0x0c, 0x91, 0x0a, 0x8a, 0x02, 0x95, 0x05, 0x9f, 0x37, 0x04, 0x9f, 0x4c, 0x08,
121 0x39, 0x00,
123 static const struct tlv ssd1_tlv = {
124 .len = sizeof(c_ssd1),
125 .value = c_ssd1,
128 const unsigned char c_pan[] = {
129 0x52, 0x85, 0x88, 0x12, 0x54, 0x34, 0x56, 0x53,
132 const unsigned char c_dd1[] = {
133 0x12, 0x34, 0x57, 0x79,
136 const unsigned char c_dd2[] = {
137 0x9f, 0x27, 0x01, 0x40, 0x9f, 0x36, 0x02, 0x00, 0x10, 0x9f, 0x10, 0x12, 0x00, 0x10, 0x90, 0x40,
138 0x01, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
141 const unsigned char c_crm1[] = {
142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x43, 0x00, 0x00,
143 0x00, 0x00, 0x00, 0x06, 0x43, 0x14, 0x09, 0x25, 0x50, 0x12, 0x34, 0x57, 0x79, 0x23, 0x00, 0x00,
144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x03, 0x00,
146 static const struct tlv crm1_tlv = {
147 .len = sizeof(c_crm1),
148 .value = c_crm1,
151 static int cda_test_raw(bool verbose)
153 const struct emv_pk *pk = &c_mchip_05;
155 struct crypto_pk *kcp = crypto_pk_open(PK_RSA,
156 pk->modulus, pk->mlen,
157 pk->exp, pk->elen);
158 if (!kcp)
159 return 1;
161 unsigned char *ipk_data;
162 size_t ipk_data_len;
163 ipk_data = crypto_pk_encrypt(kcp, c_issuer_cert, sizeof(c_issuer_cert), &ipk_data_len);
164 crypto_pk_close(kcp);
166 if (!ipk_data)
167 return 1;
169 if (verbose) {
170 printf("issuer cert:\n");
171 dump_buffer(ipk_data, ipk_data_len, stdout, 0);
174 size_t ipk_pk_len = ipk_data[13];
175 unsigned char *ipk_pk = malloc(ipk_pk_len);
176 memcpy(ipk_pk, ipk_data + 15, ipk_data_len - 36);
177 memcpy(ipk_pk + ipk_data_len - 36, c_issuer_rem, sizeof(c_issuer_rem));
179 struct crypto_hash *ch;
180 ch = crypto_hash_open(HASH_SHA_1);
181 if (!ch) {
182 free(ipk_pk);
183 free(ipk_data);
184 return 1;
187 crypto_hash_write(ch, ipk_data + 1, 14);
188 crypto_hash_write(ch, ipk_pk, ipk_pk_len);
189 crypto_hash_write(ch, c_issuer_exp, sizeof(c_issuer_exp));
191 unsigned char *h = crypto_hash_read(ch);
192 if (!h) {
193 crypto_hash_close(ch);
194 free(ipk_pk);
195 free(ipk_data);
196 return 1;
199 if (verbose) {
200 printf("crypto hash:\n");
201 dump_buffer(h, 20, stdout, 0);
204 if (memcmp(ipk_data + ipk_data_len - 21, h, 20)) {
205 crypto_hash_close(ch);
206 free(ipk_pk);
207 free(ipk_data);
208 return 1;
211 crypto_hash_close(ch);
212 free(ipk_data);
214 struct crypto_pk *ikcp = crypto_pk_open(PK_RSA, ipk_pk, (int) ipk_pk_len,
215 c_issuer_exp, (int) sizeof(c_issuer_exp));
216 free(ipk_pk);
217 if (!ikcp)
218 return 1;
220 unsigned char *iccpk_data;
221 size_t iccpk_data_len;
222 iccpk_data = crypto_pk_encrypt(ikcp, c_icc_cert, sizeof(c_icc_cert), &iccpk_data_len);
223 crypto_pk_close(ikcp);
225 if (!iccpk_data)
226 return 1;
228 if (verbose) {
229 printf("icc cert:\n");
230 dump_buffer(iccpk_data, iccpk_data_len, stdout, 0);
233 size_t iccpk_pk_len = iccpk_data[19];
234 unsigned char *iccpk_pk = malloc(iccpk_pk_len);
235 memcpy(iccpk_pk, iccpk_data + 21, /*iccpk_data_len - 36*/iccpk_pk_len);
236 /*memcpy(iccpk_pk + iccpk_data_len - 36, icc_rem, sizeof(icc_rem));*/
238 ch = crypto_hash_open(HASH_SHA_1);
239 if (!ch) {
240 free(iccpk_pk);
241 free(iccpk_data);
242 return 1;
245 crypto_hash_write(ch, iccpk_data + 1, iccpk_data_len - 22);
246 crypto_hash_write(ch, c_icc_exp, sizeof(c_icc_exp));
247 crypto_hash_write(ch, c_ssd1, sizeof(c_ssd1));
249 h = crypto_hash_read(ch);
250 if (!h) {
251 crypto_hash_close(ch);
252 free(iccpk_pk);
253 free(iccpk_data);
254 return 1;
257 if (verbose) {
258 printf("crypto hash1.1:\n");
259 dump_buffer(h, 20, stdout, 0);
262 if (memcmp(iccpk_data + iccpk_data_len - 21, h, 20)) {
263 crypto_hash_close(ch);
264 free(iccpk_pk);
265 free(iccpk_data);
266 return 1;
269 crypto_hash_close(ch);
270 free(iccpk_data);
272 struct crypto_pk *icckcp = crypto_pk_open(PK_RSA, iccpk_pk, (int) iccpk_pk_len,
273 c_issuer_exp, (int) sizeof(c_issuer_exp));
274 free(iccpk_pk);
275 if (!icckcp)
276 return 1;
278 size_t sdad_len;
279 unsigned char *sdad = crypto_pk_encrypt(icckcp, c_sdad_cr, sizeof(c_sdad_cr), &sdad_len);
280 crypto_pk_close(icckcp);
281 if (!sdad)
282 return 1;
284 if (verbose) {
285 printf("SDAD:\n");
286 dump_buffer(sdad, sdad_len, stdout, 0);
289 ch = crypto_hash_open(HASH_SHA_1);
290 if (!ch) {
291 free(sdad);
292 return 1;
295 crypto_hash_write(ch, sdad + 1, sdad_len - 22);
296 crypto_hash_write(ch, c_dd1, sizeof(c_dd1));
298 unsigned char *h2 = crypto_hash_read(ch);
299 if (!h2) {
300 crypto_hash_close(ch);
301 free(sdad);
302 return 1;
305 if (verbose) {
306 printf("crypto hash2:\n");
307 dump_buffer(h2, 20, stdout, 0);
310 crypto_hash_close(ch);
312 ch = crypto_hash_open(HASH_SHA_1);
313 if (!ch) {
314 free(sdad);
315 return 1;
318 crypto_hash_write(ch, c_crm1, sizeof(c_crm1));
319 crypto_hash_write(ch, c_dd2, sizeof(c_dd2));
321 h = crypto_hash_read(ch);
322 if (!h) {
323 crypto_hash_close(ch);
324 free(sdad);
325 return 1;
328 if (verbose) {
329 printf("crypto hash2.1:\n");
330 dump_buffer(h, 20, stdout, 0);
333 if (memcmp(sdad + 5 + 8 + 1 + 8, h, 20)) {
334 crypto_hash_close(ch);
335 free(sdad);
336 return 1;
339 crypto_hash_close(ch);
341 free(sdad);
343 return 0;
346 static int cda_test_pk(bool verbose)
348 const struct emv_pk *pk = &c_mchip_05;
349 struct tlvdb *db;
351 db = tlvdb_external(0x90, sizeof(c_issuer_cert), c_issuer_cert);
352 tlvdb_add(db, tlvdb_external(0x9f32, sizeof(c_issuer_exp), c_issuer_exp));
353 tlvdb_add(db, tlvdb_external(0x92, sizeof(c_issuer_rem), c_issuer_rem));
354 tlvdb_add(db, tlvdb_external(0x5a, sizeof(c_pan), c_pan));
356 struct emv_pk *ipk = emv_pki_recover_issuer_cert(pk, db);
357 if (!ipk) {
358 fprintf(stderr, "Could not recover Issuer certificate!\n");
359 tlvdb_free(db);
360 return 2;
363 tlvdb_add(db, tlvdb_external(0x9f46, sizeof(c_icc_cert), c_icc_cert));
364 tlvdb_add(db, tlvdb_external(0x9f47, sizeof(c_icc_exp), c_icc_exp));
365 /*tlvdb_add(db, tlvdb_external(0x9f48, sizeof(issuer_rem), issuer_rem));*/
367 struct emv_pk *iccpk = emv_pki_recover_icc_cert(ipk, db, &ssd1_tlv);
368 if (!iccpk) {
369 fprintf(stderr, "Could not recover ICC certificate!\n");
370 emv_pk_free(ipk);
371 tlvdb_free(db);
372 return 2;
375 tlvdb_add(db, tlvdb_fixed(0x9f37, sizeof(c_dd1), c_dd1));
377 struct tlvdb *cda_db;
378 cda_db = tlvdb_fixed(0x9f27, 1, (unsigned char[]){ 0x40 });
379 tlvdb_add(cda_db, tlvdb_fixed(0x9f36, 2, (unsigned char[]) { 0x00, 0x10 }));
380 tlvdb_add(cda_db, tlvdb_external(0x9f4b, sizeof(c_sdad_cr), c_sdad_cr));
381 tlvdb_add(cda_db, tlvdb_fixed(0x9f10, 0x12,
382 (unsigned char[]) { 0x00, 0x10, 0x90, 0x40, 0x01, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff}));
384 struct tlvdb *idndb = emv_pki_perform_cda(iccpk, db, cda_db,
385 NULL,
386 &crm1_tlv,
387 NULL);
388 if (!idndb) {
389 fprintf(stderr, "Could not recover IDN!\n");
390 tlvdb_free(cda_db);
391 emv_pk_free(iccpk);
392 emv_pk_free(ipk);
393 tlvdb_free(db);
394 return 2;
397 const struct tlv *idn = tlvdb_get(idndb, 0x9f4c, NULL);
398 if (!idn) {
399 fprintf(stderr, "IDN not found!\n");
400 tlvdb_free(idndb);
401 tlvdb_free(cda_db);
402 emv_pk_free(iccpk);
403 emv_pk_free(ipk);
404 tlvdb_free(db);
405 return 2;
408 if (verbose) {
409 printf("IDN:\n");
410 dump_buffer(idn->value, idn->len, stdout, 0);
413 tlvdb_free(idndb);
414 tlvdb_free(cda_db);
415 emv_pk_free(iccpk);
416 emv_pk_free(ipk);
417 tlvdb_free(db);
419 return 0;
422 int exec_cda_test(bool verbose)
424 int ret;
425 fprintf(stdout, "\n");
427 ret = cda_test_raw(verbose);
428 if (ret) {
429 fprintf(stderr, "CDA raw test: failed\n");
430 return ret;
432 fprintf(stdout, "CDA raw test: passed\n");
434 ret = cda_test_pk(verbose);
435 if (ret) {
436 fprintf(stderr, "CDA test pk: failed\n");
437 return ret;
439 fprintf(stdout, "CDA test pk: passed\n");
441 return 0;