⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iso7816_4.c

📁 at91sam9260-ek library file
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ----------------------------------------------------------------------------
 *         ATMEL Microcontroller Software Support 
 * ----------------------------------------------------------------------------
 * Copyright (c) 2008, Atmel Corporation
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the disclaimer below.
 *
 * Atmel's name may not be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 * DISCLAIMED. IN NO EVENT SHALL ATMEL 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.
 * ----------------------------------------------------------------------------
 */

//------------------------------------------------------------------------------
//         Headers
//------------------------------------------------------------------------------

#include <board.h>
#include <usart/usart.h>
#include <utility/trace.h>
#include <pio/pio.h>
#include "iso7816_4.h"
#include "iso7816_3.h"

//------------------------------------------------------------------------------
//         Definitions
//------------------------------------------------------------------------------
// Case for APDU commands
#define CASE1  1
#define CASE2  2
#define CASE3  3

// Flip flop for send and receive char
#define USART_SEND 0
#define USART_RCV  1

//------------------------------------------------------------------------------
//         Internal variables
//------------------------------------------------------------------------------
static unsigned char StateUsartGlobal = USART_RCV;
static Pin st_pinIso7816RstMC;

//-----------------------------------------------------------------------------
//         Internal functions
//-----------------------------------------------------------------------------

//------------------------------------------------------------------------------
/// Get a character from ISO7816
/// \param pCharToReceive   Pointer for store the received char
/// \return                 0: if timeout else status of US_CSR
//------------------------------------------------------------------------------
static unsigned int ISO7816_GetChar( unsigned char *pCharToReceive )
{
    unsigned int status;
    unsigned int timeout=0;

    if( StateUsartGlobal == USART_SEND ) {
        while((AT91C_BASE_US0->US_CSR & AT91C_US_TXEMPTY) == 0) {}
        AT91C_BASE_US0->US_CR = AT91C_US_RSTSTA | AT91C_US_RSTIT | AT91C_US_RSTNACK;
        StateUsartGlobal = USART_RCV;
    }

    // Wait USART ready for reception
    while( ((AT91C_BASE_US0->US_CSR & AT91C_US_RXRDY) == 0) ) {
        if(timeout++ >6000) {
            trace_LOG(trace_DEBUG, "TimeOut\n\r");
            return( 0 );
        }
    }

    trace_LOG(trace_DEBUG, "T: %d\n\r", timeout);


    // At least one complete character has been received and US_RHR has not yet been read.

    // Get a char
    *pCharToReceive = ((AT91C_BASE_US0->US_RHR) & 0xFF);

    status = (AT91C_BASE_US0->US_CSR&(AT91C_US_OVRE|AT91C_US_FRAME|
                                      AT91C_US_PARE|AT91C_US_TIMEOUT|AT91C_US_NACK|
                                      (1<<10)));

    if (status != 0 ) {
       // trace_LOG(trace_DEBUG, "R:0x%X\n\r", status);
        trace_LOG(trace_DEBUG, "R:0x%X\n\r", AT91C_BASE_US0->US_CSR);
        trace_LOG(trace_DEBUG, "Nb:0x%X\n\r", AT91C_BASE_US0->US_NER );
        AT91C_BASE_US0->US_CR = AT91C_US_RSTSTA;
    }

    // Return status
    return( status );
}


//------------------------------------------------------------------------------
/// Send a char to ISO7816
/// \param CharToSend       char to be send
/// \return                 status of US_CSR
//------------------------------------------------------------------------------
static unsigned int ISO7816_SendChar( unsigned char CharToSend )
{
    unsigned int status;

    if( StateUsartGlobal == USART_RCV ) {
        AT91C_BASE_US0->US_CR = AT91C_US_RSTSTA | AT91C_US_RSTIT | AT91C_US_RSTNACK;
        StateUsartGlobal = USART_SEND;
    }

    // Wait USART ready for transmit
    while((AT91C_BASE_US0->US_CSR & AT91C_US_TXRDY) == 0)  {}
    // There is no character in the US_THR

    // Transmit a char
    AT91C_BASE_US0->US_THR = CharToSend;

    status = (AT91C_BASE_US0->US_CSR&(AT91C_US_OVRE|AT91C_US_FRAME|
                                      AT91C_US_PARE|AT91C_US_TIMEOUT|AT91C_US_NACK|
                                      (1<<10)));

    if (status != 0 ) {
        trace_LOG(trace_DEBUG, "E:0x%X\n\r", AT91C_BASE_US0->US_CSR);
        trace_LOG(trace_DEBUG, "Nb:0x%X\n\r", AT91C_BASE_US0->US_NER );
        AT91C_BASE_US0->US_CR = AT91C_US_RSTSTA;
    }

    // Return status
    return( status );
}


//------------------------------------------------------------------------------
/// Iso 7816 ICC power on
//------------------------------------------------------------------------------
static void ISO7816_IccPowerOn( void )
{
    // Set RESET Master Card
    PIO_Set(&st_pinIso7816RstMC);
}

//-----------------------------------------------------------------------------
//         Exported functions
//-----------------------------------------------------------------------------

//------------------------------------------------------------------------------
/// Iso 7816 ICC power off
//------------------------------------------------------------------------------
void ISO7816_IccPowerOff( void )
{
    // Clear RESET Master Card
    PIO_Clear(&st_pinIso7816RstMC);
}

//------------------------------------------------------------------------------
/// Transfert Block TPDU T=0
/// \param pAPDU            APDU buffer
/// \param pMessage         Message buffer
/// \param wLength          Block length
/// \return                 Message index
//------------------------------------------------------------------------------
unsigned short ISO7816_XfrBlockTPDU_T0(const unsigned char *pAPDU, 
                                        unsigned char *pMessage, 
                                        unsigned short wLength )
{
    unsigned short NeNc;
    unsigned short indexApdu = 4;
    unsigned short indexMessage = 0;
    unsigned char SW1 = 0;
    unsigned char procByte;
    unsigned char cmdCase;

    trace_LOG(trace_DEBUG, "pAPDU[0]=0x%X\n\r",pAPDU[0]);
    trace_LOG(trace_DEBUG, "pAPDU[1]=0x%X\n\r",pAPDU[1]);
    trace_LOG(trace_DEBUG, "pAPDU[2]=0x%X\n\r",pAPDU[2]);
    trace_LOG(trace_DEBUG, "pAPDU[3]=0x%X\n\r",pAPDU[3]);
    trace_LOG(trace_DEBUG, "pAPDU[4]=0x%X\n\r",pAPDU[4]);
    trace_LOG(trace_DEBUG, "pAPDU[5]=0x%X\n\r",pAPDU[5]);
    trace_LOG(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_LOG(trace_DEBUG, "CASE=0x%X NeNc=0x%X\n\r", cmdCase, NeNc);

    // Handle Procedure Bytes
    do {
        ISO7816_GetChar(&procByte);
        // Handle NULL
        if ( procByte == 0x60 ) {
            trace_LOG(trace_DEBUG, "INS\n\r");
            continue;
        }
        // Handle SW1
        else if ( ((procByte & 0xF0) ==0x60) || ((procByte & 0xF0) ==0x90) ) {
            trace_LOG(trace_DEBUG, "SW1\n\r");
            SW1 = 1;
        }
        // Handle INS
        else if ( pAPDU[1] == procByte) {
            trace_LOG(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_LOG(trace_DEBUG, "HdlINS+\n\r");
            if (cmdCase == CASE2) {
                // receive data from card
                ISO7816_GetChar(&pMessage[indexMessage++]);
            }
            else {
                ISO7816_SendChar(pAPDU[indexApdu++]);
            }
            NeNc--;
        }
        else {
            // ??
            trace_LOG(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 );
    
}

//------------------------------------------------------------------------------
/// Escape ISO7816

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -