FileDocCategorySizeDatePackage
CustomCardAccessor.javaAPI DocJava Card6155Wed Mar 22 21:07:26 GMT 2006com.sun.javacard.clientsamples.securepurseclient

CustomCardAccessor.java

/*
 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

/*
 * @(#)CustomCardAccessor.java	1.4 06/01/03
 */

package com.sun.javacard.clientsamples.securepurseclient;

import java.util.*;
import java.io.*;
import java.net.*;
import java.rmi.*;

import com.sun.javacard.clientlib.*;
/**
 *
 */
public class CustomCardAccessor implements CardAccessor{

    private static final byte INS_SELECT   = (byte)0xA4;
    private static final byte APDU_CMD_MASK = (byte)0xFC;
    private static final byte CLA_ISO7816 = (byte)0x00;

    private static final byte CLA_AUTH = (byte)0x80;
    private static final byte INS_AUTH = (byte)0x39;

    static final byte APDU_SM_MASK_TYPE4            = (byte)0x0C;
    
    private static final boolean debug = false; // change to true to debug

    private static final ResourceBundle msg
    = ResourceBundle.getBundle("com/sun/javacard/clientsamples/securepurseclient/MessagesBundle");

    //the underlying connection to card
    private CardAccessor ca;
    
    /** Creates a new instance of CustomCardAccessor */
    public CustomCardAccessor(CardAccessor ca) throws Exception {
        this.ca = ca;
    }

    public boolean authenticateUser( short ID ){
        byte[] externalAuthCommand = new byte[8];
        externalAuthCommand[0] = CLA_AUTH;
        externalAuthCommand[1] = INS_AUTH;

        externalAuthCommand[4] = 2;  // Lc
        externalAuthCommand[5] = (byte)(ID>>8);
        externalAuthCommand[6] = (byte)ID;
        externalAuthCommand[7] = 0x7F;


        try {
            byte[] response = this.exchangeAPDU( externalAuthCommand );
            if(response[response.length-2] != (byte)0x90 || response[response.length-1] != 0x00) return false;
            else return true;
        }catch (Exception e){
            return false;
        }

    }

    /** Modifies the data and calls ca.exchangeAPDU to perform the actual send.
     * The data returned from the smart card is returned by this method within
     * the <CODE>exchangeApdu</CODE> object
     * @param apdu The command APDU to be sent to the smart card
     * @return The response APDU returned from the card. <CODE>null</CODE> if none available.
     * @throws Exception if a communication error or timeout occurred
     */
    public byte[] exchangeAPDU( byte[] sendData ) throws java.io.IOException{
        
        final boolean select = isSelect(sendData);
        
        
        byte[] dataWithChecksum;
        
        if(select) {
            dataWithChecksum = new byte[ sendData.length ];
            System.arraycopy(sendData, 0, dataWithChecksum, 0, sendData.length);
        }
        else {
            // set secure bits in CLA
            sendData[0] |= APDU_SM_MASK_TYPE4;
            
            dataWithChecksum = new byte[ sendData.length + 2];
            System.arraycopy(sendData, 0, dataWithChecksum, 0, sendData.length-1);
            dataWithChecksum[dataWithChecksum.length-1] = sendData[sendData.length-1];
            
            int Lc = dataWithChecksum[4];
            
            short csum = 0;
            for(short n = 5; n<Lc+5; ++n) {
                csum += sendData[n];
            }
            
            dataWithChecksum[Lc+5] = (byte) (csum>>8);
            dataWithChecksum[Lc+6] = (byte) (csum);
            
            dataWithChecksum[4] += 2;  // increase Lc
            
        }
        
        
        if(debug) {
            for(int i=0; i<dataWithChecksum.length;++i) {
                System.out.print(Integer.toHexString(dataWithChecksum[i] & 0x00FF) + " ");
            }
            System.out.println();
        }
        byte[] receiveDataWithChecksum =  ca.exchangeAPDU( dataWithChecksum );
        
        byte[] receiveData;
        
        if(debug) {
            for(int i=0; i<receiveDataWithChecksum.length;++i) {
                System.out.print(Integer.toHexString(receiveDataWithChecksum[i] & 0x00FF) + " ");
            }
            System.out.println();
            System.out.println();
        }
        
        if(!select)  // verify the checksum
        {
            int Le = receiveDataWithChecksum.length - 2;   // 2 bytes reserved for SW
            
            if(debug) {
                System.out.println("Le=" + Le);
            }
            
            short csum1 = 0;
            for(short n = 2; n<Le; ++n) {
                csum1 += receiveDataWithChecksum[n];
            }
            
            short csum2 = (short)
            (
            (receiveDataWithChecksum[receiveDataWithChecksum.length - 2]<<8)
            |
            (receiveDataWithChecksum[receiveDataWithChecksum.length - 1] & 0x00FF)
            );
            
            if(debug) {
                
                System.out.println("csum1=" + csum1);
                System.out.println("csum2=" + csum2);
            }
            
            if(csum1 != csum2) throw new java.io.IOException(msg.getString("msg01"));
            
            receiveData = new byte[receiveDataWithChecksum.length-2];
            System.arraycopy(receiveDataWithChecksum, 0, receiveData, 0, receiveData.length);
            
        }
        else {
            receiveData = new byte[receiveDataWithChecksum.length];
            System.arraycopy(receiveDataWithChecksum, 0, receiveData, 0, receiveData.length);
            
        }
        
        if(debug) {
            for(int i=0; i<receiveData.length;++i) {
                System.out.print(Integer.toHexString(receiveData[i] & 0x00FF) + " ");
            }
            System.out.println();
            System.out.println();
        }
        
        return receiveData;
    }

    private boolean isSelect(byte[] buffer) {
        if(buffer.length < 2) return false;

        if((buffer[0]&APDU_CMD_MASK)==CLA_ISO7816 && buffer[1]==INS_SELECT) {
            if(debug) {
                System.out.println(msg.getString("msg02"));
            }
            return true;
        }
        else {
            return false;
        }
    }

    public void closeCard() throws Exception{
        ca.closeCard();
    }
}