/src/botan/src/lib/hash/sm3/sm3.cpp
Line  | Count  | Source  | 
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];  | 
83  | 0  |    uint32_t B = digest[1];  | 
84  | 0  |    uint32_t C = digest[2];  | 
85  | 0  |    uint32_t D = digest[3];  | 
86  | 0  |    uint32_t E = digest[4];  | 
87  | 0  |    uint32_t F = digest[5];  | 
88  | 0  |    uint32_t G = digest[6];  | 
89  | 0  |    uint32_t H = digest[7];  | 
90  | 0  |    std::array<uint32_t, 16> W{}; | 
91  |  | 
  | 
92  | 0  |    BufferSlicer in(input);  | 
93  |  | 
  | 
94  | 0  |    for(size_t i = 0; i != blocks; ++i) { | 
95  | 0  |       load_be(W, in.take<block_bytes>());  | 
96  |  |  | 
97  |  |       // clang-format off  | 
98  |  | 
  | 
99  | 0  |       R1(A, B, C, D, E, F, G, H, 0x79CC4519, W[ 0], W[ 0] ^ W[ 4]);  | 
100  | 0  |       W[ 0] = SM3_E(W[ 0], W[ 7], W[13], W[ 3], W[10]);  | 
101  | 0  |       R1(D, A, B, C, H, E, F, G, 0xF3988A32, W[ 1], W[ 1] ^ W[ 5]);  | 
102  | 0  |       W[ 1] = SM3_E(W[ 1], W[ 8], W[14], W[ 4], W[11]);  | 
103  | 0  |       R1(C, D, A, B, G, H, E, F, 0xE7311465, W[ 2], W[ 2] ^ W[ 6]);  | 
104  | 0  |       W[ 2] = SM3_E(W[ 2], W[ 9], W[15], W[ 5], W[12]);  | 
105  | 0  |       R1(B, C, D, A, F, G, H, E, 0xCE6228CB, W[ 3], W[ 3] ^ W[ 7]);  | 
106  | 0  |       W[ 3] = SM3_E(W[ 3], W[10], W[ 0], W[ 6], W[13]);  | 
107  | 0  |       R1(A, B, C, D, E, F, G, H, 0x9CC45197, W[ 4], W[ 4] ^ W[ 8]);  | 
108  | 0  |       W[ 4] = SM3_E(W[ 4], W[11], W[ 1], W[ 7], W[14]);  | 
109  | 0  |       R1(D, A, B, C, H, E, F, G, 0x3988A32F, W[ 5], W[ 5] ^ W[ 9]);  | 
110  | 0  |       W[ 5] = SM3_E(W[ 5], W[12], W[ 2], W[ 8], W[15]);  | 
111  | 0  |       R1(C, D, A, B, G, H, E, F, 0x7311465E, W[ 6], W[ 6] ^ W[10]);  | 
112  | 0  |       W[ 6] = SM3_E(W[ 6], W[13], W[ 3], W[ 9], W[ 0]);  | 
113  | 0  |       R1(B, C, D, A, F, G, H, E, 0xE6228CBC, W[ 7], W[ 7] ^ W[11]);  | 
114  | 0  |       W[ 7] = SM3_E(W[ 7], W[14], W[ 4], W[10], W[ 1]);  | 
115  | 0  |       R1(A, B, C, D, E, F, G, H, 0xCC451979, W[ 8], W[ 8] ^ W[12]);  | 
116  | 0  |       W[ 8] = SM3_E(W[ 8], W[15], W[ 5], W[11], W[ 2]);  | 
117  | 0  |       R1(D, A, B, C, H, E, F, G, 0x988A32F3, W[ 9], W[ 9] ^ W[13]);  | 
118  | 0  |       W[ 9] = SM3_E(W[ 9], W[ 0], W[ 6], W[12], W[ 3]);  | 
119  | 0  |       R1(C, D, A, B, G, H, E, F, 0x311465E7, W[10], W[10] ^ W[14]);  | 
120  | 0  |       W[10] = SM3_E(W[10], W[ 1], W[ 7], W[13], W[ 4]);  | 
121  | 0  |       R1(B, C, D, A, F, G, H, E, 0x6228CBCE, W[11], W[11] ^ W[15]);  | 
122  | 0  |       W[11] = SM3_E(W[11], W[ 2], W[ 8], W[14], W[ 5]);  | 
123  | 0  |       R1(A, B, C, D, E, F, G, H, 0xC451979C, W[12], W[12] ^ W[ 0]);  | 
124  | 0  |       W[12] = SM3_E(W[12], W[ 3], W[ 9], W[15], W[ 6]);  | 
125  | 0  |       R1(D, A, B, C, H, E, F, G, 0x88A32F39, W[13], W[13] ^ W[ 1]);  | 
126  | 0  |       W[13] = SM3_E(W[13], W[ 4], W[10], W[ 0], W[ 7]);  | 
127  | 0  |       R1(C, D, A, B, G, H, E, F, 0x11465E73, W[14], W[14] ^ W[ 2]);  | 
128  | 0  |       W[14] = SM3_E(W[14], W[ 5], W[11], W[ 1], W[ 8]);  | 
129  | 0  |       R1(B, C, D, A, F, G, H, E, 0x228CBCE6, W[15], W[15] ^ W[ 3]);  | 
130  | 0  |       W[15] = SM3_E(W[15], W[ 6], W[12], W[ 2], W[ 9]);  | 
131  | 0  |       R2(A, B, C, D, E, F, G, H, 0x9D8A7A87, W[ 0], W[ 0] ^ W[ 4]);  | 
132  | 0  |       W[ 0] = SM3_E(W[ 0], W[ 7], W[13], W[ 3], W[10]);  | 
133  | 0  |       R2(D, A, B, C, H, E, F, G, 0x3B14F50F, W[ 1], W[ 1] ^ W[ 5]);  | 
134  | 0  |       W[ 1] = SM3_E(W[ 1], W[ 8], W[14], W[ 4], W[11]);  | 
135  | 0  |       R2(C, D, A, B, G, H, E, F, 0x7629EA1E, W[ 2], W[ 2] ^ W[ 6]);  | 
136  | 0  |       W[ 2] = SM3_E(W[ 2], W[ 9], W[15], W[ 5], W[12]);  | 
137  | 0  |       R2(B, C, D, A, F, G, H, E, 0xEC53D43C, W[ 3], W[ 3] ^ W[ 7]);  | 
138  | 0  |       W[ 3] = SM3_E(W[ 3], W[10], W[ 0], W[ 6], W[13]);  | 
139  | 0  |       R2(A, B, C, D, E, F, G, H, 0xD8A7A879, W[ 4], W[ 4] ^ W[ 8]);  | 
140  | 0  |       W[ 4] = SM3_E(W[ 4], W[11], W[ 1], W[ 7], W[14]);  | 
141  | 0  |       R2(D, A, B, C, H, E, F, G, 0xB14F50F3, W[ 5], W[ 5] ^ W[ 9]);  | 
142  | 0  |       W[ 5] = SM3_E(W[ 5], W[12], W[ 2], W[ 8], W[15]);  | 
143  | 0  |       R2(C, D, A, B, G, H, E, F, 0x629EA1E7, W[ 6], W[ 6] ^ W[10]);  | 
144  | 0  |       W[ 6] = SM3_E(W[ 6], W[13], W[ 3], W[ 9], W[ 0]);  | 
145  | 0  |       R2(B, C, D, A, F, G, H, E, 0xC53D43CE, W[ 7], W[ 7] ^ W[11]);  | 
146  | 0  |       W[ 7] = SM3_E(W[ 7], W[14], W[ 4], W[10], W[ 1]);  | 
147  | 0  |       R2(A, B, C, D, E, F, G, H, 0x8A7A879D, W[ 8], W[ 8] ^ W[12]);  | 
148  | 0  |       W[ 8] = SM3_E(W[ 8], W[15], W[ 5], W[11], W[ 2]);  | 
149  | 0  |       R2(D, A, B, C, H, E, F, G, 0x14F50F3B, W[ 9], W[ 9] ^ W[13]);  | 
150  | 0  |       W[ 9] = SM3_E(W[ 9], W[ 0], W[ 6], W[12], W[ 3]);  | 
151  | 0  |       R2(C, D, A, B, G, H, E, F, 0x29EA1E76, W[10], W[10] ^ W[14]);  | 
152  | 0  |       W[10] = SM3_E(W[10], W[ 1], W[ 7], W[13], W[ 4]);  | 
153  | 0  |       R2(B, C, D, A, F, G, H, E, 0x53D43CEC, W[11], W[11] ^ W[15]);  | 
154  | 0  |       W[11] = SM3_E(W[11], W[ 2], W[ 8], W[14], W[ 5]);  | 
155  | 0  |       R2(A, B, C, D, E, F, G, H, 0xA7A879D8, W[12], W[12] ^ W[ 0]);  | 
156  | 0  |       W[12] = SM3_E(W[12], W[ 3], W[ 9], W[15], W[ 6]);  | 
157  | 0  |       R2(D, A, B, C, H, E, F, G, 0x4F50F3B1, W[13], W[13] ^ W[ 1]);  | 
158  | 0  |       W[13] = SM3_E(W[13], W[ 4], W[10], W[ 0], W[ 7]);  | 
159  | 0  |       R2(C, D, A, B, G, H, E, F, 0x9EA1E762, W[14], W[14] ^ W[ 2]);  | 
160  | 0  |       W[14] = SM3_E(W[14], W[ 5], W[11], W[ 1], W[ 8]);  | 
161  | 0  |       R2(B, C, D, A, F, G, H, E, 0x3D43CEC5, W[15], W[15] ^ W[ 3]);  | 
162  | 0  |       W[15] = SM3_E(W[15], W[ 6], W[12], W[ 2], W[ 9]);  | 
163  | 0  |       R2(A, B, C, D, E, F, G, H, 0x7A879D8A, W[ 0], W[ 0] ^ W[ 4]);  | 
164  | 0  |       W[ 0] = SM3_E(W[ 0], W[ 7], W[13], W[ 3], W[10]);  | 
165  | 0  |       R2(D, A, B, C, H, E, F, G, 0xF50F3B14, W[ 1], W[ 1] ^ W[ 5]);  | 
166  | 0  |       W[ 1] = SM3_E(W[ 1], W[ 8], W[14], W[ 4], W[11]);  | 
167  | 0  |       R2(C, D, A, B, G, H, E, F, 0xEA1E7629, W[ 2], W[ 2] ^ W[ 6]);  | 
168  | 0  |       W[ 2] = SM3_E(W[ 2], W[ 9], W[15], W[ 5], W[12]);  | 
169  | 0  |       R2(B, C, D, A, F, G, H, E, 0xD43CEC53, W[ 3], W[ 3] ^ W[ 7]);  | 
170  | 0  |       W[ 3] = SM3_E(W[ 3], W[10], W[ 0], W[ 6], W[13]);  | 
171  | 0  |       R2(A, B, C, D, E, F, G, H, 0xA879D8A7, W[ 4], W[ 4] ^ W[ 8]);  | 
172  | 0  |       W[ 4] = SM3_E(W[ 4], W[11], W[ 1], W[ 7], W[14]);  | 
173  | 0  |       R2(D, A, B, C, H, E, F, G, 0x50F3B14F, W[ 5], W[ 5] ^ W[ 9]);  | 
174  | 0  |       W[ 5] = SM3_E(W[ 5], W[12], W[ 2], W[ 8], W[15]);  | 
175  | 0  |       R2(C, D, A, B, G, H, E, F, 0xA1E7629E, W[ 6], W[ 6] ^ W[10]);  | 
176  | 0  |       W[ 6] = SM3_E(W[ 6], W[13], W[ 3], W[ 9], W[ 0]);  | 
177  | 0  |       R2(B, C, D, A, F, G, H, E, 0x43CEC53D, W[ 7], W[ 7] ^ W[11]);  | 
178  | 0  |       W[ 7] = SM3_E(W[ 7], W[14], W[ 4], W[10], W[ 1]);  | 
179  | 0  |       R2(A, B, C, D, E, F, G, H, 0x879D8A7A, W[ 8], W[ 8] ^ W[12]);  | 
180  | 0  |       W[ 8] = SM3_E(W[ 8], W[15], W[ 5], W[11], W[ 2]);  | 
181  | 0  |       R2(D, A, B, C, H, E, F, G, 0x0F3B14F5, W[ 9], W[ 9] ^ W[13]);  | 
182  | 0  |       W[ 9] = SM3_E(W[ 9], W[ 0], W[ 6], W[12], W[ 3]);  | 
183  | 0  |       R2(C, D, A, B, G, H, E, F, 0x1E7629EA, W[10], W[10] ^ W[14]);  | 
184  | 0  |       W[10] = SM3_E(W[10], W[ 1], W[ 7], W[13], W[ 4]);  | 
185  | 0  |       R2(B, C, D, A, F, G, H, E, 0x3CEC53D4, W[11], W[11] ^ W[15]);  | 
186  | 0  |       W[11] = SM3_E(W[11], W[ 2], W[ 8], W[14], W[ 5]);  | 
187  | 0  |       R2(A, B, C, D, E, F, G, H, 0x79D8A7A8, W[12], W[12] ^ W[ 0]);  | 
188  | 0  |       W[12] = SM3_E(W[12], W[ 3], W[ 9], W[15], W[ 6]);  | 
189  | 0  |       R2(D, A, B, C, H, E, F, G, 0xF3B14F50, W[13], W[13] ^ W[ 1]);  | 
190  | 0  |       W[13] = SM3_E(W[13], W[ 4], W[10], W[ 0], W[ 7]);  | 
191  | 0  |       R2(C, D, A, B, G, H, E, F, 0xE7629EA1, W[14], W[14] ^ W[ 2]);  | 
192  | 0  |       W[14] = SM3_E(W[14], W[ 5], W[11], W[ 1], W[ 8]);  | 
193  | 0  |       R2(B, C, D, A, F, G, H, E, 0xCEC53D43, W[15], W[15] ^ W[ 3]);  | 
194  | 0  |       W[15] = SM3_E(W[15], W[ 6], W[12], W[ 2], W[ 9]);  | 
195  | 0  |       R2(A, B, C, D, E, F, G, H, 0x9D8A7A87, W[ 0], W[ 0] ^ W[ 4]);  | 
196  | 0  |       W[ 0] = SM3_E(W[ 0], W[ 7], W[13], W[ 3], W[10]);  | 
197  | 0  |       R2(D, A, B, C, H, E, F, G, 0x3B14F50F, W[ 1], W[ 1] ^ W[ 5]);  | 
198  | 0  |       W[ 1] = SM3_E(W[ 1], W[ 8], W[14], W[ 4], W[11]);  | 
199  | 0  |       R2(C, D, A, B, G, H, E, F, 0x7629EA1E, W[ 2], W[ 2] ^ W[ 6]);  | 
200  | 0  |       W[ 2] = SM3_E(W[ 2], W[ 9], W[15], W[ 5], W[12]);  | 
201  | 0  |       R2(B, C, D, A, F, G, H, E, 0xEC53D43C, W[ 3], W[ 3] ^ W[ 7]);  | 
202  | 0  |       W[ 3] = SM3_E(W[ 3], W[10], W[ 0], W[ 6], W[13]);  | 
203  | 0  |       R2(A, B, C, D, E, F, G, H, 0xD8A7A879, W[ 4], W[ 4] ^ W[ 8]);  | 
204  | 0  |       R2(D, A, B, C, H, E, F, G, 0xB14F50F3, W[ 5], W[ 5] ^ W[ 9]);  | 
205  | 0  |       R2(C, D, A, B, G, H, E, F, 0x629EA1E7, W[ 6], W[ 6] ^ W[10]);  | 
206  | 0  |       R2(B, C, D, A, F, G, H, E, 0xC53D43CE, W[ 7], W[ 7] ^ W[11]);  | 
207  | 0  |       R2(A, B, C, D, E, F, G, H, 0x8A7A879D, W[ 8], W[ 8] ^ W[12]);  | 
208  | 0  |       R2(D, A, B, C, H, E, F, G, 0x14F50F3B, W[ 9], W[ 9] ^ W[13]);  | 
209  | 0  |       R2(C, D, A, B, G, H, E, F, 0x29EA1E76, W[10], W[10] ^ W[14]);  | 
210  | 0  |       R2(B, C, D, A, F, G, H, E, 0x53D43CEC, W[11], W[11] ^ W[15]);  | 
211  | 0  |       R2(A, B, C, D, E, F, G, H, 0xA7A879D8, W[12], W[12] ^ W[ 0]);  | 
212  | 0  |       R2(D, A, B, C, H, E, F, G, 0x4F50F3B1, W[13], W[13] ^ W[ 1]);  | 
213  | 0  |       R2(C, D, A, B, G, H, E, F, 0x9EA1E762, W[14], W[14] ^ W[ 2]);  | 
214  | 0  |       R2(B, C, D, A, F, G, H, E, 0x3D43CEC5, W[15], W[15] ^ W[ 3]);  | 
215  |  |  | 
216  |  |       // clang-format on  | 
217  |  | 
  | 
218  | 0  |       A = (digest[0] ^= A);  | 
219  | 0  |       B = (digest[1] ^= B);  | 
220  | 0  |       C = (digest[2] ^= C);  | 
221  | 0  |       D = (digest[3] ^= D);  | 
222  | 0  |       E = (digest[4] ^= E);  | 
223  | 0  |       F = (digest[5] ^= F);  | 
224  | 0  |       G = (digest[6] ^= G);  | 
225  | 0  |       H = (digest[7] ^= H);  | 
226  | 0  |    }  | 
227  | 0  | }  | 
228  |  |  | 
229  | 0  | void SM3::init(digest_type& digest) { | 
230  | 0  |    digest.assign(  | 
231  | 0  |       {0x7380166fUL, 0x4914b2b9UL, 0x172442d7UL, 0xda8a0600UL, 0xa96f30bcUL, 0x163138aaUL, 0xe38dee4dUL, 0xb0fb0e4eUL}); | 
232  | 0  | }  | 
233  |  |  | 
234  | 0  | std::unique_ptr<HashFunction> SM3::new_object() const { | 
235  | 0  |    return std::make_unique<SM3>();  | 
236  | 0  | }  | 
237  |  |  | 
238  | 0  | std::unique_ptr<HashFunction> SM3::copy_state() const { | 
239  | 0  |    return std::make_unique<SM3>(*this);  | 
240  | 0  | }  | 
241  |  |  | 
242  | 0  | void SM3::add_data(std::span<const uint8_t> input) { | 
243  | 0  |    m_md.update(input);  | 
244  | 0  | }  | 
245  |  |  | 
246  | 0  | void SM3::final_result(std::span<uint8_t> output) { | 
247  | 0  |    m_md.final(output);  | 
248  | 0  | }  | 
249  |  |  | 
250  |  | }  // namespace Botan  |