diff options
Diffstat (limited to 'src/mrtdreader.c')
-rw-r--r-- | src/mrtdreader.c | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/src/mrtdreader.c b/src/mrtdreader.c new file mode 100644 index 0000000..d19944f --- /dev/null +++ b/src/mrtdreader.c @@ -0,0 +1,298 @@ +/* + * mrtdreader.c - Main program + * + * Copyright (C) 2014 Ruben Undheim <ruben.undheim@gmail.com> + * + * 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 <http://www.gnu.org/licenses/>. + * + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <unistd.h> +#include <time.h> +#include <nfc/nfc.h> +#include <signal.h> +#include "mrtd.h" + +#define MAX_DEVICE_COUNT 5 + +static nfc_context *context = NULL; +static nfc_device *pnd = NULL; + +static char *pn = NULL; +static char *dob = NULL; +static char *eov = NULL; +static char *extra_argument = NULL; + +static char done = 0; + +static void closedown(int sig) +{ + done = 1; + printf("Stopping...\n"); +} +static void forcestop(int sig) +{ + done = 1; + printf("Stopping...\n"); + if(pnd != NULL) + nfc_close(pnd); + if(context != NULL) + nfc_exit(context); + exit(-1); +} + +void printhex(char *description, uint8_t *input, int length) +{ + int i; + printf("%s: ",description); + for(i=0;i<length;i++){ + printf("%02x",input[i]); + } + printf("\n"); +} + +int parse_cmdline(int argc, char **argv) +{ + int s; + opterr = 0; + while((s = getopt(argc, argv, "p:b:e:")) != -1) { + switch (s) { + case 'p': + pn = malloc(strlen(optarg)+1); + memcpy(pn,optarg,strlen(optarg)); + break; + case 'b': + dob = malloc(strlen(optarg)+1); + memcpy(dob,optarg,strlen(optarg)); + break; + case 'e': + eov = malloc(strlen(optarg)+1); + memcpy(eov,optarg,strlen(optarg)); + break; + case '?': + if(optopt == 'p') + fprintf(stderr, "Option -%c requires an argument.\n",optopt); + else if(optopt == 'b') + fprintf(stderr, "Option -%c requires an argument.\n",optopt); + else if(optopt == 'e') + fprintf(stderr, "Option -%c requires an argument.\n",optopt); + else if(isprint(optopt)) + fprintf(stderr, "Unknown option '-%c'.\n",optopt); + return -1; + default: + abort(); + } + } + + if(argc == (optind + 1)){ + extra_argument = argv[optind]; + } + if((extra_argument == NULL) && ((pn == NULL) || (dob == NULL) || (eov == NULL))){ + return -1; + } + + return 0; +} + +int main(int argc, char **argv) +{ + int i,ret,res; + if(parse_cmdline(argc,argv) == -1){ + fprintf(stderr,"Usage: %s [options] <MRZ>\n",argv[0]); + goto failed; + } + uint8_t *kmrz; + uint8_t buffer[25]; + int inlength; + if(extra_argument != NULL){ + inlength = strlen(extra_argument); + if(inlength == 24){ + kmrz = extra_argument; + } + else if(inlength == 44){ + mrtd_bac_get_kmrz_from_mrz(extra_argument, buffer); + kmrz = buffer; + } + else{ + fprintf(stderr,"Did not recognize <MRZ>\n"); + goto failed; + } + } + else { + mrtd_bac_get_kmrz(pn, dob, eov, buffer); + kmrz = buffer; + } + if(pn != NULL) { + free(pn); + pn = NULL; + } + if(dob != NULL){ + free(dob); + dob = NULL; + } + if(eov != NULL){ + free(eov); + eov = NULL; + } + + + signal(SIGINT, forcestop); + srand(time(NULL)); + + nfc_init(&context); + nfc_target ant; + + if(context == NULL){ + fprintf(stderr,"Unable to init libnfc (malloc)\n"); + goto failed; + } + nfc_connstring connstrings[MAX_DEVICE_COUNT]; + size_t szDeviceFound = nfc_list_devices(context,connstrings,MAX_DEVICE_COUNT); + + if(szDeviceFound == 0){ + fprintf(stderr,"No NFC device found.\n"); + goto failed; + } + + pnd = nfc_open(context, connstrings[0]); + if(pnd == NULL){ + fprintf(stderr,"Unable to open NFC device: %s\n",connstrings[0]); + goto failed; + } + if(nfc_initiator_init(pnd) < 0){ + nfc_perror(pnd,"nfc_initiator_init"); + goto failed; + } + + printf("NFC device: %s opened\n",nfc_device_get_name(pnd)); + + if (nfc_device_set_property_bool(pnd, NP_INFINITE_SELECT, false) < 0){ + fprintf(stderr, "error setting property\n"); + goto failed; + } + + nfc_modulation nmA,nmB; + nmA.nmt = NMT_ISO14443A; + nmA.nbr = NBR_106; + nmB.nmt = NMT_ISO14443B; + nmB.nbr = NBR_106; + + signal(SIGINT, closedown); + while(1){ + ret = nfc_initiator_select_passive_target(pnd,nmA,NULL,0,&ant); + if(ret > 0 || done) break; + ret = nfc_initiator_select_passive_target(pnd,nmB,NULL,0,&ant); + if(ret > 0 || done) break; + } + if(done) + goto failed; + printf("Target found!\n"); + signal(SIGINT, forcestop); + + uint8_t txbuffer[300]; + int txlen; + uint8_t rxbuffer[300]; + int rxlen; + + uint64_t ssc_long; + uint8_t ksenc[16]; + uint8_t ksmac[16]; + + mrtd_bac_randomize_rndifd_kifd(); + ret = mrtd_bac_keyhandshake(pnd,kmrz,ksenc,ksmac,&ssc_long); + + if(ret == RET_CHALLENGE_FAILED){ + fprintf(stderr,"======================\nChallenge failed...\n======================\n"); + goto failed; + } + else if(ret < 0){ + goto failed; + } + printf("======================\nChallenge successful!\n======================\n"); + + printf("\n"); + uint8_t *filecontent = NULL; + filecontent = malloc(50000); + int filecontentlength; + + + printf("Getting EF.COM..."); + fflush(stdout); + mrtd_fileread_read(pnd,"\x01\x1e",filecontent,&filecontentlength,ksenc,ksmac,&ssc_long); + printf(" done\n"); + + printhex("File content",filecontent,filecontentlength); + printf("File size: %d\n",filecontentlength); + + uint8_t datagroups[20]; + int ndatagroups; + mrtd_fileread_decode_ef_com(filecontent,filecontentlength,datagroups,&ndatagroups); + + printf("\n"); + + printf("Getting EF.SOD..."); + fflush(stdout); + mrtd_fileread_read(pnd,"\x01\x1d",filecontent,&filecontentlength,ksenc,ksmac,&ssc_long); + printf(" done\n"); + + printhex("File content",filecontent,filecontentlength); + printf("File size: %d\n",filecontentlength); + + printf("\n"); + + printf("Getting EF.DG1..."); + fflush(stdout); + mrtd_fileread_read(pnd,"\x01\x01",filecontent,&filecontentlength,ksenc,ksmac,&ssc_long); + printf(" done\n"); + + filecontent[filecontentlength] = 0; + printf("%s\n\n",filecontent); + printf("File size: %d\n",filecontentlength); + + printf("\n"); + printf("Getting EF.DG2 which contains the image..."); + fflush(stdout); + mrtd_fileread_read(pnd,"\x01\x02",filecontent,&filecontentlength,ksenc,ksmac,&ssc_long); + printf(" done\n"); + + + mrtd_fileread_write_image_to_file(filecontent, filecontentlength, "image"); + + nfc_close(pnd); + nfc_exit(context); + if(filecontent != NULL) + free(filecontent); + return 0; + + failed: + if(pnd != NULL) + nfc_close(pnd); + if(context != NULL) + nfc_exit(context); + if(pn != NULL) + free(pn); + if(dob != NULL) + free(dob); + if(eov != NULL) + free(eov); + if(filecontent != NULL) + free(filecontent); + return -1; +} + |