]> git.zerfleddert.de Git - proxmark3-svn/blobdiff - client/cmdhfepa.c
Allow clean Legic simulation exit without button press (#668)
[proxmark3-svn] / client / cmdhfepa.c
index c6db746c6ed52945af83698af3a5eb6cd2ee5a45..76664bf59616468ba55c832dae8da24e6ba5e2e6 100644 (file)
@@ -8,16 +8,20 @@
 // Commands related to the German electronic Identification Card
 //-----------------------------------------------------------------------------
 
 // Commands related to the German electronic Identification Card
 //-----------------------------------------------------------------------------
 
+#include "cmdhfepa.h"
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
 #include "util.h"
 #include "util.h"
-#include "proxusb.h"
-#include "proxmark3.h"
+#include "util_posix.h"
+#include "comms.h"
 #include "ui.h"
 #include "cmdparser.h"
 #include "common.h"
 #include "cmdmain.h"
 #include "ui.h"
 #include "cmdparser.h"
 #include "common.h"
 #include "cmdmain.h"
-#include "sleep.h"
-
-#include "cmdhfepa.h"
 
 static int CmdHelp(const char *Cmd);
 
 
 static int CmdHelp(const char *Cmd);
 
@@ -25,28 +29,28 @@ static int CmdHelp(const char *Cmd);
 int CmdHFEPACollectPACENonces(const char *Cmd)
 {
        // requested nonce size
 int CmdHFEPACollectPACENonces(const char *Cmd)
 {
        // requested nonce size
-       uint8_t m = 0;
+       unsigned int m = 0;
        // requested number of Nonces
        unsigned int n = 0;
        // delay between requests
        unsigned int d = 0;
        // requested number of Nonces
        unsigned int n = 0;
        // delay between requests
        unsigned int d = 0;
-       
-       sscanf(Cmd, "%hhu %u %u", &m, &n, &d);
-       
+
+       sscanf(Cmd, "%u %u %u", &m, &n, &d);
+
        // values are expected to be > 0
        m = m > 0 ? m : 1;
        n = n > 0 ? n : 1;
 
        // values are expected to be > 0
        m = m > 0 ? m : 1;
        n = n > 0 ? n : 1;
 
-       PrintAndLog("Collecting %u %hhu-byte nonces", n, m);
-       PrintAndLog("Start: %u", time(NULL));
+       PrintAndLog("Collecting %u %u-byte nonces", n, m);
+       PrintAndLog("Start: %" PRIu64 , msclock()/1000);
        // repeat n times
        for (unsigned int i = 0; i < n; i++) {
                // execute PACE
                UsbCommand c = {CMD_EPA_PACE_COLLECT_NONCE, {(int)m, 0, 0}};
                SendCommand(&c);
                UsbCommand resp;
        // repeat n times
        for (unsigned int i = 0; i < n; i++) {
                // execute PACE
                UsbCommand c = {CMD_EPA_PACE_COLLECT_NONCE, {(int)m, 0, 0}};
                SendCommand(&c);
                UsbCommand resp;
-    
-    WaitForResponse(CMD_ACK,&resp);
+
+               WaitForResponse(CMD_ACK,&resp);
 
                // check if command failed
                if (resp.arg[0] != 0) {
 
                // check if command failed
                if (resp.arg[0] != 0) {
@@ -55,27 +59,138 @@ int CmdHFEPACollectPACENonces(const char *Cmd)
                        size_t nonce_length = resp.arg[1];
                        char *nonce = (char *) malloc(2 * nonce_length + 1);
                        for(int j = 0; j < nonce_length; j++) {
                        size_t nonce_length = resp.arg[1];
                        char *nonce = (char *) malloc(2 * nonce_length + 1);
                        for(int j = 0; j < nonce_length; j++) {
-                               snprintf(nonce + (2 * j), 3, "%02X", resp.d.asBytes[j]);
+                               sprintf(nonce + (2 * j), "%02X", resp.d.asBytes[j]);
                        }
                        // print nonce
                        }
                        // print nonce
-                       PrintAndLog("Length: %d, Nonce: %s",resp.arg[1], nonce);
+                       PrintAndLog("Length: %d, Nonce: %s", nonce_length, nonce);
+                       free(nonce);
                }
                if (i < n - 1) {
                        sleep(d);
                }
        }
                }
                if (i < n - 1) {
                        sleep(d);
                }
        }
-       PrintAndLog("End: %u", time(NULL));
+       PrintAndLog("End: %" PRIu64, msclock()/1000);
+
+       return 1;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////The commands lie below here/////////////////////////////////////////////////////////////////////////////////////////
+
+// perform the PACE protocol by replaying APDUs
+int CmdHFEPAPACEReplay(const char *Cmd)
+{
+       // the 4 APDUs which are replayed + their lengths
+       uint8_t msesa_apdu[41], gn_apdu[8], map_apdu[75];
+       uint8_t pka_apdu[75], ma_apdu[18], apdu_lengths[5] = {0};
+       // pointers to the arrays to be able to iterate
+       uint8_t *apdus[] = {msesa_apdu, gn_apdu, map_apdu, pka_apdu, ma_apdu};
+
+       // usage message
+       static const char *usage_msg =
+               "Please specify 5 APDUs separated by spaces. "
+               "Example:\n preplay 0022C1A4 1068000000 1086000002 1234ABCDEF 1A2B3C4D";
+
+       // Proxmark response
+       UsbCommand resp;
+
+       int skip = 0, skip_add = 0, scan_return = 0;
+       // for each APDU
+       for (int i = 0; i < sizeof(apdu_lengths); i++) {
+               // scan to next space or end of string
+               while (Cmd[skip] != ' ' && Cmd[skip] != '\0') {
+                       // convert
+                       scan_return = sscanf(Cmd + skip, "%2X%n",
+                                            (unsigned int *) (apdus[i] + apdu_lengths[i]),
+                                            &skip_add);
+                       if (scan_return < 1) {
+                               PrintAndLog((char *)usage_msg);
+                               PrintAndLog("Not enough APDUs! Try again!");
+                               return 0;
+                       }
+                       skip += skip_add;
+            apdu_lengths[i]++;
+               }
+
+               // break on EOF
+               if (Cmd[skip] == '\0') {
+                       if (i < sizeof(apdu_lengths) - 1) {
+
+                               PrintAndLog((char *)usage_msg);
+                               return 0;
+                       }
+                       break;
+               }
+               // skip the space
+               skip++;
+       }
+
+       // transfer the APDUs to the Proxmark
+       UsbCommand usb_cmd;
+       usb_cmd.cmd = CMD_EPA_PACE_REPLAY;
+       for (int i = 0; i < sizeof(apdu_lengths); i++) {
+               // APDU number
+               usb_cmd.arg[0] = i + 1;
+               // transfer the APDU in several parts if necessary
+               for (int j = 0; j * sizeof(usb_cmd.d.asBytes) < apdu_lengths[i]; j++) {
+                       // offset into the APDU
+                       usb_cmd.arg[1] = j * sizeof(usb_cmd.d.asBytes);
+                       // amount of data in this packet
+                       int packet_length = apdu_lengths[i] - (j * sizeof(usb_cmd.d.asBytes));
+                       if (packet_length > sizeof(usb_cmd.d.asBytes)) {
+                               packet_length = sizeof(usb_cmd.d.asBytes);
+                       }
+                       usb_cmd.arg[2] = packet_length;
+
+                       memcpy(usb_cmd.d.asBytes, // + (j * sizeof(usb_cmd.d.asBytes)),
+                              apdus[i] + (j * sizeof(usb_cmd.d.asBytes)),
+                              packet_length);
+                       SendCommand(&usb_cmd);
+                       WaitForResponse(CMD_ACK, &resp);
+                       if (resp.arg[0] != 0) {
+                               PrintAndLog("Transfer of APDU #%d Part %d failed!", i, j);
+                               return 0;
+                       }
+               }
+       }
+
+       // now perform the replay
+       usb_cmd.arg[0] = 0;
+       SendCommand(&usb_cmd);
+       WaitForResponse(CMD_ACK, &resp);
+       if (resp.arg[0] != 0) {
+               PrintAndLog("\nPACE replay failed in step %u!", (uint32_t)resp.arg[0]);
+               PrintAndLog("Measured times:");
+               PrintAndLog("MSE Set AT: %u us", resp.d.asDwords[0]);
+               PrintAndLog("GA Get Nonce: %u us", resp.d.asDwords[1]);
+               PrintAndLog("GA Map Nonce: %u us", resp.d.asDwords[2]);
+               PrintAndLog("GA Perform Key Agreement: %u us", resp.d.asDwords[3]);
+               PrintAndLog("GA Mutual Authenticate: %u us", resp.d.asDwords[4]);
+       } else {
+               PrintAndLog("PACE replay successfull!");
+               PrintAndLog("MSE Set AT: %u us", resp.d.asDwords[0]);
+               PrintAndLog("GA Get Nonce: %u us", resp.d.asDwords[1]);
+               PrintAndLog("GA Map Nonce: %u us", resp.d.asDwords[2]);
+               PrintAndLog("GA Perform Key Agreement: %u us", resp.d.asDwords[3]);
+               PrintAndLog("GA Mutual Authenticate: %u us", resp.d.asDwords[4]);
+       }
+
 
        return 1;
 }
 
 
        return 1;
 }
 
+////////////////////////////////The new commands lie above here/////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
 // UI-related stuff
 
 // UI-related stuff
 
-static const command_t CommandTable[] = 
+static const command_t CommandTable[] =
 {
   {"help",    CmdHelp,                   1, "This help"},
   {"cnonces", CmdHFEPACollectPACENonces, 0,
               "<m> <n> <d> Acquire n>0 encrypted PACE nonces of size m>0 with d sec pauses"},
 {
   {"help",    CmdHelp,                   1, "This help"},
   {"cnonces", CmdHFEPACollectPACENonces, 0,
               "<m> <n> <d> Acquire n>0 encrypted PACE nonces of size m>0 with d sec pauses"},
+  {"preplay", CmdHFEPAPACEReplay,        0,
+   "<mse> <get> <map> <pka> <ma> Perform PACE protocol by replaying given APDUs"},
   {NULL, NULL, 0, NULL}
 };
 
   {NULL, NULL, 0, NULL}
 };
 
@@ -87,10 +202,7 @@ int CmdHelp(const char *Cmd)
 
 int CmdHFEPA(const char *Cmd)
 {
 
 int CmdHFEPA(const char *Cmd)
 {
-       // flush
-       while (!WaitForResponseTimeout(CMD_ACK,NULL,500));
-
-       // parse
-  CmdsParse(CommandTable, Cmd);
-  return 0;
-}
\ No newline at end of file
+       (void)WaitForResponseTimeout(CMD_ACK,NULL,100);
+       CmdsParse(CommandTable, Cmd);
+       return 0;
+}
Impressum, Datenschutz