From 88d42a1af5d244387a51508520627740a3a4f6e6 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 13:46:52 +0200 Subject: [PATCH 01/20] make --- client/Makefile | 1 + client/emv/emv_roca.c | 117 ++++++++++++++++++++++++++++++++++++++++++ client/emv/emv_roca.h | 41 +++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 client/emv/emv_roca.c create mode 100644 client/emv/emv_roca.h diff --git a/client/Makefile b/client/Makefile index 766163c09..4f7168fa0 100644 --- a/client/Makefile +++ b/client/Makefile @@ -155,6 +155,7 @@ CMDSRCS = crapto1/crapto1.c \ emv/test/dda_test.c\ emv/test/cda_test.c\ emv/cmdemv.c \ + emv/emv_roca.c \ mifare4.c \ cmdanalyse.c \ cmdhf.c \ diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c new file mode 100644 index 000000000..0dfaa1339 --- /dev/null +++ b/client/emv/emv_roca.c @@ -0,0 +1,117 @@ +/* roca.c - ROCA (CVE-2017-15361) fingerprint checker. + * Written by Rob Stradling (based on https://github.com/crocs-muni/roca/blob/master/roca/detect.py) + * Copyright (C) 2017 COMODO CA Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "emv_roca.h" + +static uint8_t g_primes[ROCA_PRINTS_LENGTH] = { + 11, 13, 17, 19, 37, 53, 61, 71, 73, 79, 97, 103, 107, 109, 127, 151, 157 +}; + +mbedtls_mpi* g_prints[ROCA_PRINTS_LENGTH]; + +void rocacheck_init(void) { + + for (uint8_t i = 0; i < ROCA_PRINTS_LENGTH; i++) + mbedtls_mpi_init(g_prints[i]); + + mbedtls_mpi_read_string(g_prints[0], 10, "1026"); + mbedtls_mpi_read_string(g_prints[1], 10, "5658"); + mbedtls_mpi_read_string(g_prints[2], 10, "107286"); + mbedtls_mpi_read_string(g_prints[3], 10, "199410"); + mbedtls_mpi_read_string(g_prints[4], 10, "67109890"); + mbedtls_mpi_read_string(g_prints[5], 10, "5310023542746834"); + mbedtls_mpi_read_string(g_prints[6], 10, "1455791217086302986"); + mbedtls_mpi_read_string(g_prints[7], 10, "20052041432995567486"); + mbedtls_mpi_read_string(g_prints[8], 10, "6041388139249378920330"); + mbedtls_mpi_read_string(g_prints[9], 10, "207530445072488465666"); + mbedtls_mpi_read_string(g_prints[10], 10, "79228162521181866724264247298"); + mbedtls_mpi_read_string(g_prints[11], 10, "1760368345969468176824550810518"); + mbedtls_mpi_read_string(g_prints[12], 10, "50079290986288516948354744811034"); + mbedtls_mpi_read_string(g_prints[13], 10, "473022961816146413042658758988474"); + mbedtls_mpi_read_string(g_prints[14], 10, "144390480366845522447407333004847678774"); + mbedtls_mpi_read_string(g_prints[15], 10, "1800793591454480341970779146165214289059119882"); + mbedtls_mpi_read_string(g_prints[16], 10, "126304807362733370595828809000324029340048915994"); +} + +void rocacheck_cleanup(void) { + for (uint8_t i = 0; i < ROCA_PRINTS_LENGTH; i++) + mbedtls_mpi_free(g_prints[i]); +} + +int bitand_is_zero( mbedtls_mpi* a, mbedtls_mpi* b ) { + + for (int i = 0; i < mbedtls_mpi_bitlen(a); i++) { + + if (mbedtls_mpi_get_bit(a, i) && mbedtls_mpi_get_bit(b, i)) + return 0; + } + return 1; +} + + +bool emv_rocacheck(char *modulus) { + + mbedtls_mpi *t_modulus = NULL; + mbedtls_mpi_init(t_modulus); + + bool ret = true; + + rocacheck_init(); + + // + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(t_modulus, 10, modulus) ); + + + for (int i = 0; i < ROCA_PRINTS_LENGTH; i++) { + + mbedtls_mpi* t_temp = NULL; + mbedtls_mpi* t_prime = NULL; + mbedtls_mpi* g_one = NULL; + + mbedtls_mpi_init(g_one); + mbedtls_mpi_init(t_temp); + mbedtls_mpi_init(t_prime); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(g_one, 10, "1") ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int(t_prime, t_prime, g_primes[i]) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi(t_temp, t_modulus, t_prime) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(g_one, t_temp) ); + + if (bitand_is_zero(t_temp, g_prints[i])) { + PrintAndLogEx(FAILED, "No fingerprint found\n"); + ret = false; + goto cleanup; + } + + mbedtls_mpi_free(g_one); + mbedtls_mpi_free(t_temp); + mbedtls_mpi_free(t_prime); + } + + PrintAndLogEx(SUCCESS, "Fingerprint found!\n"); + +cleanup: + if (t_modulus) + mbedtls_mpi_free(t_modulus); + + rocacheck_cleanup(); + return ret; +} diff --git a/client/emv/emv_roca.h b/client/emv/emv_roca.h new file mode 100644 index 000000000..e2ba0ac51 --- /dev/null +++ b/client/emv/emv_roca.h @@ -0,0 +1,41 @@ + +// ROCA (CVE-2017-15361) fingerprint checker. +// Written by Rob Stradling (based on https://github.com/crocs-muni/roca/blob/master/roca/detect.py) +// Copyright (C) 2017 COMODO CA Limited +// modified 2018 iceman (dropped openssl bignum, now use mbedtls lib) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +//----------------------------------------------------------------------------- +// EMV roca commands +//----------------------------------------------------------------------------- + +#ifndef EMV_ROCA_H__ +#define EMV_ROCA_H__ + +#include +#include +#include "mbedtls/bignum.h" +#include "util.h" + +#define ROCA_PRINTS_LENGTH 17 + +void rocacheck_init(void); +void rocacheck_cleanup(void); +int bitand_is_zero( mbedtls_mpi* a, mbedtls_mpi* b ); + +extern bool emv_rocacheck( char *modulus ); + +#endif + From b1145ba57771237d5a7b8223f2f5746863b5f418 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 14:50:23 +0200 Subject: [PATCH 02/20] mpi_get_uint --- client/emv/emv_roca.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index 0dfaa1339..2843cb2c1 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -64,6 +64,15 @@ int bitand_is_zero( mbedtls_mpi* a, mbedtls_mpi* b ) { } +mbedtls_mpi_uint mpi_get_uint(const mbedtls_mpi *X) { + + if (X->n == 1) { + return X->p[0]; + } + + return 0; +} + bool emv_rocacheck(char *modulus) { mbedtls_mpi *t_modulus = NULL; @@ -93,7 +102,7 @@ bool emv_rocacheck(char *modulus) { MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi(t_temp, t_modulus, t_prime) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(g_one, t_temp) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(g_one, mpi_get_uint(t_temp)) ); if (bitand_is_zero(t_temp, g_prints[i])) { PrintAndLogEx(FAILED, "No fingerprint found\n"); From 9804526dca774c21f617b3b13d431826e3c7a685 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 14:52:24 +0200 Subject: [PATCH 03/20] small fix for unsigned int --- client/emv/emv_roca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index 2843cb2c1..48845c99f 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -66,7 +66,7 @@ int bitand_is_zero( mbedtls_mpi* a, mbedtls_mpi* b ) { mbedtls_mpi_uint mpi_get_uint(const mbedtls_mpi *X) { - if (X->n == 1) { + if (X->n == 1 && X->s > 0) { return X->p[0]; } From ab41b4a991fe4e75c1ebd6c3056ac1667f8d0e2a Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 16:40:53 +0200 Subject: [PATCH 04/20] emv_rocacheck --- client/emv/cmdemv.h | 1 + client/emv/emv_roca.c | 5 ++--- client/emv/emv_roca.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/emv/cmdemv.h b/client/emv/cmdemv.h index 0b0419b07..c91f75606 100644 --- a/client/emv/cmdemv.h +++ b/client/emv/cmdemv.h @@ -25,6 +25,7 @@ #include "cmdmain.h" #include "emvcore.h" #include "apduinfo.h" +#include "emv_roca.h" int CmdEMV(const char *Cmd); diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index 48845c99f..fe68b83ce 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -73,7 +73,7 @@ mbedtls_mpi_uint mpi_get_uint(const mbedtls_mpi *X) { return 0; } -bool emv_rocacheck(char *modulus) { +bool emv_rocacheck(const unsigned char *buf, size_t buflen) { mbedtls_mpi *t_modulus = NULL; mbedtls_mpi_init(t_modulus); @@ -82,8 +82,7 @@ bool emv_rocacheck(char *modulus) { rocacheck_init(); - // - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(t_modulus, 10, modulus) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary(t_modulus, buf, buflen) ); for (int i = 0; i < ROCA_PRINTS_LENGTH; i++) { diff --git a/client/emv/emv_roca.h b/client/emv/emv_roca.h index e2ba0ac51..a42d8349e 100644 --- a/client/emv/emv_roca.h +++ b/client/emv/emv_roca.h @@ -35,7 +35,7 @@ void rocacheck_init(void); void rocacheck_cleanup(void); int bitand_is_zero( mbedtls_mpi* a, mbedtls_mpi* b ); -extern bool emv_rocacheck( char *modulus ); +extern bool emv_rocacheck( const unsigned char *buf, size_t buflen ); #endif From 8e5133582d98e3f37cd2e94d5585678f10d456e1 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 16:43:15 +0200 Subject: [PATCH 05/20] `emv roca` select app --- client/emv/cmdemv.c | 81 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 6 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 1029d5a7e..d3ec26c53 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1464,6 +1464,12 @@ int CmdEMVTest(const char *cmd) { } int CmdEMVRoca(const char *cmd) { + uint8_t AID[APDU_AID_LEN] = {0}; + size_t AIDlen = 0; + uint8_t buf[APDU_RES_LEN] = {0}; + size_t len = 0; + uint16_t sw = 0; + int res; CLIParserInit("emv roca", "Tries to extract public keys and run the ROCA test against them.\n", @@ -1481,16 +1487,71 @@ int CmdEMVRoca(const char *cmd) { if (arg_get_lit(1)) channel = ECC_CONTACT; + // select card + uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2; + + // init applets list tree + const char *al = "Applets list"; + struct tlvdb *tlvSelect = tlvdb_fixed(1, strlen(al), (const unsigned char *)al); + + // EMV PPSE + PrintAndLogEx(NORMAL, "--> PPSE."); + res = EMVSelectPSE(channel, true, true, psenum, buf, sizeof(buf), &len, &sw); + + if (!res && sw == 0x9000){ + struct tlvdb *fci = tlvdb_parse_multi(buf, len); + tlvdb_free(fci); + } + + SetAPDULogging(false); + res = EMVSearchPSE(channel, false, true, false, tlvSelect); + + // check PPSE and select application id + if (!res) { + TLVPrintAIDlistFromSelectTLV(tlvSelect); + } else { + // EMV SEARCH with AID list + PrintAndLogEx(NORMAL, "--> AID search."); + if (EMVSearch(channel, false, true, false, tlvSelect)) { + PrintAndLogEx(ERR, "Can't found any of EMV AID. Exit..."); + tlvdb_free(tlvSelect); + DropField(); + return 3; + } + + // check search and select application id + TLVPrintAIDlistFromSelectTLV(tlvSelect); + } + + // EMV SELECT application + SetAPDULogging(false); + EMVSelectApplication(tlvSelect, AID, &AIDlen); + + tlvdb_free(tlvSelect); + + if (!AIDlen) { + PrintAndLogEx(INFO, "Can't select AID. EMV AID not found. Exit..."); + DropField(); + return 4; + } + // Init TLV tree const char *alr = "Root terminal TLV tree"; struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr); - // select card - uint8_t buf[APDU_RES_LEN] = {0}; - size_t len = 0; - uint16_t sw = 0; - uint8_t psenum = (channel == ECC_CONTACT) ? 1: 2; - int res = EMVSelectPSE(channel, true, true, psenum, buf, sizeof(buf), &len, &sw); + // EMV SELECT applet + PrintAndLogEx(NORMAL, "\n-->Selecting AID:%s.", sprint_hex_inrow(AID, AIDlen)); + res = EMVSelect(channel, false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot); + + if (res) { + PrintAndLogEx(ERR, "Can't select AID (%d). Exit...", res); + tlvdb_free(tlvRoot); + DropField(); + return 5; + } + + + // getting certificates if (tlvdb_get(tlvRoot, 0x90, NULL)) { @@ -1530,8 +1591,16 @@ int CmdEMVRoca(const char *cmd) { sprint_hex(icc_pk->serial, 3) ); + // icc_pk->exp, icc_pk->elen // icc_pk->modulus, icc_pk->mlen + if (icc_pk->elen > 0 && icc_pk->mlen > 0) { + if (emv_rocacheck(icc_pk->modulus, icc_pk->mlen)) { + PrintAndLogEx(INFO, "ICC pk is vulnerable by roca."); + } else { + PrintAndLogEx(INFO, "ICC pk is OK("); + } + } PKISetStrictExecution(true); From b0c1828c1defffeca88b150abfed924fc5125929 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 16:58:11 +0200 Subject: [PATCH 06/20] load params --- client/emv/cmdemv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index d3ec26c53..c058c9913 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1550,6 +1550,8 @@ int CmdEMVRoca(const char *cmd) { return 5; } + PrintAndLog("\n* Init transaction parameters."); + InitTransactionParameters(tlvRoot, true, TT_QVSDCMCHIP, false); From 67b7edeb44756c332cd90f0caf185d2a942b7190 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 17:07:58 +0200 Subject: [PATCH 07/20] extract keys works --- client/emv/cmdemv.c | 75 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 4 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index c058c9913..7922bc616 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1553,8 +1553,74 @@ int CmdEMVRoca(const char *cmd) { PrintAndLog("\n* Init transaction parameters."); InitTransactionParameters(tlvRoot, true, TT_QVSDCMCHIP, false); - + PrintAndLogEx(NORMAL, "-->Calc PDOL."); + struct tlv *pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83); + if (!pdol_data_tlv){ + PrintAndLogEx(ERR, "Can't create PDOL TLV."); + tlvdb_free(tlvRoot); + DropField(); + return 6; + } + size_t pdol_data_tlv_data_len; + unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len); + if (!pdol_data_tlv_data) { + PrintAndLogEx(ERR, "Can't create PDOL data."); + tlvdb_free(tlvRoot); + DropField(); + return 6; + } + PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len)); + + PrintAndLogEx(INFO, "-->GPO."); + res = EMVGPO(channel, true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot); + + free(pdol_data_tlv_data); + free(pdol_data_tlv); + + if (res) { + PrintAndLogEx(ERR, "GPO error(%d): %4x. Exit...", res, sw); + tlvdb_free(tlvRoot); + DropField(); + return 7; + } + ProcessGPOResponseFormat1(tlvRoot, buf, len, false); + + PrintAndLogEx(INFO, "-->Read records from AFL."); + const struct tlv *AFL = tlvdb_get(tlvRoot, 0x94, NULL); + + while(AFL && AFL->len) { + if (AFL->len % 4) { + PrintAndLogEx(ERR, "Wrong AFL length: %d", AFL->len); + break; + } + + for (int i = 0; i < AFL->len / 4; i++) { + uint8_t SFI = AFL->value[i * 4 + 0] >> 3; + uint8_t SFIstart = AFL->value[i * 4 + 1]; + uint8_t SFIend = AFL->value[i * 4 + 2]; + uint8_t SFIoffline = AFL->value[i * 4 + 3]; + + PrintAndLogEx(INFO, "--->SFI[%02x] start:%02x end:%02x offline:%02x", SFI, SFIstart, SFIend, SFIoffline); + if (SFI == 0 || SFI == 31 || SFIstart == 0 || SFIstart > SFIend) { + PrintAndLogEx(ERR, "SFI ERROR! Skipped..."); + continue; + } + + for(int n = SFIstart; n <= SFIend; n++) { + PrintAndLogEx(INFO, "---->SFI[%02x] %d", SFI, n); + + res = EMVReadRecord(channel, true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot); + if (res) { + PrintAndLogEx(ERR, "SFI[%02x]. APDU error %4x", SFI, sw); + continue; + } + } + } + + break; + } + // getting certificates if (tlvdb_get(tlvRoot, 0x90, NULL)) { PrintAndLogEx(INFO, "-->Recovering certificates."); @@ -1593,9 +1659,10 @@ int CmdEMVRoca(const char *cmd) { sprint_hex(icc_pk->serial, 3) ); - -// icc_pk->exp, icc_pk->elen -// icc_pk->modulus, icc_pk->mlen + PrintAndLogEx(INFO, "ICC pk modulus: %s", sprint_hex_inrow(icc_pk->modulus, icc_pk->mlen)); + + // icc_pk->exp, icc_pk->elen + // icc_pk->modulus, icc_pk->mlen if (icc_pk->elen > 0 && icc_pk->mlen > 0) { if (emv_rocacheck(icc_pk->modulus, icc_pk->mlen)) { PrintAndLogEx(INFO, "ICC pk is vulnerable by roca."); From 625b696291d734c14d420bcd55e88ffe1c40e34c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 17:25:11 +0200 Subject: [PATCH 08/20] roca works --- client/emv/emv_roca.c | 85 +++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 43 deletions(-) diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index fe68b83ce..2aaa10875 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -22,35 +22,35 @@ static uint8_t g_primes[ROCA_PRINTS_LENGTH] = { 11, 13, 17, 19, 37, 53, 61, 71, 73, 79, 97, 103, 107, 109, 127, 151, 157 }; -mbedtls_mpi* g_prints[ROCA_PRINTS_LENGTH]; +mbedtls_mpi g_prints[ROCA_PRINTS_LENGTH]; void rocacheck_init(void) { - for (uint8_t i = 0; i < ROCA_PRINTS_LENGTH; i++) - mbedtls_mpi_init(g_prints[i]); + for (int i = 0; i < ROCA_PRINTS_LENGTH; i++) + mbedtls_mpi_init(&g_prints[i]); - mbedtls_mpi_read_string(g_prints[0], 10, "1026"); - mbedtls_mpi_read_string(g_prints[1], 10, "5658"); - mbedtls_mpi_read_string(g_prints[2], 10, "107286"); - mbedtls_mpi_read_string(g_prints[3], 10, "199410"); - mbedtls_mpi_read_string(g_prints[4], 10, "67109890"); - mbedtls_mpi_read_string(g_prints[5], 10, "5310023542746834"); - mbedtls_mpi_read_string(g_prints[6], 10, "1455791217086302986"); - mbedtls_mpi_read_string(g_prints[7], 10, "20052041432995567486"); - mbedtls_mpi_read_string(g_prints[8], 10, "6041388139249378920330"); - mbedtls_mpi_read_string(g_prints[9], 10, "207530445072488465666"); - mbedtls_mpi_read_string(g_prints[10], 10, "79228162521181866724264247298"); - mbedtls_mpi_read_string(g_prints[11], 10, "1760368345969468176824550810518"); - mbedtls_mpi_read_string(g_prints[12], 10, "50079290986288516948354744811034"); - mbedtls_mpi_read_string(g_prints[13], 10, "473022961816146413042658758988474"); - mbedtls_mpi_read_string(g_prints[14], 10, "144390480366845522447407333004847678774"); - mbedtls_mpi_read_string(g_prints[15], 10, "1800793591454480341970779146165214289059119882"); - mbedtls_mpi_read_string(g_prints[16], 10, "126304807362733370595828809000324029340048915994"); + mbedtls_mpi_read_string(&g_prints[0], 10, "1026"); + mbedtls_mpi_read_string(&g_prints[1], 10, "5658"); + mbedtls_mpi_read_string(&g_prints[2], 10, "107286"); + mbedtls_mpi_read_string(&g_prints[3], 10, "199410"); + mbedtls_mpi_read_string(&g_prints[4], 10, "67109890"); + mbedtls_mpi_read_string(&g_prints[5], 10, "5310023542746834"); + mbedtls_mpi_read_string(&g_prints[6], 10, "1455791217086302986"); + mbedtls_mpi_read_string(&g_prints[7], 10, "20052041432995567486"); + mbedtls_mpi_read_string(&g_prints[8], 10, "6041388139249378920330"); + mbedtls_mpi_read_string(&g_prints[9], 10, "207530445072488465666"); + mbedtls_mpi_read_string(&g_prints[10], 10, "79228162521181866724264247298"); + mbedtls_mpi_read_string(&g_prints[11], 10, "1760368345969468176824550810518"); + mbedtls_mpi_read_string(&g_prints[12], 10, "50079290986288516948354744811034"); + mbedtls_mpi_read_string(&g_prints[13], 10, "473022961816146413042658758988474"); + mbedtls_mpi_read_string(&g_prints[14], 10, "144390480366845522447407333004847678774"); + mbedtls_mpi_read_string(&g_prints[15], 10, "1800793591454480341970779146165214289059119882"); + mbedtls_mpi_read_string(&g_prints[16], 10, "126304807362733370595828809000324029340048915994"); } void rocacheck_cleanup(void) { - for (uint8_t i = 0; i < ROCA_PRINTS_LENGTH; i++) - mbedtls_mpi_free(g_prints[i]); + for (int i = 0; i < ROCA_PRINTS_LENGTH; i++) + mbedtls_mpi_free(&g_prints[i]); } int bitand_is_zero( mbedtls_mpi* a, mbedtls_mpi* b ) { @@ -75,50 +75,49 @@ mbedtls_mpi_uint mpi_get_uint(const mbedtls_mpi *X) { bool emv_rocacheck(const unsigned char *buf, size_t buflen) { - mbedtls_mpi *t_modulus = NULL; - mbedtls_mpi_init(t_modulus); + mbedtls_mpi t_modulus; + mbedtls_mpi_init(&t_modulus); bool ret = true; rocacheck_init(); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary(t_modulus, buf, buflen) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary(&t_modulus, buf, buflen) ); + mbedtls_mpi_init(&g_one); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(&g_one, 10, "1") ); for (int i = 0; i < ROCA_PRINTS_LENGTH; i++) { +printf("--p:%d\n", i); - mbedtls_mpi* t_temp = NULL; - mbedtls_mpi* t_prime = NULL; - mbedtls_mpi* g_one = NULL; + mbedtls_mpi t_temp; + mbedtls_mpi t_prime; + mbedtls_mpi g_one; - mbedtls_mpi_init(g_one); - mbedtls_mpi_init(t_temp); - mbedtls_mpi_init(t_prime); + mbedtls_mpi_init(&t_temp); + mbedtls_mpi_init(&t_prime); + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int(&t_prime, &t_prime, g_primes[i]) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(g_one, 10, "1") ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int(t_prime, t_prime, g_primes[i]) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi(&t_temp, &t_modulus, &t_prime) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi(t_temp, t_modulus, t_prime) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(&g_one, mpi_get_uint(&t_temp)) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(g_one, mpi_get_uint(t_temp)) ); - - if (bitand_is_zero(t_temp, g_prints[i])) { + if (bitand_is_zero(&t_temp, &g_prints[i])) { PrintAndLogEx(FAILED, "No fingerprint found\n"); ret = false; goto cleanup; } - mbedtls_mpi_free(g_one); - mbedtls_mpi_free(t_temp); - mbedtls_mpi_free(t_prime); + mbedtls_mpi_free(&g_one); + mbedtls_mpi_free(&t_temp); + mbedtls_mpi_free(&t_prime); } PrintAndLogEx(SUCCESS, "Fingerprint found!\n"); cleanup: - if (t_modulus) - mbedtls_mpi_free(t_modulus); + mbedtls_mpi_free(&t_modulus); rocacheck_cleanup(); return ret; From 6afda099db761b9793a126f3616e33ebad7db315 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 17:46:57 +0200 Subject: [PATCH 09/20] added test/ not works --- client/emv/cmdemv.c | 6 ++++++ client/emv/emv_roca.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 7922bc616..a42002c60 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1661,6 +1661,12 @@ int CmdEMVRoca(const char *cmd) { PrintAndLogEx(INFO, "ICC pk modulus: %s", sprint_hex_inrow(icc_pk->modulus, icc_pk->mlen)); + + uint8_t key[] = "944e13208a280c37efc31c3114485e590192adbb8e11c87cad60cdef0037ce99278330d3f471a2538fa667802ed2a3c44a8b7dea826e888d0aa341fd664f7fa7"; + if (emv_rocacheck(key, 64)) + PrintAndLogEx(INFO, "DEMO ICC pk is vulnerable by roca."); + + // icc_pk->exp, icc_pk->elen // icc_pk->modulus, icc_pk->mlen if (icc_pk->elen > 0 && icc_pk->mlen > 0) { diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index 2aaa10875..42bcce6db 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -84,6 +84,7 @@ bool emv_rocacheck(const unsigned char *buf, size_t buflen) { MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary(&t_modulus, buf, buflen) ); + mbedtls_mpi g_one; mbedtls_mpi_init(&g_one); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(&g_one, 10, "1") ); @@ -92,7 +93,6 @@ printf("--p:%d\n", i); mbedtls_mpi t_temp; mbedtls_mpi t_prime; - mbedtls_mpi g_one; mbedtls_mpi_init(&t_temp); mbedtls_mpi_init(&t_prime); From 18225c7c7f0b466b7d77f500975c3bbb2867926b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 17:48:52 +0200 Subject: [PATCH 10/20] some fix --- client/emv/cmdemv.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index a42002c60..c1ae8b1f3 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1662,7 +1662,10 @@ int CmdEMVRoca(const char *cmd) { PrintAndLogEx(INFO, "ICC pk modulus: %s", sprint_hex_inrow(icc_pk->modulus, icc_pk->mlen)); - uint8_t key[] = "944e13208a280c37efc31c3114485e590192adbb8e11c87cad60cdef0037ce99278330d3f471a2538fa667802ed2a3c44a8b7dea826e888d0aa341fd664f7fa7"; + uint8_t key[] = "\x94\x4e\x13\x20\x8a\x28\x0c\x37\xef\xc3\x1c\x31\x14\x48\x5e\x59"\ + "\x01\x92\xad\xbb\x8e\x11\xc8\x7c\xad\x60\xcd\xef\x00\x37\xce\x99"\ + "\x27\x83\x30\xd3\xf4\x71\xa2\x53\x8f\xa6\x67\x80\x2e\xd2\xa3\xc4"\ + "\x4a\x8b\x7d\xea\x82\x6e\x88\x8d\x0a\xa3\x41\xfd\x66\x4f\x7f\xa7"; if (emv_rocacheck(key, 64)) PrintAndLogEx(INFO, "DEMO ICC pk is vulnerable by roca."); From 404f23ddbd6ae3df7f8065999250d29f9af442be Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 17:50:51 +0200 Subject: [PATCH 11/20] small fix --- client/emv/cmdemv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index c1ae8b1f3..16e5c4765 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1674,7 +1674,7 @@ int CmdEMVRoca(const char *cmd) { // icc_pk->modulus, icc_pk->mlen if (icc_pk->elen > 0 && icc_pk->mlen > 0) { if (emv_rocacheck(icc_pk->modulus, icc_pk->mlen)) { - PrintAndLogEx(INFO, "ICC pk is vulnerable by roca."); + PrintAndLogEx(INFO, "ICC pk is a subject to ROCA vulnerability, insecure.."); } else { PrintAndLogEx(INFO, "ICC pk is OK("); } From 5eafc491ec91ccdf7b98ff33f2daa3cd6352b330 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 18:00:37 +0200 Subject: [PATCH 12/20] small add --- client/emv/cmdemv.c | 1 + client/emv/emv_roca.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 16e5c4765..adb47b136 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1666,6 +1666,7 @@ int CmdEMVRoca(const char *cmd) { "\x01\x92\xad\xbb\x8e\x11\xc8\x7c\xad\x60\xcd\xef\x00\x37\xce\x99"\ "\x27\x83\x30\xd3\xf4\x71\xa2\x53\x8f\xa6\x67\x80\x2e\xd2\xa3\xc4"\ "\x4a\x8b\x7d\xea\x82\x6e\x88\x8d\x0a\xa3\x41\xfd\x66\x4f\x7f\xa7"; + PrintAndLogEx(INFO, "DEMO ICC pk modulus: %s", sprint_hex_inrow(key, 64)); if (emv_rocacheck(key, 64)) PrintAndLogEx(INFO, "DEMO ICC pk is vulnerable by roca."); diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index 42bcce6db..88a7b21ad 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -69,7 +69,7 @@ mbedtls_mpi_uint mpi_get_uint(const mbedtls_mpi *X) { if (X->n == 1 && X->s > 0) { return X->p[0]; } - + printf("ZERRRRO!!!\n"); return 0; } @@ -89,7 +89,7 @@ bool emv_rocacheck(const unsigned char *buf, size_t buflen) { MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(&g_one, 10, "1") ); for (int i = 0; i < ROCA_PRINTS_LENGTH; i++) { -printf("--p:%d\n", i); +printf("--roca:%d\n", i); mbedtls_mpi t_temp; mbedtls_mpi t_prime; From f1cd108b1a432132c922fe62b6c9966f26fdec43 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 18:09:20 +0200 Subject: [PATCH 13/20] move g_one to cycle --- client/emv/emv_roca.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index 88a7b21ad..53fd91c15 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -84,18 +84,19 @@ bool emv_rocacheck(const unsigned char *buf, size_t buflen) { MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary(&t_modulus, buf, buflen) ); - mbedtls_mpi g_one; - mbedtls_mpi_init(&g_one); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(&g_one, 10, "1") ); for (int i = 0; i < ROCA_PRINTS_LENGTH; i++) { printf("--roca:%d\n", i); mbedtls_mpi t_temp; mbedtls_mpi t_prime; + mbedtls_mpi g_one; mbedtls_mpi_init(&t_temp); mbedtls_mpi_init(&t_prime); + mbedtls_mpi_init(&g_one); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(&g_one, 10, "1") ); MBEDTLS_MPI_CHK( mbedtls_mpi_add_int(&t_prime, &t_prime, g_primes[i]) ); From 05814fbe75bd9e77dbf589c3fdf0c8c287e6a0dc Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 19:06:51 +0200 Subject: [PATCH 14/20] added mpi print --- client/emv/emv_roca.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index 53fd91c15..ad39d1043 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -73,6 +73,15 @@ mbedtls_mpi_uint mpi_get_uint(const mbedtls_mpi *X) { return 0; } +void print_mpi(const char *msg, int radix, const mbedtls_mpi *X) { + + char Xchar[400] = {0}; + size_t len = 0; + + mbedtls_mpi_write_string(X, radix, Xchar, sizeof(Xchar), &len); + printf("%s[%d] %s\n", msg, len, Xchar); +} + bool emv_rocacheck(const unsigned char *buf, size_t buflen) { mbedtls_mpi t_modulus; @@ -83,6 +92,7 @@ bool emv_rocacheck(const unsigned char *buf, size_t buflen) { rocacheck_init(); MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary(&t_modulus, buf, buflen) ); + print_mpi("--t_modulus:", 16, &t_modulus); for (int i = 0; i < ROCA_PRINTS_LENGTH; i++) { From 44343d806fa74594ac3f4f4c930599a7be787511 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 19:25:19 +0200 Subject: [PATCH 15/20] add some debug --- client/emv/emv_roca.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index ad39d1043..9297ce452 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -109,11 +109,15 @@ printf("--roca:%d\n", i); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(&g_one, 10, "1") ); MBEDTLS_MPI_CHK( mbedtls_mpi_add_int(&t_prime, &t_prime, g_primes[i]) ); + print_mpi("--t_prime:", 10, &t_prime); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi(&t_temp, &t_modulus, &t_prime) ); + print_mpi("--t_temp:", 10, &t_temp); MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(&g_one, mpi_get_uint(&t_temp)) ); + print_mpi("--g_one:", 10, &g_one); + print_mpi("--g_prints:", 10, &g_prints[i]); if (bitand_is_zero(&t_temp, &g_prints[i])) { PrintAndLogEx(FAILED, "No fingerprint found\n"); ret = false; From e315328625d9cc632dc8223d0f46e398730cb9bc Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 20:06:18 +0200 Subject: [PATCH 16/20] works --- client/emv/emv_roca.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index 9297ce452..977584f73 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -92,11 +92,8 @@ bool emv_rocacheck(const unsigned char *buf, size_t buflen) { rocacheck_init(); MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary(&t_modulus, buf, buflen) ); - print_mpi("--t_modulus:", 16, &t_modulus); - for (int i = 0; i < ROCA_PRINTS_LENGTH; i++) { -printf("--roca:%d\n", i); mbedtls_mpi t_temp; mbedtls_mpi t_prime; @@ -109,17 +106,13 @@ printf("--roca:%d\n", i); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(&g_one, 10, "1") ); MBEDTLS_MPI_CHK( mbedtls_mpi_add_int(&t_prime, &t_prime, g_primes[i]) ); - print_mpi("--t_prime:", 10, &t_prime); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi(&t_temp, &t_modulus, &t_prime) ); - print_mpi("--t_temp:", 10, &t_temp); MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(&g_one, mpi_get_uint(&t_temp)) ); - print_mpi("--g_one:", 10, &g_one); - print_mpi("--g_prints:", 10, &g_prints[i]); - if (bitand_is_zero(&t_temp, &g_prints[i])) { - PrintAndLogEx(FAILED, "No fingerprint found\n"); + if (bitand_is_zero(&g_one, &g_prints[i])) { + PrintAndLogEx(FAILED, "No fingerprint found.\n"); ret = false; goto cleanup; } From 7401d51ebf256b723e10e3db875feafaefe01c5c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 20:33:24 +0200 Subject: [PATCH 17/20] roca works --- client/emv/cmdemv.c | 15 ++--------- client/emv/emv_roca.c | 58 +++++++++++++++++++++++++++++++++++++++---- client/emv/emv_roca.h | 7 ++---- 3 files changed, 57 insertions(+), 23 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index adb47b136..4cbbe2e0b 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1661,26 +1661,15 @@ int CmdEMVRoca(const char *cmd) { PrintAndLogEx(INFO, "ICC pk modulus: %s", sprint_hex_inrow(icc_pk->modulus, icc_pk->mlen)); - - uint8_t key[] = "\x94\x4e\x13\x20\x8a\x28\x0c\x37\xef\xc3\x1c\x31\x14\x48\x5e\x59"\ - "\x01\x92\xad\xbb\x8e\x11\xc8\x7c\xad\x60\xcd\xef\x00\x37\xce\x99"\ - "\x27\x83\x30\xd3\xf4\x71\xa2\x53\x8f\xa6\x67\x80\x2e\xd2\xa3\xc4"\ - "\x4a\x8b\x7d\xea\x82\x6e\x88\x8d\x0a\xa3\x41\xfd\x66\x4f\x7f\xa7"; - PrintAndLogEx(INFO, "DEMO ICC pk modulus: %s", sprint_hex_inrow(key, 64)); - if (emv_rocacheck(key, 64)) - PrintAndLogEx(INFO, "DEMO ICC pk is vulnerable by roca."); - - // icc_pk->exp, icc_pk->elen // icc_pk->modulus, icc_pk->mlen if (icc_pk->elen > 0 && icc_pk->mlen > 0) { - if (emv_rocacheck(icc_pk->modulus, icc_pk->mlen)) { + if (emv_rocacheck(icc_pk->modulus, icc_pk->mlen, true)) { PrintAndLogEx(INFO, "ICC pk is a subject to ROCA vulnerability, insecure.."); } else { PrintAndLogEx(INFO, "ICC pk is OK("); } - } - + } PKISetStrictExecution(true); } diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index 977584f73..5081ed446 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -82,12 +82,12 @@ void print_mpi(const char *msg, int radix, const mbedtls_mpi *X) { printf("%s[%d] %s\n", msg, len, Xchar); } -bool emv_rocacheck(const unsigned char *buf, size_t buflen) { +bool emv_rocacheck(const unsigned char *buf, size_t buflen, bool verbose) { mbedtls_mpi t_modulus; mbedtls_mpi_init(&t_modulus); - bool ret = true; + bool ret = false; rocacheck_init(); @@ -112,8 +112,8 @@ bool emv_rocacheck(const unsigned char *buf, size_t buflen) { MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(&g_one, mpi_get_uint(&t_temp)) ); if (bitand_is_zero(&g_one, &g_prints[i])) { - PrintAndLogEx(FAILED, "No fingerprint found.\n"); - ret = false; + if (verbose) + PrintAndLogEx(FAILED, "No fingerprint found.\n"); goto cleanup; } @@ -122,7 +122,9 @@ bool emv_rocacheck(const unsigned char *buf, size_t buflen) { mbedtls_mpi_free(&t_prime); } - PrintAndLogEx(SUCCESS, "Fingerprint found!\n"); + ret = true; + if (verbose) + PrintAndLogEx(SUCCESS, "Fingerprint found!\n"); cleanup: mbedtls_mpi_free(&t_modulus); @@ -130,3 +132,49 @@ cleanup: rocacheck_cleanup(); return ret; } + +int roca_self_test( int verbose ) { + int ret = 0; + + if( verbose != 0 ) + printf( "\nROCA check vulnerability tests\n" ); + + // positive + uint8_t keyp[] = "\x94\x4e\x13\x20\x8a\x28\x0c\x37\xef\xc3\x1c\x31\x14\x48\x5e\x59"\ + "\x01\x92\xad\xbb\x8e\x11\xc8\x7c\xad\x60\xcd\xef\x00\x37\xce\x99"\ + "\x27\x83\x30\xd3\xf4\x71\xa2\x53\x8f\xa6\x67\x80\x2e\xd2\xa3\xc4"\ + "\x4a\x8b\x7d\xea\x82\x6e\x88\x8d\x0a\xa3\x41\xfd\x66\x4f\x7f\xa7"; + + if( verbose != 0 ) + printf( " ROCA positive test: " ); + + if (emv_rocacheck(keyp, 64, false)) { + if( verbose != 0 ) + printf( "passed\n" ); + } else { + ret = 1; + if( verbose != 0 ) + printf( "failed\n" ); + } + + // negative + uint8_t keyn[] = "\x84\x4e\x13\x20\x8a\x28\x0c\x37\xef\xc3\x1c\x31\x14\x48\x5e\x59"\ + "\x01\x92\xad\xbb\x8e\x11\xc8\x7c\xad\x60\xcd\xef\x00\x37\xce\x99"\ + "\x27\x83\x30\xd3\xf4\x71\xa2\x53\x8f\xa6\x67\x80\x2e\xd2\xa3\xc4"\ + "\x4a\x8b\x7d\xea\x82\x6e\x88\x8d\x0a\xa3\x41\xfd\x66\x4f\x7f\xa7"; + + if( verbose != 0 ) + printf( " ROCA negative test: " ); + + if (emv_rocacheck(keyn, 64, false)) { + ret = 1; + if( verbose != 0 ) + printf( "failed\n" ); + } else { + if( verbose != 0 ) + printf( "passed\n" ); + } + + + return ret; +} diff --git a/client/emv/emv_roca.h b/client/emv/emv_roca.h index a42d8349e..a9559ef79 100644 --- a/client/emv/emv_roca.h +++ b/client/emv/emv_roca.h @@ -31,11 +31,8 @@ #define ROCA_PRINTS_LENGTH 17 -void rocacheck_init(void); -void rocacheck_cleanup(void); -int bitand_is_zero( mbedtls_mpi* a, mbedtls_mpi* b ); - -extern bool emv_rocacheck( const unsigned char *buf, size_t buflen ); +extern bool emv_rocacheck( const unsigned char *buf, size_t buflen, bool verbose ); +extern int roca_self_test( int verbose ); #endif From 376ead028a07aa4ff4b4818259d762fb7f6438c9 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 20:33:38 +0200 Subject: [PATCH 18/20] added tests --- client/emv/test/cryptotest.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/emv/test/cryptotest.c b/client/emv/test/cryptotest.c index 1d5891fe0..b0212a70b 100644 --- a/client/emv/test/cryptotest.c +++ b/client/emv/test/cryptotest.c @@ -31,6 +31,7 @@ #include "dda_test.h" #include "cda_test.h" #include "crypto/libpcrypto.h" +#include "emv/emv_roca.h" int ExecuteCryptoTests(bool verbose) { int res; @@ -90,6 +91,9 @@ int ExecuteCryptoTests(bool verbose) { res = exec_crypto_test(verbose); if (res) TestFail = true; + res = roca_self_test(verbose); + if (res) TestFail = true; + PrintAndLog("\n--------------------------"); if (TestFail) PrintAndLog("Test(s) [ERROR]."); From 392687499591d30437af625d203d8fa90e0dff20 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 20:48:45 +0200 Subject: [PATCH 19/20] fix pse channels --- client/emv/cmdemv.c | 18 +++++++----------- client/emv/emvcore.c | 4 ++-- client/emv/emvcore.h | 2 +- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 4cbbe2e0b..a443f6aad 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -722,6 +722,7 @@ int CmdEMVExec(const char *cmd) { EMVCommandChannel channel = ECC_CONTACTLESS; if (arg_get_lit(11)) channel = ECC_CONTACT; + uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2; CLIParserFree(); SetAPDULogging(showAPDU); @@ -736,7 +737,7 @@ int CmdEMVExec(const char *cmd) { // PPSE PrintAndLogEx(NORMAL, "\n* PPSE."); SetAPDULogging(showAPDU); - res = EMVSearchPSE(channel, activateField, true, decodeTLV, tlvSelect); + res = EMVSearchPSE(channel, activateField, true, psenum, decodeTLV, tlvSelect); // check PPSE and select application id if (!res) { @@ -1170,6 +1171,7 @@ int CmdEMVScan(const char *cmd) { EMVCommandChannel channel = ECC_CONTACTLESS; if (arg_get_lit(11)) channel = ECC_CONTACT; + uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2; uint8_t relfname[250] ={0}; char *crelfname = (char *)relfname; int relfnamelen = 0; @@ -1248,7 +1250,7 @@ int CmdEMVScan(const char *cmd) { tlvdb_free(fci); } - res = EMVSearchPSE(channel, false, true, decodeTLV, tlvSelect); + res = EMVSearchPSE(channel, false, true, psenum, decodeTLV, tlvSelect); // check PPSE and select application id if (!res) { @@ -1490,21 +1492,15 @@ int CmdEMVRoca(const char *cmd) { // select card uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2; + SetAPDULogging(false); + // init applets list tree const char *al = "Applets list"; struct tlvdb *tlvSelect = tlvdb_fixed(1, strlen(al), (const unsigned char *)al); // EMV PPSE PrintAndLogEx(NORMAL, "--> PPSE."); - res = EMVSelectPSE(channel, true, true, psenum, buf, sizeof(buf), &len, &sw); - - if (!res && sw == 0x9000){ - struct tlvdb *fci = tlvdb_parse_multi(buf, len); - tlvdb_free(fci); - } - - SetAPDULogging(false); - res = EMVSearchPSE(channel, false, true, false, tlvSelect); + res = EMVSearchPSE(channel, false, true, psenum, false, tlvSelect); // check PPSE and select application id if (!res) { diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index b67e7ac76..b582792ac 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -332,14 +332,14 @@ int EMVSelectPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO return res; } -int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv) { +int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, bool decodeTLV, struct tlvdb *tlv) { uint8_t data[APDU_RES_LEN] = {0}; size_t datalen = 0; uint16_t sw = 0; int res; // select PPSE - res = EMVSelectPSE(channel, ActivateField, true, 2, data, sizeof(data), &datalen, &sw); + res = EMVSelectPSE(channel, ActivateField, true, PSENum, data, sizeof(data), &datalen, &sw); if (!res){ struct tlvdb *t = NULL; diff --git a/client/emv/emvcore.h b/client/emv/emvcore.h index 829107126..7d53e83bb 100644 --- a/client/emv/emvcore.h +++ b/client/emv/emvcore.h @@ -79,7 +79,7 @@ extern void SetAPDULogging(bool logging); extern int EMVExchange(EMVCommandChannel channel, bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); // search application -extern int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv); +extern int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, bool decodeTLV, struct tlvdb *tlv); extern int EMVSearch(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv); extern int EMVSelectPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); extern int EMVSelect(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); From 690a8e604aee614ab6e6ee1b159af9d587f41d38 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 29 Dec 2018 00:31:10 +0200 Subject: [PATCH 20/20] updated licanse according to changes https://gist.github.com/robstradling/f525d423c79690b72e650e2ad38a161d#file-roca-c-L138 --- client/emv/emv_roca.c | 9 +++++++-- client/emv/emv_roca.h | 38 +++++++++++++++++++------------------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index 5081ed446..a6738ae2f 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -1,10 +1,12 @@ /* roca.c - ROCA (CVE-2017-15361) fingerprint checker. * Written by Rob Stradling (based on https://github.com/crocs-muni/roca/blob/master/roca/detect.py) - * Copyright (C) 2017 COMODO CA Limited + * Copyright (C) 2017-2018 Sectigo Limited + * modified 2018 iceman (dropped openssl bignum, now use mbedtls lib) + * modified 2018 merlok * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or + * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, @@ -15,6 +17,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +//----------------------------------------------------------------------------- +// EMV roca commands +//----------------------------------------------------------------------------- #include "emv_roca.h" diff --git a/client/emv/emv_roca.h b/client/emv/emv_roca.h index a9559ef79..26d37d146 100644 --- a/client/emv/emv_roca.h +++ b/client/emv/emv_roca.h @@ -1,22 +1,22 @@ - -// ROCA (CVE-2017-15361) fingerprint checker. -// Written by Rob Stradling (based on https://github.com/crocs-muni/roca/blob/master/roca/detect.py) -// Copyright (C) 2017 COMODO CA Limited -// modified 2018 iceman (dropped openssl bignum, now use mbedtls lib) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// +/* roca.c - ROCA (CVE-2017-15361) fingerprint checker. + * Written by Rob Stradling (based on https://github.com/crocs-muni/roca/blob/master/roca/detect.py) + * Copyright (C) 2017-2018 Sectigo Limited + * modified 2018 iceman (dropped openssl bignum, now use mbedtls lib) + * modified 2018 merlok + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ //----------------------------------------------------------------------------- // EMV roca commands //-----------------------------------------------------------------------------