malb / algebraic_attacks (http://informatik.uni-bremen.de/~malb/blog.php)
This repository mainly holds code snippets for experimentation with algebraic attacks (and some general crypto code). The quality of this code is not 'release ready' at all. Although the code should work in general there is a lot of scratch, wrong and pathetic code in this repository. Also, some of this code dates back to my Diplomarbeit (master's thesis) and should be considered broken and outdated. By default all code listed here is released under the GPLv2+. Don't hesitate to ping me if you need something under some more permissive license like BSD-style.
Clone this repository (size: 122.6 KB): HTTPS / SSH
$ hg clone http://bitbucket.org/malb/algebraic_attacks/
| commit 35: | ce280e2b1a19 |
| parent 34: | 3dd50c6be752 |
| branch: | default |
| tags: | tip |
fixed a very stupid bug in PRESENT which made the polynomial system unecessarily hard
algebraic_attacks /
present_bitslice.c
| r35:ce280e2b1a19 | 223 loc | 6.9 KB | embed / history / annotate / raw / |
|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | /**
* Bit-Slice Implementation of PRESENT in C99.
* v1.0 09/03/2009
*
* This implementation is not particulary efficient, e.g. on my C2D it
* runs with roughly 28 cycles per byte, which is much worse than any
* efficient AES implementation. It could easily be optimised quite
* a bit by using SSE2, pushing critical paths down to assembly and by
* optimising the sbox() function.
*
* Martin Albrecht <M.R.Albrecht@rhul.ac.uk>
*
* To compile try:
* gcc -O2 -g -std=c99 -lgmp present_bitslice.c -o present_bitslice
*
* TODO:
* - improve performance
* - make it safer, right now we assume sizeof(word) == 8
*/
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gmp.h>
#define RADIX 64
typedef uint64_t word;
#define ONE 1ULL
#define ZERO 0ULL
#define FF (0xFFFFFFFFFFFFFFFFULL)
#define Bs 64
#define Ks 80
void transpose(word *out, word *inp, const size_t out_size, const size_t inp_size) {
for(size_t j=0; j<out_size; j++) {
out[j] = 0;
for(size_t i=0; i<inp_size; i++) {
out[j] |= ((inp[i]&(ONE<<(out_size-j-1)))>>(out_size-j-1))<<(inp_size-i-1);
}
}
}
/** Encryption **/
static inline void sbox(word *Y0, word *Y1, word *Y2, word *Y3, word X0, word X1, word X2, word X3) {
/** TODO: This is the most straight-forward representation possible, optimise it! **/
*Y1 = X0&(X1&X3 ^ X2&X3 ^ X2 ^ X3 ^ FF) ^ X1 ^ X2&X3 ^ FF;
*Y0 = X0&(X1&X3 ^ X2&X3 ^ FF) ^ X1&X2&X3 ^ X1&X2 ^ X2 ^ X3 ^ FF;
*Y2 = X0&(X1&X3 ^ X2&X3 ^ X2 ^ X1 ^ FF) ^ X1&X2&X3 ^ X2;
*Y3 = X0 ^ X1&X2 ^ X1 ^ X3;
}
void sBoxLayer(word *Y, word *X) {
sbox(Y+ 0,Y+ 1,Y+ 2,Y+ 3, X[ 0],X[ 1],X[ 2],X[ 3]);
sbox(Y+ 4,Y+ 5,Y+ 6,Y+ 7, X[ 4],X[ 5],X[ 6],X[ 7]);
sbox(Y+ 8,Y+ 9,Y+10,Y+11, X[ 8],X[ 9],X[10],X[11]);
sbox(Y+12,Y+13,Y+14,Y+15, X[12],X[13],X[14],X[15]);
sbox(Y+16,Y+17,Y+18,Y+19, X[16],X[17],X[18],X[19]);
sbox(Y+20,Y+21,Y+22,Y+23, X[20],X[21],X[22],X[23]);
sbox(Y+24,Y+25,Y+26,Y+27, X[24],X[25],X[26],X[27]);
sbox(Y+28,Y+29,Y+30,Y+31, X[28],X[29],X[30],X[31]);
sbox(Y+32,Y+33,Y+34,Y+35, X[32],X[33],X[34],X[35]);
sbox(Y+36,Y+37,Y+38,Y+39, X[36],X[37],X[38],X[39]);
sbox(Y+40,Y+41,Y+42,Y+43, X[40],X[41],X[42],X[43]);
sbox(Y+44,Y+45,Y+46,Y+47, X[44],X[45],X[46],X[47]);
sbox(Y+48,Y+49,Y+50,Y+51, X[48],X[49],X[50],X[51]);
sbox(Y+52,Y+53,Y+54,Y+55, X[52],X[53],X[54],X[55]);
sbox(Y+56,Y+57,Y+58,Y+59, X[56],X[57],X[58],X[59]);
sbox(Y+60,Y+61,Y+62,Y+63, X[60],X[61],X[62],X[63]);
}
void addRoundKey(word *X, const word *K) {
X[ 0] ^= K[ 0], X[ 1] ^= K[ 1], X[ 2] ^= K[ 2], X[ 3] ^= K[ 3];
X[ 4] ^= K[ 4], X[ 5] ^= K[ 5], X[ 6] ^= K[ 6], X[ 7] ^= K[ 7];
X[ 8] ^= K[ 8], X[ 9] ^= K[ 9], X[10] ^= K[10], X[11] ^= K[11];
X[12] ^= K[12], X[13] ^= K[13], X[14] ^= K[14], X[15] ^= K[15];
X[16] ^= K[16], X[17] ^= K[17], X[18] ^= K[18], X[19] ^= K[19];
X[20] ^= K[20], X[21] ^= K[21], X[22] ^= K[22], X[23] ^= K[23];
X[24] ^= K[24], X[25] ^= K[25], X[26] ^= K[26], X[27] ^= K[27];
X[28] ^= K[28], X[29] ^= K[29], X[30] ^= K[30], X[31] ^= K[31];
X[32] ^= K[32], X[33] ^= K[33], X[34] ^= K[34], X[35] ^= K[35];
X[36] ^= K[36], X[37] ^= K[37], X[38] ^= K[38], X[39] ^= K[39];
X[40] ^= K[40], X[41] ^= K[41], X[42] ^= K[42], X[43] ^= K[43];
X[44] ^= K[44], X[45] ^= K[45], X[46] ^= K[46], X[47] ^= K[47];
X[48] ^= K[48], X[49] ^= K[49], X[50] ^= K[50], X[51] ^= K[51];
X[52] ^= K[52], X[53] ^= K[53], X[54] ^= K[54], X[55] ^= K[55];
X[56] ^= K[56], X[57] ^= K[57], X[58] ^= K[58], X[59] ^= K[59];
X[60] ^= K[60], X[61] ^= K[61], X[62] ^= K[62], X[63] ^= K[63];
}
void pLayer(word *X, word *Y) {
X[ 0] = Y[ 0], X[ 1] = Y[ 4], X[ 2] = Y[ 8], X[ 3] = Y[12];
X[ 4] = Y[16], X[ 5] = Y[20], X[ 6] = Y[24], X[ 7] = Y[28];
X[ 8] = Y[32], X[ 9] = Y[36], X[10] = Y[40], X[11] = Y[44];
X[12] = Y[48], X[13] = Y[52], X[14] = Y[56], X[15] = Y[60];
X[16] = Y[ 1], X[17] = Y[ 5], X[18] = Y[ 9], X[19] = Y[13];
X[20] = Y[17], X[21] = Y[21], X[22] = Y[25], X[23] = Y[29];
X[24] = Y[33], X[25] = Y[37], X[26] = Y[41], X[27] = Y[45];
X[28] = Y[49], X[29] = Y[53], X[30] = Y[57], X[31] = Y[61];
X[32] = Y[ 2], X[33] = Y[ 6], X[34] = Y[10], X[35] = Y[14];
X[36] = Y[18], X[37] = Y[22], X[38] = Y[26], X[39] = Y[30];
X[40] = Y[34], X[41] = Y[38], X[42] = Y[42], X[43] = Y[46];
X[44] = Y[50], X[45] = Y[54], X[46] = Y[58], X[47] = Y[62];
X[48] = Y[ 3], X[49] = Y[ 7], X[50] = Y[11], X[51] = Y[15];
X[52] = Y[19], X[53] = Y[23], X[54] = Y[27], X[55] = Y[31];
X[56] = Y[35], X[57] = Y[39], X[58] = Y[43], X[59] = Y[47];
X[60] = Y[51], X[61] = Y[55], X[62] = Y[59], X[63] = Y[63];
}
void encrypt(word *X, const word *subkeys, const size_t nr) {
static word Y[Bs];
for(size_t i=0; i<nr;i++) {
addRoundKey(X, subkeys + (i*Bs));
sBoxLayer(Y, X);
pLayer(X, Y);
}
addRoundKey(X, subkeys + (nr*Bs));
}
/** Key Schedule **/
void rotate(word *k) {
static word temp[Ks];
memcpy(temp,k,Ks*sizeof(word));
for(size_t i =0; i<Ks; i++) {
k[i] = temp[(61+i)%Ks];
}
}
static inline void round_constant(word *rc, size_t i) {
static word lookup[2] = {ZERO,FF};
rc[4] = lookup[(i&(1<<0))>>0];
rc[3] = lookup[(i&(1<<1))>>1];
rc[2] = lookup[(i&(1<<2))>>2];
rc[1] = lookup[(i&(1<<3))>>3];
rc[0] = lookup[(i&(1<<4))>>4];
}
void key_schedule(word *subkeys, word *key, const size_t nr) {
/** TODO: The key schedule isn't optimised at all */
word *ki = subkeys;
word S[4];
word rc[5];
for(size_t i=0; i<=nr; i++) {
for(size_t j=0; j<Bs; j++)
ki[j] = key[j];
ki+=Bs;
rotate(key);
sbox(&S[0],&S[1],&S[2],&S[3], key[0], key[1], key[2], key[3]);
key[0] = S[0], key[1] = S[1], key[2] = S[2], key[3] = S[3];
round_constant(rc, i+1);
key[Ks-1-19] ^= rc[0], key[Ks-1-18] ^= rc[1], key[Ks-1-17] ^= rc[2];
key[Ks-1-16] ^= rc[3], key[Ks-1-15] ^= rc[4];
}
}
/** PRNG **/
static gmp_randstate_t r_state;
word random_word(void) {
mpz_t rand_n;
mpz_init(rand_n);
mpz_urandomb(rand_n, r_state, 64);
word ret = mpz_get_ui(rand_n);
mpz_clear(rand_n);
return ret;
};
void seed_prng(void) {
struct timeval tp;
(void) gettimeofday(&tp,NULL);
unsigned long seed = tp.tv_sec ^ tp.tv_usec;
gmp_randinit_default(r_state);
gmp_randseed_ui(r_state, seed);
}
int main(int arc, char **argv) {
const size_t ntrials = 1;
seed_prng();
uint64_t plaintexts[RADIX];
uint64_t ciphertexts[RADIX];
word tmp[Bs];
word key[Ks];
size_t nr = 31;
for(size_t i=0;i<Ks;i++)
key[i] = 0;//random_word();
word *subkeys = calloc(Bs * sizeof(word),nr+1);
key_schedule(subkeys, key, nr);
for(size_t i=0; i<Bs; i++)
plaintexts[i] = i;//random_word();
transpose(tmp, plaintexts, Bs, RADIX);
for(size_t i=0;i<ntrials;i++)
encrypt(tmp, subkeys, nr);
transpose(ciphertexts, tmp, RADIX, Bs);
for(size_t i=0; i<Bs; i++) {
printf("%16llx %16llx\n",plaintexts[i],ciphertexts[i]);
}
free(subkeys);
}
|
