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

📄 ctapi.c

📁 SOSSE,最简单的实现smart卡的教学用程序 内有电路图
💻 C
字号:
/*	Simple Operating System for Smartcard Education	Copyright (C) 2002  Matthias Bruestle <m@mbsks.franken.de>	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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*//*! @file	\brief Virtual CT-API library.	$Id: ctapi.c,v 1.4 2002/12/24 13:29:57 m Exp $*/#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <ctapi.h>#include <main.h>#include <types.h>#include <sw.h>IS32	cthandle=-1;int		fd_fromCard[2], fd_toCard[2];pid_t	pidVirtuaCard=0;int		loadEepromFile=FALSE;int		saveEepromFile=FALSE;char	eepromFile[256];int		fdEepromFile;char	atr[32];int		atrlen=0;IS8 CT_forkIcc( void ){	IS8 rv;	int i, next, toread, n;	if( (rv=CT_stopIcc())!=CTAPI_RV_OK )		return rv;	if( (pipe(fd_fromCard)<0) || (pipe(fd_toCard)<0) )		return CTAPI_RV_ERR_MEMORY;	if( (pidVirtuaCard=fork()) < 0 ) {		return CTAPI_RV_ERR_MEMORY;	} else if( pidVirtuaCard>0 ) {		/* parent */		close( fd_fromCard[1] );	} else {		/* child */		close( fd_toCard[1] );		sosse_main();		exit( 0 );	}	// Read ATR	i=0;	if( read( fd_fromCard[0], atr+i, 1 )!=1 ) {		CT_stopIcc();		return CTAPI_RV_ERR_TRANS;	}	i++;	if( read( fd_fromCard[0], atr+i, 1 )!=1 ) {		CT_stopIcc();		return CTAPI_RV_ERR_TRANS;	}	i++;	do {		next=atr[i-1]>>7;		toread=((atr[i-1]>>7)&0x01)+((atr[i-1]>>6)&0x01)+((atr[i-1]>>5)&0x01)+			((atr[i-1]>>4)&0x01);		for( n=0; n<toread; n++ ) {			if( read( fd_fromCard[0], atr+i+n, 1 )!=1 ) {				CT_stopIcc();				return CTAPI_RV_ERR_TRANS;			}		}		i+=toread;	} while( next );	for( n=0; n<(atr[1]&0xF); n++ ) {		if( read( fd_fromCard[0], atr+i+n, 1 )!=1 ) {			CT_stopIcc();			return CTAPI_RV_ERR_TRANS;		}	}	i+=atr[1]&0xF;	atrlen=i;	return CTAPI_RV_OK;}IS8 CT_stopIcc( void ){	if( pidVirtuaCard ) {		close( fd_toCard[1] );		// TODO: Wait for VirtuaCard process to terminate.		pidVirtuaCard=0;	}	return CTAPI_RV_OK;}IS8 CT_ifdCmdResetCT( IU16 lenc, IU8 *command, IU16 *lenr, IU8 *response ){	if( command[2]>1 ) {		response[0]=0x6A;		response[1]=0x00;		*lenr=2;	}	if( command[2] ) {		if( CT_forkIcc()!=CTAPI_RV_OK ) {			response[0]=0x64;			response[1]=0x00;			*lenr=2;		}		if( command[3]&1 ) {			// TODO: Check lenr			memcpy( response, atr, atrlen );			response[atrlen+1]=0x90;			response[atrlen+2]=0x00;			*lenr=atrlen+2;		} else {			response[0]=0x90;			response[1]=0x00;			*lenr=2;		}	} else {		CT_stopIcc();		response[0]=0x90;		response[1]=0x00;		*lenr=2;	}	return CTAPI_RV_OK;}IS8 CT_ifdCmdRequestICC( IU16 lenc, IU8 *command, IU16 *lenr, IU8 *response ){	if( command[2]!=1 ) {		response[0]=0x6A;		response[1]=0x00;		*lenr=2;	}	if( CT_forkIcc()!=CTAPI_RV_OK ) {		response[0]=0x64;		response[1]=0x00;		*lenr=2;	}	if( command[3]&1 ) {		// TODO: Check lenr		memcpy( response, atr, atrlen );		response[atrlen+0]=0x90;		response[atrlen+1]=0x00;		*lenr=atrlen+2;	} else {		response[0]=0x90;		response[1]=0x00;		*lenr=2;	}	return CTAPI_RV_OK;}IS8 CT_ifdCmdGetStatus( IU16 lenc, IU8 *command, IU16 *lenr, IU8 *response ){	response[0]=0x90;	response[1]=0x00;	*lenr=2;	if( command[3]==0x80 ) {		response[0]=0x80;		response[1]=0x01;		response[2]=0x01;		if( pidVirtuaCard ) response[2]=0x05;		response[3]=0x90;		response[4]=0x00;		*lenr=5;	}	return CTAPI_RV_OK;}IS8 CT_ifdCmdEjectICC( IU16 lenc, IU8 *command, IU16 *lenr, IU8 *response ){	if( command[2]==1 ) {		response[0]=0x90;		response[1]=0x00;		*lenr=2;		return CT_stopIcc();	}	response[0]=0x6A;	response[1]=0x00;	*lenr=2;	return CTAPI_RV_OK;}/*! \brief Parses EEPROM FILE command.	- CLA: '20'	- INS: 'E0'	- P1:		- bit 1: Save EEPROM to file at eject or reset.		- bit 2: Load EEPROM from file at reset.	- P2: RFU	- Lc: Length of file name	- Data: File name (possibly including path) without null-termination*/IS8 CT_ifdCmdEepromFile( IU16 lenc, IU8 *command, IU16 *lenr, IU8 *response ){	if( command[2]==2 )		loadEepromFile=TRUE;	else		loadEepromFile=FALSE;	if( command[2]==1 )		saveEepromFile=TRUE;	else		saveEepromFile=FALSE;	memset( eepromFile, 0, sizeof(eepromFile) );	memcpy( eepromFile, command+5, command[4] );	response[0]=0x90;	response[1]=0x00;	*lenr=2;	return CTAPI_RV_OK;}IS8 CT_ifdCmd( IU16 lenc, IU8 *command, IU16 *lenr, IU8 *response ){	switch( command[1] ) {	case CTAPI_INS_RESET_CT:		return CT_ifdCmdResetCT( lenc, command, lenr, response );	case CTAPI_INS_REQUEST_ICC:		return CT_ifdCmdRequestICC( lenc, command, lenr, response );	case CTAPI_INS_GET_STATUS:		return CT_ifdCmdGetStatus( lenc, command, lenr, response );	case CTAPI_INS_EJECT_ICC:		return CT_ifdCmdEjectICC( lenc, command, lenr, response );	case CTAPI_INS_EEPROM:		return CT_ifdCmdEepromFile( lenc, command, lenr, response );	default:		response[0]=0x6D;		response[1]=0x00;		*lenr=2;	}	return CTAPI_RV_OK;}int CT_t0( IU16 lenc, IU8 *command, IU16 *lenr, IU8 *response ){	char rsp[ 256+2 ];	char ins = command[1];	int	lc=0;	int le=0;	int	rsplen=0;	char byte;	int pointer=0;	int spointer=0;	int cse;	int i;	if( lenc==5 ) {		cse=2;		le=command[4];	} else if( lenc>5 ) {		cse=3;		lc=command[4];	} else {		cse=1;	}	/* Send header */	if( cse==1 ) {		write( fd_toCard[1], command, 4 );		byte=0;		write( fd_toCard[1], &byte, 1 );	} else {		write( fd_toCard[1], command, 5 );	}	while( TRUE ) {		/* Read byte */		if( read( fd_fromCard[0], &byte, 1 )!=1 ) {			return( CTAPI_RV_ERR_TRANS );		}		/* ACK */		if( (byte&0xFE)==(ins&0xFE) ) {			/* Direction: To Card */			if( cse==3 ) {				/* Send data to card */				if( write( fd_toCard[1], command+5+spointer, lc-spointer )!=					lc-spointer ) {					return( CTAPI_RV_ERR_TRANS );				}				continue;			} else			/* Direction: From Card */			if( cse==2 ) {				/* Receive data from card */				for( i=0; i<(le+2-pointer); i++ ) {					if( read( fd_fromCard[0], rsp+pointer+i, 1 )!=1 ) {						return( CTAPI_RV_ERR_TRANS );					}				}				rsplen += le+2-pointer;				/* Don't copy more than requested */				if( rsplen>*lenr ) {					memcpy( response, rsp, *lenr-2 );					memcpy( response+*lenr-2, rsp+rsplen-2, 2 );				} else {					memcpy( response, rsp, rsplen );					*lenr=rsplen;				}				return( CTAPI_RV_OK );			} else {				return( CTAPI_RV_ERR_TRANS );			}		}		/* ~ACK */		if( ((~byte)&0xFE)==(ins&0xFE) ) {			/* Direction: To Card */			if( cse==3 ) {				/* Send data to card */				if( write( fd_toCard[1], command+5+spointer, 1 )!=1 ) {					return CTAPI_RV_ERR_TRANS;				}				spointer++;				continue;			} else			/* Direction: From Card */			if( cse==2 ) {				/* Receive data from card */				if( read( fd_fromCard[0], &byte, 1 )!=1 ) {					return CTAPI_RV_ERR_TRANS;				}				if( (sizeof(rsp)-pointer)>0 ) {					rsp[pointer] = byte;					rsplen++;					pointer++;				}				continue;			} else {				return( CTAPI_RV_ERR_TRANS );			}		}		/* NULL */		if( byte==0x60 ) {			/* Do nothing */			continue;		}		/* SW1 */		if( ((byte&0xF0)==0x60) || ((byte&0xF0)==0x90) ) {			if( (sizeof(rsp)-pointer)>0 ) {				rsp[pointer]=byte;				pointer++;				rsplen++;			}			/* Read SW2 */			if( read( fd_fromCard[0], &byte, 1 )!=1 ) {				return CTAPI_RV_ERR_TRANS;			}			if( (sizeof(rsp)-pointer)>0 ) {				rsp[pointer]=byte;				pointer++;				rsplen++;			}			/* Don't copy more than requested */			if( rsplen>*lenr ) {				memcpy( response, rsp, *lenr-2 );				memcpy( response+*lenr-2, rsp+rsplen-2, 2 );			} else {				memcpy( response, rsp, rsplen );				*lenr=rsplen;			}			return( CTAPI_RV_OK );		}	}	return( CTAPI_RV_ERR_TRANS );}IS8 CT_iccCmd( IU8 *dad, IU8 *sad, IU16 lenc, IU8 *command,	IU16 *lenr, IU8 *response ){	*dad=CTAPI_AD_HOST;	*sad=CTAPI_AD_ICC1;	if( !pidVirtuaCard ) {		*sad=CTAPI_AD_CT;		response[0]=0x6E;		response[1]=0x00;		*lenr=2;		return CTAPI_RV_OK;	}	return CT_t0( lenc, command, lenr, response );}IS8 CT_init( IU16 ctn, IU16 pn ){	if( (cthandle>=0) || (pn!=CTAPI_PORT) ) return CTAPI_RV_ERR_INVALID;	cthandle=ctn;	pidVirtuaCard=0;	return CTAPI_RV_OK;}IS8 CT_data( IU16 ctn, IU8 *dad, IU8 *sad, IU16 lenc, IU8 *command,	IU16 *lenr, IU8 *response ){	if( (cthandle<0) ||		(ctn!=cthandle) ||		(dad==NULL) ||		(sad==NULL) ||		(command==NULL) ||		(lenr==NULL) ||		(response==NULL) ||		(lenc<4) ||		(*lenr<2) ||		(*sad!=CTAPI_AD_HOST) ) return CTAPI_RV_ERR_INVALID;	// TODO: Check for well formed APDUs	switch( *dad ) {	case CTAPI_AD_CT:		*dad = CTAPI_AD_HOST;		*sad = CTAPI_AD_CT;		if( command[0]!=0x20 ) {			response[0]=0x6E;			response[1]=0x00;			*lenr=2;			return CTAPI_RV_OK;		}		return CT_ifdCmd( lenc, command, lenr, response );	case CTAPI_AD_ICC1:		return CT_iccCmd( dad, sad, lenc, command, lenr, response );	default:		return CTAPI_RV_ERR_INVALID;	}}IS8 CT_close( IU16 ctn ){	IS8 rv;	if( (cthandle<0) || (ctn!=cthandle) ) return CTAPI_RV_ERR_INVALID;	cthandle=-1;	if( (rv=CT_stopIcc())!=CTAPI_RV_OK )		return rv;	return CTAPI_RV_OK;}

⌨️ 快捷键说明

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