Coverage Report

Created: 2023-09-25 06:34

/src/botan/src/lib/block/sm4/sm4.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* SM4
3
* (C) 2017 Ribose Inc
4
* (C) 2018 Jack Lloyd
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8
9
#include <botan/internal/sm4.h>
10
11
#include <botan/internal/cpuid.h>
12
#include <botan/internal/loadstor.h>
13
#include <botan/internal/rotate.h>
14
15
namespace Botan {
16
17
namespace {
18
19
alignas(256) const uint8_t SM4_SBOX[256] = {
20
   0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7, 0x16, 0xB6, 0x14, 0xC2, 0x28, 0xFB, 0x2C, 0x05, 0x2B, 0x67, 0x9A,
21
   0x76, 0x2A, 0xBE, 0x04, 0xC3, 0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, 0x9C, 0x42, 0x50, 0xF4, 0x91, 0xEF,
22
   0x98, 0x7A, 0x33, 0x54, 0x0B, 0x43, 0xED, 0xCF, 0xAC, 0x62, 0xE4, 0xB3, 0x1C, 0xA9, 0xC9, 0x08, 0xE8, 0x95, 0x80,
23
   0xDF, 0x94, 0xFA, 0x75, 0x8F, 0x3F, 0xA6, 0x47, 0x07, 0xA7, 0xFC, 0xF3, 0x73, 0x17, 0xBA, 0x83, 0x59, 0x3C, 0x19,
24
   0xE6, 0x85, 0x4F, 0xA8, 0x68, 0x6B, 0x81, 0xB2, 0x71, 0x64, 0xDA, 0x8B, 0xF8, 0xEB, 0x0F, 0x4B, 0x70, 0x56, 0x9D,
25
   0x35, 0x1E, 0x24, 0x0E, 0x5E, 0x63, 0x58, 0xD1, 0xA2, 0x25, 0x22, 0x7C, 0x3B, 0x01, 0x21, 0x78, 0x87, 0xD4, 0x00,
26
   0x46, 0x57, 0x9F, 0xD3, 0x27, 0x52, 0x4C, 0x36, 0x02, 0xE7, 0xA0, 0xC4, 0xC8, 0x9E, 0xEA, 0xBF, 0x8A, 0xD2, 0x40,
27
   0xC7, 0x38, 0xB5, 0xA3, 0xF7, 0xF2, 0xCE, 0xF9, 0x61, 0x15, 0xA1, 0xE0, 0xAE, 0x5D, 0xA4, 0x9B, 0x34, 0x1A, 0x55,
28
   0xAD, 0x93, 0x32, 0x30, 0xF5, 0x8C, 0xB1, 0xE3, 0x1D, 0xF6, 0xE2, 0x2E, 0x82, 0x66, 0xCA, 0x60, 0xC0, 0x29, 0x23,
29
   0xAB, 0x0D, 0x53, 0x4E, 0x6F, 0xD5, 0xDB, 0x37, 0x45, 0xDE, 0xFD, 0x8E, 0x2F, 0x03, 0xFF, 0x6A, 0x72, 0x6D, 0x6C,
30
   0x5B, 0x51, 0x8D, 0x1B, 0xAF, 0x92, 0xBB, 0xDD, 0xBC, 0x7F, 0x11, 0xD9, 0x5C, 0x41, 0x1F, 0x10, 0x5A, 0xD8, 0x0A,
31
   0xC1, 0x31, 0x88, 0xA5, 0xCD, 0x7B, 0xBD, 0x2D, 0x74, 0xD0, 0x12, 0xB8, 0xE5, 0xB4, 0xB0, 0x89, 0x69, 0x97, 0x4A,
32
   0x0C, 0x96, 0x77, 0x7E, 0x65, 0xB9, 0xF1, 0x09, 0xC5, 0x6E, 0xC6, 0x84, 0x18, 0xF0, 0x7D, 0xEC, 0x3A, 0xDC, 0x4D,
33
   0x20, 0x79, 0xEE, 0x5F, 0x3E, 0xD7, 0xCB, 0x39, 0x48};
34
35
/*
36
* SM4_SBOX_T[j] == L(SM4_SBOX[j]).
37
*
38
* Each entry has the form 0xXXYYZZZZ where ZZ = XX ^ YY; can we take
39
* advantage of this to create a smaller equivalent table?
40
*
41
* Additionally YY differs from SBOX[i] by at most 3 (64x 0, 96x 1, 64x 2, 32x 3)
42
*/
43
alignas(256) const uint32_t SM4_SBOX_T[256] = {
44
   0x8ED55B5B, 0xD0924242, 0x4DEAA7A7, 0x06FDFBFB, 0xFCCF3333, 0x65E28787, 0xC93DF4F4, 0x6BB5DEDE, 0x4E165858,
45
   0x6EB4DADA, 0x44145050, 0xCAC10B0B, 0x8828A0A0, 0x17F8EFEF, 0x9C2CB0B0, 0x11051414, 0x872BACAC, 0xFB669D9D,
46
   0xF2986A6A, 0xAE77D9D9, 0x822AA8A8, 0x46BCFAFA, 0x14041010, 0xCFC00F0F, 0x02A8AAAA, 0x54451111, 0x5F134C4C,
47
   0xBE269898, 0x6D482525, 0x9E841A1A, 0x1E061818, 0xFD9B6666, 0xEC9E7272, 0x4A430909, 0x10514141, 0x24F7D3D3,
48
   0xD5934646, 0x53ECBFBF, 0xF89A6262, 0x927BE9E9, 0xFF33CCCC, 0x04555151, 0x270B2C2C, 0x4F420D0D, 0x59EEB7B7,
49
   0xF3CC3F3F, 0x1CAEB2B2, 0xEA638989, 0x74E79393, 0x7FB1CECE, 0x6C1C7070, 0x0DABA6A6, 0xEDCA2727, 0x28082020,
50
   0x48EBA3A3, 0xC1975656, 0x80820202, 0xA3DC7F7F, 0xC4965252, 0x12F9EBEB, 0xA174D5D5, 0xB38D3E3E, 0xC33FFCFC,
51
   0x3EA49A9A, 0x5B461D1D, 0x1B071C1C, 0x3BA59E9E, 0x0CFFF3F3, 0x3FF0CFCF, 0xBF72CDCD, 0x4B175C5C, 0x52B8EAEA,
52
   0x8F810E0E, 0x3D586565, 0xCC3CF0F0, 0x7D196464, 0x7EE59B9B, 0x91871616, 0x734E3D3D, 0x08AAA2A2, 0xC869A1A1,
53
   0xC76AADAD, 0x85830606, 0x7AB0CACA, 0xB570C5C5, 0xF4659191, 0xB2D96B6B, 0xA7892E2E, 0x18FBE3E3, 0x47E8AFAF,
54
   0x330F3C3C, 0x674A2D2D, 0xB071C1C1, 0x0E575959, 0xE99F7676, 0xE135D4D4, 0x661E7878, 0xB4249090, 0x360E3838,
55
   0x265F7979, 0xEF628D8D, 0x38596161, 0x95D24747, 0x2AA08A8A, 0xB1259494, 0xAA228888, 0x8C7DF1F1, 0xD73BECEC,
56
   0x05010404, 0xA5218484, 0x9879E1E1, 0x9B851E1E, 0x84D75353, 0x00000000, 0x5E471919, 0x0B565D5D, 0xE39D7E7E,
57
   0x9FD04F4F, 0xBB279C9C, 0x1A534949, 0x7C4D3131, 0xEE36D8D8, 0x0A020808, 0x7BE49F9F, 0x20A28282, 0xD4C71313,
58
   0xE8CB2323, 0xE69C7A7A, 0x42E9ABAB, 0x43BDFEFE, 0xA2882A2A, 0x9AD14B4B, 0x40410101, 0xDBC41F1F, 0xD838E0E0,
59
   0x61B7D6D6, 0x2FA18E8E, 0x2BF4DFDF, 0x3AF1CBCB, 0xF6CD3B3B, 0x1DFAE7E7, 0xE5608585, 0x41155454, 0x25A38686,
60
   0x60E38383, 0x16ACBABA, 0x295C7575, 0x34A69292, 0xF7996E6E, 0xE434D0D0, 0x721A6868, 0x01545555, 0x19AFB6B6,
61
   0xDF914E4E, 0xFA32C8C8, 0xF030C0C0, 0x21F6D7D7, 0xBC8E3232, 0x75B3C6C6, 0x6FE08F8F, 0x691D7474, 0x2EF5DBDB,
62
   0x6AE18B8B, 0x962EB8B8, 0x8A800A0A, 0xFE679999, 0xE2C92B2B, 0xE0618181, 0xC0C30303, 0x8D29A4A4, 0xAF238C8C,
63
   0x07A9AEAE, 0x390D3434, 0x1F524D4D, 0x764F3939, 0xD36EBDBD, 0x81D65757, 0xB7D86F6F, 0xEB37DCDC, 0x51441515,
64
   0xA6DD7B7B, 0x09FEF7F7, 0xB68C3A3A, 0x932FBCBC, 0x0F030C0C, 0x03FCFFFF, 0xC26BA9A9, 0xBA73C9C9, 0xD96CB5B5,
65
   0xDC6DB1B1, 0x375A6D6D, 0x15504545, 0xB98F3636, 0x771B6C6C, 0x13ADBEBE, 0xDA904A4A, 0x57B9EEEE, 0xA9DE7777,
66
   0x4CBEF2F2, 0x837EFDFD, 0x55114444, 0xBDDA6767, 0x2C5D7171, 0x45400505, 0x631F7C7C, 0x50104040, 0x325B6969,
67
   0xB8DB6363, 0x220A2828, 0xC5C20707, 0xF531C4C4, 0xA88A2222, 0x31A79696, 0xF9CE3737, 0x977AEDED, 0x49BFF6F6,
68
   0x992DB4B4, 0xA475D1D1, 0x90D34343, 0x5A124848, 0x58BAE2E2, 0x71E69797, 0x64B6D2D2, 0x70B2C2C2, 0xAD8B2626,
69
   0xCD68A5A5, 0xCB955E5E, 0x624B2929, 0x3C0C3030, 0xCE945A5A, 0xAB76DDDD, 0x867FF9F9, 0xF1649595, 0x5DBBE6E6,
70
   0x35F2C7C7, 0x2D092424, 0xD1C61717, 0xD66FB9B9, 0xDEC51B1B, 0x94861212, 0x78186060, 0x30F3C3C3, 0x897CF5F5,
71
   0x5CEFB3B3, 0xD23AE8E8, 0xACDF7373, 0x794C3535, 0xA0208080, 0x9D78E5E5, 0x56EDBBBB, 0x235E7D7D, 0xC63EF8F8,
72
   0x8BD45F5F, 0xE7C82F2F, 0xDD39E4E4, 0x68492121};
73
74
9.00k
inline uint32_t SM4_T_slow(uint32_t b) {
75
9.00k
   const uint32_t t = make_uint32(
76
9.00k
      SM4_SBOX[get_byte<0>(b)], SM4_SBOX[get_byte<1>(b)], SM4_SBOX[get_byte<2>(b)], SM4_SBOX[get_byte<3>(b)]);
77
78
   // L linear transform
79
9.00k
   return t ^ rotl<2>(t) ^ rotl<10>(t) ^ rotl<18>(t) ^ rotl<24>(t);
80
9.00k
}
81
82
27.0k
inline uint32_t SM4_T(uint32_t b) {
83
27.0k
   return (SM4_SBOX_T[get_byte<0>(b)]) ^ rotr<8>(SM4_SBOX_T[get_byte<1>(b)]) ^ rotr<16>(SM4_SBOX_T[get_byte<2>(b)]) ^
84
27.0k
          rotr<24>(SM4_SBOX_T[get_byte<3>(b)]);
85
27.0k
}
86
87
// Variant of T for key schedule
88
2.49k
inline uint32_t SM4_Tp(uint32_t b) {
89
2.49k
   const uint32_t t = make_uint32(
90
2.49k
      SM4_SBOX[get_byte<0>(b)], SM4_SBOX[get_byte<1>(b)], SM4_SBOX[get_byte<2>(b)], SM4_SBOX[get_byte<3>(b)]);
91
92
   // L' linear transform
93
2.49k
   return t ^ rotl<13>(t) ^ rotl<23>(t);
94
2.49k
}
95
96
template <size_t R, typename F>
97
BOTAN_FORCE_INLINE void SM4_E(
98
9.00k
   uint32_t& B0, uint32_t& B1, uint32_t& B2, uint32_t& B3, const secure_vector<uint32_t>& RK, F& f) {
99
9.00k
   B0 ^= f(B1 ^ B2 ^ B3 ^ RK[4 * R + 0]);
100
9.00k
   B1 ^= f(B2 ^ B3 ^ B0 ^ RK[4 * R + 1]);
101
9.00k
   B2 ^= f(B3 ^ B0 ^ B1 ^ RK[4 * R + 2]);
102
9.00k
   B3 ^= f(B0 ^ B1 ^ B2 ^ RK[4 * R + 3]);
103
9.00k
}
sm4.cpp:void Botan::(anonymous namespace)::SM4_E<0ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Line
Count
Source
98
1.12k
   uint32_t& B0, uint32_t& B1, uint32_t& B2, uint32_t& B3, const secure_vector<uint32_t>& RK, F& f) {
99
1.12k
   B0 ^= f(B1 ^ B2 ^ B3 ^ RK[4 * R + 0]);
100
1.12k
   B1 ^= f(B2 ^ B3 ^ B0 ^ RK[4 * R + 1]);
101
1.12k
   B2 ^= f(B3 ^ B0 ^ B1 ^ RK[4 * R + 2]);
102
1.12k
   B3 ^= f(B0 ^ B1 ^ B2 ^ RK[4 * R + 3]);
103
1.12k
}
sm4.cpp:void Botan::(anonymous namespace)::SM4_E<1ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Line
Count
Source
98
1.12k
   uint32_t& B0, uint32_t& B1, uint32_t& B2, uint32_t& B3, const secure_vector<uint32_t>& RK, F& f) {
99
1.12k
   B0 ^= f(B1 ^ B2 ^ B3 ^ RK[4 * R + 0]);
100
1.12k
   B1 ^= f(B2 ^ B3 ^ B0 ^ RK[4 * R + 1]);
101
1.12k
   B2 ^= f(B3 ^ B0 ^ B1 ^ RK[4 * R + 2]);
102
1.12k
   B3 ^= f(B0 ^ B1 ^ B2 ^ RK[4 * R + 3]);
103
1.12k
}
sm4.cpp:void Botan::(anonymous namespace)::SM4_E<2ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Line
Count
Source
98
1.12k
   uint32_t& B0, uint32_t& B1, uint32_t& B2, uint32_t& B3, const secure_vector<uint32_t>& RK, F& f) {
99
1.12k
   B0 ^= f(B1 ^ B2 ^ B3 ^ RK[4 * R + 0]);
100
1.12k
   B1 ^= f(B2 ^ B3 ^ B0 ^ RK[4 * R + 1]);
101
1.12k
   B2 ^= f(B3 ^ B0 ^ B1 ^ RK[4 * R + 2]);
102
1.12k
   B3 ^= f(B0 ^ B1 ^ B2 ^ RK[4 * R + 3]);
103
1.12k
}
sm4.cpp:void Botan::(anonymous namespace)::SM4_E<3ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Line
Count
Source
98
1.12k
   uint32_t& B0, uint32_t& B1, uint32_t& B2, uint32_t& B3, const secure_vector<uint32_t>& RK, F& f) {
99
1.12k
   B0 ^= f(B1 ^ B2 ^ B3 ^ RK[4 * R + 0]);
100
1.12k
   B1 ^= f(B2 ^ B3 ^ B0 ^ RK[4 * R + 1]);
101
1.12k
   B2 ^= f(B3 ^ B0 ^ B1 ^ RK[4 * R + 2]);
102
1.12k
   B3 ^= f(B0 ^ B1 ^ B2 ^ RK[4 * R + 3]);
103
1.12k
}
sm4.cpp:void Botan::(anonymous namespace)::SM4_E<4ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Line
Count
Source
98
1.12k
   uint32_t& B0, uint32_t& B1, uint32_t& B2, uint32_t& B3, const secure_vector<uint32_t>& RK, F& f) {
99
1.12k
   B0 ^= f(B1 ^ B2 ^ B3 ^ RK[4 * R + 0]);
100
1.12k
   B1 ^= f(B2 ^ B3 ^ B0 ^ RK[4 * R + 1]);
101
1.12k
   B2 ^= f(B3 ^ B0 ^ B1 ^ RK[4 * R + 2]);
102
1.12k
   B3 ^= f(B0 ^ B1 ^ B2 ^ RK[4 * R + 3]);
103
1.12k
}
sm4.cpp:void Botan::(anonymous namespace)::SM4_E<5ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Line
Count
Source
98
1.12k
   uint32_t& B0, uint32_t& B1, uint32_t& B2, uint32_t& B3, const secure_vector<uint32_t>& RK, F& f) {
99
1.12k
   B0 ^= f(B1 ^ B2 ^ B3 ^ RK[4 * R + 0]);
100
1.12k
   B1 ^= f(B2 ^ B3 ^ B0 ^ RK[4 * R + 1]);
101
1.12k
   B2 ^= f(B3 ^ B0 ^ B1 ^ RK[4 * R + 2]);
102
1.12k
   B3 ^= f(B0 ^ B1 ^ B2 ^ RK[4 * R + 3]);
103
1.12k
}
sm4.cpp:void Botan::(anonymous namespace)::SM4_E<6ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Line
Count
Source
98
1.12k
   uint32_t& B0, uint32_t& B1, uint32_t& B2, uint32_t& B3, const secure_vector<uint32_t>& RK, F& f) {
99
1.12k
   B0 ^= f(B1 ^ B2 ^ B3 ^ RK[4 * R + 0]);
100
1.12k
   B1 ^= f(B2 ^ B3 ^ B0 ^ RK[4 * R + 1]);
101
1.12k
   B2 ^= f(B3 ^ B0 ^ B1 ^ RK[4 * R + 2]);
102
1.12k
   B3 ^= f(B0 ^ B1 ^ B2 ^ RK[4 * R + 3]);
103
1.12k
}
sm4.cpp:void Botan::(anonymous namespace)::SM4_E<7ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Line
Count
Source
98
1.12k
   uint32_t& B0, uint32_t& B1, uint32_t& B2, uint32_t& B3, const secure_vector<uint32_t>& RK, F& f) {
99
1.12k
   B0 ^= f(B1 ^ B2 ^ B3 ^ RK[4 * R + 0]);
100
1.12k
   B1 ^= f(B2 ^ B3 ^ B0 ^ RK[4 * R + 1]);
101
1.12k
   B2 ^= f(B3 ^ B0 ^ B1 ^ RK[4 * R + 2]);
102
1.12k
   B3 ^= f(B0 ^ B1 ^ B2 ^ RK[4 * R + 3]);
103
1.12k
}
104
105
template <size_t R, typename F>
106
BOTAN_FORCE_INLINE void SM4_E(uint32_t& B0,
107
                              uint32_t& B1,
108
                              uint32_t& B2,
109
                              uint32_t& B3,
110
                              uint32_t& C0,
111
                              uint32_t& C1,
112
                              uint32_t& C2,
113
                              uint32_t& C3,
114
                              const secure_vector<uint32_t>& RK,
115
0
                              F& f) {
116
0
   B0 ^= f(B1 ^ B2 ^ B3 ^ RK[4 * R + 0]);
117
0
   C0 ^= f(C1 ^ C2 ^ C3 ^ RK[4 * R + 0]);
118
0
   B1 ^= f(B2 ^ B3 ^ B0 ^ RK[4 * R + 1]);
119
0
   C1 ^= f(C2 ^ C3 ^ C0 ^ RK[4 * R + 1]);
120
0
   B2 ^= f(B3 ^ B0 ^ B1 ^ RK[4 * R + 2]);
121
0
   C2 ^= f(C3 ^ C0 ^ C1 ^ RK[4 * R + 2]);
122
0
   B3 ^= f(B0 ^ B1 ^ B2 ^ RK[4 * R + 3]);
123
0
   C3 ^= f(C0 ^ C1 ^ C2 ^ RK[4 * R + 3]);
124
0
}
Unexecuted instantiation: sm4.cpp:void Botan::(anonymous namespace)::SM4_E<0ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Unexecuted instantiation: sm4.cpp:void Botan::(anonymous namespace)::SM4_E<1ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Unexecuted instantiation: sm4.cpp:void Botan::(anonymous namespace)::SM4_E<2ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Unexecuted instantiation: sm4.cpp:void Botan::(anonymous namespace)::SM4_E<3ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Unexecuted instantiation: sm4.cpp:void Botan::(anonymous namespace)::SM4_E<4ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Unexecuted instantiation: sm4.cpp:void Botan::(anonymous namespace)::SM4_E<5ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Unexecuted instantiation: sm4.cpp:void Botan::(anonymous namespace)::SM4_E<6ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Unexecuted instantiation: sm4.cpp:void Botan::(anonymous namespace)::SM4_E<7ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
125
126
template <size_t R, typename F>
127
BOTAN_FORCE_INLINE void SM4_D(
128
0
   uint32_t& B0, uint32_t& B1, uint32_t& B2, uint32_t& B3, const secure_vector<uint32_t>& RK, F& f) {
129
0
   B0 ^= f(B1 ^ B2 ^ B3 ^ RK[4 * R + 3]);
130
0
   B1 ^= f(B2 ^ B3 ^ B0 ^ RK[4 * R + 2]);
131
0
   B2 ^= f(B3 ^ B0 ^ B1 ^ RK[4 * R + 1]);
132
0
   B3 ^= f(B0 ^ B1 ^ B2 ^ RK[4 * R + 0]);
133
0
}
Unexecuted instantiation: sm4.cpp:void Botan::(anonymous namespace)::SM4_D<7ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Unexecuted instantiation: sm4.cpp:void Botan::(anonymous namespace)::SM4_D<6ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Unexecuted instantiation: sm4.cpp:void Botan::(anonymous namespace)::SM4_D<5ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Unexecuted instantiation: sm4.cpp:void Botan::(anonymous namespace)::SM4_D<4ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Unexecuted instantiation: sm4.cpp:void Botan::(anonymous namespace)::SM4_D<3ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Unexecuted instantiation: sm4.cpp:void Botan::(anonymous namespace)::SM4_D<2ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Unexecuted instantiation: sm4.cpp:void Botan::(anonymous namespace)::SM4_D<1ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Unexecuted instantiation: sm4.cpp:void Botan::(anonymous namespace)::SM4_D<0ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
134
135
template <size_t R, typename F>
136
BOTAN_FORCE_INLINE void SM4_D(uint32_t& B0,
137
                              uint32_t& B1,
138
                              uint32_t& B2,
139
                              uint32_t& B3,
140
                              uint32_t& C0,
141
                              uint32_t& C1,
142
                              uint32_t& C2,
143
                              uint32_t& C3,
144
                              const secure_vector<uint32_t>& RK,
145
0
                              F& f) {
146
0
   B0 ^= f(B1 ^ B2 ^ B3 ^ RK[4 * R + 3]);
147
0
   C0 ^= f(C1 ^ C2 ^ C3 ^ RK[4 * R + 3]);
148
0
   B1 ^= f(B2 ^ B3 ^ B0 ^ RK[4 * R + 2]);
149
0
   C1 ^= f(C2 ^ C3 ^ C0 ^ RK[4 * R + 2]);
150
0
   B2 ^= f(B3 ^ B0 ^ B1 ^ RK[4 * R + 1]);
151
0
   C2 ^= f(C3 ^ C0 ^ C1 ^ RK[4 * R + 1]);
152
0
   B3 ^= f(B0 ^ B1 ^ B2 ^ RK[4 * R + 0]);
153
0
   C3 ^= f(C0 ^ C1 ^ C2 ^ RK[4 * R + 0]);
154
0
}
Unexecuted instantiation: sm4.cpp:void Botan::(anonymous namespace)::SM4_D<7ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Unexecuted instantiation: sm4.cpp:void Botan::(anonymous namespace)::SM4_D<6ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Unexecuted instantiation: sm4.cpp:void Botan::(anonymous namespace)::SM4_D<5ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Unexecuted instantiation: sm4.cpp:void Botan::(anonymous namespace)::SM4_D<4ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Unexecuted instantiation: sm4.cpp:void Botan::(anonymous namespace)::SM4_D<3ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Unexecuted instantiation: sm4.cpp:void Botan::(anonymous namespace)::SM4_D<2ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Unexecuted instantiation: sm4.cpp:void Botan::(anonymous namespace)::SM4_D<1ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
Unexecuted instantiation: sm4.cpp:void Botan::(anonymous namespace)::SM4_D<0ul, unsigned int (unsigned int)>(unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, unsigned int&, std::__1::vector<unsigned int, Botan::secure_allocator<unsigned int> > const&, unsigned int (&)(unsigned int))
155
156
}  // namespace
157
158
/*
159
* SM4 Encryption
160
*/
161
1.12k
void SM4::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
162
1.12k
   assert_key_material_set();
163
164
#if defined(BOTAN_HAS_SM4_ARMV8)
165
   if(CPUID::has_arm_sm4())
166
      return sm4_armv8_encrypt(in, out, blocks);
167
#endif
168
169
1.12k
   while(blocks >= 2) {
170
0
      uint32_t B0 = load_be<uint32_t>(in, 0);
171
0
      uint32_t B1 = load_be<uint32_t>(in, 1);
172
0
      uint32_t B2 = load_be<uint32_t>(in, 2);
173
0
      uint32_t B3 = load_be<uint32_t>(in, 3);
174
175
0
      uint32_t C0 = load_be<uint32_t>(in, 4);
176
0
      uint32_t C1 = load_be<uint32_t>(in, 5);
177
0
      uint32_t C2 = load_be<uint32_t>(in, 6);
178
0
      uint32_t C3 = load_be<uint32_t>(in, 7);
179
180
0
      SM4_E<0>(B0, B1, B2, B3, C0, C1, C2, C3, m_RK, SM4_T_slow);
181
0
      SM4_E<1>(B0, B1, B2, B3, C0, C1, C2, C3, m_RK, SM4_T);
182
0
      SM4_E<2>(B0, B1, B2, B3, C0, C1, C2, C3, m_RK, SM4_T);
183
0
      SM4_E<3>(B0, B1, B2, B3, C0, C1, C2, C3, m_RK, SM4_T);
184
0
      SM4_E<4>(B0, B1, B2, B3, C0, C1, C2, C3, m_RK, SM4_T);
185
0
      SM4_E<5>(B0, B1, B2, B3, C0, C1, C2, C3, m_RK, SM4_T);
186
0
      SM4_E<6>(B0, B1, B2, B3, C0, C1, C2, C3, m_RK, SM4_T);
187
0
      SM4_E<7>(B0, B1, B2, B3, C0, C1, C2, C3, m_RK, SM4_T_slow);
188
189
0
      store_be(out, B3, B2, B1, B0, C3, C2, C1, C0);
190
191
0
      in += 2 * BLOCK_SIZE;
192
0
      out += 2 * BLOCK_SIZE;
193
0
      blocks -= 2;
194
0
   }
195
196
2.25k
   for(size_t i = 0; i != blocks; ++i) {
197
1.12k
      uint32_t B0 = load_be<uint32_t>(in, 0);
198
1.12k
      uint32_t B1 = load_be<uint32_t>(in, 1);
199
1.12k
      uint32_t B2 = load_be<uint32_t>(in, 2);
200
1.12k
      uint32_t B3 = load_be<uint32_t>(in, 3);
201
202
1.12k
      SM4_E<0>(B0, B1, B2, B3, m_RK, SM4_T_slow);
203
1.12k
      SM4_E<1>(B0, B1, B2, B3, m_RK, SM4_T);
204
1.12k
      SM4_E<2>(B0, B1, B2, B3, m_RK, SM4_T);
205
1.12k
      SM4_E<3>(B0, B1, B2, B3, m_RK, SM4_T);
206
1.12k
      SM4_E<4>(B0, B1, B2, B3, m_RK, SM4_T);
207
1.12k
      SM4_E<5>(B0, B1, B2, B3, m_RK, SM4_T);
208
1.12k
      SM4_E<6>(B0, B1, B2, B3, m_RK, SM4_T);
209
1.12k
      SM4_E<7>(B0, B1, B2, B3, m_RK, SM4_T_slow);
210
211
1.12k
      store_be(out, B3, B2, B1, B0);
212
213
1.12k
      in += BLOCK_SIZE;
214
1.12k
      out += BLOCK_SIZE;
215
1.12k
   }
216
1.12k
}
217
218
/*
219
* SM4 Decryption
220
*/
221
0
void SM4::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
222
0
   assert_key_material_set();
223
224
#if defined(BOTAN_HAS_SM4_ARMV8)
225
   if(CPUID::has_arm_sm4())
226
      return sm4_armv8_decrypt(in, out, blocks);
227
#endif
228
229
0
   while(blocks >= 2) {
230
0
      uint32_t B0 = load_be<uint32_t>(in, 0);
231
0
      uint32_t B1 = load_be<uint32_t>(in, 1);
232
0
      uint32_t B2 = load_be<uint32_t>(in, 2);
233
0
      uint32_t B3 = load_be<uint32_t>(in, 3);
234
235
0
      uint32_t C0 = load_be<uint32_t>(in, 4);
236
0
      uint32_t C1 = load_be<uint32_t>(in, 5);
237
0
      uint32_t C2 = load_be<uint32_t>(in, 6);
238
0
      uint32_t C3 = load_be<uint32_t>(in, 7);
239
240
0
      SM4_D<7>(B0, B1, B2, B3, C0, C1, C2, C3, m_RK, SM4_T_slow);
241
0
      SM4_D<6>(B0, B1, B2, B3, C0, C1, C2, C3, m_RK, SM4_T);
242
0
      SM4_D<5>(B0, B1, B2, B3, C0, C1, C2, C3, m_RK, SM4_T);
243
0
      SM4_D<4>(B0, B1, B2, B3, C0, C1, C2, C3, m_RK, SM4_T);
244
0
      SM4_D<3>(B0, B1, B2, B3, C0, C1, C2, C3, m_RK, SM4_T);
245
0
      SM4_D<2>(B0, B1, B2, B3, C0, C1, C2, C3, m_RK, SM4_T);
246
0
      SM4_D<1>(B0, B1, B2, B3, C0, C1, C2, C3, m_RK, SM4_T);
247
0
      SM4_D<0>(B0, B1, B2, B3, C0, C1, C2, C3, m_RK, SM4_T_slow);
248
249
0
      store_be(out, B3, B2, B1, B0, C3, C2, C1, C0);
250
251
0
      in += 2 * BLOCK_SIZE;
252
0
      out += 2 * BLOCK_SIZE;
253
0
      blocks -= 2;
254
0
   }
255
256
0
   for(size_t i = 0; i != blocks; ++i) {
257
0
      uint32_t B0 = load_be<uint32_t>(in, 0);
258
0
      uint32_t B1 = load_be<uint32_t>(in, 1);
259
0
      uint32_t B2 = load_be<uint32_t>(in, 2);
260
0
      uint32_t B3 = load_be<uint32_t>(in, 3);
261
262
0
      SM4_D<7>(B0, B1, B2, B3, m_RK, SM4_T_slow);
263
0
      SM4_D<6>(B0, B1, B2, B3, m_RK, SM4_T);
264
0
      SM4_D<5>(B0, B1, B2, B3, m_RK, SM4_T);
265
0
      SM4_D<4>(B0, B1, B2, B3, m_RK, SM4_T);
266
0
      SM4_D<3>(B0, B1, B2, B3, m_RK, SM4_T);
267
0
      SM4_D<2>(B0, B1, B2, B3, m_RK, SM4_T);
268
0
      SM4_D<1>(B0, B1, B2, B3, m_RK, SM4_T);
269
0
      SM4_D<0>(B0, B1, B2, B3, m_RK, SM4_T_slow);
270
271
0
      store_be(out, B3, B2, B1, B0);
272
273
0
      in += BLOCK_SIZE;
274
0
      out += BLOCK_SIZE;
275
0
   }
276
0
}
277
278
1.12k
bool SM4::has_keying_material() const {
279
1.12k
   return !m_RK.empty();
280
1.12k
}
281
282
/*
283
* SM4 Key Schedule
284
*/
285
78
void SM4::key_schedule(std::span<const uint8_t> key) {
286
   // System parameter or family key
287
78
   const uint32_t FK[4] = {0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc};
288
289
78
   const uint32_t CK[32] = {0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269, 0x70777E85, 0x8C939AA1, 0xA8AFB6BD,
290
78
                            0xC4CBD2D9, 0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249, 0x50575E65, 0x6C737A81,
291
78
                            0x888F969D, 0xA4ABB2B9, 0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229, 0x30373E45,
292
78
                            0x4C535A61, 0x686F767D, 0x848B9299, 0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209,
293
78
                            0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279};
294
295
78
   secure_vector<uint32_t> K(4);
296
78
   K[0] = load_be<uint32_t>(key.data(), 0) ^ FK[0];
297
78
   K[1] = load_be<uint32_t>(key.data(), 1) ^ FK[1];
298
78
   K[2] = load_be<uint32_t>(key.data(), 2) ^ FK[2];
299
78
   K[3] = load_be<uint32_t>(key.data(), 3) ^ FK[3];
300
301
78
   m_RK.resize(32);
302
2.57k
   for(size_t i = 0; i != 32; ++i) {
303
2.49k
      K[i % 4] ^= SM4_Tp(K[(i + 1) % 4] ^ K[(i + 2) % 4] ^ K[(i + 3) % 4] ^ CK[i]);
304
2.49k
      m_RK[i] = K[i % 4];
305
2.49k
   }
306
78
}
307
308
78
void SM4::clear() {
309
78
   zap(m_RK);
310
78
}
311
312
110
size_t SM4::parallelism() const {
313
#if defined(BOTAN_HAS_SM4_ARMV8)
314
   if(CPUID::has_arm_sm4()) {
315
      return 4;
316
   }
317
#endif
318
319
110
   return 1;
320
110
}
321
322
0
std::string SM4::provider() const {
323
#if defined(BOTAN_HAS_SM4_ARMV8)
324
   if(CPUID::has_arm_sm4()) {
325
      return "armv8";
326
   }
327
#endif
328
329
0
   return "base";
330
0
}
331
332
}  // namespace Botan