Blame src/towitoko/atr.c

Packit Service aee942
/*
Packit Service aee942
    atr.c
Packit Service aee942
    ISO 7816 ICC's answer to reset abstract data type implementation
Packit Service aee942
Packit Service aee942
    This file is part of the Unix driver for Towitoko smartcard readers
Packit Service aee942
    Copyright (C) 2000 Carlos Prados <cprados@yahoo.com>
Packit Service aee942
Packit Service aee942
    This library is free software; you can redistribute it and/or
Packit Service aee942
    modify it under the terms of the GNU Lesser General Public
Packit Service aee942
    License as published by the Free Software Foundation; either
Packit Service aee942
    version 2 of the License, or (at your option) any later version.
Packit Service aee942
Packit Service aee942
    This library is distributed in the hope that it will be useful,
Packit Service aee942
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service aee942
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service aee942
    Lesser General Public License for more details.
Packit Service aee942
Packit Service aee942
	You should have received a copy of the GNU Lesser General Public License
Packit Service aee942
	along with this library; if not, write to the Free Software Foundation,
Packit Service aee942
	Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Packit Service aee942
*/
Packit Service aee942
Packit Service aee942
#include <config.h>
Packit Service aee942
Packit Service aee942
#include "atr.h"
Packit Service aee942
#ifdef HAVE_STRING_H
Packit Service aee942
#include <string.h>
Packit Service aee942
#endif
Packit Service aee942
#include "debug.h"
Packit Service aee942
Packit Service aee942
/*
Packit Service aee942
 * Not exported variables definition
Packit Service aee942
 */
Packit Service aee942
Packit Service aee942
static unsigned
Packit Service aee942
atr_num_ib_table[16] =
Packit Service aee942
{
Packit Service aee942
  0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
Packit Service aee942
};
Packit Service aee942
Packit Service aee942
/*
Packit Service aee942
 * Exported variables definition
Packit Service aee942
 */
Packit Service aee942
Packit Service aee942
static unsigned
Packit Service aee942
atr_f_table[16] =
Packit Service aee942
{
Packit Service aee942
  372, 372, 558, 744, 1116, 1488, 1860, 0, 0, 512, 768, 1024, 1536, 2048, 0, 0
Packit Service aee942
};
Packit Service aee942
Packit Service aee942
static unsigned
Packit Service aee942
atr_d_table[16] =
Packit Service aee942
{
Packit Service aee942
  0, 1, 2, 4, 8, 16, 32, 64, 12, 20, 0, 0, 0, 0, 0, 0
Packit Service aee942
};
Packit Service aee942
Packit Service aee942
static unsigned
Packit Service aee942
atr_i_table[4] =
Packit Service aee942
{
Packit Service aee942
  25, 50, 100, 0
Packit Service aee942
};
Packit Service aee942
Packit Service aee942
/*
Packit Service aee942
 * Exported functions definition
Packit Service aee942
 */
Packit Service aee942
Packit Service aee942
int
Packit Service aee942
ATR_InitFromArray (ATR_t * atr, const BYTE atr_buffer[ATR_MAX_SIZE], unsigned length)
Packit Service aee942
{
Packit Service aee942
  BYTE TDi;
Packit Service aee942
  unsigned pointer = 0, pn = 0;
Packit Service aee942
Packit Service aee942
  /* Check size of buffer */
Packit Service aee942
  if (length < 2)
Packit Service aee942
    return (ATR_MALFORMED);
Packit Service aee942
Packit Service aee942
  /* Store T0 and TS */
Packit Service aee942
  atr->TS = atr_buffer[0];
Packit Service aee942
Packit Service aee942
  atr->T0 = TDi = atr_buffer[1];
Packit Service aee942
  pointer = 1;
Packit Service aee942
Packit Service aee942
  /* Store number of historical bytes */
Packit Service aee942
  atr->hbn = TDi & 0x0F;
Packit Service aee942
Packit Service aee942
  /* TCK is not present by default */
Packit Service aee942
  (atr->TCK).present = FALSE;
Packit Service aee942
Packit Service aee942
  /* Extract interface bytes */
Packit Service aee942
  while (pointer < length)
Packit Service aee942
    {
Packit Service aee942
      /* Check buffer is long enought */
Packit Service aee942
      if (pointer + atr_num_ib_table[(0xF0 & TDi) >> 4] >= length)
Packit Service aee942
	{
Packit Service aee942
	  return (ATR_MALFORMED);
Packit Service aee942
	}
Packit Service aee942
      /* Check TAi is present */
Packit Service aee942
      if ((TDi | 0xEF) == 0xFF)
Packit Service aee942
	{
Packit Service aee942
	  pointer++;
Packit Service aee942
	  atr->ib[pn][ATR_INTERFACE_BYTE_TA].value = atr_buffer[pointer];
Packit Service aee942
	  atr->ib[pn][ATR_INTERFACE_BYTE_TA].present = TRUE;
Packit Service aee942
	}
Packit Service aee942
      else
Packit Service aee942
	atr->ib[pn][ATR_INTERFACE_BYTE_TA].present = FALSE;
Packit Service aee942
      /* Check TBi is present */
Packit Service aee942
      if ((TDi | 0xDF) == 0xFF)
Packit Service aee942
	{
Packit Service aee942
	  pointer++;
Packit Service aee942
	  atr->ib[pn][ATR_INTERFACE_BYTE_TB].value = atr_buffer[pointer];
Packit Service aee942
	  atr->ib[pn][ATR_INTERFACE_BYTE_TB].present = TRUE;
Packit Service aee942
	}
Packit Service aee942
      else
Packit Service aee942
	atr->ib[pn][ATR_INTERFACE_BYTE_TB].present = FALSE;
Packit Service aee942
Packit Service aee942
      /* Check TCi is present */
Packit Service aee942
      if ((TDi | 0xBF) == 0xFF)
Packit Service aee942
	{
Packit Service aee942
	  pointer++;
Packit Service aee942
	  atr->ib[pn][ATR_INTERFACE_BYTE_TC].value = atr_buffer[pointer];
Packit Service aee942
	  atr->ib[pn][ATR_INTERFACE_BYTE_TC].present = TRUE;
Packit Service aee942
	}
Packit Service aee942
      else
Packit Service aee942
	atr->ib[pn][ATR_INTERFACE_BYTE_TC].present = FALSE;
Packit Service aee942
Packit Service aee942
      /* Read TDi if present */
Packit Service aee942
      if ((TDi | 0x7F) == 0xFF)
Packit Service aee942
	{
Packit Service aee942
	  pointer++;
Packit Service aee942
	  TDi = atr->ib[pn][ATR_INTERFACE_BYTE_TD].value = atr_buffer[pointer];
Packit Service aee942
	  atr->ib[pn][ATR_INTERFACE_BYTE_TD].present = TRUE;
Packit Service aee942
	  (atr->TCK).present = ((TDi & 0x0F) != ATR_PROTOCOL_TYPE_T0);
Packit Service aee942
	  pn++;
Packit Service aee942
	  if (pn >= ATR_MAX_PROTOCOLS)
Packit Service aee942
	    return (ATR_MALFORMED);
Packit Service aee942
	}
Packit Service aee942
      else
Packit Service aee942
	{
Packit Service aee942
	  atr->ib[pn][ATR_INTERFACE_BYTE_TD].present = FALSE;
Packit Service aee942
	  break;
Packit Service aee942
	}
Packit Service aee942
    }
Packit Service aee942
Packit Service aee942
  /* Store number of protocols */
Packit Service aee942
  atr->pn = pn + 1;
Packit Service aee942
Packit Service aee942
  /* Store historical bytes */
Packit Service aee942
  if (pointer + atr->hbn >= length)
Packit Service aee942
    return (ATR_MALFORMED);
Packit Service aee942
Packit Service aee942
  memcpy (atr->hb, atr_buffer + pointer + 1, atr->hbn);
Packit Service aee942
  pointer += (atr->hbn);
Packit Service aee942
Packit Service aee942
  /* Store TCK  */
Packit Service aee942
  if ((atr->TCK).present)
Packit Service aee942
    {
Packit Service aee942
Packit Service aee942
      if (pointer + 1 >= length)
Packit Service aee942
	return (ATR_MALFORMED);
Packit Service aee942
Packit Service aee942
      pointer++;
Packit Service aee942
Packit Service aee942
      (atr->TCK).value = atr_buffer[pointer];
Packit Service aee942
    }
Packit Service aee942
Packit Service aee942
  atr->length = pointer + 1;
Packit Service aee942
  return (ATR_OK);
Packit Service aee942
}
Packit Service aee942
Packit Service aee942
int
Packit Service aee942
ATR_GetConvention (ATR_t * atr, int *convention)
Packit Service aee942
{
Packit Service aee942
  if (atr->TS == 0x3B)
Packit Service aee942
    (*convention) = ATR_CONVENTION_DIRECT;
Packit Service aee942
  else if (atr->TS == 0x3F)
Packit Service aee942
    (*convention) = ATR_CONVENTION_INVERSE;
Packit Service aee942
  else
Packit Service aee942
    return (ATR_MALFORMED);
Packit Service aee942
  return (ATR_OK);
Packit Service aee942
}
Packit Service aee942
Packit Service aee942
int
Packit Service aee942
ATR_GetIntegerValue (ATR_t * atr, int name, BYTE * value)
Packit Service aee942
{
Packit Service aee942
  int ret;
Packit Service aee942
Packit Service aee942
  if (name == ATR_INTEGER_VALUE_FI)
Packit Service aee942
    {
Packit Service aee942
      if (atr->ib[0][ATR_INTERFACE_BYTE_TA].present)
Packit Service aee942
	{
Packit Service aee942
	  (*value) = (atr->ib[0][ATR_INTERFACE_BYTE_TA].value & 0xF0) >> 4;
Packit Service aee942
	  ret = ATR_OK;
Packit Service aee942
	}
Packit Service aee942
      else
Packit Service aee942
	ret = ATR_NOT_FOUND;
Packit Service aee942
    }
Packit Service aee942
Packit Service aee942
  else if (name == ATR_INTEGER_VALUE_DI)
Packit Service aee942
    {
Packit Service aee942
      if (atr->ib[0][ATR_INTERFACE_BYTE_TA].present)
Packit Service aee942
	{
Packit Service aee942
	  (*value) = (atr->ib[0][ATR_INTERFACE_BYTE_TA].value & 0x0F);
Packit Service aee942
	  ret = ATR_OK;
Packit Service aee942
	}
Packit Service aee942
      else
Packit Service aee942
	ret = ATR_NOT_FOUND;
Packit Service aee942
    }
Packit Service aee942
Packit Service aee942
  else if (name == ATR_INTEGER_VALUE_II)
Packit Service aee942
    {
Packit Service aee942
      if (atr->ib[0][ATR_INTERFACE_BYTE_TB].present)
Packit Service aee942
	{
Packit Service aee942
	  (*value) = (atr->ib[0][ATR_INTERFACE_BYTE_TB].value & 0x60) >> 5;
Packit Service aee942
	  ret = ATR_OK;
Packit Service aee942
	}
Packit Service aee942
      else
Packit Service aee942
	ret = ATR_NOT_FOUND;
Packit Service aee942
    }
Packit Service aee942
Packit Service aee942
  else if (name == ATR_INTEGER_VALUE_PI1)
Packit Service aee942
    {
Packit Service aee942
      if (atr->ib[0][ATR_INTERFACE_BYTE_TB].present)
Packit Service aee942
	{
Packit Service aee942
	  (*value) = (atr->ib[0][ATR_INTERFACE_BYTE_TB].value & 0x1F);
Packit Service aee942
	  ret = ATR_OK;
Packit Service aee942
	}
Packit Service aee942
      else
Packit Service aee942
	ret = ATR_NOT_FOUND;
Packit Service aee942
    }
Packit Service aee942
Packit Service aee942
  else if (name == ATR_INTEGER_VALUE_PI2)
Packit Service aee942
    {
Packit Service aee942
      if (atr->ib[1][ATR_INTERFACE_BYTE_TB].present)
Packit Service aee942
	{
Packit Service aee942
	  (*value) = atr->ib[1][ATR_INTERFACE_BYTE_TB].value;
Packit Service aee942
	  ret = ATR_OK;
Packit Service aee942
	}
Packit Service aee942
      else
Packit Service aee942
	ret = ATR_NOT_FOUND;
Packit Service aee942
    }
Packit Service aee942
Packit Service aee942
  else if (name == ATR_INTEGER_VALUE_N)
Packit Service aee942
    {
Packit Service aee942
      if (atr->ib[0][ATR_INTERFACE_BYTE_TC].present)
Packit Service aee942
	{
Packit Service aee942
	  (*value) = atr->ib[0][ATR_INTERFACE_BYTE_TC].value;
Packit Service aee942
	  ret = ATR_OK;
Packit Service aee942
	}
Packit Service aee942
      else
Packit Service aee942
	ret = ATR_NOT_FOUND;
Packit Service aee942
    }
Packit Service aee942
  else
Packit Service aee942
    ret = ATR_NOT_FOUND;
Packit Service aee942
Packit Service aee942
  return ret;
Packit Service aee942
}
Packit Service aee942
Packit Service aee942
int
Packit Service aee942
ATR_GetParameter (ATR_t * atr, int name, double *parameter)
Packit Service aee942
{
Packit Service aee942
  BYTE FI, DI, II, PI1, PI2, N;
Packit Service aee942
Packit Service aee942
  if (name == ATR_PARAMETER_F)
Packit Service aee942
    {
Packit Service aee942
      if (ATR_GetIntegerValue (atr, ATR_INTEGER_VALUE_FI, &FI) == ATR_OK)
Packit Service aee942
	(*parameter) = (double) (atr_f_table[FI]);
Packit Service aee942
      else
Packit Service aee942
	(*parameter) = (double) ATR_DEFAULT_F;
Packit Service aee942
      return (ATR_OK);
Packit Service aee942
    }
Packit Service aee942
Packit Service aee942
  else if (name == ATR_PARAMETER_D)
Packit Service aee942
    {
Packit Service aee942
      if (ATR_GetIntegerValue (atr, ATR_INTEGER_VALUE_DI, &DI) == ATR_OK)
Packit Service aee942
	(*parameter) = (double) (atr_d_table[DI]);
Packit Service aee942
      else
Packit Service aee942
	(*parameter) = (double) ATR_DEFAULT_D;
Packit Service aee942
      return (ATR_OK);
Packit Service aee942
    }
Packit Service aee942
Packit Service aee942
  else if (name == ATR_PARAMETER_I)
Packit Service aee942
    {
Packit Service aee942
      if (ATR_GetIntegerValue (atr, ATR_INTEGER_VALUE_II, &II) == ATR_OK)
Packit Service aee942
	(*parameter) = (double) (atr_i_table[II]);
Packit Service aee942
      else
Packit Service aee942
	(*parameter) = ATR_DEFAULT_I;
Packit Service aee942
      return (ATR_OK);
Packit Service aee942
    }
Packit Service aee942
Packit Service aee942
  else if (name == ATR_PARAMETER_P)
Packit Service aee942
    {
Packit Service aee942
      if (ATR_GetIntegerValue (atr, ATR_INTEGER_VALUE_PI2, &PI2) == ATR_OK)
Packit Service aee942
	(*parameter) = (double) PI2;
Packit Service aee942
      else if (ATR_GetIntegerValue (atr, ATR_INTEGER_VALUE_PI1, &PI1) == ATR_OK)
Packit Service aee942
	(*parameter) = (double) PI1;
Packit Service aee942
      else
Packit Service aee942
	(*parameter) = (double) ATR_DEFAULT_P;
Packit Service aee942
      return (ATR_OK);
Packit Service aee942
    }
Packit Service aee942
Packit Service aee942
  else if (name == ATR_PARAMETER_N)
Packit Service aee942
    {
Packit Service aee942
      if (ATR_GetIntegerValue (atr, ATR_INTEGER_VALUE_N, &N) == ATR_OK)
Packit Service aee942
	(*parameter) = (double) N;
Packit Service aee942
      else
Packit Service aee942
	(*parameter) = (double) ATR_DEFAULT_N;
Packit Service aee942
      return (ATR_OK);
Packit Service aee942
    }
Packit Service aee942
Packit Service aee942
  return (ATR_NOT_FOUND);
Packit Service aee942
}
Packit Service aee942
Packit Service aee942
/*
Packit Service aee942
 * This function was greatly inspired by ATRDecodeAtr() and
Packit Service aee942
 * PHGetDefaultProtocol() from pcsc-lite
Packit Service aee942
 *
Packit Service aee942
 * It was rewritten by Ludovic Rousseau, 2004
Packit Service aee942
 */
Packit Service aee942
#define PROTOCOL_UNSET -1
Packit Service aee942
int ATR_GetDefaultProtocol(ATR_t * atr, int *protocol, int *availableProtocols)
Packit Service aee942
{
Packit Service aee942
	int i;
Packit Service aee942
Packit Service aee942
	/* default value */
Packit Service aee942
	*protocol = PROTOCOL_UNSET;
Packit Service aee942
	if (availableProtocols)
Packit Service aee942
		*availableProtocols = 0;
Packit Service aee942
Packit Service aee942
	for (i=0; i
Packit Service aee942
		if (atr->ib[i][ATR_INTERFACE_BYTE_TD].present)
Packit Service aee942
		{
Packit Service aee942
			int T = atr->ib[i][ATR_INTERFACE_BYTE_TD].value & 0x0F;
Packit Service aee942
Packit Service aee942
			DEBUG_COMM2("T=%d Protocol Found", T);
Packit Service aee942
			if (availableProtocols)
Packit Service aee942
				*availableProtocols |= 1 << T;
Packit Service aee942
Packit Service aee942
			if (PROTOCOL_UNSET == *protocol)
Packit Service aee942
			{
Packit Service aee942
				/* set to the first protocol byte found */
Packit Service aee942
				*protocol = T;
Packit Service aee942
				DEBUG_COMM2("default protocol: T=%d", *protocol);
Packit Service aee942
			}
Packit Service aee942
		}
Packit Service aee942
Packit Service aee942
	/* specific mode if TA2 present */
Packit Service aee942
	if (atr->ib[1][ATR_INTERFACE_BYTE_TA].present)
Packit Service aee942
	{
Packit Service aee942
		*protocol = atr->ib[1][ATR_INTERFACE_BYTE_TA].value & 0x0F;
Packit Service aee942
		if (availableProtocols)
Packit Service aee942
			*availableProtocols = 1 << *protocol;
Packit Service aee942
		DEBUG_COMM2("specific mode found: T=%d", *protocol);
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	if (PROTOCOL_UNSET == *protocol)
Packit Service aee942
	{
Packit Service aee942
		DEBUG_INFO1("no default protocol found in ATR. Using T=0");
Packit Service aee942
		*protocol = ATR_PROTOCOL_TYPE_T0;
Packit Service aee942
		if (availableProtocols)
Packit Service aee942
			*availableProtocols = 1 << *protocol;
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	return ATR_OK;
Packit Service aee942
}
Packit Service aee942