Commit d19b08d5 authored by YUSHIQIAN's avatar YUSHIQIAN

basic timing attack 2081 experiments

parent 07ee78d2
This diff is collapsed.
This diff is collapsed.
CC = gcc
CFLAGS = -Wall -ansi -c -O3
INCLUDES = -I./include
LD = gcc
LDFLAGS =
LIBS =
SRCS = $(wildcard src/*.c)
OBJS = $(patsubst %.c,%.o,$(SRCS))
EXECS = ta des_ta
BINDIR = /datas/teaching/courses/HWSec/labs/bin
.PHONY: help all clean ultraclean
help:
@echo "Type:"
@echo "<make> or <make help> to get this help message"
@echo "<make all> to generate the 'ta' and 'des_ta' executable"
@echo "<make clean> to clean a bit"
@echo "<make ultraclean> to really clean"
all: $(EXECS)
ta: ta.o p.o $(OBJS)
$(LD) $(LDFLAGS) $^ -o $@ $(LIBS) -lm
des_ta: des_ta.o p.o $(OBJS)
$(LD) $(LDFLAGS) $^ -o $@ $(LIBS) -lm
%.o: %.c
$(CC) $(CFLAGS) $(INCLUDES) $< -o $@
clean:
rm -f $(OBJS) des_ta.o p.o ta.o
ultraclean:
rm -f $(OBJS) $(EXECS) des_ta.o ta.o ta.o
File added
/**********************************************************************************
Copyright Institut Telecom
Contributors: Renaud Pacalet (renaud.pacalet@telecom-paristech.fr)
This software is a computer program whose purpose is to experiment timing and
power attacks against crypto-processors.
This software is governed by the CeCILL license under French law and
abiding by the rules of distribution of free software. You can use,
modify and/ or redistribute the software under the terms of the CeCILL
license as circulated by CEA, CNRS and INRIA at the following URL
"http://www.cecill.info".
As a counterpart to the access to the source code and rights to copy,
modify and redistribute granted by the license, users are provided only
with a limited warranty and the software's author, the holder of the
economic rights, and the successive licensors have only limited
liability.
In this respect, the user's attention is drawn to the risks associated
with loading, using, modifying and/or developing or reproducing the
software by the user in light of its specific status of free software,
that may mean that it is complicated to manipulate, and that also
therefore means that it is reserved for developers and experienced
professionals having in-depth computer knowledge. Users are therefore
encouraged to load and test the software's suitability as regards their
requirements in conditions enabling the security of their systems and/or
data to be ensured and, more generally, to use and operate it in the
same conditions as regards security.
The fact that you are presently reading this means that you have had
knowledge of the CeCILL license and that you accept its terms. For more
information see the LICENCE-fr.txt or LICENSE-en.txt files.
**********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/times.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
#include <math.h>
#include <utils.h>
#include <des.h>
#include <rdtsc_timer.h>
uint64_t
rand_uint64_t (void)
{
uint64_t res;
int i;
res = UINT64_C (0x0);
for (i = 0; i < 4; i++)
{
res <<= 16;
res |= (uint64_t) (rand () & 0xffff);
}
return res;
}
extern uint64_t des_p_ta (uint64_t val);
uint64_t
des_f_ta (uint64_t rk, uint64_t val)
{
if (val >> 32)
{
ERROR (-1, "illegal R input value for F function: %016" PRIx64, val);
}
if (rk >> 48)
{
ERROR (-1, "illegal RK input value for F function: %016" PRIx64, rk);
}
return des_p_ta (des_sboxes (des_e (val) ^ rk));
}
uint64_t
des_enc_ta (uint64_t * ks, uint64_t val)
{
uint64_t lr, r, l, tmp;
int i;
lr = des_ip (val);
r = des_right_half (lr);
l = des_left_half (lr);
for (i = 0; i < 16; i++)
{
tmp = r;
r = l ^ des_f_ta (ks[i], r);
l = tmp;
}
return des_fp ((r << 32) | l);
}
extern int
des_check_f (uint64_t (*f_enc) (uint64_t *, uint64_t),
uint64_t (*f_dec) (uint64_t *, uint64_t));
int
des_check_ta (void)
{
return des_check_f (des_enc_ta, des_dec);
}
int
measure (uint64_t * ks, uint64_t pt, double th, int average, double *time,
uint64_t * ct)
{
uint64_t a, b, t, min, *m;
int i, n, cnt;
if (average < 1)
{
ERROR (-1, "illegal average value: %d", average);
}
if (th < 1.0)
{
ERROR (-1, "illegal threshold value: %f", th);
}
m = XCALLOC (average, sizeof (uint64_t));
min = UINT64_C (0);
for (i = 0; i < average; i++)
{
a = get_rdtsc_timer ();
*ct = des_enc_ta (ks, pt);
b = get_rdtsc_timer ();
t = b - a;
m[i] = t;
if (i == 0 || t < min)
{
min = t;
}
}
n = 0;
i = 0;
cnt = average;
while (n < average)
{
if (m[i] <= th * min)
{
n += 1;
i = (i + 1) % average;
}
else
{
do
{
a = get_rdtsc_timer ();
*ct = des_enc_ta (ks, pt);
b = get_rdtsc_timer ();
cnt += 1;
t = b - a;
}
while (t > min * th);
if (t < min)
{
n = 0;
min = t;
}
m[i] = t;
n += 1;
i = (i + 1) % average;
}
}
t = 0;
for (i = 0; i < average; i++)
{
t += m[i];
}
*time = (double) (t) / (double) (average);
return cnt;
}
#define TH 1.1
#define AVG 10
uint64_t str2key(char *);
int
main (int argc, char **argv)
{
int n, i, j, k, l;
uint64_t ks[16], pt, ct, key;
double t;
#ifdef SRAND
struct tms dummy;
#endif
if (!des_check_ta ())
{
ERROR (-1, "%s: DES functional test failed", argv[0]);
}
if (argc != 3)
{
ERROR (-1, "usage: %s <n> <key>", argv[0]);
}
n = atoi (argv[1]);
if (n < 1)
{
ERROR (-1,
"%s: number of experiments (<n>) shall be greater than 1 (%d)",
argv[0], n);
}
key = str2key(argv[2]);
des_ks (ks, key);
#ifdef DEBUG
for (i = 0; i < 8; i++)
{
fprintf (stderr, "%02" PRIx32 " ",
(uint32_t) ((ks[15] >> ((7 - i) * 6)) & UINT64_C (0x3f)));
}
fprintf (stderr, "\n");
#endif
#ifdef SRAND
srand (times (&dummy));
#else
srand (0);
#endif
j = n / 100;
k = 0;
l = 0;
for (i = 0; i < n; i++)
{
pt = rand_uint64_t ();
if (i == 0)
{
printf ("%016" PRIx64 "\n", pt);
}
measure (ks, pt, TH, AVG, &t, &ct);
if (ct != des_enc_ta (ks, pt))
{
ERROR (-1, "data dependent DES functionally incorrect");
}
printf ("%016" PRIx64 " %f\n", ct, t);
k += 1;
if (k == j)
{
l += 1;
fprintf (stderr, "%3d%%", l);
k = 0;
}
}
fprintf (stderr, "\n");
return 0;
}
uint64_t str2key(char * str) {
uint64_t res;
int i, v;
v = 0;
res = UINT64_C (0);
for(i = 0; i < strlen(str); i++) {
switch(str[i]) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9': v = str[i] - '0';
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f': v = str[i] - 'a' + 10;
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F': v = str[i] - 'A' + 10;
break;
default: ERROR (-1, "unvalid key value: %s", str);
break;
}
if((res >> 60) != UINT64_C (0)) {
ERROR (-1, "key overflow: %s", str);
}
res = (res << 4) | (uint64_t)(v);
}
return res;
}
File added
/** \file des.h
* The \b des library, a software library dedicated to the Data Encryption
* Standard (DES).
* \author Renaud Pacalet, renaud.pacalet@telecom-paristech.fr
* \date 2009-07-08
* \attention
* <ol>
* <li>Most functions of the \b des library check their input parameters and
* issue warnings or errors when they carry illegal values. Warnings are
* printed on the standard error output. Errors are also printed on the
* standard error output and the program exits with a -1 exit status.</li>
* <li>The \b des library uses a single data type to represent all the data of
* the DES standard: ::uint64_t. It is a 64 bits unsigned integer.</li>
* <li>Data are always right aligned: when the data width is less than 64 bits,
* the meaningful bits are always the rightmost bits of the ::uint64_t.</li>
* </ol>
*/
#ifndef DES_H
#define DES_H
#include <stdint.h>
#include <inttypes.h>
/** Number of left shifts per round.
* left_shifts[0] corresponds to round #1, ... left_shifts[15] corresponds to
* round #16. A value of 0 means one shift. A value of 1 means two shifts. */
extern uint8_t left_shifts[16];
/** Initial permutation (64 to 64 bits).
* Same as des_n_fp(). \return The permutated input as a 64 bits ::uint64_t. */
uint64_t des_ip (uint64_t val /**< 64 bits input. */ );
/** Inverse of initial permutation (64 to 64 bits).
* Same as des_fp(). \return The permutated input as a 64 bits ::uint64_t. */
uint64_t des_n_ip (uint64_t val /**< 64 bits input. */ );
/** Final permutation (64 to 64 bits).
* Inverse of initial permutation, same as des_n_ip(). \return The permutated
* input as a 64 bits ::uint64_t. */
uint64_t des_fp (uint64_t val /**< 64 bits input. */ );
/** Inverse of final permutation (64 to 64 bits).
* Same as des_ip(). \return The permutated input as a 64 bits ::uint64_t. */
uint64_t des_n_fp (uint64_t val /**< 64 bits input. */ );
/** E expansion - permutation (32 to 48 bits). \return The expanded and
* permutated input as a 48 bits ::uint64_t. */
uint64_t des_e (uint64_t val /**< 32 bits input. */ );
/** Inverse of E expansion - permutation (48 to 32 bits).
* Duplicated bits must have the same value. If they do not, an error is raised.
* \return The permutated and selected input as a 32 bits ::uint64_t. */
uint64_t des_n_e (uint64_t val /**< 48 bits input. */ );
/** P permutation (32 to 32 bits). \return The permutated input as a 32 bits
* ::uint64_t. */
uint64_t des_p (uint64_t val /**< 32 bits input. */ );
/** Inverse of P permutation (32 to 32 bits). \return The permutated input as a
* 32 bits ::uint64_t. */
uint64_t des_n_p (uint64_t val /**< 32 bits input. */ );
/** PC1 permutation - selection (64 to 56 bits).
* No parity check. \return The permutated and selected input as a 56 bits
* ::uint64_t. */
uint64_t des_pc1 (uint64_t val /**< 64 bits input. */ );
/** Computes the 8 parity bits of a 64 bits word.
* Parity bits are the rightmost bit of each byte. Once computed, the number of
* set bits of each byte is odd, as specified in the DES standard. \return The
* input with odd parity bits, as a 64 bits ::uint64_t. */
uint64_t des_set_parity_bits (uint64_t val /**< 64 bits input. */ );
/** Inverse of PC1 permutation - selection (56 to 64 bits).
* Parity bits are computed. \return The permutated and expanded input as a 64
* bits ::uint64_t. */
uint64_t des_n_pc1 (uint64_t val /**< 56 bits input. */ );
/** PC2 permutation - selection (56 to 48 bits). \return The permutated and
* selected input as a 48 bits ::uint64_t. */
uint64_t des_pc2 (uint64_t val /**< 56 bits input. */ );
/** Inverse of PC2 permutation - selection (48 to 56 bits).
* Missing bits are set to 0. \return The permutated and expanded input as a 56
* bits ::uint64_t. */
uint64_t des_n_pc2 (uint64_t val /**< 48 bits input. */ );
/** Single SBox computation (6 to 4 bits). \return The 4 bits output of SBox
* number ::sbox corresponding to the 4 bits input, as a 4 bits
* ::uint64_t. */
uint64_t des_sbox (int sbox /**< SBox number, from 1 to 8. */ ,
uint64_t val
/**< 6 bits input. */
);
/** All SBoxes computation (48 to 32 bits). \return The 32 bits output of all
* SBoxes corresponding to the 48 bits input, as a 32 bits ::uint64_t. */
uint64_t des_sboxes (uint64_t val /**< 48 bits input. */ );
/** Returns the 32 bits right half of a 64 bits word. \return The 32 bits right
* half of a 64 bits word, as a 32 bits ::uint64_t. */
uint64_t des_right_half (uint64_t val /**< 64 bits input. */ );
/** Returns the 32 bits left half of a 64 bits word. \return The 32 bits left
* half of a 64 bits word, as a 32 bits ::uint64_t. */
uint64_t des_left_half (uint64_t val /**< 64 bits input. */ );
/** Applies the <strong>left shift</strong> rotation of the standard (56 to 56
* bits). \return The rotated input, as a 56 bits ::uint64_t. */
uint64_t des_ls (uint64_t val /**< 56 bits input. */ );
/** Applies the <strong>right shift</strong> rotation of the standard (56 to 56
* bits). \return The rotated input, as a 56 bits ::uint64_t. */
uint64_t des_rs (uint64_t val /**< 56 bits input. */ );
/** The F function of the standard (48+32 bits to 32 bits). \return The
* transformed input, as a 32 bits ::uint64_t. */
uint64_t des_f (uint64_t rk /**< 48 bits round key. */ ,
uint64_t val
/**< 32 bits data input. */
);
/** Computes the whole key schedule from a 64 bits secret key and stores the
* sixteen 48 bits round keys in an array. \return The sixteen 48 bits round
* keys in the array passed as first parameter. */
void des_ks (
/** The array where to store the sixteen 48 bits round keys.
* On return \e ks[0] holds the first round key, ..., \e ks[15] holds the
* last round key. Must be allocated prior the call. */
uint64_t * ks, uint64_t val
/**< 64 bits key. */
);
/** Enciphers a 64 bits plaintext with a pre-computed key schedule. \return The
* enciphered plaintext as a 64 bits ::uint64_t. */
uint64_t des_enc (uint64_t * ks /**< The pre-computed key schedule. */ ,
uint64_t val
/**< The 64 bits plaintext. */
);
/** Deciphers a 64 bits plaintext with a pre-computed key schedule. \return The
* deciphered ciphertext as a 64 bits ::uint64_t. */
uint64_t des_dec (uint64_t * ks /**< The pre-computed key schedule. */ ,
uint64_t val
/**< The 64 bits ciphertext. */
);
/** A functional verification of the DES implementation. Runs a number of
* encipherments with des_enc() and the corresponding decipherments with
* des_dec() and checks the results against pre-computed plaintext, ciphertexts
* and secret keys. If compiled in DEBUG mode, prints warnings on mismatches or
* a \b OK message if the tests pass. Returns one on success, zero on errors. */
int des_check (void);
#endif /** not DES_H */
/**********************************************************************************
Copyright Institut Telecom
Contributors: Renaud Pacalet (renaud.pacalet@telecom-paristech.fr)
This software is a computer program whose purpose is to experiment timing and
power attacks against crypto-processors.
This software is governed by the CeCILL license under French law and
abiding by the rules of distribution of free software. You can use,
modify and/ or redistribute the software under the terms of the CeCILL
license as circulated by CEA, CNRS and INRIA at the following URL
"http://www.cecill.info".
As a counterpart to the access to the source code and rights to copy,
modify and redistribute granted by the license, users are provided only
with a limited warranty and the software's author, the holder of the
economic rights, and the successive licensors have only limited
liability.
In this respect, the user's attention is drawn to the risks associated
with loading, using, modifying and/or developing or reproducing the
software by the user in light of its specific status of free software,
that may mean that it is complicated to manipulate, and that also
therefore means that it is reserved for developers and experienced
professionals having in-depth computer knowledge. Users are therefore
encouraged to load and test the software's suitability as regards their
requirements in conditions enabling the security of their systems and/or
data to be ensured and, more generally, to use and operate it in the
same conditions as regards security.
The fact that you are presently reading this means that you have had
knowledge of the CeCILL license and that you accept its terms. For more
information see the LICENCE-fr.txt or LICENSE-en.txt files.
**********************************************************************************/
/** \file km.h
* A data structure and a set of functions to manage the partial knowledge
* about a DES (Data Encryption Standard) secret key.
* \author Renaud Pacalet, renaud.pacalet@telecom-paristech.fr
* \date 2009-07-08
*/
#ifndef KM_H
#define KM_H
#include <stdint.h>
#include <inttypes.h>
/** A data structure to manage the partial knowledge we have about a 64 bits
* secret key KEY. */
struct des_key_manager_s
{
/** The 56 bits word representing C0D0 = C16D16 = PC1(KEY). */
uint64_t key;
/** The 56 bits word in which each set bit indicates a known bit. */
uint64_t mask;
};
/** A pointer to the data structure. */
typedef struct des_key_manager_s *des_key_manager;
/** Allocates and initializes a key manager with zero-knowledge.
* \return An initialized key manager. */
des_key_manager des_km_init (void);
/** Return the number of known bits. \return The number of known bits. */
int des_km_known (des_key_manager km /**< The key manager. */ );
/** Injects in a key manager a known value of a 6 bits subkey of a 48 bits round
* key.
* \return Zero if a conflict was detected between the new bit values and some
* previously known ones, a non zero value if there was no conflict. */
int des_km_set_sk (des_key_manager km /**< The key manager. */ ,
int rk
/**< The round key number (1 for the first to 16 for the last). */
, int sk
/**< The subkey number (1 for the leftmost to 8 for the righmost). */
,
/** A flag specifying what to do in case the injected knowledge conflicts
* with previous knowledge.
* If non-zero, the new bit values overwrite the old conflicting values. If
* zero, the old values are unchanged. */
int force,
/** A 6 bits mask indicating which bits of the subkey are injected: only
* these which corresponding mask bit is set (equal to 1) are injected. */
uint64_t mask, uint64_t val
/**< The 6 bits subkey to inject. */
);
/** Injects in a key manager a known value of a 48 bits round key.
* \return Zero if a conflict was detected between the new bit values and some
* previously known ones, a non zero value if there was no conflict. */
int des_km_set_rk (des_key_manager km /**< The key manager. */ ,
int rk
/**< The round key number (1 for the first to 16 for the last). */
,
/** A flag specifying what to do in case the injected knowledge conflicts
* with previous knowledge.
* If non-zero, the new bit values overwrite the old conflicting values. If
* zero, the old values are unchanged. */
int force,
/** A 48 bits mask indicating which bits of the round key are injected: only
* these which corresponding mask bit is set (equal to 1) are injected. */
uint64_t mask, uint64_t val
/**< The 48 bits round key to inject. */
);
/** Injects in a key manager a known value of a 56 bits secret key (after
* PC1 (Permutated Choice 1), that is, C0D0 or C16D16 of the DES standard).
* \return Zero if a conflict was detected between the new bit values and some
* previously known ones, a non zero value if there was no conflict. */
uint64_t des_km_set_c0d0 (des_key_manager km /**< The key manager. */ ,
/** A flag specifying what to do in case the injected knowledge conflicts
* with previous knowledge.
* If non-zero, the new bit values overwrite the old conflicting values. If
* zero, the old values are unchanged. */
int force,
/** A 56 bits mask indicating which bits of the round key are injected: only
* these which corresponding mask bit is set (equal to 1) are injected. */
uint64_t mask, uint64_t val
/**< The 56 bits secret key to inject. */
);
/** Injects in a key manager a known value of a 64 bits secret key.
* No parity check. \return Zero if a conflict was detected between the new bit
* values and some previously known ones, a non zero value if there was no
* conflict. */
int des_km_set_key (des_key_manager km /**< The key manager. */ ,
/** A flag specifying what to do in case the injected knowledge conflicts
* with previous knowledge.
* If non-zero, the new bit values overwrite the old conflicting values. If
* zero, the old values are unchanged. */
int force,
/** A 64 bits mask indicating which bits of the round key are injected: only
* these which corresponding mask bit is set (equal to 1) are injected. */
uint64_t mask, uint64_t val
/**< The 64 bits secret key to inject. */
);
/** Extracts from a key manager the knowledge about a subkey of a round key.
* \return The subkey as a 6 bits ::uint64_t, and a mask indicating which bits