/** * Answer To Reset (ATR) * \param pAtr ATR buffer * \param pLength Pointer for store the ATR length */ void ISO7816_Datablock_ATR( uint8_t* pAtr, uint8_t* pLength ) { uint32_t i; uint32_t j; uint32_t y; *pLength = 0; /* Read ATR TS */ ISO7816_GetChar(&pAtr[0]); /* Read ATR T0 */ ISO7816_GetChar(&pAtr[1]); y = pAtr[1] & 0xF0; i = 2; /* Read ATR Ti */ while (y) { if (y & 0x10) { /* TA[i] */ ISO7816_GetChar(&pAtr[i++]); } if (y & 0x20) { /* TB[i] */ ISO7816_GetChar(&pAtr[i++]); } if (y & 0x40) { /* TC[i] */ ISO7816_GetChar(&pAtr[i++]); } if (y & 0x80) { /* TD[i] */ ISO7816_GetChar(&pAtr[i]); y = pAtr[i++] & 0xF0; } else { y = 0; } } /* Historical Bytes */ y = pAtr[1] & 0x0F; for( j=0; j < y; j++ ) { ISO7816_GetChar(&pAtr[i++]); } TRACE_DEBUG_WP("Length = %d", i); TRACE_DEBUG_WP("ATR = "); for (j=0; j < i; j++) { TRACE_DEBUG_WP("%02x ", pAtr[j]); } TRACE_DEBUG_WP("\n\r"); *pLength = i; }
/** * Answer To Reset (ATR) * \param pAtr ATR buffer * \param pLength Pointer for store the ATR length */ void ISO7816_Datablock_ATR( uint8_t* pAtr, uint8_t* pLength ) { uint32_t i; uint32_t j; uint32_t y; *pLength = 0; /* Read ATR TS */ ISO7816_GetChar(&pAtr[0]); /* Read ATR T0 */ ISO7816_GetChar(&pAtr[1]); y = pAtr[1] & 0xF0; i = 2; /* Read ATR Ti */ while (y) { if (y & 0x10) { /* TA[i] */ ISO7816_GetChar(&pAtr[i++]); } if (y & 0x20) { /* TB[i] */ ISO7816_GetChar(&pAtr[i++]); } if (y & 0x40) { /* TC[i] */ ISO7816_GetChar(&pAtr[i++]); } if (y & 0x80) { /* TD[i] */ ISO7816_GetChar(&pAtr[i]); y = pAtr[i++] & 0xF0; } else { y = 0; } } /* Historical Bytes */ y = pAtr[1] & 0x0F; for( j=0; j < y; j++ ) { ISO7816_GetChar(&pAtr[i++]); } *pLength = i; }
/** * Transfert Block TPDU T=0 * \param pAPDU APDU buffer * \param pMessage Message buffer * \param wLength Block length * \return Message index */ uint16_t ISO7816_XfrBlockTPDU_T0(const uint8_t *pAPDU, uint8_t *pMessage, uint16_t wLength ) { uint16_t NeNc; uint16_t indexApdu = 4; uint16_t indexMessage = 0; uint8_t SW1 = 0; uint8_t procByte; uint8_t cmdCase; TRACE_DEBUG("pAPDU[0]=0x%X\n\r",pAPDU[0]); TRACE_DEBUG("pAPDU[1]=0x%X\n\r",pAPDU[1]); TRACE_DEBUG("pAPDU[2]=0x%X\n\r",pAPDU[2]); TRACE_DEBUG("pAPDU[3]=0x%X\n\r",pAPDU[3]); TRACE_DEBUG("pAPDU[4]=0x%X\n\r",pAPDU[4]); TRACE_DEBUG("pAPDU[5]=0x%X\n\r",pAPDU[5]); TRACE_DEBUG("wlength=%d\n\r",wLength); ISO7816_SendChar( pAPDU[0] ); /* CLA */ ISO7816_SendChar( pAPDU[1] ); /* INS */ ISO7816_SendChar( pAPDU[2] ); /* P1 */ ISO7816_SendChar( pAPDU[3] ); /* P2 */ ISO7816_SendChar( pAPDU[4] ); /* P3 */ /* Handle the four structures of command APDU */ indexApdu = 4; if( wLength == 4 ) { cmdCase = CASE1; NeNc = 0; } else if( wLength == 5) { cmdCase = CASE2; NeNc = pAPDU[4]; /* C5 */ if (NeNc == 0) { NeNc = 256; } } else if( wLength == 6) { NeNc = pAPDU[4]; /* C5 */ cmdCase = CASE3; } else if( wLength == 7) { NeNc = pAPDU[4]; /* C5 */ if( NeNc == 0 ) { cmdCase = CASE2; NeNc = (pAPDU[5]<<8)+pAPDU[6]; } else { cmdCase = CASE3; } } else { NeNc = pAPDU[4]; /* C5 */ if( NeNc == 0 ) { cmdCase = CASE3; NeNc = (pAPDU[5]<<8)+pAPDU[6]; } else { cmdCase = CASE3; } } TRACE_DEBUG("CASE=0x%X NeNc=0x%X\n\r", cmdCase, NeNc); /* Handle Procedure Bytes */ do { ISO7816_GetChar(&procByte); /* Handle NULL */ if ( procByte == ISO_NULL_VAL ) { TRACE_DEBUG("INS\n\r"); continue; } /* Handle SW1 */ else if ( ((procByte & 0xF0) ==0x60) || ((procByte & 0xF0) ==0x90) ) { TRACE_DEBUG("SW1\n\r"); SW1 = 1; } /* Handle INS */ else if ( pAPDU[1] == procByte) { TRACE_DEBUG("HdlINS\n\r"); if (cmdCase == CASE2) { /* receive data from card */ do { ISO7816_GetChar(&pMessage[indexMessage++]); } while( 0 != --NeNc ); } else { /* Send data */ do { ISO7816_SendChar(pAPDU[indexApdu++]); } while( 0 != --NeNc ); } } /* Handle INS ^ 0xff */ else if ( pAPDU[1] == (procByte ^ 0xff)) { TRACE_DEBUG("HdlINS+\n\r"); if (cmdCase == CASE2) { /* receive data from card */ ISO7816_GetChar(&pMessage[indexMessage++]); } else { ISO7816_SendChar(pAPDU[indexApdu++]); } NeNc--; } else { /* ?? */ TRACE_DEBUG("procByte=0x%X\n\r", procByte); break; } } while (NeNc != 0); /* Status Bytes */ if (SW1 == 0) { ISO7816_GetChar(&pMessage[indexMessage++]); /* SW1 */ } else { pMessage[indexMessage++] = procByte; } ISO7816_GetChar(&pMessage[indexMessage++]); /* SW2 */ return( indexMessage ); }