aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2009-03-31 01:51:32 +0000
committerlloyd <[email protected]>2009-03-31 01:51:32 +0000
commit1309862b2d60622129ba5f3fdaadc8b763d842a8 (patch)
tree3be10e240f1a7f5b88a1d4922d00f261b6b18488
parent96d6eb6f29c55e16a37cf11899547886f735b065 (diff)
Partially unroll the round structure, enough so that the subkey accesses
can be done directly, so there is no need to copy the key several times for the key schedule (since the GOST 'key schedule' is very simple and the access pattern can now be directly inserted into the code). Looks to be about 10% faster on my Core2, as well.
-rw-r--r--src/block/gost_28147/gost_28147.cpp74
-rw-r--r--src/block/gost_28147/gost_28147.h2
2 files changed, 40 insertions, 36 deletions
diff --git a/src/block/gost_28147/gost_28147.cpp b/src/block/gost_28147/gost_28147.cpp
index 0f29102de..d433924fc 100644
--- a/src/block/gost_28147/gost_28147.cpp
+++ b/src/block/gost_28147/gost_28147.cpp
@@ -37,29 +37,43 @@ GOST_28147_89::GOST_28147_89() : BlockCipher(8, 32)
}
/*
+* Two rounds of GOST
+*/
+#define GOST_2ROUND(N1, N2, R1, R2) \
+ { \
+ u32bit T0 = N1 + EK[R1]; \
+ N2 ^= SBOX[get_byte(3, T0)] | \
+ SBOX[get_byte(2, T0)+256] | \
+ SBOX[get_byte(1, T0)+512] | \
+ SBOX[get_byte(0, T0)+768]; \
+ \
+ T0 = N2 + EK[R2]; \
+ N1 ^= SBOX[get_byte(3, T0)] | \
+ SBOX[get_byte(2, T0)+256] | \
+ SBOX[get_byte(1, T0)+512] | \
+ SBOX[get_byte(0, T0)+768]; \
+ }
+
+/*
* GOST Encryption
*/
void GOST_28147_89::enc(const byte in[], byte out[]) const
{
u32bit N1 = load_le<u32bit>(in, 0), N2 = load_le<u32bit>(in, 1);
- for(u32bit j = 0; j != 32; j += 2)
+ for(size_t i = 0; i != 3; ++i)
{
- u32bit T0;
-
- T0 = N1 + EK[j];
- N2 ^= SBOX[get_byte(3, T0)] |
- SBOX[get_byte(2, T0)+256] |
- SBOX[get_byte(1, T0)+512] |
- SBOX[get_byte(0, T0)+768];
-
- T0 = N2 + EK[j+1];
- N1 ^= SBOX[get_byte(3, T0)] |
- SBOX[get_byte(2, T0)+256] |
- SBOX[get_byte(1, T0)+512] |
- SBOX[get_byte(0, T0)+768];
+ GOST_2ROUND(N1, N2, 0, 1);
+ GOST_2ROUND(N1, N2, 2, 3);
+ GOST_2ROUND(N1, N2, 4, 5);
+ GOST_2ROUND(N1, N2, 6, 7);
}
+ GOST_2ROUND(N1, N2, 7, 6);
+ GOST_2ROUND(N1, N2, 5, 4);
+ GOST_2ROUND(N1, N2, 3, 2);
+ GOST_2ROUND(N1, N2, 1, 0);
+
store_le(out, N2, N1);
}
@@ -70,21 +84,17 @@ void GOST_28147_89::dec(const byte in[], byte out[]) const
{
u32bit N1 = load_le<u32bit>(in, 0), N2 = load_le<u32bit>(in, 1);
- for(u32bit j = 0; j != 32; j += 2)
+ GOST_2ROUND(N1, N2, 0, 1);
+ GOST_2ROUND(N1, N2, 2, 3);
+ GOST_2ROUND(N1, N2, 4, 5);
+ GOST_2ROUND(N1, N2, 6, 7);
+
+ for(size_t i = 0; i != 3; ++i)
{
- u32bit T0;
-
- T0 = N1 + EK[31-j];
- N2 ^= SBOX[get_byte(3, T0)] |
- SBOX[get_byte(2, T0)+256] |
- SBOX[get_byte(1, T0)+512] |
- SBOX[get_byte(0, T0)+768];
-
- T0 = N2 + EK[30-j];
- N1 ^= SBOX[get_byte(3, T0)] |
- SBOX[get_byte(2, T0)+256] |
- SBOX[get_byte(1, T0)+512] |
- SBOX[get_byte(0, T0)+768];
+ GOST_2ROUND(N1, N2, 7, 6);
+ GOST_2ROUND(N1, N2, 5, 4);
+ GOST_2ROUND(N1, N2, 3, 2);
+ GOST_2ROUND(N1, N2, 1, 0);
}
store_le(out, N2, N1);
@@ -96,13 +106,7 @@ void GOST_28147_89::dec(const byte in[], byte out[]) const
void GOST_28147_89::key_schedule(const byte key[], u32bit)
{
for(u32bit j = 0; j != 8; ++j)
- {
- u32bit K = load_le<u32bit>(key, j);
- EK[j] = EK[j+8] = EK[j+16] = K;
- }
-
- for(u32bit j = 24; j != 32; ++j)
- EK[j] = EK[7-(j-24)];
+ EK[j] = load_le<u32bit>(key, j);
}
}
diff --git a/src/block/gost_28147/gost_28147.h b/src/block/gost_28147/gost_28147.h
index a58927e28..1ff04b890 100644
--- a/src/block/gost_28147/gost_28147.h
+++ b/src/block/gost_28147/gost_28147.h
@@ -30,7 +30,7 @@ class BOTAN_DLL GOST_28147_89 : public BlockCipher
void key_schedule(const byte[], u32bit);
SecureBuffer<u32bit, 1024> SBOX;
- SecureBuffer<u32bit, 32> EK;
+ SecureBuffer<u32bit, 8> EK;
};
}