#include "pps.h"
#include "atr.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ifdhandler.h>
#include "commands.h"
#include "defs.h"
#include "debug.h"
static bool PPS_Match (BYTE * request, unsigned len_request, BYTE * reply, unsigned len_reply);
static unsigned PPS_GetLength (BYTE * block);
static BYTE PPS_GetPCK (BYTE * block, unsigned length);
int
PPS_Exchange (int lun, BYTE * params, unsigned *length, unsigned char *pps1)
{
BYTE confirm[PPS_MAX_LENGTH];
unsigned len_request, len_confirm;
int ret;
len_request = PPS_GetLength (params);
params[len_request - 1] = PPS_GetPCK(params, len_request - 1);
DEBUG_XXD ("PPS: Sending request: ", params, len_request);
if (CCID_Transmit (lun, len_request, params, isCharLevel(lun) ? 4 : 0, 0)
!= IFD_SUCCESS)
return PPS_ICC_ERROR;
len_confirm = sizeof(confirm);
if (CCID_Receive (lun, &len_confirm, confirm, NULL) != IFD_SUCCESS)
return PPS_ICC_ERROR;
DEBUG_XXD ("PPS: Receiving confirm: ", confirm, len_confirm);
if (!PPS_Match (params, len_request, confirm, len_confirm))
ret = PPS_HANDSAKE_ERROR;
else
ret = PPS_OK;
*pps1 = 0x11;
if (PPS_HAS_PPS1 (params) && PPS_HAS_PPS1 (confirm))
*pps1 = confirm[2];
memcpy (params, confirm, len_confirm);
(*length) = len_confirm;
return ret;
}
static bool
PPS_Match (BYTE * request, unsigned len_request, BYTE * confirm, unsigned len_confirm)
{
if ((len_request == len_confirm) &&
memcmp (request, confirm, len_request))
return FALSE;
if (len_request < len_confirm)
return FALSE;
if ((PPS_HAS_PPS1 (confirm)) && (confirm[2] != request[2]))
return FALSE;
return TRUE;
}
static unsigned
PPS_GetLength (BYTE * block)
{
unsigned length = 3;
if (PPS_HAS_PPS1 (block))
length++;
if (PPS_HAS_PPS2 (block))
length++;
if (PPS_HAS_PPS3 (block))
length++;
return length;
}
static BYTE
PPS_GetPCK (BYTE * block, unsigned length)
{
BYTE pck;
unsigned i;
pck = block[0];
for (i = 1; i < length; i++)
pck ^= block[i];
return pck;
}