javacard — лучший способ измерить время команды APDU на карту Java в переполнении стека

Я пытаюсь провести какую-то временную атаку на карту Java. Мне нужен способ измерить время, прошедшее между отправкой команды и получением ответа. Я использую winscard.h интерфейс и язык c++, Я создал обертку для winscard.h интерфейс, чтобы облегчить мою работу. Например, для отправки APDU Теперь я использую этот код, который, кажется, работает.
На основе этот ответ я обновил свой код

 byte pbRecvBuffer[258];
long rv;
if (this->sessionHandle >= this->internal.vSessions.size())
throw new SmartCardException("There is no card inserted");
SCARD_IO_REQUEST pioRecvPci;
pioRecvPci.dwProtocol = (this->internal.vSessions)[sessionHandle].dwActiveProtocol;
pioRecvPci.cbPciLength = sizeof(pioRecvPci);

LPSCARD_IO_REQUEST pioSendPci;
if ((this->internal.vSessions)[sessionHandle].dwActiveProtocol == SCARD_PROTOCOL_T1)
pioSendPci = (LPSCARD_IO_REQUEST)SCARD_PCI_T1;
else
pioSendPci = (LPSCARD_IO_REQUEST)SCARD_PCI_T0;
word expected_length = 258;//apdu.getExpectedLen();
word send_length = apdu.getApduLength();
CardSession session = (this->internal.vSessions).operator[](sessionHandle);
byte * data = const_cast<Apdu&>(apdu).getNonConstantData();
auto start = Timer::now();
rv = SCardTransmit(session.hCard, pioSendPci,data,
send_length, &pioRecvPci, pbRecvBuffer,&expected_length);
auto end = Timer::now();
auto duration = (float)(end - start) / Timer::ticks();
return *new ApduResponse(pbRecvBuffer, expected_length,duration);

class Timer
{
public:
static inline int ticks()
{
LARGE_INTEGER ticks;
QueryPerformanceFrequency(&ticks);
return ticks.LowPart;
}

static inline __int64 now()
{
struct { __int32 low, high; } counter;

__asm cpuid
__asm push EDX
__asm rdtsc
__asm mov counter.low, EAX
__asm mov counter.high, EDX
__asm pop EDX
__asm pop EAX

return *(__int64 *)(&counter);
}

};

Мой код не работает с ошибкой The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention., Я предполагаю, что инструкция rdtsc не поддерживается моим процессором Intel. У меня Intel Broadwell 5500U.
Я ищу правильный способ сделать это измерение и получить ответы в конечном итоге с большей точностью.

1

Решение

Сообщение об ошибке, которое вы предоставили

Значение ESP не было должным образом сохранено при вызове функции. это
обычно является результатом вызова функции, объявленной одним вызовом
соглашение с указателем на функцию, объявленное с другим вызовом
условность.

указывает на ошибку в функции встроенной сборки, которую вы вызываете. Предполагая, что при вызове используется соглашение о вызовах по умолчанию, оно в корне ошибочно: cpuid истребляет ebx, который является сохраненным пользователем регистром. Кроме того, он помещает только один аргумент в стек и выскакивает два: второй эффект — это (наиболее вероятно) адрес возврата функции или базовый указатель, сохраненный как часть кадра стека. В результате, функция вызывает сбой при вызове ret, поскольку он не имеет действительного адреса для возврата или среда выполнения обнаруживает, что новое значение esp (которое восстанавливается из значения в начале функции) просто недопустимо. Это не имеет ничего общего с процессором, который вы используете, так как все процессоры x86 поддерживают RDTSC — хотя базовая тактовая частота, которую он использует, может отличаться в зависимости от текущего состояния скорости процессора, поэтому использование команды непосредственно не рекомендуется, и возможности ОС следует отдавать ей предпочтение, так как они предлагают компенсацию для различных реализаций команды на различных степпинги.

Видя, как вы используете C ++ 11 — судя по использованию auto — использовать std::chrono для измерения временных интервалов. Если это по какой-то причине не работает, используйте средства, предоставляемые вашей ОС (это похоже на Windows, поэтому QueryPerformanceCounter вероятно, тот, чтобы использовать). Если это все еще не удовлетворяет вас, вы можете просто сгенерировать rdtsc используя __rdtsc встроенная функция и не беспокоиться о встроенной сборке.

4

Другие решения

Других решений пока нет …