/src/botan/src/lib/block/noekeon/noekeon_simd/noekeon_simd.cpp
Line | Count | Source (jump to first uncovered line) |
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/internal/noekeon.h> |
9 | | |
10 | | #include <botan/internal/simd_4x32.h> |
11 | | |
12 | | namespace Botan { |
13 | | |
14 | | namespace { |
15 | | |
16 | | /* |
17 | | * Noekeon's Theta Operation |
18 | | */ |
19 | | inline void theta(SIMD_4x32& A0, |
20 | | SIMD_4x32& A1, |
21 | | SIMD_4x32& A2, |
22 | | SIMD_4x32& A3, |
23 | | const SIMD_4x32& K0, |
24 | | const SIMD_4x32& K1, |
25 | | const SIMD_4x32& K2, |
26 | 0 | const SIMD_4x32& K3) { |
27 | 0 | SIMD_4x32 T = A0 ^ A2; |
28 | 0 | T ^= T.rotl<8>() ^ T.rotr<8>(); |
29 | 0 | A1 ^= T; |
30 | 0 | A3 ^= T; |
31 | |
|
32 | 0 | A0 ^= K0; |
33 | 0 | A1 ^= K1; |
34 | 0 | A2 ^= K2; |
35 | 0 | A3 ^= K3; |
36 | |
|
37 | 0 | T = A1 ^ A3; |
38 | 0 | T ^= T.rotl<8>() ^ T.rotr<8>(); |
39 | 0 | A0 ^= T; |
40 | 0 | A2 ^= T; |
41 | 0 | } |
42 | | |
43 | | /* |
44 | | * Noekeon's Gamma S-Box Layer |
45 | | */ |
46 | 0 | inline void gamma(SIMD_4x32& A0, SIMD_4x32& A1, SIMD_4x32& A2, SIMD_4x32& A3) { |
47 | 0 | A1 ^= ~(A2 | A3); |
48 | 0 | A0 ^= A2 & A1; |
49 | |
|
50 | 0 | SIMD_4x32 T = A3; |
51 | 0 | A3 = A0; |
52 | 0 | A0 = T; |
53 | |
|
54 | 0 | A2 ^= A0 ^ A1 ^ A3; |
55 | |
|
56 | 0 | A1 ^= ~(A2 | A3); |
57 | 0 | A0 ^= A2 & A1; |
58 | 0 | } |
59 | | |
60 | | } // namespace |
61 | | |
62 | | /* |
63 | | * Noekeon Encryption |
64 | | */ |
65 | 0 | void Noekeon::simd_encrypt_4(const uint8_t in[], uint8_t out[]) const { |
66 | 0 | const SIMD_4x32 K0 = SIMD_4x32::splat(m_EK[0]); |
67 | 0 | const SIMD_4x32 K1 = SIMD_4x32::splat(m_EK[1]); |
68 | 0 | const SIMD_4x32 K2 = SIMD_4x32::splat(m_EK[2]); |
69 | 0 | const SIMD_4x32 K3 = SIMD_4x32::splat(m_EK[3]); |
70 | |
|
71 | 0 | SIMD_4x32 A0 = SIMD_4x32::load_be(in); |
72 | 0 | SIMD_4x32 A1 = SIMD_4x32::load_be(in + 16); |
73 | 0 | SIMD_4x32 A2 = SIMD_4x32::load_be(in + 32); |
74 | 0 | SIMD_4x32 A3 = SIMD_4x32::load_be(in + 48); |
75 | |
|
76 | 0 | SIMD_4x32::transpose(A0, A1, A2, A3); |
77 | |
|
78 | 0 | for(size_t i = 0; i != 16; ++i) { |
79 | 0 | A0 ^= SIMD_4x32::splat(RC[i]); |
80 | |
|
81 | 0 | theta(A0, A1, A2, A3, K0, K1, K2, K3); |
82 | |
|
83 | 0 | A1 = A1.rotl<1>(); |
84 | 0 | A2 = A2.rotl<5>(); |
85 | 0 | A3 = A3.rotl<2>(); |
86 | |
|
87 | 0 | gamma(A0, A1, A2, A3); |
88 | |
|
89 | 0 | A1 = A1.rotr<1>(); |
90 | 0 | A2 = A2.rotr<5>(); |
91 | 0 | A3 = A3.rotr<2>(); |
92 | 0 | } |
93 | |
|
94 | 0 | A0 ^= SIMD_4x32::splat(RC[16]); |
95 | 0 | theta(A0, A1, A2, A3, K0, K1, K2, K3); |
96 | |
|
97 | 0 | SIMD_4x32::transpose(A0, A1, A2, A3); |
98 | |
|
99 | 0 | A0.store_be(out); |
100 | 0 | A1.store_be(out + 16); |
101 | 0 | A2.store_be(out + 32); |
102 | 0 | A3.store_be(out + 48); |
103 | 0 | } |
104 | | |
105 | | /* |
106 | | * Noekeon Encryption |
107 | | */ |
108 | 0 | void Noekeon::simd_decrypt_4(const uint8_t in[], uint8_t out[]) const { |
109 | 0 | const SIMD_4x32 K0 = SIMD_4x32::splat(m_DK[0]); |
110 | 0 | const SIMD_4x32 K1 = SIMD_4x32::splat(m_DK[1]); |
111 | 0 | const SIMD_4x32 K2 = SIMD_4x32::splat(m_DK[2]); |
112 | 0 | const SIMD_4x32 K3 = SIMD_4x32::splat(m_DK[3]); |
113 | |
|
114 | 0 | SIMD_4x32 A0 = SIMD_4x32::load_be(in); |
115 | 0 | SIMD_4x32 A1 = SIMD_4x32::load_be(in + 16); |
116 | 0 | SIMD_4x32 A2 = SIMD_4x32::load_be(in + 32); |
117 | 0 | SIMD_4x32 A3 = SIMD_4x32::load_be(in + 48); |
118 | |
|
119 | 0 | SIMD_4x32::transpose(A0, A1, A2, A3); |
120 | |
|
121 | 0 | for(size_t i = 0; i != 16; ++i) { |
122 | 0 | theta(A0, A1, A2, A3, K0, K1, K2, K3); |
123 | |
|
124 | 0 | A0 ^= SIMD_4x32::splat(RC[16 - i]); |
125 | |
|
126 | 0 | A1 = A1.rotl<1>(); |
127 | 0 | A2 = A2.rotl<5>(); |
128 | 0 | A3 = A3.rotl<2>(); |
129 | |
|
130 | 0 | gamma(A0, A1, A2, A3); |
131 | |
|
132 | 0 | A1 = A1.rotr<1>(); |
133 | 0 | A2 = A2.rotr<5>(); |
134 | 0 | A3 = A3.rotr<2>(); |
135 | 0 | } |
136 | |
|
137 | 0 | theta(A0, A1, A2, A3, K0, K1, K2, K3); |
138 | 0 | A0 ^= SIMD_4x32::splat(RC[0]); |
139 | |
|
140 | 0 | SIMD_4x32::transpose(A0, A1, A2, A3); |
141 | |
|
142 | 0 | A0.store_be(out); |
143 | 0 | A1.store_be(out + 16); |
144 | 0 | A2.store_be(out + 32); |
145 | 0 | A3.store_be(out + 48); |
146 | 0 | } |
147 | | |
148 | | } // namespace Botan |