1/* 2 pps.c 3 Protocol Parameters Selection 4 5 This file is part of the Unix driver for Towitoko smartcard readers 6 Copyright (C) 2000 2001 Carlos Prados <cprados@yahoo.com> 7 8 This library is free software; you can redistribute it and/or 9 modify it under the terms of the GNU Lesser General Public 10 License as published by the Free Software Foundation; either 11 version 2 of the License, or (at your option) any later version. 12 13 This library is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 Lesser General Public License for more details. 17 18 You should have received a copy of the GNU Lesser General Public License 19 along with this library; if not, write to the Free Software Foundation, 20 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 21*/ 22 23#include "pps.h" 24#include "atr.h" 25#include <stdlib.h> 26#include <stdio.h> 27#include <string.h> 28#include <ifdhandler.h> 29 30#include "commands.h" 31#include "defs.h" 32#include "debug.h" 33 34/* 35 * Not exported funtions declaration 36 */ 37 38static bool PPS_Match (BYTE * request, unsigned len_request, BYTE * reply, unsigned len_reply); 39 40static unsigned PPS_GetLength (BYTE * block); 41 42static BYTE PPS_GetPCK (BYTE * block, unsigned length); 43 44int 45PPS_Exchange (int lun, BYTE * params, unsigned *length, unsigned char *pps1) 46{ 47 BYTE confirm[PPS_MAX_LENGTH]; 48 unsigned len_request, len_confirm; 49 int ret; 50 51 len_request = PPS_GetLength (params); 52 params[len_request - 1] = PPS_GetPCK(params, len_request - 1); 53 54 DEBUG_XXD ("PPS: Sending request: ", params, len_request); 55 56 /* Send PPS request */ 57 if (CCID_Transmit (lun, len_request, params, isCharLevel(lun) ? 4 : 0, 0) 58 != IFD_SUCCESS) 59 return PPS_ICC_ERROR; 60 61 /* Get PPS confirm */ 62 len_confirm = sizeof(confirm); 63 if (CCID_Receive (lun, &len_confirm, confirm, NULL) != IFD_SUCCESS) 64 return PPS_ICC_ERROR; 65 66 DEBUG_XXD ("PPS: Receiving confirm: ", confirm, len_confirm); 67 68 if (!PPS_Match (params, len_request, confirm, len_confirm)) 69 ret = PPS_HANDSAKE_ERROR; 70 else 71 ret = PPS_OK; 72 73 *pps1 = 0x11; /* default TA1 */ 74 75 /* if PPS1 is echoed */ 76 if (PPS_HAS_PPS1 (params) && PPS_HAS_PPS1 (confirm)) 77 *pps1 = confirm[2]; 78 79 /* Copy PPS handsake */ 80 memcpy (params, confirm, len_confirm); 81 (*length) = len_confirm; 82 83 return ret; 84} 85 86static bool 87PPS_Match (BYTE * request, unsigned len_request, BYTE * confirm, unsigned len_confirm) 88{ 89 /* See if the reply differs from request */ 90 if ((len_request == len_confirm) && /* same length */ 91 memcmp (request, confirm, len_request)) /* different contents */ 92 return FALSE; 93 94 if (len_request < len_confirm) /* confirm longer than request */ 95 return FALSE; 96 97 /* See if the card specifies other than default FI and D */ 98 if ((PPS_HAS_PPS1 (confirm)) && (confirm[2] != request[2])) 99 return FALSE; 100 101 return TRUE; 102} 103 104static unsigned 105PPS_GetLength (BYTE * block) 106{ 107 unsigned length = 3; 108 109 if (PPS_HAS_PPS1 (block)) 110 length++; 111 112 if (PPS_HAS_PPS2 (block)) 113 length++; 114 115 if (PPS_HAS_PPS3 (block)) 116 length++; 117 118 return length; 119} 120 121static BYTE 122PPS_GetPCK (BYTE * block, unsigned length) 123{ 124 BYTE pck; 125 unsigned i; 126 127 pck = block[0]; 128 for (i = 1; i < length; i++) 129 pck ^= block[i]; 130 131 return pck; 132} 133 134