/* * Copyright (c) 2005 Mark Fullmer * Copyright (c) 2009 Mark Fullmer and the Ohio State University * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: main.c 13 2009-11-26 16:37:03Z maf $ */ #include #include "r2sdk.h" #include "spi.h" #include "delay.h" /* */ #define NO_CALC /* * HI-TECH C version 9.x does not use a long jump for its startup code. * This is a problem since the bootloader in the PARII expects this. * * With the use of --codeoffset=4 and the following assembler we get the * 8.x behavior (albeit with an extra goto) * * Note this is hardcoded to jump to 0x04. If interrupts are used the startup * code may go elsewhere. * */ #asm psect reserved,class=CODE, delta=2 CLRF 0x03 MOVLW 0x0 MOVWF 0xA GOTO 0x04; Jump to startup #endasm /* also defined in otpsc.h */ #define SC_GETHOSTNAME_CLA 0x80 #define SC_GETHOTP_CLA 0x80 #define SC_SETPIN_CLA 0x80 #define SC_TESTPIN_CLA 0x80 #define SC_GETHOTPCOUNT32_CLA 0x80 #define SC_GETHOTPHOST_CLA 0x80 #define SC_GETHOTPHOSTCOUNT32_CLA 0x80 #define SC_GETSPYRUSEEBLOCK_CLA 0x80 #define SC_GETHOSTNAME_INS 0x44 #define SC_GETHOTP_INS 0x46 #define SC_SETPIN_INS 0x4C #define SC_TESTPIN_INS 0x4E #define SC_GETHOTPCOUNT32_INS 0x58 #define SC_GETHOTPHOST_INS 0x5A #define SC_GETHOTPHOSTCOUNT32_INS 0x5C #define SC_GETSPYRUSEEBLOCK_INS 0xA2 U8 protocol = 0x03; RESP_INFO *Resp; bank1 U8 Buf[72]; /* Spyrus I/O buffer */ bank2 U8 dbuf[2][16]; /* two current hostnames for menu */ bank2 U8 obuf[2][1]; /* option buffer for menu items */ U8 myPIN[5]; /* PIN */ U8 newPIN[5]; /* newPIN if set */ U8 sc_cmdLen; /* SC command length */ U8 sc_idx; /* SC host index */ /* * sc_count and sc_countp must be in same bank or C compiler will * generate incorrect code */ bank2 U32 sc_count; /* SC host count */ bank2 U8 *sc_countp; /* byte pointer to sc_count */ /* menu vars */ U8 menu_active; /* # of active menu items */ U8 menu_cursor; /* menu cursor position (top/bottom) */ U8 menu_idx; /* index of menu */ U8 ml_flags; /* flags for main loop */ U8 short_d0; /* shortcut digit 0 */ U8 key; /* key input */ U8 key_num; /* key number (ASCII 0..9) */ /* scratch bytes */ U8 scratch_buf5[5]; /* size of initialization data for EEProm */ #define EE_INIT_SIZE 224 /* size of EEProm */ #define EE_SIZE 256 /* number of 16 byte blocks in EEProm */ #define EE_BLOCKS 16 /* number of bytes in a block */ #define EE_BLOCK_SIZE 16 #define EE_BLOCK_SIZE_SHIFT 4 /* 2^4=16 */ /* EE Memory Map */ #define EE_MAGIC_ADDR 0 #define EE_READER_KEY_ADDR 3 #define EE_CALC_MSG_ADDR 8 #define EE_L1GREET_ADDR 20 #define EE_L2GREET_ADDR 32 #define EE_L1MAIN_ADDR 44 #define EE_L2MAIN_ADDR 56 #define EE_CHALLENGE_ADDR 68 #define EE_L1LOCKED_ADDR 80 #define EE_L2LOCKED_ADDR 92 #define EE_L1ACCESS_DENY_ADDR 104 #define EE_L2ACCESS_DENY_ADDR 116 #define EE_NOHOSTS_ADDR 128 #define EE_L1NEWPIN_ADDR 140 #define EE_L2NEWPIN_ADDR 152 #define EE_L3NEWPIN_ADDR 164 #define EE_PINCHANGED_ADDR 176 #define EE_NOCARD_ADDR 188 #define EE_TRYHARDER_ADDR 200 #define EE_MAGIC_LEN 3 #define EE_READER_KEY_LEN 5 #define EE_CALC_MSG_LEN 12 #define EE_L1GREET_LEN 12 #define EE_L2GREET_LEN 12 #define EE_L1MAIN_LEN 12 #define EE_L2MAIN_LEN 12 #define EE_CHALLENGE_LEN 12 #define EE_L1LOCKED_LEN 12 #define EE_L2LOCKED_LEN 12 #define EE_L1ACCESS_DENY_LEN 12 #define EE_L2ACCESS_DENY_LEN 12 #define EE_NOHOSTS_LEN 12 #define EE_L1NEWPIN_LEN 12 #define EE_L2NEWPIN_LEN 12 #define EE_L3NEWPIN_LEN 12 #define EE_PINCHANGED_LEN 12 #define EE_NOCARD_LEN 12 #define EE_TRYHARDER_LEN 12 /* EEInit */ const U8 EEDefault[] = { 0x6d,0x61,0x66,0x30,0x30,0x30,0x30,0x30, 0x4f,0x41,0x52,0x6e,0x65,0x74,0x3a,0x32, 0x30,0x30,0x39,0x20,0x20,0x20,0x20,0x4f, 0x41,0x52,0x6e,0x65,0x74,0x20,0x20,0x20, 0x50,0x49,0x4e,0x3a,0x20,0x20,0x20,0x20, 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x4f, 0x41,0x52,0x6e,0x65,0x74,0x20,0x20,0x20, 0x20,0x20,0x56,0x65,0x72,0x69,0x66,0x69, 0x65,0x64,0x20,0x20,0x43,0x68,0x61,0x6c, 0x6c,0x65,0x6e,0x67,0x65,0x3a,0x20,0x20, 0x31,0x30,0x20,0x46,0x61,0x69,0x6c,0x75, 0x72,0x65,0x73,0x20,0x43,0x61,0x72,0x64, 0x20,0x4c,0x6f,0x63,0x6b,0x65,0x64,0x20, 0x20,0x20,0x20,0x41,0x63,0x63,0x65,0x73, 0x73,0x20,0x20,0x20,0x20,0x20,0x20,0x44, 0x65,0x6e,0x69,0x65,0x64,0x20,0x20,0x20, 0x20,0x20,0x4e,0x6f,0x20,0x48,0x6f,0x73, 0x74,0x73,0x20,0x20,0x53,0x65,0x74,0x20, 0x4e,0x65,0x77,0x20,0x50,0x49,0x4e,0x20, 0x4e,0x65,0x77,0x50,0x49,0x4e,0x3a,0x20, 0x20,0x20,0x20,0x20,0x41,0x67,0x61,0x69, 0x6e,0x3a,0x20,0x20,0x20,0x20,0x20,0x20, 0x50,0x49,0x4e,0x20,0x43,0x68,0x61,0x6e, 0x67,0x65,0x64,0x20,0x4e,0x6f,0x20,0x43, 0x61,0x72,0x64,0x20,0x20,0x20,0x20,0x20, 0x54,0x72,0x79,0x20,0x48,0x61,0x72,0x64, 0x65,0x72,0x20,0x20,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; const U8 VERSION[] = { /* record length */ 0x0C,\ /* Serial # */ 0x0A, 'm', 'a', 'f', ' ', 'H', 'O', 'T', 'P', ' ', ' ',\ /* AE kernel version / program access (unused) */ 0x13, 0x22, 0x33 }; U8 getPIN(U8 *dest, U8 pos); void getCount(void); void dispHOTP(void); U8 hexdigit(U8 d); U8 SCTransact(void); void cmdSCTestPIN(void); void cmdSCSetPIN(void); void cmdSCGetHOTPHostCount32(void); void cmdSCGetHOTPCount32(void); void cmdCsum(void); void cmdSCGetSpyrusEEBlock(U8 i); U8 doSCGetHostname(U8 idx, U8 row); void powerdown(void); void menuUpdateCursor(void); void menuUpdate(void); void menuInit(void); void keyGet(void); void keyDecodeNumber(void); void EEInit(void); U8 EELen(U8 addr, U8 len); #define FLAGS_SCREEN0_UPDATE 0x01 /* initial screen update? */ #define FLAGS_INPUT_COUNT 0x02 /* input count before HOTP? */ #define FLAGS_MENU_SHORT_D0 0x04 /* menu shortcut digit 0 */ #define FLAGS_MENU_ACTIVE 0x08 /* menu is active */ #define HOSTNAME_FLAG_MASK 0x80 /* high bit set */ #define HOSTNAME_POS_CHALLENGE 0x00 /* require challenge input */ #define HOSTNAME_POS_READERKEY 0x01 /* require reader key */ #define OPTION_FLAG_CHALLENGE 0x01 /* option set to request challenge */ int main(void) { U8 i, c, j, addr; /* init */ Resp = (RESP_INFO*)Buf; r2_init(); sc_countp = (U8*)&sc_count; i = ServiceQuery(); /* initialize EEProm if not set */ EEInit(); if (i == SQ_CALC) { #ifndef NO_CALC DoCalc(&Resp->data[2]); Str2Lcd(0,0,&Resp->data[2]); #else EE2LCD(0, 0, EE_CALC_MSG_ADDR, EE_CALC_MSG_LEN); powerdown(); #endif /* NO_CALC */ } /* SQ_CALC */ if (i == SQ_FW_VERSION) { for (i = 0; i < 0x0E; ++i) Buf[i] = VERSION[i]; snd_cmd(FIRMWARE_INFO, 0x0E, Buf); get_resp(Resp); } /* anything to do? */ if (i != SQ_CARD_KEY) powerdown(); ClearLcd(); /* get valid PIN */ while (1) { /* initial greeting */ EE2LCD(0, 0, EE_L1GREET_ADDR, EE_L1GREET_LEN); EE2LCD(1, 0, EE_L2GREET_ADDR, EE_L2GREET_LEN); /* Get PIN */ i = getPIN(myPIN,4); /* magic sequence to load EEProm */ if (i == 1) { scratch_buf5[2] = 0; ClearLcd(); Str2Lcd(0, 0, "EEWrite"); /* foreach block */ for (i = 0; i < EE_BLOCKS; ++i) { cmdSCGetSpyrusEEBlock(i); if (SCTransact() != 0) powerdown(); /* * 2 byte resp (2) : 0,1 * NAD,PCB,LEN (3) : 2,3,4 * idx (1) : 5 * eeData (16) : 6..21 */ scratch_buf5[0] = hexdigit(i>>4); scratch_buf5[1] = hexdigit(i&0x0F); Str2Lcd(1, 0, scratch_buf5); /* foreach byte in the block */ for (j = 0; j < EE_BLOCK_SIZE; ++j) { c = Buf[6+j]; addr = (i< 2) { menu_idx = menu_idx - menu_active; doSCGetHostname(menu_idx-2,0); doSCGetHostname(menu_idx-1,1); menu_active = 2; menu_cursor = 1; menuUpdate(); } } continue; } /* RAW_UP */ /****** MENU ENTER ****/ if (key == RAW_ENTER) { /* host menu active? */ if (!(ml_flags & FLAGS_MENU_ACTIVE)) { /* no */ /* index is first digit input or 0 if no digits input */ sc_idx = short_d0; goto enter_shortcut; } /* host menu not active yet */ /* index on smart card */ sc_idx = menu_idx - menu_active + menu_cursor; /* challenge input? */ if ((obuf[menu_cursor][0] & OPTION_FLAG_CHALLENGE) || (ml_flags & FLAGS_INPUT_COUNT)) getCount(); /* GetHOTPCount32 command */ cmdSCGetHOTPCount32(); /* initiate SC transaction */ if (SCTransact() == 0) { /* * 2 byte resp (2) : 0,1 * NAD,PCB,LEN (3) : 2,3,4 * idx (1) : 5 * PIN (5) : 6,7,8,9,10 * count (4) : 11,12,13,14 * HOTP (5) : 15,16,17,18,19 */ /* display hostname on top */ for (i = 0; i < 12; ++i) dbuf[0][i] = dbuf[menu_cursor][i+3]; dbuf[0][12] = 0; /* display HOTP screen */ dispHOTP(); } else { /* Failure */ Str2Lcd(0,0,"GHPC32 Fail"); /* any key to continue */ GetRawKey(Resp); } /* SC transaction */ /* start back to main screen */ menuInit(); /* next input */ continue; } /****** CHANGE PIN ****/ if (key == RAW_STAR) { while (1) { ClearLcd(); EE2LCD(0, 0, EE_L1NEWPIN_ADDR, EE_L1NEWPIN_LEN); EE2LCD(1, 0, EE_L2NEWPIN_ADDR, EE_L2NEWPIN_LEN); i = EELen(EE_L2NEWPIN_ADDR, EE_L2NEWPIN_LEN); getPIN(newPIN, i); /* minimal checking, all digits equal not permitted */ if ((newPIN[0] == newPIN[1]) && (newPIN[1] == newPIN[2]) && (newPIN[2] == newPIN[3]) && (newPIN[3] == newPIN[4])) { ClearLcd(); EE2LCD(0, 0, EE_TRYHARDER_ADDR, EE_TRYHARDER_LEN); Beep(2); GetRawKey(Resp); continue; } EE2LCD(1, 0, EE_L3NEWPIN_ADDR, EE_L3NEWPIN_LEN); i = EELen(EE_L3NEWPIN_ADDR, EE_L3NEWPIN_LEN); getPIN(scratch_buf5, i); /* make sure user entered it correctly */ if ((newPIN[0] == scratch_buf5[0]) && (newPIN[1] == scratch_buf5[1]) && (newPIN[2] == scratch_buf5[2]) && (newPIN[3] == scratch_buf5[3]) && (newPIN[4] == scratch_buf5[4])) break; /* have valid new pin */ /* two did not match */ Beep(2); } /* get new pin */ /* Set PIN command */ cmdSCSetPIN(); /* Initiate smart card transaction */ if (SCTransact() == 0) { /* success */ ClearLcd(); EE2LCD(0, 0, EE_PINCHANGED_ADDR, EE_PINCHANGED_LEN); myPIN[0] = newPIN[0]; myPIN[1] = newPIN[1]; myPIN[2] = newPIN[2]; myPIN[3] = newPIN[3]; myPIN[4] = newPIN[4]; } else { /* Failure */ Str2Lcd(0,0,"SetPIN Fail"); } /* go back to initial screen */ ml_flags |= FLAGS_SCREEN0_UPDATE; /* any key to continue */ GetRawKey(Resp); /* success / next input */ continue; } /* RAW_STAR / CHANGE_PIN */ /***** CLEAN INPUT DIGITS */ if (key == RAW_CANCEL) { short_d0 = 0; ml_flags &= ~FLAGS_MENU_SHORT_D0; continue; } /****** MENU SHORTCUT WITH DIGIT ENTRY ***** */ /* * require two digit host index */ /* convert raw keypress to 0..9 */ keyDecodeNumber(); /* any keys input not 0..9 are no longer valid */ if (!key_num) { Beep(1); continue; } /* first digit? */ if (!(ml_flags & FLAGS_MENU_SHORT_D0)) { /* store first digit */ short_d0 = key_num - '0'; /* first digit input success */ ml_flags |= FLAGS_MENU_SHORT_D0; } else { /* 2nd digit triggers HOTP generation */ /* sc_idx = short_d0*10+d1 */ sc_idx = short_d0 <<3; sc_idx += short_d0; sc_idx += short_d0; sc_idx += (key_num - '0'); enter_shortcut: /* input count first? */ if (ml_flags & FLAGS_INPUT_COUNT) getCount(); /* GetHOTPHostCount32 command */ cmdSCGetHOTPHostCount32(); /* initiate SC transaction */ if (SCTransact() == 0) { /* * 2 byte resp (2) : 0,1 * NAD,PCB,LEN (3) : 2,3,4 * idx (1) : 5 * PIN (5) : 6,7,8,9,10 * count (4) : 11,12,13,14 * HOTP (5) : 15,16,17,18,19 * HostName(12) : 20..31 */ /* skip display for empty hostname */ if (Buf[20] != 0) { /* display hostname on top */ for (i = 0; i < 12; ++i) dbuf[0][i] = (Buf[20+i]&0x7F); dbuf[0][12] = 0; /* display HOTP screen */ dispHOTP(); } } else { /* Failure */ Str2Lcd(0,0,"GHPHC32 Fail"); /* any key to continue */ GetRawKey(Resp); } /* SC transaction */ /* initialize for main screen input */ menuInit(); } /* digit */ /* next input */ continue; } /* main key loop */ powerdown(); } /* main */ void getCount(void) { U32 tmp32u; U8 pos; /* prime loop */ key = RAW_CANCEL; /* LCD output string */ scratch_buf5[1] = 0; /* init to 0 */ sc_count = 0; while (1) { if (key == RAW_CANCEL) { ClearLcd(); EE2LCD(0, 0, EE_CHALLENGE_ADDR, EE_CHALLENGE_LEN); sc_count = 0; pos = 0; goto next_key; } /* done? */ if (key == RAW_ENTER) break; keyDecodeNumber(); /* only accept digits */ if (key_num == 0) { Beep(1); goto next_key; } /* 2^32-1 is 10 digits */ if (pos >= 10) { Beep(1); goto next_key; } scratch_buf5[0] = key_num; Str2Lcd(1,pos,scratch_buf5); /* drop leading 0's */ if ((pos == 0) && (key_num == '0')) goto next_key; /* ignore potential overflow from user input, not meaningful */ tmp32u = (sc_count<<3); /* *8 */ tmp32u += (sc_count<<1); /* +*2 or *10 */ tmp32u += (key_num - '0'); /* + new digit */ sc_count = tmp32u; ++pos; next_key: keyGet(); } /* get count input */ } /* getCount */ /* * function: getPIN() * * Get PIN from user. * dest = 0 Store in myPIN * dest = 1 Store in newPIN * * return 0 good * 1 fail */ U8 getPIN(U8 *dest, U8 pos) { U8 i; i = 0; while (1) { /* get a single key */ keyGet(); /* Enter is valid when 5 digits have been entered */ if (key == RAW_ENTER && i == 5) break; if ((key == RAW_POUND) && (i == 1) && (dest[0] == '3')) return 1; /* Clear entry */ if (key == RAW_CANCEL) { Str2Lcd(1,pos," "); i = 0; continue; } /* convert keycode to ASCII */ keyDecodeNumber(); /* else if pin not full and valid digit */ if (i < 5 && key_num) { Str2Lcd(1,i+pos,"*"); dest[i++] = key_num; } else { Beep(1); } } /* while */ return 0; } /* get_pin */ void keyGet(void) { GetRawKey(Resp); key = *Resp->data; } /* keyGet */ /* * function: keyDecodeNumber() * * decode ASCII code for Spyrus keycode 0..9 * else 0 */ void keyDecodeNumber (void) { if (key == RAW0) key_num = '0'; else if (key == RAW1) key_num = '1'; else if (key == RAW2) key_num = '2'; else if (key == RAW3) key_num = '3'; else if (key == RAW4) key_num = '4'; else if (key == RAW5) key_num = '5'; else if (key == RAW6) key_num = '6'; else if (key == RAW7) key_num = '7'; else if (key == RAW8) key_num = '8'; else if (key == RAW9) key_num = '9'; else key_num = 0; } /* keyDecodeNumber */ /* * function: hexdigit() * * return a hex digit in ASCII */ U8 hexdigit(U8 d) { if (d < 10) return d + '0'; return d + 'A' - 10; } /* hexdigit */ /* * function: cmdCsum() * * perform ISO checksum calculation on Buf */ void cmdCsum(void) { U8 k, l; l = 29+sc_cmdLen; for (k = 30; k < l; ++k) Buf[l] = Buf[l] ^ Buf[k]; } /* cmdCsum */ void cmdSCTestPIN(void) { Buf[30] = 0x00; /* NAD */ Buf[31] = 0x00; /* PCB */ Buf[32] = 0x0B; /* LEN */ Buf[33] = SC_TESTPIN_CLA; /* CLA */ Buf[34] = SC_TESTPIN_INS; /* INS */ Buf[35] = 0x00; /* P1 */ Buf[36] = 0x00; /* P2 */ Buf[37] = 0x05; /* DATA LEN */ Buf[38] = myPIN[0]; /* PIN[0] */ Buf[39] = myPIN[1]; /* PIN[1] */ Buf[40] = myPIN[2]; /* PIN[2] */ Buf[41] = myPIN[3]; /* PIN[3] */ Buf[42] = myPIN[4]; /* PIN[4] */ Buf[43] = 0x05; /* Expected response size */ Buf[44] = 0; /* CSUM */ sc_cmdLen = (44-30) + 1; cmdCsum(); } /* cmdSCTestPIN */ void cmdSCSetPIN(void) { Buf[30] = 0x00; /* NAD */ Buf[31] = 0x00; /* PCB */ Buf[32] = 0x10; /* LEN */ Buf[33] = SC_SETPIN_CLA; /* CLA */ Buf[34] = SC_SETPIN_INS; /* INS */ Buf[35] = 0x00; /* P1 */ Buf[36] = 0x00; /* P2 */ Buf[37] = 0x0A; /* DATA LEN */ Buf[38] = myPIN[0]; /* PIN */ Buf[39] = myPIN[1]; /* PIN */ Buf[40] = myPIN[2]; /* PIN */ Buf[41] = myPIN[3]; /* PIN */ Buf[42] = myPIN[4]; /* PIN */ Buf[43] = newPIN[0]; /* newPIN */ Buf[44] = newPIN[1]; /* newPIN */ Buf[45] = newPIN[2]; /* newPIN */ Buf[46] = newPIN[3]; /* newPIN */ Buf[47] = newPIN[4]; /* newPIN */ Buf[48] = 0x0A; /* Expected response size */ Buf[49] = 0; /* CSUM */ sc_cmdLen = (49-30) + 1; /* DATA_LEN + 4 */ cmdCsum(); } /* cmdSCSetPIN */ void cmdSCGetHOTPHostCount32(void) { U8 i; Buf[30] = 0x00; /* NAD */ Buf[31] = 0x00; /* PCB */ Buf[32] = 21; /* LEN (DATA_LEN + 6) */ Buf[33] = SC_GETHOTPHOSTCOUNT32_CLA; /* CLA */ Buf[34] = SC_GETHOTPHOSTCOUNT32_INS; /* INS */ Buf[35] = 0x00; /* P1 */ Buf[36] = 0x00; /* P2 */ Buf[37] = 15; /* DATA LEN 1+5+4+5+0 */ Buf[38] = sc_idx; /* Index */ Buf[39] = myPIN[0]; /* PIN[0] */ Buf[40] = myPIN[1]; /* PIN[1] */ Buf[41] = myPIN[2]; /* PIN[2] */ Buf[42] = myPIN[3]; /* PIN[3] */ Buf[43] = myPIN[4]; /* PIN[4] */ Buf[44] = sc_countp[3]; /* COUNT */ Buf[45] = sc_countp[2]; /* COUNT */ Buf[46] = sc_countp[1]; /* COUNT */ Buf[47] = sc_countp[0]; /* COUNT */ /* 48..52 /* ReaderPIN */ Buf[53] = 27; /* Expected response size 1+5+4+5+12*/ Buf[54] = 0; /* CSUM */ sc_cmdLen = (54-30) + 1; /* DATA_LEN + 4 */ for (i = 0; i < EE_READER_KEY_LEN; ++i) Buf[48+i] = EEPROM_READ(EE_READER_KEY_ADDR+i); cmdCsum(); } /* cmdSCGetHOTPHostCount32 */ void cmdSCGetHOTPCount32(void) { U8 i; Buf[30] = 0x00; /* NAD */ Buf[31] = 0x00; /* PCB */ Buf[32] = 21; /* LEN (DATA_LEN + 6) */ Buf[33] = SC_GETHOTPCOUNT32_CLA; /* CLA */ Buf[34] = SC_GETHOTPCOUNT32_INS; /* INS */ Buf[35] = 0x00; /* P1 */ Buf[36] = 0x00; /* P2 */ Buf[37] = 15; /* DATA LEN 1+5+4+5 */ Buf[38] = sc_idx; /* Index */ Buf[39] = myPIN[0]; /* PIN[0] */ Buf[40] = myPIN[1]; /* PIN[1] */ Buf[41] = myPIN[2]; /* PIN[2] */ Buf[42] = myPIN[3]; /* PIN[3] */ Buf[43] = myPIN[4]; /* PIN[4] */ Buf[44] = sc_countp[3]; /* COUNT */ Buf[45] = sc_countp[2]; /* COUNT */ Buf[46] = sc_countp[1]; /* COUNT */ Buf[47] = sc_countp[0]; /* COUNT */ /* 48..52 /* ReaderPIN */ Buf[53] = 15; /* Expected response size 1+5+4+5*/ Buf[54] = 0; /* CSUM */ sc_cmdLen = (54-30) + 1; /* DATA_LEN + 4 */ for (i = 0; i < EE_READER_KEY_LEN; ++i) Buf[48+i] = EEPROM_READ(EE_READER_KEY_ADDR+i); cmdCsum(); } /* cmdSCGetHOTPCount32 */ void cmdSCGetSpyrusEEBlock(U8 i) { Buf[30] = 0x00; /* NAD */ Buf[31] = 0x00; /* PCB */ Buf[32] = 7; /* LEN DATA_LEN + 6)*/ Buf[33] = SC_GETSPYRUSEEBLOCK_CLA; /* CLA */ Buf[34] = SC_GETSPYRUSEEBLOCK_INS; /* INS */ Buf[35] = 0x00; /* P1 */ Buf[36] = 0x00; /* P2 */ Buf[37] = 1; /* DATA LEN 1 */ Buf[38] = i; /* index */ Buf[39] = 17; /* Expected response size 1+16 */ Buf[40] = 0; /* CSUM */ sc_cmdLen = (40-30) + 1; cmdCsum(); } /* cmdSCGetSpyrusEEBlock */ /* * function: SCTransact() * * return codes: * 0 : success * 1 : no card * 2 : access denied * 9 : fatal (will not return) */ U8 SCTransact(void) { U8 r, x1, x2; if (CardPowerOn(Resp)) { ClearLcd(); EE2LCD(0, 0, EE_NOCARD_ADDR, EE_NOCARD_LEN); r = 1; /* no card */ goto SCTransact_err2; } r = SendRawCmd(ICC_CMD, sc_cmdLen, &Buf[30], Resp); CardPowerOff(); /* fatal error? bail with CLA,INS */ if ((r != BLOCK_RESP) || (Resp->len < 3)) { x1 = Buf[33]; /* CLA */ x2 = Buf[34]; /* INS */ r = 9; /* fatal error */ ClearLcd(); Str2Lcd(0,0,"Err CLA:INS"); goto SCTransact_err; } x1 = Resp->data[Resp->len - 3]; /* SW1 */ x2 = Resp->data[Resp->len - 2]; /* SW2 */ if (x1 == 0x90 && x2 == 0x00) return 0; /* success */ ClearLcd(); if (x1 == 0x66 && x2 == 0xC7) { EE2LCD(0, 0, EE_L1LOCKED_ADDR, EE_L1LOCKED_LEN); EE2LCD(1, 0, EE_L2LOCKED_ADDR, EE_L1LOCKED_LEN); r = 9; /* fatal error */ goto SCTransact_err2; } if (x1 == 0x69 && x2 == 0xC2) { EE2LCD(0, 0, EE_L1ACCESS_DENY_ADDR, EE_L1ACCESS_DENY_LEN); EE2LCD(1, 0, EE_L2ACCESS_DENY_ADDR, EE_L2ACCESS_DENY_LEN); r = 2; /* access denied */ goto SCTransact_err2; } Str2Lcd(0,0,"Err SW1:SW2"); /* error */ SCTransact_err: scratch_buf5[0] = hexdigit(x1>>4); scratch_buf5[1] = hexdigit(x1 & 0x0F); scratch_buf5[2] = hexdigit(x2>>4); scratch_buf5[3] = hexdigit(x2 & 0x0F); scratch_buf5[4] = 0; Str2Lcd(1,0,scratch_buf5); /* get any key */ SCTransact_err2: GetRawKey(Resp); ClearLcd(); /* return other than fatal */ if (r != 9) return r; powerdown(); return r; /* unused */ } /* SCTransact */ /* * function: doSCGetHostname() * * grab a single hostname with index i from the card. store in dbuf position j * * returns 1 if hostname is retrieved, else 0. */ U8 doSCGetHostname(U8 idx, U8 row) { U8 k; Buf[30] = 0x00; /* NAD */ Buf[31] = 0x00; /* PCB */ Buf[32] = 12; /* LEN DATA_LEN + 6 */ Buf[33] = SC_GETHOSTNAME_CLA; /* CLA */ Buf[34] = SC_GETHOSTNAME_INS; /* INS */ Buf[35] = 0x00; /* P1 */ Buf[36] = 0x00; /* P2 */ Buf[37] = 6; /* DATA LEN (1+5) */ Buf[38] = idx; /* index */ Buf[39] = myPIN[0]; /* PIN[0] */ Buf[40] = myPIN[1]; /* PIN[1] */ Buf[41] = myPIN[2]; /* PIN[2] */ Buf[42] = myPIN[3]; /* PIN[3] */ Buf[43] = myPIN[4]; /* PIN[4] */ Buf[44] = 18; /* Expected response size 1+5+12 */ Buf[45] = 0; /* CSUM */ sc_cmdLen = (45-30) + 1; /* DATA_LEN + 4 */ cmdCsum(); /* * 2 byte resp (2) : 0,1 * NAD,PCB,LEN (3) : 2,3,4 * idx (1) : 5 * PIN (5) : 6,7,8,9,10 * HostName(12) : 11,12,13,14,15,16,17,18,19,20,21,22 */ if (SCTransact() == 0) { /* success */ /* high bit set on first character signals challenge required */ if (Buf[11+HOSTNAME_POS_CHALLENGE] & HOSTNAME_FLAG_MASK) obuf[row][0] = OPTION_FLAG_CHALLENGE; else obuf[row][0] = 0; /* empty hostname is last */ if (Buf[11] == 0) return 0; /* copy hostname to display buffer */ for (k = 3; k < 15; ++k) dbuf[row][k] = (Buf[k+8] & 0x7F); dbuf[row][0] = hexdigit(idx>>4); dbuf[row][1] = hexdigit(idx&0x0F); dbuf[row][2] = ':'; dbuf[row][12] = 0; return 1; } else { powerdown(); } return 0; /* notreached */ } /* doSCGetHostname */ void powerdown(void) { CardPowerOff(); GetRawKey(Resp); DeactivateRdr(); } /* off */ void menuUpdate(void) { ClearLcd(); Str2Lcd(0,0,&dbuf[0][0]); if (menu_active == 2) Str2Lcd(1,0,&dbuf[1][0]); menuUpdateCursor(); } /* menuUpdate() */ /* * function: menuUpdateCursor() * * Update menu_cursor based on menu_cursor variable */ void menuUpdateCursor(void) { if (menu_cursor == 0) { Str2Lcd(0,2,">"); if (menu_active == 2) Str2Lcd(1,2,":"); } else { Str2Lcd(0,2,":"); if (menu_active == 2) Str2Lcd(1,2,">"); } } /* menuUpdateCursor() */ void dispHOTP(void) { U8 i, j, c; /* HOTP to hex */ for (i = 0, j = 0; i < 5; ++i) { c = Buf[15+i]; dbuf[1][j++] = hexdigit(c>>4); dbuf[1][j++] = hexdigit(c&0x0F); } dbuf[1][j] = 0; /* * note the following code will not compile properly. certain * bits are Xor'd * .X.X.X.X.X (X is nybble with flipped bit) * 74bfe44b40 (generated) * 73BCE44D4C (correct) * * for (i = 0, j = 0; i < 5; ++i) { * c = Buf[15+i] >> 4; * dbuf[1][j++] = hexdigit(c); * c = Buf[15+i] &0x0F * dbuf[1][j++] = hexdigit(c); * } */ /* display hostname and HOTP */ ClearLcd(); Str2Lcd(0,0,&dbuf[0][0]); Str2Lcd(1,1,&dbuf[1][0]); /* any key to continue ~ 10 seconds each, jump out on a key */ for (i = 0, j = 0; i < 3; ++i) { if (!GetRawKey(Resp)) { j = 1; break; } } /* any key will return, timeout to powerdown */ if (j == 0) powerdown(); } /* dispHOTP */ void menuInit(void) { /* initial input screen / no menu activated yet */ ml_flags = FLAGS_SCREEN0_UPDATE; /* smart card index */ sc_idx = 0; /* menu cursor */ menu_cursor = 0; /* SC HOTP count is 0 (default ) */ sc_count = 0; /* first digit if hit enter with host menu not enabled */ short_d0 = 0; /* menu index */ menu_idx = 0; } /* menuInit() */ void EEInit(void) { U8 i, c, match; match = 0; /* Check if EEProm is initialized */ for (i = EE_MAGIC_ADDR; i < EE_MAGIC_LEN; ++i) { c = EEDefault[i]; if (EEPROM_READ(i) == c) ++match; } /* initialized? */ if (match == 3) return; /* no, copy in default data */ for (i = 0; i < EE_INIT_SIZE; ++i) { c = EEDefault[i]; EEPROM_WRITE(i, c); } /* wait for last write to complete */ while (WR) continue; } /* EEInit */ U8 EELen(U8 addr, U8 len) { U8 i, c; for (i = 0; i < len; ++i) { c = EEPROM_READ(addr); if ((c == 0) || (c == ' ')) break; ++addr; } /* max hpos of LCD */ if (i > 11) i = 11; return i; } /* EELen */