HRESULT Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_CryptokiVerify::VerifyInternal___BOOLEAN__SZARRAY_U1__I4__I4__SZARRAY_U1__I4__I4( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();

    CLR_RT_HeapBlock*       pThis    = stack.This();
    CLR_RT_HeapBlock_Array* pData    = stack.Arg1().DereferenceArray(); 
    CLR_INT32               offset   = stack.Arg2().NumericByRef().s4;
    CLR_INT32               len      = stack.Arg3().NumericByRef().s4;
    CLR_RT_HeapBlock_Array* pSig     = stack.Arg4().DereferenceArray(); 
    CLR_INT32               sigOff   = stack.Arg5().NumericByRef().s4;
    CLR_INT32               sigLen   = stack.Arg6().NumericByRef().s4;
    CLR_RT_HeapBlock*       pSession = pThis[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_SessionContainer::FIELD__m_session].Dereference();
    CK_SESSION_HANDLE       hSession;
    bool                    retVal   = false;
    CK_RV                   result;

    FAULT_ON_NULL_ARG(pData);
    FAULT_ON_NULL_ARG(pSig);

    if((offset + len   ) > (CLR_INT32)pData->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);
    if((sigOff + sigLen) > (CLR_INT32)pSig->m_numOfElements ) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);

    hSession = (CK_SESSION_HANDLE)pSession[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Session::FIELD__m_handle].NumericByRef().s4;

    if(hSession == CK_SESSION_HANDLE_INVALID) TINYCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED);

    result = C_Verify(hSession, pData->GetElement(offset), len, pSig->GetElement(sigOff), sigLen);

    retVal = CKR_OK == result;

    stack.SetResult_Boolean(retVal);

    TINYCLR_NOCLEANUP();
}
// TODO: Make common functions for transformBlock for encrypt/decrypt when async logic is in place
HRESULT Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Decryptor::TransformBlockInternal___I4__SZARRAY_U1__I4__I4__SZARRAY_U1__I4( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();

    CLR_RT_HeapBlock*       pThis      = stack.This();
    CLR_RT_HeapBlock_Array* pData      = stack.Arg1().DereferenceArray(); 
    CLR_INT32               dataOffset = stack.Arg2().NumericByRef().s4;
    CLR_INT32               dataLen    = stack.Arg3().NumericByRef().s4;
    CLR_RT_HeapBlock_Array* pOutput    = stack.Arg4().DereferenceArray(); 
    CLR_INT32               outOffset  = stack.Arg5().NumericByRef().s4;
    CLR_RT_HeapBlock*       pSession   = pThis[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_SessionContainer::FIELD__m_session].Dereference();
    CK_SESSION_HANDLE       hSession;
    CLR_UINT32              decrSize;   

    FAULT_ON_NULL_ARG(pData);
    FAULT_ON_NULL_ARG(pOutput);
    FAULT_ON_NULL_ARG(pSession);

    hSession = (CK_SESSION_HANDLE)pSession[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Session::FIELD__m_handle].NumericByRef().s4;

    if(hSession == CK_SESSION_HANDLE_INVALID) TINYCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED);

    if((dataOffset + dataLen) > (CLR_INT32)pData->m_numOfElements  ) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);
    if((outOffset           ) > (CLR_INT32)pOutput->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);

    decrSize = pOutput->m_numOfElements - outOffset;

    CRYPTOKI_CHECK_RESULT(stack, C_DecryptUpdate(hSession, pData->GetElement(dataOffset), dataLen, pOutput->GetElement(outOffset), (CK_ULONG_PTR)&decrSize));

    stack.SetResult_I4(decrSize);

    TINYCLR_NOCLEANUP();
}
HRESULT Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Decryptor::TransformFinalBlockInternal___SZARRAY_U1__SZARRAY_U1__I4__I4( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();

    CLR_RT_HeapBlock*       pThis     = stack.This();
    CLR_RT_HeapBlock_Array* pData     = stack.Arg1().DereferenceArray(); 
    CLR_INT32               offset    = stack.Arg2().NumericByRef().s4;
    CLR_INT32               len       = stack.Arg3().NumericByRef().s4;
    CLR_RT_HeapBlock*       pSession  = pThis[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_SessionContainer::FIELD__m_session].Dereference();
    CLR_UINT32              decrSize  = 0;
    CK_SESSION_HANDLE       hSession;
    CLR_RT_HeapBlock        hbRef;
    CLR_RT_HeapBlock*       pRet;
    CLR_UINT32              maxOut;

    FAULT_ON_NULL_ARG(pData);
    FAULT_ON_NULL_ARG(pSession);

    if((offset + len) > (CLR_INT32)pData->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);

    hSession  = (CK_SESSION_HANDLE)pSession[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Session::FIELD__m_handle].NumericByRef().s4;

    if(hSession == CK_SESSION_HANDLE_INVALID) TINYCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED);

    CRYPTOKI_CHECK_RESULT(stack, C_Decrypt(hSession, pData->GetElement(offset), len, NULL, (CK_ULONG_PTR)&decrSize));

    maxOut = decrSize;

    TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(hbRef, decrSize, g_CLR_RT_WellKnownTypes.m_UInt8));

    CRYPTOKI_CHECK_RESULT(stack, C_Decrypt(hSession, pData->GetElement(offset), len, hbRef.DereferenceArray()->GetFirstElement(), (CK_ULONG_PTR)&decrSize));

    if(decrSize < maxOut)
    {
        CLR_RT_HeapBlock refSmall;
        
        TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(refSmall, decrSize, g_CLR_RT_WellKnownTypes.m_UInt8));

        memcpy(refSmall.DereferenceArray()->GetFirstElement(), hbRef.DereferenceArray()->GetFirstElement(), decrSize);

        pRet = refSmall.Dereference();
    }
    else
    {
        pRet = hbRef.Dereference();
    }

    stack.SetResult_Object(pRet);

    TINYCLR_NOCLEANUP();
}
HRESULT Library_spot_net_security_native_Microsoft_SPOT_Net_Security_SslNative::SecureConnect___STATIC__VOID__I4__STRING__OBJECT( CLR_RT_StackFrame& stack )
{
    NATIVE_PROFILE_CLR_NETWORK();
    TINYCLR_HEADER();

    CLR_INT32 sslContext     = stack.Arg0().NumericByRef().s4;
    CLR_RT_HeapBlock* hb     = stack.Arg1().DereferenceString();
    CLR_RT_HeapBlock* socket = stack.Arg2().Dereference();
    CLR_INT32         timeout_ms = -1; // wait forever
    CLR_RT_HeapBlock  hbTimeout;
    
    int        result;    
    LPCSTR     szName;
    CLR_INT32  handle;
    bool       fRes = true;
    CLR_INT64 *timeout;

    FAULT_ON_NULL(socket);

    handle = socket[ Library_spot_net_native_Microsoft_SPOT_Net_SocketNative::FIELD__m_Handle ].NumericByRef().s4;

    /* Because we could have been a rescheduled call due to a prior call that would have blocked, we need to see
     * if our handle has been shutdown before continuing. */
    if (handle == Library_spot_net_native_Microsoft_SPOT_Net_SocketNative::DISPOSED_HANDLE)
    {
        ThrowError( stack, CLR_E_OBJECT_DISPOSED );
        TINYCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION);
    }

    FAULT_ON_NULL_ARG(hb);

    szName = hb->StringText();

    hbTimeout.SetInteger( timeout_ms );
        
    TINYCLR_CHECK_HRESULT(stack.SetupTimeout( hbTimeout, timeout ));

    while(true)
    {
        result = SSL_Connect( handle, szName, sslContext );

        if(result == SOCK_EWOULDBLOCK || result == SOCK_TRY_AGAIN)
        {
            // non-blocking - allow other threads to run while we wait for socket activity
            TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_Socket, fRes ));

            if(result < 0) break;
        }
        else
        {
            break;
        }
    }

    stack.PopValue();       // Timeout

    TINYCLR_CHECK_HRESULT(ThrowOnError( stack, result ));

    TINYCLR_NOCLEANUP();
}
HRESULT Library_corlib_native_System_BitConverter::ToString___STATIC__STRING__SZARRAY_U1__I4__I4( CLR_RT_StackFrame& stack )
{
	NATIVE_PROFILE_CLR_CORE();
	TINYCLR_HEADER();

	CLR_RT_HeapBlock_Array* pArray = stack.Arg0().DereferenceArray();
	FAULT_ON_NULL_ARG(pArray);

	int index;
	index = stack.Arg1().NumericByRefConst().s4;
	int length;
	length = stack.Arg2().NumericByRefConst().s4;
	if (pArray->m_numOfElements == 0 && index == 0 && length == 0)
	{
		TINYCLR_CHECK_HRESULT(stack.SetResult_String(""));
	}
	else
	{
		if (index < 0 || length < 0 || (unsigned int)index >= pArray->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);
		if ((unsigned int)index + length > pArray->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);

		BYTE* p;
		p  = pArray->GetFirstElement();
		char* pOutput = ByteArrayToHex(p, index, length);
		TINYCLR_CHECK_HRESULT(stack.SetResult_String(pOutput));
		delete[] pOutput;
	}

	TINYCLR_NOCLEANUP();
}
HRESULT Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_CryptokiSign::SignUpdateInternal___VOID__SZARRAY_U1__I4__I4( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();

    CLR_RT_HeapBlock*       pThis      = stack.This();
    CLR_RT_HeapBlock_Array* pData      = stack.Arg1().DereferenceArray();
    CLR_INT32               offset     = stack.Arg2().NumericByRef().s4;
    CLR_INT32               len        = stack.Arg3().NumericByRef().s4;
    CLR_RT_HeapBlock*       pSession   = pThis[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_SessionContainer::FIELD__m_session].Dereference();
    CLR_INT32               sigLen     = pThis[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_CryptokiSign::FIELD__m_signatureLength].NumericByRef().s4;
    CK_SESSION_HANDLE       hSession;

    FAULT_ON_NULL_ARG(pData);
    FAULT_ON_NULL(pSession);

    if((offset + len) > (CLR_INT32)pData->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);

    hSession = (CK_SESSION_HANDLE)pSession[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Session::FIELD__m_handle].NumericByRef().s4;

    // TODO: add code for processing chunks at a time if size is too big
    //maxProcessingBytes = pSession[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Session::FIELD__m_maxProcessingBytes].NumericByRef().s4;

    if(hSession == CK_SESSION_HANDLE_INVALID) TINYCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED);

    CRYPTOKI_CHECK_RESULT(stack, C_SignUpdate(hSession, pData->GetElement(offset), len));

    TINYCLR_NOCLEANUP();
}
HRESULT Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_FindObjectEnum::FindObjectsInit___VOID__SZARRAY_MicrosoftSPOTCryptokiCryptokiAttribute( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();
    CLR_RT_HeapBlock*       pThis      = stack.This();
    CLR_RT_HeapBlock_Array* pAttribs   = stack.Arg1().DereferenceArray();
    CLR_RT_HeapBlock*       pAttrib;
    CLR_RT_HeapBlock*       pSession   = pThis[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_FindObjectEnum::FIELD__m_session].Dereference();
    CK_SESSION_HANDLE       hSession;
    CK_ATTRIBUTE            attribs[20];
    CLR_UINT32              i;

    FAULT_ON_NULL_ARG(pAttribs);
    FAULT_ON_NULL(pSession);

    if(pAttribs->m_numOfElements > ARRAYSIZE(attribs)) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);

    hSession = pSession[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Session::FIELD__m_handle].NumericByRef().u4;
    pAttrib  = (CLR_RT_HeapBlock*)pAttribs->GetFirstElement();

    for(i=0; i<pAttribs->m_numOfElements; i++)
    {
        CLR_RT_HeapBlock*       pElement    = pAttrib->Dereference();  FAULT_ON_NULL(pElement);
        CLR_RT_HeapBlock_Array* pValueArray = pElement[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_CryptokiAttribute::FIELD__Value].DereferenceArray();  FAULT_ON_NULL(pValueArray);

        attribs[i].type       = pElement[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_CryptokiAttribute::FIELD__Type].NumericByRef().u4;
        attribs[i].pValue     = pValueArray->GetFirstElement();
        attribs[i].ulValueLen = pValueArray->m_numOfElements;

        pAttrib++;
    }

    CRYPTOKI_CHECK_RESULT(stack, C_FindObjectsInit(hSession, attribs, pAttribs->m_numOfElements));

    TINYCLR_NOCLEANUP();
}
HRESULT Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_CryptokiDigest::DigestInternal___SZARRAY_U1__SZARRAY_U1__I4__I4( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();

    CLR_RT_HeapBlock*       pThis      = stack.This();
    CLR_RT_HeapBlock_Array* pData      = stack.Arg1().DereferenceArray(); 
    CLR_INT32               offset     = stack.Arg2().NumericByRef().s4;
    CLR_INT32               len        = stack.Arg3().NumericByRef().s4;
    CLR_RT_HeapBlock*       pSession   = pThis[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_SessionContainer::FIELD__m_session].Dereference();
    CLR_INT32               digestSize = pThis[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_CryptokiDigest::FIELD__m_hashSize].NumericByRef().s4;
    CK_SESSION_HANDLE       hSession;
    //CLR_INT32                     maxProcessingBytes;

    FAULT_ON_NULL_ARG(pData);
    FAULT_ON_NULL(pSession);

    if((offset + len) > (CLR_INT32)pData->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);

    hSession = (CK_SESSION_HANDLE)pSession[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Session::FIELD__m_handle].NumericByRef().s4;

    if(hSession == CK_SESSION_HANDLE_INVALID) TINYCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED);

    // TODO: add code for processing chunks at a time if size is too big
    //maxProcessingBytes = pSession[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Session::FIELD__m_maxProcessingBytes].NumericByRef().s4;

    TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(stack.PushValue(), digestSize, g_CLR_RT_WellKnownTypes.m_UInt8));

    CRYPTOKI_CHECK_RESULT(stack, C_Digest(hSession, pData->GetElement(offset), len, stack.TopValue().DereferenceArray()->GetFirstElement(), (CK_ULONG_PTR)&digestSize));

    TINYCLR_NOCLEANUP();
}
HRESULT Library_spot_update_native_Microsoft_SPOT_MFUpdate_MFNativeUpdate::GetUpdateProperty___STATIC__BOOLEAN__I4__STRING__BYREF_SZARRAY_U1( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();

    CLR_INT32  handle = stack.Arg0().NumericByRef().s4;
    LPCSTR szProperty = stack.Arg1().StringText(); 
    CLR_RT_HeapBlock* pRef;
    CLR_RT_HeapBlock_Array* pData;
    int dataLen;

    FAULT_ON_NULL(szProperty);

    pRef    = stack.Arg2().Dereference();  FAULT_ON_NULL_ARG(pRef);
    pData   = pRef->DereferenceArray();    FAULT_ON_NULL_ARG(pData);
    dataLen = pData->m_numOfElements;

    stack.SetResult_Boolean(TRUE == MFUpdate_GetProperty(handle, szProperty, pData->GetFirstElement(), &dataLen));

    TINYCLR_NOCLEANUP();
}
HRESULT Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Decryptor::DecryptInit___VOID__MicrosoftSPOTCryptokiSession__MicrosoftSPOTCryptokiMechanism__SystemSecurityCryptographyCryptoKey( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();

    CLR_RT_HeapBlock*       pSession   = stack.Arg1().Dereference(); 
    CLR_RT_HeapBlock*       pMech      = stack.Arg2().Dereference(); 
    CLR_RT_HeapBlock*       pKeyHandle = stack.Arg3().Dereference();
    CLR_RT_HeapBlock_Array* pArrParam;
    CK_MECHANISM            mech;
    CK_OBJECT_HANDLE        hKey;
    CK_SESSION_HANDLE       hSession;

    FAULT_ON_NULL_ARG(pSession);
    FAULT_ON_NULL_ARG(pMech);
    FAULT_ON_NULL_ARG(pKeyHandle);

    hSession = (CK_SESSION_HANDLE)pSession[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Session::FIELD__m_handle].NumericByRef().s4;

    if(hSession == CK_SESSION_HANDLE_INVALID) TINYCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED);

    mech.mechanism = pMech[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Mechanism::FIELD__Type].NumericByRef().u4;

    pArrParam = pMech[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Mechanism::FIELD__Parameter].DereferenceArray();

    if(pArrParam != NULL && pArrParam->m_numOfElements > 0)
    {
        mech.pParameter     = pArrParam->GetFirstElement();
        mech.ulParameterLen = pArrParam->m_numOfElements;
    }
    else
    {
        mech.pParameter     = NULL;
        mech.ulParameterLen = 0;
    }

    hKey = (CK_OBJECT_HANDLE)pKeyHandle[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_CryptokiObject::FIELD__m_handle].NumericByRef().s4;

    CRYPTOKI_CHECK_RESULT(stack, C_DecryptInit(hSession, &mech, hKey));

    TINYCLR_NOCLEANUP();
}
HRESULT Library_spot_update_native_Microsoft_SPOT_MFUpdate_MFNativeUpdate::AuthCommand___STATIC__BOOLEAN__I4__I4__SZARRAY_U1__BYREF_SZARRAY_U1( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();

    CLR_INT32               handle = stack.Arg0().NumericByRef().s4;
    CLR_INT32               cmd    = stack.Arg1().NumericByRef().s4;
    CLR_RT_HeapBlock_Array* paArgs = stack.Arg2().DereferenceArray();
    CLR_RT_HeapBlock_Array* paResp = stack.Arg3().Dereference()->DereferenceArray();    
    CLR_UINT8*              pResp   = paResp == NULL ? NULL : paResp->GetFirstElement();
    CLR_INT32               respLen = paResp == NULL ? 0    : paResp->m_numOfElements;

    FAULT_ON_NULL_ARG(paArgs);

    stack.SetResult_Boolean(TRUE == MFUpdate_AuthCommand(handle, cmd, paArgs->GetFirstElement(), paArgs->m_numOfElements, pResp, respLen));

    TINYCLR_NOCLEANUP();
}
HRESULT Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_CryptokiRNG::GenerateRandom___VOID__SZARRAY_U1__I4__I4__BOOLEAN( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();

    CLR_RT_HeapBlock*       pThis    = stack.This();
    CLR_RT_HeapBlock*       pSession;
    CLR_RT_HeapBlock_Array* pData    = stack.Arg1().DereferenceArray();
    CLR_INT32               offset   = stack.Arg2().NumericByRef().s4;
    CLR_INT32               len      = stack.Arg3().NumericByRef().s4;
    bool                    fNonZero = stack.Arg4().NumericByRef().s4 == 1;
    CK_SESSION_HANDLE       hSession;
    CLR_UINT8*              pDataElem;

    FAULT_ON_NULL_ARG(pData);

    if(len+offset > (CLR_INT32)pData->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);

    pSession = pThis[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_SessionContainer::FIELD__m_session].Dereference(); FAULT_ON_NULL(pSession);
    hSession = pSession[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Session::FIELD__m_handle].NumericByRef().s4;

    pDataElem = pData->GetElement(offset);
    
    CRYPTOKI_CHECK_RESULT(stack, C_GenerateRandom(hSession, pDataElem, len));

    if(fNonZero)
    {
        int i,idx = -1;
        CLR_UINT8 replacements[20];

        for(i=0; i<len; i++)
        {
            if(*pDataElem == 0)
            {
                if(idx == -1 || idx >= ARRAYSIZE(replacements))
                {
                    CRYPTOKI_CHECK_RESULT(stack, C_GenerateRandom(hSession, replacements, ARRAYSIZE(replacements)));
                    idx = 0;
                }

                *pDataElem = replacements[idx++];
            }
        }
    }

    TINYCLR_NOCLEANUP();
}
HRESULT Library_corlib_native_System_BitConverter::ToBoolean___STATIC__BOOLEAN__SZARRAY_U1__I4( CLR_RT_StackFrame& stack )
{
	NATIVE_PROFILE_CLR_CORE();
	TINYCLR_HEADER();

	CLR_RT_HeapBlock_Array* pArray = stack.Arg0().DereferenceArray();
	FAULT_ON_NULL_ARG(pArray);

	int index;
	index = stack.Arg1().NumericByRefConst().s4;
	if (index < 0 || (unsigned int)index >= pArray->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);

	BYTE* p;
	p  = pArray->GetFirstElement();
	stack.SetResult_Boolean(*reinterpret_cast<bool*>(p + index));

	TINYCLR_NOCLEANUP();
}
HRESULT Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_CryptokiRNG::SeedRandom___VOID__SZARRAY_U1( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();

    CLR_RT_HeapBlock*       pThis    = stack.This();
    CLR_RT_HeapBlock_Array* pData    = stack.Arg1().DereferenceArray();
    CLR_RT_HeapBlock*       pSession;
    CK_SESSION_HANDLE       hSession;

    FAULT_ON_NULL_ARG(pData);

    pSession = pThis[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_SessionContainer::FIELD__m_session].Dereference(); FAULT_ON_NULL(pSession);
    hSession = pSession[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Session::FIELD__m_handle].NumericByRef().s4;

    CRYPTOKI_CHECK_RESULT(stack, C_SeedRandom(hSession, pData->GetFirstElement(), pData->m_numOfElements));

    TINYCLR_NOCLEANUP();
}
HRESULT Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_CryptokiSign::SignInternal___SZARRAY_U1__SZARRAY_U1__I4__I4( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();

    CLR_RT_HeapBlock*       pThis    = stack.This();
    CLR_RT_HeapBlock_Array* pData    = stack.Arg1().DereferenceArray();
    CLR_RT_HeapBlock_Array* pRes;
    CLR_INT32               offset   = stack.Arg2().NumericByRef().s4;
    CLR_INT32               len      = stack.Arg3().NumericByRef().s4;
    CLR_RT_HeapBlock*       pSession = pThis[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_SessionContainer::FIELD__m_session].Dereference();
    CK_SESSION_HANDLE       hSession;
    CK_ULONG                sigLen   = 0;
    CLR_RT_HeapBlock        hbRef;

    FAULT_ON_NULL(pSession);
    FAULT_ON_NULL_ARG(pData);

    if((offset + len) > (CLR_INT32)pData->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);

    hSession = (CK_SESSION_HANDLE)pSession[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Session::FIELD__m_handle].NumericByRef().s4;

    if(hSession == CK_SESSION_HANDLE_INVALID) TINYCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED);

    CRYPTOKI_CHECK_RESULT(stack, C_Sign(hSession, pData->GetElement(offset), len, NULL, (CK_ULONG_PTR)&sigLen));

    TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(hbRef, sigLen, g_CLR_RT_WellKnownTypes.m_UInt8));

    pRes = hbRef.DereferenceArray();

    CRYPTOKI_CHECK_RESULT(stack, C_Sign(hSession, pData->GetElement(offset), len, pRes->GetFirstElement(), (CK_ULONG_PTR)&sigLen));

    if(sigLen < pRes->m_numOfElements)
    {
        TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(stack.PushValue(), sigLen, g_CLR_RT_WellKnownTypes.m_UInt8));

        memcpy(stack.TopValue().DereferenceArray()->GetFirstElement(), pRes->GetFirstElement(), sigLen);
    }
    else
    {
        stack.SetResult_Object(pRes);
    }

    TINYCLR_NOCLEANUP();
}
HRESULT Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_CryptokiVerify::VerifyFinalInternal___BOOLEAN__SZARRAY_U1__I4__I4( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();

    CLR_RT_HeapBlock*       pThis    = stack.This();
    CLR_RT_HeapBlock_Array* pSig     = stack.Arg1().DereferenceArray(); 
    CLR_INT32               sigOff   = stack.Arg2().NumericByRef().s4;
    CLR_INT32               sigLen   = stack.Arg3().NumericByRef().s4;
    CLR_RT_HeapBlock*       pSession = pThis[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_SessionContainer::FIELD__m_session].Dereference();
    CK_SESSION_HANDLE       hSession;
    bool                    retVal   = false;
    CK_RV                   result;

    FAULT_ON_NULL_ARG(pSig);

    if((sigOff + sigLen) > (CLR_INT32)pSig->m_numOfElements ) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);

    hSession = pSession[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Session::FIELD__m_handle].NumericByRef().s4;

    if(hSession == CK_SESSION_HANDLE_INVALID) TINYCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED);

    result = C_VerifyFinal(hSession, pSig->GetElement(sigOff), sigLen);

    switch(result)
    {
        case CKR_SIGNATURE_INVALID:
            retVal = false;
            break;
        case CKR_OK:
            retVal = true;
            break;

        case CKR_SIGNATURE_LEN_RANGE:
            TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
        default:
            CRYPTOKI_CHECK_RESULT(stack, result);
            break;
    }

    stack.SetResult_Boolean(retVal);

    TINYCLR_NOCLEANUP();
}
HRESULT Library_corlib_native_System_BitConverter::ToUInt16___STATIC__U2__SZARRAY_U1__I4(CLR_RT_StackFrame& stack)
{
	NATIVE_PROFILE_CLR_CORE();
	TINYCLR_HEADER();

	BYTE *p = NULL;
	int index = 0;

	CLR_RT_HeapBlock_Array* pArray = stack.Arg0().DereferenceArray();
	FAULT_ON_NULL_ARG(pArray);

	index = stack.Arg1().NumericByRefConst().s4;
	if (index < 0 || (unsigned int)index >= pArray->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);
	if ((unsigned int)index + 2 > pArray->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);

	p = pArray->GetFirstElement();
	stack.SetResult(*reinterpret_cast<unsigned short*>(p + index), DATATYPE_U2);

	TINYCLR_NOCLEANUP();
}
HRESULT Library_corlib_native_System_BitConverter::ToString___STATIC__STRING__SZARRAY_U1(CLR_RT_StackFrame& stack)
{
	NATIVE_PROFILE_CLR_CORE();
	TINYCLR_HEADER();

	CLR_RT_HeapBlock_Array* pArray = stack.Arg0().DereferenceArray();
	FAULT_ON_NULL_ARG(pArray);

	if (pArray->m_numOfElements == 0)
	{
		TINYCLR_CHECK_HRESULT(stack.SetResult_String(""));
	}
	else
	{
		BYTE* p = pArray->GetFirstElement();
		char* pOutput = ByteArrayToHex(p, 0, pArray->m_numOfElements);
		TINYCLR_CHECK_HRESULT(stack.SetResult_String(pOutput));
		delete[] pOutput;
	}

	TINYCLR_NOCLEANUP();
}
HRESULT Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_CryptokiVerify::VerifyUpdateInternal___VOID__SZARRAY_U1__I4__I4( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();

    CLR_RT_HeapBlock*       pThis    = stack.This();
    CLR_RT_HeapBlock_Array* pData    = stack.Arg1().DereferenceArray(); 
    CLR_INT32               offset   = stack.Arg2().NumericByRef().s4;
    CLR_INT32               len      = stack.Arg3().NumericByRef().s4;
    CLR_RT_HeapBlock*       pSession = pThis[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_SessionContainer::FIELD__m_session].Dereference();
    CK_SESSION_HANDLE       hSession;

    FAULT_ON_NULL_ARG(pData);

    if((offset + len) > (CLR_INT32)pData->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);

    hSession = pSession[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Session::FIELD__m_handle].NumericByRef().s4;

    if(hSession == CK_SESSION_HANDLE_INVALID) TINYCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED);

    CRYPTOKI_CHECK_RESULT(stack, C_VerifyUpdate(hSession, pData->GetElement(offset), len));

    TINYCLR_NOCLEANUP();
}
HRESULT Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_CryptokiDigest::DigestKeyInternal___VOID__SystemSecurityCryptographyCryptoKey( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();

    CLR_RT_HeapBlock* pThis      = stack.This();
    CLR_RT_HeapBlock* phKey      = stack.Arg1().Dereference(); 
    CLR_RT_HeapBlock* pSession   = pThis[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_SessionContainer::FIELD__m_session].Dereference();
    CK_SESSION_HANDLE hSession;
    CK_OBJECT_HANDLE  hKey;

    FAULT_ON_NULL_ARG(phKey);
    FAULT_ON_NULL(pSession);

    hSession = (CK_SESSION_HANDLE)pSession[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Session::FIELD__m_handle].NumericByRef().s4;

    if(hSession == CK_SESSION_HANDLE_INVALID) TINYCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED);

    hKey = (CK_OBJECT_HANDLE)phKey[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_CryptokiObject::FIELD__m_handle].NumericByRef().s4;

    CRYPTOKI_CHECK_RESULT(stack, C_DigestKey(hSession, hKey));

    TINYCLR_NOCLEANUP();
}
HRESULT Library_corlib_native_System_BitConverter::ToSingle___STATIC__R4__SZARRAY_U1__I4(CLR_RT_StackFrame& stack)
{
	NATIVE_PROFILE_CLR_CORE();
	TINYCLR_HEADER();

	BYTE *p = NULL;
	int index = 0;

	CLR_RT_HeapBlock_Array* pArray = stack.Arg0().DereferenceArray();
	FAULT_ON_NULL_ARG(pArray);

	index = stack.Arg1().NumericByRefConst().s4;
	if (index < 0 || (unsigned int)index >= pArray->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);
	if ((unsigned int)index + 4 > pArray->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);

	p = pArray->GetFirstElement();
#if !defined(TINYCLR_EMULATED_FLOATINGPOINT)
	stack.SetResult_R4(*reinterpret_cast<float*>(p + index));
#else
	stack.SetResult_R4(*reinterpret_cast<CLR_INT32*>(p + index));
#endif

	TINYCLR_NOCLEANUP();
}
HRESULT Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_CryptokiDigest::Init___VOID__MicrosoftSPOTCryptokiMechanism( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();

    CLR_RT_HeapBlock*       pThis    = stack.This(); 
    CLR_RT_HeapBlock*       pMech    = stack.Arg1().Dereference(); 
    CLR_RT_HeapBlock*       pSession = pThis[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_SessionContainer::FIELD__m_session].Dereference();
    CLR_RT_HeapBlock_Array* pParam;
    CK_MECHANISM            mech;
    CK_SESSION_HANDLE       hSession;

    FAULT_ON_NULL(pSession);
    FAULT_ON_NULL_ARG(pMech);

    hSession = (CK_SESSION_HANDLE)pSession[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Session::FIELD__m_handle].NumericByRef().s4;
    pParam   = pMech[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Mechanism::FIELD__Parameter].DereferenceArray();

    if(hSession == CK_SESSION_HANDLE_INVALID) TINYCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED);

    mech.mechanism  = pMech[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Mechanism::FIELD__Type].NumericByRef().u4;

    if(pParam != NULL)
    {
        mech.pParameter     = pParam->GetFirstElement();
        mech.ulParameterLen = pParam->m_numOfElements;
    }
    else
    {
        mech.pParameter     = NULL;
        mech.ulParameterLen = 0;
    }

    CRYPTOKI_CHECK_RESULT(stack, C_DigestInit(hSession, &mech));

    TINYCLR_NOCLEANUP();
}
HRESULT Library_spot_net_security_native_Microsoft_SPOT_Net_Security_SslNative::ParseCertificate___STATIC__VOID__SZARRAY_U1__STRING__BYREF_STRING__BYREF_STRING__BYREF_mscorlibSystemDateTime__BYREF_mscorlibSystemDateTime( CLR_RT_StackFrame& stack )
{
    NATIVE_PROFILE_CLR_NETWORK();
    TINYCLR_HEADER();

    CLR_RT_HeapBlock_Array* arrData    = stack.Arg0().DereferenceArray(); 
    CLR_UINT8*              certBytes;
    CLR_RT_HeapBlock        hbIssuer;
    CLR_RT_HeapBlock        hbSubject;
    CLR_RT_ProtectFromGC    gc1( hbIssuer  );
    CLR_RT_ProtectFromGC    gc2( hbSubject );
    X509CertData            cert;
    CLR_INT64*              val;
    CLR_INT64               tzOffset;
    SYSTEMTIME              st;
    INT32                   standardBias;
    CLR_RT_HeapBlock*       hbPwd     = stack.Arg1().DereferenceString();
    LPCSTR                  szPwd;


    FAULT_ON_NULL_ARG(hbPwd);

    szPwd = hbPwd->StringText();

    CLR_RT_Memory::ZeroFill( &cert, sizeof(cert) );

    FAULT_ON_NULL(arrData);

    certBytes = arrData->GetFirstElement();

    if(!SSL_ParseCertificate( (const char*)certBytes, arrData->m_numOfElements, szPwd, &cert )) TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);

    TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbIssuer, cert.Issuer ));
    TINYCLR_CHECK_HRESULT(hbIssuer.StoreToReference( stack.Arg2(), 0 ));

    TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbSubject, cert.Subject ));
    TINYCLR_CHECK_HRESULT(hbSubject.StoreToReference( stack.Arg3(), 0 ));

    st.wYear         = cert.EffectiveDate.year;
    st.wMonth        = cert.EffectiveDate.month;
    st.wDay          = cert.EffectiveDate.day;
    st.wHour         = cert.EffectiveDate.hour;
    st.wMinute       = cert.EffectiveDate.minute;
    st.wSecond       = cert.EffectiveDate.second;
    st.wMilliseconds = cert.EffectiveDate.msec;

    standardBias     = Time_GetTimeZoneOffset();
    standardBias    *= TIME_CONVERSION__ONEMINUTE;

    val = Library_corlib_native_System_DateTime::GetValuePtr( stack.Arg4() );
    *val = Time_FromSystemTime( &st );

    tzOffset = cert.EffectiveDate.tzOffset;

    // adjust for timezone differences
    if(standardBias != tzOffset)
    {
        *val += tzOffset - standardBias; 
    }

    st.wYear         = cert.ExpirationDate.year;
    st.wMonth        = cert.ExpirationDate.month;
    st.wDay          = cert.ExpirationDate.day;
    st.wHour         = cert.ExpirationDate.hour;
    st.wMinute       = cert.ExpirationDate.minute;
    st.wSecond       = cert.ExpirationDate.second;
    st.wMilliseconds = cert.ExpirationDate.msec;
    
    val = Library_corlib_native_System_DateTime::GetValuePtr( stack.ArgN( 5 ) );
    *val = Time_FromSystemTime( &st );

    tzOffset = cert.ExpirationDate.tzOffset;
    
    if(standardBias != tzOffset)
    {
       *val += tzOffset - standardBias; 
    }

    TINYCLR_NOCLEANUP();
}