Blame src/towitoko/pps.c

Packit 9f0df5
/*
Packit 9f0df5
    pps.c
Packit 9f0df5
    Protocol Parameters Selection
Packit 9f0df5
Packit 9f0df5
    This file is part of the Unix driver for Towitoko smartcard readers
Packit 9f0df5
    Copyright (C) 2000 2001 Carlos Prados <cprados@yahoo.com>
Packit 9f0df5
Packit 9f0df5
    This library is free software; you can redistribute it and/or
Packit 9f0df5
    modify it under the terms of the GNU Lesser General Public
Packit 9f0df5
    License as published by the Free Software Foundation; either
Packit 9f0df5
    version 2 of the License, or (at your option) any later version.
Packit 9f0df5
Packit 9f0df5
    This library is distributed in the hope that it will be useful,
Packit 9f0df5
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 9f0df5
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 9f0df5
    Lesser General Public License for more details.
Packit 9f0df5
Packit 9f0df5
	You should have received a copy of the GNU Lesser General Public License
Packit 9f0df5
	along with this library; if not, write to the Free Software Foundation,
Packit 9f0df5
	Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Packit 9f0df5
*/
Packit 9f0df5
Packit 9f0df5
#include "pps.h"
Packit 9f0df5
#include "atr.h"
Packit 9f0df5
#ifdef HAVE_STDLIB_H
Packit 9f0df5
#include <stdlib.h>
Packit 9f0df5
#endif
Packit 9f0df5
#ifdef HAVE_STRING_H
Packit 9f0df5
#include <string.h>
Packit 9f0df5
#endif
Packit 9f0df5
#include <ifdhandler.h>
Packit 9f0df5
Packit 9f0df5
#include "commands.h"
Packit 9f0df5
#include "defs.h"
Packit 9f0df5
#include "debug.h"
Packit 9f0df5
Packit 9f0df5
/*
Packit 9f0df5
 * Not exported funtions declaration
Packit 9f0df5
 */
Packit 9f0df5
Packit 9f0df5
static bool PPS_Match (BYTE * request, unsigned len_request, BYTE * reply, unsigned len_reply);
Packit 9f0df5
Packit 9f0df5
static unsigned PPS_GetLength (BYTE * block);
Packit 9f0df5
Packit 9f0df5
static BYTE PPS_GetPCK (BYTE * block, unsigned length);
Packit 9f0df5
Packit 9f0df5
int
Packit 9f0df5
PPS_Exchange (int lun, BYTE * params, unsigned *length, unsigned char *pps1)
Packit 9f0df5
{
Packit 9f0df5
  BYTE confirm[PPS_MAX_LENGTH];
Packit 9f0df5
  unsigned len_request, len_confirm;
Packit 9f0df5
  int ret;
Packit 9f0df5
Packit 9f0df5
  len_request = PPS_GetLength (params);
Packit 9f0df5
  params[len_request - 1] = PPS_GetPCK(params, len_request - 1);
Packit 9f0df5
Packit 9f0df5
  DEBUG_XXD ("PPS: Sending request: ", params, len_request);
Packit 9f0df5
Packit 9f0df5
  /* Send PPS request */
Packit 9f0df5
  if (CCID_Transmit (lun, len_request, params, isCharLevel(lun) ? 4 : 0, 0)
Packit 9f0df5
	!= IFD_SUCCESS)
Packit 9f0df5
    return PPS_ICC_ERROR;
Packit 9f0df5
Packit 9f0df5
  /* Get PPS confirm */
Packit 9f0df5
  len_confirm = sizeof(confirm);
Packit 9f0df5
  if (CCID_Receive (lun, &len_confirm, confirm, NULL) != IFD_SUCCESS)
Packit 9f0df5
    return PPS_ICC_ERROR;
Packit 9f0df5
Packit 9f0df5
  DEBUG_XXD ("PPS: Receiving confirm: ", confirm, len_confirm);
Packit 9f0df5
Packit 9f0df5
  if (!PPS_Match (params, len_request, confirm, len_confirm))
Packit 9f0df5
    ret = PPS_HANDSAKE_ERROR;
Packit 9f0df5
  else
Packit 9f0df5
    ret = PPS_OK;
Packit 9f0df5
Packit 9f0df5
  *pps1 = 0x11;	/* default TA1 */
Packit 9f0df5
Packit 9f0df5
  /* if PPS1 is echoed */
Packit 9f0df5
  if (PPS_HAS_PPS1 (params) && PPS_HAS_PPS1 (confirm))
Packit 9f0df5
      *pps1 = confirm[2];
Packit 9f0df5
Packit 9f0df5
  /* Copy PPS handsake */
Packit 9f0df5
  memcpy (params, confirm, len_confirm);
Packit 9f0df5
  (*length) = len_confirm;
Packit 9f0df5
Packit 9f0df5
  return ret;
Packit 9f0df5
}
Packit 9f0df5
Packit 9f0df5
static bool
Packit 9f0df5
PPS_Match (BYTE * request, unsigned len_request, BYTE * confirm, unsigned len_confirm)
Packit 9f0df5
{
Packit 9f0df5
  /* See if the reply differs from request */
Packit 9f0df5
  if ((len_request == len_confirm) &&	/* same length */
Packit 9f0df5
      memcmp (request, confirm, len_request))	/* different contents */
Packit 9f0df5
	return FALSE;
Packit 9f0df5
Packit 9f0df5
  if (len_request < len_confirm)	/* confirm longer than request */
Packit 9f0df5
    return FALSE;
Packit 9f0df5
Packit 9f0df5
  /* See if the card specifies other than default FI and D */
Packit 9f0df5
  if ((PPS_HAS_PPS1 (confirm)) && (confirm[2] != request[2]))
Packit 9f0df5
    return FALSE;
Packit 9f0df5
Packit 9f0df5
  return TRUE;
Packit 9f0df5
}
Packit 9f0df5
Packit 9f0df5
static unsigned
Packit 9f0df5
PPS_GetLength (BYTE * block)
Packit 9f0df5
{
Packit 9f0df5
  unsigned length = 3;
Packit 9f0df5
Packit 9f0df5
  if (PPS_HAS_PPS1 (block))
Packit 9f0df5
    length++;
Packit 9f0df5
Packit 9f0df5
  if (PPS_HAS_PPS2 (block))
Packit 9f0df5
    length++;
Packit 9f0df5
Packit 9f0df5
  if (PPS_HAS_PPS3 (block))
Packit 9f0df5
    length++;
Packit 9f0df5
Packit 9f0df5
  return length;
Packit 9f0df5
}
Packit 9f0df5
Packit 9f0df5
static BYTE
Packit 9f0df5
PPS_GetPCK (BYTE * block, unsigned length)
Packit 9f0df5
{
Packit 9f0df5
  BYTE pck;
Packit 9f0df5
  unsigned i;
Packit 9f0df5
Packit 9f0df5
  pck = block[0];
Packit 9f0df5
  for (i = 1; i < length; i++)
Packit 9f0df5
    pck ^= block[i];
Packit 9f0df5
Packit 9f0df5
  return pck;
Packit 9f0df5
}
Packit 9f0df5