Coverage Report

Created: 2025-04-11 06:34

/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