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
//-----------------------------------------------------------------------------