Botan  2.1.0
Crypto and TLS for C++11
noekeon_simd.cpp
Go to the documentation of this file.
1 /*
2 * Noekeon in SIMD
3 * (C) 2010 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/noekeon.h>
9 #include <botan/internal/simd_32.h>
10 
11 namespace Botan {
12 
13 /*
14 * Noekeon's Theta Operation
15 */
16 #define NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3) \
17  do { \
18  SIMD_32 T = A0 ^ A2; \
19  SIMD_32 T_l8 = T; \
20  SIMD_32 T_r8 = T; \
21  T_l8.rotate_left(8); \
22  T_r8.rotate_right(8); \
23  T ^= T_l8; \
24  T ^= T_r8; \
25  A1 ^= T; \
26  A3 ^= T; \
27  \
28  A0 ^= K0; \
29  A1 ^= K1; \
30  A2 ^= K2; \
31  A3 ^= K3; \
32  \
33  T = A1 ^ A3; \
34  T_l8 = T; \
35  T_r8 = T; \
36  T_l8.rotate_left(8); \
37  T_r8.rotate_right(8); \
38  T ^= T_l8; \
39  T ^= T_r8; \
40  A0 ^= T; \
41  A2 ^= T; \
42  } while(0)
43 
44 /*
45 * Noekeon's Gamma S-Box Layer
46 */
47 #define NOK_SIMD_GAMMA(A0, A1, A2, A3) \
48  do \
49  { \
50  A1 ^= A3.andc(~A2); \
51  A0 ^= A2 & A1; \
52  \
53  SIMD_32 T = A3; \
54  A3 = A0; \
55  A0 = T; \
56  \
57  A2 ^= A0 ^ A1 ^ A3; \
58  \
59  A1 ^= A3.andc(~A2); \
60  A0 ^= A2 & A1; \
61  } while(0)
62 
63 /*
64 * Noekeon Encryption
65 */
66 void Noekeon::simd_encrypt_4(const uint8_t in[], uint8_t out[]) const
67  {
68  const SIMD_32 K0 = SIMD_32::splat(m_EK[0]);
69  const SIMD_32 K1 = SIMD_32::splat(m_EK[1]);
70  const SIMD_32 K2 = SIMD_32::splat(m_EK[2]);
71  const SIMD_32 K3 = SIMD_32::splat(m_EK[3]);
72 
73  SIMD_32 A0 = SIMD_32::load_be(in );
74  SIMD_32 A1 = SIMD_32::load_be(in + 16);
75  SIMD_32 A2 = SIMD_32::load_be(in + 32);
76  SIMD_32 A3 = SIMD_32::load_be(in + 48);
77 
78  SIMD_32::transpose(A0, A1, A2, A3);
79 
80  for(size_t i = 0; i != 16; ++i)
81  {
82  A0 ^= SIMD_32::splat(RC[i]);
83 
84  NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3);
85 
86  A1.rotate_left(1);
87  A2.rotate_left(5);
88  A3.rotate_left(2);
89 
90  NOK_SIMD_GAMMA(A0, A1, A2, A3);
91 
92  A1.rotate_right(1);
93  A2.rotate_right(5);
94  A3.rotate_right(2);
95  }
96 
97  A0 ^= SIMD_32::splat(RC[16]);
98  NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3);
99 
100  SIMD_32::transpose(A0, A1, A2, A3);
101 
102  A0.store_be(out);
103  A1.store_be(out + 16);
104  A2.store_be(out + 32);
105  A3.store_be(out + 48);
106  }
107 
108 /*
109 * Noekeon Encryption
110 */
111 void Noekeon::simd_decrypt_4(const uint8_t in[], uint8_t out[]) const
112  {
113  const SIMD_32 K0 = SIMD_32::splat(m_DK[0]);
114  const SIMD_32 K1 = SIMD_32::splat(m_DK[1]);
115  const SIMD_32 K2 = SIMD_32::splat(m_DK[2]);
116  const SIMD_32 K3 = SIMD_32::splat(m_DK[3]);
117 
118  SIMD_32 A0 = SIMD_32::load_be(in );
119  SIMD_32 A1 = SIMD_32::load_be(in + 16);
120  SIMD_32 A2 = SIMD_32::load_be(in + 32);
121  SIMD_32 A3 = SIMD_32::load_be(in + 48);
122 
123  SIMD_32::transpose(A0, A1, A2, A3);
124 
125  for(size_t i = 0; i != 16; ++i)
126  {
127  NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3);
128 
129  A0 ^= SIMD_32::splat(RC[16-i]);
130 
131  A1.rotate_left(1);
132  A2.rotate_left(5);
133  A3.rotate_left(2);
134 
135  NOK_SIMD_GAMMA(A0, A1, A2, A3);
136 
137  A1.rotate_right(1);
138  A2.rotate_right(5);
139  A3.rotate_right(2);
140  }
141 
142  NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3);
143  A0 ^= SIMD_32::splat(RC[0]);
144 
145  SIMD_32::transpose(A0, A1, A2, A3);
146 
147  A0.store_be(out);
148  A1.store_be(out + 16);
149  A2.store_be(out + 32);
150  A3.store_be(out + 48);
151  }
152 
153 }
static void transpose(SIMD_4x32 &B0, SIMD_4x32 &B1, SIMD_4x32 &B2, SIMD_4x32 &B3)
Definition: simd_32.h:564
#define NOK_SIMD_GAMMA(A0, A1, A2, A3)
static SIMD_4x32 load_be(const void *in)
Definition: simd_32.h:168
Definition: alg_id.cpp:13
static SIMD_4x32 splat(uint32_t B)
Definition: simd_32.h:114
#define NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3)
SIMD_4x32 SIMD_32
Definition: simd_32.h:650