Skip to content

Commit b7fa31a

Browse files
committed
when exception is thrown during a measurement (e.g. oscilloscope error), the scenarios fail safely (save data that got measured so far), resolves #9
1 parent 7adc32f commit b7fa31a

File tree

5 files changed

+225
-144
lines changed

5 files changed

+225
-144
lines changed

include/types_basic.hpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* SICAK - SIde-Channel Analysis toolKit
3-
* Copyright (C) 2018 Petr Socha, FIT, CTU in Prague
3+
* Copyright (C) 2018-2019 Petr Socha, FIT, CTU in Prague
44
*
55
* This program is free software: you can redistribute it and/or modify
66
* it under the terms of the GNU General Public License as published by
@@ -23,7 +23,7 @@
2323
*
2424
*
2525
* \author Petr Socha
26-
* \version 1.0
26+
* \version 1.1
2727
*/
2828

2929
#ifndef TYPES_BASIC_HPP
@@ -146,6 +146,9 @@ class MatrixType : public ArrayType<T> {
146146
/// Initializes the matrix with a specified number of cols and rows and fills it with 'val'
147147
virtual void init(size_t cols, size_t rows, T initVal) = 0;
148148

149+
/// Vertically shrinks the matrix, with remaining elements and addressing left intact
150+
virtual void shrinkRows(size_t rows) = 0;
151+
149152
/// Accesses an element in the matrix. Doesn't check for bounds.
150153
virtual T & operator() (size_t col, size_t row) = 0;
151154
/// Accesses an element in the matrix. Doesn't check for bounds.
@@ -257,6 +260,7 @@ class Vector : public VectorType<T> {
257260
m_capacity = length;
258261

259262
} catch (std::bad_alloc & e) {
263+
(void)e; // supress MSVC warnings about an unused local variable
260264
throw RuntimeException("Memory allocation failed");
261265
}
262266

@@ -339,6 +343,13 @@ class Matrix : public MatrixType<T> {
339343
m_cols = cols;
340344
m_rows = rows;
341345
}
346+
347+
virtual void shrinkRows(size_t rows) {
348+
if(rows > m_rows) throw RuntimeException("Cannot shrink Matrix to a larger size!");
349+
m_vector.init(m_cols * rows); // (rows <= m_rows) -> (Vector::m_capacity >= m_cols * rows) -> no memory reallocation happens, only upper bound is lowered
350+
m_rows = rows;
351+
// Matrix now appears "less tall"... enlargening it back to the previous size would actually give back the original matrix, but we cant guarantee that generally
352+
}
342353

343354
virtual T * data() { return m_vector.data(); }
344355
virtual const T * data() const { return m_vector.data(); }

plugins/measurement/random128apdu/random128apdu.cpp

Lines changed: 52 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -172,50 +172,69 @@ void Random128APDU::run(const char * measurementId, size_t measurements, Oscillo
172172
// We run the oscilloscope runs times
173173
for(size_t run = 0; run < runs; run++){
174174

175-
oscilloscope->run(); //< Start capturing capturesPerRun captures
175+
try { // try to perform a measurement run
176176

177-
// Send capturesPerRun blocks to cipher
178-
for(size_t capture = 0; capture < capturesPerRun; capture++){
177+
oscilloscope->run(); //< Start capturing capturesPerRun captures
179178

180-
size_t measurement = run * capturesPerRun + capture; //< Number of current measurement
181-
182-
// Generate random plaintext
183-
for(int byte = 0; byte < 16; byte++){
179+
// Send capturesPerRun blocks to cipher
180+
for(size_t capture = 0; capture < capturesPerRun; capture++){
181+
182+
size_t measurement = run * capturesPerRun + capture; //< Number of current measurement
183+
184+
// Generate random plaintext
185+
for(int byte = 0; byte < 16; byte++){
186+
187+
plaintext(byte, measurement) = (uint8_t) byteUnif(prng);
188+
189+
}
190+
191+
// Send plaintext
192+
193+
// fill APDU with plaintext
194+
for(int byte = 0; byte < 16; byte++){
195+
commandAPDU(5+byte) = plaintext(byte, measurement);
196+
}
197+
// send APDU
198+
charDevice->send(commandAPDU);
199+
200+
// Receive ciphertext
201+
202+
// receive APDU
203+
if(charDevice->receive(responseAPDU) != 18) throw RuntimeException("Failed to receive 18 bytes APDU response (16 bytes ciphertext + SW1 + SW2).");
204+
// copy ciphertext
205+
for(int byte = 0; byte < 16; byte++){
206+
ciphertext(byte, measurement) = responseAPDU(byte);
207+
}
208+
209+
CoutProgress::get().update(measurement);
184210

185-
plaintext(byte, measurement) = (uint8_t) byteUnif(prng);
186-
187211
}
188212

189-
// Send plaintext
213+
size_t measuredSamples;
214+
size_t measuredCaptures;
190215

191-
// fill APDU with plaintext
192-
for(int byte = 0; byte < 16; byte++){
193-
commandAPDU(5+byte) = plaintext(byte, measurement);
216+
// Download the sampled data from oscilloscope
217+
oscilloscope->getValues(m_channel, &( measuredTraces(0, run * capturesPerRun) ), capturesPerRun * samplesPerTrace, measuredSamples, measuredCaptures);
218+
219+
if(measuredSamples != samplesPerTrace || measuredCaptures != capturesPerRun){
220+
throw RuntimeException("Measurement went wrong: samples*captures mismatch");
194221
}
195-
// send APDU
196-
charDevice->send(commandAPDU);
222+
223+
} catch (std::exception & e){ // an oscilloscope run or communication with the target failed
197224

198-
// Receive ciphertext
225+
cout << QString("\n[!] An error has occured during the %1. oscilloscope run: %2\n").arg(run+1).arg(e.what());
226+
cout << QString("[!] Before an error, %1 power traces were measured and will be saved.\n").arg(run * capturesPerRun);
227+
cout.flush();
199228

200-
// receive APDU
201-
if(charDevice->receive(responseAPDU) != 18) throw RuntimeException("Failed to receive 18 bytes APDU response (16 bytes ciphertext + SW1 + SW2).");
202-
// copy ciphertext
203-
for(int byte = 0; byte < 16; byte++){
204-
ciphertext(byte, measurement) = responseAPDU(byte);
205-
}
229+
measurements = run * capturesPerRun; // update the number of succesfully performed measurements
206230

207-
CoutProgress::get().update(measurement);
231+
// Shrink the containers to fit the data actually measured
232+
measuredTraces.shrinkRows(measurements);
233+
plaintext.shrinkRows(measurements);
234+
ciphertext.shrinkRows(measurements);
235+
236+
break; // break the measurement
208237

209-
}
210-
211-
size_t measuredSamples;
212-
size_t measuredCaptures;
213-
214-
// Download the sampled data from oscilloscope
215-
oscilloscope->getValues(m_channel, &( measuredTraces(0, run * capturesPerRun) ), capturesPerRun * samplesPerTrace, measuredSamples, measuredCaptures);
216-
217-
if(measuredSamples != samplesPerTrace || measuredCaptures != capturesPerRun){
218-
throw RuntimeException("Measurement went wrong: samples*captures mismatch");
219238
}
220239

221240
}

plugins/measurement/random128co/random128co.cpp

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -149,39 +149,58 @@ void Random128CO::run(const char * measurementId, size_t measurements, Oscillosc
149149
// We run the oscilloscope runs times
150150
for(size_t run = 0; run < runs; run++){
151151

152-
oscilloscope->run(); //< Start capturing capturesPerRun captures
152+
try { // try to perform a measurement run
153153

154-
// Send capturesPerRun blocks to cipher
155-
for(size_t capture = 0; capture < capturesPerRun; capture++){
154+
oscilloscope->run(); //< Start capturing capturesPerRun captures
156155

157-
size_t measurement = run * capturesPerRun + capture; //< Number of current measurement
158-
159-
// Generate random plaintext
160-
for(int byte = 0; byte < 16; byte++){
156+
// Send capturesPerRun blocks to cipher
157+
for(size_t capture = 0; capture < capturesPerRun; capture++){
158+
159+
size_t measurement = run * capturesPerRun + capture; //< Number of current measurement
160+
161+
// Generate random plaintext
162+
for(int byte = 0; byte < 16; byte++){
163+
164+
plaintext(byte, measurement) = (uint8_t) byteUnif(prng);
165+
166+
}
167+
168+
// Send plaintext
169+
charDevice->send(command); //< Send the encryption command
170+
charDevice->send( &( plaintext(0, measurement) ), 16); //< Send 16 bytes of plaintext //TODO MatrixRowPtr
171+
172+
// Receive ciphertext
173+
charDevice->receive( &( ciphertext(0, measurement) ), 16); //< Receive 16 bytes of ciphertext //TODO MatrixRowPtr
174+
175+
CoutProgress::get().update(measurement);
161176

162-
plaintext(byte, measurement) = (uint8_t) byteUnif(prng);
163-
164177
}
165178

166-
// Send plaintext
167-
charDevice->send(command); //< Send the encryption command
168-
charDevice->send( &( plaintext(0, measurement) ), 16); //< Send 16 bytes of plaintext //TODO MatrixRowPtr
179+
size_t measuredSamples;
180+
size_t measuredCaptures;
169181

170-
// Receive ciphertext
171-
charDevice->receive( &( ciphertext(0, measurement) ), 16); //< Receive 16 bytes of ciphertext //TODO MatrixRowPtr
182+
// Download the sampled data from oscilloscope
183+
oscilloscope->getValues(m_channel, &( measuredTraces(0, run * capturesPerRun) ), capturesPerRun * samplesPerTrace, measuredSamples, measuredCaptures);
172184

173-
CoutProgress::get().update(measurement);
174-
175-
}
176-
177-
size_t measuredSamples;
178-
size_t measuredCaptures;
179-
180-
// Download the sampled data from oscilloscope
181-
oscilloscope->getValues(m_channel, &( measuredTraces(0, run * capturesPerRun) ), capturesPerRun * samplesPerTrace, measuredSamples, measuredCaptures);
185+
if(measuredSamples != samplesPerTrace || measuredCaptures != capturesPerRun){
186+
throw RuntimeException("Measurement went wrong: samples*captures mismatch");
187+
}
182188

183-
if(measuredSamples != samplesPerTrace || measuredCaptures != capturesPerRun){
184-
throw RuntimeException("Measurement went wrong: samples*captures mismatch");
189+
} catch (std::exception & e){ // an oscilloscope run or communication with the target failed
190+
191+
cout << QString("\n[!] An error has occured during the %1. oscilloscope run: %2\n").arg(run+1).arg(e.what());
192+
cout << QString("[!] Before an error, %1 power traces were measured and will be saved.\n").arg(run * capturesPerRun);
193+
cout.flush();
194+
195+
measurements = run * capturesPerRun; // update the number of succesfully performed measurements
196+
197+
// Shrink the containers to fit the data actually measured
198+
measuredTraces.shrinkRows(measurements);
199+
plaintext.shrinkRows(measurements);
200+
ciphertext.shrinkRows(measurements);
201+
202+
break; // break the measurement
203+
185204
}
186205

187206
}

plugins/measurement/ttest128apdu/ttest128apdu.cpp

Lines changed: 62 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -185,67 +185,83 @@ void TTest128APDU::run(const char * measurementId, size_t measurements, Oscillos
185185
// We run the oscilloscope runs times
186186
for(size_t run = 0; run < runs; run++){
187187

188-
oscilloscope->run(); //< Start capturing capturesPerRun captures
188+
try { // try to perform a measurement run
189189

190-
// Send capturesPerRun blocks to cipher
191-
for(size_t capture = 0; capture < capturesPerRun; capture++){
190+
oscilloscope->run(); //< Start capturing capturesPerRun captures
192191

193-
size_t measurement = run * capturesPerRun + capture; //< Number of current measurement
194-
195-
isTraceConstant(measurement) = (uint8_t) bitUnif(prng) % 2; //< Decide whatever next measurement will be random or constant
196-
197-
if(isTraceConstant(measurement)){
198-
199-
// Use constant plaintext
200-
for(int byte = 0; byte < 16; byte++){
192+
// Send capturesPerRun blocks to cipher
193+
for(size_t capture = 0; capture < capturesPerRun; capture++){
194+
195+
size_t measurement = run * capturesPerRun + capture; //< Number of current measurement
196+
197+
isTraceConstant(measurement) = (uint8_t) bitUnif(prng) % 2; //< Decide whatever next measurement will be random or constant
198+
199+
if(isTraceConstant(measurement)){
200+
201+
// Use constant plaintext
202+
for(int byte = 0; byte < 16; byte++){
203+
204+
plaintext(byte, measurement) = constPlaintext[byte];
205+
206+
}
201207

202-
plaintext(byte, measurement) = constPlaintext[byte];
203-
204-
}
208+
} else {
209+
210+
// Generate random plaintext
211+
for(int byte = 0; byte < 16; byte++){
212+
213+
plaintext(byte, measurement) = (uint8_t) byteUnif(prng);
214+
215+
}
216+
217+
}
205218

206-
} else {
219+
// Send plaintext
207220

208-
// Generate random plaintext
221+
// fill APDU with plaintext
209222
for(int byte = 0; byte < 16; byte++){
210-
211-
plaintext(byte, measurement) = (uint8_t) byteUnif(prng);
223+
commandAPDU(5+byte) = plaintext(byte, measurement);
224+
}
225+
// send APDU
226+
charDevice->send(commandAPDU);
212227

213-
}
214228

215-
}
229+
// Receive ciphertext
230+
231+
// receive APDU
232+
if(charDevice->receive(responseAPDU) != 18) throw RuntimeException("Failed to receive 18 bytes APDU response (16 bytes ciphertext + SW1 + SW2).");
233+
// copy ciphertext
234+
for(int byte = 0; byte < 16; byte++){
235+
ciphertext(byte, measurement) = responseAPDU(byte);
236+
}
237+
238+
239+
CoutProgress::get().update(measurement);
240+
241+
}
216242

217-
// Send plaintext
243+
size_t measuredSamples;
244+
size_t measuredCaptures;
218245

219-
// fill APDU with plaintext
220-
for(int byte = 0; byte < 16; byte++){
221-
commandAPDU(5+byte) = plaintext(byte, measurement);
222-
}
223-
// send APDU
224-
charDevice->send(commandAPDU);
225-
246+
// Download the sampled data from oscilloscope
247+
oscilloscope->getValues(m_channel, &( measuredTraces(0, run * capturesPerRun) ), capturesPerRun * samplesPerTrace, measuredSamples, measuredCaptures);
226248

227-
// Receive ciphertext
228-
229-
// receive APDU
230-
if(charDevice->receive(responseAPDU) != 18) throw RuntimeException("Failed to receive 18 bytes APDU response (16 bytes ciphertext + SW1 + SW2).");
231-
// copy ciphertext
232-
for(int byte = 0; byte < 16; byte++){
233-
ciphertext(byte, measurement) = responseAPDU(byte);
249+
if(measuredSamples != samplesPerTrace || measuredCaptures != capturesPerRun){
250+
throw RuntimeException("Measurement went wrong: samples*captures mismatch");
234251
}
235252

253+
} catch (std::exception & e){ // an oscilloscope run or communication with the target failed
236254

237-
CoutProgress::get().update(measurement);
255+
cout << QString("\n[!] An error has occured during the %1. oscilloscope run: %2\n").arg(run+1).arg(e.what());
256+
cout << QString("[!] Before an error, %1 power traces were measured and will be saved.\n").arg(run * capturesPerRun);
257+
cout.flush();
258+
259+
measurements = run * capturesPerRun; // update the number of succesfully performed measurements
260+
261+
// No need to shrink the containers here, since every single measurement is written to file separately
262+
263+
break; // break the measurement
238264

239-
}
240-
241-
size_t measuredSamples;
242-
size_t measuredCaptures;
243-
244-
// Download the sampled data from oscilloscope
245-
oscilloscope->getValues(m_channel, &( measuredTraces(0, run * capturesPerRun) ), capturesPerRun * samplesPerTrace, measuredSamples, measuredCaptures);
246-
247-
if(measuredSamples != samplesPerTrace || measuredCaptures != capturesPerRun){
248-
throw RuntimeException("Measurement went wrong: samples*captures mismatch");
249265
}
250266

251267
}

0 commit comments

Comments
 (0)