You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
11999 lines
365 KiB
11999 lines
365 KiB
///////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright 2000 Gemplus Canada Inc.
|
|
//
|
|
// Project:
|
|
// Kenny (GPK CSP)
|
|
//
|
|
// Authors: Laurent CASSIER
|
|
// Jean-Marc ROBERT
|
|
//
|
|
// Modifications: Thierry Tremblay
|
|
// Francois Paradis
|
|
// GPK8000 support, key importation, enhancement for Whistler & debug
|
|
//
|
|
// Compiler:
|
|
// Microsoft Visual C++ 6.0 - SP3
|
|
// Platform SDK - January 2000
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
#ifdef _UNICODE
|
|
#define UNICODE
|
|
#endif
|
|
#include "gpkcsp.h"
|
|
#include <tchar.h>
|
|
#include <process.h>
|
|
|
|
#include <cassert>
|
|
#include <cstdio>
|
|
|
|
#include "resource.h"
|
|
#include "gmem.h"
|
|
#include "compcert.h"
|
|
#include "pincache.h"
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Configuration
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
const int MAX_SLOT = 16;
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Prototypes
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
static void zap_gpk_objects( DWORD SlotNb, BOOL IsPrivate );
|
|
BOOL SCARDPROBLEM( LONG result, WORD sc_status, BYTE offset );
|
|
|
|
#ifdef _DEBUG
|
|
static DWORD dw1, dw2;
|
|
#endif
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Macros & Templates
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
template<class T>
|
|
bool IsNull( const T* p )
|
|
{
|
|
return p == 0;
|
|
}
|
|
|
|
|
|
template<class T>
|
|
bool IsNotNull( const T* p )
|
|
{
|
|
return p != 0;
|
|
}
|
|
|
|
|
|
template<class T>
|
|
bool IsNullStr( const T* p )
|
|
{
|
|
return p == 0 || *p == 0;
|
|
}
|
|
|
|
|
|
template<class T>
|
|
bool IsNotNullStr( const T* p )
|
|
{
|
|
return p != 0 && *p != 0;
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Definitions
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
const char* SYSTEM_DF = "SYSTEM";
|
|
const char* GPK_DF = "GTOK1";
|
|
|
|
const WORD MAX_SES_KEY_EF = 0x01FF;
|
|
const WORD GPK_MF = 0x3F00;
|
|
const WORD GPK_OBJ_PRIV_EF = 0x0002;
|
|
const WORD GPK_OBJ_PUB_EF = 0x0004;
|
|
const WORD GPK_IADF_EF = 0x0005;
|
|
const WORD GPK_PIN_EF = 0x0006;
|
|
const BYTE GPK_FIRST_KEY = 0x07;
|
|
|
|
const BYTE FILE_CHUNK_SIZE = 200;
|
|
|
|
const int REALLOC_SIZE = 50;
|
|
|
|
const int MAX_FIELD = 16;
|
|
extern const DWORD MAX_GPK_OBJ = 100;
|
|
|
|
// Values for a GPK8000 INTL
|
|
const int MAX_GPK_PUBLIC = 4000;
|
|
const int MAX_GPK_PRIVATE = 1600;
|
|
|
|
|
|
const int RC2_40_SIZE = 0x05;
|
|
const int RC2_128_SIZE = 0x10;
|
|
const int DES_SIZE = 0x08;
|
|
const int DES3_112_SIZE = 0x10;
|
|
const int DES3_SIZE = 0x18;
|
|
const int DES_BLOCK_SIZE = 0x08;
|
|
const int RC2_BLOCK_SIZE = 0x08;
|
|
|
|
const BYTE TAG_RSA_PUBLIC = 0x01;
|
|
const BYTE TAG_DSA_PUBLIC = 0x02;
|
|
const BYTE TAG_RSA_PRIVATE = 0x03;
|
|
const BYTE TAG_DSA_PRIVATE = 0x04;
|
|
const BYTE TAG_CERTIFICATE = 0x05;
|
|
const BYTE TAG_DATA = 0x06;
|
|
const BYTE TAG_KEYSET = 0x20;
|
|
|
|
const WORD FLAG_APPLICATION = 0x0001;
|
|
const WORD FLAG_END_DATE = 0x0002;
|
|
const WORD FLAG_ID = 0x0004;
|
|
const WORD FLAG_ISSUER = 0x0008;
|
|
const WORD FLAG_LABEL = 0x0010;
|
|
const WORD FLAG_SERIAL_NUMBER = 0x0020;
|
|
const WORD FLAG_START_DATE = 0x0040;
|
|
const WORD FLAG_SUBJECT = 0x0080;
|
|
const WORD FLAG_VALUE = 0x0100;
|
|
const WORD FLAG_RESERVED = 0x0200; // Not used by CSP
|
|
const WORD FLAG_KEY_TYPE = 0x0400;
|
|
const WORD FLAG_KEYSET = 0x0800;
|
|
const WORD FLAG_SIGN = 0x1000;
|
|
const WORD FLAG_EXCHANGE = 0x2000;
|
|
const WORD FLAG_EXPORT = 0x4000;
|
|
const WORD FLAG_MODIFIABLE = 0x8000;
|
|
|
|
enum
|
|
{
|
|
POS_APPLICATION = 0,
|
|
POS_END_DATE,
|
|
POS_ID,
|
|
POS_ISSUER,
|
|
POS_LABEL,
|
|
POS_SERIAL_NUMBER,
|
|
POS_START_DATE,
|
|
POS_SUBJECT,
|
|
POS_VALUE,
|
|
POS_RESERVED, // Not used by CSP
|
|
POS_KEY_TYPE,
|
|
POS_KEYSET
|
|
};
|
|
|
|
|
|
|
|
const int PIN_LEN = PIN_MAX;
|
|
const int TIME_GEN_512 = 30;
|
|
const int TIME_GEN_1024 = 35;
|
|
|
|
|
|
// Used for GPK4000 perso (filter)
|
|
const WORD EF_PUBLIC_SIZE = 1483;
|
|
const WORD EF_PRIVATE_SIZE = 620;
|
|
const WORD DIFF_US_EXPORT = 240;
|
|
|
|
// depend on the GemSAFE mapping
|
|
const BYTE USER_PIN = 0;
|
|
|
|
|
|
|
|
|
|
const BYTE TAG_MODULUS = 0x01;
|
|
const BYTE TAG_PUB_EXP = 0x07;
|
|
const BYTE TAG_LEN = 1;
|
|
const BYTE PUB_EXP_LEN = 3;
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Structures
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
typedef struct OBJ_FIELD
|
|
{
|
|
BYTE *pValue;
|
|
WORD Len;
|
|
WORD Reserved1;
|
|
BOOL bReal;
|
|
WORD Reserved2;
|
|
} OBJ_FIELD;
|
|
|
|
|
|
typedef struct GPK_EXP_KEY
|
|
{
|
|
BYTE KeySize;
|
|
BYTE ExpSize;
|
|
WORD Reserved;
|
|
BYTE Exposant[256];
|
|
BYTE Modulus[256];
|
|
} GPK_EXP_KEY;
|
|
|
|
|
|
typedef struct GPK_OBJ
|
|
{
|
|
BYTE Tag;
|
|
BYTE LastField;
|
|
BYTE ObjId;
|
|
BYTE FileId;
|
|
WORD Flags;
|
|
WORD Reserved1;
|
|
GPK_EXP_KEY PubKey;
|
|
OBJ_FIELD Field[MAX_FIELD];
|
|
HCRYPTKEY hKeyBase;
|
|
BOOL IsPrivate;
|
|
WORD Reserved2;
|
|
BOOL IsCreated;
|
|
WORD Reserved3;
|
|
} GPK_OBJ;
|
|
|
|
|
|
typedef struct TMP_OBJ
|
|
{
|
|
HCRYPTPROV hProv;
|
|
HCRYPTKEY hKeyBase;
|
|
} TMP_OBJ;
|
|
|
|
|
|
typedef struct TMP_HASH
|
|
{
|
|
HCRYPTPROV hProv;
|
|
HCRYPTHASH hHashBase;
|
|
} TMP_HASH;
|
|
|
|
|
|
|
|
|
|
typedef struct Slot_Description
|
|
{
|
|
// NK 06.02.2001 - PinCache
|
|
PINCACHE_HANDLE hPinCacheHandle;
|
|
// End NK
|
|
|
|
BOOL Read_Priv;
|
|
BOOL Read_Public;
|
|
BOOL InitFlag;
|
|
BOOL UseFile [MAX_REAL_KEY];
|
|
BYTE NbGpkObject;
|
|
BYTE bGpkSerNb[8];
|
|
GPK_EXP_KEY GpkPubKeys[MAX_REAL_KEY];
|
|
GPK_OBJ GpkObject[MAX_GPK_OBJ + 1]; // 0 is not used, valid 1-MAX_GPK_OBJ
|
|
DWORD NbKeyFile; // number of key file version 2.00.002
|
|
DWORD GpkMaxSessionKey; // Card unwrap capability
|
|
DWORD ContextCount;
|
|
HANDLE CheckThread;
|
|
SCARD_READERSTATE ReaderState;
|
|
BOOL CheckThreadStateEmpty; // TRUE if card has been removed and detected by checkThread
|
|
TCHAR szReaderName[128];
|
|
|
|
// TT - 17/10/2000 - Timestamps on card
|
|
BYTE m_TSPublic;
|
|
BYTE m_TSPrivate;
|
|
BYTE m_TSPIN;
|
|
|
|
BOOL ValidateTimestamps( HCRYPTPROV prov );
|
|
} Slot_Description;
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Statics (locals)
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
static HINSTANCE hFirstInstMod = 0;
|
|
static BOOL bFirstGUILoad = TRUE;
|
|
static HCRYPTPROV hProvBase = 0;
|
|
static SCARDCONTEXT hCardContext = 0; // mv
|
|
|
|
static unsigned l_globalLockCount;
|
|
|
|
|
|
static BYTE bSendBuffer[512];
|
|
static BYTE bRecvBuffer[512];
|
|
static BYTE* g_pbGpkObj = 0;
|
|
|
|
static DWORD cbSendLength;
|
|
static DWORD cbRecvLength;
|
|
static DWORD dwSW1SW2;
|
|
|
|
static DWORD countCardContextRef= 0;
|
|
static DWORD NbInst;
|
|
|
|
static TCHAR mszCardList[MAX_PATH];
|
|
|
|
// For dynamic reallocation of TmpObject, hHashGpk and ProvCont
|
|
static DWORD MAX_CONTEXT = 50;
|
|
static DWORD MAX_TMP_KEY = 200;
|
|
static DWORD MAX_TMP_HASH = 200;
|
|
|
|
// Temporary objects in each context
|
|
static TMP_OBJ* TmpObject; // dynamic allocated/reallocated
|
|
static TMP_HASH* hHashGpk; // dynamic allocated/reallocated
|
|
|
|
// Many contexts management
|
|
Prov_Context* ProvCont; // dynamic allocated/reallocated
|
|
|
|
// Per slot information
|
|
static SCARDCONTEXT hCardContextCheck[MAX_SLOT];
|
|
static volatile BOOL g_fStopMonitor[MAX_SLOT];
|
|
static Slot_Description Slot[MAX_SLOT];
|
|
static BOOL InitSlot[MAX_SLOT];
|
|
|
|
|
|
static DWORD g_FuncSlotNb = 0;
|
|
static long g_threadAttach = 0;
|
|
|
|
// Gen key time for GPK8000
|
|
static int g_GPK8000KeyGenTime512 = 0;
|
|
static int g_GPK8000KeyGenTime1024 = 0;
|
|
|
|
// End of the Dialogue Management
|
|
|
|
static HCRYPTKEY hRsaIdentityKey = 0;
|
|
static DWORD AuxMaxSessionKeyLength = 0;
|
|
static DWORD dwRsaIdentityLen = 64;
|
|
static BYTE RC2_Key_Size = 0;
|
|
static BYTE RSA_KEK_Size = 0;
|
|
static BYTE PrivateBlob[] =
|
|
{
|
|
// Blob header
|
|
0x07, // PRIVATEKEYBLOB
|
|
0x02, // CUR_BLOB_VERSION
|
|
0x00,0x00, // RESERVED
|
|
0x00,0xa4,0x00,0x00, // CALG_RSA_KEYX
|
|
// RSA Public Key
|
|
0x52,0x53,0x41,0x32, // "RSA2"
|
|
0x00,0x02,0x00,0x00, // 512 bits
|
|
0x01,0x00,0x00,0x00, // Public Exponent
|
|
// Modulus
|
|
0x6b,0xdf,0x51,0xef,0xdb,0x6f,0x10,0x5c,
|
|
0x32,0xbf,0x87,0x1c,0xd1,0x4c,0x24,0x7e,
|
|
0xe7,0x2a,0x14,0x10,0x6d,0xeb,0x2c,0xd5,
|
|
0x8c,0x0b,0x95,0x7b,0xc7,0x5d,0xc6,0x87,
|
|
0x12,0xea,0xa9,0xcd,0x57,0x7d,0x3e,0xcb,
|
|
0xe9,0x6a,0x46,0xd0,0xe1,0xae,0x2f,0x86,
|
|
0xd9,0x50,0xf9,0x98,0x71,0xdd,0x39,0xfc,
|
|
0x0e,0x60,0xa9,0xd3,0xf2,0x38,0xbb,0x8d,
|
|
// Prime 1
|
|
0x5d,0x2c,0xbc,0x1e,0xc3,0x38,0xfe,0x00,
|
|
0x5e,0xca,0xcf,0xcd,0xb4,0x13,0x89,0x16,
|
|
0xd2,0x07,0xbc,0x9b,0xe1,0x20,0x31,0x0b,
|
|
0x81,0x28,0x17,0x0c,0xc7,0x73,0x94,0xee,
|
|
// Prime 2
|
|
0x67,0xbe,0x7b,0x78,0x4e,0xc7,0x91,0x73,
|
|
0xa8,0x34,0x5a,0x24,0x9d,0x92,0x0d,0xe8,
|
|
0x91,0x61,0x24,0xdc,0xb5,0xeb,0xdf,0x71,
|
|
0x66,0xdc,0xe1,0x77,0xd4,0x78,0x14,0x98,
|
|
// Exponent 1
|
|
0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
// Exponent 2
|
|
0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
// Coefficient
|
|
0xa0,0x51,0xe9,0x83,0xca,0xee,0x4b,0xf0,
|
|
0x59,0xeb,0xa4,0x81,0xd6,0x1f,0x49,0x42,
|
|
0x2b,0x75,0x89,0xa7,0x9f,0x84,0x7f,0x1f,
|
|
0xc3,0x8f,0x70,0xb6,0x7e,0x06,0x5e,0x8b,
|
|
// Private Exponent
|
|
0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
|
};
|
|
|
|
|
|
|
|
|
|
static BYTE InitValue[2][2*16+2] =
|
|
{
|
|
{
|
|
// 1 key case
|
|
0x01, 0xF0, 0x00, GPK_FIRST_KEY,
|
|
0x01, 0xD0, 0x00, GPK_FIRST_KEY,
|
|
0x03, 0xB0, 0x00, GPK_FIRST_KEY,
|
|
0x03, 0x90, 0x00, GPK_FIRST_KEY,
|
|
0x00,
|
|
0xFF
|
|
},
|
|
{
|
|
// 2 keys case
|
|
0x01, 0xF0,0x00, GPK_FIRST_KEY,
|
|
0x01, 0xD0,0x00, GPK_FIRST_KEY,
|
|
0x03, 0xB0,0x00, GPK_FIRST_KEY,
|
|
0x03, 0x90,0x00, GPK_FIRST_KEY,
|
|
0x01, 0xF0,0x00, GPK_FIRST_KEY+1,
|
|
0x01, 0xD0,0x00, GPK_FIRST_KEY+1,
|
|
0x03, 0xB0,0x00, GPK_FIRST_KEY+1,
|
|
0x03, 0x90,0x00, GPK_FIRST_KEY+1,
|
|
0x00,
|
|
0xFF
|
|
}
|
|
};
|
|
|
|
|
|
// NK 09.02.2001 PinCache functions
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PopulatePins()
|
|
// Initializes the Pins structure and storea data
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void PopulatePins( PPINCACHE_PINS pPins,
|
|
BYTE *szCurPin,
|
|
DWORD bCurPin,
|
|
BYTE *szNewPin,
|
|
DWORD bNewPin )
|
|
{
|
|
if ( NULL == szCurPin )
|
|
pPins->pbCurrentPin = NULL;
|
|
else
|
|
pPins->pbCurrentPin = szCurPin;
|
|
|
|
pPins->cbCurrentPin = bCurPin;
|
|
|
|
if ( NULL == szNewPin )
|
|
pPins->pbNewPin = NULL;
|
|
else
|
|
pPins->pbNewPin = szNewPin;
|
|
|
|
pPins->cbNewPin = bNewPin;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
|
|
DWORD Select_MF(HCRYPTPROV hProv);
|
|
BOOL Coherent(HCRYPTPROV hProv, bool *cardReinserted=NULL);
|
|
static DWORD OpenCard(CHAR* szContainerAsked, DWORD dwFlags, SCARDHANDLE* hCard, PTCHAR szReaderName, DWORD dwReaderNameLen);
|
|
void ReleaseProvider(HCRYPTPROV hProv);
|
|
static int get_pin_free(HCRYPTPROV hProv);
|
|
static BOOL verify_pin(HCRYPTPROV hProv, const char* pPin, DWORD dwPinLen);
|
|
static BOOL change_pin(HCRYPTPROV hProv, BYTE secretCode, const char* a_pOldPin, DWORD dwOldPinLen, const char* a_pNewPin, DWORD dwNewPinLen);
|
|
static BOOL Context_exist(HCRYPTPROV hProv);
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
|
|
struct CallbackData
|
|
{
|
|
HCRYPTPROV hProv;
|
|
BOOL IsCoherent;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Callbacks for PinCache
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
DWORD Callback_VerifyPinLength( PPINCACHE_PINS pPins, PVOID pvCallBackCtx )
|
|
{
|
|
if ((pPins->cbCurrentPin < PIN_MIN) || (pPins->cbCurrentPin > PIN_MAX))
|
|
return SCARD_E_INVALID_CHV;
|
|
|
|
if (( pPins->cbNewPin != 0 ) &&
|
|
((pPins->cbNewPin < PIN_MIN) || (pPins->cbNewPin > PIN_MAX)))
|
|
return SCARD_E_INVALID_CHV;
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
DWORD Callback_VerifyChangePin( PPINCACHE_PINS pPins, PVOID pvCallBackCtx )
|
|
{
|
|
DWORD dwStatus;
|
|
|
|
if ((dwStatus = Callback_VerifyPinLength(pPins, 0)) != ERROR_SUCCESS)
|
|
return dwStatus;
|
|
|
|
if (pvCallBackCtx == 0)
|
|
return NTE_FAIL;
|
|
|
|
CallbackData* pCallbackData = (CallbackData*)pvCallBackCtx;
|
|
HCRYPTPROV hProv = pCallbackData->hProv;
|
|
BOOL IsCoherent = pCallbackData->IsCoherent;
|
|
|
|
if (!IsCoherent)
|
|
{
|
|
if (!Coherent(hProv))
|
|
return NTE_FAIL;
|
|
}
|
|
|
|
DWORD dwPinFree = get_pin_free(hProv);
|
|
|
|
if (dwPinFree == -1)
|
|
dwStatus = NTE_FAIL;
|
|
|
|
if ((dwStatus == ERROR_SUCCESS) && (dwPinFree == 0))
|
|
dwStatus = SCARD_W_CHV_BLOCKED;
|
|
|
|
if ((dwStatus == ERROR_SUCCESS) && (!verify_pin(hProv, (CHAR*)pPins->pbCurrentPin, pPins->cbCurrentPin)))
|
|
dwStatus = SCARD_W_WRONG_CHV;
|
|
|
|
if (pPins->cbNewPin != 0)
|
|
{
|
|
if ((dwStatus == ERROR_SUCCESS) && (!change_pin(hProv, USER_PIN, (CHAR*)pPins->pbCurrentPin, pPins->cbCurrentPin, (CHAR*)pPins->pbNewPin, pPins->cbNewPin)))
|
|
dwStatus = SCARD_W_WRONG_CHV;
|
|
}
|
|
|
|
if (!IsCoherent)
|
|
{
|
|
Select_MF(hProv);
|
|
SCardEndTransaction(ProvCont[hProv].hCard, SCARD_LEAVE_CARD);
|
|
}
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
|
|
DWORD Callback_VerifyChangePin2( PPINCACHE_PINS pPins, PVOID pvCallBackCtx )
|
|
{
|
|
DWORD dwStatus;
|
|
if ((dwStatus = Callback_VerifyPinLength(pPins, 0)) != ERROR_SUCCESS)
|
|
return dwStatus;
|
|
|
|
if (pvCallBackCtx == 0)
|
|
return NTE_FAIL;
|
|
|
|
HCRYPTPROV hProv = (HCRYPTPROV)pvCallBackCtx;
|
|
|
|
if (!verify_pin(hProv, (CHAR*)pPins->pbCurrentPin, pPins->cbCurrentPin))
|
|
return SCARD_W_WRONG_CHV;
|
|
|
|
if (pPins->cbNewPin != 0)
|
|
{
|
|
if (!change_pin(hProv, USER_PIN, (CHAR*)pPins->pbCurrentPin, pPins->cbCurrentPin, (CHAR*)pPins->pbNewPin, pPins->cbNewPin))
|
|
return SCARD_W_WRONG_CHV;
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Query_MSPinCache()
|
|
// Wrapper for Microsoft PinCacheQuery
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
DWORD Query_MSPinCache( PINCACHE_HANDLE hCache, PBYTE pbPin, PDWORD pcbPin )
|
|
{
|
|
DWORD dwStatus = PinCacheQuery( hCache, pbPin, pcbPin );
|
|
|
|
if ( (dwStatus == ERROR_EMPTY) && (*pcbPin == 0) )
|
|
return ERROR_EMPTY;
|
|
|
|
if ( (dwStatus == ERROR_SUCCESS) && (*pcbPin == 0) )
|
|
return SCARD_E_INVALID_CHV;
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Flush_MSPinCache()
|
|
// Wrapper for Microsoft PinCacheFlush
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void Flush_MSPinCache ( PINCACHE_HANDLE *phCache )
|
|
{
|
|
PinCacheFlush( phCache );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Wrapper for SCardConnect
|
|
//
|
|
// fix SCR 43 : Reconnect after the ressource manager had been stopped and
|
|
// restarted.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
DWORD ConnectToCard( IN LPCTSTR szReaderFriendlyName,
|
|
IN DWORD dwShareMode,
|
|
IN DWORD dwPreferredProtocols,
|
|
OUT LPSCARDHANDLE phCard,
|
|
OUT LPDWORD pdwActiveProtocol
|
|
)
|
|
{
|
|
DWORD dwSts = SCardConnect( hCardContext, szReaderFriendlyName,
|
|
dwShareMode, dwPreferredProtocols,
|
|
phCard, pdwActiveProtocol );
|
|
|
|
if (dwSts == SCARD_E_SERVICE_STOPPED)
|
|
{
|
|
DBG_PRINT(TEXT("ScardConnect fails because RM has been stopped and restarted"));
|
|
|
|
SCardReleaseContext(hCardContext);
|
|
dwSts = SCardEstablishContext( SCARD_SCOPE_SYSTEM, 0, 0, &hCardContext );
|
|
|
|
if (dwSts == SCARD_S_SUCCESS)
|
|
{
|
|
dwSts = SCardConnect( hCardContext, szReaderFriendlyName,
|
|
dwShareMode, dwPreferredProtocols, phCard, pdwActiveProtocol );
|
|
}
|
|
}
|
|
|
|
DBG_PRINT(TEXT("SCardConnect"));
|
|
return dwSts;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Add_MSPinCache()
|
|
// Wrapper for Microsoft PinCacheAdd
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
DWORD Add_MSPinCache( PINCACHE_HANDLE *phCache,
|
|
PPINCACHE_PINS pPins,
|
|
PFN_VERIFYPIN_CALLBACK pfnVerifyPinCallback,
|
|
PVOID pvCallbackCtx)
|
|
{
|
|
DWORD dwStatus = PinCacheAdd( phCache,
|
|
pPins,
|
|
pfnVerifyPinCallback,
|
|
pvCallbackCtx );
|
|
|
|
return dwStatus;
|
|
|
|
}
|
|
// End NK
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// DoSCardTransmit:
|
|
// This function performs an SCardTransmit operation, plus retries the
|
|
// operation should an SCARD_E_COMM_DATA_LOST or similar error be reported.
|
|
//
|
|
// Arguments:
|
|
// Per SCardTransmit
|
|
//
|
|
// Return Value:
|
|
// Per SCardTransmit
|
|
//
|
|
// Author:
|
|
// Doug Barlow (dbarlow) 1/27/1999
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
LONG WINAPI
|
|
DoSCardTransmit(
|
|
IN SCARDHANDLE hCard,
|
|
IN LPCSCARD_IO_REQUEST pioSendPci,
|
|
IN LPCBYTE pbSendBuffer,
|
|
IN DWORD cbSendLength,
|
|
IN OUT LPSCARD_IO_REQUEST pioRecvPci,
|
|
OUT LPBYTE pbRecvBuffer,
|
|
IN OUT LPDWORD pcbRecvLength)
|
|
{
|
|
LONG lRet=SCARD_E_UNEXPECTED;
|
|
BOOL fAgain = TRUE;
|
|
DWORD dwRetryLimit = 3;
|
|
DWORD dwLength;
|
|
|
|
DBG_TIME1;
|
|
|
|
while (fAgain)
|
|
{
|
|
if (0 == dwRetryLimit--)
|
|
break;
|
|
dwLength = *pcbRecvLength;
|
|
lRet = SCardTransmit(
|
|
hCard,
|
|
pioSendPci,
|
|
pbSendBuffer,
|
|
cbSendLength,
|
|
pioRecvPci,
|
|
pbRecvBuffer,
|
|
&dwLength);
|
|
switch (lRet)
|
|
{
|
|
#ifdef SCARD_E_COMM_DATA_LOST
|
|
case SCARD_E_COMM_DATA_LOST:
|
|
#endif
|
|
case ERROR_SEM_TIMEOUT:
|
|
break;
|
|
default:
|
|
fAgain = FALSE;
|
|
*pcbRecvLength = dwLength;
|
|
}
|
|
}
|
|
|
|
DBG_TIME2;
|
|
DBG_PRINT(TEXT("SCardTransmit(CLA:0x%02X, INS:0x%02X, P1:0x%02X, P2:0x%02X, Li:0x%02X) in %d msec"),
|
|
pbSendBuffer[0],
|
|
pbSendBuffer[1],
|
|
pbSendBuffer[2],
|
|
pbSendBuffer[3],
|
|
pbSendBuffer[4],
|
|
DBG_DELTA);
|
|
|
|
return lRet;
|
|
}
|
|
|
|
|
|
#define SCardTransmit DoSCardTransmit
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// TT END: La passe a Doug
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// TT - 17/10/2000 - Inter-process synchronisation using timestamps
|
|
// stored on the card. There is three timestamps:
|
|
//
|
|
// Public objects timestamp: GemSAFE IADF offset 68
|
|
// Private objects timestamp: GemSAFE IADF offset 69
|
|
// PIN modification timestamp: GemSAFE IADF offset 70
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL ReadTimestamps( HCRYPTPROV hProv, BYTE* pTSPublic, BYTE* pTSPrivate, BYTE* pTSPIN )
|
|
{
|
|
// Issue a read binary command at offset 68 of the IADF
|
|
bSendBuffer[0] = 0x00;
|
|
bSendBuffer[1] = 0xB0;
|
|
bSendBuffer[2] = 0x80 | LOBYTE( GPK_IADF_EF );
|
|
bSendBuffer[3] = 68 / ProvCont[hProv].dataUnitSize;
|
|
bSendBuffer[4] = 3;
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
|
|
DWORD lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if (SCARDPROBLEM(lRet,0x9000,bSendBuffer[4]))
|
|
{
|
|
RETURN( CRYPT_FAILED, SCARD_W_EOF );
|
|
}
|
|
|
|
*pTSPublic = bRecvBuffer[0];
|
|
*pTSPrivate = bRecvBuffer[1];
|
|
*pTSPIN = bRecvBuffer[2];
|
|
|
|
RETURN( CRYPT_SUCCEED, 0 );
|
|
}
|
|
|
|
|
|
|
|
BOOL WriteTimestamps( HCRYPTPROV hProv, BYTE TSPublic, BYTE TSPrivate, BYTE TSPIN )
|
|
{
|
|
// Issue a update binary command at offset 68 of the IADF
|
|
bSendBuffer[0] = 0x00;
|
|
bSendBuffer[1] = 0xD6;
|
|
bSendBuffer[2] = 0x80 | LOBYTE( GPK_IADF_EF );
|
|
bSendBuffer[3] = 68 / ProvCont[hProv].dataUnitSize;
|
|
bSendBuffer[4] = 3;
|
|
bSendBuffer[5] = TSPublic;
|
|
bSendBuffer[6] = TSPrivate;
|
|
bSendBuffer[7] = TSPIN;
|
|
cbSendLength = 8;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
DWORD lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if (SCARDPROBLEM(lRet,0x9000,0))
|
|
{
|
|
RETURN( CRYPT_FAILED, SCARD_W_EOF );
|
|
}
|
|
|
|
RETURN( CRYPT_SUCCEED, 0 );
|
|
}
|
|
|
|
|
|
|
|
BOOL Slot_Description::ValidateTimestamps( HCRYPTPROV hProv )
|
|
{
|
|
BYTE TSPublic, TSPrivate, TSPIN;
|
|
|
|
if (!ReadTimestamps( hProv, &TSPublic, &TSPrivate, &TSPIN ))
|
|
return CRYPT_FAILED;
|
|
|
|
if (m_TSPublic != TSPublic)
|
|
{
|
|
Read_Public = FALSE;
|
|
zap_gpk_objects( ProvCont[hProv].Slot, FALSE );
|
|
}
|
|
|
|
if (m_TSPrivate != TSPrivate)
|
|
{
|
|
Read_Priv = FALSE;
|
|
zap_gpk_objects( ProvCont[hProv].Slot, TRUE );
|
|
}
|
|
|
|
if (m_TSPIN != TSPIN)
|
|
{
|
|
// ClearPin(); // NK 06.02.2001
|
|
Flush_MSPinCache(&hPinCacheHandle);
|
|
}
|
|
|
|
m_TSPublic = TSPublic;
|
|
m_TSPrivate = TSPrivate;
|
|
m_TSPIN = TSPIN;
|
|
|
|
return CRYPT_SUCCEED;
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IsWin2000() - Detect if we are running under Win2000 (and above)
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
bool IsWin2000()
|
|
{
|
|
#if (_WIN32_WINNT >= 0x0500)
|
|
|
|
return true;
|
|
|
|
#else
|
|
|
|
OSVERSIONINFO info;
|
|
info.dwOSVersionInfoSize = sizeof(info);
|
|
|
|
GetVersionEx( &info );
|
|
|
|
if (info.dwPlatformId == VER_PLATFORM_WIN32_NT && info.dwMajorVersion >= 5)
|
|
return true;
|
|
|
|
return false;
|
|
|
|
#endif
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// TT 28/07/2000
|
|
//
|
|
// Detect GPK4000 ATR instead of GPK8000 ATR. This is to ensure
|
|
// that the GPK16000 will work as-is with the CSP.
|
|
//
|
|
// The return value is the error code from SCardStatus()
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static DWORD DetectGPK8000( SCARDHANDLE hCard, BOOL* pbGPK8000 )
|
|
{
|
|
const BYTE ATR_GPK4000[] = { 0x3B, 0x27, 0x00, 0x80, 0x65, 0xA2, 0x04, 0x01, 0x01, 0x37 };
|
|
const BYTE ATR_MASK[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE5, 0xFF, 0xFF, 0xFF };
|
|
|
|
|
|
DWORD lRet;
|
|
TCHAR szReaderName[1024];
|
|
DWORD lenReaderName;
|
|
DWORD state;
|
|
DWORD protocol;
|
|
BYTE ATR[32];
|
|
DWORD lenATR;
|
|
DWORD i;
|
|
|
|
lenReaderName = sizeof( szReaderName ) / sizeof( TCHAR );
|
|
lenATR = sizeof(ATR);
|
|
|
|
// Assume we have a GPK4000
|
|
*pbGPK8000 = FALSE;
|
|
|
|
// Read the ATR
|
|
lRet = SCardStatus( hCard, szReaderName, &lenReaderName, &state, &protocol, ATR, &lenATR );
|
|
if (lRet != SCARD_S_SUCCESS)
|
|
return lRet;
|
|
|
|
// Check for GPK4000
|
|
for (i = 0; i < lenATR; ++i)
|
|
{
|
|
if ( (ATR[i] & ATR_MASK[i]) != (ATR_GPK4000[i] & ATR_MASK[i]) )
|
|
{
|
|
// Not a GPK4000
|
|
*pbGPK8000 = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return SCARD_S_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------
|
|
// Critical section
|
|
------------------------------------------------------------------------------*/
|
|
|
|
static CRITICAL_SECTION l_csLocalLock;
|
|
|
|
|
|
void GpkLocalLock()
|
|
{
|
|
EnterCriticalSection(&l_csLocalLock);
|
|
}
|
|
|
|
void GpkLocalUnlock()
|
|
{
|
|
LeaveCriticalSection(&l_csLocalLock);
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static void r_memcpy(BYTE *pbOut, BYTE *pbIn, DWORD dwLen)
|
|
{
|
|
DWORD i;
|
|
|
|
for (i = 0; i < dwLen; i++)
|
|
{
|
|
pbOut[i] = pbIn[dwLen - i -1];
|
|
}
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
|
|
static BOOL sw_mask(WORD sw, BYTE x)
|
|
{
|
|
if ((sw == 0x0000) || (x == 0xFF))
|
|
{
|
|
return (CRYPT_SUCCEED);
|
|
}
|
|
|
|
|
|
dwSW1SW2 = (bRecvBuffer[x]*256) + bRecvBuffer[x+1];
|
|
|
|
if (LOBYTE(sw) == 0xFF)
|
|
{
|
|
if (bRecvBuffer[x] != HIBYTE(sw))
|
|
{
|
|
return (CRYPT_FAILED);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((bRecvBuffer[x] != HIBYTE(sw))
|
|
||(bRecvBuffer[x+1] != LOBYTE(sw))
|
|
)
|
|
{
|
|
return (CRYPT_FAILED);
|
|
}
|
|
}
|
|
|
|
return (CRYPT_SUCCEED);
|
|
}
|
|
|
|
|
|
|
|
BOOL SCARDPROBLEM( LONG result, WORD sc_status, BYTE offset )
|
|
{
|
|
if (!sw_mask( sc_status, offset ))
|
|
return TRUE;
|
|
|
|
if (result != SCARD_S_SUCCESS)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static void conv_hex( const char* pInput, WORD wLen, BYTE* pOut )
|
|
{
|
|
BYTE pin[32];
|
|
WORD i;
|
|
|
|
memcpy( pin, pInput, min(wLen,sizeof(pin)) );
|
|
|
|
if (wLen & 1)
|
|
pin[wLen] = '0';
|
|
|
|
|
|
for (i=0; i < wLen; i+=2)
|
|
{
|
|
pOut[i/2] = ((pin[i] & 0x0F) << 4) + (pin[i+1] & 0x0F);
|
|
}
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
|
|
HWND GetAppWindow()
|
|
{
|
|
HWND hActWnd = g_hMainWnd;
|
|
|
|
if (!IsWindow(hActWnd))
|
|
hActWnd = GetActiveWindow();
|
|
|
|
return hActWnd;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
|
|
static void clean_slot( DWORD SlotNb, Prov_Context* pContext )
|
|
{
|
|
Slot_Description* pSlot;
|
|
|
|
pSlot = &Slot[ SlotNb ];
|
|
|
|
pSlot->Read_Priv = FALSE;
|
|
pSlot->Read_Public = FALSE;
|
|
pSlot->ContextCount = 0;
|
|
pSlot->GpkMaxSessionKey = 0;
|
|
pSlot->NbKeyFile = 0;
|
|
|
|
// pSlot->ClearPin(); NK 06.02.2001
|
|
Flush_MSPinCache(&(pSlot->hPinCacheHandle));
|
|
|
|
if (pContext->hRSASign != 0)
|
|
{
|
|
CryptDestroyKey( pContext->hRSASign );
|
|
pContext->hRSASign = 0;
|
|
}
|
|
|
|
if (pContext->hRSAKEK != 0)
|
|
{
|
|
CryptDestroyKey( pContext->hRSAKEK );
|
|
pContext->hRSAKEK = 0;
|
|
}
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
|
|
static int multistrlen( const PTCHAR mszString )
|
|
{
|
|
int res, tmp;
|
|
PTCHAR ptr = mszString;
|
|
|
|
res = 0;
|
|
|
|
if (IsNullStr(ptr))
|
|
{
|
|
ptr++;
|
|
res++;
|
|
}
|
|
|
|
while (IsNotNullStr(ptr))
|
|
{
|
|
tmp = _tcslen(ptr) + 1;
|
|
res = res + tmp;
|
|
ptr = ptr + tmp;
|
|
}
|
|
|
|
return (res);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static LONG BeginTransaction(SCARDHANDLE hCard)
|
|
{
|
|
DWORD lRet, dwProtocol;
|
|
|
|
lRet = SCardBeginTransaction(hCard);
|
|
|
|
if (lRet == SCARD_W_UNPOWERED_CARD || lRet == SCARD_W_RESET_CARD)
|
|
{
|
|
DBG_PRINT(TEXT("ScardBeginTransaction fails, try to reconnect"));
|
|
lRet = SCardReconnect(hCard,
|
|
SCARD_SHARE_SHARED,
|
|
SCARD_PROTOCOL_T0,
|
|
SCARD_LEAVE_CARD,
|
|
&dwProtocol);
|
|
|
|
if (lRet == SCARD_S_SUCCESS)
|
|
{
|
|
lRet = SCardBeginTransaction(hCard);
|
|
}
|
|
}
|
|
|
|
DBG_PRINT(TEXT("SCardBeginTransaction"));
|
|
return(lRet);
|
|
}
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
|
|
DWORD Select_MF(HCRYPTPROV hProv)
|
|
{
|
|
DWORD lRet;
|
|
// This function is used to make sure to reset the access condition
|
|
// on the sensitive files
|
|
|
|
/* Select GPK Card MF */
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xA4; //INS
|
|
bSendBuffer[2] = 0x00; //P1
|
|
bSendBuffer[3] = 0x0C; //P2
|
|
bSendBuffer[4] = 0x02; //Li
|
|
bSendBuffer[5] = HIBYTE(GPK_MF);
|
|
bSendBuffer[6] = LOBYTE(GPK_MF);
|
|
cbSendLength = 7;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x9000,0x00))
|
|
{
|
|
DBG_PRINT(TEXT("Select MF failed, lRet = 0x%08X, SW1 = %X%X, SW2 = %X%X"), lRet, (bRecvBuffer[0] & 0xF0) >> 4, (bRecvBuffer[0] & 0x0F), (bRecvBuffer[1] & 0xF0) >> 4, (bRecvBuffer[1] & 0x0F));
|
|
RETURN (CRYPT_FAILED, SCARD_E_DIR_NOT_FOUND);
|
|
}
|
|
|
|
if (ProvCont[hProv].dataUnitSize == 0)
|
|
{
|
|
// TT 03/11/99: Check data unit size
|
|
bSendBuffer[0] = 0x80;
|
|
bSendBuffer[1] = 0xC0;
|
|
bSendBuffer[2] = 0x02;
|
|
bSendBuffer[3] = 0xA4;
|
|
bSendBuffer[4] = 0x0D;
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength);
|
|
|
|
if (SCARDPROBLEM(lRet,0x9000,bSendBuffer[4]))
|
|
{
|
|
DBG_PRINT(TEXT("Check data unit size failed"));
|
|
RETURN (CRYPT_FAILED, SCARD_E_DIR_NOT_FOUND);
|
|
}
|
|
|
|
if (bRecvBuffer[11] & 0x40) // LOCK1 & 0x40
|
|
ProvCont[hProv].dataUnitSize = 1;
|
|
else
|
|
ProvCont[hProv].dataUnitSize = 4;
|
|
}
|
|
|
|
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static int get_pin_free(HCRYPTPROV hProv)
|
|
{
|
|
DWORD lRet;
|
|
int nPinFree,
|
|
nb, val; // [JMR 02-04]
|
|
|
|
/* Select GPK PIN EF */
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xA4; //INS
|
|
bSendBuffer[2] = 0x02; //P1
|
|
bSendBuffer[3] = 0x0C; //P2
|
|
bSendBuffer[4] = 0x02; //Li
|
|
bSendBuffer[5] = HIBYTE(GPK_PIN_EF);
|
|
bSendBuffer[6] = LOBYTE(GPK_PIN_EF);
|
|
cbSendLength = 7;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x9000,0x00))
|
|
{
|
|
SetLastError(lRet);
|
|
return (-1);
|
|
}
|
|
|
|
/* Get EF information for User PIN Code (code 0) */
|
|
bSendBuffer[0] = 0x80; //CLA
|
|
bSendBuffer[1] = 0xC0; //INS
|
|
bSendBuffer[2] = 0x02; //P1
|
|
bSendBuffer[3] = 0x05; //P2
|
|
bSendBuffer[4] = 0x0C; //Lo 4*number of secret codes
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x9000, bSendBuffer[4]))
|
|
{
|
|
SetLastError(SCARD_E_UNEXPECTED);
|
|
return (-1);
|
|
}
|
|
|
|
// [JMR 02-04] begin
|
|
nb = 0;
|
|
val = bRecvBuffer[1];
|
|
|
|
while (val > 0)
|
|
{
|
|
nb++;
|
|
val = val >> 1;
|
|
}
|
|
|
|
nPinFree = bRecvBuffer[0] - nb;
|
|
// [JMR 02-04] end
|
|
|
|
SetLastError(0);
|
|
return (max(0, nPinFree));
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static BOOL verify_pin( HCRYPTPROV hProv,
|
|
const char* pPin,
|
|
DWORD dwPinLen
|
|
)
|
|
{
|
|
DWORD lRet;
|
|
|
|
/* Verify User PIN Code (code 0) */
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0x20; //INS
|
|
bSendBuffer[2] = 0x00; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = 0x08; //Li
|
|
|
|
// TT 22/09/99: New PIN padding for GPK8000
|
|
if (ProvCont[hProv].bGPK_ISO_DF)
|
|
{
|
|
memset(&bSendBuffer[5], 0xFF, 8 );
|
|
memcpy(&bSendBuffer[5], pPin, min(strlen(pPin)+1,8) );
|
|
}
|
|
else
|
|
{
|
|
memset(&bSendBuffer[5], 0x00, 8);
|
|
memcpy(&bSendBuffer[5], pPin, dwPinLen);
|
|
}
|
|
// TT - END -
|
|
|
|
cbSendLength = 5 + bSendBuffer[4];
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if (ProvCont[hProv].bGPK_ISO_DF)
|
|
{
|
|
memset(&bSendBuffer[5], 0, min(strlen(pPin)+1,8) );
|
|
}
|
|
else
|
|
{
|
|
memset(&bSendBuffer[5], 0, dwPinLen);
|
|
}
|
|
|
|
if (SCARDPROBLEM(lRet,0x9000,0x00))
|
|
{
|
|
RETURN(CRYPT_FAILED, SCARD_W_WRONG_CHV);
|
|
}
|
|
|
|
RETURN(CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static BOOL change_pin(HCRYPTPROV hProv,
|
|
BYTE secretCode,
|
|
const char* a_pOldPin,
|
|
DWORD dwOldPinLen,
|
|
const char* a_pNewPin,
|
|
DWORD dwNewPinLen
|
|
)
|
|
{
|
|
DWORD lRet;
|
|
|
|
// TT - 17/10/2000 - Update the timestamps
|
|
Slot_Description* pSlot = &Slot[ProvCont[hProv].Slot];
|
|
|
|
++pSlot->m_TSPIN;
|
|
|
|
if (0 == pSlot->m_TSPIN)
|
|
pSlot->m_TSPIN = 1;
|
|
|
|
if (!WriteTimestamps( hProv, pSlot->m_TSPublic, pSlot->m_TSPrivate, pSlot->m_TSPIN ))
|
|
return CRYPT_FAILED;
|
|
// TT - END -
|
|
|
|
|
|
// TT 22/09/99: New PIN padding for GPK8000
|
|
char pOldPin[PIN_MAX+1];
|
|
char pNewPin[PIN_MAX+1];
|
|
|
|
strncpy( pOldPin, a_pOldPin, PIN_MAX );
|
|
pOldPin[sizeof(pOldPin)-1]=0;
|
|
strncpy( pNewPin, a_pNewPin, PIN_MAX );
|
|
pNewPin[sizeof(pNewPin)-1]=0;
|
|
|
|
if (ProvCont[hProv].bGPK_ISO_DF)
|
|
{
|
|
if (dwOldPinLen < PIN_MAX)
|
|
{
|
|
pOldPin[dwOldPinLen] = 0;
|
|
++dwOldPinLen;
|
|
|
|
while (dwOldPinLen != PIN_MAX)
|
|
{
|
|
pOldPin[dwOldPinLen] = '\xFF';
|
|
++dwOldPinLen;
|
|
}
|
|
}
|
|
|
|
if (dwNewPinLen < PIN_MAX)
|
|
{
|
|
pNewPin[dwNewPinLen] = 0;
|
|
++dwNewPinLen;
|
|
|
|
while (dwNewPinLen != PIN_MAX)
|
|
{
|
|
pNewPin[dwNewPinLen] = '\xFF';
|
|
++dwNewPinLen;
|
|
}
|
|
}
|
|
}
|
|
// TT - END -
|
|
|
|
|
|
|
|
/* Change User PIN Code (code 0) */
|
|
bSendBuffer[0] = 0x80; //CLA
|
|
bSendBuffer[1] = 0x24; //INS
|
|
bSendBuffer[2] = 0x00; //P1
|
|
bSendBuffer[3] = secretCode; //P2
|
|
bSendBuffer[4] = 0x08; //Li
|
|
memset(&bSendBuffer[5], 0x00, 8);
|
|
conv_hex(pOldPin, (WORD)dwOldPinLen, &bSendBuffer[5]);
|
|
conv_hex(pNewPin, (WORD)dwNewPinLen, &bSendBuffer[9]);
|
|
cbSendLength = 5 + bSendBuffer[4];
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
memset(bSendBuffer, 0, sizeof(bSendBuffer));
|
|
if (SCARDPROBLEM(lRet,0x9000,0x00))
|
|
{
|
|
RETURN(CRYPT_FAILED, SCARD_W_WRONG_CHV);
|
|
}
|
|
|
|
RETURN(CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
--------------------------------------------------------------------------------*/
|
|
|
|
BOOL StopMonitor( DWORD SlotNb, DWORD* pThreadExitCode )
|
|
{
|
|
|
|
|
|
|
|
HANDLE hThread;
|
|
DWORD threadExitCode;
|
|
DWORD dwStatus;
|
|
|
|
if (SlotNb >= MAX_SLOT)
|
|
{
|
|
SetLastError( NTE_FAIL );
|
|
return FALSE;
|
|
}
|
|
|
|
hThread = Slot[SlotNb].CheckThread;
|
|
Slot[SlotNb].CheckThread = NULL;
|
|
Slot[SlotNb].CheckThreadStateEmpty = FALSE;
|
|
|
|
if (hThread==NULL)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
g_fStopMonitor[SlotNb] = TRUE;
|
|
SCardCancel( hCardContextCheck[SlotNb] );
|
|
dwStatus = WaitForSingleObject( hThread, 30000 );
|
|
|
|
if (dwStatus == WAIT_TIMEOUT)
|
|
{
|
|
DBG_PRINT( TEXT("THREAD: ...WaitForSingleObject() timeout, thread handle: %08x"), hThread );
|
|
// + [FP]
|
|
// TerminateThread( hThread, 0 );
|
|
// - [FP]
|
|
}
|
|
else
|
|
if (dwStatus == WAIT_FAILED)
|
|
{
|
|
DBG_PRINT( TEXT("THREAD: ...WaitForSingleObject() failed!, thread handle: %08x"), hThread );
|
|
return FALSE;
|
|
}
|
|
|
|
GetExitCodeThread( hThread, &threadExitCode );
|
|
if (pThreadExitCode) *pThreadExitCode = threadExitCode;
|
|
|
|
CloseHandle( hThread );
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
Function: CheckReaderThead
|
|
Out:
|
|
ExitCode:
|
|
0 = any scard error
|
|
1 = scard context has been cancelled
|
|
2 = card has been removed
|
|
Global variables
|
|
g_fStopMonitor[SlotNb] can stops the thread
|
|
|
|
--------------------------------------------------------------------------------*/
|
|
|
|
unsigned WINAPI CheckReaderThread( void* lpParameter )
|
|
{
|
|
DWORD lRet, ExitCode;
|
|
DWORD SlotNb = (DWORD)((DWORD_PTR)lpParameter);
|
|
|
|
ExitCode = 0;
|
|
|
|
|
|
if (SlotNb >= MAX_SLOT)
|
|
{
|
|
return ExitCode;
|
|
}
|
|
|
|
DBG_PRINT(TEXT("CheckReaderThread on Slot %d\n"),SlotNb);
|
|
|
|
if (hCardContextCheck[SlotNb] == 0)
|
|
{
|
|
lRet = SCardEstablishContext (SCARD_SCOPE_SYSTEM, 0, 0, &hCardContextCheck[SlotNb]);
|
|
if (lRet != SCARD_S_SUCCESS)
|
|
{
|
|
DBG_PRINT(TEXT("CheckReaderThread. SCardEstablishContext returns 0x%x\n"),lRet);
|
|
return ExitCode;
|
|
}
|
|
}
|
|
|
|
while (( !ExitCode) && (!g_fStopMonitor[SlotNb]))
|
|
{
|
|
lRet = SCardGetStatusChange(hCardContextCheck[SlotNb], INFINITE, &Slot[SlotNb].ReaderState, 1);
|
|
if (lRet == SCARD_E_CANCELLED)
|
|
{
|
|
ExitCode = 1;
|
|
}
|
|
else
|
|
{
|
|
if (lRet == SCARD_S_SUCCESS)
|
|
{
|
|
if (Slot[SlotNb].ReaderState.dwEventState & SCARD_STATE_EMPTY)
|
|
{
|
|
|
|
DBG_PRINT(TEXT("Card has been removed"));
|
|
Slot[SlotNb].CheckThreadStateEmpty = TRUE;
|
|
GpkLocalLock();
|
|
// TT 19/11/99: When the card is removed, reset the PIN
|
|
// Slot[SlotNb].ClearPin();NK 06.02.2001
|
|
Flush_MSPinCache(&(Slot[SlotNb].hPinCacheHandle));
|
|
|
|
Slot[SlotNb].Read_Public = FALSE;
|
|
Slot[SlotNb].Read_Priv = FALSE;
|
|
zap_gpk_objects( SlotNb, FALSE );
|
|
zap_gpk_objects( SlotNb, TRUE );
|
|
Slot[SlotNb].NbKeyFile = 0;
|
|
Slot[SlotNb].GpkMaxSessionKey = 0;
|
|
GpkLocalUnlock();
|
|
|
|
// the thread has done is job, exit.
|
|
ExitCode = 2 ;
|
|
}
|
|
else
|
|
{
|
|
Slot[SlotNb].ReaderState.dwCurrentState = Slot[SlotNb].ReaderState.dwEventState;
|
|
}
|
|
}
|
|
// [FP] stop the thread on any other error returned by
|
|
//SCardGetStatusChange to avoid endless loop
|
|
else
|
|
{
|
|
DBG_PRINT(TEXT("Problem with RM"));
|
|
|
|
Slot[SlotNb].CheckThreadStateEmpty = TRUE;
|
|
GpkLocalLock();
|
|
// Slot[SlotNb].ClearPin();NK 06.02.2001
|
|
Flush_MSPinCache(&(Slot[SlotNb].hPinCacheHandle));
|
|
|
|
Slot[SlotNb].Read_Public = FALSE;
|
|
Slot[SlotNb].Read_Priv = FALSE;
|
|
zap_gpk_objects( SlotNb, FALSE );
|
|
zap_gpk_objects( SlotNb, TRUE );
|
|
Slot[SlotNb].NbKeyFile = 0;
|
|
Slot[SlotNb].GpkMaxSessionKey = 0;
|
|
//Slot[SlotNb].CheckThread = 0;
|
|
GpkLocalUnlock();
|
|
|
|
ExitCode = 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (hCardContextCheck[SlotNb] != 0)
|
|
{
|
|
SCardReleaseContext( hCardContextCheck[SlotNb] );
|
|
hCardContextCheck[SlotNb] = 0;
|
|
}
|
|
|
|
|
|
return ExitCode;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
BOOL BeginCheckReaderThread(DWORD SlotNb)
|
|
{
|
|
unsigned checkThreadId;
|
|
DWORD lRet;
|
|
SCARDCONTEXT hCardContextThread;
|
|
|
|
if (SlotNb >= MAX_SLOT)
|
|
{
|
|
SetLastError( NTE_FAIL );
|
|
return FALSE;
|
|
}
|
|
|
|
// Monitoring thread
|
|
if (Slot[SlotNb].CheckThread == NULL)
|
|
{
|
|
// In this case, use an auxiliairy thread to check if the card has
|
|
// been removed from this reader.
|
|
|
|
// checks the initial state
|
|
lRet = SCardEstablishContext (SCARD_SCOPE_SYSTEM, 0, 0, &hCardContextThread);
|
|
if (lRet != SCARD_S_SUCCESS)
|
|
{
|
|
return FALSE;
|
|
}
|
|
Slot[SlotNb].ReaderState.szReader = Slot[SlotNb].szReaderName;
|
|
Slot[SlotNb].ReaderState.dwCurrentState = SCARD_STATE_UNAWARE;
|
|
lRet = SCardGetStatusChange(hCardContextThread, 1, &Slot[SlotNb].ReaderState, 1);
|
|
if (hCardContextThread != 0)
|
|
{
|
|
SCardReleaseContext( hCardContextThread );
|
|
hCardContextCheck[SlotNb] = 0;
|
|
}
|
|
|
|
if (lRet != SCARD_S_SUCCESS)
|
|
{
|
|
return FALSE;
|
|
}
|
|
Slot[SlotNb].ReaderState.dwCurrentState = Slot[SlotNb].ReaderState.dwEventState;
|
|
|
|
// Allocate and trigger the thread, if there is a card
|
|
g_fStopMonitor[SlotNb] = FALSE;
|
|
Slot[SlotNb].CheckThreadStateEmpty = FALSE;
|
|
|
|
if (Slot[SlotNb].ReaderState.dwEventState & SCARD_STATE_PRESENT)
|
|
{
|
|
|
|
Slot[SlotNb].CheckThread = (HANDLE)_beginthreadex( 0, 0, CheckReaderThread,
|
|
(LPVOID)((DWORD_PTR)SlotNb), 0, &checkThreadId );
|
|
}
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL PIN_Validation(HCRYPTPROV hProv)
|
|
{
|
|
BOOL CryptResp;
|
|
DWORD nPinFree;
|
|
DWORD SlotNb;
|
|
TCHAR szCspTitle[MAX_STRING];
|
|
PINCACHE_PINS Pins;
|
|
DWORD dwStatus;
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
// Get PIN free presentation number
|
|
nPinFree = get_pin_free(hProv);
|
|
|
|
// The flags of the context should be passed to the GUI functions with the global variable
|
|
CspFlags = ProvCont[hProv].Flags;
|
|
|
|
// Failure to retreive PIN free presentation count (-1)
|
|
if ( nPinFree == DWORD(-1) )
|
|
{
|
|
// Slot[SlotNb].ClearPin();
|
|
Flush_MSPinCache( &(Slot[SlotNb].hPinCacheHandle) );
|
|
RETURN ( CRYPT_FAILED, NTE_FAIL );
|
|
}
|
|
|
|
// PIN is locked
|
|
if ( nPinFree == 0 )
|
|
{
|
|
// Slot[SlotNb].ClearPin();
|
|
Flush_MSPinCache( &(Slot[SlotNb].hPinCacheHandle) );
|
|
|
|
if ( ProvCont[hProv].Flags & CRYPT_SILENT )
|
|
{
|
|
RETURN ( CRYPT_FAILED, SCARD_W_CHV_BLOCKED );
|
|
}
|
|
else
|
|
{
|
|
LoadString( g_hInstMod, IDS_GPKCSP_TITLE, szCspTitle, sizeof(szCspTitle)/sizeof(TCHAR) );
|
|
DisplayMessage( TEXT("locked"), szCspTitle, 0 );
|
|
RETURN ( CRYPT_FAILED, SCARD_W_CHV_BLOCKED );
|
|
}
|
|
}
|
|
|
|
// Normal PIN verification
|
|
|
|
// dwGpkPinLen = strlen(Slot[SlotNb].GetPin());
|
|
dwGpkPinLen = PIN_LEN + 1;
|
|
dwStatus = Query_MSPinCache( Slot[SlotNb].hPinCacheHandle,
|
|
(BYTE*)szGpkPin,
|
|
&dwGpkPinLen );
|
|
|
|
if ( (dwStatus != ERROR_SUCCESS) && (dwStatus != ERROR_EMPTY) )
|
|
RETURN (CRYPT_FAILED, dwStatus);
|
|
|
|
bNewPin = FALSE;
|
|
bChangePin = FALSE;
|
|
|
|
if ( dwStatus == ERROR_EMPTY )
|
|
{
|
|
if (ProvCont[hProv].Flags & CRYPT_SILENT)
|
|
{
|
|
RETURN ( CRYPT_FAILED, NTE_SILENT_CONTEXT );
|
|
}
|
|
|
|
for(;;)
|
|
{
|
|
Select_MF( hProv );
|
|
SCardEndTransaction( ProvCont[hProv].hCard, SCARD_LEAVE_CARD );
|
|
|
|
DialogBox( g_hInstRes, TEXT("PINDIALOG"), GetAppWindow(), PinDlgProc );
|
|
|
|
if ( dwGpkPinLen == 0 )
|
|
{
|
|
RETURN( CRYPT_FAILED, SCARD_W_CANCELLED_BY_USER );
|
|
}
|
|
else
|
|
{
|
|
bool bCardReinserted=false;
|
|
|
|
if( !Coherent(hProv, &bCardReinserted) )
|
|
RETURN ( CRYPT_FAILED, NTE_FAIL );
|
|
if(bCardReinserted)
|
|
continue;
|
|
|
|
// Slot[SlotNb].SetPin( szGpkPin );
|
|
if (!bChangePin)
|
|
PopulatePins( &Pins, (BYTE *)szGpkPin, dwGpkPinLen, 0, 0 );
|
|
else
|
|
PopulatePins( &Pins, (BYTE *)szGpkPin, dwGpkPinLen, (BYTE *)szGpkNewPin, wGpkNewPinLen );
|
|
|
|
dwStatus = Add_MSPinCache( &(Slot[SlotNb].hPinCacheHandle),
|
|
&Pins,
|
|
Callback_VerifyChangePin2,
|
|
(void*)hProv );
|
|
|
|
memset(szGpkPin, 0, sizeof(szGpkPin));
|
|
dwGpkPinLen=0;
|
|
memset(szGpkNewPin, 0, sizeof(szGpkNewPin));
|
|
wGpkNewPinLen=0;
|
|
if( dwStatus != ERROR_SUCCESS && dwStatus != SCARD_W_WRONG_CHV )
|
|
{
|
|
RETURN ( CRYPT_FAILED, dwStatus );
|
|
}
|
|
}
|
|
break;
|
|
} // for
|
|
}
|
|
else
|
|
{
|
|
CryptResp = verify_pin( hProv, szGpkPin, dwGpkPinLen );
|
|
|
|
if ( CryptResp )
|
|
{
|
|
dwStatus = ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
Flush_MSPinCache( &(Slot[SlotNb].hPinCacheHandle) );
|
|
dwStatus = SCARD_W_WRONG_CHV;
|
|
}
|
|
memset(szGpkPin, 0, sizeof(szGpkPin));
|
|
dwGpkPinLen=0;
|
|
}
|
|
|
|
if ( dwStatus != ERROR_SUCCESS )
|
|
{
|
|
if ( ProvCont[hProv].Flags & CRYPT_SILENT )
|
|
{
|
|
// Slot[SlotNb].ClearPin();
|
|
//Flush_MSPinCache( &(Slot[SlotNb].hPinCacheHandle) );
|
|
RETURN ( CRYPT_FAILED, SCARD_W_WRONG_CHV );
|
|
}
|
|
|
|
do
|
|
{
|
|
bNewPin = FALSE;
|
|
bChangePin = FALSE;
|
|
|
|
nPinFree = get_pin_free(hProv);
|
|
|
|
// Failure to retrieve PIN free presentation count (-1)
|
|
if ( nPinFree == DWORD(-1) )
|
|
{
|
|
// Slot[SlotNb].ClearPin();
|
|
//Flush_MSPinCache(&(Slot[SlotNb].hPinCacheHandle));
|
|
RETURN ( CRYPT_FAILED, NTE_FAIL );
|
|
}
|
|
else if ( nPinFree > 0 )
|
|
{
|
|
LoadString( g_hInstMod, IDS_GPKCSP_TITLE, szCspTitle, sizeof(szCspTitle)/sizeof(TCHAR) );
|
|
DisplayMessage( TEXT("badpin"), szCspTitle, &nPinFree );
|
|
|
|
for(;;)
|
|
{
|
|
Select_MF( hProv );
|
|
SCardEndTransaction( ProvCont[hProv].hCard, SCARD_LEAVE_CARD );
|
|
|
|
DialogBox( g_hInstRes, TEXT("PINDIALOG"), GetAppWindow(), PinDlgProc );
|
|
|
|
if (dwGpkPinLen != 0)
|
|
{
|
|
bool bCardReinserted=false;
|
|
|
|
if ( !Coherent(hProv, &bCardReinserted) )
|
|
RETURN ( CRYPT_FAILED, NTE_FAIL );
|
|
if(bCardReinserted)
|
|
continue;
|
|
|
|
if (!bChangePin)
|
|
PopulatePins( &Pins, (BYTE *)szGpkPin, dwGpkPinLen, 0, 0 );
|
|
else
|
|
PopulatePins( &Pins, (BYTE *)szGpkPin, dwGpkPinLen, (BYTE *)szGpkNewPin, wGpkNewPinLen );
|
|
|
|
dwStatus = Add_MSPinCache( &(Slot[SlotNb].hPinCacheHandle),
|
|
&Pins,
|
|
Callback_VerifyChangePin2,
|
|
(void*)hProv );
|
|
|
|
memset(szGpkPin, 0, sizeof(szGpkPin));
|
|
dwGpkPinLen=0;
|
|
memset(szGpkNewPin, 0, sizeof(szGpkNewPin));
|
|
wGpkNewPinLen=0;
|
|
if ( dwStatus != ERROR_SUCCESS && dwStatus != SCARD_W_WRONG_CHV )
|
|
{
|
|
RETURN ( CRYPT_FAILED, dwStatus );
|
|
}
|
|
}
|
|
break;
|
|
} // for
|
|
}
|
|
|
|
}
|
|
while ( dwStatus != ERROR_SUCCESS && dwGpkPinLen != 0 && nPinFree > 0 );
|
|
|
|
if ( dwStatus != ERROR_SUCCESS )
|
|
{
|
|
if ( nPinFree == 0 )
|
|
{
|
|
// Slot[SlotNb].ClearPin();
|
|
//Flush_MSPinCache(&(Slot[SlotNb].hPinCacheHandle));
|
|
|
|
if ( ProvCont[hProv].Flags & CRYPT_SILENT )
|
|
{
|
|
RETURN ( CRYPT_FAILED, SCARD_W_CHV_BLOCKED );
|
|
}
|
|
else
|
|
{
|
|
LoadString( g_hInstMod, IDS_GPKCSP_TITLE, szCspTitle, sizeof(szCspTitle)/sizeof(TCHAR) );
|
|
DisplayMessage( TEXT("locked"), szCspTitle, 0 );
|
|
RETURN( CRYPT_FAILED, SCARD_W_CHV_BLOCKED );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Slot[SlotNb].ClearPin();
|
|
//Flush_MSPinCache(&(Slot[SlotNb].hPinCacheHandle));
|
|
RETURN( CRYPT_FAILED, SCARD_W_CANCELLED_BY_USER );
|
|
}
|
|
}
|
|
}
|
|
|
|
memset(szGpkPin, 0x00, PIN_MAX+2);
|
|
memset(szGpkNewPin, 0x00, PIN_MAX+2);
|
|
dwGpkPinLen = 0;
|
|
wGpkNewPinLen = 0;
|
|
|
|
RETURN(CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
|
|
BOOL VerifyDivPIN(HCRYPTPROV hProv, BOOL Local)
|
|
{
|
|
DWORD lRet;
|
|
BYTE MKey[9] = "F1961ACF";
|
|
BYTE ChipSN[8];
|
|
BYTE Data[16];
|
|
BYTE hashData[20];
|
|
DWORD cbData = 20;
|
|
|
|
BYTE DivPIN[8];
|
|
|
|
HCRYPTHASH hHash = 0;
|
|
|
|
// Get Chip Serial Number
|
|
bSendBuffer[0] = 0x80; //CLA
|
|
bSendBuffer[1] = 0xC0; //INS
|
|
bSendBuffer[2] = 0x02; //P1
|
|
bSendBuffer[3] = 0xA0; //P2
|
|
bSendBuffer[4] = 0x08; //Lo
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if (SCARDPROBLEM(lRet,0x9000, bSendBuffer[4]))
|
|
{
|
|
RETURN (CRYPT_FAILED, SCARD_E_UNEXPECTED);
|
|
}
|
|
|
|
ZeroMemory( ChipSN, sizeof(ChipSN) );
|
|
memcpy(ChipSN, bRecvBuffer, min(bSendBuffer[4], sizeof(ChipSN)));
|
|
|
|
|
|
// Create Data buffer
|
|
memcpy(&Data[0], MKey, 8);
|
|
memcpy(&Data[8], ChipSN, 8);
|
|
|
|
// Create a hash object
|
|
if (!CryptCreateHash(hProvBase, CALG_SHA, 0, 0, &hHash))
|
|
return CRYPT_FAILED;
|
|
|
|
// hash data
|
|
if (!CryptHashData(hHash, Data, 16, 0))
|
|
{
|
|
lRet = GetLastError();
|
|
CryptDestroyHash(hHash);
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
// get the hash value
|
|
ZeroMemory( hashData, sizeof(hashData) );
|
|
if (!CryptGetHashParam(hHash, HP_HASHVAL, hashData, &cbData, 0))
|
|
{
|
|
lRet = GetLastError();
|
|
CryptDestroyHash(hHash);
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
|
|
// get the last 8 bytes of the hash value as diversified PIN
|
|
memcpy(DivPIN, &hashData[20-8], 8);
|
|
|
|
CryptDestroyHash(hHash);
|
|
|
|
// Send the VERIFY COMMAND to the card
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0x20; //INS
|
|
bSendBuffer[2] = 0x00; //P1
|
|
if (Local)
|
|
{
|
|
bSendBuffer[3] = 0x02; //P2 -> Locally it is the second PIN
|
|
}
|
|
else
|
|
{
|
|
bSendBuffer[3] = 0x00; //P2 -> At the MF level it is the first PIN
|
|
}
|
|
bSendBuffer[4] = 0x08; //Li
|
|
memset(&bSendBuffer[5], 0x00, 8);
|
|
memcpy(&bSendBuffer[5], DivPIN, 8);
|
|
cbSendLength = 5 + bSendBuffer[4];
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if (SCARDPROBLEM(lRet,0x9000,0x00))
|
|
{
|
|
RETURN( CRYPT_FAILED, SCARD_E_INVALID_CHV );
|
|
}
|
|
|
|
RETURN( CRYPT_SUCCEED, 0 );
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
|
|
static DWORD Select_Crypto_DF(HCRYPTPROV hProv)
|
|
{
|
|
static BYTE GPK8000_ISO_DF[] = { 0xA0,0,0,0,0x18,0xF,0,1,0x63,0,1 };
|
|
|
|
DWORD lRet;
|
|
BOOL CryptResp;
|
|
|
|
// This function is used to avoid to presuppose the state in which the
|
|
// card might be in
|
|
|
|
BOOL fAgain = TRUE;
|
|
int iRetryLimit = 3;
|
|
|
|
while (fAgain)
|
|
{
|
|
if (0 == iRetryLimit--)
|
|
fAgain = FALSE;
|
|
else
|
|
{
|
|
CryptResp = Select_MF(hProv);
|
|
if (CryptResp)
|
|
fAgain = FALSE;
|
|
else
|
|
Sleep(250);
|
|
}
|
|
}
|
|
|
|
if (iRetryLimit < 0)
|
|
{
|
|
DBG_PRINT(TEXT("Select_MF failed"));
|
|
return CRYPT_FAILED;
|
|
}
|
|
|
|
// TT 22/09/99 : We now check for ISO 7816-5 compliant GPK8000
|
|
|
|
ProvCont[hProv].bGPK_ISO_DF = FALSE;
|
|
|
|
bSendBuffer[0] = 0x00;
|
|
bSendBuffer[1] = 0xA4; // Select File
|
|
bSendBuffer[2] = 0x04; // Select DF by name
|
|
bSendBuffer[3] = 0x00; // We want a response
|
|
bSendBuffer[4] = sizeof(GPK8000_ISO_DF);
|
|
memcpy( &bSendBuffer[5], GPK8000_ISO_DF, sizeof(GPK8000_ISO_DF) );
|
|
cbSendLength = sizeof(GPK8000_ISO_DF) + 5;
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
// TT 17/11/99: Must check the status bytes
|
|
if (!(SCARDPROBLEM(lRet,0x61FF,0x00)))
|
|
{
|
|
ProvCont[hProv].bGPK_ISO_DF = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// Select Dedicated Application DF on GPK Card
|
|
BYTE lenDF = strlen(GPK_DF);
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xA4; //INS
|
|
bSendBuffer[2] = 0x04; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = lenDF;
|
|
memcpy( &bSendBuffer[5], GPK_DF, lenDF );
|
|
cbSendLength = 5 + lenDF;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x61FF,0x00))
|
|
{
|
|
DBG_PRINT(TEXT("Select DF failed"));
|
|
RETURN (CRYPT_FAILED, SCARD_E_DIR_NOT_FOUND);
|
|
}
|
|
}
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static BOOL card_is_present (HCRYPTPROV hProv)
|
|
{
|
|
DWORD lRet;
|
|
DWORD SlotNb;
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
/* Read Serial number to check if card is present */
|
|
bSendBuffer[0] = 0x80; //CLA
|
|
bSendBuffer[1] = 0xC0; //INS
|
|
bSendBuffer[2] = 0x02; //P1
|
|
bSendBuffer[3] = 0xA0; //P2
|
|
bSendBuffer[4] = 0x08; //Lo
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit(ProvCont[hProv].hCard,
|
|
SCARD_PCI_T0,
|
|
bSendBuffer,
|
|
cbSendLength,
|
|
NULL,
|
|
bRecvBuffer,
|
|
&cbRecvLength
|
|
);
|
|
|
|
if (SCARDPROBLEM(lRet,0x9000, bSendBuffer[4]))
|
|
{
|
|
RETURN (CRYPT_FAILED, SCARD_E_UNEXPECTED);
|
|
}
|
|
|
|
if (memcmp(bRecvBuffer, Slot[SlotNb].bGpkSerNb, bSendBuffer[4]))
|
|
{
|
|
RETURN (CRYPT_FAILED, SCARD_W_REMOVED_CARD);
|
|
}
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static DWORD Auxiliary_CSP_key_size (DWORD AlgId)
|
|
{
|
|
DWORD i, dwFlags, cbData,dwBits, res;
|
|
BYTE pbData[1000], *ptr;
|
|
ALG_ID aiAlgid;
|
|
|
|
res = 0;
|
|
|
|
// Enumerate Algo.
|
|
for (i=0 ; ; i++)
|
|
{
|
|
if (i == 0)
|
|
dwFlags = CRYPT_FIRST;
|
|
else
|
|
dwFlags = 0;
|
|
|
|
// Retrieve information about an algorithm.
|
|
cbData = sizeof (pbData);
|
|
SetLastError(0);
|
|
if (!CryptGetProvParam(hProvBase, PP_ENUMALGS, pbData, &cbData, dwFlags))
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Extract algorithm information from the ‘pbData’ buffer.
|
|
ptr = pbData;
|
|
aiAlgid = *(ALG_ID UNALIGNED *)ptr;
|
|
if (aiAlgid == AlgId)
|
|
{
|
|
ptr += sizeof(ALG_ID);
|
|
dwBits = *(DWORD UNALIGNED *)ptr;
|
|
res = dwBits;
|
|
break;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static BOOL copy_gpk_key( HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwAlgid )
|
|
{
|
|
BOOL CryptResp;
|
|
DWORD dwDataLen;
|
|
BYTE pbData[1024];
|
|
DWORD SlotNb;
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
NoDisplay = TRUE;
|
|
|
|
if ((hKey >= 1) && (hKey <= MAX_GPK_OBJ))
|
|
{
|
|
dwDataLen = sizeof(pbData);
|
|
ZeroMemory( pbData, sizeof(pbData) );
|
|
if (MyCPExportKey(hProv, hKey, 0, PUBLICKEYBLOB, 0, pbData, &dwDataLen))
|
|
{
|
|
if (dwAlgid == AT_KEYEXCHANGE)
|
|
{
|
|
if (ProvCont[hProv].hRSAKEK != 0)
|
|
{
|
|
CryptResp = CryptDestroyKey (ProvCont[hProv].hRSAKEK);
|
|
if (!CryptResp)
|
|
{
|
|
NoDisplay = FALSE;
|
|
return CRYPT_FAILED;
|
|
}
|
|
ProvCont[hProv].hRSAKEK = 0;
|
|
}
|
|
|
|
CryptResp = CryptImportKey( hProvBase, pbData, dwDataLen, 0, 0,
|
|
&ProvCont[hProv].hRSAKEK );
|
|
|
|
//Slot[SlotNb].GpkObject[hKey].hKeyBase = ProvCont[hProv].hRSAKEK;
|
|
}
|
|
else
|
|
{
|
|
if (ProvCont[hProv].hRSASign!= 0)
|
|
{
|
|
CryptResp = CryptDestroyKey (ProvCont[hProv].hRSASign);
|
|
if (!CryptResp)
|
|
{
|
|
NoDisplay = FALSE;
|
|
return CRYPT_FAILED;
|
|
}
|
|
ProvCont[hProv].hRSASign = 0;
|
|
}
|
|
|
|
CryptResp = CryptImportKey( hProvBase, pbData, dwDataLen, 0, 0,
|
|
&ProvCont[hProv].hRSASign );
|
|
|
|
//Slot[SlotNb].GpkObject[hKey].hKeyBase = ProvCont[hProv].hRSASign;
|
|
}
|
|
|
|
if (!CryptResp)
|
|
{
|
|
NoDisplay = FALSE;
|
|
return CRYPT_FAILED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NoDisplay = FALSE;
|
|
RETURN (CRYPT_FAILED, NTE_BAD_KEY);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NoDisplay = FALSE;
|
|
RETURN (CRYPT_FAILED, NTE_BAD_KEY);
|
|
}
|
|
|
|
NoDisplay = FALSE;
|
|
RETURN(CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static BOOL Select_Key_File(HCRYPTPROV hProv, int KeyFileId)
|
|
{
|
|
DWORD lRet;
|
|
BOOL CryptResp;
|
|
|
|
CryptResp = Select_Crypto_DF(hProv);
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
|
|
/* Select Key File on GPK Card */
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xA4; //INS
|
|
bSendBuffer[2] = 0x02; //P1
|
|
bSendBuffer[3] = 0x0C; //P2
|
|
bSendBuffer[4] = 0x02; //Li
|
|
bSendBuffer[5] = HIBYTE(KeyFileId);
|
|
bSendBuffer[6] = LOBYTE(KeyFileId);
|
|
cbSendLength = 7;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x9000,0x00))
|
|
{
|
|
RETURN (CRYPT_FAILED, SCARD_E_FILE_NOT_FOUND);
|
|
}
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static DWORD Read_NbKeyFile(HCRYPTPROV hProv)
|
|
{
|
|
|
|
DWORD i = 0;
|
|
|
|
while ((i<MAX_REAL_KEY) && Select_Key_File(hProv, GPK_FIRST_KEY + i))
|
|
i++;
|
|
return i;
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
|
|
static void perso_public(HCRYPTPROV hProv, int Start)
|
|
{
|
|
DWORD i, j;
|
|
DWORD SlotNb;
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
for (i = 0; i < Slot[SlotNb].NbKeyFile; i++)
|
|
{
|
|
Slot[SlotNb].GpkObject[Start+4*i+1].IsPrivate = FALSE;
|
|
Slot[SlotNb].GpkObject[Start+4*i+1].Tag = TAG_RSA_PUBLIC;
|
|
Slot[SlotNb].GpkObject[Start+4*i+1].Flags = 0xF000; // Verify + Encrypt + Export + Modifiable
|
|
Slot[SlotNb].GpkObject[Start+4*i+1].FileId = LOBYTE(GPK_FIRST_KEY + i);
|
|
|
|
Slot[SlotNb].GpkObject[Start+4*i+2].IsPrivate = FALSE;
|
|
Slot[SlotNb].GpkObject[Start+4*i+2].Tag = TAG_RSA_PUBLIC;
|
|
Slot[SlotNb].GpkObject[Start+4*i+2].Flags = 0xD000; // Verify + Export + Modifiable
|
|
Slot[SlotNb].GpkObject[Start+4*i+2].FileId = LOBYTE(GPK_FIRST_KEY + i);
|
|
|
|
Slot[SlotNb].GpkObject[Start+4*i+3].IsPrivate = FALSE;
|
|
Slot[SlotNb].GpkObject[Start+4*i+3].Tag = TAG_RSA_PRIVATE;
|
|
Slot[SlotNb].GpkObject[Start+4*i+3].Flags = 0xB000; // Sign + Decrypt + Modifiable
|
|
Slot[SlotNb].GpkObject[Start+4*i+3].FileId = LOBYTE(GPK_FIRST_KEY + i);
|
|
|
|
Slot[SlotNb].GpkObject[Start+4*i+4].IsPrivate = FALSE;
|
|
Slot[SlotNb].GpkObject[Start+4*i+4].Tag = TAG_RSA_PRIVATE;
|
|
Slot[SlotNb].GpkObject[Start+4*i+4].Flags = 0x9000; // Sign + Modifiable
|
|
Slot[SlotNb].GpkObject[Start+4*i+4].FileId = LOBYTE(GPK_FIRST_KEY + i);
|
|
}
|
|
|
|
Slot[SlotNb].NbGpkObject = Start+LOBYTE(4*Slot[SlotNb].NbKeyFile);
|
|
|
|
for (i = Start+1; i <= Slot[SlotNb].NbGpkObject; i++)
|
|
{
|
|
for (j = 0; j < MAX_FIELD; j++)
|
|
{
|
|
Slot[SlotNb].GpkObject[i].Field[j].bReal = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
|
|
static void perso_priv(HCRYPTPROV hProv, int Start)
|
|
{
|
|
DWORD i, j;
|
|
DWORD SlotNb;
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
for (i = 0; i < Slot[SlotNb].NbKeyFile; i++)
|
|
{
|
|
Slot[SlotNb].GpkObject[Start+4*i+1].IsPrivate = TRUE;
|
|
Slot[SlotNb].GpkObject[Start+4*i+1].Tag = TAG_RSA_PUBLIC;
|
|
Slot[SlotNb].GpkObject[Start+4*i+1].Flags = 0xF000; // Verify + Encrypt + Export + Modifiable
|
|
Slot[SlotNb].GpkObject[Start+4*i+1].FileId = LOBYTE(GPK_FIRST_KEY+i);
|
|
|
|
Slot[SlotNb].GpkObject[Start+4*i+2].IsPrivate = TRUE;
|
|
Slot[SlotNb].GpkObject[Start+4*i+2].Tag = TAG_RSA_PUBLIC;
|
|
Slot[SlotNb].GpkObject[Start+4*i+2].Flags = 0xD000; // Verify + Export + Modifiable
|
|
Slot[SlotNb].GpkObject[Start+4*i+2].FileId = LOBYTE(GPK_FIRST_KEY+i);
|
|
|
|
Slot[SlotNb].GpkObject[Start+4*i+3].IsPrivate = TRUE;
|
|
Slot[SlotNb].GpkObject[Start+4*i+3].Tag = TAG_RSA_PRIVATE;
|
|
Slot[SlotNb].GpkObject[Start+4*i+3].Flags = 0xB000; // Sign + Decrypt + Modifiable
|
|
Slot[SlotNb].GpkObject[Start+4*i+3].FileId = LOBYTE(GPK_FIRST_KEY+i);
|
|
|
|
Slot[SlotNb].GpkObject[Start+4*i+4].IsPrivate = TRUE;
|
|
Slot[SlotNb].GpkObject[Start+4*i+4].Tag = TAG_RSA_PRIVATE;
|
|
Slot[SlotNb].GpkObject[Start+4*i+4].Flags = 0x9000; // Sign + Modifiable
|
|
Slot[SlotNb].GpkObject[Start+4*i+4].FileId = LOBYTE(GPK_FIRST_KEY+i);
|
|
}
|
|
|
|
Slot[SlotNb].NbGpkObject = Start+LOBYTE(4*Slot[SlotNb].NbKeyFile);
|
|
|
|
for (i = Start+1; i <= Slot[SlotNb].NbGpkObject; i++)
|
|
{
|
|
for (j = 0; j < MAX_FIELD; j++)
|
|
{
|
|
Slot[SlotNb].GpkObject[i].Field[j].bReal = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
|
|
static void perso_card(HCRYPTPROV hProv, int Start)
|
|
{
|
|
perso_public (hProv, Start);
|
|
perso_priv (hProv, Slot[ProvCont[hProv].Slot].NbGpkObject);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static void zap_gpk_objects( DWORD SlotNb, BOOL IsPrivate)
|
|
{
|
|
WORD
|
|
i, j;
|
|
|
|
if (IsPrivate)
|
|
{
|
|
for (i = 0; i <= MAX_GPK_OBJ; i++)
|
|
{
|
|
if ((Slot[SlotNb].GpkObject[i].IsPrivate) &&
|
|
(Slot[SlotNb].GpkObject[i].Tag > 0))
|
|
{
|
|
for (j = 0; j < MAX_FIELD; j++)
|
|
{
|
|
if (IsNotNull(Slot[SlotNb].GpkObject[i].Field[j].pValue))
|
|
{
|
|
GMEM_Free(Slot[SlotNb].GpkObject[i].Field[j].pValue);
|
|
}
|
|
}
|
|
|
|
for (j = i; j < Slot[SlotNb].NbGpkObject; j++)
|
|
{
|
|
Slot[SlotNb].GpkObject[j] = Slot[SlotNb].GpkObject[j+1];
|
|
}
|
|
|
|
ZeroMemory( &Slot[SlotNb].GpkObject[Slot[SlotNb].NbGpkObject], sizeof(GPK_OBJ));
|
|
|
|
// Since the object i+1 is now at position i, the new object i has to
|
|
// process again.
|
|
|
|
i--;
|
|
Slot[SlotNb].NbGpkObject--;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i <= MAX_GPK_OBJ; i++)
|
|
{
|
|
for (j = 0; j < MAX_FIELD; j++)
|
|
{
|
|
if (IsNotNull(Slot[SlotNb].GpkObject[i].Field[j].pValue))
|
|
{
|
|
GMEM_Free(Slot[SlotNb].GpkObject[i].Field[j].pValue);
|
|
}
|
|
}
|
|
|
|
}
|
|
ZeroMemory( Slot[SlotNb].GpkObject, sizeof(Slot[SlotNb].GpkObject) );
|
|
ZeroMemory( Slot[SlotNb].GpkPubKeys, sizeof(Slot[SlotNb].GpkPubKeys) );
|
|
|
|
Slot[SlotNb].NbGpkObject = 0;
|
|
|
|
for (i = 0; i < MAX_REAL_KEY; i++) // version 2.00.002
|
|
Slot[SlotNb].UseFile[i] = FALSE;
|
|
|
|
}
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static void clean_card(HCRYPTPROV hProv)
|
|
{
|
|
/* Erase the GemSAFE objects of the cards BUT keep the other PKCS#11 objects */
|
|
|
|
WORD i, j;
|
|
DWORD SlotNb;
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
for (i = 0; i <= Slot[SlotNb].NbGpkObject; i++)
|
|
{
|
|
if ((Slot[SlotNb].GpkObject[i].Tag <= TAG_CERTIFICATE) &&
|
|
(Slot[SlotNb].GpkObject[i].Tag > 0))
|
|
{
|
|
for (j = 0; j < MAX_FIELD; j++)
|
|
{
|
|
if (IsNotNull(Slot[SlotNb].GpkObject[i].Field[j].pValue))
|
|
{
|
|
GMEM_Free(Slot[SlotNb].GpkObject[i].Field[j].pValue);
|
|
}
|
|
}
|
|
|
|
for (j = i; j < Slot[SlotNb].NbGpkObject; j++)
|
|
{
|
|
Slot[SlotNb].GpkObject[j] = Slot[SlotNb].GpkObject[j+1];
|
|
}
|
|
|
|
ZeroMemory( &Slot[SlotNb].GpkObject[Slot[SlotNb].NbGpkObject], sizeof(GPK_OBJ) );
|
|
|
|
// Since the object i+1 is now at position i, the new object i has to
|
|
// process again.
|
|
|
|
i--;
|
|
Slot[SlotNb].NbGpkObject--;
|
|
}
|
|
}
|
|
|
|
perso_card (hProv, Slot[SlotNb].NbGpkObject);// value of Slot[SlotNb].NbGpkObject?0?
|
|
ZeroMemory( Slot[SlotNb].GpkPubKeys, sizeof(Slot[SlotNb].GpkPubKeys) );
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static BYTE get_gpk_object_nb(HCRYPTPROV hProv, BYTE ObjId, BOOL IsPrivate)
|
|
{
|
|
BYTE i;
|
|
DWORD SlotNb;
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
for (i = 1; i <= Slot[SlotNb].NbGpkObject; i++)
|
|
{
|
|
if ((Slot[SlotNb].GpkObject[i].IsPrivate == IsPrivate)
|
|
&&(Slot[SlotNb].GpkObject[i].ObjId == ObjId)
|
|
)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (i);
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static BYTE calc_gpk_field(HCRYPTPROV hProv, BYTE ObjId)
|
|
{
|
|
BYTE i;
|
|
DWORD SlotNb;
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
for (i = Slot[SlotNb].GpkObject[ObjId].LastField; i <= 15; i++)
|
|
{
|
|
if (Slot[SlotNb].GpkObject[ObjId].Flags & 1<<i)
|
|
{
|
|
Slot[SlotNb].GpkObject[ObjId].LastField = i+1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (i);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static BYTE find_gpk_obj_tag_type( HCRYPTPROV hProv,
|
|
BYTE KeyTag,
|
|
BYTE KeyType,
|
|
BYTE KeyLen,
|
|
BOOL IsExchange,
|
|
BOOL IsPrivate
|
|
)
|
|
{
|
|
BYTE i, tmp;
|
|
DWORD SlotNb;
|
|
BYTE keysetID;
|
|
GPK_OBJ* pObject;
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
tmp = 0;
|
|
|
|
for (i = 1; i <= Slot[SlotNb].NbGpkObject; i++)
|
|
{
|
|
pObject = &Slot[SlotNb].GpkObject[i];
|
|
|
|
if ( pObject->Tag != KeyTag )
|
|
continue;
|
|
|
|
if ( pObject->IsPrivate != IsPrivate )
|
|
continue;
|
|
|
|
if (IsExchange && !(pObject->Flags & FLAG_EXCHANGE))
|
|
continue;
|
|
|
|
if ( (KeyType == 0xFF)
|
|
|| (KeyType == 0x00 && !pObject->IsCreated && pObject->PubKey.KeySize == KeyLen)
|
|
|| (KeyType != 0x00 && pObject->IsCreated && pObject->Field[POS_KEY_TYPE].pValue[0] == KeyType)
|
|
)
|
|
{
|
|
// Key file...
|
|
if (!Slot[SlotNb].UseFile[pObject->FileId - GPK_FIRST_KEY])
|
|
{
|
|
// If the file never has been used, use it. Otherwise, keep on the search
|
|
return i;
|
|
}
|
|
else
|
|
{
|
|
// Not a key file...
|
|
// Keep this possible choice. The file has already been
|
|
// used but another one may exist.
|
|
if (ProvCont[hProv].bLegacyKeyset)
|
|
{
|
|
tmp = i;
|
|
}
|
|
else
|
|
{
|
|
if ( (pObject->Flags & FLAG_KEYSET)
|
|
&& (pObject->Field[POS_KEYSET].pValue))
|
|
{
|
|
keysetID = pObject->Field[POS_KEYSET].pValue[0];
|
|
if (keysetID == ProvCont[hProv].keysetID)
|
|
{
|
|
tmp = i;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return tmp;
|
|
}
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
|
|
static BYTE find_gpk_obj_tag_file(HCRYPTPROV hProv, BYTE KeyTag, BYTE FileId, BOOL IsExchange)
|
|
{
|
|
BYTE i;
|
|
DWORD SlotNb;
|
|
GPK_OBJ* pObject;
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
for (i = 1; i <= Slot[SlotNb].NbGpkObject; i++)
|
|
{
|
|
pObject = &Slot[SlotNb].GpkObject[i];
|
|
|
|
if (pObject->Tag != KeyTag)
|
|
continue;
|
|
|
|
if (pObject->FileId != FileId)
|
|
continue;
|
|
|
|
if (pObject->IsPrivate == FALSE)
|
|
continue;
|
|
|
|
if (IsExchange && !(pObject->Flags & FLAG_EXCHANGE))
|
|
continue;
|
|
|
|
if (!pObject->IsCreated)
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static BOOL read_gpk_pub_key(HCRYPTPROV hProv,
|
|
HCRYPTKEY hKey,
|
|
GPK_EXP_KEY *PubKey
|
|
)
|
|
{
|
|
|
|
DWORD lRet;
|
|
BYTE Sfi, RecLen, RecNum;
|
|
BOOL IsLast = FALSE;
|
|
DWORD SlotNb;
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
ZeroMemory( PubKey, sizeof(GPK_EXP_KEY) );
|
|
|
|
/* Check if Public Key file already read to avoid new access if possible */
|
|
if (Slot[SlotNb].GpkPubKeys[Slot[SlotNb].GpkObject[hKey].FileId - GPK_FIRST_KEY].KeySize > 0)
|
|
{
|
|
memcpy(PubKey,
|
|
&(Slot[SlotNb].GpkPubKeys[Slot[SlotNb].GpkObject[hKey].FileId - GPK_FIRST_KEY]),
|
|
sizeof(GPK_EXP_KEY)
|
|
);
|
|
RETURN(CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
/* Initialize Default Public key value */
|
|
memcpy(PubKey->Exposant, "\x01\x00\x01", 3);
|
|
PubKey->ExpSize = 3;
|
|
|
|
/* Calculate Short File id of PK file for P2 parameter */
|
|
Sfi = 0x04 | (Slot[SlotNb].GpkObject[hKey].FileId<<3);
|
|
|
|
/* First record to read is number 2, number 1 is reserved for TAG_INFO */
|
|
RecNum = 2;
|
|
do
|
|
{
|
|
/* Read Record (RecNum) to get size */
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xB2; //INS
|
|
bSendBuffer[2] = RecNum; //P1
|
|
bSendBuffer[3] = Sfi; //P2
|
|
bSendBuffer[4] = 0xFB; //Lo
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x0000,0xFF))
|
|
{
|
|
RETURN (CRYPT_FAILED, SCARD_W_EOF);
|
|
}
|
|
|
|
if (2 == cbRecvLength)
|
|
{
|
|
//
|
|
// If the receive length is two bytes, we know there's an error
|
|
// condition.
|
|
//
|
|
|
|
if (bRecvBuffer[0] == 0x6C) // Communication bufer exceeded
|
|
{
|
|
// Re-send the request for the same record, this time with
|
|
// the correct record length.
|
|
|
|
RecLen = bRecvBuffer[1];
|
|
|
|
/* Read Record (RecNum) to get value */
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xB2; //INS
|
|
bSendBuffer[2] = RecNum; //P1
|
|
bSendBuffer[3] = Sfi; //P2
|
|
bSendBuffer[4] = RecLen; //Lo
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x9000,bSendBuffer[4]))
|
|
{
|
|
RETURN (CRYPT_FAILED, SCARD_W_EOF);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Some other error occurred. We're done.
|
|
IsLast = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Received a valid response from the card. Set the correct
|
|
// record length for this case.
|
|
|
|
RecLen = (BYTE) (cbRecvLength - 2); // subtract length of status bytes
|
|
}
|
|
|
|
/* Which Record is it? */
|
|
switch (bRecvBuffer[0])
|
|
{
|
|
/* This is the Modulus */
|
|
case 0x01:
|
|
{
|
|
ZeroMemory( PubKey->Modulus, PubKey->KeySize );
|
|
PubKey->KeySize = RecLen-1;
|
|
r_memcpy(PubKey->Modulus, &bRecvBuffer[1],RecLen-1);
|
|
}
|
|
break;
|
|
|
|
/* This is the Public Exposant */
|
|
case 0x06:
|
|
case 0x07:
|
|
{
|
|
ZeroMemory( PubKey->Exposant, PubKey->ExpSize );
|
|
PubKey->ExpSize = RecLen-1;
|
|
r_memcpy(PubKey->Exposant, &bRecvBuffer[1],RecLen-1);
|
|
}
|
|
break;
|
|
|
|
/* This is an unknown or not signifiant record, ignore it */
|
|
default:
|
|
break;
|
|
}
|
|
|
|
RecNum++;
|
|
}
|
|
while (!IsLast);
|
|
|
|
if ((PubKey->KeySize == 0) || (PubKey->ExpSize == 0))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_PUBLIC_KEY);
|
|
}
|
|
|
|
/* Store Public key to avoid new read if requested */
|
|
memcpy(&(Slot[SlotNb].GpkPubKeys[Slot[SlotNb].GpkObject[hKey].FileId - GPK_FIRST_KEY]),
|
|
PubKey,
|
|
sizeof(GPK_EXP_KEY)
|
|
);
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static BOOL read_gpk_objects(HCRYPTPROV hProv, BOOL IsPrivate)
|
|
{
|
|
DWORD lRet;
|
|
DWORD
|
|
dwGpkObjLen,
|
|
dwNumberofCommands,
|
|
dwLastCommandLen,
|
|
dwCommandLen,
|
|
i, j,
|
|
dwLen,
|
|
dwNb,
|
|
FirstObj;
|
|
BYTE
|
|
curId,
|
|
EmptyBuff[512];
|
|
DWORD SlotNb;
|
|
WORD offset;
|
|
|
|
|
|
|
|
ZeroMemory( EmptyBuff, sizeof(EmptyBuff) );
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
BeginWait();
|
|
|
|
zap_gpk_objects( SlotNb, IsPrivate);
|
|
FirstObj = Slot[SlotNb].NbGpkObject;
|
|
|
|
/* Select Dedicated Object storage EF on GPK Card */
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xA4; //INS
|
|
bSendBuffer[2] = 0x02; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = 0x02; //Li
|
|
if (IsPrivate)
|
|
{
|
|
bSendBuffer[5] = HIBYTE(GPK_OBJ_PRIV_EF);
|
|
bSendBuffer[6] = LOBYTE(GPK_OBJ_PRIV_EF);
|
|
}
|
|
else
|
|
{
|
|
bSendBuffer[5] = HIBYTE(GPK_OBJ_PUB_EF);
|
|
bSendBuffer[6] = LOBYTE(GPK_OBJ_PUB_EF);
|
|
}
|
|
cbSendLength = 7;
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if (SCARDPROBLEM(lRet,0x61FF,0x00))
|
|
{
|
|
if (IsPrivate)
|
|
{
|
|
perso_priv (hProv, Slot[SlotNb].NbGpkObject);
|
|
}
|
|
else
|
|
{
|
|
perso_public (hProv, Slot[SlotNb].NbGpkObject);
|
|
}
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
/* Get Response */
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xC0; //INS
|
|
bSendBuffer[2] = 0x00; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = bRecvBuffer[1]; //Lo
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if (SCARDPROBLEM(lRet,0x9000,bSendBuffer[4]))
|
|
{
|
|
RETURN (CRYPT_FAILED, SCARD_E_UNEXPECTED);
|
|
}
|
|
dwGpkObjLen = bRecvBuffer[8]*256 + bRecvBuffer[9];
|
|
|
|
if (IsNotNull(g_pbGpkObj))
|
|
{
|
|
GMEM_Free(g_pbGpkObj);
|
|
}
|
|
g_pbGpkObj = (BYTE*)GMEM_Alloc(dwGpkObjLen);
|
|
if (IsNull(g_pbGpkObj))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
/* Read the Objects EF */
|
|
dwNumberofCommands = (dwGpkObjLen-1)/FILE_CHUNK_SIZE + 1;
|
|
dwLastCommandLen = dwGpkObjLen%FILE_CHUNK_SIZE;
|
|
|
|
if (dwLastCommandLen == 0)
|
|
{
|
|
dwLastCommandLen = FILE_CHUNK_SIZE;
|
|
}
|
|
|
|
dwCommandLen = FILE_CHUNK_SIZE;
|
|
for (i=0; i < dwNumberofCommands ; i++)
|
|
{
|
|
if (i == dwNumberofCommands - 1)
|
|
{
|
|
dwCommandLen = dwLastCommandLen;
|
|
}
|
|
/* Read FILE_CHUCK_SIZE bytes or last bytes */
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xB0; //INS
|
|
offset = (WORD)(i * FILE_CHUNK_SIZE) / ProvCont[hProv].dataUnitSize;
|
|
bSendBuffer[2] = HIBYTE( offset );
|
|
bSendBuffer[3] = LOBYTE( offset );
|
|
bSendBuffer[4] = (BYTE) dwCommandLen; //Lo
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if (SCARDPROBLEM(lRet,0x9000,bSendBuffer[4]))
|
|
RETURN( CRYPT_FAILED, SCARD_W_EOF );
|
|
|
|
memcpy( &g_pbGpkObj[i*FILE_CHUNK_SIZE], bRecvBuffer, cbRecvLength - 2 );
|
|
|
|
if (memcmp(bRecvBuffer, EmptyBuff, cbRecvLength -2) == 0)
|
|
break;
|
|
}
|
|
|
|
// Fill Gpk Fixed Objects structure with read Buffer
|
|
i = 0;
|
|
while (i < dwGpkObjLen)
|
|
{
|
|
// No more fixed object
|
|
if (g_pbGpkObj[i] == 0x00)
|
|
{
|
|
i++;
|
|
break;
|
|
}
|
|
|
|
if (Slot[SlotNb].NbGpkObject >= MAX_GPK_OBJ)
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
|
|
Slot[SlotNb].NbGpkObject++;
|
|
|
|
// Initalize fields
|
|
for (j = 0; j < MAX_FIELD; j++)
|
|
{
|
|
Slot[SlotNb].GpkObject[Slot[SlotNb].NbGpkObject].Field[j].bReal = TRUE;
|
|
}
|
|
|
|
// Tag
|
|
Slot[SlotNb].GpkObject[Slot[SlotNb].NbGpkObject].Tag = g_pbGpkObj[i];
|
|
|
|
i++;
|
|
|
|
if (i > dwGpkObjLen-1)
|
|
RETURN( CRYPT_FAILED, SCARD_W_EOF );
|
|
|
|
// Flags
|
|
Slot[SlotNb].GpkObject[Slot[SlotNb].NbGpkObject].Flags = (g_pbGpkObj[i]*256) + g_pbGpkObj[i+1];
|
|
i = i + 2;
|
|
|
|
// IsPrivate
|
|
Slot[SlotNb].GpkObject[Slot[SlotNb].NbGpkObject].IsPrivate = IsPrivate;
|
|
|
|
// IsCreated
|
|
if (Slot[SlotNb].GpkObject[Slot[SlotNb].NbGpkObject].Tag >= TAG_CERTIFICATE)
|
|
{
|
|
Slot[SlotNb].GpkObject[Slot[SlotNb].NbGpkObject].IsCreated = TRUE;
|
|
}
|
|
else if ((Slot[SlotNb].GpkObject[Slot[SlotNb].NbGpkObject].Tag <= TAG_DSA_PRIVATE)
|
|
&&(Slot[SlotNb].GpkObject[Slot[SlotNb].NbGpkObject].Flags & FLAG_KEY_TYPE)
|
|
)
|
|
{
|
|
Slot[SlotNb].GpkObject[Slot[SlotNb].NbGpkObject].IsCreated = TRUE;
|
|
}
|
|
else
|
|
{
|
|
Slot[SlotNb].GpkObject[Slot[SlotNb].NbGpkObject].IsCreated = FALSE;
|
|
}
|
|
|
|
// Object Id ?
|
|
if ((Slot[SlotNb].GpkObject[Slot[SlotNb].NbGpkObject].Flags & 0x0FFF) != 0x0000)
|
|
{
|
|
if (i > dwGpkObjLen)
|
|
{
|
|
RETURN (CRYPT_FAILED, SCARD_W_EOF);
|
|
}
|
|
Slot[SlotNb].GpkObject[Slot[SlotNb].NbGpkObject].ObjId = g_pbGpkObj[i];
|
|
i++;
|
|
}
|
|
else
|
|
{
|
|
Slot[SlotNb].GpkObject[Slot[SlotNb].NbGpkObject].ObjId = 0xFF;
|
|
}
|
|
|
|
// File Id ?
|
|
if (Slot[SlotNb].GpkObject[Slot[SlotNb].NbGpkObject].Tag <= TAG_CERTIFICATE)
|
|
{
|
|
if (i > dwGpkObjLen)
|
|
{
|
|
RETURN (CRYPT_FAILED, SCARD_W_EOF);
|
|
}
|
|
Slot[SlotNb].GpkObject[Slot[SlotNb].NbGpkObject].FileId = g_pbGpkObj[i];
|
|
i++;
|
|
|
|
if (Slot[SlotNb].GpkObject[Slot[SlotNb].NbGpkObject].IsCreated)
|
|
{
|
|
// If the object has been created, the corresponding key file is used
|
|
Slot[SlotNb].UseFile[ Slot[SlotNb].GpkObject[Slot[SlotNb].NbGpkObject].FileId - GPK_FIRST_KEY] = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fill Gpk Variable Objects structure with read Buffer
|
|
curId = 0;
|
|
dwNb = 0;
|
|
while (i < dwGpkObjLen)
|
|
{
|
|
if (g_pbGpkObj[i] == 0xFF)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Field length
|
|
dwLen = 0;
|
|
if (g_pbGpkObj[i] & 0x80)
|
|
{
|
|
dwLen = (g_pbGpkObj[i] & 0x7F) * 256;
|
|
i++;
|
|
}
|
|
|
|
if (i > dwGpkObjLen)
|
|
{
|
|
RETURN (CRYPT_FAILED, SCARD_W_EOF);
|
|
}
|
|
|
|
dwLen = dwLen + g_pbGpkObj[i];
|
|
i++;
|
|
|
|
/* Object Id for retrieve object number */
|
|
if (i > dwGpkObjLen)
|
|
{
|
|
RETURN (CRYPT_FAILED, SCARD_W_EOF);
|
|
}
|
|
|
|
curId = g_pbGpkObj[i];
|
|
i++;
|
|
dwNb = get_gpk_object_nb(hProv, curId, IsPrivate);
|
|
j = calc_gpk_field(hProv, (BYTE)dwNb);
|
|
|
|
/* Object Field length */
|
|
Slot[SlotNb].GpkObject[dwNb].Field[j].Len = (WORD)dwLen;
|
|
|
|
/* Object Field value */
|
|
if (dwLen > 0)
|
|
{
|
|
if ((i + dwLen - 1)> dwGpkObjLen)
|
|
{
|
|
RETURN (CRYPT_FAILED, SCARD_W_EOF);
|
|
}
|
|
|
|
Slot[SlotNb]. GpkObject[dwNb].Field[j].pValue = (BYTE*)GMEM_Alloc(dwLen);
|
|
if (IsNull(Slot[SlotNb].GpkObject[dwNb].Field[j].pValue))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
memcpy(Slot[SlotNb].GpkObject[dwNb].Field[j].pValue, &g_pbGpkObj[i], dwLen);
|
|
i = i + dwLen;
|
|
Slot[SlotNb].GpkObject[dwNb].Field[j].bReal = TRUE;
|
|
}
|
|
else
|
|
{
|
|
Slot[SlotNb].GpkObject[dwNb].Field[j].bReal = FALSE;
|
|
}
|
|
}
|
|
|
|
/* Read Extra objects attributes */
|
|
for (i = FirstObj+1; i <= Slot[SlotNb].NbGpkObject; i++)
|
|
{
|
|
/* RSA Public or Private keys */
|
|
if ((Slot[SlotNb].GpkObject[i].Tag == TAG_RSA_PUBLIC)
|
|
||(Slot[SlotNb].GpkObject[i].Tag == TAG_RSA_PRIVATE)
|
|
)
|
|
{
|
|
/* Modulus and Public Exponant */
|
|
if (!read_gpk_pub_key(hProv, i, &(Slot[SlotNb].GpkObject[i].PubKey)))
|
|
return CRYPT_FAILED;
|
|
|
|
//if ((Slot[SlotNb].GpkObject[i].Flags & FLAG_EXCHANGE) == FLAG_EXCHANGE)
|
|
//{
|
|
// Slot[SlotNb].GpkObject[i].hKeyBase = ProvCont[hProv].hRSAKEK;
|
|
//}
|
|
//else
|
|
//{
|
|
// Slot[SlotNb].GpkObject[i].hKeyBase = ProvCont[hProv].hRSASign;
|
|
//}
|
|
}
|
|
|
|
/* X509 Certificate */
|
|
if (Slot[SlotNb].GpkObject[i].Tag == TAG_CERTIFICATE)
|
|
{
|
|
/* Uncompress Certificate Value if necessary */
|
|
if ((Slot[SlotNb].GpkObject[i].Field[POS_VALUE].Len > 0)
|
|
&&(Slot[SlotNb].GpkObject[i].Field[POS_VALUE].pValue[0] != 0x30)
|
|
)
|
|
{
|
|
BLOC InpBlock, OutBlock;
|
|
|
|
InpBlock.usLen = (USHORT)Slot[SlotNb].GpkObject[i].Field[POS_VALUE].Len;
|
|
InpBlock.pData = Slot[SlotNb].GpkObject[i].Field[POS_VALUE].pValue;
|
|
|
|
OutBlock.usLen = 0;
|
|
OutBlock.pData = 0;
|
|
|
|
if (CC_Uncompress(&InpBlock, &OutBlock) != RV_SUCCESS)
|
|
{
|
|
RETURN(CRYPT_FAILED, SCARD_E_CERTIFICATE_UNAVAILABLE);
|
|
}
|
|
|
|
OutBlock.pData = (BYTE*)GMEM_Alloc (OutBlock.usLen);
|
|
if (IsNull(OutBlock.pData))
|
|
{
|
|
RETURN(CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
if (CC_Uncompress(&InpBlock, &OutBlock) != RV_SUCCESS)
|
|
{
|
|
GMEM_Free (OutBlock.pData);
|
|
RETURN(CRYPT_FAILED, SCARD_E_CERTIFICATE_UNAVAILABLE);
|
|
}
|
|
|
|
GMEM_Free(Slot[SlotNb].GpkObject[i].Field[POS_VALUE].pValue);
|
|
|
|
Slot[SlotNb].GpkObject[i].Field[POS_VALUE].pValue = (BYTE*)GMEM_Alloc(OutBlock.usLen);
|
|
if (IsNull(Slot[SlotNb].GpkObject[i].Field[POS_VALUE].pValue))
|
|
{
|
|
GMEM_Free (OutBlock.pData);
|
|
RETURN(CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
memcpy(Slot[SlotNb].GpkObject[i].Field[POS_VALUE].pValue,
|
|
OutBlock.pData,
|
|
OutBlock.usLen
|
|
);
|
|
Slot[SlotNb].GpkObject[i].Field[POS_VALUE].Len = OutBlock.usLen;
|
|
GMEM_Free(OutBlock.pData);
|
|
}
|
|
|
|
/* Associated RSA key */
|
|
if (Slot[SlotNb].GpkObject[i].FileId != 0)
|
|
{
|
|
if (!read_gpk_pub_key(hProv, i, &(Slot[SlotNb].GpkObject[i].PubKey)))
|
|
return CRYPT_FAILED;
|
|
}
|
|
}
|
|
}
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static BOOL prepare_write_gpk_objects(HCRYPTPROV hProv, BYTE *pbGpkObj, DWORD *dwGpkObjLen, BOOL IsPrivate)
|
|
{
|
|
DWORD lRet;
|
|
DWORD
|
|
i, j, dwNb;
|
|
WORD
|
|
FieldLen;
|
|
BYTE
|
|
ObjId;
|
|
BLOC
|
|
InpBlock,
|
|
OutBlock;
|
|
DWORD SlotNb;
|
|
DWORD FileLen;
|
|
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
i = 0;
|
|
|
|
|
|
/* Remap Internal GPK ObjId */
|
|
ObjId = 0;
|
|
for (dwNb = 1; dwNb <= Slot[SlotNb].NbGpkObject; dwNb++)
|
|
{
|
|
if (((Slot[SlotNb].GpkObject[dwNb].Flags & 0x0FFF) != 0x0000) &&
|
|
(Slot[SlotNb].GpkObject[dwNb].IsPrivate == IsPrivate)
|
|
)
|
|
{
|
|
Slot[SlotNb].GpkObject[dwNb].ObjId = ObjId;
|
|
ObjId++;
|
|
}
|
|
}
|
|
|
|
/* Fixed Object part */
|
|
for (dwNb = 1; dwNb <= Slot[SlotNb].NbGpkObject; dwNb++)
|
|
{
|
|
|
|
if (Slot[SlotNb].GpkObject[dwNb].IsPrivate != IsPrivate)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
/* Tag */
|
|
if (i > *dwGpkObjLen)
|
|
{
|
|
*dwGpkObjLen = 0;
|
|
RETURN (CRYPT_FAILED, SCARD_E_WRITE_TOO_MANY);
|
|
}
|
|
|
|
pbGpkObj[i] = Slot[SlotNb].GpkObject[dwNb].Tag;
|
|
|
|
i++;
|
|
|
|
/* Flag */
|
|
if (i > *dwGpkObjLen)
|
|
{
|
|
*dwGpkObjLen = 0;
|
|
RETURN (CRYPT_FAILED, SCARD_E_WRITE_TOO_MANY);
|
|
}
|
|
|
|
pbGpkObj[i] = HIBYTE(Slot[SlotNb].GpkObject[dwNb].Flags);
|
|
|
|
i++;
|
|
|
|
if (i > *dwGpkObjLen)
|
|
{
|
|
*dwGpkObjLen = 0;
|
|
RETURN (CRYPT_FAILED, SCARD_E_WRITE_TOO_MANY);
|
|
}
|
|
|
|
pbGpkObj[i] = LOBYTE(Slot[SlotNb].GpkObject[dwNb].Flags);
|
|
|
|
if (i > *dwGpkObjLen)
|
|
{
|
|
*dwGpkObjLen = 0;
|
|
RETURN (CRYPT_FAILED, SCARD_E_WRITE_TOO_MANY);
|
|
}
|
|
|
|
i++;
|
|
|
|
/* Object Id ? */
|
|
if (((Slot[SlotNb].GpkObject[dwNb].Flags & 0x0FFF) != 0x0000) &&
|
|
(Slot[SlotNb].GpkObject[dwNb].IsPrivate == IsPrivate)
|
|
)
|
|
{
|
|
if (i > *dwGpkObjLen)
|
|
{
|
|
*dwGpkObjLen = 0;
|
|
RETURN (CRYPT_FAILED, SCARD_E_WRITE_TOO_MANY);
|
|
}
|
|
pbGpkObj[i] = Slot[SlotNb].GpkObject[dwNb].ObjId;
|
|
|
|
i++;
|
|
}
|
|
|
|
/* File Id ? */
|
|
if (Slot[SlotNb].GpkObject[dwNb].Tag <= TAG_CERTIFICATE)
|
|
{
|
|
if (i > *dwGpkObjLen)
|
|
{
|
|
*dwGpkObjLen = 0;
|
|
RETURN (CRYPT_FAILED, SCARD_E_WRITE_TOO_MANY);
|
|
}
|
|
pbGpkObj[i] = Slot[SlotNb].GpkObject[dwNb].FileId;
|
|
i++;
|
|
}
|
|
}
|
|
if (i > *dwGpkObjLen)
|
|
{
|
|
*dwGpkObjLen = 0;
|
|
RETURN (CRYPT_FAILED, SCARD_E_WRITE_TOO_MANY);
|
|
}
|
|
pbGpkObj[i] = 0x00;
|
|
i++;
|
|
|
|
/* Variable Object part */
|
|
for (dwNb = 1; dwNb <= Slot[SlotNb].NbGpkObject; dwNb++)
|
|
{
|
|
if (Slot[SlotNb].GpkObject[dwNb].IsPrivate != IsPrivate)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
for (j = 0; j < MAX_FIELD; j++)
|
|
{
|
|
if (( (Slot[SlotNb].GpkObject[dwNb].Field[j].Len != 0) &&
|
|
(Slot[SlotNb].GpkObject[dwNb].Field[j].bReal)
|
|
) ||
|
|
( (Slot[SlotNb].GpkObject[dwNb].Field[j].Len == 0) &&
|
|
(!Slot[SlotNb].GpkObject[dwNb].Field[j].bReal)
|
|
)
|
|
)
|
|
{
|
|
OutBlock.usLen = 0;
|
|
|
|
/* Field Length */
|
|
if (Slot[SlotNb].GpkObject[dwNb].Field[j].bReal)
|
|
{
|
|
FieldLen = Slot[SlotNb].GpkObject[dwNb].Field[j].Len;
|
|
|
|
/* Try to Compress Certificate Value */
|
|
if ((j == POS_VALUE)
|
|
&&(Slot[SlotNb].GpkObject[dwNb].Tag == TAG_CERTIFICATE)
|
|
&&(Slot[SlotNb].GpkObject[dwNb].Field[POS_VALUE].Len > 0)
|
|
&&(Slot[SlotNb].GpkObject[dwNb].Field[POS_VALUE].pValue[0] == 0x30)
|
|
)
|
|
{
|
|
InpBlock.usLen = (USHORT)Slot[SlotNb].GpkObject[dwNb].Field[POS_VALUE].Len;
|
|
InpBlock.pData = Slot[SlotNb].GpkObject[dwNb].Field[POS_VALUE].pValue;
|
|
|
|
OutBlock.usLen = InpBlock.usLen+1;
|
|
OutBlock.pData = (BYTE*)GMEM_Alloc(OutBlock.usLen);
|
|
|
|
if (IsNull(OutBlock.pData))
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_NO_MEMORY );
|
|
}
|
|
|
|
if (CC_Compress(&InpBlock, &OutBlock) != RV_SUCCESS)
|
|
{
|
|
OutBlock.usLen = 0;
|
|
}
|
|
else
|
|
{
|
|
FieldLen = OutBlock.usLen;
|
|
}
|
|
}
|
|
|
|
if (FieldLen > 0x7F)
|
|
{
|
|
if (i > *dwGpkObjLen)
|
|
{
|
|
GMEM_Free(OutBlock.pData);
|
|
*dwGpkObjLen = 0;
|
|
RETURN (CRYPT_FAILED, SCARD_E_WRITE_TOO_MANY);
|
|
}
|
|
pbGpkObj[i] = HIBYTE(FieldLen) | 0x80;
|
|
i++;
|
|
}
|
|
|
|
if (i > *dwGpkObjLen)
|
|
{
|
|
GMEM_Free(OutBlock.pData);
|
|
*dwGpkObjLen = 0;
|
|
RETURN (CRYPT_FAILED, SCARD_E_WRITE_TOO_MANY);
|
|
}
|
|
pbGpkObj[i] = LOBYTE(FieldLen);
|
|
i++;
|
|
}
|
|
else
|
|
{
|
|
if (i > *dwGpkObjLen)
|
|
{
|
|
GMEM_Free(OutBlock.pData);
|
|
*dwGpkObjLen = 0;
|
|
RETURN (CRYPT_FAILED, SCARD_E_WRITE_TOO_MANY);
|
|
}
|
|
pbGpkObj[i] = 0x00;
|
|
i++;
|
|
}
|
|
|
|
/* Object Id */
|
|
if (i > *dwGpkObjLen)
|
|
{
|
|
GMEM_Free(OutBlock.pData);
|
|
*dwGpkObjLen = 0;
|
|
RETURN (CRYPT_FAILED, SCARD_E_WRITE_TOO_MANY);
|
|
}
|
|
pbGpkObj[i] = Slot[SlotNb].GpkObject[dwNb].ObjId;
|
|
i++;
|
|
|
|
/* Field Value */
|
|
if (Slot[SlotNb].GpkObject[dwNb].Field[j].bReal)
|
|
{
|
|
if ((j == POS_VALUE)
|
|
&&(Slot[SlotNb].GpkObject[dwNb].Tag == TAG_CERTIFICATE)
|
|
&&(OutBlock.usLen > 0)
|
|
)
|
|
{
|
|
if ((i+OutBlock.usLen-1) > *dwGpkObjLen)
|
|
{
|
|
GMEM_Free(OutBlock.pData);
|
|
*dwGpkObjLen = 0;
|
|
RETURN (CRYPT_FAILED, SCARD_E_WRITE_TOO_MANY);
|
|
}
|
|
memcpy(&pbGpkObj[i],
|
|
OutBlock.pData,
|
|
OutBlock.usLen
|
|
);
|
|
|
|
i = i + OutBlock.usLen;
|
|
|
|
GMEM_Free(OutBlock.pData);
|
|
OutBlock.usLen = 0;
|
|
}
|
|
else
|
|
{
|
|
if ((i+Slot[SlotNb].GpkObject[dwNb].Field[j].Len-1) > *dwGpkObjLen)
|
|
{
|
|
*dwGpkObjLen = 0;
|
|
RETURN (CRYPT_FAILED, SCARD_E_WRITE_TOO_MANY);
|
|
}
|
|
|
|
memcpy(&pbGpkObj[i],
|
|
Slot[SlotNb].GpkObject[dwNb].Field[j].pValue,
|
|
Slot[SlotNb].GpkObject[dwNb].Field[j].Len
|
|
);
|
|
i = i + Slot[SlotNb].GpkObject[dwNb].Field[j].Len;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (i > *dwGpkObjLen)
|
|
{
|
|
RETURN (CRYPT_FAILED, SCARD_E_WRITE_TOO_MANY);
|
|
}
|
|
|
|
pbGpkObj[i] = 0xFF;
|
|
*dwGpkObjLen = i+1;
|
|
|
|
/* Select Dedicated Object storage EF on GPK Card */
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xA4; //INS
|
|
bSendBuffer[2] = 0x02; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = 0x02; //Li
|
|
if (IsPrivate)
|
|
{
|
|
bSendBuffer[5] = HIBYTE(GPK_OBJ_PRIV_EF);
|
|
bSendBuffer[6] = LOBYTE(GPK_OBJ_PRIV_EF);
|
|
}
|
|
else
|
|
{
|
|
bSendBuffer[5] = HIBYTE(GPK_OBJ_PUB_EF);
|
|
bSendBuffer[6] = LOBYTE(GPK_OBJ_PUB_EF);
|
|
}
|
|
cbSendLength = 7;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if (SCARDPROBLEM(lRet,0x61FF,0x00))
|
|
RETURN( CRYPT_FAILED, SCARD_E_FILE_NOT_FOUND );
|
|
|
|
/* Get Response */
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xC0; //INS
|
|
bSendBuffer[2] = 0x00; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = bRecvBuffer[1]; //Lo
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if (SCARDPROBLEM(lRet,0x9000,bSendBuffer[4]))
|
|
RETURN( CRYPT_FAILED, SCARD_E_UNEXPECTED );
|
|
|
|
FileLen = bRecvBuffer[8]*256 + bRecvBuffer[9];
|
|
|
|
if (*dwGpkObjLen < FileLen)
|
|
{
|
|
RETURN( CRYPT_SUCCEED, 0 );
|
|
}
|
|
else
|
|
{
|
|
*dwGpkObjLen = 0;
|
|
RETURN( CRYPT_FAILED, SCARD_E_WRITE_TOO_MANY );
|
|
}
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static BOOL write_gpk_objects(HCRYPTPROV hProv, BYTE *pbGpkObj, DWORD dwGpkObjLen, BOOL IsErase, BOOL IsPrivate)
|
|
{
|
|
DWORD lRet,
|
|
i,
|
|
dwCommandLen,
|
|
dwNumberofCommands,
|
|
dwLastCommandLen,
|
|
FileLen;
|
|
DWORD SlotNb;
|
|
BYTE EmptyBuff[512];
|
|
WORD offset;
|
|
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
ZeroMemory( EmptyBuff, sizeof(EmptyBuff) );
|
|
|
|
BeginWait();
|
|
|
|
// TT - 17/10/2000 - Update the timestamps
|
|
Slot_Description* pSlot = &Slot[SlotNb];
|
|
BYTE& refTimestamp = (IsPrivate) ? pSlot->m_TSPrivate : pSlot->m_TSPublic;
|
|
|
|
++refTimestamp;
|
|
|
|
if (0 == refTimestamp)
|
|
refTimestamp = 1;
|
|
|
|
if (!WriteTimestamps( hProv, pSlot->m_TSPublic, pSlot->m_TSPrivate, pSlot->m_TSPIN ))
|
|
return CRYPT_FAILED;
|
|
|
|
/* Select Dedicated Object storage EF on GPK Card */
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xA4; //INS
|
|
bSendBuffer[2] = 0x02; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = 0x02; //Li
|
|
if (IsPrivate)
|
|
{
|
|
bSendBuffer[5] = HIBYTE(GPK_OBJ_PRIV_EF);
|
|
bSendBuffer[6] = LOBYTE(GPK_OBJ_PRIV_EF);
|
|
}
|
|
else
|
|
{
|
|
bSendBuffer[5] = HIBYTE(GPK_OBJ_PUB_EF);
|
|
bSendBuffer[6] = LOBYTE(GPK_OBJ_PUB_EF);
|
|
}
|
|
cbSendLength = 7;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if (SCARDPROBLEM(lRet,0x61FF,0x00))
|
|
RETURN( CRYPT_FAILED, SCARD_E_FILE_NOT_FOUND );
|
|
|
|
/* Get Response */
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xC0; //INS
|
|
bSendBuffer[2] = 0x00; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = bRecvBuffer[1]; //Lo
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if (SCARDPROBLEM(lRet,0x9000,bSendBuffer[4]))
|
|
{
|
|
RETURN (CRYPT_FAILED, SCARD_E_UNEXPECTED);
|
|
}
|
|
|
|
FileLen = bRecvBuffer[8]*256 + bRecvBuffer[9];
|
|
|
|
/* Write the Objects EF */
|
|
dwNumberofCommands = (dwGpkObjLen-1)/FILE_CHUNK_SIZE + 1;
|
|
dwLastCommandLen = dwGpkObjLen%FILE_CHUNK_SIZE;
|
|
|
|
if (dwLastCommandLen == 0)
|
|
{
|
|
dwLastCommandLen = FILE_CHUNK_SIZE;
|
|
}
|
|
|
|
dwCommandLen = FILE_CHUNK_SIZE;
|
|
|
|
|
|
for (i=0; i < dwNumberofCommands ; i++)
|
|
{
|
|
if (i == dwNumberofCommands - 1)
|
|
{
|
|
dwCommandLen = dwLastCommandLen;
|
|
}
|
|
|
|
// Write FILE_CHUCK_SIZE bytes or last bytes
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xD6; //INS
|
|
offset = (WORD)(i * FILE_CHUNK_SIZE) / ProvCont[hProv].dataUnitSize;
|
|
bSendBuffer[2] = HIBYTE( offset );
|
|
bSendBuffer[3] = LOBYTE( offset );
|
|
bSendBuffer[4] = (BYTE)dwCommandLen; //Li
|
|
memcpy( &bSendBuffer[5], &pbGpkObj[i*FILE_CHUNK_SIZE], dwCommandLen );
|
|
cbSendLength = 5 + dwCommandLen;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x9000,0x00))
|
|
{
|
|
RETURN (CRYPT_FAILED, SCARD_E_WRITE_TOO_MANY);
|
|
}
|
|
}
|
|
|
|
if (IsErase)
|
|
{
|
|
// Align the info on a word (4 bytes) boundary
|
|
|
|
if ((dwGpkObjLen % 4) != 0)
|
|
dwGpkObjLen = dwGpkObjLen + 4 - (dwGpkObjLen % 4);
|
|
|
|
dwNumberofCommands = ((FileLen - dwGpkObjLen)-1)/FILE_CHUNK_SIZE + 1;
|
|
dwLastCommandLen = (FileLen - dwGpkObjLen)%FILE_CHUNK_SIZE;
|
|
|
|
if (dwLastCommandLen == 0)
|
|
{
|
|
dwLastCommandLen = FILE_CHUNK_SIZE;
|
|
}
|
|
|
|
dwCommandLen = FILE_CHUNK_SIZE;
|
|
|
|
for (i=0; i < dwNumberofCommands ; i++)
|
|
{
|
|
if (i == dwNumberofCommands - 1)
|
|
{
|
|
dwCommandLen = dwLastCommandLen;
|
|
}
|
|
|
|
// Write FILE_CHUCK_SIZE bytes or last bytes
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xD6; //INS
|
|
offset = (WORD)(i * FILE_CHUNK_SIZE + dwGpkObjLen) / ProvCont[hProv].dataUnitSize;
|
|
bSendBuffer[2] = HIBYTE( offset );
|
|
bSendBuffer[3] = LOBYTE( offset );
|
|
bSendBuffer[4] = (BYTE)dwCommandLen; //Li
|
|
memcpy(&bSendBuffer[5], EmptyBuff, dwCommandLen );
|
|
cbSendLength = 5 + dwCommandLen;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x9000,0x00))
|
|
{
|
|
RETURN (CRYPT_FAILED, SCARD_E_WRITE_TOO_MANY);
|
|
}
|
|
}
|
|
}
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static DWORD find_tmp_free(void)
|
|
{
|
|
DWORD i;
|
|
TMP_OBJ* aTemp;
|
|
|
|
for (i = 1; i <= MAX_TMP_KEY; i++)
|
|
{
|
|
if (TmpObject[i].hKeyBase == 0x00)
|
|
{
|
|
return (i);
|
|
}
|
|
}
|
|
|
|
// realloc TmpObject
|
|
// use aTemp pointer in case of failure
|
|
aTemp = (TMP_OBJ*)GMEM_ReAlloc( TmpObject,
|
|
(MAX_TMP_KEY + REALLOC_SIZE + 1)*sizeof(TMP_OBJ));
|
|
|
|
if (IsNotNull(aTemp))
|
|
{
|
|
TmpObject = aTemp;
|
|
MAX_TMP_KEY += REALLOC_SIZE;
|
|
return (MAX_TMP_KEY - REALLOC_SIZE + 1);
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static BOOL Context_exist(HCRYPTPROV hProv)
|
|
{
|
|
if ((hProv > 0) && (hProv <= MAX_CONTEXT) && (ProvCont[hProv].hProv != 0))
|
|
return (TRUE);
|
|
else
|
|
return (FALSE);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static BOOL hash_exist(HCRYPTHASH hHash, HCRYPTPROV hProv)
|
|
{
|
|
if ((hHash > 0) && (hHash <= MAX_TMP_HASH) &&
|
|
(hHashGpk[hHash].hHashBase != 0) && (hHashGpk[hHash].hProv == hProv))
|
|
return (TRUE);
|
|
else
|
|
if (hHash == 0) // Special case. The NULL Handle exits
|
|
return (TRUE); // It corresponds to the NULL Handle in the RSA Base
|
|
else
|
|
return (FALSE);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static BOOL key_exist(HCRYPTKEY hKey, HCRYPTPROV hProv)
|
|
{
|
|
if ((hKey > 0) && (hKey <= MAX_TMP_KEY) &&
|
|
(TmpObject[hKey].hKeyBase != 0) && (TmpObject[hKey].hProv == hProv))
|
|
return (TRUE);
|
|
else
|
|
return (FALSE);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
|
|
static DWORD find_context_free(void)
|
|
{
|
|
DWORD i;
|
|
Prov_Context* aTemp;
|
|
|
|
for (i = 1; i <= MAX_CONTEXT; i++)
|
|
{
|
|
if (ProvCont[i].hProv == 0x00)
|
|
{
|
|
return (i);
|
|
}
|
|
}
|
|
|
|
// realloc TmpObject
|
|
// use aTemp pointer in case of failure
|
|
aTemp = (Prov_Context*)GMEM_ReAlloc(ProvCont,
|
|
(MAX_CONTEXT + REALLOC_SIZE + 1)*sizeof(Prov_Context));
|
|
|
|
if (IsNotNull(aTemp))
|
|
{
|
|
ProvCont = aTemp;
|
|
MAX_CONTEXT += REALLOC_SIZE;
|
|
return (MAX_CONTEXT - REALLOC_SIZE + 1);
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static DWORD find_hash_free(void)
|
|
{
|
|
DWORD i;
|
|
TMP_HASH* aTemp;
|
|
|
|
for (i = 1; i <= MAX_TMP_HASH; i++)
|
|
{
|
|
if (hHashGpk[i].hHashBase == 0x00)
|
|
{
|
|
return (i);
|
|
}
|
|
}
|
|
|
|
// realloc TmpObject
|
|
// use aTemp pointer in case of failure
|
|
aTemp = (TMP_HASH*)GMEM_ReAlloc(hHashGpk,
|
|
(MAX_TMP_HASH + REALLOC_SIZE + 1)*sizeof(TMP_HASH));
|
|
|
|
if (IsNotNull(aTemp))
|
|
{
|
|
hHashGpk = aTemp;
|
|
MAX_TMP_HASH += REALLOC_SIZE;
|
|
return (MAX_TMP_HASH - REALLOC_SIZE + 1);
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
static BOOL find_reader( DWORD *SlotNb, const PTCHAR szReaderName )
|
|
{
|
|
int i, j;
|
|
DWORD dwReturnSlot = (DWORD)(-1);
|
|
DWORD cchReaders, dwSts;
|
|
LPCTSTR mszReaders = 0, szRdr;
|
|
BOOL fFreedSlot;
|
|
|
|
for (;;)
|
|
{
|
|
|
|
//
|
|
// Look for an existing slot with this reader name.
|
|
//
|
|
|
|
for (i = 0; i < MAX_SLOT; i++)
|
|
{
|
|
if (0 == _tcsnicmp( Slot[i].szReaderName, szReaderName, sizeof(Slot[i].szReaderName) / sizeof(TCHAR)))
|
|
{
|
|
dwReturnSlot = i;
|
|
break;
|
|
}
|
|
}
|
|
if ((DWORD)(-1) != dwReturnSlot)
|
|
break; // All Done!
|
|
|
|
|
|
//
|
|
// Look for an empty reader slot.
|
|
//
|
|
|
|
for (i = 0; i < MAX_SLOT; i++)
|
|
{
|
|
if (IsNullStr(Slot[i].szReaderName))
|
|
{
|
|
_tcsncpy(Slot[i].szReaderName, szReaderName, (sizeof(Slot[i].szReaderName) / sizeof(TCHAR)) - 1);
|
|
Slot[i].szReaderName[(sizeof(Slot[i].szReaderName)/sizeof(TCHAR))-1]=0;
|
|
dwReturnSlot = i;
|
|
break;
|
|
}
|
|
}
|
|
if ((DWORD)(-1) != dwReturnSlot)
|
|
break; // All Done!
|
|
|
|
|
|
//
|
|
// Look for an existing unused reader, and replace it.
|
|
//
|
|
|
|
for (i = 0; i < MAX_SLOT; i++)
|
|
{
|
|
if (0 == Slot[i].ContextCount)
|
|
{
|
|
_tcsncpy( Slot[i].szReaderName, szReaderName, (sizeof(Slot[i].szReaderName) / sizeof(TCHAR)) - 1);
|
|
Slot[i].szReaderName[(sizeof(Slot[i].szReaderName)/sizeof(TCHAR))-1]=0;
|
|
dwReturnSlot = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ((DWORD)(-1) != dwReturnSlot)
|
|
break; // All Done!
|
|
|
|
//
|
|
// Eliminate any duplicate entries.
|
|
//
|
|
|
|
fFreedSlot = FALSE;
|
|
for (i = 0; i < MAX_SLOT; i++)
|
|
{
|
|
if (0 != *Slot[i].szReaderName)
|
|
{
|
|
for (j = i + 1; j < MAX_SLOT; j++)
|
|
{
|
|
if (0 == _tcsnicmp(Slot[i].szReaderName, Slot[j].szReaderName, sizeof(Slot[i].szReaderName) / sizeof(TCHAR)))
|
|
{
|
|
ZeroMemory(&Slot[j], sizeof(Slot_Description));
|
|
fFreedSlot = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (fFreedSlot)
|
|
continue;
|
|
|
|
|
|
//
|
|
// Make sure all the entries are valid.
|
|
//
|
|
|
|
cchReaders = SCARD_AUTOALLOCATE;
|
|
fFreedSlot = FALSE;
|
|
assert(0 != hCardContext);
|
|
assert(0 == mszReaders);
|
|
dwSts = SCardListReaders( hCardContext, 0, (LPTSTR)&mszReaders, &cchReaders );
|
|
if (SCARD_S_SUCCESS != dwSts)
|
|
goto ErrorExit;
|
|
for (i = 0; i < MAX_SLOT; i++)
|
|
{
|
|
for (szRdr = mszReaders; 0 != *szRdr; szRdr += lstrlen(szRdr) + 1)
|
|
{
|
|
if (0 == _tcsnicmp(szRdr, Slot[i].szReaderName, sizeof(Slot[i].szReaderName) / sizeof(TCHAR)))
|
|
break;
|
|
}
|
|
if (0 == *szRdr)
|
|
{
|
|
ZeroMemory(&Slot[i], sizeof(Slot_Description));
|
|
fFreedSlot = TRUE;
|
|
}
|
|
}
|
|
|
|
if (!fFreedSlot)
|
|
goto ErrorExit;
|
|
dwSts = SCardFreeMemory(hCardContext, mszReaders);
|
|
assert(SCARD_S_SUCCESS == dwSts);
|
|
mszReaders = 0;
|
|
}
|
|
|
|
*SlotNb = dwReturnSlot;
|
|
return TRUE;
|
|
|
|
ErrorExit:
|
|
if (0 != mszReaders)
|
|
SCardFreeMemory(hCardContext, mszReaders);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
|
|
static BOOL copy_tmp_key(HCRYPTPROV hProv,HCRYPTKEY hKey,
|
|
DWORD dwFlags, int Algid,
|
|
BYTE KeyBuff[], DWORD KeyLen,
|
|
BYTE SaltBuff[], DWORD SaltLen)
|
|
{
|
|
BOOL CryptResp;
|
|
DWORD i, dwDataLen, dwAlgid;
|
|
BLOBHEADER BlobHeader;
|
|
BYTE *pbTmp;
|
|
BYTE pbData[1024];
|
|
|
|
NoDisplay = TRUE;
|
|
|
|
dwDataLen = sizeof(pbData);
|
|
ZeroMemory( pbData, sizeof(pbData) );
|
|
|
|
/* Make the Blob for Session key */
|
|
BlobHeader.bType = SIMPLEBLOB;
|
|
BlobHeader.bVersion = CUR_BLOB_VERSION;
|
|
BlobHeader.reserved = 0x0000;
|
|
BlobHeader.aiKeyAlg = Algid;
|
|
|
|
memcpy(pbData,
|
|
&BlobHeader,
|
|
sizeof(BlobHeader)
|
|
);
|
|
dwAlgid = CALG_RSA_KEYX;
|
|
memcpy( &pbData[sizeof(BlobHeader)], &dwAlgid, sizeof(DWORD) );
|
|
|
|
pbTmp = (BYTE*)GMEM_Alloc(dwRsaIdentityLen);
|
|
|
|
if (IsNull(pbTmp))
|
|
{
|
|
RETURN(CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
pbTmp[0] = 0x00;
|
|
pbTmp[1] = 0x02;
|
|
CryptGenRandom(hProvBase, dwRsaIdentityLen-KeyLen-3, &pbTmp[2]);
|
|
for (i = 2; i < dwRsaIdentityLen-KeyLen-1; i++)
|
|
{
|
|
if (pbTmp[i] == 0x00)
|
|
{
|
|
pbTmp[i] = 0x01;
|
|
}
|
|
}
|
|
|
|
pbTmp[dwRsaIdentityLen-KeyLen-1] = 0x00;
|
|
memcpy( &pbTmp[dwRsaIdentityLen-KeyLen], KeyBuff, KeyLen );
|
|
|
|
r_memcpy( &pbData[sizeof(BlobHeader)+sizeof(DWORD)], pbTmp, dwRsaIdentityLen );
|
|
GMEM_Free(pbTmp);
|
|
|
|
dwDataLen = sizeof(BLOBHEADER) + sizeof(DWORD) + dwRsaIdentityLen;
|
|
|
|
/* Import Session key blob in RSA Base without the SALT, if presents */
|
|
|
|
CryptResp = CryptImportKey(hProvBase,
|
|
pbData,
|
|
dwDataLen,
|
|
hRsaIdentityKey,
|
|
dwFlags,
|
|
&(TmpObject[hKey].hKeyBase));
|
|
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
|
|
TmpObject[hKey].hProv = hProv;
|
|
|
|
if (SaltLen > 0)
|
|
{
|
|
// In this case, the key has been created with a SALT
|
|
CRYPT_DATA_BLOB sCrypt_Data_Blob;
|
|
|
|
sCrypt_Data_Blob.cbData = SaltLen;
|
|
|
|
sCrypt_Data_Blob.pbData = (BYTE*)GMEM_Alloc (sCrypt_Data_Blob.cbData);
|
|
|
|
if (IsNull(sCrypt_Data_Blob.pbData))
|
|
{
|
|
RETURN(CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
memcpy( sCrypt_Data_Blob.pbData, SaltBuff, SaltLen );
|
|
|
|
CryptResp = CryptSetKeyParam( TmpObject[hKey].hKeyBase, KP_SALT_EX, (BYTE*)&sCrypt_Data_Blob, 0 );
|
|
|
|
GMEM_Free (sCrypt_Data_Blob.pbData);
|
|
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
}
|
|
|
|
NoDisplay = FALSE;
|
|
RETURN( CRYPT_SUCCEED, 0 );
|
|
}
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
|
|
static BOOL key_unwrap( HCRYPTPROV hProv,
|
|
HCRYPTKEY hKey,
|
|
BYTE* pIn,
|
|
DWORD dwInLen,
|
|
BYTE* pOut,
|
|
DWORD* pdwOutLen )
|
|
{
|
|
DWORD lRet;
|
|
BYTE GpkKeySize;
|
|
DWORD SlotNb;
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
if (hKey < 1 || hKey > MAX_GPK_OBJ)
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_BAD_KEY );
|
|
}
|
|
|
|
if (!(Slot[SlotNb].GpkObject[hKey].Flags & FLAG_EXCHANGE))
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_PERM );
|
|
}
|
|
|
|
GpkKeySize = Slot[SlotNb].GpkPubKeys[Slot[SlotNb].GpkObject[hKey].FileId - GPK_FIRST_KEY].KeySize;
|
|
if (GpkKeySize == 0)
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_BAD_KEY );
|
|
}
|
|
|
|
if (dwInLen != GpkKeySize)
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_BAD_DATA );
|
|
}
|
|
|
|
// Card Select Context for enveloppe opening
|
|
bSendBuffer[0] = 0x80; //CLA
|
|
bSendBuffer[1] = 0xA6; //INS
|
|
bSendBuffer[2] = Slot[SlotNb].GpkObject[hKey].FileId; //P1
|
|
bSendBuffer[3] = 0x77; //P2
|
|
cbSendLength = 4;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if (SCARDPROBLEM(lRet,0x9000,0x00))
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_BAD_KEY_STATE );
|
|
}
|
|
|
|
// Open the enveloppe containing the session key
|
|
bSendBuffer[0] = 0x80; //CLA
|
|
bSendBuffer[1] = 0x1C; //INS
|
|
bSendBuffer[2] = 0x00; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = (BYTE) dwInLen; //Lo
|
|
|
|
memcpy(&bSendBuffer[5], pIn, dwInLen);
|
|
|
|
cbSendLength = dwInLen + 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if (SCARDPROBLEM(lRet,0x61FF,0x00))
|
|
RETURN( CRYPT_FAILED, SCARD_E_UNSUPPORTED_FEATURE );
|
|
|
|
// Get Response
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xC0; //INS
|
|
bSendBuffer[2] = 0x00; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = bRecvBuffer[1]; //Lo
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if (SCARDPROBLEM(lRet,0x9000,bSendBuffer[4]))
|
|
RETURN( CRYPT_FAILED, SCARD_E_UNEXPECTED );
|
|
|
|
*pdwOutLen = cbRecvLength - 2;
|
|
r_memcpy(pOut, bRecvBuffer, *pdwOutLen);
|
|
|
|
RETURN( CRYPT_SUCCEED, 0 );
|
|
}
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
|
|
static BYTE GPKHashMode (HCRYPTHASH hHash)
|
|
{
|
|
BOOL CryptResp;
|
|
DWORD dwLen, dwTypeAlg;
|
|
|
|
// This function is called only if the hHash exists
|
|
|
|
dwLen = sizeof (DWORD);
|
|
CryptResp = CryptGetHashParam( hHashGpk[hHash].hHashBase, HP_ALGID, (BYTE *)&dwTypeAlg, &dwLen, 0 );
|
|
|
|
if (CryptResp)
|
|
{
|
|
switch (dwTypeAlg)
|
|
{
|
|
case CALG_MD5 : return 0x11; break;
|
|
case CALG_SHA : return 0x12; break;
|
|
case CALG_SSL3_SHAMD5 : return 0x18; break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
|
|
static BOOL PublicEFExists(HCRYPTPROV hProv)
|
|
{
|
|
// The DF Crypto has been already selected
|
|
|
|
DWORD lRet;
|
|
|
|
if (ProvCont[hProv].bGPK8000)
|
|
return TRUE; // Public object EF always exists on GPK8000
|
|
|
|
// Select Dedicated Object storage EF on GPK Card
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xA4; //INS
|
|
bSendBuffer[2] = 0x02; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = 0x02; //Li
|
|
bSendBuffer[5] = HIBYTE(GPK_OBJ_PUB_EF);
|
|
bSendBuffer[6] = LOBYTE(GPK_OBJ_PUB_EF);
|
|
cbSendLength = 7;
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if (SCARDPROBLEM(lRet,0x61FF,0x00))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
static BOOL Read_MaxSessionKey_EF( HCRYPTPROV hProv, DWORD* ptrMaxSessionKey )
|
|
{
|
|
DWORD lRet;
|
|
|
|
*ptrMaxSessionKey = 0; // default, nothing supported
|
|
|
|
// Select System DF on GPK Card
|
|
BYTE lenDF = strlen(SYSTEM_DF);
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xA4; //INS
|
|
bSendBuffer[2] = 0x04; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = lenDF;
|
|
memcpy( &bSendBuffer[5], SYSTEM_DF, lenDF );
|
|
cbSendLength = 5 + lenDF;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x61FF,0x00))
|
|
RETURN( CRYPT_FAILED, SCARD_E_DIR_NOT_FOUND );
|
|
|
|
|
|
// Select Max Session key EF on GPK Card
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xA4; //INS
|
|
bSendBuffer[2] = 0x02; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = 0x02; //Li
|
|
bSendBuffer[5] = HIBYTE(MAX_SES_KEY_EF);
|
|
bSendBuffer[6] = LOBYTE(MAX_SES_KEY_EF);
|
|
cbSendLength = 7;
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if (SCARDPROBLEM(lRet,0x61FF,0x00))
|
|
{
|
|
RETURN (CRYPT_FAILED, SCARD_E_FILE_NOT_FOUND);
|
|
}
|
|
|
|
// Read Max Session key data on GPK Card
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xB0; //INS
|
|
bSendBuffer[2] = 0x00; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = 0x01; //Li
|
|
cbSendLength = 5;
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if (SCARDPROBLEM(lRet,0x9000, bSendBuffer[4]))
|
|
{
|
|
RETURN(CRYPT_FAILED, NTE_BAD_DATA);
|
|
}
|
|
|
|
*ptrMaxSessionKey = (bRecvBuffer[0] * 8);
|
|
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
|
|
static BOOL init_key_set(HCRYPTPROV hProv, const char* szContainerName)
|
|
{
|
|
|
|
BYTE* pbBuff1 = 0;
|
|
WORD wIadfLen;
|
|
DWORD lRet, dwBuff1Len, SlotNb;
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
if (Slot[SlotNb].NbKeyFile == 0)
|
|
Slot[SlotNb].NbKeyFile = Read_NbKeyFile(hProv);
|
|
|
|
if (Slot[SlotNb].NbKeyFile == 0 || Slot[SlotNb].NbKeyFile > MAX_REAL_KEY)
|
|
{
|
|
RETURN( CRYPT_FAILED, SCARD_E_FILE_NOT_FOUND );
|
|
}
|
|
|
|
// Select GPK EF_IADF
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xA4; //INS
|
|
bSendBuffer[2] = 0x02; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = 0x02; //Li
|
|
bSendBuffer[5] = HIBYTE(GPK_IADF_EF);
|
|
bSendBuffer[6] = LOBYTE(GPK_IADF_EF);
|
|
cbSendLength = 7;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if (SCARDPROBLEM(lRet,0x61FF,0x00))
|
|
RETURN( CRYPT_FAILED, SCARD_E_FILE_NOT_FOUND );
|
|
|
|
// Get Response
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xC0; //INS
|
|
bSendBuffer[2] = 0x00; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = bRecvBuffer[1]; //Lo
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x9000,bSendBuffer[4]))
|
|
{
|
|
RETURN( CRYPT_FAILED, SCARD_E_UNEXPECTED );
|
|
}
|
|
|
|
wIadfLen = bRecvBuffer[8]*256 + bRecvBuffer[9];
|
|
|
|
// Update GPK EF_IADF with Container Name
|
|
memset(bSendBuffer, 0x00, sizeof(bSendBuffer));
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xD6; //INS
|
|
bSendBuffer[2] = 0x00; //P1
|
|
bSendBuffer[3] = 8 / ProvCont[hProv].dataUnitSize;
|
|
bSendBuffer[4] = (BYTE)wIadfLen - 8;//Li
|
|
|
|
ZeroMemory( &bSendBuffer[5], wIadfLen-8 );
|
|
|
|
if (IsNullStr(szContainerName))
|
|
{
|
|
bSendBuffer[5] = 0x30;
|
|
Slot[SlotNb].InitFlag = FALSE;
|
|
}
|
|
else
|
|
{
|
|
bSendBuffer[5] = 0x31;
|
|
Slot[SlotNb].InitFlag = TRUE;
|
|
}
|
|
|
|
strncpy( (char*)&bSendBuffer[6], szContainerName, sizeof(bSendBuffer)-7);
|
|
cbSendLength = wIadfLen - 8 + 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x9000,0x00))
|
|
{
|
|
RETURN(CRYPT_FAILED, SCARD_E_UNEXPECTED);
|
|
}
|
|
|
|
if (!Select_Crypto_DF(hProv))
|
|
return CRYPT_FAILED;
|
|
|
|
// Get Response
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xC0; //INS
|
|
bSendBuffer[2] = 0x00; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = bRecvBuffer[1]; //Lo
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x9000,bSendBuffer[4]))
|
|
{
|
|
RETURN(CRYPT_FAILED, SCARD_E_UNEXPECTED);
|
|
}
|
|
|
|
// Initialize New Container Name
|
|
ZeroMemory( ProvCont[hProv].szContainer, sizeof(ProvCont[hProv].szContainer) );
|
|
memcpy(ProvCont[hProv].szContainer, &bRecvBuffer[5], cbRecvLength - 7);
|
|
|
|
if (!PublicEFExists(hProv))
|
|
{
|
|
// The GPK4000suo still has its generation on-board filter. No key has been
|
|
// generated yet.
|
|
RETURN( CRYPT_SUCCEED, 0 );
|
|
}
|
|
|
|
// New verify Pin code because DF reselected
|
|
if (!PIN_Validation(hProv))
|
|
{
|
|
lRet = GetLastError();
|
|
Select_MF(hProv);
|
|
RETURN( CRYPT_FAILED, lRet );
|
|
}
|
|
|
|
if (read_gpk_objects( hProv, FALSE ))
|
|
{
|
|
if (read_gpk_objects( hProv, TRUE ))
|
|
{
|
|
/* Re-personalize the card BUT keep the PKCS#11 objects not related
|
|
to the GemSAFE application */
|
|
Slot[SlotNb].Read_Public = FALSE;
|
|
Slot[SlotNb].Read_Priv = FALSE;
|
|
clean_card(hProv);
|
|
}
|
|
else
|
|
{
|
|
/* An error occured in the card; ERASE all the objects */
|
|
Slot[SlotNb].Read_Public = FALSE;
|
|
zap_gpk_objects(SlotNb, FALSE);
|
|
|
|
/* Re-personalize the card */
|
|
perso_card(hProv, 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* An error occured in the card; ERASE all the objects */
|
|
Slot[SlotNb].Read_Public = FALSE;
|
|
zap_gpk_objects(SlotNb, FALSE);
|
|
|
|
/* Re-personalize the card */
|
|
perso_card(hProv, 0);
|
|
}
|
|
|
|
pbBuff1 = (BYTE*)GMEM_Alloc(MAX_GPK_PUBLIC);
|
|
|
|
if (IsNull(pbBuff1))
|
|
RETURN( CRYPT_FAILED, NTE_NO_MEMORY );
|
|
|
|
bool bErrorInTryOccured=false;
|
|
__try
|
|
{
|
|
dwBuff1Len = MAX_GPK_PUBLIC;
|
|
if (prepare_write_gpk_objects( hProv, pbBuff1, &dwBuff1Len, FALSE ))
|
|
{
|
|
if (!write_gpk_objects( hProv, pbBuff1, dwBuff1Len, TRUE, FALSE ))
|
|
bErrorInTryOccured=true;
|
|
}
|
|
else bErrorInTryOccured=true;
|
|
}
|
|
__finally
|
|
{
|
|
GMEM_Free( pbBuff1 );
|
|
}
|
|
if(bErrorInTryOccured)
|
|
return CRYPT_FAILED;
|
|
|
|
pbBuff1 = (BYTE*)GMEM_Alloc( MAX_GPK_PRIVATE );
|
|
|
|
if (IsNull(pbBuff1))
|
|
RETURN( CRYPT_FAILED, NTE_NO_MEMORY );
|
|
|
|
__try
|
|
{
|
|
dwBuff1Len = MAX_GPK_PRIVATE;
|
|
if (prepare_write_gpk_objects( hProv, pbBuff1, &dwBuff1Len, TRUE ))
|
|
{
|
|
if (!write_gpk_objects( hProv, pbBuff1, dwBuff1Len, TRUE, TRUE ))
|
|
bErrorInTryOccured=true;
|
|
}
|
|
else bErrorInTryOccured=true;
|
|
}
|
|
__finally
|
|
{
|
|
GMEM_Free( pbBuff1 );
|
|
}
|
|
if(bErrorInTryOccured)
|
|
return CRYPT_FAILED;
|
|
|
|
RETURN( CRYPT_SUCCEED, 0 );
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
* static int ExtractContent(ASN1 *pAsn1)
|
|
*
|
|
* Description : Extract contents of a Asn1 block 'pAsn1->Asn1' and place it
|
|
* in 'pAsn1->Content'.
|
|
*
|
|
* Remarks : Field Asn1.pData is allocated by calling function.
|
|
*
|
|
* In : pAsn1->Asn1.pData
|
|
*
|
|
* Out : This fileds are filled (if RV_SUCCESS) :
|
|
* - Tag
|
|
* - Asn1.usLen
|
|
* - Content.usLen
|
|
* - Content.pData
|
|
*
|
|
* Responses : RV_SUCCESS : All is OK.
|
|
* RV_INVALID_DATA : Asn1 block format not supported.
|
|
*
|
|
------------------------------------------------------------------------------*/
|
|
static int ExtractContent(ASN1 *pAsn1)
|
|
|
|
{
|
|
BYTE* pData;
|
|
int NbBytes, i;
|
|
|
|
|
|
pData = pAsn1->Asn1.pData;
|
|
|
|
if ((pData[0] & 0x1F) == 0x1F)
|
|
{
|
|
// High-tag-number: not supported
|
|
return RV_INVALID_DATA;
|
|
}
|
|
else
|
|
{
|
|
pAsn1->Tag = pData[0];
|
|
}
|
|
|
|
if (pData[1] == 0x80)
|
|
{
|
|
// Constructed, indefinite-length method : not supported
|
|
return (RV_INVALID_DATA);
|
|
}
|
|
else if (pData[1] > 0x82)
|
|
{
|
|
// Constructed, definite-length method : too long
|
|
return (RV_INVALID_DATA);
|
|
}
|
|
else if (pData[1] < 0x80)
|
|
{
|
|
// Primitive, definite-length method
|
|
pAsn1->Content.usLen = pData[1];
|
|
pAsn1->Content.pData = &pData[2];
|
|
|
|
pAsn1->Asn1.usLen = pAsn1->Content.usLen + 2;
|
|
}
|
|
else
|
|
{
|
|
// Constructed, definite-length method
|
|
NbBytes = pData[1] & 0x7F;
|
|
|
|
pAsn1->Content.usLen = 0;
|
|
for (i = 0; i < NbBytes; i++)
|
|
{
|
|
pAsn1->Content.usLen = (pAsn1->Content.usLen << 8) + pData[2+i];
|
|
}
|
|
pAsn1->Content.pData = &pData[2+NbBytes];
|
|
|
|
pAsn1->Asn1.usLen = pAsn1->Content.usLen + 2 + NbBytes;
|
|
}
|
|
|
|
return RV_SUCCESS;
|
|
}
|
|
|
|
/**********************************************************************************/
|
|
static BOOL Read_Priv_Obj (HCRYPTPROV hProv)
|
|
{
|
|
DWORD lRet;
|
|
|
|
if (!PIN_Validation(hProv))
|
|
{
|
|
lRet = GetLastError();
|
|
Select_MF(hProv);
|
|
SCardEndTransaction(ProvCont[hProv].hCard, SCARD_LEAVE_CARD);
|
|
RETURN( CRYPT_FAILED, lRet );
|
|
}
|
|
|
|
if (!Slot[ProvCont[hProv].Slot].Read_Priv)
|
|
{
|
|
if (!read_gpk_objects(hProv, TRUE))
|
|
{
|
|
lRet = GetLastError();
|
|
Select_MF(hProv);
|
|
SCardEndTransaction(ProvCont[hProv].hCard, SCARD_LEAVE_CARD);
|
|
RETURN( CRYPT_FAILED, lRet );
|
|
}
|
|
|
|
Slot[ProvCont[hProv].Slot].Read_Priv = TRUE;
|
|
}
|
|
|
|
|
|
RETURN( CRYPT_SUCCEED, 0 );
|
|
}
|
|
|
|
/**********************************************************************************/
|
|
BOOL Coherent(HCRYPTPROV hProv, bool *bCardReinserted)
|
|
{
|
|
DWORD lRet, SlotNb;
|
|
|
|
if(bCardReinserted)
|
|
{
|
|
*bCardReinserted=false;
|
|
}
|
|
if (!Context_exist(hProv))
|
|
RETURN( CRYPT_FAILED, NTE_BAD_UID );
|
|
|
|
|
|
// [mv - 15/05/98]
|
|
// No access to the card in this case
|
|
if ( ProvCont[hProv].Flags & CRYPT_VERIFYCONTEXT &&
|
|
ProvCont[hProv].isContNameNullBlank )
|
|
{
|
|
RETURN( CRYPT_SUCCEED, 0 );
|
|
}
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
// The thread is stopping, wait for it
|
|
if ( Slot[SlotNb].CheckThreadStateEmpty)
|
|
{
|
|
DWORD threadExitCode;
|
|
StopMonitor(SlotNb,&threadExitCode);
|
|
|
|
// TT 19/11/99: When the card is removed, reset the PIN
|
|
//Slot[SlotNb].ClearPin(); [FP] already cleared
|
|
|
|
Slot[SlotNb].Read_Public = FALSE;
|
|
Slot[SlotNb].Read_Priv = FALSE;
|
|
zap_gpk_objects( SlotNb, FALSE );
|
|
zap_gpk_objects( SlotNb, TRUE );
|
|
Slot[SlotNb].NbKeyFile = 0;
|
|
Slot[SlotNb].GpkMaxSessionKey = 0;
|
|
|
|
// [FP] req for Whistler, if card has been removed, ask card to continue
|
|
SCARDHANDLE hCard = 0;
|
|
TCHAR szReaderName[512];
|
|
DWORD dwFlags = ProvCont[hProv].Flags;
|
|
if (dwFlags & CRYPT_NEWKEYSET) dwFlags = dwFlags^CRYPT_NEWKEYSET; // always find the keyset on the card
|
|
DWORD dwStatus = OpenCard(ProvCont[hProv].szContainer, dwFlags, &hCard, szReaderName, sizeof(szReaderName)/sizeof(TCHAR));
|
|
if ((hCard == 0) || (dwStatus != SCARD_S_SUCCESS))
|
|
{
|
|
if ((dwStatus == SCARD_E_CANCELLED) && (dwFlags & CRYPT_SILENT))
|
|
{
|
|
// Silent reconnection to the card failed
|
|
dwStatus = SCARD_W_REMOVED_CARD;
|
|
}
|
|
//ReleaseProvider(hProv);
|
|
Slot[SlotNb].CheckThreadStateEmpty = TRUE;
|
|
RETURN (CRYPT_FAILED, dwStatus);
|
|
}
|
|
else
|
|
{
|
|
if (ProvCont[hProv].Slot != g_FuncSlotNb)
|
|
{
|
|
DWORD OldSlotNb = SlotNb;
|
|
SlotNb = ProvCont[hProv].Slot = g_FuncSlotNb;
|
|
|
|
//copy slot info
|
|
//Slot[SlotNb].SetPin(Slot[OldSlotNb].GetPin());
|
|
|
|
Slot[SlotNb].InitFlag = Slot[OldSlotNb].InitFlag;
|
|
memcpy(Slot[SlotNb].bGpkSerNb, Slot[OldSlotNb].bGpkSerNb, 8);
|
|
Slot[SlotNb].ContextCount = Slot[OldSlotNb].ContextCount;
|
|
//Slot[SlotNb].CheckThread = Slot[OldSlotNb].CheckThread;
|
|
|
|
// clean old slot
|
|
Slot[OldSlotNb].ContextCount = 0;
|
|
// Slot[OldSlotNb].ClearPin();
|
|
|
|
// synchronize other contexts
|
|
for (DWORD i = 1; i < MAX_CONTEXT; i++)
|
|
{
|
|
if (Context_exist(i))
|
|
{
|
|
if (ProvCont[i].Slot == OldSlotNb)
|
|
{
|
|
ProvCont[i].Slot = SlotNb;
|
|
ProvCont[i].hCard = 0;
|
|
ProvCont[i].bDisconnected = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// synchronize other contexts
|
|
for (DWORD i = 1; i < MAX_CONTEXT; i++)
|
|
{
|
|
if (Context_exist(i))
|
|
{
|
|
if ((ProvCont[i].Slot == SlotNb) && (i != hProv))
|
|
{
|
|
ProvCont[i].hCard = 0;
|
|
ProvCont[i].bDisconnected = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// compare SN
|
|
bSendBuffer[0] = 0x80; //CLA
|
|
bSendBuffer[1] = 0xC0; //INS
|
|
bSendBuffer[2] = 0x02; //P1
|
|
bSendBuffer[3] = 0xA0; //P2
|
|
bSendBuffer[4] = 0x08; //Lo
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit(hCard,
|
|
SCARD_PCI_T0,
|
|
bSendBuffer,
|
|
cbSendLength,
|
|
NULL,
|
|
bRecvBuffer,
|
|
&cbRecvLength);
|
|
|
|
if (SCARDPROBLEM(lRet,0x9000, bSendBuffer[4]))
|
|
{
|
|
//ReleaseProvider(hProv);
|
|
RETURN (CRYPT_FAILED, (SCARD_S_SUCCESS == lRet) ? NTE_FAIL : lRet);
|
|
}
|
|
|
|
if (memcmp(Slot[SlotNb].bGpkSerNb, bRecvBuffer, bSendBuffer[4]) != 0)
|
|
{
|
|
//ReleaseProvider(hProv);
|
|
RETURN (CRYPT_FAILED, NTE_FAIL);
|
|
}
|
|
}
|
|
|
|
ProvCont[hProv].hCard = hCard;
|
|
if(bCardReinserted)
|
|
{
|
|
*bCardReinserted=true;
|
|
}
|
|
|
|
// reassign hKeyBase
|
|
//BOOL CryptResp;
|
|
//HCRYPTKEY hPubKey = 0;
|
|
//CryptResp = MyCPGetUserKey(hProv, AT_KEYEXCHANGE, &hPubKey);
|
|
|
|
//if (CryptResp && hPubKey !=0 && ProvCont[hProv].hRSAKEK!=0)
|
|
// Slot[SlotNb].GpkObject[hPubKey].hKeyBase = ProvCont[hProv].hRSAKEK;
|
|
|
|
//CryptResp = MyCPGetUserKey(hProv, AT_SIGNATURE, &hPubKey);
|
|
|
|
//if (CryptResp && hPubKey !=0 && ProvCont[hProv].hRSASign!=0)
|
|
// Slot[SlotNb].GpkObject[hPubKey].hKeyBase = ProvCont[hProv].hRSASign;
|
|
}
|
|
|
|
if (ProvCont[hProv].bDisconnected)
|
|
{
|
|
DWORD dwProto;
|
|
DWORD dwSts = ConnectToCard( Slot[SlotNb].szReaderName,
|
|
SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0,
|
|
&ProvCont[hProv].hCard, &dwProto );
|
|
|
|
if (dwSts != SCARD_S_SUCCESS)
|
|
{
|
|
//ReleaseProvider(hProv);
|
|
RETURN( CRYPT_FAILED, dwSts );
|
|
}
|
|
|
|
ProvCont[hProv].bDisconnected = FALSE;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////
|
|
/*if (!Prepare_CardBeginTransaction(hProv))
|
|
return CRYPT_FAILED;
|
|
|
|
lRet = SCardBeginTransaction(ProvCont[hProv].hCard);
|
|
|
|
if (SCARDPROBLEM(lRet,0x0000,0xFF))
|
|
{
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}*/
|
|
|
|
lRet = BeginTransaction(ProvCont[hProv].hCard);
|
|
if (lRet != SCARD_S_SUCCESS)
|
|
{
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
// Monitoring thread
|
|
BeginCheckReaderThread(SlotNb);
|
|
|
|
// Make sure that the card has not been replaced by another one [JMR 27-07]
|
|
if (!Select_Crypto_DF(hProv))
|
|
{
|
|
lRet = GetLastError();
|
|
clean_slot(SlotNb, &ProvCont[hProv]);
|
|
|
|
SCardEndTransaction(ProvCont[hProv].hCard, SCARD_LEAVE_CARD);
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
// TT - START 17/10/2000 - Check the card's timestamps
|
|
if (!Slot[SlotNb].ValidateTimestamps(hProv))
|
|
{
|
|
SCardEndTransaction(ProvCont[hProv].hCard, SCARD_LEAVE_CARD);
|
|
return CRYPT_FAILED;
|
|
}
|
|
// TT - END 17/10/2000
|
|
|
|
// Check modif flags
|
|
if (!Slot[SlotNb].Read_Public)
|
|
{
|
|
if (!read_gpk_objects(hProv, FALSE))
|
|
{
|
|
lRet = GetLastError();
|
|
Select_MF(hProv);
|
|
SCardEndTransaction(ProvCont[hProv].hCard, SCARD_LEAVE_CARD);
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
Slot[SlotNb].Read_Public = TRUE;
|
|
Slot[SlotNb].Read_Priv = FALSE;
|
|
}
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
* int MakeLabel(BYTE *pValue, USHORT usValueLen,
|
|
* BYTE *pLabel, USHORT *pusLabelLen
|
|
* )
|
|
*
|
|
* In : pValue : Certificat value
|
|
* usValueLen : Value length
|
|
*
|
|
* Out : pLabel : Certificate Label
|
|
* pLabelLen : Field length
|
|
*
|
|
* Responses : RV_SUCCESS : All is OK.
|
|
* RV_INVALID_DATA : Bad certificate value format.
|
|
* RV_BUFFER_TOO_SMALL : At least one buffer is to small.
|
|
*
|
|
------------------------------------------------------------------------------*/
|
|
int MakeLabel(BYTE *pValue, USHORT usValueLen,
|
|
BYTE *pLabel, USHORT *pusLabelLen
|
|
)
|
|
|
|
{
|
|
ASN1
|
|
AttributeTypePart,
|
|
AttributeValuePart,
|
|
AVA,
|
|
RDN,
|
|
Value,
|
|
tbsCert,
|
|
serialNumberPart,
|
|
signaturePart,
|
|
issuerPart,
|
|
validityPart,
|
|
subjectPart;
|
|
BLOC
|
|
OrganizationName,
|
|
CommonName;
|
|
BOOL
|
|
bValuesToBeReturned;
|
|
BYTE
|
|
*pCurrentRDN,
|
|
*pCurrent;
|
|
int
|
|
rv;
|
|
|
|
OrganizationName.pData = 0;
|
|
OrganizationName.usLen = 0;
|
|
CommonName.pData = 0;
|
|
CommonName.usLen = 0;
|
|
|
|
bValuesToBeReturned = (pLabel != 0);
|
|
|
|
Value.Asn1.pData = pValue;
|
|
rv = ExtractContent(&Value);
|
|
if (rv != RV_SUCCESS) return rv;
|
|
|
|
tbsCert.Asn1.pData = Value.Content.pData;
|
|
rv = ExtractContent(&tbsCert);
|
|
if (rv != RV_SUCCESS) return rv;
|
|
|
|
pCurrent = tbsCert.Content.pData;
|
|
if (pCurrent[0] == 0xA0)
|
|
{
|
|
// We have A0 03 02 01 vv where vv is the version
|
|
pCurrent += 5;
|
|
}
|
|
|
|
serialNumberPart.Asn1.pData = pCurrent;
|
|
rv = ExtractContent(&serialNumberPart);
|
|
if (rv != RV_SUCCESS) return rv;
|
|
pCurrent = serialNumberPart.Content.pData + serialNumberPart.Content.usLen;
|
|
|
|
signaturePart.Asn1.pData = pCurrent;
|
|
rv = ExtractContent(&signaturePart);
|
|
if (rv != RV_SUCCESS) return rv;
|
|
pCurrent = signaturePart.Content.pData + signaturePart.Content.usLen;
|
|
|
|
issuerPart.Asn1.pData = pCurrent;
|
|
rv = ExtractContent(&issuerPart);
|
|
if (rv != RV_SUCCESS) return rv;
|
|
pCurrent = issuerPart.Content.pData + issuerPart.Content.usLen;
|
|
|
|
validityPart.Asn1.pData = pCurrent;
|
|
rv = ExtractContent(&validityPart);
|
|
if (rv != RV_SUCCESS) return rv;
|
|
pCurrent = validityPart.Content.pData + validityPart.Content.usLen;
|
|
|
|
subjectPart.Asn1.pData = pCurrent;
|
|
rv = ExtractContent(&subjectPart);
|
|
if (rv != RV_SUCCESS) return rv;
|
|
pCurrent = subjectPart.Content.pData + subjectPart.Content.usLen;
|
|
|
|
// Search field 'OrganizationName' in 'Issuer'
|
|
pCurrent = issuerPart.Content.pData;
|
|
|
|
while (pCurrent < issuerPart.Content.pData + issuerPart.Content.usLen)
|
|
{
|
|
RDN.Asn1.pData = pCurrent;
|
|
rv = ExtractContent(&RDN);
|
|
if (rv != RV_SUCCESS) return rv;
|
|
|
|
pCurrentRDN = RDN.Content.pData;
|
|
|
|
while (pCurrentRDN < RDN.Content.pData + RDN.Content.usLen)
|
|
{
|
|
AVA.Asn1.pData = pCurrentRDN;
|
|
rv = ExtractContent(&AVA);
|
|
if (rv != RV_SUCCESS) return rv;
|
|
|
|
AttributeTypePart.Asn1.pData = AVA.Content.pData;
|
|
rv = ExtractContent(&AttributeTypePart);
|
|
if (rv != RV_SUCCESS) return rv;
|
|
|
|
AttributeValuePart.Asn1.pData = AttributeTypePart.Content.pData
|
|
+ AttributeTypePart.Content.usLen;
|
|
rv = ExtractContent(&AttributeValuePart);
|
|
if (rv != RV_SUCCESS) return rv;
|
|
|
|
// Search 'OrganisationName'
|
|
if (!memcmp("\x55\x04\x0A",
|
|
AttributeTypePart.Content.pData,
|
|
AttributeTypePart.Content.usLen)
|
|
)
|
|
{
|
|
OrganizationName = AttributeValuePart.Content;
|
|
}
|
|
|
|
pCurrentRDN = AVA.Content.pData + AVA.Content.usLen;
|
|
}
|
|
|
|
pCurrent = RDN.Content.pData + RDN.Content.usLen;
|
|
}
|
|
|
|
// Search 'CommonName' in 'Subject'
|
|
pCurrent = subjectPart.Content.pData;
|
|
|
|
while (pCurrent < subjectPart.Content.pData + subjectPart.Content.usLen)
|
|
{
|
|
RDN.Asn1.pData = pCurrent;
|
|
rv = ExtractContent(&RDN);
|
|
if (rv != RV_SUCCESS) return rv;
|
|
|
|
pCurrentRDN = RDN.Content.pData;
|
|
|
|
while (pCurrentRDN < RDN.Content.pData + RDN.Content.usLen)
|
|
{
|
|
AVA.Asn1.pData = pCurrentRDN;
|
|
rv = ExtractContent(&AVA);
|
|
if (rv != RV_SUCCESS) return rv;
|
|
|
|
AttributeTypePart.Asn1.pData = AVA.Content.pData;
|
|
rv = ExtractContent(&AttributeTypePart);
|
|
if (rv != RV_SUCCESS) return rv;
|
|
|
|
AttributeValuePart.Asn1.pData = AttributeTypePart.Content.pData
|
|
+ AttributeTypePart.Content.usLen;
|
|
rv = ExtractContent(&AttributeValuePart);
|
|
if (rv != RV_SUCCESS) return rv;
|
|
|
|
// Search 'CommonName'
|
|
if (!memcmp("\x55\x04\x03",
|
|
AttributeTypePart.Content.pData,
|
|
AttributeTypePart.Content.usLen)
|
|
)
|
|
{
|
|
CommonName = AttributeValuePart.Content;
|
|
}
|
|
|
|
pCurrentRDN = AVA.Content.pData + AVA.Content.usLen;
|
|
}
|
|
|
|
pCurrent = RDN.Content.pData + RDN.Content.usLen;
|
|
}
|
|
|
|
if (bValuesToBeReturned)
|
|
{
|
|
if ((*pusLabelLen < OrganizationName.usLen + CommonName.usLen + 6)
|
|
)
|
|
{
|
|
return (RV_BUFFER_TOO_SMALL);
|
|
}
|
|
memcpy(pLabel,
|
|
CommonName.pData,
|
|
CommonName.usLen
|
|
);
|
|
memcpy(&pLabel[CommonName.usLen],
|
|
"'s ",
|
|
3
|
|
);
|
|
memcpy(&pLabel[CommonName.usLen+3],
|
|
OrganizationName.pData,
|
|
OrganizationName.usLen
|
|
);
|
|
memcpy(&pLabel[CommonName.usLen+3+OrganizationName.usLen],
|
|
" ID",
|
|
3
|
|
);
|
|
*pusLabelLen = OrganizationName.usLen + CommonName.usLen + 6;
|
|
}
|
|
else
|
|
{
|
|
*pusLabelLen = OrganizationName.usLen + CommonName.usLen + 6;
|
|
}
|
|
|
|
return RV_SUCCESS;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
[DCB3] vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv [DCB3]
|
|
--------------------------------------------------------------------------------*/
|
|
static LPCSTR read_gpk_keyset(SCARDHANDLE hLocalCard)
|
|
{
|
|
DWORD lRet;
|
|
BYTE lenDF;
|
|
|
|
/*lRet = SCardBeginTransaction(hLocalCard);
|
|
if (SCARD_S_SUCCESS != lRet)
|
|
goto ErrorExit;*/
|
|
|
|
lRet = BeginTransaction(hLocalCard);
|
|
if (lRet != SCARD_S_SUCCESS)
|
|
goto ErrorExit;
|
|
|
|
/* Select GPK Card MF */
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xA4; //INS
|
|
bSendBuffer[2] = 0x00; //P1
|
|
bSendBuffer[3] = 0x0C; //P2
|
|
bSendBuffer[4] = 0x02; //Li
|
|
bSendBuffer[5] = HIBYTE(GPK_MF);
|
|
bSendBuffer[6] = LOBYTE(GPK_MF);
|
|
cbSendLength = 7;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( hLocalCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x9000,0x00))
|
|
goto ErrorExit;
|
|
|
|
/* Select Dedicated Application DF on GPK Card */
|
|
lenDF = strlen(GPK_DF);
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xA4; //INS
|
|
bSendBuffer[2] = 0x04; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = lenDF;
|
|
memcpy( &bSendBuffer[5], GPK_DF, lenDF );
|
|
cbSendLength = 5 + lenDF;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( hLocalCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x61FF,0x00))
|
|
goto ErrorExit;
|
|
|
|
/* Get Response of the Select DF to obtain the IADF */
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xC0; //INS
|
|
bSendBuffer[2] = 0x00; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = bRecvBuffer[1]; //Lo
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( hLocalCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x9000,bSendBuffer[4]))
|
|
goto ErrorExit;
|
|
|
|
bRecvBuffer[cbRecvLength - 2] = 0;
|
|
SCardEndTransaction(hLocalCard, SCARD_LEAVE_CARD);
|
|
|
|
return (LPCSTR)&bRecvBuffer[5];
|
|
|
|
ErrorExit:
|
|
SCardEndTransaction(hLocalCard, SCARD_LEAVE_CARD);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
[DCB3] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [DCB3]
|
|
--------------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
--------------------------------------------------------------------------------*/
|
|
|
|
GPK_OBJ* FindKeySet( Slot_Description* pSlot, LPCSTR szDesiredContainer )
|
|
{
|
|
GPK_OBJ* pFirstObject = &pSlot->GpkObject[1];
|
|
GPK_OBJ* pLastObject = pFirstObject + pSlot->NbGpkObject;
|
|
GPK_OBJ* pObject;
|
|
int len;
|
|
|
|
if (IsNullStr( szDesiredContainer))
|
|
return 0;
|
|
|
|
len = strlen( szDesiredContainer );
|
|
|
|
for (pObject = pFirstObject; pObject != pLastObject; ++pObject)
|
|
{
|
|
if ( (pObject->Tag & 0x7F) == TAG_KEYSET )
|
|
{
|
|
if ( pObject->Field[POS_LABEL].Len == len )
|
|
{
|
|
if (0==memcmp( szDesiredContainer, pObject->Field[POS_LABEL].pValue, len))
|
|
{
|
|
// Found the keyset
|
|
return pObject;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
GPK_OBJ* FindKeySetByID( Slot_Description* pSlot, BYTE keysetID )
|
|
{
|
|
GPK_OBJ* pFirstObject = &pSlot->GpkObject[1];
|
|
GPK_OBJ* pLastObject = pFirstObject + pSlot->NbGpkObject;
|
|
GPK_OBJ* pObject;
|
|
|
|
for (pObject = pFirstObject; pObject != pLastObject; ++pObject)
|
|
{
|
|
if ( (pObject->Tag & 0x7F) == TAG_KEYSET )
|
|
{
|
|
if (pObject->Field[POS_ID].Len > 0)
|
|
{
|
|
if (keysetID == pObject->Field[POS_ID].pValue[0])
|
|
{
|
|
// Found the keyset
|
|
return pObject;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
GPK_OBJ* FindFirstKeyset( Slot_Description* pSlot )
|
|
{
|
|
GPK_OBJ* pFirstObject = &pSlot->GpkObject[1];
|
|
GPK_OBJ* pLastObject = pFirstObject + pSlot->NbGpkObject;
|
|
GPK_OBJ* pObject;
|
|
|
|
for (pObject = pFirstObject; pObject != pLastObject; ++pObject)
|
|
{
|
|
if ( (pObject->Tag & 0x7F) == TAG_KEYSET )
|
|
{
|
|
return pObject;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
BOOL DetectLegacy( Slot_Description* pSlot )
|
|
{
|
|
BOOL bHasPublicKey = FALSE;
|
|
BOOL bHasKeyset = FALSE;
|
|
GPK_OBJ* pFirstObject = &pSlot->GpkObject[1];
|
|
GPK_OBJ* pLastObject = pFirstObject + pSlot->NbGpkObject;
|
|
GPK_OBJ* pObject;
|
|
|
|
for (pObject = pFirstObject; pObject != pLastObject; ++pObject)
|
|
{
|
|
if (((pObject->Tag & 0x7F) == TAG_RSA_PUBLIC) &&
|
|
( pObject->IsCreated == TRUE))
|
|
bHasPublicKey = TRUE;
|
|
if ( (pObject->Tag & 0x7F) == TAG_KEYSET )
|
|
bHasKeyset = TRUE;
|
|
}
|
|
|
|
if (bHasPublicKey && !bHasKeyset)
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Initialize the specified slot
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void InitializeSlot( DWORD SlotNb )
|
|
{
|
|
if (SlotNb >= MAX_SLOT)
|
|
{
|
|
SetLastError( NTE_FAIL );
|
|
return;
|
|
}
|
|
|
|
if (!InitSlot[SlotNb])
|
|
{
|
|
TCHAR szBuff[128];
|
|
|
|
_tcsncpy(szBuff, Slot[SlotNb].szReaderName, 127);
|
|
szBuff[127]=0;
|
|
ZeroMemory(&Slot[SlotNb], sizeof(Slot_Description));
|
|
_tcsncpy(Slot[SlotNb].szReaderName, szBuff, 127);
|
|
Slot[SlotNb].szReaderName[127]=0;
|
|
InitSlot[SlotNb] = TRUE;
|
|
}
|
|
|
|
if (Slot[SlotNb].CheckThreadStateEmpty)
|
|
{
|
|
DBG_PRINT(TEXT("Thread had stopped, wait for it"));
|
|
DWORD threadExitCode;
|
|
StopMonitor(SlotNb,&threadExitCode);
|
|
|
|
// TT 19/11/99: When the card is removed, reset the PIN
|
|
// Slot[SlotNb].ClearPin();
|
|
|
|
Flush_MSPinCache(&(Slot[SlotNb].hPinCacheHandle)); // NK 06.02.2001 #5 5106
|
|
Slot[SlotNb].Read_Public = FALSE;
|
|
Slot[SlotNb].Read_Priv = FALSE;
|
|
zap_gpk_objects( SlotNb, FALSE );
|
|
zap_gpk_objects( SlotNb, TRUE );
|
|
Slot[SlotNb].NbKeyFile = 0;
|
|
Slot[SlotNb].GpkMaxSessionKey = 0;
|
|
|
|
// [FP] +
|
|
/*
|
|
for (DWORD i = 1; i < MAX_CONTEXT; i++)
|
|
{
|
|
if (Context_exist(i))
|
|
{
|
|
if (ProvCont[i].Slot == SlotNb)
|
|
{
|
|
ProvCont[i].hCard = 0;
|
|
ProvCont[i].bDisconnected = TRUE;
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
// [FP] -
|
|
}
|
|
|
|
// Monitoring thread
|
|
BeginCheckReaderThread(SlotNb);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
--------------------------------------------------------------------------------*/
|
|
|
|
SCARDHANDLE WINAPI funcConnect (SCARDCONTEXT hSCardContext, LPTSTR szReader, LPTSTR mszCards, PVOID pvUserData)
|
|
{
|
|
SCARDHANDLE hCard;
|
|
DWORD dwProto, dwSts;
|
|
|
|
GpkLocalLock();
|
|
|
|
hCard = 0;
|
|
dwSts = ConnectToCard( szReader, SCARD_SHARE_SHARED,
|
|
SCARD_PROTOCOL_T0, &hCard, &dwProto );
|
|
|
|
if (dwSts != SCARD_S_SUCCESS)
|
|
{
|
|
hCard =0;
|
|
GpkLocalUnlock();
|
|
return 0;
|
|
}
|
|
|
|
if (!find_reader( &g_FuncSlotNb, szReader ))
|
|
{
|
|
GpkLocalUnlock();
|
|
return 0;
|
|
}
|
|
|
|
GpkLocalUnlock();
|
|
return hCard;
|
|
}
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
--------------------------------------------------------------------------------*/
|
|
|
|
// TT 05/10/99
|
|
BOOL WINAPI funcCheck( SCARDCONTEXT hSCardContext, SCARDHANDLE hCard, void* pvUserData )
|
|
{
|
|
GPK_OBJ* pKeySet = 0;
|
|
int hProv = 0;
|
|
int SlotNb = g_FuncSlotNb;
|
|
BOOL bGPK8000;
|
|
BOOL bResult;
|
|
|
|
GpkLocalLock();
|
|
|
|
ProvCont[hProv].hCard = hCard;
|
|
ProvCont[hProv].Slot = SlotNb;
|
|
ProvCont[hProv].dataUnitSize = 0;
|
|
|
|
//GpkLocalLock();
|
|
|
|
/*if (!Prepare_CardBeginTransaction(0))
|
|
{
|
|
GpkLocalUnlock();
|
|
return FALSE;
|
|
}*/
|
|
|
|
if (BeginTransaction(hCard) != SCARD_S_SUCCESS)
|
|
{
|
|
GpkLocalUnlock();
|
|
return FALSE;
|
|
}
|
|
|
|
LPCSTR szDesiredContainer = (char*)pvUserData;
|
|
/*
|
|
GPK_OBJ* pKeySet = 0;
|
|
int hProv = 0;
|
|
int SlotNb = g_FuncSlotNb;
|
|
BOOL bGPK8000;
|
|
BOOL bResult;
|
|
*/
|
|
InitializeSlot( SlotNb );
|
|
|
|
// If we are acquiring a new keyset, we return TRUE
|
|
if ( szDesiredContainer == 0 || *szDesiredContainer == 0)
|
|
{
|
|
SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
|
|
GpkLocalUnlock();
|
|
return TRUE;
|
|
}
|
|
|
|
// Read the public objects
|
|
/*
|
|
ProvCont[hProv].hCard = hCard;
|
|
ProvCont[hProv].Slot = SlotNb;
|
|
ProvCont[hProv].dataUnitSize = 0;
|
|
*/
|
|
bResult = Select_Crypto_DF( hProv );
|
|
if (bResult)
|
|
{
|
|
bResult = Slot[SlotNb].ValidateTimestamps(hProv);
|
|
|
|
if (bResult && !Slot[SlotNb].Read_Public)
|
|
{
|
|
bResult = read_gpk_objects( hProv, FALSE );
|
|
|
|
if (bResult)
|
|
{
|
|
Slot[SlotNb].Read_Public = TRUE;
|
|
Slot[SlotNb].Read_Priv = FALSE;
|
|
}
|
|
}
|
|
|
|
if (bResult)
|
|
{
|
|
pKeySet = FindKeySet( &Slot[SlotNb], szDesiredContainer );
|
|
if (pKeySet==0)
|
|
{
|
|
if (DetectGPK8000( hCard, &bGPK8000 ) == SCARD_S_SUCCESS)
|
|
{
|
|
bResult = FALSE;
|
|
if (!bGPK8000)
|
|
{
|
|
BOOL bLegacy = DetectLegacy( &Slot[SlotNb] );
|
|
if (bLegacy)
|
|
{
|
|
LPCSTR szCardContainer = read_gpk_keyset( hCard );
|
|
if (szCardContainer!=0)
|
|
{
|
|
bResult = (0 == strcmp(szCardContainer, szDesiredContainer));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bResult = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
ZeroMemory( &ProvCont[hProv], sizeof(ProvCont[hProv]) );
|
|
|
|
SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
|
|
GpkLocalUnlock();
|
|
|
|
return bResult;
|
|
}
|
|
// TT: END
|
|
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
--------------------------------------------------------------------------------*/
|
|
void WINAPI funcDisconnect( SCARDCONTEXT hSCardContext, SCARDHANDLE hCard, PVOID pvUserData )
|
|
{
|
|
SCardDisconnect( hCard, SCARD_LEAVE_CARD );
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
|
|
static DWORD OpenCard(CHAR* szContainerAsked, DWORD dwFlags, SCARDHANDLE* hCard, PTCHAR szReaderName, DWORD dwReaderNameLen)
|
|
{
|
|
OPENCARDNAME open_card;
|
|
TCHAR szCardName[512],
|
|
szOpenDlgTitle[MAX_STRING];
|
|
|
|
ZeroMemory( szReaderName, dwReaderNameLen * sizeof(TCHAR) );
|
|
ZeroMemory( szCardName, sizeof(szCardName) );
|
|
|
|
open_card.dwStructSize = sizeof(open_card);
|
|
open_card.hwndOwner = GetAppWindow();
|
|
open_card.hSCardContext = hCardContext;
|
|
open_card.lpstrGroupNames = 0;
|
|
open_card.nMaxGroupNames = 0;
|
|
open_card.lpstrCardNames = mszCardList;
|
|
open_card.nMaxCardNames = multistrlen(mszCardList)+1;
|
|
open_card.rgguidInterfaces = 0;
|
|
open_card.cguidInterfaces = 0;
|
|
open_card.lpstrRdr = szReaderName;
|
|
open_card.nMaxRdr = dwReaderNameLen;
|
|
open_card.lpstrCard = szCardName;
|
|
open_card.nMaxCard = sizeof(szCardName) / sizeof(TCHAR);
|
|
LoadString(g_hInstRes, 1017, szOpenDlgTitle, sizeof(szOpenDlgTitle)/sizeof(TCHAR));
|
|
open_card.lpstrTitle = szOpenDlgTitle;
|
|
if (dwFlags & CRYPT_SILENT)
|
|
open_card.dwFlags = SC_DLG_NO_UI;
|
|
else
|
|
open_card.dwFlags = SC_DLG_MINIMAL_UI;
|
|
if (dwFlags & CRYPT_NEWKEYSET) // [DCB3]
|
|
open_card.pvUserData = 0; // [DCB3]
|
|
else // [DCB3]
|
|
open_card.pvUserData = szContainerAsked; // [DCB3]
|
|
open_card.dwShareMode = SCARD_SHARE_SHARED;
|
|
open_card.dwPreferredProtocols = SCARD_PROTOCOL_T0;
|
|
open_card.dwActiveProtocol = 0;
|
|
open_card.lpfnConnect = funcConnect;
|
|
open_card.lpfnCheck = funcCheck;
|
|
open_card.lpfnDisconnect = funcDisconnect;
|
|
open_card.hCardHandle = 0;
|
|
|
|
GpkLocalUnlock();
|
|
DWORD dwStatus = GetOpenCardName (&open_card);
|
|
DBG_PRINT(TEXT("dwStatus = 0x%08X, open_card.hCardHandle = 0x%08X"), dwStatus, open_card.hCardHandle);
|
|
GpkLocalLock();
|
|
*hCard = open_card.hCardHandle;
|
|
|
|
return(dwStatus);
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
--------------------------------------------------------------------------------*/
|
|
void ReleaseProvider(HCRYPTPROV hProv)
|
|
{
|
|
BOOL CryptResp;
|
|
DWORD i;
|
|
DWORD dwProto; //[FP]
|
|
|
|
/* Release Hash parameters */
|
|
for (i = 1; i <= MAX_TMP_HASH; i++)
|
|
{
|
|
if ((hHashGpk[i].hHashBase != 0) && (hHashGpk[i].hProv == hProv))
|
|
{
|
|
CryptResp = CryptDestroyHash(hHashGpk[i].hHashBase);
|
|
hHashGpk[i].hHashBase = 0;
|
|
hHashGpk[i].hProv = 0;
|
|
}
|
|
}
|
|
|
|
/* Release Key parameters */
|
|
for (i = 1; i <= MAX_TMP_KEY; i++)
|
|
{
|
|
if ((TmpObject[i].hKeyBase != 0) && (TmpObject[i].hProv == hProv))
|
|
{
|
|
CryptResp = CryptDestroyKey(TmpObject[i].hKeyBase);
|
|
TmpObject[i].hKeyBase = 0;
|
|
TmpObject[i].hProv = 0;
|
|
}
|
|
}
|
|
|
|
ProvCont[hProv].hProv = 0;
|
|
|
|
if ((ProvCont[hProv].Flags & CRYPT_VERIFYCONTEXT) &&
|
|
(ProvCont[hProv].isContNameNullBlank))
|
|
{
|
|
|
|
}
|
|
else
|
|
{
|
|
// + [FP] if a transaction is opened, close it and reconnect in shared mode
|
|
if (ProvCont[hProv].bCardTransactionOpened)
|
|
{
|
|
// Select_MF(hProv); [FP] PIN not presented
|
|
SCardEndTransaction(ProvCont[hProv].hCard, SCARD_LEAVE_CARD);
|
|
SCardReconnect(ProvCont[hProv].hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_LEAVE_CARD, &dwProto);
|
|
ProvCont[hProv].bCardTransactionOpened = FALSE;
|
|
}
|
|
// - [FP]
|
|
|
|
if (ProvCont[hProv].hRSAKEK != 0)
|
|
{
|
|
CryptDestroyKey( ProvCont[hProv].hRSAKEK );
|
|
ProvCont[hProv].hRSAKEK = 0;
|
|
}
|
|
|
|
if (ProvCont[hProv].hRSASign != 0)
|
|
{
|
|
CryptDestroyKey( ProvCont[hProv].hRSASign );
|
|
ProvCont[hProv].hRSASign = 0;
|
|
}
|
|
|
|
if (ProvCont[hProv].hCard != 0)
|
|
{
|
|
SCardDisconnect(ProvCont[hProv].hCard, SCARD_LEAVE_CARD);
|
|
ProvCont[hProv].hCard = 0;
|
|
}
|
|
|
|
if (countCardContextRef == 0)
|
|
{
|
|
if (hCardContext != 0)
|
|
SCardReleaseContext(hCardContext);
|
|
|
|
hCardContext = 0;
|
|
}
|
|
}
|
|
|
|
ProvCont[hProv].Flags = 0;
|
|
ProvCont[hProv].isContNameNullBlank = TRUE;
|
|
ProvCont[hProv].hCard = 0;
|
|
ProvCont[hProv].Slot = 0;
|
|
}
|
|
|
|
|
|
|
|
DWORD getAuxMaxKeyLength(HCRYPTPROV hProv)
|
|
{
|
|
BYTE *ptr = 0;
|
|
DWORD i;
|
|
ALG_ID aiAlgid;
|
|
DWORD dwBits;
|
|
|
|
BYTE pbData[1000];
|
|
DWORD cbData;
|
|
DWORD dwFlags = 0;
|
|
|
|
DWORD maxLength = 0;
|
|
|
|
// Enumerate the supported algorithms.
|
|
|
|
for (i=0 ; ; i++)
|
|
{
|
|
if (i == 0)
|
|
dwFlags = CRYPT_FIRST;
|
|
else
|
|
dwFlags = 0;
|
|
|
|
cbData = 1000;
|
|
|
|
if (!CryptGetProvParam(hProv, PP_ENUMALGS, pbData, &cbData, dwFlags))
|
|
break;
|
|
|
|
// Extract algorithm information from the ‘pbData’ buffer.
|
|
ptr = pbData;
|
|
aiAlgid = *(ALG_ID UNALIGNED *)ptr;
|
|
ptr += sizeof(ALG_ID);
|
|
dwBits = *(DWORD UNALIGNED *)ptr;
|
|
|
|
switch (aiAlgid)
|
|
{
|
|
case CALG_DES: dwBits += 8;
|
|
break;
|
|
case CALG_3DES_112: dwBits += 16;
|
|
break;
|
|
case CALG_3DES: dwBits += 24;
|
|
break;
|
|
}
|
|
|
|
if (GET_ALG_CLASS(aiAlgid) == ALG_CLASS_DATA_ENCRYPT)
|
|
{
|
|
maxLength = max(maxLength, dwBits);
|
|
}
|
|
|
|
}
|
|
|
|
return maxLength;
|
|
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
[FP] used in the case of PRIVATEKEYBLOB in MyCPImportKey
|
|
--------------------------------------------------------------------------------*/
|
|
BOOL LoadPrivateKey(SCARDHANDLE hCard,
|
|
BYTE Sfi,
|
|
WORD ElementLen,
|
|
CONST BYTE* pbData,
|
|
DWORD dwDataLen
|
|
)
|
|
{
|
|
DWORD lRet;
|
|
|
|
/* Load SK APDU command */
|
|
bSendBuffer[0] = 0x80; //CLA
|
|
bSendBuffer[1] = 0x18; //INS
|
|
bSendBuffer[2] = Sfi; //P1
|
|
bSendBuffer[3] = (BYTE)ElementLen; //P2
|
|
bSendBuffer[4] = (BYTE)dwDataLen; //Li
|
|
memcpy(&bSendBuffer[5], pbData, dwDataLen);
|
|
cbSendLength = 5 + dwDataLen;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
memset(bSendBuffer, 0, sizeof(bSendBuffer));
|
|
if(SCARDPROBLEM(lRet, 0x9000, 0x00))
|
|
{
|
|
SetLastError(lRet);
|
|
return (FALSE);
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* BOOL WINAPI DllMain (HINSTANCE hInstDLL,
|
|
* DWORD fdwRaison,
|
|
* LPVOID lpReserved
|
|
* )
|
|
*
|
|
* Description :
|
|
*
|
|
* Remarks :
|
|
*
|
|
* In :
|
|
*
|
|
* Out :
|
|
*
|
|
* Responses :
|
|
*
|
|
*******************************************************************************/
|
|
|
|
BOOL WINAPI DllMain (HINSTANCE hInstDLL,
|
|
DWORD fdwRaison,
|
|
LPVOID lpReserved
|
|
)
|
|
{
|
|
int i;
|
|
BOOL ReturnValue = TRUE;
|
|
|
|
switch (fdwRaison)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
{
|
|
DBG_PRINT(TEXT("DLL_PROCESS_ATTACH [start]..."));
|
|
|
|
g_hInstMod = hInstDLL;
|
|
|
|
|
|
// Allocation of TmpObject, hHashGpk and ProvCont
|
|
TmpObject= (TMP_OBJ*)GMEM_Alloc((MAX_TMP_KEY + 1)*sizeof(TMP_OBJ));
|
|
hHashGpk = (TMP_HASH*)GMEM_Alloc((MAX_TMP_HASH + 1)*sizeof(TMP_HASH));
|
|
ProvCont = (Prov_Context*)GMEM_Alloc((MAX_CONTEXT + 1)*sizeof(Prov_Context));
|
|
|
|
if (IsNull(TmpObject) || IsNull(hHashGpk) || IsNull (ProvCont))
|
|
{
|
|
ReturnValue = FALSE;
|
|
break;
|
|
}
|
|
|
|
ZeroMemory( ProvCont, (MAX_CONTEXT+1) * sizeof(Prov_Context) );
|
|
ZeroMemory( TmpObject, (MAX_TMP_KEY+1) * sizeof(TMP_OBJ) );
|
|
ZeroMemory( hHashGpk, (MAX_TMP_HASH+1) * sizeof(TMP_HASH) );
|
|
|
|
try
|
|
{
|
|
InitializeCriticalSection(&l_csLocalLock);
|
|
}
|
|
catch(...)
|
|
{
|
|
ReturnValue=FALSE;
|
|
}
|
|
|
|
|
|
DBG_PRINT(TEXT("...[end] DLL_PROCESS_ATTACH"));
|
|
|
|
break;
|
|
}
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
{
|
|
DBG_PRINT(TEXT("DLL_PROCESS_DETACH [start]..."));
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
// Deallocation of TmpObject, hHashGpk and ProvCont
|
|
|
|
if (TmpObject != 0)
|
|
GMEM_Free(TmpObject);
|
|
if (hHashGpk != 0)
|
|
GMEM_Free(hHashGpk);
|
|
if (ProvCont != 0)
|
|
GMEM_Free(ProvCont);
|
|
|
|
for (i=0; i< MAX_SLOT; i++)
|
|
{
|
|
if (Slot[i].CheckThread != NULL)
|
|
{
|
|
// + [FP]
|
|
g_fStopMonitor[i] = TRUE;
|
|
SCardCancel( hCardContextCheck[i] );
|
|
// TerminateThread( Slot[i].CheckThread, 0 );
|
|
// - [FP]
|
|
CloseHandle( Slot[i].CheckThread );
|
|
Slot[i].CheckThread = NULL;
|
|
}
|
|
}
|
|
|
|
if (hProvBase != 0)
|
|
{
|
|
CryptDestroyKey(hRsaIdentityKey);
|
|
CryptReleaseContext(hProvBase, 0);
|
|
}
|
|
|
|
CC_Exit();
|
|
|
|
DeleteCriticalSection(&l_csLocalLock);
|
|
|
|
DBG_PRINT(TEXT("...[end] DLL_PROCESS_DETACH"));
|
|
}
|
|
break;
|
|
|
|
|
|
case DLL_THREAD_ATTACH:
|
|
InterlockedIncrement( &g_threadAttach );
|
|
break;
|
|
|
|
case DLL_THREAD_DETACH:
|
|
InterlockedDecrement( &g_threadAttach );
|
|
break;
|
|
}
|
|
return (ReturnValue);
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
--------------------------------------------------------------------------------*/
|
|
|
|
BOOL InitAcquire()
|
|
{
|
|
BOOL CryptResp;
|
|
DWORD dwIgn, lRet;
|
|
TCHAR szCspName[MAX_STRING];
|
|
TCHAR szCspBaseName[256];
|
|
TCHAR szDictionaryName[256];
|
|
TCHAR szEntry[MAX_STRING];
|
|
HKEY hRegKey;
|
|
int i;
|
|
|
|
// Initialize arrays here instead of using static initializers.
|
|
for (i = 0; i < MAX_SLOT; ++i)
|
|
hCardContextCheck[i] = 0;
|
|
|
|
for (i = 0; i < MAX_SLOT; ++i)
|
|
InitSlot[i] = FALSE;
|
|
|
|
ZeroMemory( Slot, sizeof(Slot) );
|
|
|
|
for (i = 0; i < MAX_SLOT; ++i)
|
|
Slot[i].CheckThreadStateEmpty = FALSE;
|
|
|
|
OSVERSIONINFO osver;
|
|
HCRYPTPROV hProvTest;
|
|
|
|
LoadString(g_hInstMod, IDS_GPKCSP_ENTRY, szEntry, sizeof(szEntry)/sizeof(TCHAR));
|
|
DBG_PRINT(TEXT(" Registry entry: \"%s\"\n"), szEntry );
|
|
|
|
lRet = RegCreateKeyEx( HKEY_LOCAL_MACHINE, szEntry, 0, TEXT(""), REG_OPTION_NON_VOLATILE,
|
|
KEY_READ, 0, &hRegKey, &dwIgn );
|
|
|
|
// Detect provider available
|
|
CryptResp = CryptAcquireContext( &hProvTest, 0, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT );
|
|
if (CryptResp)
|
|
{
|
|
lstrcpy( szCspBaseName, MS_ENHANCED_PROV );
|
|
CryptReleaseContext( hProvTest, 0 );
|
|
}
|
|
else
|
|
{
|
|
lstrcpy( szCspBaseName, MS_DEF_PROV );
|
|
}
|
|
|
|
DBG_PRINT(TEXT(" Base CSP provider: \"%s\"\n"), szCspBaseName );
|
|
|
|
hProvBase = 0;
|
|
|
|
osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
GetVersionEx (&osver);
|
|
|
|
if (osver.dwPlatformId==VER_PLATFORM_WIN32_NT && osver.dwMajorVersion > 4)
|
|
{
|
|
CryptResp = CryptAcquireContext( &hProvBase, 0, szCspBaseName, PROV_RSA_FULL,
|
|
CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET );
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
}
|
|
else
|
|
{
|
|
LoadString(g_hInstMod, IDS_GPKCSP_NAME, szCspName, sizeof(szCspName)/sizeof(TCHAR));
|
|
CryptResp = CryptAcquireContext( &hProvBase, szCspName, szCspBaseName,
|
|
PROV_RSA_FULL, CRYPT_DELETEKEYSET );
|
|
|
|
if (0 != hProvBase)
|
|
{
|
|
CryptReleaseContext(hProvBase, 0);
|
|
}
|
|
|
|
LoadString(g_hInstMod, IDS_GPKCSP_NAME, szCspName, sizeof(szCspName)/sizeof(TCHAR));
|
|
CryptResp = CryptAcquireContext( &hProvBase, szCspName, szCspBaseName,
|
|
PROV_RSA_FULL, CRYPT_NEWKEYSET );
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
}
|
|
|
|
/* Set a Dummy RSA exchange key in RSA Base */
|
|
CryptResp = CryptImportKey( hProvBase, PrivateBlob, sizeof(PrivateBlob),
|
|
0, 0, &hRsaIdentityKey );
|
|
|
|
if (!CryptResp)
|
|
{
|
|
lRet = GetLastError();
|
|
CryptReleaseContext( hProvBase, 0 );
|
|
RETURN( CRYPT_FAILED, lRet );
|
|
}
|
|
|
|
RC2_Key_Size = (BYTE) (Auxiliary_CSP_key_size (CALG_RC2) / 8);
|
|
if (RC2_Key_Size == 0)
|
|
{
|
|
lRet = GetLastError();
|
|
|
|
CryptDestroyKey(hRsaIdentityKey); // MV - 13/03/98
|
|
CryptReleaseContext(hProvBase, 0); // MV - 13/03/98
|
|
|
|
RETURN( CRYPT_FAILED, lRet );
|
|
}
|
|
|
|
RSA_KEK_Size = (BYTE) (Auxiliary_CSP_key_size (CALG_RSA_KEYX) / 8);
|
|
if (RSA_KEK_Size == 0)
|
|
{
|
|
lRet = GetLastError();
|
|
|
|
CryptDestroyKey(hRsaIdentityKey); // MV - 13/03/98
|
|
CryptReleaseContext(hProvBase, 0); // MV - 13/03/98
|
|
|
|
RETURN( CRYPT_FAILED, lRet );
|
|
}
|
|
|
|
AuxMaxSessionKeyLength = getAuxMaxKeyLength(hProvBase) / 8;
|
|
if (AuxMaxSessionKeyLength == 0)
|
|
{
|
|
lRet = GetLastError();
|
|
|
|
CryptDestroyKey(hRsaIdentityKey); // MV - 13/03/98
|
|
CryptReleaseContext(hProvBase, 0); // MV - 13/03/98
|
|
|
|
RETURN( CRYPT_FAILED, lRet );
|
|
}
|
|
|
|
// CARD_LIST UPDATE
|
|
LoadString(g_hInstMod, IDS_GPKCSP_CARDLIST, mszCardList, sizeof(mszCardList)/sizeof(TCHAR));
|
|
DBG_PRINT(TEXT(" Card list entry string: \"%s\"\n"), mszCardList );
|
|
|
|
#ifndef UNICODE
|
|
dwIgn = sizeof(mszCardList);
|
|
lRet = RegQueryValueEx( hRegKey, "Card List", 0, 0, (BYTE*)mszCardList, &dwIgn );
|
|
#else
|
|
BYTE bCardList[MAX_PATH];
|
|
DWORD dwCardListLen = MAX_PATH;
|
|
|
|
lRet = RegQueryValueEx( hRegKey, TEXT("Card List"), 0, 0, bCardList, &dwCardListLen );
|
|
MultiByteToWideChar( CP_ACP, 0, (char*)bCardList, MAX_PATH, mszCardList, MAX_PATH );
|
|
#endif
|
|
|
|
// Find in the base registry the name (and the path) for the dictionary
|
|
DBG_PRINT(TEXT(" Reading dictionary name...\n") );
|
|
|
|
#ifndef UNICODE
|
|
dwIgn = sizeof(szDictionaryName);
|
|
lRet = RegQueryValueEx( hRegKey, "X509 Dictionary Name", 0, 0, (BYTE*)szDictionaryName, &dwIgn );
|
|
#else
|
|
BYTE bDictName[256];
|
|
DWORD dwDictNameLen = 256;
|
|
|
|
lRet = RegQueryValueEx( hRegKey, TEXT("X509 Dictionary Name"), 0, 0, bDictName, &dwDictNameLen );
|
|
if (lRet == ERROR_SUCCESS)
|
|
{
|
|
// always use the resource dictionary
|
|
lRet = 2;
|
|
//MultiByteToWideChar( CP_ACP, 0, (char*)bDictName, 256, szDictionaryName, 256);
|
|
}
|
|
#endif
|
|
|
|
// Try to use registry dict first
|
|
if (lRet == ERROR_SUCCESS && IsNotNull( szDictionaryName ))
|
|
{
|
|
lRet = CC_Init( DICT_FILE, (BYTE*)szDictionaryName );
|
|
|
|
if (lRet != RV_SUCCESS)
|
|
lRet = CC_Init( DICT_STANDARD, 0 );
|
|
}
|
|
else
|
|
lRet = CC_Init( DICT_STANDARD, 0 );
|
|
|
|
|
|
RegCloseKey(hRegKey);
|
|
|
|
if (lRet)
|
|
{
|
|
CryptDestroyKey(hRsaIdentityKey);
|
|
CryptReleaseContext(hProvBase, 0);
|
|
|
|
RETURN (CRYPT_FAILED, NTE_NOT_FOUND);
|
|
}
|
|
|
|
// Key gen time for GPK8000
|
|
g_GPK8000KeyGenTime512 = 0;
|
|
g_GPK8000KeyGenTime1024 = 0;
|
|
|
|
lRet = RegCreateKeyEx( HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Gemplus\\Cryptography\\SmartCards"),
|
|
0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_READ, 0, &hRegKey, 0 );
|
|
if (lRet == ERROR_SUCCESS)
|
|
{
|
|
dwIgn = sizeof(g_GPK8000KeyGenTime512);
|
|
lRet = RegQueryValueEx( hRegKey, TEXT("GPK8000KeyGenTime512"), 0, 0, (BYTE*)&g_GPK8000KeyGenTime512, &dwIgn );
|
|
|
|
dwIgn = sizeof(g_GPK8000KeyGenTime1024);
|
|
lRet = RegQueryValueEx( hRegKey, TEXT("GPK8000KeyGenTime1024"), 0, 0, (BYTE*)&g_GPK8000KeyGenTime1024, &dwIgn );
|
|
|
|
RegCloseKey(hRegKey);
|
|
}
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
--------------------------------------------------------------------------------*/
|
|
BOOL LegacyAcquireDeleteKeySet( HCRYPTPROV* phProv,
|
|
const char* szContainer,
|
|
const char* szContainerAsked,
|
|
DWORD BuffFlags )
|
|
{
|
|
BOOL CryptResp;
|
|
//DWORD i;
|
|
DWORD SlotNb;
|
|
|
|
SlotNb = ProvCont[*phProv].Slot;
|
|
|
|
/*if (Slot[SlotNb].ContextCount > 0)
|
|
{
|
|
fLocked = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// Must have exclusive access to destroy a keyset
|
|
DWORD protocol;
|
|
lRet = SCardReconnect( ProvCont[*phProv].hCard, SCARD_SHARE_EXCLUSIVE,
|
|
SCARD_PROTOCOL_T0, SCARD_LEAVE_CARD, &protocol );
|
|
|
|
if (lRet==SCARD_S_SUCCESS)
|
|
fLocked = FALSE;
|
|
else if (lRet==SCARD_E_SHARING_VIOLATION)
|
|
fLocked = TRUE;
|
|
else
|
|
RETURN( CRYPT_FAILED, lRet );
|
|
}
|
|
|
|
if (fLocked)
|
|
RETURN( CRYPT_FAILED, SCARD_E_SHARING_VIOLATION );*/
|
|
|
|
if (BuffFlags & CRYPT_VERIFYCONTEXT)
|
|
RETURN( CRYPT_FAILED, NTE_BAD_FLAGS );
|
|
|
|
if (IsNotNullStr(szContainer))
|
|
{
|
|
// Accept only if the container asked is the same as the one on the card
|
|
// OR if the container asked is NULL (default key set)
|
|
if (IsNotNullStr(szContainerAsked) && strcmp(szContainer, szContainerAsked))
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_KEYSET_NOT_DEF );
|
|
}
|
|
|
|
/* Release Microsoft RSA Base Module */
|
|
//for (i = 1; i <= MAX_GPK_OBJ; i++)
|
|
//{
|
|
// if (Slot[SlotNb].GpkObject[i].hKeyBase != 0)
|
|
// {
|
|
// CryptResp = CryptDestroyKey(Slot[SlotNb].GpkObject[i].hKeyBase);
|
|
// }
|
|
//}
|
|
|
|
//ProvCont[*phProv].hRSASign = 0;
|
|
//ProvCont[*phProv].hRSAKEK = 0;
|
|
if (ProvCont[*phProv].hRSAKEK != 0)
|
|
{
|
|
CryptDestroyKey( ProvCont[*phProv].hRSAKEK );
|
|
ProvCont[*phProv].hRSAKEK = 0;
|
|
}
|
|
if (ProvCont[*phProv].hRSASign != 0)
|
|
{
|
|
CryptDestroyKey( ProvCont[*phProv].hRSASign );
|
|
ProvCont[*phProv].hRSASign = 0;
|
|
}
|
|
ProvCont[*phProv].hProv = *phProv;
|
|
ProvCont[*phProv].Flags = BuffFlags;
|
|
|
|
if (!PIN_Validation(*phProv))
|
|
return CRYPT_FAILED;
|
|
|
|
ProvCont[*phProv].hProv = 0;
|
|
ProvCont[*phProv].Flags = 0;
|
|
|
|
CryptResp = init_key_set(*phProv, "");
|
|
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
|
|
// Update the container name
|
|
|
|
strcpy( ProvCont[*phProv].szContainer, "" );
|
|
|
|
RETURN( CRYPT_SUCCEED, 0 );
|
|
}
|
|
else
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_BAD_KEYSET_PARAM );
|
|
}
|
|
}
|
|
|
|
|
|
// TT 12/10/99: Bug #1454
|
|
void DeleteGPKObject( Slot_Description* pSlot, int i )
|
|
{
|
|
GPK_OBJ* pObject = &pSlot->GpkObject[i];
|
|
int j;
|
|
|
|
// Delete object #i
|
|
|
|
// Release Microsoft RSA Base Module
|
|
if (pObject->hKeyBase != 0)
|
|
{
|
|
CryptDestroyKey( pObject->hKeyBase );
|
|
pObject->hKeyBase = 0;
|
|
}
|
|
|
|
// First free all memory for this object
|
|
for (j=0; j<MAX_FIELD; ++j)
|
|
{
|
|
if (pObject->Field[j].pValue)
|
|
{
|
|
GMEM_Free( pObject->Field[j].pValue );
|
|
pObject->Field[j].pValue = 0;
|
|
pObject->Field[j].Len = 0;
|
|
}
|
|
}
|
|
|
|
if (i < pSlot->NbGpkObject)
|
|
{
|
|
// Patch the hole
|
|
memmove( pObject, pObject + 1, (pSlot->NbGpkObject - i) * sizeof(GPK_OBJ) );
|
|
}
|
|
|
|
// Clear last object
|
|
ZeroMemory( &pSlot->GpkObject[pSlot->NbGpkObject], sizeof(GPK_OBJ) );
|
|
|
|
--pSlot->NbGpkObject;
|
|
}
|
|
// TT: End
|
|
|
|
|
|
BOOL AcquireDeleteKeySet( HCRYPTPROV* phProv,
|
|
const char* szContainer,
|
|
const char* szContainerAsked,
|
|
DWORD BuffFlags )
|
|
{
|
|
Prov_Context* pContext;
|
|
GPK_OBJ* pKeySet;
|
|
GPK_OBJ* pObject;
|
|
Slot_Description* pSlot;
|
|
BYTE keysetID;
|
|
int i, j, k;
|
|
BYTE* pbBuff1;
|
|
DWORD dwBuff1Len;
|
|
DWORD lRet;
|
|
|
|
DWORD SlotNb = ProvCont[*phProv].Slot;
|
|
|
|
/*if (Slot[SlotNb].ContextCount > 0)
|
|
{
|
|
fLocked = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// Must have exclusive access to destroy a keyset
|
|
DWORD protocol;
|
|
lRet = SCardReconnect( ProvCont[*phProv].hCard, SCARD_SHARE_EXCLUSIVE,
|
|
SCARD_PROTOCOL_T0, SCARD_LEAVE_CARD, &protocol );
|
|
|
|
if (lRet==SCARD_S_SUCCESS)
|
|
fLocked = FALSE;
|
|
else if (lRet==SCARD_E_SHARING_VIOLATION)
|
|
fLocked = TRUE;
|
|
else
|
|
RETURN( CRYPT_FAILED, lRet );
|
|
}
|
|
|
|
if (fLocked)
|
|
{
|
|
RETURN( CRYPT_FAILED, SCARD_E_SHARING_VIOLATION );
|
|
}*/
|
|
|
|
if (BuffFlags & CRYPT_VERIFYCONTEXT)
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_BAD_FLAGS );
|
|
}
|
|
|
|
pContext = &ProvCont[*phProv];
|
|
pSlot = &Slot[ pContext->Slot ];
|
|
|
|
// if default keyset, let's use the first
|
|
// one available =)
|
|
if ( IsNullStr(szContainerAsked) )
|
|
{
|
|
pKeySet = FindFirstKeyset( pSlot );
|
|
}
|
|
else
|
|
{
|
|
// Check if keyset is on the card
|
|
pKeySet = FindKeySet( pSlot, szContainerAsked );
|
|
}
|
|
|
|
if (!pKeySet)
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_KEYSET_NOT_DEF );
|
|
}
|
|
|
|
|
|
// Must validate PIN to destroy the key objects
|
|
//pContext->hRSASign = 0;
|
|
//pContext->hRSAKEK = 0;
|
|
if (pContext->hRSAKEK != 0)
|
|
{
|
|
CryptDestroyKey( pContext->hRSAKEK );
|
|
pContext->hRSAKEK = 0;
|
|
}
|
|
if (pContext->hRSASign != 0)
|
|
{
|
|
CryptDestroyKey( pContext->hRSASign );
|
|
pContext->hRSASign = 0;
|
|
}
|
|
pContext->hProv = *phProv;
|
|
pContext->Flags = BuffFlags;
|
|
|
|
if (!PIN_Validation(*phProv))
|
|
{
|
|
// SetLastError() already used by PIN_Validation()
|
|
return CRYPT_FAILED;
|
|
}
|
|
|
|
if (!Read_Priv_Obj(*phProv))
|
|
return CRYPT_FAILED;
|
|
|
|
// TT 12/10/99: Bug #1454
|
|
keysetID = pKeySet->Field[POS_ID].pValue[0];
|
|
|
|
// Find objects in the keyset and destroy them
|
|
for (i = 1; i <= pSlot->NbGpkObject; ++i)
|
|
{
|
|
pObject = &pSlot->GpkObject[i];
|
|
|
|
if (pObject->Flags & FLAG_KEYSET && pObject->Field[POS_KEYSET].pValue[0] == keysetID)
|
|
{
|
|
// If we found a key, "zap it"
|
|
if (pObject->Tag >= TAG_RSA_PUBLIC && pObject->Tag <= TAG_DSA_PRIVATE)
|
|
{
|
|
// Zap all keys with the same FileId
|
|
BYTE FileId = pObject->FileId;
|
|
|
|
for (j = 1; j<= pSlot->NbGpkObject; ++j)
|
|
{
|
|
GPK_OBJ* pObj = &pSlot->GpkObject[j];
|
|
if (pObj->Tag >= TAG_RSA_PUBLIC && pObj->Tag <= TAG_DSA_PRIVATE)
|
|
{
|
|
if (pObj->FileId == FileId)
|
|
{
|
|
pObj->Flags &= 0xF000;
|
|
pObj->ObjId = 0xFF;
|
|
|
|
// Release the fields
|
|
for (k=0; k<MAX_FIELD; ++k)
|
|
{
|
|
if (pObj->Field[k].pValue)
|
|
{
|
|
GMEM_Free( pObj->Field[k].pValue );
|
|
pObj->Field[k].pValue = 0;
|
|
pObj->Field[k].Len = 0;
|
|
}
|
|
pObj->Field[k].bReal = TRUE;
|
|
}
|
|
pObj->LastField = 0;
|
|
pObj->IsCreated = FALSE; //PYR 00/08/08 ensure that find_gpk_obj_tag_type will still work
|
|
|
|
// Release Microsoft RSA Base Module
|
|
//if (pObj->hKeyBase != 0)
|
|
//{
|
|
// CryptDestroyKey( pObj->hKeyBase );
|
|
// pObj->hKeyBase = 0;
|
|
//}
|
|
|
|
// PYR 00/08/08. This key becomes available
|
|
pSlot->UseFile[FileId - GPK_FIRST_KEY] = FALSE;
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Not a key, destroy the object
|
|
DeleteGPKObject( pSlot, i );
|
|
--i;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Destroy the keyset object
|
|
DeleteGPKObject( pSlot, (int)(pKeySet - &pSlot->GpkObject[0]) );
|
|
|
|
|
|
// TT: End
|
|
|
|
// TT 12/10/99: Bug #1454 - Update the card
|
|
pbBuff1 = (BYTE*)GMEM_Alloc( MAX_GPK_PUBLIC );
|
|
if (IsNull(pbBuff1))
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_NO_MEMORY );
|
|
}
|
|
|
|
dwBuff1Len = MAX_GPK_PUBLIC;
|
|
if (!prepare_write_gpk_objects (pContext->hProv, pbBuff1, &dwBuff1Len, FALSE))
|
|
{
|
|
lRet = GetLastError();
|
|
GMEM_Free (pbBuff1);
|
|
RETURN( CRYPT_FAILED, lRet );
|
|
}
|
|
|
|
if (!write_gpk_objects(pContext->hProv, pbBuff1, dwBuff1Len, TRUE, FALSE))
|
|
{
|
|
lRet = GetLastError();
|
|
GMEM_Free (pbBuff1);
|
|
RETURN( CRYPT_FAILED, lRet );
|
|
}
|
|
|
|
GMEM_Free( pbBuff1 );
|
|
|
|
pbBuff1 = (BYTE*)GMEM_Alloc( MAX_GPK_PRIVATE );
|
|
if (IsNull(pbBuff1))
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_NO_MEMORY );
|
|
}
|
|
|
|
dwBuff1Len = MAX_GPK_PRIVATE;
|
|
if (!prepare_write_gpk_objects (pContext->hProv, pbBuff1, &dwBuff1Len, TRUE))
|
|
{
|
|
lRet = GetLastError();
|
|
GMEM_Free (pbBuff1);
|
|
RETURN( CRYPT_FAILED, lRet );
|
|
}
|
|
|
|
if (!write_gpk_objects(pContext->hProv, pbBuff1, dwBuff1Len, TRUE, TRUE))
|
|
{
|
|
lRet = GetLastError();
|
|
GMEM_Free (pbBuff1);
|
|
RETURN( CRYPT_FAILED, lRet );
|
|
}
|
|
|
|
GMEM_Free( pbBuff1 );
|
|
// TT: End
|
|
|
|
|
|
// Byebye context
|
|
pContext->hProv = 0;
|
|
pContext->Flags = 0;
|
|
pContext->szContainer[0] = 0;
|
|
|
|
RETURN( CRYPT_SUCCEED, 0 );
|
|
}
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
--------------------------------------------------------------------------------*/
|
|
BOOL LegacyAcquireNewKeySet( IN HCRYPTPROV* phProv,
|
|
OUT char* szContainer,
|
|
IN const char* szContainerAsked,
|
|
IN DWORD BuffFlags )
|
|
{
|
|
BOOL CryptResp, fLocked;
|
|
DWORD i, SlotNb;
|
|
HCRYPTKEY hPubKey;
|
|
// +NK 06.02.2001
|
|
// BYTE bPinValue[PIN_MAX+2];
|
|
DWORD dwPinLength;
|
|
DWORD dwStatus;
|
|
// -
|
|
|
|
ProvCont[*phProv].keysetID = 0;
|
|
|
|
SlotNb = ProvCont[*phProv].Slot;
|
|
|
|
// If another AcquireContext - without its related ReleaseContest -
|
|
// has been done before, this new AcquireContext can not be done
|
|
|
|
if (BuffFlags & CRYPT_VERIFYCONTEXT)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_FLAGS);
|
|
}
|
|
|
|
|
|
|
|
/* IN CASE THAT A DELETEKEY IS NOT DONE FOR A RE-ENROLLMENT */
|
|
|
|
// Reserve the Provider Context handle since the Acquire Context succeeded
|
|
ProvCont[*phProv].hProv = *phProv;
|
|
ProvCont[*phProv].Flags = BuffFlags;
|
|
|
|
if (Slot[SlotNb].InitFlag)
|
|
{
|
|
CryptResp = MyCPGetUserKey(*phProv, AT_KEYEXCHANGE, &hPubKey);
|
|
if (CryptResp)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_TOKEN_KEYSET_STORAGE_FULL);
|
|
}
|
|
else
|
|
{
|
|
CryptResp = MyCPGetUserKey(*phProv, AT_SIGNATURE, &hPubKey);
|
|
if (CryptResp)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_TOKEN_KEYSET_STORAGE_FULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
// If another AcquireContext - without its related ReleaseContest -
|
|
// has been done before, this new AcquireContext can not be done
|
|
// {DCB} -- It's possible that the application that marked this busy
|
|
// exited without calling CryptReleaseContext. Hence, it's
|
|
// possible that this check will fail even if no one else
|
|
// is using the card. By making this check last, we reduce
|
|
// the likelyhood that this bug is encountered.
|
|
|
|
fLocked = FALSE;
|
|
|
|
if (fLocked)
|
|
{
|
|
RETURN (CRYPT_FAILED, SCARD_E_SHARING_VIOLATION);
|
|
}
|
|
|
|
|
|
// +NK 06.02.2001
|
|
// if ((BuffFlags & CRYPT_SILENT) && (IsNullStr(Slot[SlotNb].GetPin())))
|
|
|
|
dwStatus = Query_MSPinCache( Slot[SlotNb].hPinCacheHandle,
|
|
NULL,
|
|
&dwPinLength );
|
|
if ( (dwStatus != ERROR_SUCCESS) && (dwStatus != ERROR_EMPTY) )
|
|
RETURN (CRYPT_FAILED, dwStatus);
|
|
|
|
if ((BuffFlags & CRYPT_SILENT) && (dwStatus == ERROR_EMPTY))
|
|
// -
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_SILENT_CONTEXT);
|
|
}
|
|
|
|
if (!PIN_Validation(*phProv))
|
|
return CRYPT_FAILED;
|
|
|
|
/* If the PIN code can be or has been entered, read the description of the
|
|
private key parameters*/
|
|
|
|
CspFlags = BuffFlags;
|
|
|
|
|
|
if (IsNullStr(szContainerAsked))
|
|
{
|
|
// no szContainerAsked is specified, create the keyset object with default name
|
|
CryptResp = init_key_set(*phProv, CSP_DEFAULTKEYSETNAME);
|
|
}
|
|
else
|
|
{
|
|
CryptResp = init_key_set(*phProv, szContainerAsked);
|
|
}
|
|
|
|
|
|
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
|
|
if (PublicEFExists(*phProv))
|
|
{
|
|
for (i = 1; i <= Slot[SlotNb].NbGpkObject; i++)
|
|
{
|
|
if ((Slot[SlotNb].GpkObject[i].Tag == TAG_RSA_PUBLIC)||
|
|
(Slot[SlotNb].GpkObject[i].Tag == TAG_RSA_PRIVATE))
|
|
{
|
|
read_gpk_pub_key(*phProv, i, &(Slot[SlotNb].GpkObject[i].PubKey));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 1; i <= Slot[SlotNb].NbGpkObject; i++)
|
|
{
|
|
if ((Slot[SlotNb].GpkObject[i].Tag == TAG_RSA_PUBLIC)||
|
|
(Slot[SlotNb].GpkObject[i].Tag == TAG_RSA_PRIVATE))
|
|
{
|
|
Slot[SlotNb].GpkObject[i].PubKey.KeySize = 0;
|
|
}
|
|
}
|
|
}
|
|
// Update the container name
|
|
if (IsNullStr(szContainerAsked))
|
|
{
|
|
// no szContainerAsked is specified, use default name
|
|
strcpy( szContainer, CSP_DEFAULTKEYSETNAME );
|
|
}
|
|
else
|
|
{
|
|
strcpy( szContainer, szContainerAsked );
|
|
}
|
|
|
|
|
|
Slot[SlotNb].ContextCount++;
|
|
|
|
countCardContextRef++;
|
|
|
|
ProvCont[*phProv].keysetID = 0xFF;
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
|
|
|
|
BOOL CreateKeyset( HCRYPTPROV hProv, Slot_Description* pSlot, LPCSTR szName, BYTE* pKeySetID )
|
|
{
|
|
GPK_OBJ* pObject;
|
|
BYTE* pbBuff1;
|
|
DWORD dwBuff1Len;
|
|
int lRet;
|
|
BYTE keysetID;
|
|
int i, len;
|
|
|
|
*pKeySetID = 0;
|
|
|
|
if (pSlot->NbGpkObject >= MAX_GPK_OBJ)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
pObject = &pSlot->GpkObject[ pSlot->NbGpkObject + 1 ];
|
|
ZeroMemory( pObject, sizeof(*pObject) );
|
|
|
|
// Find an unused keyset ID
|
|
for (keysetID = 1; keysetID < 0xFF; ++keysetID)
|
|
{
|
|
if (FindKeySetByID( pSlot, keysetID ) == 0)
|
|
break; // Found one =)
|
|
}
|
|
|
|
if (keysetID == 0xFF)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
// Now initialize the fields
|
|
for (i=0; i<MAX_FIELD; ++i)
|
|
pObject->Field[i].bReal = TRUE;
|
|
|
|
pObject->Tag = TAG_KEYSET;
|
|
pObject->Flags = FLAG_ID | FLAG_LABEL;
|
|
pObject->ObjId = pSlot->NbGpkObject + 1;
|
|
pObject->IsPrivate = FALSE;
|
|
|
|
// Keyset ID
|
|
pObject->Field[POS_ID].Len = 1;
|
|
pObject->Field[POS_ID].pValue = (BYTE*)GMEM_Alloc( 1 );
|
|
if(IsNull(pObject->Field[POS_ID].pValue))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
pObject->Field[POS_ID].pValue[0] = keysetID;
|
|
|
|
// Keyset name
|
|
len = strlen( szName );
|
|
pObject->Field[POS_LABEL].Len = (WORD)len;
|
|
pObject->Field[POS_LABEL].pValue = (BYTE*)GMEM_Alloc( len );
|
|
if(IsNull(pObject->Field[POS_LABEL].pValue))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
memcpy( pObject->Field[POS_LABEL].pValue, szName, len );
|
|
|
|
// One more object!
|
|
++(pSlot->NbGpkObject);
|
|
|
|
*pKeySetID = keysetID;
|
|
|
|
// TT 29/09/99: Save the keyset object =)
|
|
pbBuff1 = (BYTE*)GMEM_Alloc(MAX_GPK_PUBLIC);
|
|
if (IsNull(pbBuff1))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
dwBuff1Len = MAX_GPK_PUBLIC;
|
|
if (!prepare_write_gpk_objects (hProv, pbBuff1, &dwBuff1Len, FALSE))
|
|
{
|
|
lRet = GetLastError();
|
|
GMEM_Free (pbBuff1);
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
if (!write_gpk_objects(hProv, pbBuff1, dwBuff1Len, FALSE, FALSE))
|
|
{
|
|
lRet = GetLastError();
|
|
GMEM_Free (pbBuff1);
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
GMEM_Free (pbBuff1);
|
|
// TT - END -
|
|
|
|
|
|
RETURN( CRYPT_SUCCEED, 0 );
|
|
}
|
|
|
|
|
|
|
|
BOOL AcquireNewKeySet( IN HCRYPTPROV* phProv,
|
|
OUT char* szContainer,
|
|
IN const char* szContainerAsked,
|
|
DWORD BuffFlags )
|
|
{
|
|
Slot_Description* pSlot;
|
|
int SlotNb;
|
|
|
|
SlotNb = ProvCont[*phProv].Slot;
|
|
pSlot = &Slot[SlotNb];
|
|
|
|
ProvCont[*phProv].keysetID = 0;
|
|
|
|
// If another AcquireContext - without its related ReleaseContest -
|
|
// has been done before, this new AcquireContext can not be done
|
|
if (BuffFlags & CRYPT_VERIFYCONTEXT)
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_BAD_FLAGS );
|
|
}
|
|
|
|
// Check if keyset already exist on the card
|
|
if (FindKeySet( pSlot, szContainerAsked ))
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_EXISTS );
|
|
}
|
|
|
|
|
|
// Reserve the Provider Context handle since the Acquire Context succeeded
|
|
ProvCont[*phProv].hProv = *phProv;
|
|
ProvCont[*phProv].Flags = BuffFlags;
|
|
|
|
CspFlags = BuffFlags;
|
|
|
|
|
|
if (IsNullStr(szContainerAsked))
|
|
{
|
|
// no szContainerAsked is specified, create the keyset object with default name
|
|
if (!CreateKeyset( *phProv, pSlot, CSP_DEFAULTKEYSETNAME, &ProvCont[*phProv].keysetID ))
|
|
{
|
|
return FALSE;
|
|
}
|
|
// Update the container name
|
|
strcpy( szContainer, CSP_DEFAULTKEYSETNAME );
|
|
}
|
|
else
|
|
{
|
|
// Create the keyset object
|
|
if (!CreateKeyset( *phProv, pSlot, szContainerAsked, &ProvCont[*phProv].keysetID ))
|
|
{
|
|
return FALSE;
|
|
}
|
|
// Update the container name
|
|
strcpy( szContainer, szContainerAsked );
|
|
}
|
|
|
|
++(pSlot->ContextCount);
|
|
|
|
++countCardContextRef;
|
|
|
|
RETURN( CRYPT_SUCCEED, 0 );
|
|
}
|
|
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
--------------------------------------------------------------------------------*/
|
|
BOOL LegacyAcquireUseKeySet( HCRYPTPROV* phProv,
|
|
const char* szContainer,
|
|
const char* szContainerAsked,
|
|
DWORD BuffFlags )
|
|
{
|
|
BOOL CryptResp;
|
|
HCRYPTKEY hPubKey;
|
|
DWORD SlotNb;
|
|
|
|
SlotNb = ProvCont[*phProv].Slot;
|
|
ProvCont[*phProv].keysetID = 0;
|
|
|
|
if (IsNullStr(szContainer))
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_KEYSET_NOT_DEF );
|
|
}
|
|
|
|
// Accept only if the container asked is the same as the one on the card
|
|
// OR if the container asked is NULL and a reader is specified (SECURE LOGON)
|
|
if (IsNotNullStr(szContainerAsked) && strcmp(szContainer, szContainerAsked))
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_BAD_KEYSET );
|
|
}
|
|
|
|
// Reserve the Provider Context handle since the Acquire Context succeeded
|
|
ProvCont[*phProv].hProv = *phProv;
|
|
ProvCont[*phProv].Flags = BuffFlags;
|
|
|
|
hPubKey = 0;
|
|
CryptResp = MyCPGetUserKey(*phProv, AT_KEYEXCHANGE, &hPubKey);
|
|
|
|
// Copy the key into the RSA Base, if the key exists AND it has not been imported
|
|
// previously
|
|
|
|
if ((CryptResp) && (hPubKey != 0) && (ProvCont[*phProv].hRSAKEK == 0))
|
|
{
|
|
if (!copy_gpk_key(*phProv, hPubKey, AT_KEYEXCHANGE))
|
|
return CRYPT_FAILED;
|
|
}
|
|
|
|
hPubKey = 0;
|
|
CryptResp = MyCPGetUserKey(*phProv, AT_SIGNATURE, &hPubKey);
|
|
|
|
// Copy the key into the RSA Base, if the key exists AND it has not been imported
|
|
// previously
|
|
|
|
if (CryptResp && hPubKey!=0 && ProvCont[*phProv].hRSASign==0)
|
|
{
|
|
if (!copy_gpk_key(*phProv, hPubKey, AT_SIGNATURE))
|
|
return CRYPT_FAILED;
|
|
}
|
|
|
|
Slot[SlotNb].ContextCount++;
|
|
|
|
countCardContextRef++;
|
|
|
|
ProvCont[*phProv].keysetID = 0xFF;
|
|
|
|
RETURN( CRYPT_SUCCEED, 0 );
|
|
}
|
|
|
|
|
|
|
|
BOOL AcquireUseKeySet( HCRYPTPROV* phProv,
|
|
const char* szContainer,
|
|
const char* szContainerAsked,
|
|
DWORD BuffFlags )
|
|
{
|
|
BOOL CryptResp;
|
|
HCRYPTKEY hPubKey;
|
|
DWORD SlotNb;
|
|
GPK_OBJ* pKeySet;
|
|
|
|
SlotNb = ProvCont[*phProv].Slot;
|
|
ProvCont[*phProv].keysetID = 0;
|
|
|
|
// Secure logon doesn't specify a keyset name, let's use the first
|
|
// one available =)
|
|
if ( IsNullStr(szContainerAsked) )
|
|
{
|
|
pKeySet = FindFirstKeyset( &Slot[SlotNb] );
|
|
}
|
|
else
|
|
{
|
|
// Check if keyset is on the card
|
|
pKeySet = FindKeySet( &Slot[SlotNb], szContainerAsked );
|
|
}
|
|
|
|
if (pKeySet==0)
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_KEYSET_NOT_DEF );
|
|
}
|
|
|
|
// Found the container...
|
|
memcpy( ProvCont[*phProv].szContainer, (char*)pKeySet->Field[POS_LABEL].pValue,
|
|
pKeySet->Field[POS_LABEL].Len );
|
|
|
|
// Reserve the Provider Context handle since the Acquire Context succeeded
|
|
ProvCont[*phProv].hProv = *phProv;
|
|
ProvCont[*phProv].Flags = BuffFlags;
|
|
ProvCont[*phProv].keysetID = pKeySet->Field[POS_ID].pValue[0];
|
|
|
|
hPubKey = 0;
|
|
|
|
CryptResp = MyCPGetUserKey(*phProv, AT_KEYEXCHANGE, &hPubKey);
|
|
|
|
// Copy the key into the RSA Base, if the key exists AND it has not been imported
|
|
// previously
|
|
|
|
if ((CryptResp) && (hPubKey != 0) && (ProvCont[*phProv].hRSAKEK == 0))
|
|
{
|
|
if (!copy_gpk_key(*phProv, hPubKey, AT_KEYEXCHANGE))
|
|
{
|
|
return CRYPT_FAILED;
|
|
}
|
|
}
|
|
|
|
hPubKey = 0;
|
|
CryptResp = MyCPGetUserKey(*phProv, AT_SIGNATURE, &hPubKey);
|
|
|
|
// Copy the key into the RSA Base, if the key exists AND it has not been imported
|
|
// previously
|
|
|
|
if ((CryptResp) && (hPubKey != 0) && (ProvCont[*phProv].hRSASign == 0))
|
|
{
|
|
if (!copy_gpk_key(*phProv, hPubKey, AT_SIGNATURE))
|
|
{
|
|
return CRYPT_FAILED;
|
|
}
|
|
}
|
|
|
|
Slot[SlotNb].ContextCount++;
|
|
|
|
countCardContextRef++;
|
|
|
|
RETURN( CRYPT_SUCCEED, 0 );
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
- MyCPAcquireContext
|
|
-
|
|
* Purpose:
|
|
* The CPAcquireContext function is used to acquire a context
|
|
* handle to a cryptograghic service provider (CSP).
|
|
*
|
|
*
|
|
* Parameters:
|
|
* OUT phProv - Handle to a CSP
|
|
* OUT pszIdentity - Pointer to a string which is the
|
|
* identity of the logged on user
|
|
* IN dwFlags - Flags values
|
|
* IN pVTable - Pointer to table of function pointers
|
|
*
|
|
* Returns:
|
|
*/
|
|
BOOL WINAPI MyCPAcquireContext(OUT HCRYPTPROV *phProv,
|
|
IN LPCSTR pszContainer,
|
|
IN DWORD dwFlags,
|
|
IN PVTableProvStruc pVTable
|
|
)
|
|
{
|
|
SCARD_READERSTATE ReaderState;
|
|
DWORD dwStatus;
|
|
DWORD dwProto, ind, ind2;
|
|
DWORD BuffFlags;
|
|
DWORD lRet;
|
|
DWORD SlotNb;
|
|
BOOL CryptResp;
|
|
char szContainerAsked[MAX_PATH];
|
|
TCHAR szReaderName[512],
|
|
szReaderFriendlyName[512],
|
|
szModulePath[MAX_PATH],
|
|
szCspTitle[MAX_STRING],
|
|
szCspText[MAX_STRING];
|
|
|
|
*phProv = 0;
|
|
|
|
if (IsNull(hFirstInstMod))
|
|
{
|
|
hFirstInstMod = g_hInstMod;
|
|
|
|
dwStatus = GetModuleFileName( g_hInstMod, szModulePath, sizeof(szModulePath)/sizeof(TCHAR) );
|
|
|
|
if (dwStatus)
|
|
LoadLibrary(szModulePath);
|
|
}
|
|
|
|
if (bFirstGUILoad)
|
|
{
|
|
bFirstGUILoad = FALSE;
|
|
|
|
dwStatus = GetModuleFileName( g_hInstMod, szModulePath, sizeof(szModulePath)/sizeof(TCHAR) );
|
|
|
|
if (dwStatus)
|
|
{
|
|
#ifdef MS_BUILD
|
|
// Microsoft uses "gpkrsrc.dll"
|
|
_tcscpy(&szModulePath[_tcslen(szModulePath) - 7], TEXT("rsrc.dll"));
|
|
#else
|
|
// Gemplus uses "gpkgui.dll"
|
|
_tcscpy(&szModulePath[_tcslen(szModulePath) - 7], TEXT("gui.dll"));
|
|
#endif
|
|
DBG_PRINT(TEXT("Trying to load resource DLL: \"%s\""), szModulePath );
|
|
g_hInstRes = LoadLibrary(szModulePath);
|
|
DBG_PRINT(TEXT("Result is g_hInstRes = %08x, error is %08x"), g_hInstRes, (g_hInstRes) ? GetLastError(): 0 );
|
|
|
|
if (IsNull(g_hInstRes))
|
|
{
|
|
if (!(dwFlags & CRYPT_SILENT))
|
|
{
|
|
LoadString(g_hInstMod, IDS_GPKCSP_TITLE, szCspTitle, sizeof(szCspTitle)/sizeof(TCHAR));
|
|
LoadString(g_hInstMod, IDS_GPKCSP_NOGUI, szCspText, sizeof(szCspText)/sizeof(TCHAR));
|
|
MessageBox(0, szCspText, szCspTitle, MB_OK | MB_ICONEXCLAMATION);
|
|
}
|
|
RETURN( CRYPT_FAILED, NTE_PROVIDER_DLL_FAIL );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!(dwFlags & CRYPT_SILENT))
|
|
{
|
|
LoadString(g_hInstMod, IDS_GPKCSP_TITLE, szCspTitle, sizeof(szCspTitle)/sizeof(TCHAR));
|
|
LoadString(g_hInstMod, IDS_GPKCSP_NOGUI, szCspText, sizeof(szCspText)/sizeof(TCHAR));
|
|
MessageBox(0, szCspText, szCspTitle, MB_OK | MB_ICONEXCLAMATION);
|
|
}
|
|
RETURN( CRYPT_FAILED, NTE_PROVIDER_DLL_FAIL );
|
|
}
|
|
}
|
|
|
|
g_hMainWnd = 0;
|
|
if (pVTable)
|
|
{
|
|
if (pVTable->FuncReturnhWnd != 0)
|
|
{
|
|
// cspdk.h doesn't define the calling convention properly
|
|
typedef void (__stdcall *STDCALL_CRYPT_RETURN_HWND)(HWND *phWnd);
|
|
STDCALL_CRYPT_RETURN_HWND pfnFuncRreturnhWnd = (STDCALL_CRYPT_RETURN_HWND)pVTable->FuncReturnhWnd;
|
|
pfnFuncRreturnhWnd( &g_hMainWnd );
|
|
}
|
|
}
|
|
|
|
|
|
// If it is the first AcquireContext done by the application, then
|
|
// prepare the RSA BASE and initialize some variables;
|
|
if (hProvBase == 0)
|
|
{
|
|
CryptResp = InitAcquire();
|
|
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
}
|
|
|
|
BuffFlags = dwFlags;
|
|
|
|
if (dwFlags & CRYPT_VERIFYCONTEXT)
|
|
dwFlags = dwFlags^CRYPT_VERIFYCONTEXT;
|
|
|
|
if (dwFlags & CRYPT_SILENT)
|
|
dwFlags = dwFlags^CRYPT_SILENT;
|
|
|
|
if (dwFlags & CRYPT_MACHINE_KEYSET) // This flag is ignored by this CSP
|
|
dwFlags = dwFlags^CRYPT_MACHINE_KEYSET;
|
|
|
|
|
|
// Parse the container name
|
|
|
|
ZeroMemory( szReaderFriendlyName, sizeof(szReaderFriendlyName) );
|
|
ZeroMemory( szContainerAsked, sizeof(szContainerAsked) );
|
|
|
|
if (IsNotNull (pszContainer))
|
|
{
|
|
ind = 0;
|
|
if (pszContainer[ind] == '\\')
|
|
{
|
|
ind = 4;
|
|
while ((pszContainer[ind] != 0x00) && (pszContainer[ind] != '\\'))
|
|
{
|
|
szReaderFriendlyName[ind-4] = pszContainer[ind];
|
|
ind++;
|
|
}
|
|
|
|
if (pszContainer[ind] == '\\')
|
|
{
|
|
ind++;
|
|
}
|
|
}
|
|
|
|
ind2 = 0;
|
|
while ((pszContainer[ind] != 0x00) && (ind2<sizeof(szContainerAsked)-1))
|
|
{
|
|
szContainerAsked[ind2] = pszContainer[ind];
|
|
ind++;
|
|
ind2++;
|
|
}
|
|
}
|
|
|
|
// Find a free handle for this new AcquireContext
|
|
|
|
*phProv = find_context_free();
|
|
if (*phProv == 0)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
ProvCont[*phProv].isContNameNullBlank = IsNullStr(pszContainer); // [mv - 15/05/98]
|
|
ProvCont[*phProv].bCardTransactionOpened = FALSE; // [FP]
|
|
|
|
if ((BuffFlags & CRYPT_VERIFYCONTEXT) && (ProvCont[*phProv].isContNameNullBlank)) // [mv - 15/05/98]
|
|
{
|
|
// return a velid handle, but without any access to the card
|
|
ProvCont[*phProv].hProv = *phProv;
|
|
ProvCont[*phProv].Flags = BuffFlags;
|
|
RETURN( CRYPT_SUCCEED, 0 );
|
|
}
|
|
else
|
|
{
|
|
/* Calais IRM Establish Context */
|
|
if (hCardContext == 0) // mv
|
|
{
|
|
lRet = SCardEstablishContext( SCARD_SCOPE_SYSTEM, 0, 0, &hCardContext );
|
|
|
|
if (SCARDPROBLEM(lRet,0x0000,0xFF))
|
|
{
|
|
hCardContext = 0;
|
|
countCardContextRef = 0;
|
|
ReleaseProvider(*phProv);
|
|
*phProv = 0;
|
|
RETURN( CRYPT_FAILED, lRet );
|
|
}
|
|
}
|
|
|
|
|
|
#if (_WIN32_WINNT < 0x0500)
|
|
|
|
// Read the reader list
|
|
char* pAllocatedBuff = 0;
|
|
|
|
__try
|
|
{
|
|
static s_bInit = false;
|
|
|
|
if (!s_bInit)
|
|
{
|
|
DWORD i, BuffLength;
|
|
char* Buff;
|
|
|
|
lRet = SCardListReaders(hCardContext, 0, 0, &BuffLength);
|
|
if (SCARDPROBLEM(lRet,0x0000,0xFF))
|
|
{
|
|
ReleaseProvider(*phProv);
|
|
*phProv = 0;
|
|
RETURN( CRYPT_FAILED, lRet );
|
|
}
|
|
|
|
pAllocatedBuff = (char*)GMEM_Alloc(BuffLength);
|
|
|
|
if (pAllocatedBuff == 0)
|
|
{
|
|
ReleaseProvider(*phProv);
|
|
*phProv = 0;
|
|
RETURN( CRYPT_FAILED, NTE_NO_MEMORY );
|
|
}
|
|
|
|
Buff = pAllocatedBuff;
|
|
|
|
lRet = SCardListReaders(hCardContext, 0, Buff, &BuffLength);
|
|
if (SCARDPROBLEM(lRet,0x0000,0xFF))
|
|
{
|
|
ReleaseProvider(*phProv);
|
|
*phProv = 0;
|
|
RETURN( CRYPT_FAILED, lRet );
|
|
}
|
|
|
|
i = 0;
|
|
while (strlen(Buff) != 0 && i < MAX_SLOT)
|
|
{
|
|
ZeroMemory( Slot[i].szReaderName, sizeof(Slot[i].szReaderName) );
|
|
strncpy(Slot[i].szReaderName, Buff, (sizeof(Slot[i].szReaderName)/sizeof(TCHAR))-1);
|
|
Slot[i].szReaderName[(sizeof(Slot[i].szReaderName)/sizeof(TCHAR))-1]=0;
|
|
Buff = Buff + strlen(Buff) + 1;
|
|
i++;
|
|
}
|
|
|
|
if (strlen(Buff) != 0)
|
|
{
|
|
ReleaseProvider(*phProv);
|
|
*phProv = 0;
|
|
RETURN( CRYPT_FAILED, NTE_FAIL );
|
|
}
|
|
|
|
for (; i < MAX_SLOT; i++)
|
|
{
|
|
ZeroMemory( Slot[i].szReaderName, sizeof(Slot[i].szReaderName) );
|
|
}
|
|
|
|
s_bInit = true;
|
|
}
|
|
}
|
|
__finally
|
|
{
|
|
if (pAllocatedBuff)
|
|
{
|
|
GMEM_Free( pAllocatedBuff );
|
|
pAllocatedBuff = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// If the ReaderFriendlyName is NULL, scan the list of readers to find the one
|
|
// containing the container key set that is looked for.
|
|
|
|
// This fix is to work around the bug on the
|
|
// OPEN_CARD - Ressource Manager v1.0 (NT4, Win 95) -
|
|
|
|
if (!IsWin2000() && IsNullStr(szReaderFriendlyName))
|
|
{
|
|
SCARDHANDLE hCard;
|
|
int NbMatch = 0;
|
|
|
|
GpkLocalUnlock();
|
|
__try
|
|
{
|
|
DWORD i;
|
|
char szSlotReaderName[512];
|
|
|
|
for (i = 0; i < MAX_SLOT; i++)
|
|
{
|
|
strncpy(szSlotReaderName, Slot[i].szReaderName, sizeof(szSlotReaderName)-1);
|
|
szSlotReaderName[sizeof(szSlotReaderName)-1]=0;
|
|
|
|
if (IsNotNullStr (szSlotReaderName))
|
|
{
|
|
hCard = funcConnect (hCardContext, szSlotReaderName, mszCardList, 0);
|
|
if (hCard != 0)
|
|
{
|
|
//if (SCardBeginTransaction(hCard) == SCARD_S_SUCCESS)
|
|
//{
|
|
if (funcCheck (hCardContext, hCard, szContainerAsked))
|
|
{
|
|
strncpy (szReaderFriendlyName, szSlotReaderName, (sizeof(szReaderFriendlyName)/sizeof(TCHAR))-1);
|
|
szReaderFriendlyName[(sizeof(szReaderFriendlyName)/sizeof(TCHAR))-1]=0;
|
|
NbMatch++;
|
|
}
|
|
|
|
// SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
|
|
//}
|
|
funcDisconnect (hCardContext, hCard, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
__finally
|
|
{
|
|
GpkLocalLock();
|
|
}
|
|
|
|
// If there are more than one match, the user has to chose
|
|
|
|
if (NbMatch != 1)
|
|
{
|
|
ZeroMemory( szReaderFriendlyName, sizeof(szReaderFriendlyName) );
|
|
}
|
|
}
|
|
|
|
#endif // (_WIN32_WINNT < 0x0500)
|
|
|
|
|
|
if (IsNullStr(szReaderFriendlyName))
|
|
{
|
|
|
|
SCARDHANDLE hCard = 0;
|
|
dwStatus = OpenCard(szContainerAsked, BuffFlags, &hCard, szReaderName, sizeof(szReaderName)/sizeof(TCHAR));
|
|
|
|
if ((hCard == 0) || (dwStatus != SCARD_S_SUCCESS))
|
|
{
|
|
ReleaseProvider(*phProv);
|
|
*phProv = 0;
|
|
RETURN (CRYPT_FAILED, dwStatus);
|
|
}
|
|
|
|
ProvCont[*phProv].hCard = hCard;
|
|
|
|
ReaderState.szReader = szReaderName;
|
|
ReaderState.dwCurrentState = SCARD_STATE_UNAWARE;
|
|
SCardGetStatusChange(hCardContext, 1, &ReaderState, 1);
|
|
|
|
_tcscpy(szReaderName, ReaderState.szReader);
|
|
|
|
if (!find_reader (&(ProvCont[*phProv].Slot), szReaderName))
|
|
{
|
|
ReleaseProvider(*phProv);
|
|
*phProv = 0;
|
|
RETURN( CRYPT_FAILED, SCARD_E_READER_UNAVAILABLE );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DWORD dwSts = ConnectToCard( szReaderFriendlyName,
|
|
SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0,
|
|
&ProvCont[*phProv].hCard, &dwProto );
|
|
|
|
if (dwSts != SCARD_S_SUCCESS)
|
|
{
|
|
ReleaseProvider(*phProv);
|
|
*phProv = 0;
|
|
RETURN( CRYPT_FAILED, dwSts );
|
|
}
|
|
|
|
ReaderState.szReader = szReaderFriendlyName;
|
|
ReaderState.dwCurrentState = SCARD_STATE_UNAWARE;
|
|
SCardGetStatusChange(hCardContext, 1, &ReaderState, 1);
|
|
|
|
_tcscpy(szReaderName, ReaderState.szReader);
|
|
|
|
if (!find_reader (&(ProvCont[*phProv].Slot), szReaderFriendlyName))
|
|
{
|
|
ReleaseProvider(*phProv);
|
|
*phProv = 0;
|
|
RETURN( CRYPT_FAILED, SCARD_E_READER_UNAVAILABLE );
|
|
}
|
|
}
|
|
|
|
// Now we know which reader is used. start a thread to check that reader if necessary
|
|
|
|
lRet = BeginTransaction(ProvCont[*phProv].hCard);
|
|
if (lRet != SCARD_S_SUCCESS)
|
|
{
|
|
ReleaseProvider(*phProv);
|
|
*phProv = 0;
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
SlotNb = ProvCont[*phProv].Slot;
|
|
|
|
InitializeSlot( SlotNb );
|
|
|
|
// TT 30/07/99
|
|
lRet = DetectGPK8000( ProvCont[*phProv].hCard, &ProvCont[*phProv].bGPK8000 );
|
|
if (lRet != SCARD_S_SUCCESS)
|
|
{
|
|
SCardEndTransaction(ProvCont[*phProv].hCard, SCARD_LEAVE_CARD);
|
|
ReleaseProvider(*phProv);
|
|
*phProv = 0;
|
|
RETURN (CRYPT_FAILED, lRet );
|
|
}
|
|
|
|
ProvCont[*phProv].bLegacyKeyset = FALSE;
|
|
// TT: END
|
|
|
|
ProvCont[*phProv].hRSASign = 0;
|
|
ProvCont[*phProv].hRSAKEK = 0;
|
|
ProvCont[*phProv].keysetID = 0xFF; // TT: GPK8000 support
|
|
ProvCont[*phProv].bGPK_ISO_DF = FALSE;
|
|
ProvCont[*phProv].dataUnitSize = 0;
|
|
ProvCont[*phProv].bDisconnected = FALSE;
|
|
|
|
if (!Select_MF(*phProv))
|
|
{
|
|
// [FP] +
|
|
DBG_PRINT(TEXT("Try to reconnect"));
|
|
//DWORD dwProto;
|
|
lRet = SCardReconnect(ProvCont[*phProv].hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_RESET_CARD, &dwProto);
|
|
if (lRet != SCARD_S_SUCCESS) RETURN (CRYPT_FAILED, lRet);
|
|
|
|
DBG_PRINT(TEXT("Try Select_MF again"));
|
|
if (!Select_MF(*phProv))
|
|
{
|
|
DBG_PRINT(TEXT("Second Select_MF fails"));
|
|
// [FP] -
|
|
lRet = GetLastError();
|
|
|
|
SCardEndTransaction(ProvCont[*phProv].hCard, SCARD_LEAVE_CARD);
|
|
ReleaseProvider(*phProv);
|
|
*phProv = 0;
|
|
RETURN( CRYPT_FAILED, lRet );
|
|
}
|
|
}
|
|
|
|
// Read Serial number to store it
|
|
bSendBuffer[0] = 0x80; //CLA
|
|
bSendBuffer[1] = 0xC0; //INS
|
|
bSendBuffer[2] = 0x02; //P1
|
|
bSendBuffer[3] = 0xA0; //P2
|
|
bSendBuffer[4] = 0x08; //Lo
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit(ProvCont[*phProv].hCard,
|
|
SCARD_PCI_T0,
|
|
bSendBuffer,
|
|
cbSendLength,
|
|
NULL,
|
|
bRecvBuffer,
|
|
&cbRecvLength);
|
|
|
|
if (SCARDPROBLEM(lRet,0x9000, bSendBuffer[4]))
|
|
{
|
|
SCardEndTransaction(ProvCont[*phProv].hCard, SCARD_LEAVE_CARD);
|
|
ReleaseProvider(*phProv);
|
|
*phProv = 0;
|
|
RETURN (CRYPT_FAILED,
|
|
(SCARD_S_SUCCESS == lRet) ? NTE_BAD_KEYSET : lRet);
|
|
}
|
|
|
|
memcpy(Slot[SlotNb].bGpkSerNb, bRecvBuffer, bSendBuffer[4]);
|
|
|
|
if (!Select_Crypto_DF(*phProv))
|
|
{
|
|
lRet = GetLastError();
|
|
|
|
SCardEndTransaction(ProvCont[*phProv].hCard, SCARD_LEAVE_CARD);
|
|
ReleaseProvider(*phProv);
|
|
*phProv = 0;
|
|
RETURN( CRYPT_FAILED, lRet );
|
|
}
|
|
|
|
// Get the response from the Select DF to obtain the IADF
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xC0; //INS
|
|
bSendBuffer[2] = 0x00; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = bRecvBuffer[1]; //Lo
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[*phProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if (SCARDPROBLEM(lRet,0x9000,bSendBuffer[4]))
|
|
{
|
|
Select_MF(*phProv);
|
|
SCardEndTransaction(ProvCont[*phProv].hCard, SCARD_LEAVE_CARD);
|
|
ReleaseProvider(*phProv);
|
|
*phProv = 0;
|
|
|
|
RETURN( CRYPT_FAILED, (SCARD_S_SUCCESS == lRet) ? NTE_BAD_KEYSET : lRet );
|
|
}
|
|
|
|
ZeroMemory( ProvCont[*phProv].szContainer, sizeof(ProvCont[*phProv].szContainer));
|
|
|
|
if (bRecvBuffer[4] == 0x30)
|
|
Slot[SlotNb].InitFlag = FALSE;
|
|
else
|
|
{
|
|
Slot[SlotNb].InitFlag = TRUE;
|
|
|
|
if (ProvCont[*phProv].bGPK8000)
|
|
{
|
|
// Find the keyset's name
|
|
// This is done in AcquireUseKeySet()
|
|
ZeroMemory( ProvCont[*phProv].szContainer, sizeof(ProvCont[*phProv].szContainer) );
|
|
}
|
|
else
|
|
{
|
|
memcpy(ProvCont[*phProv].szContainer, &bRecvBuffer[5], cbRecvLength - 7);
|
|
}
|
|
}
|
|
|
|
// inserted by sven: Force re-reading of all objects to detect modifications by other processes
|
|
Slot[SlotNb].m_TSPublic=Slot[SlotNb].m_TSPrivate=0;
|
|
|
|
// read the description of the public key parameters
|
|
if (!Slot[SlotNb].ValidateTimestamps(*phProv))
|
|
return CRYPT_FAILED;
|
|
|
|
if (!Slot[SlotNb].Read_Public)
|
|
{
|
|
if (!read_gpk_objects(*phProv, FALSE))
|
|
{
|
|
lRet = GetLastError();
|
|
Select_MF(*phProv);
|
|
SCardEndTransaction(ProvCont[*phProv].hCard, SCARD_LEAVE_CARD);
|
|
ReleaseProvider(*phProv);
|
|
*phProv = 0;
|
|
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
Slot[SlotNb].Read_Public = TRUE;
|
|
Slot[SlotNb].Read_Priv = FALSE;
|
|
}
|
|
}
|
|
|
|
// TT 05/10/99
|
|
if (!ProvCont[*phProv].bGPK8000)
|
|
{
|
|
ProvCont[*phProv].bLegacyKeyset = DetectLegacy( &Slot[SlotNb] );
|
|
if (!ProvCont[*phProv].bLegacyKeyset)
|
|
{
|
|
ZeroMemory( ProvCont[*phProv].szContainer, sizeof(ProvCont[*phProv].szContainer) );
|
|
}
|
|
}
|
|
// TT - END -
|
|
|
|
if (dwFlags == CRYPT_DELETEKEYSET)
|
|
{
|
|
if (ProvCont[*phProv].bLegacyKeyset)
|
|
CryptResp = LegacyAcquireDeleteKeySet(phProv, ProvCont[*phProv].szContainer, szContainerAsked, BuffFlags);
|
|
else
|
|
CryptResp = AcquireDeleteKeySet(phProv, ProvCont[*phProv].szContainer, szContainerAsked, BuffFlags);
|
|
|
|
lRet = GetLastError();
|
|
|
|
Select_MF (*phProv);
|
|
SCardEndTransaction(ProvCont[*phProv].hCard, SCARD_LEAVE_CARD);
|
|
|
|
ReleaseProvider(*phProv);
|
|
*phProv = 0;
|
|
|
|
RETURN( CryptResp, lRet );
|
|
}
|
|
else if (dwFlags == CRYPT_NEWKEYSET)
|
|
{
|
|
if (ProvCont[*phProv].bLegacyKeyset)
|
|
CryptResp = LegacyAcquireNewKeySet(phProv, ProvCont[*phProv].szContainer, szContainerAsked, BuffFlags);
|
|
else
|
|
CryptResp = AcquireNewKeySet( phProv, ProvCont[*phProv].szContainer, szContainerAsked, BuffFlags );
|
|
|
|
lRet = GetLastError();
|
|
Select_MF (*phProv);
|
|
SCardEndTransaction(ProvCont[*phProv].hCard, SCARD_LEAVE_CARD);
|
|
|
|
if (!CryptResp)
|
|
{
|
|
ReleaseProvider (*phProv);
|
|
*phProv = 0;
|
|
}
|
|
|
|
RETURN( CryptResp, lRet );
|
|
}
|
|
else if (dwFlags == 0)
|
|
{
|
|
if (ProvCont[*phProv].bLegacyKeyset)
|
|
CryptResp = LegacyAcquireUseKeySet(phProv, ProvCont[*phProv].szContainer, szContainerAsked, BuffFlags);
|
|
else
|
|
CryptResp = AcquireUseKeySet(phProv, ProvCont[*phProv].szContainer, szContainerAsked, BuffFlags);
|
|
|
|
lRet = GetLastError();
|
|
|
|
//Select_MF (*phProv); // [FP] PIN not presented
|
|
SCardEndTransaction(ProvCont[*phProv].hCard, SCARD_LEAVE_CARD);
|
|
|
|
if (!CryptResp)
|
|
{
|
|
ReleaseProvider (*phProv);
|
|
*phProv = 0;
|
|
}
|
|
|
|
RETURN( CryptResp, lRet );
|
|
}
|
|
else
|
|
{
|
|
SCardEndTransaction(ProvCont[*phProv].hCard, SCARD_LEAVE_CARD);
|
|
|
|
ReleaseProvider(*phProv);
|
|
*phProv = 0;
|
|
RETURN( CRYPT_FAILED, NTE_BAD_FLAGS );
|
|
}
|
|
}
|
|
|
|
/*
|
|
- MyCPGetProvParam
|
|
-
|
|
* Purpose:
|
|
|
|
* Allows applications to get various aspects of the
|
|
* operations of a provider
|
|
*
|
|
* Parameters:
|
|
* IN hProv - Handle to a CSP
|
|
* IN dwParam - Parameter number
|
|
* OUT pbData - Pointer to data
|
|
* IN pdwDataLen - Length of parameter data
|
|
* IN dwFlags - Flags values
|
|
*
|
|
* Returns:
|
|
*/
|
|
BOOL WINAPI MyCPGetProvParam( IN HCRYPTPROV hProv,
|
|
IN DWORD dwParam,
|
|
IN BYTE* pbData,
|
|
IN DWORD* pdwDataLen,
|
|
IN DWORD dwFlags )
|
|
{
|
|
DWORD lRet;
|
|
BOOL CryptResp;
|
|
DWORD SlotNb;
|
|
ALG_ID aiAlgid;
|
|
BOOL algNotSupported;
|
|
TCHAR szCspName[MAX_STRING];
|
|
|
|
//BYTE* ptr = 0;
|
|
|
|
if (!Context_exist(hProv))
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_BAD_UID );
|
|
}
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
if (dwFlags & CRYPT_MACHINE_KEYSET)
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_BAD_FLAGS );
|
|
}
|
|
|
|
if ((dwFlags == CRYPT_FIRST)
|
|
&&(dwParam != PP_ENUMALGS)
|
|
&&(dwParam != PP_ENUMALGS_EX)
|
|
&&(dwParam != PP_ENUMCONTAINERS)
|
|
)
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_BAD_FLAGS );
|
|
}
|
|
|
|
switch (dwParam)
|
|
{
|
|
case PP_UNIQUE_CONTAINER:
|
|
case PP_CONTAINER:
|
|
// [mv - 15/05/98]
|
|
if ((ProvCont[hProv].Flags & CRYPT_VERIFYCONTEXT) &&
|
|
(ProvCont[hProv].isContNameNullBlank))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_PERM);
|
|
}
|
|
|
|
if (IsNotNull(pbData))
|
|
{
|
|
if (*pdwDataLen < strlen(ProvCont[hProv].szContainer)+1)
|
|
{
|
|
*pdwDataLen = strlen(ProvCont[hProv].szContainer)+1;
|
|
RETURN (CRYPT_FAILED, ERROR_MORE_DATA);
|
|
}
|
|
strcpy( (char*)pbData, ProvCont[hProv].szContainer);
|
|
}
|
|
|
|
*pdwDataLen = strlen(ProvCont[hProv].szContainer)+1;
|
|
break;
|
|
|
|
case PP_ENUMALGS:
|
|
case PP_ENUMALGS_EX:
|
|
CryptResp = CryptGetProvParam(hProvBase,
|
|
dwParam,
|
|
pbData,
|
|
pdwDataLen,
|
|
dwFlags
|
|
);
|
|
if (!CryptResp)
|
|
{
|
|
lRet = GetLastError();
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
if (NULL != pbData)
|
|
{
|
|
// Extract algorithm information from 'pbData' buffer.
|
|
BYTE *ptr = pbData;
|
|
aiAlgid = *(ALG_ID UNALIGNED *)ptr;
|
|
|
|
BOOL b512exist = FALSE,
|
|
b1024exist = FALSE;
|
|
|
|
for ( unsigned i = 0 ; i < Slot[SlotNb].NbKeyFile; ++i )
|
|
{
|
|
if (Slot[SlotNb].GpkPubKeys[i].KeySize == 512/8) b512exist = TRUE;
|
|
else if (Slot[SlotNb].GpkPubKeys[i].KeySize == 1024/8) b1024exist = TRUE;
|
|
}
|
|
|
|
// Can happen if card is removed
|
|
if (!b512exist && !b1024exist)
|
|
Slot[SlotNb].NbKeyFile = 0;
|
|
|
|
if (aiAlgid == CALG_RSA_KEYX)
|
|
{
|
|
if (PP_ENUMALGS_EX == dwParam)
|
|
{
|
|
PROV_ENUMALGS_EX *penAlg = (PROV_ENUMALGS_EX *)pbData;
|
|
if (Slot[SlotNb].NbKeyFile==0)
|
|
{
|
|
penAlg->dwDefaultLen = RSA_KEK_Size * 8;
|
|
penAlg->dwMinLen = 512;
|
|
penAlg->dwMaxLen = RSA_KEK_Size * 8;
|
|
}
|
|
else
|
|
{
|
|
penAlg->dwDefaultLen = RSA_KEK_Size * 8;
|
|
penAlg->dwMinLen = (b512exist) ? 512 : 1024;
|
|
penAlg->dwMaxLen = (b1024exist) ? 1024 : 512;
|
|
|
|
if (penAlg->dwMaxLen > (DWORD)RSA_KEK_Size * 8)
|
|
penAlg->dwMaxLen = (DWORD)RSA_KEK_Size * 8;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PROV_ENUMALGS *penAlg = (PROV_ENUMALGS *)pbData;
|
|
if (Slot[SlotNb].NbKeyFile==0)
|
|
penAlg->dwBitLen = RSA_KEK_Size * 8;
|
|
else
|
|
{
|
|
penAlg->dwBitLen = (b1024exist) ? 1024 : 512;
|
|
if (penAlg->dwBitLen > (DWORD)RSA_KEK_Size * 8)
|
|
penAlg->dwBitLen = (DWORD)RSA_KEK_Size * 8;
|
|
}
|
|
}
|
|
}
|
|
else if (aiAlgid == CALG_RSA_SIGN)
|
|
{
|
|
if (PP_ENUMALGS_EX == dwParam)
|
|
{
|
|
PROV_ENUMALGS_EX *penAlg = (PROV_ENUMALGS_EX *)pbData;
|
|
if (Slot[SlotNb].NbKeyFile==0)
|
|
{
|
|
penAlg->dwDefaultLen = 1024;
|
|
penAlg->dwMinLen = 512;
|
|
penAlg->dwMaxLen = 1024;
|
|
}
|
|
else
|
|
{
|
|
penAlg->dwDefaultLen = (b1024exist) ? 1024 : 512;
|
|
penAlg->dwMinLen = (b512exist) ? 512 : 1024;
|
|
penAlg->dwMaxLen = (b1024exist) ? 1024 : 512;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PROV_ENUMALGS *penAlg = (PROV_ENUMALGS *)pbData;
|
|
if (Slot[SlotNb].NbKeyFile==0)
|
|
penAlg->dwBitLen = 1024;
|
|
else
|
|
penAlg->dwBitLen = (b1024exist) ? 1024 : 512;
|
|
}
|
|
}
|
|
else if ( ProvCont[hProv].Flags & CRYPT_VERIFYCONTEXT &&
|
|
ProvCont[hProv].isContNameNullBlank )
|
|
{
|
|
// No access to the card has been done in this case
|
|
}
|
|
else if ((dwFlags != CRYPT_FIRST ) && (Slot[SlotNb].GpkMaxSessionKey == 0))
|
|
{
|
|
// card was removed, nothing to do
|
|
}
|
|
else if (GET_ALG_CLASS(aiAlgid) == ALG_CLASS_DATA_ENCRYPT)
|
|
{
|
|
// The max session key in the card is only for encryption
|
|
// There is a card in the Reader,
|
|
// read the max session key, if not already done
|
|
|
|
if (Slot[SlotNb].GpkMaxSessionKey == 0)
|
|
{
|
|
CryptResp = Read_MaxSessionKey_EF(hProv,
|
|
&(Slot[SlotNb].GpkMaxSessionKey));
|
|
// if the DF of EF is not here, maxSessionKey==0
|
|
}
|
|
|
|
// skip the algo if not supported by the card
|
|
do
|
|
{
|
|
algNotSupported = FALSE;
|
|
|
|
if (dwParam == PP_ENUMALGS)
|
|
{
|
|
PROV_ENUMALGS *penAlg = (PROV_ENUMALGS *)pbData;
|
|
|
|
// TT Hack: "Unknown cryptographic algorithm" at winlogon problem.
|
|
if (penAlg->aiAlgid == CALG_RC2 && Slot[SlotNb].GpkMaxSessionKey < 128)
|
|
{
|
|
penAlg->dwBitLen = 40;
|
|
}
|
|
|
|
// DES needs 64 bits of unwrap capability
|
|
if (penAlg->aiAlgid == CALG_DES && Slot[SlotNb].GpkMaxSessionKey < 64)
|
|
algNotSupported = TRUE;
|
|
else
|
|
// Limit encryption algorithms to unwrap capabilities
|
|
if (GET_ALG_CLASS(penAlg->aiAlgid)==ALG_CLASS_DATA_ENCRYPT)
|
|
{
|
|
if (penAlg->dwBitLen > Slot[SlotNb].GpkMaxSessionKey)
|
|
algNotSupported = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PROV_ENUMALGS_EX *penAlg = (PROV_ENUMALGS_EX *)pbData;
|
|
|
|
// TT Hack: "Unknown cryptographic algorithm" at winlogon problem.
|
|
if (penAlg->aiAlgid == CALG_RC2 && Slot[SlotNb].GpkMaxSessionKey < 128)
|
|
{
|
|
penAlg->dwDefaultLen = 40;
|
|
penAlg->dwMinLen = 40;
|
|
penAlg->dwMaxLen = 40;
|
|
}
|
|
|
|
// DES needs 64 bits of unwrap capability
|
|
if (penAlg->aiAlgid == CALG_DES && Slot[SlotNb].GpkMaxSessionKey < 64)
|
|
algNotSupported = TRUE;
|
|
else
|
|
// Limit encryption algorithms to unwrap capabilities
|
|
if (GET_ALG_CLASS(penAlg->aiAlgid)==ALG_CLASS_DATA_ENCRYPT)
|
|
{
|
|
if (penAlg->dwMinLen > Slot[SlotNb].GpkMaxSessionKey)
|
|
algNotSupported = TRUE;
|
|
else
|
|
{
|
|
if (penAlg->dwMaxLen > Slot[SlotNb].GpkMaxSessionKey)
|
|
penAlg->dwMaxLen = Slot[SlotNb].GpkMaxSessionKey;
|
|
|
|
if (penAlg->dwDefaultLen > penAlg->dwMaxLen)
|
|
penAlg->dwDefaultLen = penAlg->dwMaxLen;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (algNotSupported)
|
|
{
|
|
// Algo not supported, read the next one
|
|
dwFlags = 0;
|
|
CryptResp = CryptGetProvParam( hProvBase, dwParam, pbData, pdwDataLen, dwFlags );
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
}
|
|
|
|
} while (algNotSupported);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case PP_ENUMCONTAINERS:
|
|
{
|
|
if ((ProvCont[hProv].Flags & CRYPT_VERIFYCONTEXT) &&
|
|
(ProvCont[hProv].isContNameNullBlank))
|
|
{
|
|
static CHAR* lpszCurrentContainerInList = 0; // multi sz strings of containters
|
|
static CHAR mszContainerList[(MAX_SLOT * 128) + 1];
|
|
DWORD dwContainerListLen = 0;
|
|
static DWORD dwContainerMaxLen = 0;
|
|
|
|
if (dwFlags == CRYPT_FIRST)
|
|
{
|
|
// List readers
|
|
SCARDCONTEXT hCardEnumContext;
|
|
lRet = SCardEstablishContext(SCARD_SCOPE_SYSTEM, 0, 0, &hCardEnumContext);
|
|
if (lRet != SCARD_S_SUCCESS)
|
|
{
|
|
if (lRet == SCARD_E_NO_SERVICE)
|
|
lRet = ERROR_NO_MORE_ITEMS;
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
PTCHAR mszReaderList = 0;
|
|
DWORD dwReaderListLen = 0;
|
|
lRet = SCardListReaders(hCardEnumContext, 0, mszReaderList, &dwReaderListLen);
|
|
if (lRet != SCARD_S_SUCCESS)
|
|
{
|
|
if (lRet == SCARD_E_NO_READERS_AVAILABLE)
|
|
lRet = ERROR_NO_MORE_ITEMS;
|
|
SCardReleaseContext(hCardEnumContext);
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
mszReaderList = (PTCHAR)GMEM_Alloc(dwReaderListLen * sizeof(TCHAR));
|
|
if (IsNull(mszReaderList))
|
|
{
|
|
SCardReleaseContext(hCardEnumContext);
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
lRet = SCardListReaders(hCardEnumContext, 0, mszReaderList, &dwReaderListLen);
|
|
if (lRet != SCARD_S_SUCCESS)
|
|
{
|
|
GMEM_Free(mszReaderList);
|
|
SCardReleaseContext(hCardEnumContext);
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
SCardReleaseContext(hCardEnumContext);
|
|
|
|
// For each reader, find the container if any
|
|
PTCHAR szReader = 0;
|
|
PTCHAR szReader2 = 0;
|
|
CHAR szContainer[128];
|
|
DWORD dwContainerLen = 128;
|
|
HCRYPTPROV hReaderProv;
|
|
|
|
for (szReader = mszReaderList; *szReader != 0; szReader += (_tcsclen(szReader) + 1))
|
|
{
|
|
szReader2 = (PTCHAR)GMEM_Alloc((_tcslen(szReader) + 5)*sizeof(TCHAR));
|
|
if (IsNull(szReader2))
|
|
{
|
|
GMEM_Free(mszReaderList);
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
_tcscpy(szReader2, TEXT("\\\\.\\"));
|
|
_tcscat(szReader2, szReader);
|
|
|
|
CHAR szReaderChar[128];
|
|
|
|
#ifndef UNICODE
|
|
strncpy(szReaderChar, szReader2, sizeof(szReaderChar)-1);
|
|
szReaderChar[sizeof(szReaderChar)-1]=0;
|
|
#else
|
|
WideCharToMultiByte(CP_ACP, 0, szReader2, -1, szReaderChar, 128, 0, 0);
|
|
#endif
|
|
|
|
GMEM_Free(szReader2);
|
|
|
|
if (!MyCPAcquireContext(&hReaderProv, szReaderChar, CRYPT_VERIFYCONTEXT | CRYPT_SILENT, 0))
|
|
{
|
|
DWORD dwGLE = GetLastError();
|
|
|
|
if (dwGLE == NTE_KEYSET_NOT_DEF ||
|
|
dwGLE == SCARD_W_REMOVED_CARD ||
|
|
dwGLE == SCARD_E_DIR_NOT_FOUND || // likely to happen with a non Gemplus card
|
|
dwGLE == SCARD_E_PROTO_MISMATCH) // likely to happen with T=1 card
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
GMEM_Free(mszReaderList);
|
|
RETURN (CRYPT_FAILED, NTE_FAIL);
|
|
}
|
|
}
|
|
|
|
dwContainerLen = 128;
|
|
if (!MyCPGetProvParam(hReaderProv, PP_CONTAINER, (BYTE*)szContainer, &dwContainerLen, 0))
|
|
{
|
|
GMEM_Free(mszReaderList);
|
|
RETURN (CRYPT_FAILED, NTE_FAIL);
|
|
}
|
|
|
|
MyCPReleaseContext(hReaderProv, 0);
|
|
|
|
strcpy(&mszContainerList[dwContainerListLen], szContainer);
|
|
dwContainerListLen += dwContainerLen;
|
|
dwContainerMaxLen = max(dwContainerMaxLen, dwContainerLen);
|
|
}
|
|
|
|
GMEM_Free(mszReaderList);
|
|
|
|
lpszCurrentContainerInList = mszContainerList;
|
|
}
|
|
|
|
// Return containers one by one
|
|
if (lpszCurrentContainerInList == 0 || *lpszCurrentContainerInList == 0)
|
|
RETURN (CRYPT_FAILED, ERROR_NO_MORE_ITEMS);
|
|
|
|
if (IsNotNull(pbData))
|
|
{
|
|
if (*pdwDataLen < dwContainerMaxLen)
|
|
{
|
|
*pdwDataLen = dwContainerMaxLen;
|
|
RETURN (CRYPT_FAILED, ERROR_MORE_DATA);
|
|
}
|
|
|
|
strcpy((CHAR*)pbData, lpszCurrentContainerInList);
|
|
*pdwDataLen = strlen(lpszCurrentContainerInList) + 1;
|
|
lpszCurrentContainerInList += strlen(lpszCurrentContainerInList) + 1;
|
|
}
|
|
else
|
|
{
|
|
*pdwDataLen = dwContainerMaxLen;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (dwFlags == CRYPT_FIRST)
|
|
{
|
|
if (!MyCPGetProvParam(hProv, PP_CONTAINER, pbData, pdwDataLen, 0))
|
|
{
|
|
RETURN (CRYPT_FAILED, GetLastError());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RETURN (CRYPT_FAILED, ERROR_NO_MORE_ITEMS);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case PP_IMPTYPE:
|
|
if (IsNotNull(pbData))
|
|
{
|
|
DWORD dwType = CRYPT_IMPL_MIXED | CRYPT_IMPL_REMOVABLE;
|
|
if (*pdwDataLen < sizeof(DWORD))
|
|
{
|
|
*pdwDataLen = sizeof(DWORD);
|
|
RETURN (CRYPT_FAILED, ERROR_MORE_DATA);
|
|
}
|
|
|
|
memcpy(pbData, &dwType, sizeof(dwType));
|
|
}
|
|
|
|
*pdwDataLen = sizeof(DWORD);
|
|
break;
|
|
|
|
case PP_KEYX_KEYSIZE_INC:
|
|
case PP_SIG_KEYSIZE_INC:
|
|
|
|
if (IsNotNull(pbData))
|
|
{
|
|
BOOL b512exist = FALSE,
|
|
b1024exist = FALSE;
|
|
|
|
for ( unsigned i = 0 ; i < Slot[SlotNb].NbKeyFile; ++i )
|
|
{
|
|
if (Slot[SlotNb].GpkPubKeys[i].KeySize == 512) b512exist = TRUE;
|
|
else if (Slot[SlotNb].GpkPubKeys[i].KeySize == 1024) b1024exist = TRUE;
|
|
}
|
|
|
|
// Can happen if card is removed
|
|
if (!b512exist && !b1024exist)
|
|
Slot[SlotNb].NbKeyFile = 0;
|
|
|
|
if (dwParam == PP_KEYX_KEYSIZE_INC && b1024exist && RSA_KEK_Size * 8 < 1024)
|
|
b1024exist = FALSE;
|
|
|
|
DWORD dwSize = 0;
|
|
|
|
if (b512exist && b1024exist)
|
|
dwSize = 512;
|
|
|
|
if (*pdwDataLen < sizeof(DWORD))
|
|
{
|
|
*pdwDataLen = sizeof(DWORD);
|
|
RETURN (CRYPT_FAILED, ERROR_MORE_DATA);
|
|
}
|
|
|
|
memcpy(pbData, &dwSize, sizeof(dwSize));
|
|
}
|
|
|
|
*pdwDataLen = sizeof(DWORD);
|
|
break;
|
|
|
|
case PP_NAME:
|
|
LoadString(g_hInstMod, IDS_GPKCSP_NAME, szCspName, sizeof(szCspName)/sizeof(TCHAR));
|
|
|
|
if (IsNotNull(pbData))
|
|
{
|
|
if (*pdwDataLen < (_tcslen(szCspName)+1))
|
|
{
|
|
*pdwDataLen = (_tcslen(szCspName)+1);
|
|
RETURN (CRYPT_FAILED, ERROR_MORE_DATA);
|
|
}
|
|
|
|
#ifndef UNICODE
|
|
strcpy((CHAR*)pbData, szCspName);
|
|
#else
|
|
char szCspName1[MAX_STRING];
|
|
WideCharToMultiByte(CP_ACP, 0, szCspName, MAX_STRING, szCspName1, MAX_STRING, 0, 0);
|
|
strcpy((CHAR*)pbData, szCspName1);
|
|
#endif
|
|
}
|
|
|
|
*pdwDataLen = (_tcslen(szCspName)+1);
|
|
break;
|
|
|
|
case PP_VERSION:
|
|
if (IsNotNull(pbData))
|
|
{
|
|
if (*pdwDataLen < sizeof(DWORD))
|
|
{
|
|
*pdwDataLen = sizeof(DWORD);
|
|
RETURN (CRYPT_FAILED, ERROR_MORE_DATA);
|
|
}
|
|
|
|
pbData[0] = 20;
|
|
pbData[1] = 2;
|
|
pbData[2] = 0;
|
|
pbData[3] = 0;
|
|
}
|
|
|
|
*pdwDataLen = sizeof(DWORD);
|
|
break;
|
|
|
|
case PP_PROVTYPE:
|
|
if (IsNotNull(pbData))
|
|
{
|
|
if (*pdwDataLen < sizeof(DWORD))
|
|
{
|
|
*pdwDataLen = sizeof(DWORD);
|
|
RETURN (CRYPT_FAILED, ERROR_MORE_DATA);
|
|
}
|
|
*(LPDWORD)pbData = PROV_RSA_FULL;
|
|
}
|
|
|
|
*pdwDataLen = sizeof(DWORD);
|
|
break;
|
|
|
|
case PP_KEYSPEC:
|
|
if (IsNotNull(pbData))
|
|
{
|
|
DWORD dwSpec = AT_KEYEXCHANGE | AT_SIGNATURE;
|
|
if (*pdwDataLen < sizeof(DWORD))
|
|
{
|
|
*pdwDataLen = sizeof(DWORD);
|
|
RETURN (CRYPT_FAILED, ERROR_MORE_DATA);
|
|
}
|
|
|
|
memcpy(pbData, &dwSpec, sizeof(dwSpec));
|
|
}
|
|
|
|
*pdwDataLen = sizeof(DWORD);
|
|
break;
|
|
|
|
// + [FP] Proprietary functions used to load a RSA private key into the GPK card
|
|
case GPP_SERIAL_NUMBER:
|
|
if (dwFlags != 0)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_FLAGS);
|
|
}
|
|
|
|
if ((ProvCont[hProv].Flags & CRYPT_VERIFYCONTEXT) &&
|
|
(ProvCont[hProv].isContNameNullBlank))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_PERM);
|
|
}
|
|
|
|
if (IsNotNull(pbData))
|
|
{
|
|
if (*pdwDataLen < 8)
|
|
{
|
|
*pdwDataLen = 8;
|
|
RETURN (CRYPT_FAILED, ERROR_MORE_DATA);
|
|
}
|
|
|
|
CryptResp = Select_MF(hProv);
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
|
|
bSendBuffer[0] = 0x80; //CLA
|
|
bSendBuffer[1] = 0xC0; //INS
|
|
bSendBuffer[2] = 0x02; //P1
|
|
bSendBuffer[3] = 0xA0; //P2
|
|
bSendBuffer[4] = 0x08; //Lo
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if (SCARDPROBLEM(lRet, 0x9000, bSendBuffer[4]))
|
|
{
|
|
RETURN (CRYPT_FAILED, SCARD_E_UNEXPECTED);
|
|
}
|
|
|
|
memcpy(pbData, bRecvBuffer, bSendBuffer[4]);
|
|
}
|
|
|
|
*pdwDataLen = 8;
|
|
break;
|
|
|
|
case GPP_SESSION_RANDOM:
|
|
if (dwFlags != 0)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_FLAGS);
|
|
}
|
|
|
|
if ((ProvCont[hProv].Flags & CRYPT_VERIFYCONTEXT) &&
|
|
(ProvCont[hProv].isContNameNullBlank))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_PERM);
|
|
}
|
|
|
|
if (IsNotNull(pbData))
|
|
{
|
|
if (*pdwDataLen < 8)
|
|
{
|
|
*pdwDataLen = 8;
|
|
RETURN (CRYPT_FAILED, ERROR_MORE_DATA);
|
|
}
|
|
|
|
if (Slot[SlotNb].NbKeyFile == 0) // [FP] here instead of MyCPImportKey because
|
|
{ // it does a Select_Crypto_DF and we have to do
|
|
Slot[SlotNb].NbKeyFile = Read_NbKeyFile(hProv); // it before the select file key
|
|
}
|
|
|
|
/* Select File Key */
|
|
bSendBuffer[0] = 0x80; //CLA
|
|
bSendBuffer[1] = 0x28; //INS
|
|
bSendBuffer[2] = 0x00; //P1
|
|
bSendBuffer[3] = (BYTE)(0x3F01 /*& 0x1F*/); //P2
|
|
bSendBuffer[4] = 0x08; //Lc
|
|
memcpy(&bSendBuffer[5], pbData, 0x08);
|
|
cbSendLength = 13;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if(SCARDPROBLEM(lRet, 0x61FF, 0x00))
|
|
{
|
|
RETURN(CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
/* Get Response */
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xC0; //INS
|
|
bSendBuffer[2] = 0x00; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = bRecvBuffer[1]; //Lo
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if(SCARDPROBLEM(lRet, 0x9000, bSendBuffer[4]))
|
|
{
|
|
RETURN(CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
memcpy(pbData, &bRecvBuffer[4], 8);
|
|
ProvCont[hProv].bCardTransactionOpened = TRUE;
|
|
}
|
|
|
|
*pdwDataLen = 8;
|
|
break;
|
|
|
|
case GPP_IMPORT_MECHANISM:
|
|
if (IsNotNull(pbData))
|
|
{
|
|
DWORD dwMechanism = GCRYPT_IMPORT_SECURE;
|
|
|
|
if (*pdwDataLen < sizeof(DWORD))
|
|
{
|
|
*pdwDataLen = sizeof(DWORD);
|
|
RETURN (CRYPT_FAILED, ERROR_MORE_DATA);
|
|
}
|
|
|
|
memcpy(pbData, &dwMechanism, sizeof(dwMechanism));
|
|
}
|
|
|
|
*pdwDataLen = sizeof(DWORD);
|
|
break;
|
|
// - [FP]
|
|
|
|
default:
|
|
RETURN (CRYPT_FAILED, NTE_BAD_TYPE);
|
|
}
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
|
|
/*
|
|
- MyCPReleaseContext
|
|
-
|
|
* Purpose:
|
|
* The CPReleaseContext function is used to release a
|
|
* context created by CryptAcquireContext.
|
|
*
|
|
* Parameters:
|
|
* IN phProv - Handle to a CSP
|
|
* IN dwFlags - Flags values
|
|
*
|
|
* Returns:
|
|
*/
|
|
BOOL WINAPI MyCPReleaseContext( HCRYPTPROV hProv, DWORD dwFlags )
|
|
{
|
|
DWORD SlotNb;
|
|
|
|
if (!Context_exist(hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_UID);
|
|
}
|
|
|
|
|
|
if ( ProvCont[hProv].Flags & CRYPT_VERIFYCONTEXT &&
|
|
ProvCont[hProv].isContNameNullBlank)
|
|
{
|
|
|
|
}
|
|
else
|
|
{
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
if (Slot[SlotNb].ContextCount > 0)
|
|
Slot[SlotNb].ContextCount--;
|
|
|
|
if (countCardContextRef > 0)
|
|
countCardContextRef--;
|
|
}
|
|
|
|
|
|
if (ProvCont[hProv].Flags & CRYPT_VERIFYCONTEXT &&
|
|
ProvCont[hProv].isContNameNullBlank)
|
|
{
|
|
// No access to the card has been done in this case
|
|
}
|
|
else
|
|
{
|
|
// Select_MF(hProv); [FP] PIN not presented
|
|
// SCardEndTransaction(ProvCont[hProv].hCard, SCARD_LEAVE_CARD); [FP] coherence not checked
|
|
}
|
|
|
|
ReleaseProvider(hProv);
|
|
|
|
/* PYR 11/08/00: Do not unload
|
|
if (IsNotNull(g_hInstRes) && Slot[SlotNb].ContextCount == 0)
|
|
{
|
|
bFirstGUILoad = TRUE;
|
|
FreeLibrary(g_hInstRes);
|
|
g_hInstRes = 0;
|
|
}
|
|
*/
|
|
//If dwFlags is not set to zero, this function returns FALSE but the CSP is released
|
|
//PYR 08/08/00. Note that CryptoAPI will not call again CPReleaseContext with the same handle.
|
|
if (dwFlags != 0)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_FLAGS);
|
|
}
|
|
else
|
|
{
|
|
RETURN( CRYPT_SUCCEED, 0 );
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
- MyCPSetProvParam
|
|
-
|
|
* Purpose:
|
|
* Allows applications to customize various aspects of the
|
|
* operations of a provider
|
|
*
|
|
* Parameters:
|
|
* IN hProv - Handle to a CSP
|
|
* IN dwParam - Parameter number
|
|
* IN pbData - Pointer to data
|
|
* IN dwFlags - Flags values
|
|
*
|
|
* Returns:
|
|
*/
|
|
BOOL WINAPI MyCPSetProvParam(IN HCRYPTPROV hProv,
|
|
IN DWORD dwParam,
|
|
IN CONST BYTE *pbData,
|
|
IN DWORD dwFlags
|
|
)
|
|
{
|
|
DWORD SlotNb;
|
|
// + [FP] for GPP_CHANGE_PIN
|
|
const char* Buff;
|
|
char szOldPin[PIN_LEN + 1];
|
|
char szNewPin[PIN_LEN + 1];
|
|
// - [FP]
|
|
// + NK 06.02.2001
|
|
PINCACHE_PINS Pins;
|
|
CallbackData sCallbackData;
|
|
DWORD dwStatus;
|
|
// -
|
|
|
|
if (!Context_exist(hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_UID);
|
|
}
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
switch (dwParam)
|
|
{
|
|
case PP_KEYEXCHANGE_PIN:
|
|
case PP_SIGNATURE_PIN:
|
|
{
|
|
// Slot[SlotNb].ClearPin();
|
|
// Slot[SlotNb].SetPin( (char*)pbData );
|
|
PopulatePins( &Pins, (BYTE *)pbData, strlen( (char*)pbData ), NULL, 0 );
|
|
|
|
sCallbackData.hProv = hProv;
|
|
sCallbackData.IsCoherent = FALSE;
|
|
|
|
// SlotNb may not be the same before and after Add_MSPinCache because of the call
|
|
// to Coherent in the callback of the pin cache function. To be sure that we save
|
|
// the handle to the good slot, we store it after the call
|
|
PINCACHE_HANDLE hPinCacheHandle = Slot[SlotNb].hPinCacheHandle;
|
|
if ( (dwStatus = Add_MSPinCache( &hPinCacheHandle,
|
|
&Pins,
|
|
Callback_VerifyChangePin,
|
|
(void*)&sCallbackData )) != ERROR_SUCCESS )
|
|
{
|
|
RETURN (CRYPT_FAILED, dwStatus);
|
|
}
|
|
Slot[ProvCont[hProv].Slot].hPinCacheHandle = hPinCacheHandle;
|
|
break;
|
|
}
|
|
case PP_KEYSET_SEC_DESCR:
|
|
break; // Assume success.
|
|
|
|
case GPP_CHANGE_PIN:
|
|
if (dwFlags != 0)
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_BAD_FLAGS );
|
|
}
|
|
|
|
if ( ProvCont[hProv].Flags & CRYPT_VERIFYCONTEXT &&
|
|
ProvCont[hProv].isContNameNullBlank )
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_PERM );
|
|
}
|
|
|
|
// parse input buffer
|
|
Buff = (char*)pbData;
|
|
memset(szOldPin, 0x00, PIN_LEN + 1);
|
|
strncpy(szOldPin, Buff, PIN_LEN);
|
|
|
|
Buff = Buff + strlen(Buff) + 1;
|
|
memset(szNewPin, 0x00, PIN_LEN + 1);
|
|
strncpy(szNewPin, Buff, PIN_LEN);
|
|
|
|
PopulatePins( &Pins, (BYTE *)szOldPin, strlen(szOldPin), (BYTE *)szNewPin, strlen(szNewPin) );
|
|
|
|
sCallbackData.hProv = hProv;
|
|
sCallbackData.IsCoherent = TRUE;
|
|
|
|
dwStatus = Add_MSPinCache( &(Slot[SlotNb].hPinCacheHandle),
|
|
&Pins,
|
|
Callback_VerifyChangePin,
|
|
(void*)&sCallbackData );
|
|
memset(szOldPin, 0x00, PIN_LEN + 1);
|
|
memset(szNewPin, 0x00, PIN_LEN + 1);
|
|
if(szOldPin[0] || szNewPin[0]) { MessageBeep(0); } // to prevent compiler from optimization
|
|
if(dwStatus!=ERROR_SUCCESS)
|
|
{
|
|
RETURN (CRYPT_FAILED, dwStatus);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
RETURN( CRYPT_FAILED, E_NOTIMPL );
|
|
}
|
|
|
|
RETURN( CRYPT_SUCCEED, 0 );
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
Key Generation and Exchange Functions
|
|
*******************************************************************************/
|
|
|
|
/*
|
|
- MyCPDeriveKey
|
|
-
|
|
* Purpose:
|
|
* Derive cryptographic keys from base data
|
|
*
|
|
*
|
|
* Parameters:
|
|
* IN hProv - Handle to a CSP
|
|
* IN Algid - Algorithm identifier
|
|
* IN hHash - Handle to hash
|
|
* IN dwFlags - Flags values
|
|
* OUT phKey - Handle to a generated key
|
|
*
|
|
* Returns:
|
|
*/
|
|
BOOL WINAPI MyCPDeriveKey(IN HCRYPTPROV hProv,
|
|
IN ALG_ID Algid,
|
|
IN HCRYPTHASH hHash,
|
|
IN DWORD dwFlags,
|
|
OUT HCRYPTKEY *phKey
|
|
)
|
|
{
|
|
BOOL CryptResp;
|
|
HCRYPTKEY hKey;
|
|
|
|
*phKey = 0;
|
|
|
|
if (!Context_exist(hProv))
|
|
RETURN( CRYPT_FAILED, NTE_BAD_UID );
|
|
|
|
if (!hash_exist(hHash, hProv))
|
|
RETURN( CRYPT_FAILED, NTE_BAD_HASH );
|
|
|
|
hKey = find_tmp_free();
|
|
if (hKey == 0)
|
|
RETURN( CRYPT_FAILED, NTE_NO_MEMORY );
|
|
|
|
// In fact, the flags are processed implicitly in the RSA Base
|
|
CryptResp = CryptDeriveKey( hProvBase, Algid, hHashGpk[hHash].hHashBase,
|
|
dwFlags, &TmpObject[hKey].hKeyBase );
|
|
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
|
|
TmpObject[hKey].hProv = hProv;
|
|
*phKey = hKey + MAX_GPK_OBJ;
|
|
|
|
RETURN( CRYPT_SUCCEED, 0 );
|
|
}
|
|
|
|
|
|
/*
|
|
- MyCPDestroyKey
|
|
-
|
|
* Purpose:
|
|
* Destroys the cryptographic key that is being referenced
|
|
* with the hKey parameter
|
|
*
|
|
*
|
|
* Parameters:
|
|
* IN hProv - Handle to a CSP
|
|
* IN hKey - Handle to a key
|
|
*
|
|
* Returns:
|
|
*/
|
|
BOOL WINAPI MyCPDestroyKey(IN HCRYPTPROV hProv,
|
|
IN HCRYPTKEY hKey
|
|
)
|
|
{
|
|
BOOL CryptResp;
|
|
|
|
if (!Context_exist(hProv))
|
|
RETURN( CRYPT_FAILED, NTE_BAD_UID );
|
|
|
|
if (hKey == 0)
|
|
RETURN( CRYPT_FAILED, NTE_BAD_KEY );
|
|
|
|
if (ProvCont[hProv].Flags & CRYPT_VERIFYCONTEXT)
|
|
RETURN( CRYPT_FAILED, NTE_PERM );
|
|
|
|
if (hKey <= MAX_GPK_OBJ)
|
|
RETURN( CRYPT_SUCCEED, 0 );
|
|
|
|
if (!key_exist(hKey-MAX_GPK_OBJ, hProv))
|
|
RETURN( CRYPT_FAILED, NTE_BAD_KEY );
|
|
|
|
if (TmpObject[hKey-MAX_GPK_OBJ].hKeyBase != 0)
|
|
{
|
|
CryptResp = CryptDestroyKey(TmpObject[hKey-MAX_GPK_OBJ].hKeyBase);
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
}
|
|
|
|
TmpObject[hKey-MAX_GPK_OBJ].hKeyBase = 0;
|
|
TmpObject[hKey-MAX_GPK_OBJ].hProv = 0;
|
|
|
|
RETURN( CRYPT_SUCCEED, 0 );
|
|
}
|
|
|
|
|
|
/*
|
|
- MyCPExportKey
|
|
-
|
|
* Purpose:
|
|
* Export cryptographic keys out of a CSP in a secure manner
|
|
*
|
|
*
|
|
* Parameters:
|
|
* IN hProv - Handle to the CSP user
|
|
* IN hKey - Handle to the key to export
|
|
* IN hPubKey - Handle to the exchange public key value of
|
|
* the destination user
|
|
* IN dwBlobType - Type of key blob to be exported
|
|
* IN dwFlags - Flags values
|
|
* OUT pbData - Key blob data
|
|
* OUT pdwDataLen - Length of key blob in bytes
|
|
*
|
|
* Returns:
|
|
*/
|
|
BOOL WINAPI MyCPExportKey(IN HCRYPTPROV hProv,
|
|
IN HCRYPTKEY hKey,
|
|
IN HCRYPTKEY hPubKey,
|
|
IN DWORD dwBlobType,
|
|
IN DWORD dwFlags,
|
|
OUT BYTE *pbData,
|
|
OUT DWORD *pdwDataLen
|
|
)
|
|
{
|
|
BOOL CryptResp;
|
|
DWORD dwBlobLen;
|
|
HCRYPTKEY hTmpKey,hKeyExp;
|
|
BLOBHEADER BlobHeader;
|
|
RSAPUBKEY RsaPubKey;
|
|
GPK_EXP_KEY PubKey;
|
|
DWORD SlotNb;
|
|
|
|
if (!Context_exist(hProv))
|
|
{
|
|
*pdwDataLen = 0;
|
|
RETURN( CRYPT_FAILED, NTE_BAD_UID );
|
|
}
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
if (hKey == 0)
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_BAD_KEY );
|
|
}
|
|
else if (hKey <= MAX_GPK_OBJ)
|
|
{
|
|
if ( ProvCont[hProv].Flags & CRYPT_VERIFYCONTEXT &&
|
|
ProvCont[hProv].isContNameNullBlank )
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_PERM );
|
|
}
|
|
|
|
if (dwBlobType == PUBLICKEYBLOB)
|
|
{
|
|
if (dwFlags != 0)
|
|
RETURN( CRYPT_FAILED, NTE_BAD_FLAGS );
|
|
|
|
if (hPubKey != 0)
|
|
{
|
|
*pdwDataLen = 0;
|
|
RETURN( CRYPT_FAILED, NTE_BAD_KEY );
|
|
}
|
|
|
|
if (Slot[SlotNb].GpkObject[hKey].FileId == 0x00)
|
|
{
|
|
*pdwDataLen = 0;
|
|
RETURN( CRYPT_FAILED, NTE_BAD_KEY );
|
|
}
|
|
|
|
if ( Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].Len == 0 ||
|
|
( Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].pValue[0] != AT_KEYEXCHANGE &&
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].pValue[0] != AT_SIGNATURE ) )
|
|
{
|
|
*pdwDataLen = 0;
|
|
RETURN( CRYPT_FAILED, NTE_BAD_KEY );
|
|
}
|
|
|
|
PubKey = Slot[SlotNb].GpkPubKeys[Slot[SlotNb].GpkObject[hKey].FileId - GPK_FIRST_KEY];
|
|
|
|
if (PubKey.KeySize == 0)
|
|
{
|
|
*pdwDataLen = 0;
|
|
RETURN( CRYPT_FAILED, NTE_BAD_KEY );
|
|
}
|
|
|
|
if (PubKey.ExpSize > sizeof(DWORD))
|
|
{
|
|
*pdwDataLen = 0;
|
|
RETURN( CRYPT_FAILED, NTE_BAD_KEY );
|
|
}
|
|
|
|
dwBlobLen = sizeof(BLOBHEADER) +
|
|
sizeof(RSAPUBKEY) +
|
|
PubKey.KeySize;
|
|
|
|
if (IsNull(pbData))
|
|
{
|
|
*pdwDataLen = dwBlobLen;
|
|
RETURN( CRYPT_SUCCEED, 0 );
|
|
}
|
|
else if (*pdwDataLen < dwBlobLen)
|
|
{
|
|
*pdwDataLen = dwBlobLen;
|
|
RETURN( CRYPT_FAILED, ERROR_MORE_DATA );
|
|
}
|
|
BlobHeader.bType = PUBLICKEYBLOB;
|
|
BlobHeader.bVersion = CUR_BLOB_VERSION;
|
|
BlobHeader.reserved = 0x0000;
|
|
if (Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].pValue[0] == AT_KEYEXCHANGE)
|
|
{
|
|
BlobHeader.aiKeyAlg = CALG_RSA_KEYX;
|
|
}
|
|
else
|
|
{
|
|
BlobHeader.aiKeyAlg = CALG_RSA_SIGN;
|
|
}
|
|
RsaPubKey.magic = 0x31415352;
|
|
RsaPubKey.bitlen = PubKey.KeySize * 8;
|
|
RsaPubKey.pubexp = 0;
|
|
memcpy( &RsaPubKey.pubexp, PubKey.Exposant, sizeof(DWORD) );
|
|
memcpy( pbData, &BlobHeader, sizeof(BlobHeader) );
|
|
memcpy( &pbData[sizeof(BlobHeader)], &RsaPubKey, sizeof(RsaPubKey) );
|
|
r_memcpy( &pbData[sizeof(BlobHeader)+ sizeof(RsaPubKey) ], PubKey.Modulus, PubKey.KeySize );
|
|
*pdwDataLen = dwBlobLen;
|
|
}
|
|
else
|
|
{
|
|
*pdwDataLen = 0;
|
|
RETURN( CRYPT_FAILED, NTE_BAD_TYPE );
|
|
}
|
|
}
|
|
|
|
/* Temporary key */
|
|
else if (key_exist( hKey - MAX_GPK_OBJ, hProv ))
|
|
{
|
|
hTmpKey = hKey - MAX_GPK_OBJ;
|
|
|
|
if (hPubKey == 0)
|
|
{
|
|
*pdwDataLen = 0;
|
|
RETURN( CRYPT_FAILED, NTE_BAD_KEY );
|
|
}
|
|
|
|
if (hPubKey <= MAX_GPK_OBJ)
|
|
{
|
|
//hKeyExp = Slot[SlotNb].GpkObject[hPubKey].hKeyBase;
|
|
if ((Slot[SlotNb].GpkObject[hPubKey].Field[POS_KEY_TYPE].Len == 0) ||
|
|
((Slot[SlotNb].GpkObject[hPubKey].Field[POS_KEY_TYPE].pValue[0] != AT_KEYEXCHANGE) &&
|
|
(Slot[SlotNb].GpkObject[hPubKey].Field[POS_KEY_TYPE].pValue[0] != AT_SIGNATURE)))
|
|
{
|
|
*pdwDataLen = 0;
|
|
RETURN(CRYPT_FAILED, NTE_BAD_KEY);
|
|
}
|
|
|
|
if (Slot[SlotNb].GpkObject[hPubKey].Field[POS_KEY_TYPE].pValue[0] == AT_KEYEXCHANGE)
|
|
{
|
|
hKeyExp = ProvCont[hProv].hRSAKEK;
|
|
}
|
|
else
|
|
{
|
|
hKeyExp = ProvCont[hProv].hRSASign;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!key_exist(hPubKey-MAX_GPK_OBJ, hProv))
|
|
{
|
|
*pdwDataLen = 0;
|
|
RETURN( CRYPT_FAILED, NTE_BAD_KEY );
|
|
}
|
|
else
|
|
{
|
|
hKeyExp = TmpObject[hPubKey-MAX_GPK_OBJ].hKeyBase;
|
|
}
|
|
}
|
|
|
|
CryptResp = CryptExportKey( TmpObject[hTmpKey].hKeyBase, hKeyExp, dwBlobType,
|
|
dwFlags, pbData, pdwDataLen );
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
}
|
|
|
|
/* Unknown key handle */
|
|
else
|
|
{
|
|
*pdwDataLen = 0;
|
|
RETURN( CRYPT_FAILED, NTE_BAD_KEY );
|
|
}
|
|
|
|
RETURN( CRYPT_SUCCEED, 0 );
|
|
}
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
|
|
static BOOL gen_key_on_board8000( HCRYPTPROV hProv, BYTE fileId )
|
|
{
|
|
BOOL Is1024 = FALSE;
|
|
ULONG ulStart, ulEnd;
|
|
BYTE KeyType, Sfi;
|
|
//char szTmp[100];
|
|
WORD wKeySize = 0;
|
|
SCARDHANDLE hCard;
|
|
DWORD lRet;
|
|
|
|
hCard = ProvCont[hProv].hCard;
|
|
|
|
BeginWait();
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
/* Call on board generation for specified key file */
|
|
/*-------------------------------------------------------------------------*/
|
|
Sfi = 0x04 | (fileId<<3);
|
|
|
|
/* Read Record (TAG_INFO) to get key size */
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xB2; //INS
|
|
bSendBuffer[2] = 0x01; //P1
|
|
bSendBuffer[3] = Sfi; //P2
|
|
bSendBuffer[4] = 0x07; //Lo
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength
|
|
);
|
|
if(SCARDPROBLEM(lRet,0x9000,bSendBuffer[4]))
|
|
{
|
|
EndWait();
|
|
return CRYPT_FAILED;
|
|
}
|
|
|
|
KeyType = bRecvBuffer[1];
|
|
|
|
if (KeyType == 0x11)
|
|
{
|
|
Is1024 = TRUE;
|
|
wKeySize = 1024;
|
|
}
|
|
else if (KeyType == 0x00)
|
|
{
|
|
Is1024 = FALSE;
|
|
wKeySize = 512;
|
|
}
|
|
else
|
|
{
|
|
EndWait();
|
|
return CRYPT_FAILED;
|
|
}
|
|
|
|
Sfi = 0x80 | (fileId);
|
|
|
|
// + [FP]
|
|
//sprintf(szTmp,
|
|
// "RSA %d bit key pair on-board generation",
|
|
// wKeySize
|
|
// );
|
|
|
|
//ShowProgress(GetActiveWindow(), szTmp, "Operation in progress...", 0);
|
|
ShowProgressWrapper(wKeySize);
|
|
// - [FP]
|
|
|
|
ulStart = GetTickCount();
|
|
if (Is1024)
|
|
{
|
|
ulEnd = ulStart + (TIME_GEN_1024 * 1000);
|
|
}
|
|
else
|
|
{
|
|
ulEnd = ulStart + (TIME_GEN_512 * 1000);
|
|
}
|
|
|
|
GEN_KEY:
|
|
/* Call on-board generation */
|
|
bSendBuffer[0] = 0x80; //CLA
|
|
bSendBuffer[1] = 0xD2; //INS
|
|
bSendBuffer[2] = Sfi; //P1
|
|
bSendBuffer[3] = KeyType; //P2
|
|
cbSendLength = 4;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if(SCARDPROBLEM(lRet,0x9000,0x00))
|
|
{
|
|
DestroyProgress();
|
|
EndWait();
|
|
return CRYPT_FAILED;
|
|
}
|
|
|
|
/* Wait for generation is successfull */
|
|
if (Is1024 && g_GPK8000KeyGenTime1024 > 0)
|
|
{
|
|
Wait( 1, 1, g_GPK8000KeyGenTime1024 );
|
|
}
|
|
else
|
|
if (!Is1024 && g_GPK8000KeyGenTime512 > 0)
|
|
{
|
|
Wait( 1, 1, g_GPK8000KeyGenTime512 );
|
|
}
|
|
|
|
do
|
|
{
|
|
/* Get response to know if generation successfull */
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xC0; //INS
|
|
bSendBuffer[2] = 0x00; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = 0x42; //Le
|
|
if (Is1024)
|
|
{
|
|
bSendBuffer[4] = 0x82; //Le
|
|
}
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if(SCARDPROBLEM(lRet,0x9000,0x00))
|
|
{
|
|
|
|
if ((dwSW1SW2 == 0x6a88) || (dwSW1SW2 == 0x9220))
|
|
{
|
|
goto GEN_KEY;
|
|
}
|
|
}
|
|
|
|
// + [FP]
|
|
//sprintf(szTmp,
|
|
// "Operation started since %d seconds",
|
|
// (GetTickCount() - ulStart) / 1000
|
|
// );
|
|
//ChangeProgressText(szTmp);
|
|
ChangeProgressWrapper((GetTickCount() - ulStart) / 1000);
|
|
// - [FP]
|
|
|
|
if (GetTickCount() > ulEnd)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
while ((lRet != SCARD_S_SUCCESS) || (dwSW1SW2 != 0x9000));
|
|
DestroyProgress();
|
|
|
|
if ((lRet != SCARD_S_SUCCESS) || (dwSW1SW2 != 0x9000))
|
|
{
|
|
EndWait();
|
|
return CRYPT_FAILED;
|
|
}
|
|
|
|
EndWait();
|
|
|
|
return CRYPT_SUCCEED;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------*/
|
|
|
|
static BOOL gen_key_on_board (HCRYPTPROV hProv)
|
|
{
|
|
BOOL IsLast = FALSE,
|
|
IsExport = TRUE,
|
|
Is1024 = FALSE;
|
|
BYTE Sfi, TmpKeyLength;
|
|
WORD wPubSize;
|
|
DWORD i, lRet ,dwLen,
|
|
dwNumberofCommands,
|
|
dwLastCommandLen,
|
|
dwCommandLen;
|
|
DWORD SlotNb;
|
|
WORD offset;
|
|
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
if (Slot[SlotNb].NbKeyFile == 0)
|
|
Slot[SlotNb].NbKeyFile = Read_NbKeyFile(hProv);
|
|
|
|
if (Slot[SlotNb].NbKeyFile == 0 || Slot[SlotNb].NbKeyFile > MAX_REAL_KEY)
|
|
{
|
|
RETURN( CRYPT_FAILED, SCARD_E_FILE_NOT_FOUND );
|
|
}
|
|
|
|
if (!Select_MF(hProv))
|
|
return CRYPT_FAILED;
|
|
|
|
if (!VerifyDivPIN(hProv, FALSE))
|
|
return CRYPT_FAILED;
|
|
|
|
if (!Select_Crypto_DF(hProv))
|
|
return CRYPT_FAILED;
|
|
|
|
if (!PIN_Validation(hProv))
|
|
return CRYPT_FAILED;
|
|
|
|
if (!VerifyDivPIN(hProv, TRUE))
|
|
return CRYPT_FAILED;
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
/* Call on board generation for each key file */
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
i = 0;
|
|
do
|
|
{
|
|
Sfi = 0x04 | ((GPK_FIRST_KEY+(BYTE)i)<<3);
|
|
|
|
/* Read Record (TAG_INFO) to get key size */
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xB2; //INS
|
|
bSendBuffer[2] = 0x01; //P1
|
|
bSendBuffer[3] = Sfi; //P2
|
|
bSendBuffer[4] = 0x07; //Lo
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x9000,bSendBuffer[4]))
|
|
{
|
|
EndWait();
|
|
RETURN( CRYPT_FAILED, SCARD_E_UNEXPECTED );
|
|
}
|
|
|
|
if (bRecvBuffer[1] == 0x11)
|
|
{
|
|
IsExport = FALSE;
|
|
Is1024 = TRUE;
|
|
}
|
|
else
|
|
{
|
|
Is1024 = FALSE;
|
|
}
|
|
|
|
TmpKeyLength = bRecvBuffer[1];
|
|
|
|
Sfi = 0x80 | (GPK_FIRST_KEY+(BYTE)i);
|
|
|
|
GEN_KEY:
|
|
/* Call on-board generation */
|
|
bSendBuffer[0] = 0x80; //CLA
|
|
bSendBuffer[1] = 0xD2; //INS
|
|
bSendBuffer[2] = Sfi; //P1
|
|
bSendBuffer[3] = TmpKeyLength; //P2
|
|
cbSendLength = 4;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if (SCARDPROBLEM(lRet,0x9000,0x00))
|
|
{
|
|
// if the first key has been generate successfully -- meaning??
|
|
if (dwSW1SW2 == 0x6982) // 0x6982: access condition not fulfilled
|
|
{
|
|
i++; // skip and generate another key
|
|
continue;
|
|
}
|
|
|
|
EndWait();
|
|
RETURN( CRYPT_FAILED, SCARD_E_UNEXPECTED );
|
|
}
|
|
|
|
/* Wait for generation is successfull */
|
|
if (Is1024)
|
|
{
|
|
Wait( i+1, Slot[SlotNb].NbKeyFile, TIME_GEN_1024 );
|
|
}
|
|
else
|
|
{
|
|
Wait( i+1, Slot[SlotNb].NbKeyFile, TIME_GEN_512 );
|
|
}
|
|
|
|
/* Get response to know if generation successfull */
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xC0; //INS
|
|
bSendBuffer[2] = 0x00; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = 0x42; //Le
|
|
if (Is1024)
|
|
{
|
|
bSendBuffer[4] = 0x82; //Le
|
|
}
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x9000,0x00))
|
|
{
|
|
if (dwSW1SW2 == 0x6a88) // 0x6a88: key selection error
|
|
{
|
|
goto GEN_KEY;
|
|
}
|
|
|
|
EndWait();
|
|
RETURN(CRYPT_FAILED, SCARD_E_UNEXPECTED);
|
|
}
|
|
|
|
/* Freeze key file */
|
|
bSendBuffer[0] = 0x80; //CLA
|
|
bSendBuffer[1] = 0x16; //INS
|
|
bSendBuffer[2] = 0x02; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = 0x05; //Li
|
|
bSendBuffer[5] = 0x00;
|
|
bSendBuffer[6] = 0x07+(BYTE)i;
|
|
bSendBuffer[7] = 0x40;
|
|
bSendBuffer[8] = 0x40;
|
|
bSendBuffer[9] = 0x00;
|
|
|
|
cbSendLength = 10;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x9000,0x00))
|
|
{
|
|
EndWait();
|
|
RETURN( CRYPT_FAILED, SCARD_E_UNEXPECTED );
|
|
}
|
|
|
|
i++;
|
|
}
|
|
while (i < Slot[SlotNb].NbKeyFile); // version 2.00.002, it was "(i<MAX_REAL_KEY)"
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
/* Erase on board generation filter */
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
/* Call erase command */
|
|
bSendBuffer[0] = 0x80; //CLA
|
|
bSendBuffer[1] = 0xD4; //INS
|
|
bSendBuffer[2] = 0x00; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
cbSendLength = 4;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x9000,0x00))
|
|
{
|
|
EndWait();
|
|
RETURN(CRYPT_FAILED, SCARD_E_UNEXPECTED);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
/* Public Part */
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
wPubSize = EF_PUBLIC_SIZE;
|
|
if (IsExport)
|
|
{
|
|
wPubSize = wPubSize + DIFF_US_EXPORT;
|
|
}
|
|
|
|
/* Create EF for Public Object storage */
|
|
bSendBuffer[0] = 0x80; //CLA
|
|
bSendBuffer[1] = 0xE0; //INS
|
|
bSendBuffer[2] = 0x02; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = 0x0C; //Li
|
|
bSendBuffer[5] = HIBYTE(GPK_OBJ_PUB_EF); //File Id
|
|
bSendBuffer[6] = LOBYTE(GPK_OBJ_PUB_EF);
|
|
bSendBuffer[7] = 0x01; //FDB
|
|
bSendBuffer[8] = 0x00; //Rec Len
|
|
bSendBuffer[9] = HIBYTE(wPubSize); //Body Length
|
|
bSendBuffer[10] = LOBYTE(wPubSize);
|
|
bSendBuffer[11] = 0x00; //AC1
|
|
bSendBuffer[12] = 0x00;
|
|
bSendBuffer[13] = 0xC0; //AC2
|
|
bSendBuffer[14] = 0x00;
|
|
bSendBuffer[15] = 0x00; //AC3
|
|
bSendBuffer[16] = 0x00;
|
|
|
|
cbSendLength = 17;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x9000,0x00))
|
|
{
|
|
EndWait();
|
|
RETURN(CRYPT_FAILED, SCARD_E_UNEXPECTED);
|
|
}
|
|
|
|
/* Select Public Object storage EF */
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xA4; //INS
|
|
bSendBuffer[2] = 0x02; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = 0x02; //Li
|
|
bSendBuffer[5] = HIBYTE(GPK_OBJ_PUB_EF);
|
|
bSendBuffer[6] = LOBYTE(GPK_OBJ_PUB_EF);
|
|
cbSendLength = 7;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x61FF,0x00))
|
|
{
|
|
EndWait();
|
|
RETURN(CRYPT_FAILED, SCARD_E_UNEXPECTED);
|
|
}
|
|
|
|
dwLen = sizeof(InitValue[Slot[SlotNb].NbKeyFile-1]);//wPubSize;
|
|
|
|
/* Write the Objects EF */
|
|
dwNumberofCommands = (dwLen-1)/FILE_CHUNK_SIZE + 1;
|
|
dwLastCommandLen = dwLen%FILE_CHUNK_SIZE;
|
|
|
|
if (dwLastCommandLen == 0)
|
|
{
|
|
dwLastCommandLen = FILE_CHUNK_SIZE;
|
|
}
|
|
|
|
dwCommandLen = FILE_CHUNK_SIZE;
|
|
|
|
for (i=0; i < dwNumberofCommands ; i++)
|
|
{
|
|
if (i == dwNumberofCommands - 1)
|
|
{
|
|
dwCommandLen = dwLastCommandLen;
|
|
}
|
|
|
|
/* Write FILE_CHUCK_SIZE bytes or last bytes */
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xD6; //INS
|
|
// TT 03/11/99
|
|
//bSendBuffer[2] = HIBYTE(i*FILE_CHUNK_SIZE/4); //P1
|
|
//bSendBuffer[3] = LOBYTE(i*FILE_CHUNK_SIZE/4); //P2
|
|
offset = (WORD)(i * FILE_CHUNK_SIZE) / ProvCont[hProv].dataUnitSize;
|
|
bSendBuffer[2] = HIBYTE( offset );
|
|
bSendBuffer[3] = LOBYTE( offset );
|
|
bSendBuffer[4] = (BYTE)dwCommandLen; //Li
|
|
memcpy(&bSendBuffer[5],
|
|
&InitValue[Slot[SlotNb].NbKeyFile-1][i*FILE_CHUNK_SIZE],
|
|
dwCommandLen
|
|
);
|
|
cbSendLength = 5 + dwCommandLen;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x9000, 0x00))
|
|
{
|
|
EndWait();
|
|
RETURN(CRYPT_FAILED, SCARD_E_UNEXPECTED);
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
/* Private Part */
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
/* Create EF for Private Object storage */
|
|
bSendBuffer[0] = 0x80; //CLA
|
|
bSendBuffer[1] = 0xE0; //INS
|
|
bSendBuffer[2] = 0x02; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = 0x0C; //Li
|
|
bSendBuffer[5] = HIBYTE(GPK_OBJ_PRIV_EF); //File Id
|
|
bSendBuffer[6] = LOBYTE(GPK_OBJ_PRIV_EF);
|
|
bSendBuffer[7] = 0x01; //FDB
|
|
bSendBuffer[8] = 0x00; //Rec Len
|
|
bSendBuffer[9] = HIBYTE(EF_PRIVATE_SIZE); //Body Length
|
|
bSendBuffer[10] = LOBYTE(EF_PRIVATE_SIZE);
|
|
bSendBuffer[11] = 0x40; //AC1
|
|
bSendBuffer[12] = 0x80;
|
|
bSendBuffer[13] = 0xC0; //AC2
|
|
bSendBuffer[14] = 0x80;
|
|
bSendBuffer[15] = 0x40; //AC3
|
|
bSendBuffer[16] = 0x80;
|
|
|
|
cbSendLength = 17;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x9000,0x00))
|
|
{
|
|
EndWait();
|
|
RETURN(CRYPT_FAILED, SCARD_E_UNEXPECTED);
|
|
}
|
|
|
|
/* Select Private Object storage EF */
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xA4; //INS
|
|
bSendBuffer[2] = 0x02; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = 0x02; //Li
|
|
bSendBuffer[5] = HIBYTE(GPK_OBJ_PRIV_EF);
|
|
bSendBuffer[6] = LOBYTE(GPK_OBJ_PRIV_EF);
|
|
cbSendLength = 7;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x61FF,0x00))
|
|
{
|
|
EndWait();
|
|
RETURN(CRYPT_FAILED, SCARD_E_UNEXPECTED);
|
|
}
|
|
|
|
dwLen = sizeof(InitValue[Slot[SlotNb].NbKeyFile-1]);//EF_PRIVATE_SIZE;
|
|
|
|
/* Write the Objects EF */
|
|
dwNumberofCommands = (dwLen-1)/FILE_CHUNK_SIZE + 1;
|
|
dwLastCommandLen = dwLen%FILE_CHUNK_SIZE;
|
|
|
|
if (dwLastCommandLen == 0)
|
|
{
|
|
dwLastCommandLen = FILE_CHUNK_SIZE;
|
|
}
|
|
|
|
dwCommandLen = FILE_CHUNK_SIZE;
|
|
|
|
for (i=0; i < dwNumberofCommands ; i++)
|
|
{
|
|
if (i == dwNumberofCommands - 1)
|
|
{
|
|
dwCommandLen = dwLastCommandLen;
|
|
}
|
|
|
|
// Write FILE_CHUCK_SIZE bytes or last bytes
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xD6; //INS
|
|
offset = (WORD)(i * FILE_CHUNK_SIZE) / ProvCont[hProv].dataUnitSize;
|
|
bSendBuffer[2] = HIBYTE( offset );
|
|
bSendBuffer[3] = LOBYTE( offset );
|
|
bSendBuffer[4] = (BYTE)dwCommandLen; //Li
|
|
memcpy(&bSendBuffer[5],
|
|
&InitValue[Slot[SlotNb].NbKeyFile-1][i*FILE_CHUNK_SIZE],
|
|
dwCommandLen
|
|
);
|
|
cbSendLength = 5 + dwCommandLen;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x9000, 0x00))
|
|
{
|
|
EndWait();
|
|
RETURN(CRYPT_FAILED, SCARD_E_UNEXPECTED);
|
|
}
|
|
}
|
|
EndWait();
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
- MyCPGenKey
|
|
-
|
|
* Purpose:
|
|
* Generate cryptographic keys
|
|
*
|
|
*
|
|
* Parameters:
|
|
* IN hProv - Handle to a CSP
|
|
* IN Algid - Algorithm identifier
|
|
* IN dwFlags - Flags values
|
|
* OUT phKey - Handle to a generated key
|
|
*
|
|
* Returns:
|
|
*/
|
|
|
|
BOOL WINAPI MyCPGenKey(IN HCRYPTPROV hProv,
|
|
IN ALG_ID Algid,
|
|
IN DWORD dwFlags,
|
|
OUT HCRYPTKEY *phKey
|
|
)
|
|
{
|
|
HCRYPTKEY hKey, hKeyPriv;
|
|
BOOL bSessKey;
|
|
BYTE *pbBuff1 = 0, i;
|
|
BYTE KeyBuff[50], SaltBuff[50];
|
|
BYTE SaltLen, KeyLen;
|
|
DWORD lRet,
|
|
dwBuff1Len,
|
|
SlotNb;
|
|
int nbKey;
|
|
BOOL bAllSameSize;
|
|
BOOL b512avail;
|
|
BOOL b1024avail;
|
|
// +NK 06.02.2001
|
|
DWORD dwPinLength;
|
|
// -
|
|
|
|
*phKey = 0;
|
|
bSessKey = FALSE;
|
|
|
|
if (!Context_exist(hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_UID);
|
|
}
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
if (Algid == AT_KEYEXCHANGE || Algid == AT_SIGNATURE)
|
|
{
|
|
if (ProvCont[hProv].Flags & CRYPT_VERIFYCONTEXT)
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_PERM );
|
|
}
|
|
|
|
if (Slot[SlotNb].NbKeyFile == 0)
|
|
Slot[SlotNb].NbKeyFile = Read_NbKeyFile(hProv);
|
|
|
|
if (Slot[SlotNb].NbKeyFile == 0 || Slot[SlotNb].NbKeyFile > MAX_REAL_KEY)
|
|
{
|
|
RETURN (CRYPT_FAILED, SCARD_E_FILE_NOT_FOUND); // should not bigger than MAX_REAL_KEY
|
|
}
|
|
}
|
|
|
|
switch (Algid)
|
|
{
|
|
case AT_SIGNATURE:
|
|
//
|
|
// Verisign Enrollment process does not respect this fact
|
|
//
|
|
// if (dwFlags & CRYPT_EXPORTABLE)
|
|
// {
|
|
// RETURN (CRYPT_FAILED, NTE_BAD_FLAGS);
|
|
// }
|
|
|
|
if (ProvCont[hProv].Flags & CRYPT_VERIFYCONTEXT)
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_PERM );
|
|
}
|
|
|
|
// + NK 06.02.2001
|
|
// if ((ProvCont[hProv].Flags & CRYPT_SILENT) && (IsNullStr(Slot[SlotNb].GetPin())))
|
|
lRet = Query_MSPinCache( Slot[SlotNb].hPinCacheHandle,
|
|
NULL,
|
|
&dwPinLength );
|
|
|
|
if ((lRet != ERROR_SUCCESS) && (lRet != ERROR_EMPTY))
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
|
|
if ((ProvCont[hProv].Flags & CRYPT_SILENT) && (lRet == ERROR_EMPTY))
|
|
// - NK
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_SILENT_CONTEXT );
|
|
}
|
|
|
|
if (!PublicEFExists(hProv))
|
|
{
|
|
if (!gen_key_on_board(hProv))
|
|
{
|
|
return CRYPT_FAILED;
|
|
}
|
|
else
|
|
{
|
|
if (!read_gpk_objects(hProv, FALSE))
|
|
return CRYPT_FAILED;
|
|
|
|
Slot[SlotNb].Read_Public = TRUE;
|
|
Slot[SlotNb].Read_Priv = FALSE;
|
|
}
|
|
}
|
|
|
|
if (!Read_Priv_Obj(hProv))
|
|
return CRYPT_FAILED;
|
|
|
|
if (HIWORD(dwFlags) != 0x0000)
|
|
{
|
|
KeyLen = HIWORD(dwFlags) / 8;
|
|
//check for the keylen, only 512 or 1024 key are supported for now
|
|
if (( KeyLen != 64 && KeyLen != 128 ) || (HIWORD(dwFlags) & 7))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_LEN);
|
|
}
|
|
|
|
// [FP] +
|
|
switch(Slot[SlotNb].NbKeyFile)
|
|
{
|
|
case 2:
|
|
if ((Slot[SlotNb].GpkPubKeys[0].KeySize == 64) &&
|
|
(Slot[SlotNb].GpkPubKeys[1].KeySize == 64) && // GPK4K Intl
|
|
(KeyLen == 128))
|
|
RETURN (CRYPT_FAILED, NTE_BAD_LEN);
|
|
break;
|
|
|
|
case 4:
|
|
break;
|
|
|
|
default:
|
|
RETURN (CRYPT_FAILED, NTE_FAIL);
|
|
}
|
|
// [FP] +
|
|
}
|
|
else
|
|
{
|
|
KeyLen = 0;
|
|
|
|
// Read key file lengths
|
|
nbKey = Slot[SlotNb].NbKeyFile;
|
|
|
|
for (i = 0; i<nbKey; ++i)
|
|
KeyLenFile[i] = Slot[SlotNb].GpkPubKeys[i].KeySize;
|
|
|
|
// If all keys have the same size, use that size
|
|
bAllSameSize = TRUE;
|
|
for (i = 1; i<nbKey; ++i)
|
|
{
|
|
if (KeyLenFile[i] != KeyLenFile[0])
|
|
{
|
|
bAllSameSize = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (bAllSameSize)
|
|
KeyLen = KeyLenFile[0];
|
|
else
|
|
{
|
|
// TT - BUG #1504: If only one key size is available, try to use it
|
|
b512avail = find_gpk_obj_tag_type( hProv, TAG_RSA_PUBLIC, 0, 512/8, FALSE, FALSE ) != 0;
|
|
b1024avail = find_gpk_obj_tag_type( hProv, TAG_RSA_PUBLIC, 0, 1024/8, FALSE, FALSE ) != 0;
|
|
|
|
if (!b512avail && !b1024avail)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_FAIL );
|
|
}
|
|
|
|
if (b512avail && !b1024avail) KeyLen = 512/8;
|
|
else if (!b512avail && b1024avail) KeyLen = 1024/8;
|
|
else
|
|
{
|
|
// TT - END
|
|
if (ProvCont[hProv].Flags & CRYPT_SILENT)
|
|
{
|
|
// Check if default key length (1024) is available
|
|
for (i = 0; i<nbKey; ++i)
|
|
{
|
|
if (KeyLenFile[i] == 0x80)
|
|
{
|
|
KeyLen = 0x80;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (KeyLen==0)
|
|
{
|
|
// Take smallest key size available
|
|
KeyLen = KeyLenFile[0];
|
|
for (i = 1; i<nbKey; ++i)
|
|
{
|
|
if (KeyLenFile[i] < KeyLen)
|
|
KeyLen = KeyLenFile[i];
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DialogBox(g_hInstRes, TEXT("KEYDIALOG"), GetAppWindow(), KeyDlgProc);
|
|
if (KeyLenChoice == 0)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_LEN);
|
|
}
|
|
else
|
|
{
|
|
KeyLen = KeyLenChoice;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// AT_SIGNATURE
|
|
hKey = find_gpk_obj_tag_type(hProv, TAG_RSA_PUBLIC, 0x00, KeyLen, FALSE, FALSE);
|
|
if ((hKey != 0)
|
|
&&(find_gpk_obj_tag_type(hProv, TAG_RSA_PUBLIC, AT_SIGNATURE, 0x00, FALSE, FALSE) == 0)
|
|
&&(find_gpk_obj_tag_type(hProv, TAG_CERTIFICATE, AT_SIGNATURE, 0x00, FALSE, FALSE) == 0)
|
|
)
|
|
{
|
|
*phKey = hKey;
|
|
}
|
|
else
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_FAIL );
|
|
}
|
|
|
|
// TT 24/09/99: On board key generation for GPK8000
|
|
if (ProvCont[hProv].bGPK8000)
|
|
{
|
|
if (!gen_key_on_board8000( hProv, Slot[SlotNb].GpkObject[hKey].FileId ))
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_FAIL );
|
|
}
|
|
}
|
|
// TT - END -
|
|
|
|
|
|
|
|
hKeyPriv = find_gpk_obj_tag_file(hProv,
|
|
TAG_RSA_PRIVATE,
|
|
Slot[SlotNb].GpkObject[hKey].FileId,
|
|
FALSE
|
|
);
|
|
|
|
if ( hKeyPriv == 0 )
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_SIGNATURE_FILE_BAD);
|
|
}
|
|
|
|
if ((HIWORD(dwFlags) != 0) &&
|
|
(Slot[SlotNb].GpkObject[hKeyPriv].PubKey.KeySize != (HIWORD(dwFlags) / 8))
|
|
)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_FLAGS);
|
|
}
|
|
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].pValue = (BYTE*)GMEM_Alloc(1);
|
|
if (IsNull (Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].pValue))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Field[POS_KEY_TYPE].pValue = (BYTE*)GMEM_Alloc(1);
|
|
if (IsNull (Slot[SlotNb].GpkObject[hKeyPriv].Field[POS_KEY_TYPE].pValue))
|
|
{
|
|
GMEM_Free (Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].pValue);
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
Slot[SlotNb].GpkObject[hKey].IsCreated = TRUE;
|
|
Slot[SlotNb].GpkObject[hKey].Flags = Slot[SlotNb].GpkObject[hKey].Flags | FLAG_KEY_TYPE;
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].Len = 1;
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].pValue[0] = AT_SIGNATURE;
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].bReal = TRUE;
|
|
|
|
/* Set Flags of automatic fields for PKCS#11 compatibility */
|
|
Slot[SlotNb].GpkObject[hKey].Flags = Slot[SlotNb].GpkObject[hKey].Flags | FLAG_ID;
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_ID].Len = 0;
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_ID].bReal = FALSE;
|
|
|
|
Slot[SlotNb].GpkObject[hKeyPriv].IsCreated = TRUE;
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Flags = Slot[SlotNb].GpkObject[hKeyPriv].Flags | FLAG_KEY_TYPE;
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Field[POS_KEY_TYPE].Len = 1;
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Field[POS_KEY_TYPE].pValue[0] = AT_SIGNATURE;
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Field[POS_KEY_TYPE].bReal = TRUE;
|
|
|
|
/* Set Flags of automatic fields for PKCS#11 compatibility */
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Flags = Slot[SlotNb].GpkObject[hKeyPriv].Flags | FLAG_ID;
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Field[POS_ID].Len = 0;
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Field[POS_ID].bReal = FALSE;
|
|
|
|
if (!ProvCont[hProv].bLegacyKeyset)
|
|
{
|
|
Slot[SlotNb].GpkObject[hKey].Flags |= FLAG_KEYSET;
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEYSET].Len = 1;
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEYSET].pValue = (BYTE*)GMEM_Alloc(1);
|
|
if(IsNull(Slot[SlotNb].GpkObject[hKey].Field[POS_KEYSET].pValue))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEYSET].pValue[0] = ProvCont[hProv].keysetID;
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEYSET].bReal = TRUE;
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Flags |= FLAG_KEYSET;
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Field[POS_KEYSET].Len = 1;
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Field[POS_KEYSET].pValue = (BYTE*)GMEM_Alloc(1);
|
|
if(IsNull(Slot[SlotNb].GpkObject[hKeyPriv].Field[POS_KEYSET].pValue))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Field[POS_KEYSET].pValue[0] = ProvCont[hProv].keysetID;
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Field[POS_KEYSET].bReal = TRUE;
|
|
}
|
|
|
|
// Set the file containing the key to USE, add "- GPK_FIRST_KEY" here. version 2.00.002
|
|
Slot[SlotNb].UseFile [Slot[SlotNb].GpkObject[hKey].FileId- GPK_FIRST_KEY] = TRUE;
|
|
|
|
break;
|
|
|
|
case AT_KEYEXCHANGE:
|
|
//
|
|
// Verisign Enrollment process does not respect this fact
|
|
//
|
|
// if (dwFlags & CRYPT_EXPORTABLE)
|
|
// {
|
|
// RETURN (CRYPT_FAILED, NTE_BAD_FLAGS);
|
|
// }
|
|
|
|
if (ProvCont[hProv].Flags & CRYPT_VERIFYCONTEXT)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_PERM);
|
|
}
|
|
|
|
// + NK 06.02.2001
|
|
// if ((ProvCont[hProv].Flags & CRYPT_SILENT) && (IsNullStr(Slot[SlotNb].GetPin())))
|
|
lRet = Query_MSPinCache( Slot[SlotNb].hPinCacheHandle,
|
|
NULL,
|
|
&dwPinLength );
|
|
|
|
if ( (lRet != ERROR_SUCCESS) && (lRet != ERROR_EMPTY) )
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
|
|
if ((ProvCont[hProv].Flags & CRYPT_SILENT) && (lRet == ERROR_EMPTY))
|
|
// - NK
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_SILENT_CONTEXT);
|
|
}
|
|
|
|
if (!PublicEFExists(hProv))
|
|
{
|
|
if (!gen_key_on_board(hProv))
|
|
{
|
|
return CRYPT_FAILED;
|
|
}
|
|
else
|
|
{
|
|
if (!read_gpk_objects(hProv, FALSE))
|
|
return CRYPT_FAILED;
|
|
|
|
Slot[SlotNb].Read_Public = TRUE;
|
|
Slot[SlotNb].Read_Priv = FALSE;
|
|
}
|
|
}
|
|
|
|
if (!Read_Priv_Obj(hProv))
|
|
return CRYPT_FAILED;
|
|
|
|
if (HIWORD(dwFlags) != 0x0000)
|
|
{
|
|
KeyLen = HIWORD(dwFlags) / 8;
|
|
|
|
//check for the keylen, only 512 or 1024 key are supported for now
|
|
if (( KeyLen != 64 && KeyLen != 128 ) || (HIWORD(dwFlags) & 7))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_LEN);
|
|
}
|
|
|
|
// [FP] +
|
|
switch(Slot[SlotNb].NbKeyFile)
|
|
{
|
|
case 2:
|
|
if ((Slot[SlotNb].GpkPubKeys[0].KeySize == 64) &&
|
|
(Slot[SlotNb].GpkPubKeys[1].KeySize == 64) && // GPK4K Intl
|
|
(KeyLen == 128))
|
|
RETURN (CRYPT_FAILED, NTE_BAD_LEN);
|
|
break;
|
|
|
|
case 4:
|
|
if ((Slot[SlotNb].GpkPubKeys[0].KeySize == 64) &&
|
|
(Slot[SlotNb].GpkPubKeys[1].KeySize == 64) &&
|
|
(Slot[SlotNb].GpkPubKeys[2].KeySize == 64) &&
|
|
(Slot[SlotNb].GpkPubKeys[3].KeySize == 128) && // GPK8K Intl
|
|
(KeyLen == 128))
|
|
RETURN (CRYPT_FAILED, NTE_BAD_LEN);
|
|
break;
|
|
|
|
default:
|
|
RETURN (CRYPT_FAILED, NTE_FAIL);
|
|
}
|
|
// [FP] +
|
|
}
|
|
else
|
|
{
|
|
KeyLen = 0;
|
|
|
|
// Read key file lengths
|
|
nbKey = Slot[SlotNb].NbKeyFile;
|
|
|
|
for (i = 0; i<nbKey; ++i)
|
|
KeyLenFile[i] = Slot[SlotNb].GpkPubKeys[i].KeySize;
|
|
|
|
// If all keys have the same size, use that size
|
|
bAllSameSize = TRUE;
|
|
for (i = 1; i<nbKey; ++i)
|
|
{
|
|
if (KeyLenFile[i] != KeyLenFile[0])
|
|
{
|
|
bAllSameSize = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (bAllSameSize)
|
|
KeyLen = KeyLenFile[0];
|
|
else
|
|
{
|
|
// TT - BUG #1504: If only one key size is available, try to use it
|
|
b512avail = find_gpk_obj_tag_type( hProv, TAG_RSA_PUBLIC, 0, 512/8, TRUE, FALSE ) != 0;
|
|
b1024avail = find_gpk_obj_tag_type( hProv, TAG_RSA_PUBLIC, 0, 1024/8, TRUE, FALSE ) != 0;
|
|
|
|
if (!b512avail && !b1024avail)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_FAIL );
|
|
}
|
|
|
|
if (b512avail && !b1024avail) KeyLen = 512/8;
|
|
else if (!b512avail && b1024avail) KeyLen = 1024/8;
|
|
else
|
|
{
|
|
// TT - END
|
|
// Check if default key length is available
|
|
for (i = 0; i<nbKey; ++i)
|
|
{
|
|
if (KeyLenFile[i] == RSA_KEK_Size)
|
|
{
|
|
KeyLen = RSA_KEK_Size;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (KeyLen==0)
|
|
{
|
|
// Take smallest key size available
|
|
KeyLen = KeyLenFile[0];
|
|
for (i = 1; i<nbKey; ++i)
|
|
{
|
|
if (KeyLenFile[i] < KeyLen)
|
|
KeyLen = KeyLenFile[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (KeyLen > RSA_KEK_Size)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_LEN);
|
|
}
|
|
|
|
// AT_EXCHANGE
|
|
hKey = find_gpk_obj_tag_type(hProv, TAG_RSA_PUBLIC, 0x00, KeyLen, TRUE, FALSE);
|
|
if ((hKey != 0)
|
|
&&(find_gpk_obj_tag_type(hProv, TAG_RSA_PUBLIC, AT_KEYEXCHANGE, 0x00, TRUE, FALSE) == 0)
|
|
&&(find_gpk_obj_tag_type(hProv, TAG_CERTIFICATE, AT_KEYEXCHANGE, 0x00, FALSE, FALSE) == 0)
|
|
)
|
|
{
|
|
*phKey = hKey;
|
|
}
|
|
else
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_FAIL );
|
|
}
|
|
|
|
// TT 24/09/99: On board key generation for GPK8000
|
|
if (ProvCont[hProv].bGPK8000)
|
|
{
|
|
if (!gen_key_on_board8000( hProv, Slot[SlotNb].GpkObject[hKey].FileId ))
|
|
{
|
|
RETURN( CRYPT_FAILED, NTE_FAIL );
|
|
}
|
|
}
|
|
// TT - END -
|
|
|
|
hKeyPriv = find_gpk_obj_tag_file(hProv,
|
|
TAG_RSA_PRIVATE,
|
|
Slot[SlotNb].GpkObject[hKey].FileId,
|
|
TRUE
|
|
);
|
|
|
|
if ( hKeyPriv == 0 )
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_SIGNATURE_FILE_BAD);
|
|
}
|
|
|
|
if ((HIWORD(dwFlags) != 0) &&
|
|
(Slot[SlotNb].GpkObject[hKeyPriv].PubKey.KeySize != (HIWORD(dwFlags) / 8))
|
|
)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_FLAGS);
|
|
}
|
|
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].pValue = (BYTE*)GMEM_Alloc(1);
|
|
if (IsNull (Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].pValue))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Field[POS_KEY_TYPE].pValue = (BYTE*)GMEM_Alloc(1);
|
|
if (IsNull (Slot[SlotNb].GpkObject[hKeyPriv].Field[POS_KEY_TYPE].pValue))
|
|
{
|
|
GMEM_Free (Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].pValue);
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
Slot[SlotNb].GpkObject[hKey].IsCreated = TRUE;
|
|
Slot[SlotNb].GpkObject[hKey].Flags = Slot[SlotNb].GpkObject[hKey].Flags | FLAG_KEY_TYPE;
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].Len = 1;
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].pValue[0] = AT_KEYEXCHANGE;
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].bReal = TRUE;
|
|
|
|
/* Set Flags of automatic fields for PKCS#11 compatibility */
|
|
Slot[SlotNb].GpkObject[hKey].Flags = Slot[SlotNb].GpkObject[hKey].Flags | FLAG_ID;
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_ID].Len = 0;
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_ID].bReal = FALSE;
|
|
|
|
Slot[SlotNb].GpkObject[hKeyPriv].IsCreated = TRUE;
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Flags = Slot[SlotNb].GpkObject[hKeyPriv].Flags | FLAG_KEY_TYPE;
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Field[POS_KEY_TYPE].Len = 1;
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Field[POS_KEY_TYPE].pValue[0] = AT_KEYEXCHANGE;
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Field[POS_KEY_TYPE].bReal = TRUE;
|
|
|
|
/* Set Flags of automatic fields for PKCS#11 compatibility */
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Flags = Slot[SlotNb].GpkObject[hKeyPriv].Flags | FLAG_ID;
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Field[POS_ID].Len = 0;
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Field[POS_ID].bReal = FALSE;
|
|
|
|
if (!ProvCont[hProv].bLegacyKeyset)
|
|
{
|
|
Slot[SlotNb].GpkObject[hKey].Flags |= FLAG_KEYSET;
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEYSET].Len = 1;
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEYSET].pValue = (BYTE*)GMEM_Alloc(1);
|
|
if(IsNull(Slot[SlotNb].GpkObject[hKey].Field[POS_KEYSET].pValue))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEYSET].pValue[0] = ProvCont[hProv].keysetID;
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEYSET].bReal = TRUE;
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Flags |= FLAG_KEYSET;
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Field[POS_KEYSET].Len = 1;
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Field[POS_KEYSET].pValue = (BYTE*)GMEM_Alloc(1);
|
|
if(IsNull(Slot[SlotNb].GpkObject[hKeyPriv].Field[POS_KEYSET].pValue))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Field[POS_KEYSET].pValue[0] = ProvCont[hProv].keysetID;
|
|
Slot[SlotNb].GpkObject[hKeyPriv].Field[POS_KEYSET].bReal = TRUE;
|
|
}
|
|
|
|
|
|
// Set the file containing the key to USE, add "- GPK_FIRST_KEY" here, version 2.00.002
|
|
Slot[SlotNb].UseFile [Slot[SlotNb].GpkObject[hKey].FileId - GPK_FIRST_KEY] = TRUE;
|
|
break;
|
|
|
|
case CALG_RC2:
|
|
KeyLen = RC2_Key_Size;
|
|
SaltLen = 0;
|
|
if (dwFlags & CRYPT_CREATE_SALT)
|
|
{
|
|
SaltLen = RC2_128_SIZE - RC2_Key_Size;
|
|
}
|
|
bSessKey = TRUE;
|
|
break;
|
|
|
|
case CALG_RC4:
|
|
KeyLen = RC2_Key_Size;
|
|
SaltLen = 0;
|
|
if (dwFlags & CRYPT_CREATE_SALT)
|
|
{
|
|
SaltLen = RC2_128_SIZE - RC2_Key_Size;
|
|
}
|
|
bSessKey = TRUE;
|
|
break;
|
|
|
|
case CALG_DES:
|
|
KeyLen = DES_SIZE;
|
|
SaltLen = 0;
|
|
if (dwFlags & CRYPT_CREATE_SALT)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_FLAGS);
|
|
}
|
|
bSessKey = TRUE;
|
|
break;
|
|
|
|
case CALG_3DES_112:
|
|
KeyLen = DES3_112_SIZE;
|
|
SaltLen = 0;
|
|
if (dwFlags & CRYPT_CREATE_SALT)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_FLAGS);
|
|
}
|
|
bSessKey = TRUE;
|
|
break;
|
|
|
|
case CALG_3DES:
|
|
KeyLen = DES3_SIZE;
|
|
SaltLen = 0;
|
|
if (dwFlags & CRYPT_CREATE_SALT)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_FLAGS);
|
|
}
|
|
bSessKey = TRUE;
|
|
break;
|
|
|
|
default:
|
|
RETURN (CRYPT_FAILED, NTE_BAD_ALGID);
|
|
}
|
|
|
|
if (!bSessKey)
|
|
{
|
|
CspFlags = ProvCont[hProv].Flags;
|
|
|
|
|
|
pbBuff1 = (BYTE*)GMEM_Alloc (MAX_GPK_PUBLIC);
|
|
if (IsNull(pbBuff1))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
dwBuff1Len = MAX_GPK_PUBLIC;
|
|
if (!prepare_write_gpk_objects (hProv, pbBuff1, &dwBuff1Len, FALSE))
|
|
{
|
|
lRet = GetLastError();
|
|
GMEM_Free (pbBuff1);
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
if (!write_gpk_objects(hProv, pbBuff1, dwBuff1Len, FALSE, FALSE))
|
|
{
|
|
lRet = GetLastError();
|
|
GMEM_Free (pbBuff1);
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
GMEM_Free (pbBuff1);
|
|
|
|
pbBuff1 = (BYTE*)GMEM_Alloc (MAX_GPK_PRIVATE);
|
|
if (IsNull(pbBuff1))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
dwBuff1Len = MAX_GPK_PRIVATE;
|
|
if (!prepare_write_gpk_objects (hProv, pbBuff1, &dwBuff1Len, TRUE))
|
|
{
|
|
lRet = GetLastError();
|
|
GMEM_Free (pbBuff1);
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
if (!write_gpk_objects(hProv, pbBuff1, dwBuff1Len, FALSE, TRUE))
|
|
{
|
|
lRet = GetLastError();
|
|
GMEM_Free (pbBuff1);
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
GMEM_Free (pbBuff1);
|
|
|
|
/* Copy Gpk Key in Microsoft RSA base Module */
|
|
|
|
Slot[SlotNb].GpkPubKeys[Slot[SlotNb].GpkObject[*phKey].FileId - GPK_FIRST_KEY].KeySize = 0;
|
|
|
|
if (!read_gpk_pub_key( hProv, *phKey, &Slot[SlotNb].GpkObject[*phKey].PubKey ))
|
|
return CRYPT_FAILED;
|
|
|
|
if (!copy_gpk_key(hProv, *phKey, Algid))
|
|
return CRYPT_FAILED;
|
|
}
|
|
else
|
|
{
|
|
hKey = find_tmp_free();
|
|
if (hKey == 0)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
if (KeyLen > AuxMaxSessionKeyLength)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_LEN);
|
|
}
|
|
|
|
// Notice: Implicitly we also need in this case to establish a transaction
|
|
// with the card. OK done by the wrapper
|
|
|
|
if ((ProvCont[hProv].Flags & CRYPT_VERIFYCONTEXT) &&
|
|
(ProvCont[hProv].isContNameNullBlank))
|
|
{
|
|
if (!CryptGenKey (hProvBase, Algid, dwFlags, &(TmpObject[hKey].hKeyBase)))
|
|
return CRYPT_FAILED;
|
|
|
|
TmpObject[hKey].hProv = hProv;
|
|
*phKey = hKey + MAX_GPK_OBJ;
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
if (!MyCPGenRandom(hProv, KeyLen, KeyBuff))
|
|
return CRYPT_FAILED;
|
|
|
|
if (SaltLen != 0)
|
|
{
|
|
if (!MyCPGenRandom(hProv, SaltLen, SaltBuff))
|
|
return CRYPT_FAILED;
|
|
}
|
|
|
|
/* Copy Session Key in Microsoft RSA base Module*/
|
|
if (dwFlags & CRYPT_CREATE_SALT) // CryptImport does not deal with that flag
|
|
dwFlags ^= CRYPT_CREATE_SALT; // however, it is consider anyhow with the
|
|
// SaltLen parameter.
|
|
|
|
if (!copy_tmp_key(hProv, hKey, dwFlags, Algid, KeyBuff, KeyLen, SaltBuff, SaltLen))
|
|
return CRYPT_FAILED;
|
|
|
|
*phKey = hKey + MAX_GPK_OBJ;
|
|
}
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
- MyCPGenRandom
|
|
-
|
|
* Purpose:
|
|
* Used to fill a buffer with random bytes
|
|
*
|
|
*
|
|
* Parameters:
|
|
* IN hProv - Handle to the user identifcation
|
|
* OUT pbBuffer - Pointer to the buffer where the random
|
|
* bytes are to be placed
|
|
* IN dwLen - Number of bytes of random data requested
|
|
*
|
|
* Returns:
|
|
*/
|
|
BOOL WINAPI MyCPGenRandom(IN HCRYPTPROV hProv,
|
|
IN DWORD dwLen,
|
|
IN OUT BYTE *pbBuffer
|
|
)
|
|
|
|
{
|
|
DWORD i, dwMod, dwLastCommandLen, lRet;
|
|
|
|
if (!Context_exist(hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_UID);
|
|
}
|
|
|
|
if ((ProvCont[hProv].Flags & CRYPT_VERIFYCONTEXT) &&
|
|
(ProvCont[hProv].isContNameNullBlank))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_PERM);
|
|
}
|
|
|
|
if (dwLen==0)
|
|
{
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
/* Generate random by blocks of 32 bytes */
|
|
dwMod = (dwLen-1)/32 + 1;
|
|
dwLastCommandLen = dwLen%32;
|
|
|
|
if (dwLastCommandLen == 0)
|
|
{
|
|
dwLastCommandLen = 32;
|
|
}
|
|
|
|
for (i=0 ; i < dwMod ; i++)
|
|
{
|
|
/* Ask card for a 32 bytes random number */
|
|
bSendBuffer[0] = 0x80; //CLA
|
|
bSendBuffer[1] = 0x84; //INS
|
|
bSendBuffer[2] = 0x00; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = 0x20; //Lo
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x9000,bSendBuffer[4]))
|
|
{
|
|
RETURN (CRYPT_FAILED, SCARD_E_UNSUPPORTED_FEATURE);
|
|
}
|
|
|
|
memcpy(&pbBuffer[i*32],
|
|
bRecvBuffer,
|
|
((i == dwMod - 1) ? dwLastCommandLen : 32)
|
|
);
|
|
}
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
|
|
/*
|
|
- MyCPGetKeyParam
|
|
-
|
|
* Purpose:
|
|
* Allows applications to get various aspects of the
|
|
* operations of a key
|
|
*
|
|
* Parameters:
|
|
* IN hProv - Handle to a CSP
|
|
* IN hKey - Handle to a key
|
|
* IN dwParam - Parameter number
|
|
* IN pbData - Pointer to data
|
|
* IN pdwDataLen - Length of parameter data
|
|
* IN dwFlags - Flags values
|
|
*
|
|
* Returns:
|
|
*/
|
|
BOOL WINAPI MyCPGetKeyParam(IN HCRYPTPROV hProv,
|
|
IN HCRYPTKEY hKey,
|
|
IN DWORD dwParam,
|
|
IN BYTE *pbData,
|
|
IN DWORD *pdwDataLen,
|
|
IN DWORD dwFlags
|
|
)
|
|
{
|
|
BOOL CryptResp;
|
|
BYTE hCert;
|
|
BYTE KeyType;
|
|
BYTE KeyId;
|
|
BYTE GpkKeySize;
|
|
DWORD SlotNb;
|
|
|
|
if (!Context_exist(hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_UID);
|
|
}
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
/* Resident Key */
|
|
if (hKey == 0)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_KEY);
|
|
}
|
|
else if (hKey <= MAX_GPK_OBJ)
|
|
{
|
|
if (dwFlags != 0)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_FLAGS);
|
|
}
|
|
|
|
// [mv - 15/05/98]
|
|
if ((ProvCont[hProv].Flags & CRYPT_VERIFYCONTEXT) &&
|
|
(ProvCont[hProv].isContNameNullBlank))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_PERM);
|
|
}
|
|
|
|
if (Slot[SlotNb].GpkObject[hKey].FileId == 0)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_KEY);
|
|
}
|
|
|
|
if (Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].Len == 0)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_KEY);
|
|
}
|
|
|
|
KeyId = Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].pValue[0];
|
|
|
|
switch (dwParam)
|
|
{
|
|
case KP_ALGID:
|
|
if (IsNotNull(pbData))
|
|
{
|
|
DWORD dwAlgid;
|
|
|
|
if (*pdwDataLen < sizeof(DWORD))
|
|
{
|
|
*pdwDataLen = sizeof(DWORD);
|
|
RETURN (CRYPT_FAILED, ERROR_MORE_DATA);
|
|
}
|
|
|
|
switch (KeyId)
|
|
{
|
|
case AT_KEYEXCHANGE:
|
|
dwAlgid = CALG_RSA_KEYX;
|
|
break;
|
|
|
|
case AT_SIGNATURE:
|
|
dwAlgid = CALG_RSA_SIGN;
|
|
break;
|
|
|
|
default:
|
|
RETURN (CRYPT_FAILED, NTE_BAD_TYPE);
|
|
}
|
|
memcpy(pbData, &dwAlgid, sizeof(DWORD));
|
|
}
|
|
|
|
*pdwDataLen = sizeof(DWORD);
|
|
break;
|
|
|
|
case KP_BLOCKLEN:
|
|
case KP_KEYLEN:
|
|
if (IsNotNull(pbData))
|
|
{
|
|
DWORD dwBlockLen;
|
|
|
|
if (*pdwDataLen < sizeof(DWORD))
|
|
{
|
|
*pdwDataLen = sizeof(DWORD);
|
|
RETURN (CRYPT_FAILED, ERROR_MORE_DATA);
|
|
}
|
|
|
|
GpkKeySize = Slot[SlotNb].GpkPubKeys[Slot[SlotNb].GpkObject[hKey].FileId - GPK_FIRST_KEY].KeySize;
|
|
if (GpkKeySize == 0)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_KEY);
|
|
}
|
|
|
|
dwBlockLen = GpkKeySize*8;
|
|
memcpy(pbData, &dwBlockLen, sizeof(DWORD));
|
|
}
|
|
|
|
*pdwDataLen = sizeof(DWORD);
|
|
break;
|
|
|
|
case KP_PERMISSIONS:
|
|
if (IsNotNull(pbData))
|
|
{
|
|
DWORD dwPerm;
|
|
|
|
if (*pdwDataLen < sizeof(DWORD))
|
|
{
|
|
*pdwDataLen = sizeof(DWORD);
|
|
RETURN (CRYPT_FAILED, ERROR_MORE_DATA);
|
|
}
|
|
|
|
switch (KeyId)
|
|
{
|
|
case AT_KEYEXCHANGE:
|
|
dwPerm = 0
|
|
| CRYPT_ENCRYPT // Allow encryption
|
|
| CRYPT_DECRYPT // Allow decryption
|
|
// CRYPT_EXPORT // Allow key to be exported
|
|
| CRYPT_READ // Allow parameters to be read
|
|
| CRYPT_WRITE // Allow parameters to be set
|
|
| CRYPT_MAC // Allow MACs to be used with key
|
|
| CRYPT_EXPORT_KEY// Allow key to be used for exporting keys
|
|
| CRYPT_IMPORT_KEY// Allow key to be used for importing keys
|
|
;
|
|
break;
|
|
|
|
case AT_SIGNATURE:
|
|
dwPerm = 0
|
|
// CRYPT_ENCRYPT // Allow encryption
|
|
// CRYPT_DECRYPT // Allow decryption
|
|
// CRYPT_EXPORT // Allow key to be exported
|
|
| CRYPT_READ // Allow parameters to be read
|
|
| CRYPT_WRITE // Allow parameters to be set
|
|
| CRYPT_MAC // Allow MACs to be used with key
|
|
// CRYPT_EXPORT_KEY// Allow key to be used for exporting keys
|
|
// CRYPT_IMPORT_KEY// Allow key to be used for importing keys
|
|
;
|
|
break;
|
|
|
|
default:
|
|
RETURN (CRYPT_FAILED, NTE_BAD_TYPE);
|
|
}
|
|
memcpy(pbData, &dwPerm, sizeof(DWORD));
|
|
}
|
|
|
|
*pdwDataLen = sizeof(DWORD);
|
|
break;
|
|
|
|
case KP_CERTIFICATE:
|
|
KeyType = Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].pValue[0];
|
|
hCert = find_gpk_obj_tag_type( hProv, TAG_CERTIFICATE, KeyType,
|
|
0x00, FALSE, FALSE );
|
|
if (hCert == 0)
|
|
{
|
|
RETURN( CRYPT_FAILED, SCARD_E_NO_SUCH_CERTIFICATE );
|
|
}
|
|
|
|
/* Retrieve Certificate Value */
|
|
if (IsNotNull(pbData))
|
|
{
|
|
if (*pdwDataLen < Slot[SlotNb].GpkObject[hCert].Field[POS_VALUE].Len)
|
|
{
|
|
*pdwDataLen = Slot[SlotNb].GpkObject[hCert].Field[POS_VALUE].Len;
|
|
RETURN (CRYPT_FAILED, ERROR_MORE_DATA);
|
|
}
|
|
memcpy(pbData,
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_VALUE].pValue,
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_VALUE].Len
|
|
);
|
|
}
|
|
|
|
*pdwDataLen = Slot[SlotNb].GpkObject[hCert].Field[POS_VALUE].Len;
|
|
break;
|
|
|
|
|
|
default:
|
|
RETURN (CRYPT_FAILED, NTE_BAD_TYPE);
|
|
}
|
|
}
|
|
/* Session Key */
|
|
else if (key_exist (hKey-MAX_GPK_OBJ, hProv))
|
|
{
|
|
CryptResp = CryptGetKeyParam (TmpObject[hKey-MAX_GPK_OBJ].hKeyBase,
|
|
dwParam,
|
|
pbData,
|
|
pdwDataLen,
|
|
dwFlags);
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
}
|
|
/* Bad Key */
|
|
else
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_KEY);
|
|
}
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
|
|
/*
|
|
- MyCPGetUserKey
|
|
-
|
|
* Purpose:
|
|
* Gets a handle to a permanent user key
|
|
*
|
|
*
|
|
* Parameters:
|
|
* IN hProv - Handle to the user identifcation
|
|
* IN dwKeySpec - Specification of the key to retrieve
|
|
* OUT phUserKey - Pointer to key handle of retrieved key
|
|
*
|
|
* Returns:
|
|
*/
|
|
BOOL WINAPI MyCPGetUserKey(IN HCRYPTPROV hProv,
|
|
IN DWORD dwKeySpec,
|
|
OUT HCRYPTKEY *phUserKey
|
|
)
|
|
{
|
|
HCRYPTKEY hKey;
|
|
GPK_EXP_KEY aPubKey;
|
|
DWORD dwLen;
|
|
|
|
*phUserKey = 0;
|
|
|
|
if (!Context_exist(hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_UID);
|
|
}
|
|
|
|
/* Bug # 1103
|
|
if ((ProvCont[hProv].Flags & CRYPT_VERIFYCONTEXT) &&
|
|
(ProvCont[hProv].isContNameNullBlank))
|
|
*/
|
|
if ( ProvCont[hProv].Flags & CRYPT_VERIFYCONTEXT )
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_PERM);
|
|
}
|
|
|
|
if (!PublicEFExists(hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_KEY);
|
|
}
|
|
|
|
if (dwKeySpec != AT_KEYEXCHANGE && dwKeySpec != AT_SIGNATURE)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_KEY);
|
|
}
|
|
|
|
if (dwKeySpec == AT_KEYEXCHANGE)
|
|
{
|
|
hKey = find_gpk_obj_tag_type(hProv,
|
|
TAG_RSA_PUBLIC,
|
|
(BYTE)dwKeySpec,
|
|
0x00,
|
|
TRUE,
|
|
FALSE
|
|
);
|
|
|
|
// get the key length
|
|
if (hKey != 0)
|
|
{
|
|
if (!read_gpk_pub_key(hProv, hKey, &aPubKey))
|
|
{
|
|
hKey = 0;
|
|
}
|
|
else
|
|
{
|
|
dwLen = aPubKey.KeySize;
|
|
if (dwLen > RSA_KEK_Size)
|
|
{
|
|
hKey = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hKey = find_gpk_obj_tag_type(hProv,
|
|
TAG_RSA_PUBLIC,
|
|
(BYTE)dwKeySpec,
|
|
0x00,
|
|
FALSE,
|
|
FALSE
|
|
);
|
|
}
|
|
|
|
if (hKey == 0)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_KEY);
|
|
}
|
|
|
|
*phUserKey = hKey;
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
/*
|
|
- MyCPImportKey
|
|
-
|
|
* Purpose:
|
|
* Import cryptographic keys
|
|
*
|
|
*
|
|
* Parameters:
|
|
* IN hProv - Handle to the CSP user
|
|
* IN pbData - Key blob data
|
|
* IN dwDataLen - Length of the key blob data
|
|
* IN hPubKey - Handle to the exchange public key value of
|
|
* the destination user
|
|
* IN dwFlags - Flags values
|
|
* OUT phKey - Pointer to the handle to the key which was
|
|
* Imported
|
|
*
|
|
* Returns:
|
|
*/
|
|
BOOL WINAPI MyCPImportKey(IN HCRYPTPROV hProv,
|
|
IN CONST BYTE *pbData,
|
|
IN DWORD dwDataLen,
|
|
IN HCRYPTKEY hPubKey,
|
|
IN DWORD dwFlags,
|
|
OUT HCRYPTKEY *phKey
|
|
)
|
|
{
|
|
DWORD lRet;
|
|
BOOL CryptResp;
|
|
HCRYPTKEY hTmpKey, hPrivKey;
|
|
BLOBHEADER BlobHeader;
|
|
DWORD dwAlgid, dwBlobLen;
|
|
BYTE* pBlob;
|
|
BYTE* pBlobOut;
|
|
DWORD SlotNb;
|
|
// + [FP] for PRIVATEKEYBLOB
|
|
BOOL GpkObj;
|
|
GPK_EXP_KEY aPubKey;
|
|
DWORD dwKeyLen;
|
|
BYTE bKeyType;
|
|
BOOL IsExchange;
|
|
HCRYPTKEY hKey;
|
|
BYTE bSfi;
|
|
BYTE *pbBuff1 = 0;
|
|
DWORD dwBuff1Len;
|
|
// - [FP]
|
|
// + NK 07.02.2001
|
|
DWORD dwPinLength;
|
|
// -NK
|
|
|
|
if (!Context_exist(hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_UID);
|
|
}
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
if ((IsNull(pbData)) || (dwDataLen < sizeof(BLOBHEADER)+sizeof(RSAPUBKEY)))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_DATA);
|
|
}
|
|
|
|
memcpy(&BlobHeader, pbData, sizeof(BLOBHEADER));
|
|
|
|
if (BlobHeader.bVersion != CUR_BLOB_VERSION)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_VER);
|
|
}
|
|
|
|
switch (BlobHeader.bType)
|
|
{
|
|
case PUBLICKEYBLOB:
|
|
{
|
|
hTmpKey = find_tmp_free();
|
|
if (hTmpKey == 0)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
/* Copy Session Key in Microsoft RSA base Module */
|
|
CryptResp = CryptImportKey(hProvBase,
|
|
pbData,
|
|
dwDataLen,
|
|
0,
|
|
dwFlags,
|
|
&(TmpObject[hTmpKey].hKeyBase));
|
|
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
|
|
TmpObject[hTmpKey].hProv = hProv;
|
|
|
|
*phKey = hTmpKey+MAX_GPK_OBJ;
|
|
}
|
|
break;
|
|
|
|
case SIMPLEBLOB:
|
|
{
|
|
if (ProvCont[hProv].Flags & CRYPT_VERIFYCONTEXT)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_PERM);
|
|
}
|
|
|
|
// + NK 06.02.2001
|
|
// if ((ProvCont[hProv].Flags & CRYPT_SILENT) && (IsNullStr(Slot[SlotNb].GetPin())))
|
|
lRet = Query_MSPinCache( Slot[SlotNb].hPinCacheHandle,
|
|
NULL,
|
|
&dwPinLength );
|
|
|
|
if ( (lRet != ERROR_SUCCESS) && (lRet != ERROR_EMPTY) )
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
|
|
if ((ProvCont[hProv].Flags & CRYPT_SILENT) && (lRet == ERROR_EMPTY))
|
|
// - NK
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_SILENT_CONTEXT);
|
|
}
|
|
|
|
// Verify the PINs
|
|
|
|
if (!PIN_Validation(hProv))
|
|
return CRYPT_FAILED;
|
|
|
|
if (!VerifyDivPIN(hProv, TRUE))
|
|
return CRYPT_FAILED;
|
|
|
|
switch (BlobHeader.aiKeyAlg)
|
|
{
|
|
case CALG_RC2:
|
|
case CALG_RC4:
|
|
case CALG_DES:
|
|
case CALG_3DES_112:
|
|
case CALG_3DES: break;
|
|
|
|
default:
|
|
RETURN (CRYPT_FAILED, NTE_BAD_ALGID);
|
|
}
|
|
|
|
memcpy( &dwAlgid, &pbData[sizeof(BlobHeader)], sizeof(DWORD) );
|
|
|
|
switch (dwAlgid)
|
|
{
|
|
case CALG_RSA_KEYX:
|
|
CryptResp = MyCPGetUserKey(hProv, AT_KEYEXCHANGE, &hPrivKey);
|
|
if ((!CryptResp) || (hPrivKey == 0))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_DATA);
|
|
}
|
|
break;
|
|
|
|
case CALG_RSA_SIGN:
|
|
RETURN (CRYPT_FAILED, NTE_BAD_DATA);
|
|
break;
|
|
|
|
default:
|
|
RETURN (CRYPT_FAILED, NTE_BAD_DATA);
|
|
}
|
|
|
|
dwBlobLen = dwDataLen-sizeof(BLOBHEADER)-sizeof(DWORD);
|
|
|
|
pBlob = (BYTE*)GMEM_Alloc(dwBlobLen);
|
|
if (IsNull(pBlob))
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
|
|
pBlobOut = (BYTE*)GMEM_Alloc(dwBlobLen);
|
|
if (IsNull(pBlobOut))
|
|
{
|
|
GMEM_Free (pBlob);
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
bool bErrorInTryOccured=false;
|
|
DWORD dwErrorCode=ERROR_SUCCESS;
|
|
__try
|
|
{
|
|
memcpy( pBlob, &pbData[sizeof(BLOBHEADER)+sizeof(DWORD)], dwBlobLen );
|
|
|
|
hTmpKey = find_tmp_free();
|
|
if (hTmpKey == 0)
|
|
{
|
|
bErrorInTryOccured=true;
|
|
dwErrorCode=NTE_NO_MEMORY;
|
|
__leave;
|
|
}
|
|
// RETURN( CRYPT_FAILED, NTE_NO_MEMORY );
|
|
|
|
CryptResp = key_unwrap( hProv, hPrivKey, pBlob, dwBlobLen, pBlobOut, &dwBlobLen );
|
|
if (!CryptResp)
|
|
{
|
|
bErrorInTryOccured=true;
|
|
__leave;
|
|
}
|
|
//return CRYPT_FAILED;
|
|
|
|
if (dwBlobLen > AuxMaxSessionKeyLength)
|
|
{
|
|
bErrorInTryOccured=true;
|
|
dwErrorCode=NTE_BAD_KEY;
|
|
__leave;
|
|
}
|
|
// RETURN( CRYPT_FAILED, NTE_BAD_KEY );
|
|
|
|
/* Copy Session Key in Microsoft RSA base Module */
|
|
if (!copy_tmp_key(hProv, hTmpKey, dwFlags, BlobHeader.aiKeyAlg, pBlobOut, dwBlobLen, 0, 0))
|
|
{
|
|
bErrorInTryOccured=true;
|
|
__leave;
|
|
}
|
|
//return CRYPT_FAILED;
|
|
|
|
*phKey = hTmpKey+MAX_GPK_OBJ;
|
|
}
|
|
__finally
|
|
{
|
|
GMEM_Free(pBlob);
|
|
GMEM_Free(pBlobOut);
|
|
}
|
|
if(bErrorInTryOccured)
|
|
{
|
|
if(dwErrorCode==ERROR_SUCCESS)
|
|
return CRYPT_FAILED;
|
|
else
|
|
RETURN(CRYPT_FAILED, dwErrorCode);
|
|
}
|
|
}
|
|
break;
|
|
|
|
// + [FP]
|
|
case PRIVATEKEYBLOB:
|
|
{
|
|
if (ProvCont[hProv].Flags & CRYPT_VERIFYCONTEXT)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_PERM);
|
|
}
|
|
|
|
// + NK 06.02.2001
|
|
// if ((ProvCont[hProv].Flags & CRYPT_SILENT) && (IsNullStr(Slot[SlotNb].GetPin())))
|
|
|
|
lRet = Query_MSPinCache( Slot[SlotNb].hPinCacheHandle,
|
|
NULL,
|
|
&dwPinLength );
|
|
if ( (lRet != ERROR_SUCCESS) && (lRet != ERROR_EMPTY) )
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
|
|
if ((ProvCont[hProv].Flags & CRYPT_SILENT) && (lRet == ERROR_EMPTY))
|
|
// - NK
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_SILENT_CONTEXT);
|
|
}
|
|
|
|
if (Slot[SlotNb].NbKeyFile == 0 || Slot[SlotNb].NbKeyFile > MAX_REAL_KEY)
|
|
{
|
|
RETURN (CRYPT_FAILED, SCARD_E_FILE_NOT_FOUND); // should not bigger than MAX_REAL_KEY
|
|
}
|
|
|
|
// get the key type
|
|
bKeyType = (BlobHeader.aiKeyAlg == CALG_RSA_KEYX) ? AT_KEYEXCHANGE : AT_SIGNATURE;
|
|
IsExchange = (BlobHeader.aiKeyAlg == CALG_RSA_KEYX) ? TRUE : FALSE;
|
|
|
|
// get the key size (in bits)
|
|
memcpy(&dwKeyLen,
|
|
&pbData[sizeof(BlobHeader)+ sizeof(DWORD)],
|
|
sizeof(DWORD)
|
|
);
|
|
|
|
if (bKeyType == AT_KEYEXCHANGE)
|
|
{
|
|
if ((dwKeyLen / 8) > RSA_KEK_Size)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_LEN);
|
|
}
|
|
}
|
|
|
|
GpkObj = TRUE;
|
|
|
|
hKey = find_gpk_obj_tag_type(hProv, TAG_RSA_PUBLIC, bKeyType, 0x00, IsExchange, FALSE);
|
|
|
|
if (hKey != 0)
|
|
{
|
|
if (!read_gpk_pub_key(hProv, hKey, &aPubKey))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_FAIL);
|
|
}
|
|
|
|
if ((dwKeyLen / 8) != aPubKey.KeySize)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_LEN);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GpkObj = FALSE;
|
|
|
|
// find a file on the card
|
|
hKey = find_gpk_obj_tag_type(hProv, TAG_RSA_PUBLIC, 0x00, (BYTE)(dwKeyLen / 8), IsExchange, FALSE);
|
|
|
|
if ((hKey != 0)
|
|
&&(find_gpk_obj_tag_type(hProv, TAG_RSA_PUBLIC, bKeyType, 0x00, IsExchange, FALSE) == 0)
|
|
&&(find_gpk_obj_tag_type(hProv, TAG_CERTIFICATE, bKeyType, 0x00, FALSE, FALSE) == 0)
|
|
)
|
|
{
|
|
*phKey = hKey;
|
|
}
|
|
else
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_FAIL);
|
|
}
|
|
}
|
|
|
|
bSfi = Slot[SlotNb].GpkObject[hKey].FileId;
|
|
|
|
if (!Read_Priv_Obj(hProv))
|
|
return CRYPT_FAILED;
|
|
|
|
if (!VerifyDivPIN(hProv, TRUE))
|
|
return CRYPT_FAILED;
|
|
|
|
// load the public key in the card
|
|
// Update record 2 (modulus)
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xDC; //INS
|
|
bSendBuffer[2] = 0x02; //P1
|
|
bSendBuffer[3] = (BYTE)(bSfi << 3) + 0x04; //P2
|
|
bSendBuffer[4] = (BYTE)(TAG_LEN + (dwKeyLen / 8)); //Li
|
|
bSendBuffer[5] = TAG_MODULUS;
|
|
memcpy(&bSendBuffer[6], &pbData[sizeof(BlobHeader) + sizeof(RSAPUBKEY)], dwKeyLen / 8);
|
|
cbSendLength = 5 + bSendBuffer[4];
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if(SCARDPROBLEM(lRet, 0x9000, 0x00))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_FAIL);
|
|
}
|
|
|
|
// Update record 3 (public exponent)
|
|
bSendBuffer[0] = 0x00; //CLA
|
|
bSendBuffer[1] = 0xDC; //INS
|
|
bSendBuffer[2] = 0x03; //P1
|
|
bSendBuffer[3] = (BYTE)(bSfi << 3) + 0x04; //P2
|
|
bSendBuffer[4] = (BYTE)(TAG_LEN + PUB_EXP_LEN); //Li
|
|
bSendBuffer[5] = TAG_PUB_EXP;
|
|
memcpy(&bSendBuffer[6], &pbData[sizeof(BlobHeader) + (2 * sizeof(DWORD))], PUB_EXP_LEN);
|
|
cbSendLength = 5 + bSendBuffer[4];
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if(SCARDPROBLEM(lRet, 0x9000, 0x00))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_FAIL);
|
|
}
|
|
|
|
// load the private key in the card
|
|
if (dwKeyLen == 512)
|
|
{
|
|
if (!LoadPrivateKey(ProvCont[hProv].hCard,
|
|
bSfi,
|
|
(WORD)(dwKeyLen / 16 * 5),
|
|
&pbData[sizeof(BlobHeader)+ sizeof(RSAPUBKEY) + (dwKeyLen/8)],
|
|
168
|
|
)
|
|
)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_FAIL);
|
|
}
|
|
}
|
|
else if (dwKeyLen == 1024)
|
|
{
|
|
// PRIME 1 CRT part
|
|
if (!LoadPrivateKey(ProvCont[hProv].hCard,
|
|
bSfi,
|
|
(WORD)(dwKeyLen / 16),
|
|
&pbData[sizeof(BlobHeader)+ sizeof(RSAPUBKEY) + (dwKeyLen/8)],
|
|
72
|
|
)
|
|
)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_FAIL);
|
|
}
|
|
|
|
// PRIME 2 CRT part
|
|
if (!LoadPrivateKey(ProvCont[hProv].hCard,
|
|
bSfi,
|
|
(WORD)(dwKeyLen / 16),
|
|
&pbData[sizeof(BlobHeader)+ sizeof(RSAPUBKEY) + (dwKeyLen/8) + 72],
|
|
72
|
|
)
|
|
)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_FAIL);
|
|
}
|
|
|
|
// COEFFICIENT CRT part
|
|
if (!LoadPrivateKey(ProvCont[hProv].hCard,
|
|
bSfi,
|
|
(WORD)(dwKeyLen / 16),
|
|
&pbData[sizeof(BlobHeader)+ sizeof(RSAPUBKEY) + (dwKeyLen/8) + 144],
|
|
72
|
|
)
|
|
)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_FAIL);
|
|
}
|
|
|
|
// EXPONENT 1 CRT part
|
|
if (!LoadPrivateKey(ProvCont[hProv].hCard,
|
|
bSfi,
|
|
(WORD)(dwKeyLen / 16),
|
|
&pbData[sizeof(BlobHeader)+ sizeof(RSAPUBKEY) + (dwKeyLen/8) + 216],
|
|
72
|
|
)
|
|
)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_FAIL);
|
|
}
|
|
|
|
// EXPONENT 2 CRT part
|
|
if (!LoadPrivateKey(ProvCont[hProv].hCard,
|
|
bSfi,
|
|
(WORD)(dwKeyLen / 16),
|
|
&pbData[sizeof(BlobHeader)+ sizeof(RSAPUBKEY) + (dwKeyLen/8) + 288],
|
|
72
|
|
)
|
|
)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_FAIL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_LEN);
|
|
}
|
|
|
|
if (!GpkObj)
|
|
{
|
|
hPrivKey = find_gpk_obj_tag_file(hProv, TAG_RSA_PRIVATE, Slot[SlotNb].GpkObject[hKey].FileId, TRUE);
|
|
|
|
if ( hPrivKey == 0 )
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_SIGNATURE_FILE_BAD);
|
|
}
|
|
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].pValue = (BYTE*)GMEM_Alloc(1);
|
|
if (IsNull(Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].pValue))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
Slot[SlotNb].GpkObject[hPrivKey].Field[POS_KEY_TYPE].pValue = (BYTE*)GMEM_Alloc(1);
|
|
if (IsNull(Slot[SlotNb].GpkObject[hPrivKey].Field[POS_KEY_TYPE].pValue))
|
|
{
|
|
GMEM_Free(Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].pValue);
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
Slot[SlotNb].GpkObject[hKey].IsCreated = TRUE;
|
|
Slot[SlotNb].GpkObject[hKey].Flags = Slot[SlotNb].GpkObject[hKey].Flags | FLAG_KEY_TYPE;
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].Len = 1;
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].pValue[0] = bKeyType;
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].bReal = TRUE;
|
|
|
|
/* Set Flags of automatic fields for PKCS#11 compatibility */
|
|
Slot[SlotNb].GpkObject[hKey].Flags = Slot[SlotNb].GpkObject[hKey].Flags | FLAG_ID;
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_ID].Len = 0;
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_ID].bReal = FALSE;
|
|
|
|
Slot[SlotNb].GpkObject[hPrivKey].IsCreated = TRUE;
|
|
Slot[SlotNb].GpkObject[hPrivKey].Flags = Slot[SlotNb].GpkObject[hPrivKey].Flags | FLAG_KEY_TYPE;
|
|
Slot[SlotNb].GpkObject[hPrivKey].Field[POS_KEY_TYPE].Len = 1;
|
|
Slot[SlotNb].GpkObject[hPrivKey].Field[POS_KEY_TYPE].pValue[0] = bKeyType;
|
|
Slot[SlotNb].GpkObject[hPrivKey].Field[POS_KEY_TYPE].bReal = TRUE;
|
|
|
|
/* Set Flags of automatic fields for PKCS#11 compatibility */
|
|
Slot[SlotNb].GpkObject[hPrivKey].Flags = Slot[SlotNb].GpkObject[hPrivKey].Flags | FLAG_ID;
|
|
Slot[SlotNb].GpkObject[hPrivKey].Field[POS_ID].Len = 0;
|
|
Slot[SlotNb].GpkObject[hPrivKey].Field[POS_ID].bReal = FALSE;
|
|
|
|
if (!ProvCont[hProv].bLegacyKeyset)
|
|
{
|
|
Slot[SlotNb].GpkObject[hKey].Flags |= FLAG_KEYSET;
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEYSET].Len = 1;
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEYSET].pValue = (BYTE*)GMEM_Alloc(1);
|
|
if(IsNull(Slot[SlotNb].GpkObject[hKey].Field[POS_KEYSET].pValue))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEYSET].pValue[0] = ProvCont[hProv].keysetID;
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEYSET].bReal = TRUE;
|
|
|
|
Slot[SlotNb].GpkObject[hPrivKey].Flags |= FLAG_KEYSET;
|
|
Slot[SlotNb].GpkObject[hPrivKey].Field[POS_KEYSET].Len = 1;
|
|
Slot[SlotNb].GpkObject[hPrivKey].Field[POS_KEYSET].pValue = (BYTE*)GMEM_Alloc(1);
|
|
if(IsNull(Slot[SlotNb].GpkObject[hPrivKey].Field[POS_KEYSET].pValue))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
Slot[SlotNb].GpkObject[hPrivKey].Field[POS_KEYSET].pValue[0] = ProvCont[hProv].keysetID;
|
|
Slot[SlotNb].GpkObject[hPrivKey].Field[POS_KEYSET].bReal = TRUE;
|
|
}
|
|
|
|
// set the file containing the key to USE, add "- GPK_FIRST_KEY" here, version 2.00.002
|
|
Slot[SlotNb].UseFile[Slot[SlotNb].GpkObject[hKey].FileId - GPK_FIRST_KEY] = TRUE;
|
|
|
|
pbBuff1 = (BYTE*)GMEM_Alloc (MAX_GPK_PUBLIC);
|
|
if (IsNull(pbBuff1))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
dwBuff1Len = MAX_GPK_PUBLIC;
|
|
if (!prepare_write_gpk_objects (hProv, pbBuff1, &dwBuff1Len, FALSE))
|
|
{
|
|
lRet = GetLastError();
|
|
GMEM_Free (pbBuff1);
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
if (!write_gpk_objects(hProv, pbBuff1, dwBuff1Len, FALSE, FALSE))
|
|
{
|
|
lRet = GetLastError();
|
|
GMEM_Free (pbBuff1);
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
GMEM_Free (pbBuff1);
|
|
|
|
pbBuff1 = (BYTE*)GMEM_Alloc (MAX_GPK_PRIVATE);
|
|
if (IsNull(pbBuff1))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
dwBuff1Len = MAX_GPK_PRIVATE;
|
|
if (!prepare_write_gpk_objects (hProv, pbBuff1, &dwBuff1Len, TRUE))
|
|
{
|
|
lRet = GetLastError();
|
|
GMEM_Free (pbBuff1);
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
if (!write_gpk_objects(hProv, pbBuff1, dwBuff1Len, FALSE, TRUE))
|
|
{
|
|
lRet = GetLastError();
|
|
GMEM_Free (pbBuff1);
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
GMEM_Free (pbBuff1);
|
|
|
|
// copy Gpk Key in Microsoft RSA base Module
|
|
if (!copy_gpk_key(hProv, *phKey, bKeyType))
|
|
return CRYPT_FAILED;
|
|
}
|
|
break;
|
|
}
|
|
// - [FP]
|
|
|
|
case SYMMETRICWRAPKEYBLOB:
|
|
{
|
|
hTmpKey = find_tmp_free();
|
|
if (hTmpKey == 0)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
// find the handle of imported key
|
|
HCRYPTKEY hEncKey;
|
|
|
|
if ((hPubKey <= MAX_GPK_OBJ) || (!key_exist(hPubKey-MAX_GPK_OBJ, hProv)))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_KEY);
|
|
}
|
|
else
|
|
{
|
|
hEncKey = TmpObject[hPubKey-MAX_GPK_OBJ].hKeyBase;
|
|
}
|
|
|
|
/* import Session Key in Microsoft Base Module */
|
|
CryptResp = CryptImportKey(hProvBase,
|
|
pbData,
|
|
dwDataLen,
|
|
hEncKey,
|
|
dwFlags,
|
|
&(TmpObject[hTmpKey].hKeyBase));
|
|
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
|
|
TmpObject[hTmpKey].hProv = hProv;
|
|
|
|
*phKey = hTmpKey+MAX_GPK_OBJ;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_TYPE);
|
|
}
|
|
}
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
/*
|
|
- CPSetKeyParam
|
|
-
|
|
* Purpose:
|
|
* Allows applications to customize various aspects of the
|
|
* operations of a key
|
|
*
|
|
* Parameters:
|
|
* IN hProv - Handle to a CSP
|
|
* IN hKey - Handle to a key
|
|
* IN dwParam - Parameter number
|
|
* IN pbData - Pointer to data
|
|
* IN dwFlags - Flags values
|
|
*
|
|
* Returns:
|
|
*/
|
|
BOOL WINAPI MyCPSetKeyParam(IN HCRYPTPROV hProv,
|
|
IN HCRYPTKEY hKey,
|
|
IN DWORD dwParam,
|
|
IN CONST BYTE *pbData,
|
|
IN DWORD dwFlags
|
|
)
|
|
{
|
|
BOOL bNew;
|
|
BOOL WriteCert;
|
|
BOOL CryptResp;
|
|
BYTE hCert;
|
|
BYTE KeyType;
|
|
BYTE hPrivKey;
|
|
BYTE *pbLabel;
|
|
BYTE *pbBuff1 = 0, *pbBuff2 = 0;
|
|
WORD wLabelLen, i;
|
|
DWORD lRet,
|
|
dwBuff1Len,
|
|
dwBuff2Len,
|
|
SlotNb;
|
|
GPK_OBJ TmpCert, TmpPrivKey;
|
|
// + NK 07.02.2001
|
|
PINCACHE_PINS Pins;
|
|
DWORD dwPinLength;
|
|
// -NK
|
|
|
|
if (!Context_exist(hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_UID);
|
|
}
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
/* Resident Key */
|
|
if (hKey == 0)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_KEY);
|
|
}
|
|
else if (hKey <= MAX_GPK_OBJ)
|
|
{
|
|
if (ProvCont[hProv].Flags & CRYPT_VERIFYCONTEXT)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_PERM);
|
|
}
|
|
|
|
if ((!Slot[SlotNb].GpkObject[hKey].IsCreated) ||
|
|
( Slot[SlotNb].GpkObject[hKey].FileId == 0))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_KEY);
|
|
}
|
|
|
|
switch (dwParam)
|
|
{
|
|
case KP_ADMIN_PIN:
|
|
RETURN(CRYPT_FAILED, E_NOTIMPL);
|
|
break;
|
|
|
|
case KP_KEYEXCHANGE_PIN:
|
|
case KP_SIGNATURE_PIN:
|
|
// Slot[SlotNb].ClearPin();
|
|
// Slot[SlotNb].SetPin( (char*)pbData );
|
|
PopulatePins( &Pins, (BYTE *)pbData, strlen( (char*)pbData ), NULL, 0 );
|
|
|
|
CallbackData sCallbackData;
|
|
sCallbackData.hProv = hProv;
|
|
sCallbackData.IsCoherent = TRUE;
|
|
|
|
if ( (lRet = Add_MSPinCache( &(Slot[SlotNb].hPinCacheHandle),
|
|
&Pins,
|
|
Callback_VerifyChangePin,
|
|
(void*)&sCallbackData )) != ERROR_SUCCESS )
|
|
{
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}
|
|
break;
|
|
|
|
case KP_CERTIFICATE:
|
|
if (!Read_Priv_Obj(hProv))
|
|
return CRYPT_FAILED;
|
|
|
|
// + NK 06.02.2001
|
|
// if ((ProvCont[hProv].Flags & CRYPT_SILENT) && (IsNullStr(Slot[SlotNb].GetPin())))
|
|
|
|
lRet = Query_MSPinCache( Slot[SlotNb].hPinCacheHandle,
|
|
NULL,
|
|
&dwPinLength );
|
|
|
|
if ( (lRet != ERROR_SUCCESS) && (lRet != ERROR_EMPTY) )
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
|
|
if ((ProvCont[hProv].Flags & CRYPT_SILENT) && (lRet == ERROR_EMPTY))
|
|
// - NK
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_SILENT_CONTEXT);
|
|
}
|
|
|
|
// Supports only X509 certificats
|
|
|
|
if ((IsNull(pbData)) || (pbData[0] != 0x30) ||(pbData[1] != 0x82))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_DATA);
|
|
}
|
|
|
|
/* Store Certificate value */
|
|
/* Try to found existing certificate */
|
|
KeyType = Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].pValue[0];
|
|
hCert = find_gpk_obj_tag_type(hProv,
|
|
TAG_CERTIFICATE,
|
|
KeyType,
|
|
0x00,
|
|
FALSE,
|
|
FALSE);
|
|
|
|
/* If not found create new object */
|
|
bNew = FALSE;
|
|
if (hCert == 0)
|
|
{
|
|
if (Slot[SlotNb].NbGpkObject >= MAX_GPK_OBJ)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
Slot[SlotNb].NbGpkObject++;
|
|
|
|
hCert = Slot[SlotNb].NbGpkObject;
|
|
bNew = TRUE;
|
|
}
|
|
else
|
|
{
|
|
DialogBox(g_hInstRes, TEXT("CONTDIALOG"), GetAppWindow(), ContDlgProc);
|
|
if (ContainerStatus == ABORT_OPERATION)
|
|
{
|
|
RETURN (CRYPT_FAILED, SCARD_W_CANCELLED_BY_USER);
|
|
}
|
|
}
|
|
|
|
/* Search associated private RSA key part */
|
|
if (KeyType == AT_KEYEXCHANGE)
|
|
{
|
|
hPrivKey = find_gpk_obj_tag_type(hProv,
|
|
TAG_RSA_PRIVATE,
|
|
KeyType,
|
|
0x00,
|
|
TRUE, // Exchange key
|
|
TRUE
|
|
);
|
|
}
|
|
else
|
|
{
|
|
hPrivKey = find_gpk_obj_tag_type(hProv,
|
|
TAG_RSA_PRIVATE,
|
|
KeyType,
|
|
0x00,
|
|
FALSE, // Signature key
|
|
TRUE
|
|
);
|
|
}
|
|
|
|
TmpCert = Slot[SlotNb].GpkObject[hCert];
|
|
|
|
for (i = 0; i < MAX_FIELD; i++)
|
|
{
|
|
Slot[SlotNb].GpkObject[hCert].Field[i].bReal = TRUE;
|
|
}
|
|
|
|
Slot[SlotNb].GpkObject[hCert].Tag = TAG_CERTIFICATE;
|
|
Slot[SlotNb].GpkObject[hCert].Flags = FLAG_VALUE | FLAG_KEY_TYPE | FLAG_LABEL |
|
|
FLAG_SUBJECT | FLAG_SERIAL_NUMBER |
|
|
FLAG_ISSUER | FLAG_ID | FLAG_MODIFIABLE;
|
|
if (bNew)
|
|
{
|
|
Slot[SlotNb].GpkObject[hCert].ObjId = Slot[SlotNb].NbGpkObject-1;
|
|
}
|
|
Slot[SlotNb].GpkObject[hCert].FileId = Slot[SlotNb].GpkObject[hKey].FileId;
|
|
Slot[SlotNb].GpkObject[hCert].PubKey = Slot[SlotNb].GpkObject[hKey].PubKey;
|
|
Slot[SlotNb].GpkObject[hCert].IsCreated = TRUE;
|
|
Slot[SlotNb].GpkObject[hCert].IsPrivate = FALSE;
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_VALUE].Len = (pbData[2] * 256) + pbData[3] + 4;
|
|
|
|
// TT 12/08/99: Keyset ID
|
|
if (!ProvCont[hProv].bLegacyKeyset)
|
|
{
|
|
Slot[SlotNb].GpkObject[hCert].Flags |= FLAG_KEYSET;
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_KEYSET].Len = 1;
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_KEYSET].pValue = (BYTE*)GMEM_Alloc(1);
|
|
if(IsNull(Slot[SlotNb].GpkObject[hCert].Field[POS_KEYSET].pValue))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_KEYSET].pValue[0] = ProvCont[hProv].keysetID;
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_KEYSET].bReal = TRUE;
|
|
}
|
|
|
|
// TT: END
|
|
|
|
// if (IsNotNull(GpkObject[hCert].Field[POS_VALUE].pValue))
|
|
// {
|
|
// This will be free later with TmpCert
|
|
// }
|
|
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_VALUE].pValue =
|
|
(BYTE*)GMEM_Alloc(Slot[SlotNb].GpkObject[hCert].Field[POS_VALUE].Len);
|
|
|
|
if (IsNull(Slot[SlotNb].GpkObject[hCert].Field[POS_VALUE].pValue))
|
|
{
|
|
Slot[SlotNb].GpkObject[hCert] = TmpCert;
|
|
--Slot[SlotNb].NbGpkObject; // Bug #1675/1676
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
memcpy(Slot[SlotNb].GpkObject[hCert].Field[POS_VALUE].pValue,
|
|
pbData,
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_VALUE].Len
|
|
);
|
|
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_VALUE].bReal = TRUE;
|
|
|
|
/* Type = Type of associated key */
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_KEY_TYPE].Len =
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].Len;
|
|
|
|
// if (IsNotNull(GpkObject[hCert].Field[POS_KEY_TYPE].pValue))
|
|
// {
|
|
// This will be free later with TmpCert
|
|
// }
|
|
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_KEY_TYPE].pValue =
|
|
(BYTE*)GMEM_Alloc(Slot[SlotNb].GpkObject[hCert].Field[POS_KEY_TYPE].Len);
|
|
|
|
if (IsNull(Slot[SlotNb].GpkObject[hCert].Field[POS_KEY_TYPE].pValue))
|
|
{
|
|
GMEM_Free(Slot[SlotNb].GpkObject[hCert].Field[POS_VALUE].pValue);
|
|
Slot[SlotNb].GpkObject[hCert] = TmpCert;
|
|
--Slot[SlotNb].NbGpkObject; // Bug #1675/1676
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
memcpy(Slot[SlotNb].GpkObject[hCert].Field[POS_KEY_TYPE].pValue,
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].pValue,
|
|
Slot[SlotNb].GpkObject[hKey].Field[POS_KEY_TYPE].Len
|
|
);
|
|
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_KEY_TYPE].bReal = TRUE;
|
|
|
|
/* Derive Label from certificate value for PKCS#11 compatibility */
|
|
|
|
if (MakeLabel( Slot[SlotNb].GpkObject[hCert].Field[POS_VALUE].pValue,
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_VALUE].Len,
|
|
0, &wLabelLen ) == RV_SUCCESS)
|
|
{
|
|
pbLabel = (BYTE*)GMEM_Alloc(wLabelLen);
|
|
|
|
if (IsNull(pbLabel))
|
|
{
|
|
GMEM_Free(Slot[SlotNb].GpkObject[hCert].Field[POS_KEY_TYPE].pValue);
|
|
GMEM_Free(Slot[SlotNb].GpkObject[hCert].Field[POS_VALUE].pValue);
|
|
Slot[SlotNb].GpkObject[hCert] = TmpCert;
|
|
--Slot[SlotNb].NbGpkObject; // Bug #1675/1676
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
MakeLabel(Slot[SlotNb].GpkObject[hCert].Field[POS_VALUE].pValue,
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_VALUE].Len,
|
|
pbLabel,
|
|
&wLabelLen
|
|
);
|
|
}
|
|
else
|
|
{
|
|
wLabelLen = 17;
|
|
pbLabel = (BYTE*)GMEM_Alloc(wLabelLen);
|
|
|
|
if (IsNull(pbLabel))
|
|
{
|
|
GMEM_Free(Slot[SlotNb].GpkObject[hCert].Field[POS_KEY_TYPE].pValue);
|
|
GMEM_Free(Slot[SlotNb].GpkObject[hCert].Field[POS_VALUE].pValue);
|
|
Slot[SlotNb].GpkObject[hCert] = TmpCert;
|
|
--Slot[SlotNb].NbGpkObject; // Bug #1675/1676
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
memcpy(pbLabel, "User's Digital ID", 17);
|
|
}
|
|
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_LABEL].Len = wLabelLen;
|
|
|
|
// if (IsNotNull(GpkObject[hCert].Field[POS_LABEL].pValue))
|
|
// {
|
|
// This will be free later with TmpCert
|
|
// }
|
|
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_LABEL].pValue = (BYTE*)GMEM_Alloc(wLabelLen);
|
|
|
|
if (IsNull(Slot[SlotNb].GpkObject[hCert].Field[POS_LABEL].pValue))
|
|
{
|
|
GMEM_Free(pbLabel);
|
|
GMEM_Free(Slot[SlotNb].GpkObject[hCert].Field[POS_KEY_TYPE].pValue);
|
|
GMEM_Free(Slot[SlotNb].GpkObject[hCert].Field[POS_VALUE].pValue);
|
|
Slot[SlotNb].GpkObject[hCert] = TmpCert;
|
|
--Slot[SlotNb].NbGpkObject; // Bug #1675/1676
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
memcpy(Slot[SlotNb].GpkObject[hCert].Field[POS_LABEL].pValue,
|
|
pbLabel,
|
|
wLabelLen
|
|
);
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_LABEL].bReal = TRUE;
|
|
|
|
TmpPrivKey = Slot[SlotNb].GpkObject[hPrivKey];
|
|
|
|
Slot[SlotNb].GpkObject[hPrivKey].Flags = Slot[SlotNb].GpkObject[hPrivKey].Flags | FLAG_LABEL;
|
|
Slot[SlotNb].GpkObject[hPrivKey].Field[POS_LABEL].Len = wLabelLen;
|
|
|
|
// if (IsNotNull(GpkObject[hPrivKey].Field[POS_LABEL].pValue))
|
|
// {
|
|
// This will be free later with TmpPrivKey
|
|
// }
|
|
|
|
Slot[SlotNb].GpkObject[hPrivKey].Field[POS_LABEL].pValue = (BYTE*)GMEM_Alloc(wLabelLen);
|
|
|
|
if (IsNull(Slot[SlotNb].GpkObject[hPrivKey].Field[POS_LABEL].pValue))
|
|
{
|
|
GMEM_Free(Slot[SlotNb].GpkObject[hCert].Field[POS_LABEL].pValue);
|
|
GMEM_Free(pbLabel);
|
|
GMEM_Free(Slot[SlotNb].GpkObject[hCert].Field[POS_KEY_TYPE].pValue);
|
|
GMEM_Free(Slot[SlotNb].GpkObject[hCert].Field[POS_VALUE].pValue);
|
|
|
|
Slot[SlotNb].GpkObject[hPrivKey] = TmpPrivKey;
|
|
Slot[SlotNb].GpkObject[hCert] = TmpCert;
|
|
--Slot[SlotNb].NbGpkObject; // Bug #1675/1676
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
memcpy(Slot[SlotNb].GpkObject[hPrivKey].Field[POS_LABEL].pValue,
|
|
pbLabel,
|
|
wLabelLen
|
|
);
|
|
Slot[SlotNb].GpkObject[hPrivKey].Field[POS_LABEL].bReal = TRUE;
|
|
GMEM_Free(pbLabel);
|
|
|
|
/* Set automatic fields for PKCS#11 compatibility */
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_ID].Len = 0;
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_ID].bReal = FALSE;
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_SUBJECT].Len = 0;
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_SUBJECT].bReal = FALSE;
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_ISSUER].Len = 0;
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_ISSUER].bReal = FALSE;
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_SERIAL_NUMBER].Len = 0;
|
|
Slot[SlotNb].GpkObject[hCert].Field[POS_SERIAL_NUMBER].bReal = FALSE;
|
|
|
|
/* Set automatic fields of assocoiated key for PKCS#11 */
|
|
Slot[SlotNb].GpkObject[hPrivKey].Flags = Slot[SlotNb].GpkObject[hPrivKey].Flags | FLAG_SUBJECT;
|
|
Slot[SlotNb].GpkObject[hPrivKey].Field[POS_SUBJECT].Len = 0;
|
|
Slot[SlotNb].GpkObject[hPrivKey].Field[POS_SUBJECT].bReal = FALSE;
|
|
|
|
CspFlags = ProvCont[hProv].Flags;
|
|
|
|
|
|
WriteCert = TRUE;
|
|
pbBuff1 = (BYTE*)GMEM_Alloc (MAX_GPK_PUBLIC);
|
|
|
|
if (IsNull(pbBuff1))
|
|
{
|
|
WriteCert = FALSE;
|
|
}
|
|
|
|
dwBuff1Len = MAX_GPK_PUBLIC;
|
|
if (WriteCert && (!prepare_write_gpk_objects (hProv, pbBuff1, &dwBuff1Len, FALSE)))
|
|
{
|
|
WriteCert = FALSE;
|
|
GMEM_Free (pbBuff1);
|
|
}
|
|
|
|
if (WriteCert)
|
|
{
|
|
pbBuff2 = (BYTE*)GMEM_Alloc (MAX_GPK_PRIVATE);
|
|
if (IsNull(pbBuff2))
|
|
{
|
|
WriteCert = FALSE;
|
|
GMEM_Free (pbBuff1);
|
|
}
|
|
}
|
|
|
|
dwBuff2Len = MAX_GPK_PRIVATE;
|
|
if (WriteCert && (!prepare_write_gpk_objects (hProv, pbBuff2, &dwBuff2Len, TRUE)))
|
|
{
|
|
WriteCert = FALSE;
|
|
GMEM_Free (pbBuff1);
|
|
GMEM_Free (pbBuff2);
|
|
}
|
|
|
|
if (!WriteCert)
|
|
{
|
|
// restore the info. the new certificate is too large
|
|
|
|
GMEM_Free(Slot[SlotNb].GpkObject[hCert].Field[POS_VALUE].pValue);
|
|
GMEM_Free(Slot[SlotNb].GpkObject[hCert].Field[POS_KEY_TYPE].pValue);
|
|
GMEM_Free(Slot[SlotNb].GpkObject[hCert].Field[POS_LABEL].pValue);
|
|
GMEM_Free(Slot[SlotNb].GpkObject[hPrivKey].Field[POS_LABEL].pValue);
|
|
|
|
Slot[SlotNb].GpkObject[hCert] = TmpCert;
|
|
Slot[SlotNb].GpkObject[hPrivKey] = TmpPrivKey;
|
|
|
|
--Slot[SlotNb].NbGpkObject; // Bug #1675/1676
|
|
RETURN (CRYPT_FAILED, SCARD_E_WRITE_TOO_MANY);
|
|
}
|
|
|
|
if (IsNotNull(TmpCert.Field[POS_VALUE].pValue))
|
|
{
|
|
GMEM_Free(TmpCert.Field[POS_VALUE].pValue);
|
|
}
|
|
|
|
if (IsNotNull(TmpCert.Field[POS_KEY_TYPE].pValue))
|
|
{
|
|
GMEM_Free(TmpCert.Field[POS_KEY_TYPE].pValue);
|
|
}
|
|
|
|
if (IsNotNull(TmpCert.Field[POS_LABEL].pValue))
|
|
{
|
|
GMEM_Free(TmpCert.Field[POS_LABEL].pValue);
|
|
}
|
|
|
|
if (IsNotNull(TmpPrivKey.Field[POS_LABEL].pValue))
|
|
{
|
|
GMEM_Free(TmpPrivKey.Field[POS_LABEL].pValue);
|
|
}
|
|
|
|
if (!write_gpk_objects(hProv, pbBuff1, dwBuff1Len, FALSE, FALSE))
|
|
{
|
|
lRet = GetLastError();
|
|
GMEM_Free (pbBuff1);
|
|
GMEM_Free (pbBuff2);
|
|
--Slot[SlotNb].NbGpkObject; // Bug #1675/1676
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
if (!write_gpk_objects(hProv, pbBuff2, dwBuff2Len, FALSE, TRUE))
|
|
{
|
|
lRet = GetLastError();
|
|
Select_MF(hProv);
|
|
GMEM_Free (pbBuff1);
|
|
GMEM_Free (pbBuff2);
|
|
--Slot[SlotNb].NbGpkObject; // Bug #1675/1676
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
}
|
|
|
|
GMEM_Free (pbBuff1);
|
|
GMEM_Free (pbBuff2);
|
|
|
|
break;
|
|
|
|
default:
|
|
RETURN (CRYPT_FAILED, NTE_BAD_TYPE);
|
|
}
|
|
|
|
}
|
|
|
|
/* Session Key */
|
|
else if (key_exist(hKey-MAX_GPK_OBJ, hProv))
|
|
{
|
|
/* Set Key Parameter in Microsoft RSA Base Module */
|
|
CryptResp = CryptSetKeyParam(TmpObject[hKey-MAX_GPK_OBJ].hKeyBase,
|
|
dwParam,
|
|
pbData,
|
|
dwFlags
|
|
);
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
}
|
|
/* Bad Key */
|
|
else
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_KEY);
|
|
}
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
Data Encryption Functions
|
|
*******************************************************************************/
|
|
|
|
/*
|
|
- CPDecrypt
|
|
-
|
|
* Purpose:
|
|
* Decrypt data
|
|
*
|
|
*
|
|
* Parameters:
|
|
* IN hProv - Handle to the CSP user
|
|
* IN hKey - Handle to the key
|
|
* IN hHash - Optional handle to a hash
|
|
* IN Final - Boolean indicating if this is the final
|
|
* block of ciphertext
|
|
* IN dwFlags - Flags values
|
|
* IN OUT pbData - Data to be decrypted
|
|
* IN OUT pdwDataLen - Pointer to the length of the data to be
|
|
* decrypted
|
|
*
|
|
* Returns:
|
|
*/
|
|
BOOL WINAPI MyCPDecrypt(IN HCRYPTPROV hProv,
|
|
IN HCRYPTKEY hKey,
|
|
IN HCRYPTHASH hHash,
|
|
IN BOOL Final,
|
|
IN DWORD dwFlags,
|
|
IN OUT BYTE *pbData,
|
|
IN OUT DWORD *pdwDataLen
|
|
)
|
|
|
|
{
|
|
BOOL CryptResp;
|
|
HCRYPTKEY hDecKey;
|
|
|
|
if (!Context_exist(hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_UID);
|
|
}
|
|
|
|
if ((hKey <= MAX_GPK_OBJ) || (!key_exist(hKey-MAX_GPK_OBJ, hProv)))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_KEY);
|
|
}
|
|
else
|
|
{
|
|
hDecKey = TmpObject[hKey-MAX_GPK_OBJ].hKeyBase;
|
|
}
|
|
|
|
if (!hash_exist(hHash, hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_HASH);
|
|
}
|
|
|
|
CryptResp = CryptDecrypt(hDecKey,
|
|
hHashGpk[hHash].hHashBase,
|
|
Final,
|
|
dwFlags,
|
|
pbData,
|
|
pdwDataLen
|
|
);
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
/*
|
|
- CPEncrypt
|
|
-
|
|
* Purpose:
|
|
* Encrypt data
|
|
*
|
|
*
|
|
* Parameters:
|
|
* IN hProv - Handle to the CSP user
|
|
* IN hKey - Handle to the key
|
|
* IN hHash - Optional handle to a hash
|
|
* IN Final - Boolean indicating if this is the final
|
|
* block of plaintext
|
|
* IN dwFlags - Flags values
|
|
* IN OUT pbData - Data to be encrypted
|
|
* IN OUT pdwDataLen - Pointer to the length of the data to be
|
|
* encrypted
|
|
* IN dwBufLen - Size of Data buffer
|
|
*
|
|
* Returns:
|
|
*/
|
|
BOOL WINAPI MyCPEncrypt(IN HCRYPTPROV hProv,
|
|
IN HCRYPTKEY hKey,
|
|
IN HCRYPTHASH hHash,
|
|
IN BOOL Final,
|
|
IN DWORD dwFlags,
|
|
IN OUT BYTE *pbData,
|
|
IN OUT DWORD *pdwDataLen,
|
|
IN DWORD dwBufLen
|
|
)
|
|
{
|
|
BOOL CryptResp;
|
|
HCRYPTKEY hEncKey;
|
|
|
|
if (!Context_exist(hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_UID);
|
|
}
|
|
|
|
if ((hKey <= MAX_GPK_OBJ) || (!key_exist(hKey-MAX_GPK_OBJ, hProv)))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_KEY);
|
|
}
|
|
else
|
|
{
|
|
hEncKey = TmpObject[hKey-MAX_GPK_OBJ].hKeyBase;
|
|
}
|
|
|
|
if (!hash_exist(hHash, hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_HASH);
|
|
}
|
|
|
|
CryptResp = CryptEncrypt(hEncKey,
|
|
hHashGpk[hHash].hHashBase,
|
|
Final,
|
|
dwFlags,
|
|
pbData,
|
|
pdwDataLen,
|
|
dwBufLen
|
|
);
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
Hashing and Digital Signature Functions
|
|
*******************************************************************************/
|
|
|
|
/*
|
|
- MyCPCreateHash
|
|
-
|
|
* Purpose:
|
|
* initate the hashing of a stream of data
|
|
*
|
|
*
|
|
* Parameters:
|
|
* IN hUID - Handle to the user identifcation
|
|
* IN Algid - Algorithm identifier of the hash algorithm
|
|
* to be used
|
|
* IN hKey - Optional key for MAC algorithms
|
|
* IN dwFlags - Flags values
|
|
* OUT pHash - Handle to hash object
|
|
*
|
|
* Returns:
|
|
*/
|
|
BOOL WINAPI MyCPCreateHash(IN HCRYPTPROV hProv,
|
|
IN ALG_ID Algid,
|
|
IN HCRYPTKEY hKey,
|
|
IN DWORD dwFlags,
|
|
OUT HCRYPTHASH *phHash
|
|
)
|
|
{
|
|
BOOL CryptResp;
|
|
HCRYPTKEY hKeyMac;
|
|
|
|
if (!Context_exist(hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_UID);
|
|
}
|
|
|
|
*phHash = find_hash_free();
|
|
if ((*phHash) == 0)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_NO_MEMORY);
|
|
}
|
|
|
|
hKeyMac = 0;
|
|
if ((Algid == CALG_MAC) || (Algid == CALG_HMAC) )
|
|
{
|
|
if ((hKey <= MAX_GPK_OBJ) || (!key_exist(hKey - MAX_GPK_OBJ, hProv)))
|
|
{
|
|
*phHash = 0;
|
|
RETURN (CRYPT_FAILED, NTE_BAD_KEY);
|
|
}
|
|
else
|
|
{
|
|
hKeyMac = TmpObject[hKey-MAX_GPK_OBJ].hKeyBase;
|
|
}
|
|
}
|
|
|
|
CryptResp = CryptCreateHash(hProvBase,
|
|
Algid,
|
|
hKeyMac,
|
|
dwFlags,
|
|
&(hHashGpk[*phHash].hHashBase)
|
|
);
|
|
if (!CryptResp)
|
|
{
|
|
*phHash = 0;
|
|
return CRYPT_FAILED;
|
|
}
|
|
|
|
hHashGpk[*phHash].hProv = hProv;
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
|
|
/*
|
|
- MyCPDestroyHash
|
|
-
|
|
* Purpose:
|
|
* Destroy the hash object
|
|
*
|
|
*
|
|
* Parameters:
|
|
* IN hProv - Handle to the user identifcation
|
|
* IN hHash - Handle to hash object
|
|
*
|
|
* Returns:
|
|
*/
|
|
BOOL WINAPI MyCPDestroyHash(IN HCRYPTPROV hProv,
|
|
IN HCRYPTHASH hHash
|
|
)
|
|
{
|
|
BOOL CryptResp;
|
|
|
|
if (!Context_exist(hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_UID);
|
|
}
|
|
|
|
if (!hash_exist(hHash, hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_HASH);
|
|
}
|
|
|
|
/* Destroy Microsoft RSA Base Hash */
|
|
CryptResp = CryptDestroyHash(hHashGpk[hHash].hHashBase);
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
|
|
hHashGpk[hHash].hHashBase = 0;
|
|
hHashGpk[hHash].hProv = 0;
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
|
|
/*
|
|
- MyCPGetHashParam
|
|
-
|
|
* Purpose:
|
|
* Allows applications to get various aspects of the
|
|
* operations of a hash
|
|
*
|
|
* Parameters:
|
|
* IN hProv - Handle to a CSP
|
|
* IN hHash - Handle to a hash
|
|
* IN dwParam - Parameter number
|
|
* IN pbData - Pointer to data
|
|
* IN pdwDataLen - Length of parameter data
|
|
* IN dwFlags - Flags values
|
|
*
|
|
* Returns:
|
|
*/
|
|
BOOL WINAPI MyCPGetHashParam(IN HCRYPTPROV hProv,
|
|
IN HCRYPTHASH hHash,
|
|
IN DWORD dwParam,
|
|
IN BYTE *pbData,
|
|
IN DWORD *pdwDataLen,
|
|
IN DWORD dwFlags
|
|
)
|
|
{
|
|
BOOL CryptResp;
|
|
|
|
if (!Context_exist(hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_UID);
|
|
}
|
|
|
|
if (!hash_exist(hHash, hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_HASH);
|
|
}
|
|
|
|
CryptResp = CryptGetHashParam(hHashGpk[hHash].hHashBase,
|
|
dwParam,
|
|
pbData,
|
|
pdwDataLen,
|
|
dwFlags
|
|
);
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
|
|
/*
|
|
- MyCPHashData
|
|
-
|
|
* Purpose:
|
|
* Compute the cryptograghic hash on a stream of data
|
|
*
|
|
*
|
|
* Parameters:
|
|
* IN hProv - Handle to the user identifcation
|
|
* IN hHash - Handle to hash object
|
|
* IN pbData - Pointer to data to be hashed
|
|
* IN dwDataLen - Length of the data to be hashed
|
|
* IN dwFlags - Flags values
|
|
* IN pdwMaxLen - Maximum length of the data stream the CSP
|
|
* module may handle
|
|
*
|
|
* Returns:
|
|
*/
|
|
BOOL WINAPI MyCPHashData(IN HCRYPTPROV hProv,
|
|
IN HCRYPTHASH hHash,
|
|
IN CONST BYTE *pbData,
|
|
IN DWORD dwDataLen,
|
|
IN DWORD dwFlags
|
|
)
|
|
{
|
|
BOOL CryptResp;
|
|
|
|
if (!Context_exist(hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_UID);
|
|
}
|
|
|
|
if (!hash_exist(hHash, hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_HASH);
|
|
}
|
|
|
|
/* Hash Data with Microsoft RSA Base */
|
|
CryptResp = CryptHashData(hHashGpk[hHash].hHashBase,
|
|
pbData,
|
|
dwDataLen,
|
|
dwFlags);
|
|
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
|
|
/*
|
|
- CPHashSessionKey
|
|
-
|
|
* Purpose:
|
|
* Compute the cryptograghic hash on a key object.
|
|
*
|
|
*
|
|
* Parameters:
|
|
* IN hProv - Handle to the user identifcation
|
|
* IN hHash - Handle to hash object
|
|
* IN hKey - Handle to a key object
|
|
* IN dwFlags - Flags values
|
|
*
|
|
* Returns:
|
|
* CRYPT_FAILED
|
|
* CRYPT_SUCCEED
|
|
*/
|
|
BOOL WINAPI MyCPHashSessionKey(IN HCRYPTPROV hProv,
|
|
IN HCRYPTHASH hHash,
|
|
IN HCRYPTKEY hKey,
|
|
IN DWORD dwFlags
|
|
)
|
|
{
|
|
BOOL CryptResp;
|
|
HCRYPTKEY hTmpKey;
|
|
|
|
if (!Context_exist(hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_UID);
|
|
}
|
|
|
|
if (!hash_exist(hHash, hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_HASH);
|
|
}
|
|
|
|
if (hKey <= MAX_GPK_OBJ)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_KEY);
|
|
}
|
|
|
|
hTmpKey = hKey - MAX_GPK_OBJ;
|
|
|
|
if (!key_exist(hTmpKey, hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_KEY);
|
|
}
|
|
|
|
/* Hash Data with Microsoft RSA Base */
|
|
CryptResp = CryptHashSessionKey(hHashGpk[hHash].hHashBase,
|
|
TmpObject[hTmpKey].hKeyBase,
|
|
dwFlags
|
|
);
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
|
|
/*
|
|
- MyCPSetHashParam
|
|
-
|
|
* Purpose:
|
|
* Allows applications to customize various aspects of the
|
|
* operations of a hash
|
|
*
|
|
* Parameters:
|
|
* IN hProv - Handle to a CSP
|
|
* IN hHash - Handle to a hash
|
|
* IN dwParam - Parameter number
|
|
* IN pbData - Pointer to data
|
|
* IN dwFlags - Flags values
|
|
*
|
|
* Returns:
|
|
*/
|
|
BOOL WINAPI MyCPSetHashParam(IN HCRYPTPROV hProv,
|
|
IN HCRYPTHASH hHash,
|
|
IN DWORD dwParam,
|
|
IN CONST BYTE *pbData,
|
|
IN DWORD dwFlags
|
|
)
|
|
{
|
|
BOOL CryptResp;
|
|
|
|
if (!Context_exist(hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_UID);
|
|
}
|
|
|
|
if (!hash_exist(hHash, hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_HASH);
|
|
}
|
|
|
|
/* Set Hash parameter with Microsoft RSA Base */
|
|
CryptResp = CryptSetHashParam(hHashGpk[hHash].hHashBase,
|
|
dwParam,
|
|
pbData,
|
|
dwFlags
|
|
);
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
|
|
/*
|
|
- MyCPSignHash
|
|
-
|
|
* Purpose:
|
|
* Create a digital signature from a hash
|
|
*
|
|
*
|
|
* Parameters:
|
|
* IN hProv - Handle to the user identifcation
|
|
* IN hHash - Handle to hash object
|
|
* IN Algid - Algorithm identifier of the signature
|
|
* algorithm to be used
|
|
* IN sDescription - Description of data to be signed
|
|
* IN dwFlags - Flags values
|
|
* OUT pbSignture - Pointer to signature data
|
|
* OUT dwHashLen - Pointer to the len of the signature data
|
|
*
|
|
* Returns:
|
|
*/
|
|
BOOL WINAPI MyCPSignHash(IN HCRYPTPROV hProv,
|
|
IN HCRYPTHASH hHash,
|
|
IN DWORD dwKeySpec,
|
|
IN LPCWSTR sDescription,
|
|
IN DWORD dwFlags,
|
|
OUT BYTE *pbSignature,
|
|
OUT DWORD *pdwSigLen
|
|
)
|
|
{
|
|
DWORD lRet;
|
|
DWORD SlotNb;
|
|
BOOL CryptResp;
|
|
DWORD dwLen;
|
|
BYTE GpkKeySize;
|
|
BYTE HashMode;
|
|
HCRYPTKEY hKey;
|
|
BYTE TmpHashValue[64];
|
|
// + NK 07.02.2001
|
|
DWORD dwPinLength;
|
|
// -NK
|
|
|
|
if (!Context_exist(hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_UID);
|
|
}
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
if (dwFlags != 0)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_FLAGS);
|
|
}
|
|
|
|
// returns same value as aux csp
|
|
if (dwKeySpec != AT_KEYEXCHANGE && dwKeySpec != AT_SIGNATURE)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_ALGID);
|
|
}
|
|
|
|
|
|
/* sDescription is not supported */
|
|
if (IsNotNullStr(sDescription))
|
|
{
|
|
RETURN(CRYPT_FAILED, ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
if (!hash_exist(hHash, hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_HASH);
|
|
}
|
|
|
|
HashMode = GPKHashMode (hHash);
|
|
if (HashMode == 0x00)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_HASH);
|
|
}
|
|
|
|
/* Select Key */
|
|
CryptResp = MyCPGetUserKey(hProv, dwKeySpec, &hKey);
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
|
|
if (!(Slot[SlotNb].GpkObject[hKey].Flags & FLAG_SIGN))
|
|
{
|
|
*pdwSigLen = 0;
|
|
RETURN(CRYPT_FAILED, NTE_BAD_KEY);
|
|
}
|
|
|
|
GpkKeySize = Slot[SlotNb].GpkPubKeys[Slot[SlotNb].GpkObject[hKey].FileId - GPK_FIRST_KEY].KeySize;
|
|
if (GpkKeySize == 0)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_KEY);
|
|
}
|
|
|
|
if (IsNull(pbSignature) || (0 == *pdwSigLen))
|
|
{
|
|
*pdwSigLen = GpkKeySize;
|
|
RETURN (CRYPT_SUCCEED, 0 );
|
|
}
|
|
|
|
if (GpkKeySize > *pdwSigLen)
|
|
{
|
|
*pdwSigLen = GpkKeySize;
|
|
RETURN (CRYPT_FAILED, ERROR_MORE_DATA);
|
|
}
|
|
|
|
// + NK 06.02.2001
|
|
// if ((ProvCont[hProv].Flags & CRYPT_SILENT) && (IsNullStr(Slot[SlotNb].GetPin())))
|
|
lRet = Query_MSPinCache( Slot[SlotNb].hPinCacheHandle,
|
|
NULL,
|
|
&dwPinLength );
|
|
|
|
if ( (lRet != ERROR_SUCCESS) && (lRet != ERROR_EMPTY) )
|
|
RETURN (CRYPT_FAILED, lRet);
|
|
|
|
if ((ProvCont[hProv].Flags & CRYPT_SILENT) && (lRet == ERROR_EMPTY))
|
|
// - NK
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_SILENT_CONTEXT);
|
|
}
|
|
|
|
// Verify the PINs
|
|
if (!PIN_Validation(hProv)) {
|
|
return CRYPT_FAILED;
|
|
}
|
|
|
|
if (!VerifyDivPIN(hProv, TRUE))
|
|
return CRYPT_FAILED;
|
|
|
|
/* Card Select Context for RSA with specified Hash type */
|
|
bSendBuffer[0] = 0x80; //CLA
|
|
bSendBuffer[1] = 0xA6; //INS
|
|
bSendBuffer[2] = Slot[SlotNb].GpkObject[hKey].FileId; //P1
|
|
bSendBuffer[3] = HashMode; //P2
|
|
cbSendLength = 4;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x9000,0x00))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_KEY_STATE);
|
|
}
|
|
|
|
/* Force Calculation of Hash Value */
|
|
dwLen = sizeof(TmpHashValue);
|
|
CryptResp = CryptGetHashParam(hHashGpk[hHash].hHashBase,
|
|
HP_HASHVAL,
|
|
TmpHashValue,
|
|
&dwLen,
|
|
0);
|
|
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
|
|
r_memcpy(&bSendBuffer[5], TmpHashValue, dwLen);
|
|
/* Send hash Data with only one command */
|
|
bSendBuffer[0] = 0x80; //CLA
|
|
bSendBuffer[1] = 0xEA; //INS
|
|
bSendBuffer[2] = 0x00; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = (BYTE)dwLen; //Li
|
|
cbSendLength = dwLen + 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
|
|
if (SCARDPROBLEM(lRet,0x9000,0x00))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_SIGNATURE);
|
|
}
|
|
|
|
/* Get signature */
|
|
bSendBuffer[0] = 0x80; //CLA
|
|
bSendBuffer[1] = 0x86; //INS
|
|
bSendBuffer[2] = 0x00; //P1
|
|
bSendBuffer[3] = 0x00; //P2
|
|
bSendBuffer[4] = GpkKeySize; //Lo
|
|
cbSendLength = 5;
|
|
|
|
cbRecvLength = sizeof(bRecvBuffer);
|
|
lRet = SCardTransmit( ProvCont[hProv].hCard, SCARD_PCI_T0, bSendBuffer,
|
|
cbSendLength, 0, bRecvBuffer, &cbRecvLength );
|
|
if (SCARDPROBLEM(lRet,0x9000,bSendBuffer[4]))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_SIGNATURE);
|
|
}
|
|
|
|
cbRecvLength = cbRecvLength - 2;
|
|
|
|
*pdwSigLen = cbRecvLength;
|
|
|
|
memcpy(pbSignature, bRecvBuffer, cbRecvLength);
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|
|
|
|
/*
|
|
- MyCPVerifySignature
|
|
-
|
|
* Purpose:
|
|
* Used to verify a signature against a hash object
|
|
*
|
|
*
|
|
* Parameters:
|
|
* IN hProv - Handle to the user identifcation
|
|
* IN hHash - Handle to hash object
|
|
* IN pbSignture - Pointer to signature data
|
|
* IN dwSigLen - Length of the signature data
|
|
* IN hPubKey - Handle to the public key for verifying
|
|
* the signature
|
|
* IN Algid - Algorithm identifier of the signature
|
|
* algorithm to be used
|
|
* IN sDescription - Description of data to be signed
|
|
* IN dwFlags - Flags values
|
|
*
|
|
* Returns:
|
|
*/
|
|
BOOL WINAPI MyCPVerifySignature(IN HCRYPTPROV hProv,
|
|
IN HCRYPTHASH hHash,
|
|
IN CONST BYTE *pbSignature,
|
|
IN DWORD dwSigLen,
|
|
IN HCRYPTKEY hPubKey,
|
|
IN LPCWSTR sDescription,
|
|
IN DWORD dwFlags
|
|
)
|
|
{
|
|
DWORD SlotNb;
|
|
BOOL CryptResp;
|
|
HCRYPTKEY hTmpKey;
|
|
|
|
if (!Context_exist(hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_UID);
|
|
}
|
|
|
|
SlotNb = ProvCont[hProv].Slot;
|
|
|
|
if (!hash_exist(hHash, hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_HASH);
|
|
}
|
|
|
|
if (hPubKey <= MAX_GPK_OBJ)
|
|
{
|
|
if ((ProvCont[hProv].Flags & CRYPT_VERIFYCONTEXT) &&
|
|
(ProvCont[hProv].isContNameNullBlank))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_PERM);
|
|
}
|
|
|
|
if (( !Slot[SlotNb].GpkObject[hPubKey].IsCreated) ||
|
|
( (Slot[SlotNb].GpkObject[hPubKey].Tag != TAG_RSA_PUBLIC ) &&
|
|
(Slot[SlotNb].GpkObject[hPubKey].Tag != TAG_RSA_PRIVATE) )
|
|
|
|
)
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_KEY);
|
|
}
|
|
|
|
HCRYPTKEY hVerKey;
|
|
if ((Slot[SlotNb].GpkObject[hPubKey].Field[POS_KEY_TYPE].Len == 0) ||
|
|
((Slot[SlotNb].GpkObject[hPubKey].Field[POS_KEY_TYPE].pValue[0] != AT_KEYEXCHANGE) &&
|
|
(Slot[SlotNb].GpkObject[hPubKey].Field[POS_KEY_TYPE].pValue[0] != AT_SIGNATURE)))
|
|
{
|
|
RETURN(CRYPT_FAILED, NTE_BAD_KEY);
|
|
}
|
|
|
|
if (Slot[SlotNb].GpkObject[hPubKey].Field[POS_KEY_TYPE].pValue[0] == AT_KEYEXCHANGE)
|
|
{
|
|
hVerKey = ProvCont[hProv].hRSAKEK;
|
|
}
|
|
else
|
|
{
|
|
hVerKey = ProvCont[hProv].hRSASign;
|
|
}
|
|
|
|
CryptResp = CryptVerifySignature(hHashGpk[hHash].hHashBase,
|
|
pbSignature,
|
|
dwSigLen,
|
|
hVerKey, //Slot[SlotNb].GpkObject[hPubKey].hKeyBase,
|
|
(LPCTSTR)sDescription,
|
|
dwFlags);
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
}
|
|
else
|
|
{
|
|
hTmpKey = hPubKey - MAX_GPK_OBJ;
|
|
|
|
if (!key_exist(hTmpKey, hProv))
|
|
{
|
|
RETURN (CRYPT_FAILED, NTE_BAD_KEY);
|
|
}
|
|
|
|
/* Verify Signature with Microsoft RSA Base Module */
|
|
CryptResp = CryptVerifySignature(hHashGpk[hHash].hHashBase,
|
|
pbSignature,
|
|
dwSigLen,
|
|
TmpObject[hTmpKey].hKeyBase,
|
|
(LPCTSTR)sDescription,
|
|
dwFlags);
|
|
if (!CryptResp)
|
|
return CRYPT_FAILED;
|
|
}
|
|
|
|
RETURN (CRYPT_SUCCEED, 0);
|
|
}
|