/* SIM test application */ /* (C) 2010 by Harald Welte * * All Rights Reserved * * 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, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define DEBUG /* Dump bytes in hex on the console */ static void myHexdump(uint8_t *data, int len) { int i; for(i=0;i> 8); if(calypso_sim_transceive(SIM_CLASS, SIM_SELECT, 0x00, 0x00, 0x02, txBuffer, status_word, SIM_APDU_PUT) != 0) return 0xFFFF; return (status_word[0] << 8) | status_word[1]; } /* Get the status of the currently selected file */ uint16_t sim_status(void) { uint8_t status_word[2]; if(calypso_sim_transceive(SIM_CLASS, SIM_STATUS, 0x00, 0x00, 0x00, 0, status_word, SIM_APDU_PUT) != 0) return 0xFFFF; return (status_word[0] << 8) | status_word[1]; } /* Read file in binary mode */ uint16_t sim_readbinary(uint8_t offset_high, uint8_t offset_low, uint8_t length, uint8_t *data) { uint8_t status_word[2]; if(calypso_sim_transceive(SIM_CLASS, SIM_READ_BINARY, offset_high, offset_low, length, data ,status_word, SIM_APDU_GET) != 0) return 0xFFFF; return (status_word[0] << 8) | status_word[1]; } uint16_t sim_verify(char *pin) { uint8_t txBuffer[8]; uint8_t status_word[2]; memset(txBuffer, 0xFF, 8); memcpy(txBuffer, pin, strlen(pin)); if(calypso_sim_transceive(SIM_CLASS, SIM_VERIFY_CHV, 0x00, 0x01, 0x08, txBuffer,status_word, SIM_APDU_PUT) != 0) return 0xFFFF; return (status_word[0] << 8) | status_word[1]; } uint16_t sim_run_gsm_algorith(uint8_t *data) { uint8_t status_word[2]; if(calypso_sim_transceive(SIM_CLASS, SIM_RUN_GSM_ALGORITHM, 0x00, 0x00, 0x10, data, status_word, SIM_APDU_PUT) != 0) return 0xFFFF; printf(" ==> Status word: %x\n", (status_word[0] << 8) | status_word[1]); if(status_word[0] != 0x9F || status_word[1] != 0x0C) return (status_word[0] << 8) | status_word[1]; /* GET RESPONSE */ if(calypso_sim_transceive(SIM_CLASS, SIM_GET_RESPONSE, 0, 0, 0x0C, data ,status_word, SIM_APDU_GET) != 0) return 0xFFFF; return (status_word[0] << 8) | status_word[1]; } /* FIXME: We need proper calibrated delay loops at some point! */ void delay_us(unsigned int us) { volatile unsigned int i; for (i= 0; i < us*4; i++) { i; } } void delay_ms(unsigned int ms) { volatile unsigned int i; for (i= 0; i < ms*1300; i++) { i; } } /* Execute my (dexter's) personal test */ void do_sim_test(void) { uint8_t testBuffer[20]; uint8_t testtxBuffer[20]; uint8_t testDataBody[257]; uint8_t testStatusWord[2]; int recivedChars; int i; uint8_t atr[20]; uint8_t atrLength = 0; memset(atr,0,sizeof(atr)); uint8_t buffer[20]; memset(testtxBuffer,0,sizeof(testtxBuffer)); puts("----------------SIMTEST----8<-----------------\n"); /* Initialize Sim-Controller driver */ puts("Initializing driver:\n"); calypso_sim_init(NULL); /* Power up sim and display ATR */ puts("Power up simcard:\n"); memset(atr,0,sizeof(atr)); atrLength = calypso_sim_powerup(atr); myHexdump(atr,atrLength); /* Reset sim and display ATR */ puts("Reset simcard:\n"); memset(atr,0,sizeof(atr)); atrLength = calypso_sim_reset(atr); myHexdump(atr,atrLength); testDataBody[0] = 0x3F; testDataBody[1] = 0x00; calypso_sim_transceive(0xA0, 0xA4, 0x00, 0x00, 0x02, testDataBody,0, SIM_APDU_PUT); calypso_sim_transceive(0xA0, 0xC0, 0x00, 0x00, 0x0f, testDataBody,0, SIM_APDU_GET); myHexdump(testDataBody,0x0F); puts("Test Phase 1: Testing bare sim commands...\n"); puts(" * Testing SELECT: Selecting MF\n"); printf(" ==> Status word: %x\n", sim_select(SIM_MF)); puts(" * Testing SELECT: Selecting DF_GSM\n"); printf(" ==> Status word: %x\n", sim_select(SIM_DF_GSM)); puts(" * Testing PIN VERIFY\n"); printf(" ==> Status word: %x\n", sim_verify("1234")); puts(" * Testing SELECT: Selecting EF_IMSI\n"); printf(" ==> Status word: %x\n", sim_select(SIM_EF_IMSI)); puts(" * Testing STATUS:\n"); printf(" ==> Status word: %x\n", sim_status()); memset(buffer,0,sizeof(buffer)); puts(" * Testing READ BINARY:\n"); printf(" ==> Status word: %x\n", sim_readbinary(0,0,9,buffer)); printf(" Data: "); myHexdump(buffer,9); memset(buffer,0,sizeof(buffer)); memcpy(buffer,"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff",16); puts(" * Testing RUN GSM ALGORITHM\n"); printf(" ==> Status word: %x\n", sim_run_gsm_algorith(buffer)); printf(" Result: "); myHexdump(buffer,12); delay_ms(5000); calypso_sim_powerdown(); puts("------------END SIMTEST----8<-----------------\n"); } /* Main Program */ const char *hr = "======================================================================\n"; void key_handler(enum key_codes code, enum key_states state); static void *console_rx_cb(uint8_t dlci, struct msgb *msg) { if (dlci != SC_DLCI_CONSOLE) { printf("Message for unknown DLCI %u\n", dlci); return; } printf("Message on console DLCI: '%s'\n", msg->data); msgb_free(msg); } int main(void) { board_init(); puts("\n\nOSMOCOM SIM Test (revision " GIT_REVISION ")\n"); puts(hr); /* Dump device identification */ dump_dev_id(); puts(hr); /* Dump clock config before PLL set */ calypso_clk_dump(); puts(hr); keypad_set_handler(&key_handler); /* Dump clock config after PLL set */ calypso_clk_dump(); puts(hr); /* Dump all memory */ //dump_mem(); #if 0 /* Dump Bootloader */ memdump_range((void *)0x00000000, 0x2000); puts(hr); #endif sercomm_register_rx_cb(SC_DLCI_CONSOLE, console_rx_cb); do_sim_test(); /* beyond this point we only react to interrupts */ puts("entering interrupt loop\n"); while (1) { } twl3025_power_off(); while (1) {} } void key_handler(enum key_codes code, enum key_states state) { if (state != PRESSED) return; switch (code) { default: break; } }