/src/botan/src/lib/hash/sm3/sm3.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * SM3 |
3 | | * (C) 2017 Ribose Inc. |
4 | | * (C) 2021 Jack Lloyd |
5 | | * |
6 | | * Botan is released under the Simplified BSD License (see license.txt) |
7 | | */ |
8 | | |
9 | | #include <botan/internal/sm3.h> |
10 | | |
11 | | #include <botan/internal/bit_ops.h> |
12 | | #include <botan/internal/loadstor.h> |
13 | | #include <botan/internal/rotate.h> |
14 | | #include <botan/internal/stl_util.h> |
15 | | |
16 | | namespace Botan { |
17 | | |
18 | | namespace { |
19 | | |
20 | 0 | inline uint32_t P0(uint32_t X) { |
21 | 0 | return X ^ rotl<9>(X) ^ rotl<17>(X); |
22 | 0 | } |
23 | | |
24 | | inline void R1(uint32_t A, |
25 | | uint32_t& B, |
26 | | uint32_t C, |
27 | | uint32_t& D, |
28 | | uint32_t E, |
29 | | uint32_t& F, |
30 | | uint32_t G, |
31 | | uint32_t& H, |
32 | | uint32_t TJ, |
33 | | uint32_t Wi, |
34 | 0 | uint32_t Wj) { |
35 | 0 | const uint32_t A12 = rotl<12>(A); |
36 | 0 | const uint32_t SS1 = rotl<7>(A12 + E + TJ); |
37 | 0 | const uint32_t TT1 = (A ^ B ^ C) + D + (SS1 ^ A12) + Wj; |
38 | 0 | const uint32_t TT2 = (E ^ F ^ G) + H + SS1 + Wi; |
39 | |
|
40 | 0 | B = rotl<9>(B); |
41 | 0 | D = TT1; |
42 | 0 | F = rotl<19>(F); |
43 | 0 | H = P0(TT2); |
44 | 0 | } |
45 | | |
46 | | inline void R2(uint32_t A, |
47 | | uint32_t& B, |
48 | | uint32_t C, |
49 | | uint32_t& D, |
50 | | uint32_t E, |
51 | | uint32_t& F, |
52 | | uint32_t G, |
53 | | uint32_t& H, |
54 | | uint32_t TJ, |
55 | | uint32_t Wi, |
56 | 0 | uint32_t Wj) { |
57 | 0 | const uint32_t A12 = rotl<12>(A); |
58 | 0 | const uint32_t SS1 = rotl<7>(A12 + E + TJ); |
59 | 0 | const uint32_t TT1 = majority(A, B, C) + D + (SS1 ^ A12) + Wj; |
60 | 0 | const uint32_t TT2 = choose(E, F, G) + H + SS1 + Wi; |
61 | |
|
62 | 0 | B = rotl<9>(B); |
63 | 0 | D = TT1; |
64 | 0 | F = rotl<19>(F); |
65 | 0 | H = P0(TT2); |
66 | 0 | } |
67 | | |
68 | 0 | inline uint32_t P1(uint32_t X) { |
69 | 0 | return X ^ rotl<15>(X) ^ rotl<23>(X); |
70 | 0 | } |
71 | | |
72 | 0 | inline uint32_t SM3_E(uint32_t W0, uint32_t W7, uint32_t W13, uint32_t W3, uint32_t W10) { |
73 | 0 | return P1(W0 ^ W7 ^ rotl<15>(W13)) ^ rotl<7>(W3) ^ W10; |
74 | 0 | } |
75 | | |
76 | | } // namespace |
77 | | |
78 | | /* |
79 | | * SM3 Compression Function |
80 | | */ |
81 | 0 | void SM3::compress_n(digest_type& digest, std::span<const uint8_t> input, size_t blocks) { |
82 | 0 | uint32_t A = digest[0], B = digest[1], C = digest[2], D = digest[3], E = digest[4], F = digest[5], G = digest[6], |
83 | 0 | H = digest[7]; |
84 | 0 | std::array<uint32_t, 16> W; |
85 | |
|
86 | 0 | BufferSlicer in(input); |
87 | |
|
88 | 0 | for(size_t i = 0; i != blocks; ++i) { |
89 | 0 | load_be(W, in.take<block_bytes>()); |
90 | | |
91 | | // clang-format off |
92 | |
|
93 | 0 | R1(A, B, C, D, E, F, G, H, 0x79CC4519, W[ 0], W[ 0] ^ W[ 4]); |
94 | 0 | W[ 0] = SM3_E(W[ 0], W[ 7], W[13], W[ 3], W[10]); |
95 | 0 | R1(D, A, B, C, H, E, F, G, 0xF3988A32, W[ 1], W[ 1] ^ W[ 5]); |
96 | 0 | W[ 1] = SM3_E(W[ 1], W[ 8], W[14], W[ 4], W[11]); |
97 | 0 | R1(C, D, A, B, G, H, E, F, 0xE7311465, W[ 2], W[ 2] ^ W[ 6]); |
98 | 0 | W[ 2] = SM3_E(W[ 2], W[ 9], W[15], W[ 5], W[12]); |
99 | 0 | R1(B, C, D, A, F, G, H, E, 0xCE6228CB, W[ 3], W[ 3] ^ W[ 7]); |
100 | 0 | W[ 3] = SM3_E(W[ 3], W[10], W[ 0], W[ 6], W[13]); |
101 | 0 | R1(A, B, C, D, E, F, G, H, 0x9CC45197, W[ 4], W[ 4] ^ W[ 8]); |
102 | 0 | W[ 4] = SM3_E(W[ 4], W[11], W[ 1], W[ 7], W[14]); |
103 | 0 | R1(D, A, B, C, H, E, F, G, 0x3988A32F, W[ 5], W[ 5] ^ W[ 9]); |
104 | 0 | W[ 5] = SM3_E(W[ 5], W[12], W[ 2], W[ 8], W[15]); |
105 | 0 | R1(C, D, A, B, G, H, E, F, 0x7311465E, W[ 6], W[ 6] ^ W[10]); |
106 | 0 | W[ 6] = SM3_E(W[ 6], W[13], W[ 3], W[ 9], W[ 0]); |
107 | 0 | R1(B, C, D, A, F, G, H, E, 0xE6228CBC, W[ 7], W[ 7] ^ W[11]); |
108 | 0 | W[ 7] = SM3_E(W[ 7], W[14], W[ 4], W[10], W[ 1]); |
109 | 0 | R1(A, B, C, D, E, F, G, H, 0xCC451979, W[ 8], W[ 8] ^ W[12]); |
110 | 0 | W[ 8] = SM3_E(W[ 8], W[15], W[ 5], W[11], W[ 2]); |
111 | 0 | R1(D, A, B, C, H, E, F, G, 0x988A32F3, W[ 9], W[ 9] ^ W[13]); |
112 | 0 | W[ 9] = SM3_E(W[ 9], W[ 0], W[ 6], W[12], W[ 3]); |
113 | 0 | R1(C, D, A, B, G, H, E, F, 0x311465E7, W[10], W[10] ^ W[14]); |
114 | 0 | W[10] = SM3_E(W[10], W[ 1], W[ 7], W[13], W[ 4]); |
115 | 0 | R1(B, C, D, A, F, G, H, E, 0x6228CBCE, W[11], W[11] ^ W[15]); |
116 | 0 | W[11] = SM3_E(W[11], W[ 2], W[ 8], W[14], W[ 5]); |
117 | 0 | R1(A, B, C, D, E, F, G, H, 0xC451979C, W[12], W[12] ^ W[ 0]); |
118 | 0 | W[12] = SM3_E(W[12], W[ 3], W[ 9], W[15], W[ 6]); |
119 | 0 | R1(D, A, B, C, H, E, F, G, 0x88A32F39, W[13], W[13] ^ W[ 1]); |
120 | 0 | W[13] = SM3_E(W[13], W[ 4], W[10], W[ 0], W[ 7]); |
121 | 0 | R1(C, D, A, B, G, H, E, F, 0x11465E73, W[14], W[14] ^ W[ 2]); |
122 | 0 | W[14] = SM3_E(W[14], W[ 5], W[11], W[ 1], W[ 8]); |
123 | 0 | R1(B, C, D, A, F, G, H, E, 0x228CBCE6, W[15], W[15] ^ W[ 3]); |
124 | 0 | W[15] = SM3_E(W[15], W[ 6], W[12], W[ 2], W[ 9]); |
125 | 0 | R2(A, B, C, D, E, F, G, H, 0x9D8A7A87, W[ 0], W[ 0] ^ W[ 4]); |
126 | 0 | W[ 0] = SM3_E(W[ 0], W[ 7], W[13], W[ 3], W[10]); |
127 | 0 | R2(D, A, B, C, H, E, F, G, 0x3B14F50F, W[ 1], W[ 1] ^ W[ 5]); |
128 | 0 | W[ 1] = SM3_E(W[ 1], W[ 8], W[14], W[ 4], W[11]); |
129 | 0 | R2(C, D, A, B, G, H, E, F, 0x7629EA1E, W[ 2], W[ 2] ^ W[ 6]); |
130 | 0 | W[ 2] = SM3_E(W[ 2], W[ 9], W[15], W[ 5], W[12]); |
131 | 0 | R2(B, C, D, A, F, G, H, E, 0xEC53D43C, W[ 3], W[ 3] ^ W[ 7]); |
132 | 0 | W[ 3] = SM3_E(W[ 3], W[10], W[ 0], W[ 6], W[13]); |
133 | 0 | R2(A, B, C, D, E, F, G, H, 0xD8A7A879, W[ 4], W[ 4] ^ W[ 8]); |
134 | 0 | W[ 4] = SM3_E(W[ 4], W[11], W[ 1], W[ 7], W[14]); |
135 | 0 | R2(D, A, B, C, H, E, F, G, 0xB14F50F3, W[ 5], W[ 5] ^ W[ 9]); |
136 | 0 | W[ 5] = SM3_E(W[ 5], W[12], W[ 2], W[ 8], W[15]); |
137 | 0 | R2(C, D, A, B, G, H, E, F, 0x629EA1E7, W[ 6], W[ 6] ^ W[10]); |
138 | 0 | W[ 6] = SM3_E(W[ 6], W[13], W[ 3], W[ 9], W[ 0]); |
139 | 0 | R2(B, C, D, A, F, G, H, E, 0xC53D43CE, W[ 7], W[ 7] ^ W[11]); |
140 | 0 | W[ 7] = SM3_E(W[ 7], W[14], W[ 4], W[10], W[ 1]); |
141 | 0 | R2(A, B, C, D, E, F, G, H, 0x8A7A879D, W[ 8], W[ 8] ^ W[12]); |
142 | 0 | W[ 8] = SM3_E(W[ 8], W[15], W[ 5], W[11], W[ 2]); |
143 | 0 | R2(D, A, B, C, H, E, F, G, 0x14F50F3B, W[ 9], W[ 9] ^ W[13]); |
144 | 0 | W[ 9] = SM3_E(W[ 9], W[ 0], W[ 6], W[12], W[ 3]); |
145 | 0 | R2(C, D, A, B, G, H, E, F, 0x29EA1E76, W[10], W[10] ^ W[14]); |
146 | 0 | W[10] = SM3_E(W[10], W[ 1], W[ 7], W[13], W[ 4]); |
147 | 0 | R2(B, C, D, A, F, G, H, E, 0x53D43CEC, W[11], W[11] ^ W[15]); |
148 | 0 | W[11] = SM3_E(W[11], W[ 2], W[ 8], W[14], W[ 5]); |
149 | 0 | R2(A, B, C, D, E, F, G, H, 0xA7A879D8, W[12], W[12] ^ W[ 0]); |
150 | 0 | W[12] = SM3_E(W[12], W[ 3], W[ 9], W[15], W[ 6]); |
151 | 0 | R2(D, A, B, C, H, E, F, G, 0x4F50F3B1, W[13], W[13] ^ W[ 1]); |
152 | 0 | W[13] = SM3_E(W[13], W[ 4], W[10], W[ 0], W[ 7]); |
153 | 0 | R2(C, D, A, B, G, H, E, F, 0x9EA1E762, W[14], W[14] ^ W[ 2]); |
154 | 0 | W[14] = SM3_E(W[14], W[ 5], W[11], W[ 1], W[ 8]); |
155 | 0 | R2(B, C, D, A, F, G, H, E, 0x3D43CEC5, W[15], W[15] ^ W[ 3]); |
156 | 0 | W[15] = SM3_E(W[15], W[ 6], W[12], W[ 2], W[ 9]); |
157 | 0 | R2(A, B, C, D, E, F, G, H, 0x7A879D8A, W[ 0], W[ 0] ^ W[ 4]); |
158 | 0 | W[ 0] = SM3_E(W[ 0], W[ 7], W[13], W[ 3], W[10]); |
159 | 0 | R2(D, A, B, C, H, E, F, G, 0xF50F3B14, W[ 1], W[ 1] ^ W[ 5]); |
160 | 0 | W[ 1] = SM3_E(W[ 1], W[ 8], W[14], W[ 4], W[11]); |
161 | 0 | R2(C, D, A, B, G, H, E, F, 0xEA1E7629, W[ 2], W[ 2] ^ W[ 6]); |
162 | 0 | W[ 2] = SM3_E(W[ 2], W[ 9], W[15], W[ 5], W[12]); |
163 | 0 | R2(B, C, D, A, F, G, H, E, 0xD43CEC53, W[ 3], W[ 3] ^ W[ 7]); |
164 | 0 | W[ 3] = SM3_E(W[ 3], W[10], W[ 0], W[ 6], W[13]); |
165 | 0 | R2(A, B, C, D, E, F, G, H, 0xA879D8A7, W[ 4], W[ 4] ^ W[ 8]); |
166 | 0 | W[ 4] = SM3_E(W[ 4], W[11], W[ 1], W[ 7], W[14]); |
167 | 0 | R2(D, A, B, C, H, E, F, G, 0x50F3B14F, W[ 5], W[ 5] ^ W[ 9]); |
168 | 0 | W[ 5] = SM3_E(W[ 5], W[12], W[ 2], W[ 8], W[15]); |
169 | 0 | R2(C, D, A, B, G, H, E, F, 0xA1E7629E, W[ 6], W[ 6] ^ W[10]); |
170 | 0 | W[ 6] = SM3_E(W[ 6], W[13], W[ 3], W[ 9], W[ 0]); |
171 | 0 | R2(B, C, D, A, F, G, H, E, 0x43CEC53D, W[ 7], W[ 7] ^ W[11]); |
172 | 0 | W[ 7] = SM3_E(W[ 7], W[14], W[ 4], W[10], W[ 1]); |
173 | 0 | R2(A, B, C, D, E, F, G, H, 0x879D8A7A, W[ 8], W[ 8] ^ W[12]); |
174 | 0 | W[ 8] = SM3_E(W[ 8], W[15], W[ 5], W[11], W[ 2]); |
175 | 0 | R2(D, A, B, C, H, E, F, G, 0x0F3B14F5, W[ 9], W[ 9] ^ W[13]); |
176 | 0 | W[ 9] = SM3_E(W[ 9], W[ 0], W[ 6], W[12], W[ 3]); |
177 | 0 | R2(C, D, A, B, G, H, E, F, 0x1E7629EA, W[10], W[10] ^ W[14]); |
178 | 0 | W[10] = SM3_E(W[10], W[ 1], W[ 7], W[13], W[ 4]); |
179 | 0 | R2(B, C, D, A, F, G, H, E, 0x3CEC53D4, W[11], W[11] ^ W[15]); |
180 | 0 | W[11] = SM3_E(W[11], W[ 2], W[ 8], W[14], W[ 5]); |
181 | 0 | R2(A, B, C, D, E, F, G, H, 0x79D8A7A8, W[12], W[12] ^ W[ 0]); |
182 | 0 | W[12] = SM3_E(W[12], W[ 3], W[ 9], W[15], W[ 6]); |
183 | 0 | R2(D, A, B, C, H, E, F, G, 0xF3B14F50, W[13], W[13] ^ W[ 1]); |
184 | 0 | W[13] = SM3_E(W[13], W[ 4], W[10], W[ 0], W[ 7]); |
185 | 0 | R2(C, D, A, B, G, H, E, F, 0xE7629EA1, W[14], W[14] ^ W[ 2]); |
186 | 0 | W[14] = SM3_E(W[14], W[ 5], W[11], W[ 1], W[ 8]); |
187 | 0 | R2(B, C, D, A, F, G, H, E, 0xCEC53D43, W[15], W[15] ^ W[ 3]); |
188 | 0 | W[15] = SM3_E(W[15], W[ 6], W[12], W[ 2], W[ 9]); |
189 | 0 | R2(A, B, C, D, E, F, G, H, 0x9D8A7A87, W[ 0], W[ 0] ^ W[ 4]); |
190 | 0 | W[ 0] = SM3_E(W[ 0], W[ 7], W[13], W[ 3], W[10]); |
191 | 0 | R2(D, A, B, C, H, E, F, G, 0x3B14F50F, W[ 1], W[ 1] ^ W[ 5]); |
192 | 0 | W[ 1] = SM3_E(W[ 1], W[ 8], W[14], W[ 4], W[11]); |
193 | 0 | R2(C, D, A, B, G, H, E, F, 0x7629EA1E, W[ 2], W[ 2] ^ W[ 6]); |
194 | 0 | W[ 2] = SM3_E(W[ 2], W[ 9], W[15], W[ 5], W[12]); |
195 | 0 | R2(B, C, D, A, F, G, H, E, 0xEC53D43C, W[ 3], W[ 3] ^ W[ 7]); |
196 | 0 | W[ 3] = SM3_E(W[ 3], W[10], W[ 0], W[ 6], W[13]); |
197 | 0 | R2(A, B, C, D, E, F, G, H, 0xD8A7A879, W[ 4], W[ 4] ^ W[ 8]); |
198 | 0 | R2(D, A, B, C, H, E, F, G, 0xB14F50F3, W[ 5], W[ 5] ^ W[ 9]); |
199 | 0 | R2(C, D, A, B, G, H, E, F, 0x629EA1E7, W[ 6], W[ 6] ^ W[10]); |
200 | 0 | R2(B, C, D, A, F, G, H, E, 0xC53D43CE, W[ 7], W[ 7] ^ W[11]); |
201 | 0 | R2(A, B, C, D, E, F, G, H, 0x8A7A879D, W[ 8], W[ 8] ^ W[12]); |
202 | 0 | R2(D, A, B, C, H, E, F, G, 0x14F50F3B, W[ 9], W[ 9] ^ W[13]); |
203 | 0 | R2(C, D, A, B, G, H, E, F, 0x29EA1E76, W[10], W[10] ^ W[14]); |
204 | 0 | R2(B, C, D, A, F, G, H, E, 0x53D43CEC, W[11], W[11] ^ W[15]); |
205 | 0 | R2(A, B, C, D, E, F, G, H, 0xA7A879D8, W[12], W[12] ^ W[ 0]); |
206 | 0 | R2(D, A, B, C, H, E, F, G, 0x4F50F3B1, W[13], W[13] ^ W[ 1]); |
207 | 0 | R2(C, D, A, B, G, H, E, F, 0x9EA1E762, W[14], W[14] ^ W[ 2]); |
208 | 0 | R2(B, C, D, A, F, G, H, E, 0x3D43CEC5, W[15], W[15] ^ W[ 3]); |
209 | | |
210 | | // clang-format on |
211 | |
|
212 | 0 | A = (digest[0] ^= A); |
213 | 0 | B = (digest[1] ^= B); |
214 | 0 | C = (digest[2] ^= C); |
215 | 0 | D = (digest[3] ^= D); |
216 | 0 | E = (digest[4] ^= E); |
217 | 0 | F = (digest[5] ^= F); |
218 | 0 | G = (digest[6] ^= G); |
219 | 0 | H = (digest[7] ^= H); |
220 | 0 | } |
221 | 0 | } |
222 | | |
223 | 0 | void SM3::init(digest_type& digest) { |
224 | 0 | digest.assign( |
225 | 0 | {0x7380166fUL, 0x4914b2b9UL, 0x172442d7UL, 0xda8a0600UL, 0xa96f30bcUL, 0x163138aaUL, 0xe38dee4dUL, 0xb0fb0e4eUL}); |
226 | 0 | } |
227 | | |
228 | 0 | std::unique_ptr<HashFunction> SM3::new_object() const { |
229 | 0 | return std::make_unique<SM3>(); |
230 | 0 | } |
231 | | |
232 | 0 | std::unique_ptr<HashFunction> SM3::copy_state() const { |
233 | 0 | return std::make_unique<SM3>(*this); |
234 | 0 | } |
235 | | |
236 | 0 | void SM3::add_data(std::span<const uint8_t> input) { |
237 | 0 | m_md.update(input); |
238 | 0 | } |
239 | | |
240 | 0 | void SM3::final_result(std::span<uint8_t> output) { |
241 | 0 | m_md.final(output); |
242 | 0 | } |
243 | | |
244 | | } // namespace Botan |