aboutsummaryrefslogtreecommitdiffstats
path: root/src/block/gost_28147/gost_28147.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/block/gost_28147/gost_28147.cpp')
-rw-r--r--src/block/gost_28147/gost_28147.cpp106
1 files changed, 106 insertions, 0 deletions
diff --git a/src/block/gost_28147/gost_28147.cpp b/src/block/gost_28147/gost_28147.cpp
new file mode 100644
index 000000000..ad57a2ca7
--- /dev/null
+++ b/src/block/gost_28147/gost_28147.cpp
@@ -0,0 +1,106 @@
+/*
+* GOST 28147-89
+* (C) 1999-2009 Jack Lloyd
+*/
+
+#include <botan/gost_28147.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+/*
+* GOST Constructor
+*/
+GOST_28147_89::GOST_28147_89() : BlockCipher(8, 32)
+ {
+
+ // GostR3411_94_TestParamSet (OID 1.2.643.2.2.31.0)
+ const byte sbox[8][16] = {
+ {0x4,0xA,0x9,0x2,0xD,0x8,0x0,0xE,0x6,0xB,0x1,0xC,0x7,0xF,0x5,0x3}
+ {0xE,0xB,0x4,0xC,0x6,0xD,0xF,0xA,0x2,0x3,0x8,0x1,0x0,0x7,0x5,0x9},
+ {0x5,0x8,0x1,0xD,0xA,0x3,0x4,0x2,0xE,0xF,0xC,0x7,0x6,0x0,0x9,0xB},
+ {0x7,0xD,0xA,0x1,0x0,0x8,0x9,0xF,0xE,0x4,0x6,0xC,0xB,0x2,0x5,0x3},
+ {0x6,0xC,0x7,0x1,0x5,0xF,0xD,0x8,0x4,0xA,0x9,0xE,0x0,0x3,0xB,0x2},
+ {0x4,0xB,0xA,0x0,0x7,0x2,0x1,0xD,0x3,0x6,0x8,0x5,0x9,0xC,0xF,0xE},
+ {0xD,0xB,0x4,0x1,0x3,0xF,0x5,0x9,0x0,0xA,0xE,0x7,0x6,0x8,0x2,0xC},
+ {0x1,0xF,0xD,0x0,0x5,0x7,0xA,0x4,0x9,0x2,0x3,0xE,0x6,0xB,0x8,0xC},
+ };
+
+ for(size_t i = 0; i != 4; ++i)
+ for(size_t j = 0; j != 256; ++j)
+ {
+ u32bit T = sbox[2*i][j%16] | (sbox[2*i+1][j/16] << 4);
+ SBOX[256*i+j] = rotate_left(T, (11+8*i) % 32);
+ }
+ }
+
+/*
+* 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)
+ {
+ 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];
+ }
+
+ store_le(out, N2, N1);
+ }
+
+/*
+* GOST Decryption
+*/
+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)
+ {
+ 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];
+ }
+
+ store_le(out, N2, N1);
+ }
+
+/*
+* GOST Key Schedule
+*/
+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)];
+ }
+
+}