SCARDATH.CPP

// SCardAth.cpp : Implementation of CSCardAuth 

//////////////////////////////////////////////////////////////////////////
//
// Includes
//
#include "stdafx.h"
#include "SCardCom.h"
#include "SCardAth.h"
#include "SCardDef.h"

///////////////////////////////////////////////////////////////////////////
// Macros
//
#ifdef _DEBUG
#define TRACE_STR(name,sz) \
TRACE(_T("SCardCom.DLL: CSCardAuth::%s: %s\n"), name, sz)
#define TRACE_CODE(name,code) \
TRACE(_T("SCardCom.DLL: CSCardAuth::%s: error = 0x%x\n"), name, code)
#define TRACE_CATCH(name,code)TRACE_CODE(name,code)
#define TRACE_CATCH_UNKNOWN(name)TRACE_STR(name,_T("An unidentified exception has occurred!"))
#else
#define TRACE_STR(name,sz)((void)0)
#define TRACE_CODE(name,code)((void)0)
#define TRACE_CATCH(name,code)((void)0)
#define TRACE_CATCH_UNKNOWN(name)((void)0)
#endif // _DEBUG

/////////////////////////////////////////////////////////////////////////////
// CSCardAuth

/*++

CSCardAuth::FinalConstruct:

This routine defines a final constructor that is called after the constructor
for the template class is called.

Arguments:

None

Return Value:

A HRESULT value indicating the status of the requested action.

ReturnMeaning
=============
S_OKOperation completed successfully.
S_FALSEUnknown error occurred.
E_OUTOFMEMORYThere is not enough memory in this process to
satisfy the request.
E_FAILUnspecified error.
E_INVALIDARGOne or more arguments are invalid.
E_UNEXPECTEDUnexpected event occurred in this function.

Author:


--*/

HRESULT CSCardAuth::FinalConstruct()
{
// Locals.
HRESULT hresult = S_OK;

try {
m_Manage = NULL;
}

catch (...) {
hresult = E_UNEXPECTED;
TRACE_CATCH_UNKNOWN(_T("GetChallenge"));
}

return (hresult);
}


/*++

CSCardAuth::FinalRelease:

This routine defines a final release.

Arguments:

None

Return Value:

A HRESULT value indicating the status of the requested action.

ReturnMeaning
=============
S_OKOperation completed successfully.
S_FALSEUnknown error occurred.
E_OUTOFMEMORYThere is not enough memory in this process to
satisfy the request.
E_FAILUnspecified error.
E_INVALIDARGOne or more arguments are invalid.
E_UNEXPECTEDUnexpected event occurred in this function.

Author:

--*/

HRESULT CSCardAuth::FinalRelease()
{
// Locals.
HRESULT hresult = S_OK;

try {
// Decrement the reference count on the "creation" object
if (m_Manage != NULL)
m_Manage->Release();
}

catch (...) {
}

return (hresult);
}


/////////////////////////////////////////////////////////////////////////////
//
// ISCardAuth Methods
//


/*++

CSCardAuth::APP_Auth

This method allows an application to athenticate itself to the ICC
using a Challange/signature protocol.

Arguments:

lAlogID- specifies the algorithm to be used in the authentcation
process

pParam - IByteBuffer containing vendor specific parameters of the
authentication process

pBuffer - contains data required for authentication.

Return Value:

A HRESULT value indicating the status of the requested action.

ReturnMeaning
=============
S_OKOperation completed successfully.
S_FALSEUnknown error occurred.
E_OUTOFMEMORYThere is not enough memory in this process to
satisfy the request.
E_FAILUnspecified error.
E_INVALIDARGOne or more arguments are invalid.
E_UNEXPECTEDUnexpected event occurred in this function.

Author:

--*/

STDMETHODIMP CSCardAuth::APP_Auth(
long lAlgorID,
LPBYTEBUFFER pParam,
LPBYTEBUFFER pBuffer)
{
//locals
HRESULThresult = S_OK;
LPSCARDCMDpCmd = NULL;

try {
m_lAlgorID = lAlgorID;

// Is internal pointer to "Creation Class" valid
if (m_Manage == NULL)
throw ( (HRESULT) E_FAIL );

// Must have valid pointer...
if (pBuffer == NULL)
throw ( (HRESULT) E_POINTER );

// Create cmd object
hresult = m_Manage->CreateCmdObject(&pCmd);
if (FAILED(hresult))
throw (hresult);

// Do internal Authenticate
hresult = m_Manage->m_pISCardISO7816->ExternalAuthenticate((BYTE) lAlgorID,
NULL,
pBuffer,
&pCmd);
if (FAILED(hresult))
throw (hresult);
// Force correct class id
hresult = pCmd->put_ClassId(VENDOR_CLASS_ID);
if (FAILED(hresult))
throw (hresult);

hresult = m_Manage->m_pISCard->LockSCard();
if (FAILED(hresult))
throw (hresult);
hresult = m_Manage->m_pISCard->Transaction(&pCmd);
if (FAILED(hresult))
throw (hresult);
hresult = m_Manage->m_pISCard->UnlockSCard(LEAVE);
if (FAILED(hresult))
throw(hresult);

//interpret results and return
hresult = pCmd->get_ApduReplyLength(&m_lReplyLength);
if (FAILED(hresult))
throw (hresult);
hresult = pCmd->get_ReplyStatus( &m_wReplyStatus );
if (FAILED(hresult))
throw (hresult);
if ( m_wReplyStatus != 0x9000)
throw (E_FAIL);
}

catch (HRESULT hr) {
hresult=hr;
TRACE_CATCH(_T("APP_Auth"), hr);
}

catch (...) {
hresult = (HRESULT) E_UNEXPECTED;
TRACE_CATCH_UNKNOWN(_T("APP_AUTH"));
}

// Release cmd interface
if (pCmd != NULL)
pCmd->Release();

return hresult;
}


/*++

CSCardAuth::GetChallenge

Returns a challenge from the ICC.

Arguments:

lAlgorID - specifies the algorithm the challenge will be used with.

pParam - Contains vendor specific parameters used in the
authentication process.

lpLengthOfChallenge - indicates length of ppBuffer

ppBuffer - contains the challenge to be used in subsequent
application authentication

Return Value:

A HRESULT value indicating the status of the requested action.

ReturnMeaning
=============
S_OKOperation completed successfully.
S_FALSEUnknown error occurred.
E_OUTOFMEMORYThere is not enough memory in this process to
satisfy the request.
E_FAILUnspecified error.
E_INVALIDARGOne or more arguments are invalid.
E_UNEXPECTEDUnexpected event occurred in this function.

Author:

--*/

STDMETHODIMP CSCardAuth::GetChallenge(
LONG lAlgorID,
LPBYTEBUFFER pParam,
LONG* lpLengthOfChallenge,
LPBYTEBUFFER *ppBuffer)
{
//locals
HRESULThresult = S_OK;
LPSCARDCMDpCmd = NULL;

try {
m_lAlgorID = lAlgorID;

// CheckLength
if (*lpLengthOfChallenge<0)
throw ( (HRESULT) E_INVALIDARG );

// Is internal pointer to "Creation Class" valid
if (m_Manage == NULL)
throw ( (HRESULT) E_FAIL );

// Check pointer...Will create it later if needed.
if (ppBuffer == NULL)
throw ( (HRESULT) E_POINTER );

// Create a command object
hresult = m_Manage->CreateCmdObject(&pCmd);
if (FAILED(hresult))
throw (hresult);

// Do challenge
hresult = m_Manage->m_pISCardISO7816->GetChallenge(*lpLengthOfChallenge,
&pCmd);
if (FAILED(hresult))
throw (hresult);
// Force correct class id for the the CryptoFlex card
hresult = pCmd->put_ClassId(VENDOR_CLASS_ID);
if (FAILED(hresult))
throw (hresult);

hresult = m_Manage->m_pISCard->LockSCard();
if (FAILED(hresult))
throw (hresult);
hresult = m_Manage->m_pISCard->Transaction(&pCmd);
if (FAILED(hresult))
throw (hresult);
hresult = m_Manage->m_pISCard->UnlockSCard(LEAVE);
if (FAILED(hresult))
throw(hresult);

//interpret results and return
hresult = pCmd->get_ApduReplyLength(&m_lReplyLength);
if (FAILED(hresult))
throw (hresult);
hresult = pCmd->get_ReplyStatus( &m_wReplyStatus );
if (FAILED(hresult))
throw (hresult);
if ( m_wReplyStatus != 0x9000)
throw (E_FAIL);
hresult = pCmd->get_ApduReply( ppBuffer );
if (FAILED(hresult))
throw (hresult);
}

catch (HRESULT hr) {
hresult = hr;
TRACE_CATCH(_T("GetChallenge"),hr);
}

catch (...) {
hresult = E_UNEXPECTED;
TRACE_CATCH_UNKNOWN(_T("GetChallenge"));
}

// Release cmd interface
if (pCmd != NULL)
pCmd->Release();

return hresult;
}


/*++

CSCardAuth::ICC_Auth

Allows application to authenticate the ICC

Arguments:

lAlgorID - specifies the algorithm to be used in the authentication
process.

pParam - Contains vendor specific parameters used in the
authentication process.

lpLength - contains the length of the valid data in ppBuffer.

ppBuffer - (in) cotains the data to be used in the authentication process;
(out) contins the result of the signation process

Return Value:

A HRESULT value indicating the status of the requested action.

ReturnMeaning
=============
S_OKOperation completed successfully.
S_FALSEUnknown error occurred.
E_OUTOFMEMORYThere is not enough memory in this process to
satisfy the request.
E_FAILUnspecified error.
E_INVALIDARGOne or more arguments are invalid.
E_UNEXPECTEDUnexpected event occurred in this function.

Author:

--*/

STDMETHODIMP CSCardAuth::ICC_Auth(
long lAlgorID,
LPBYTEBUFFER pParam,
LONG* lpLength,
LPBYTEBUFFER *ppBuffer)
{
//locals
HRESULThresult = S_OK;
LPSCARDCMDpCmd = NULL;

try {
m_lAlgorID = lAlgorID;

// Is internal pointer to "Creation Class" valid
if (m_Manage == NULL)
throw ( (HRESULT) E_FAIL );

// Must have valid pointer...
if (ppBuffer == NULL)
throw ( (HRESULT) E_POINTER );

// create buffer if needed
if ( (*ppBuffer) == NULL) {
hresult = m_Manage->m_pISCardTypeConv->CreateByteBuffer((ULONG) 0,
ppBuffer);
if (FAILED(hresult))
throw (hresult);
};// if

// Create Cmd Object
hresult = m_Manage->CreateCmdObject(&pCmd);
if (FAILED(hresult))
throw (hresult);

// Do internal Authenticate
hresult = m_Manage->m_pISCardISO7816->InternalAuthenticate((BYTE) lAlgorID,
NULL,
(*ppBuffer),
0,
&pCmd);
if (FAILED(hresult))
throw (hresult);
// Force correct class id for the the CryptoFlex card
hresult = pCmd->put_ClassId(VENDOR_CLASS_ID);
if (FAILED(hresult))
throw (hresult);

hresult = m_Manage->m_pISCard->LockSCard();
if (FAILED(hresult))
throw (hresult);
hresult = m_Manage->m_pISCard->Transaction(&pCmd);
if (FAILED(hresult))
throw (hresult);
hresult = m_Manage->m_pISCard->UnlockSCard(LEAVE);
if (FAILED(hresult))
throw(hresult);

//interpret results and return
hresult = pCmd->get_ApduReplyLength(&m_lReplyLength);
if (FAILED(hresult))
throw (hresult);
hresult = pCmd->get_ReplyStatus( &m_wReplyStatus );
if (FAILED(hresult))
throw (hresult);
if ( m_wReplyStatus != 0x9000)
throw (E_FAIL);
hresult = pCmd->get_ApduReply( ppBuffer );
if (FAILED(hresult))
throw (hresult);
}

catch (HRESULT hr) {
hresult=hr;
TRACE_CATCH(_T("ICC_Auth"), hr);
}

catch (...) {
hresult = (HRESULT) E_UNEXPECTED;
TRACE_CATCH_UNKNOWN(_T("ICC_AUTH"));
}

// Release cmd interface
if (pCmd != NULL)
pCmd->Release();

return hresult;
}


/*++

CSCardAuth::Initialize

Initializes the object for use.

Arguments:

lp - a long pointer to the "controlling" ISCardManage object.

Return Value:

A HRESULT value indicating the status of the requested action.

ReturnMeaning
=============
S_OKOperation completed successfully.
S_FALSEUnknown error occurred.
E_OUTOFMEMORYThere is not enough memory in this process to
satisfy the request.
E_FAILUnspecified error.
E_INVALIDARGOne or more arguments are invalid.
E_UNEXPECTEDUnexpected event occurred in this function.

Author:

--*/
STDMETHODIMP CSCardAuth::Initialize( LONG *lp)
{
// Locals
HRESULThresult = S_OK;

try {
// Check Params, etc..
if (lp == NULL)
throw ( (HRESULT) E_INVALIDARG );

if (m_Manage != NULL)
throw ( (HRESULT) E_FAIL );

// Ok...
m_Manage = (LPCSCARDMANAGE) lp;
}

catch (HRESULT hr) {
hresult=hr;
TRACE_CATCH(_T("Initialize"), hr);
}

catch (...) {
hresult = (HRESULT) E_UNEXPECTED;
TRACE_CATCH_UNKNOWN(_T("Initialize"));
}

return (hresult);
}


/*++

CSCardAuth::User_Auth

Allows a remote app to authenticate the Client

Arguments:

lAlgorID - specifies the algorithm to be used in the authentication
process.

pParam - Contains vendor specific parameters used in the
authentication process.

lpLength - contains the length of the valid data in pBuffer.

ppBuffer - contains the challenge data on input and the authentication
data on output.

Return Value:

A HRESULT value indicating the status of the requested action.

ReturnMeaning
=============
S_OKOperation completed successfully.
S_FALSEUnknown error occurred.
E_OUTOFMEMORYThere is not enough memory in this process to
satisfy the request.
E_FAILUnspecified error.
E_INVALIDARGOne or more arguments are invalid.
E_UNEXPECTEDUnexpected event occurred in this function.

Author:

--*/

STDMETHODIMP CSCardAuth::User_Auth(
LONG lAlgorID,
LPBYTEBUFFER pParam,
LONG* lpLength,
LPBYTEBUFFER* ppBuffer)
{
//locals
HRESULThresult = E_NOTIMPL;

try {
// Todo: Add code if ICC supports
}

catch (HRESULT hr) {
hresult=hr;
TRACE_CATCH(_T("User_Auth"), hr);
}

catch (...) {
hresult = (HRESULT) E_UNEXPECTED;
TRACE_CATCH_UNKNOWN(_T("USER_AUTH"));
}

return hresult;
}