2016-05-12 16 views
1

Java Cardにある種のタイミング攻撃をしようとしています。コマンドの送信から取得までの経過時間を測定する方法が必要です答え。winscard.hインターフェイスを使用しています。言語はc++です。私は仕事を簡単にするためにwinscard.hインターフェースへのラッパーを作成しました。たとえば、APDUを送信する場合は、このコードを使用していますが、これはうまくいくようです。私は私のコードJava CardへのAPDUコマンドの時刻をC++で測定する最も良い方法

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); 
} 

}を更新this回答に基づいて 。

エラーコード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

[Linux/Windowsの両方でCPU時間と壁掛け時間を測定するにはどうすればよいですか?](http://stackoverflow.com/questions/17432502/how-can-i-measure-cpu-time-and) -wall-clock-on-both-linux-windows) –

+0

@MichaelRolandがコードを更新し、私の問題をより明確に説明しました – Marga

答えて

4

あなたはESPの値が正しく関数呼び出しの間で保存されませんでした

を提供するエラーメッセージ。この は通常、1つの呼び出しで宣言された関数 の規則を、別の呼び出しで宣言された関数ポインタ の規則で呼び出した結果です。

は、呼び出したインラインアセンブリ関数で間違いを示します。呼び出し時にデフォルトの呼び出し規約が使用されていると仮定すると、根本的に欠陥があります。cpuidは、呼び出し先保存レジスタであるebxを破棄します。さらに、スタックへの引数を1つだけプッシュし、2つをポップします。つまり、2番目のポップは、関数の戻りアドレス、またはスタックフレームの一部として保存されたベースポインタです。結果として、retを呼び出すときに関数は失敗します。戻り値に有効なアドレスがないか、またはランタイムによって新しい値がesp(関数の先頭の値から復元されます)が単に無効であることが検出されます。すべてのx86 CPUがRDTSCをサポートしているので、使用しているCPUとは何の関係もありませんが、使用するベースクロックはCPUの現在の速度状態によって異なる場合があります。そのため、命令を直接使用することはお勧めしません。 OSの機能は、さまざまなステッピングに関する命令のさまざまな実装のための補償を提供するので、それ以上の利点があるはずです。

autoを使用して判断すると、C++ 11の使い方を見て - 時間間隔を測定するのにstd::chronoを使用してください。それが何らかの理由で動作しない場合は、お使いのOSで提供されている機能を使用してください(Windowsのように見えるので、おそらくQueryPerformanceCounterが使用されます)。これでも依然として満足できない場合は、__rdtsc組み込み関数を使用して、rdtscを生成し、インラインアセンブリを心配する必要はありません。

関連する問題