Botan 3.13.0
Crypto and TLS for C&
sm4_armv8.cpp
Go to the documentation of this file.
1/*
2* (C) 2018 Jack Lloyd
3*
4* Botan is released under the Simplified BSD License (see license.txt)
5*/
6
7#include <botan/internal/sm4.h>
8
9#include <botan/internal/isa_extn.h>
10#include <arm_neon.h>
11
12namespace Botan {
13
14namespace {
15
16alignas(16) const uint8_t qswap_tbl[16] = {12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3};
17
18alignas(16) const uint8_t bswap_tbl[16] = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
19
20inline uint32x4_t qswap_32(uint32x4_t B) {
21 return vreinterpretq_u32_u8(vqtbl1q_u8(vreinterpretq_u8_u32(B), vld1q_u8(qswap_tbl)));
22}
23
24inline uint32x4_t bswap_32(uint32x4_t B) {
25 return vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(B)));
26}
27
28/*
29 Swap both the quad-words and bytes within each word
30 equivalent to return bswap_32(qswap_32(B))
31*/
32inline uint32x4_t bqswap_32(uint32x4_t B) {
33 return vreinterpretq_u32_u8(vqtbl1q_u8(vreinterpretq_u8_u32(B), vld1q_u8(bswap_tbl)));
34}
35
36inline void BOTAN_FN_ISA_SM4 SM4_E(uint32x4_t& B0, uint32x4_t& B1, uint32x4_t& B2, uint32x4_t& B3, uint32x4_t K) {
37 B0 = vsm4eq_u32(B0, K);
38 B1 = vsm4eq_u32(B1, K);
39 B2 = vsm4eq_u32(B2, K);
40 B3 = vsm4eq_u32(B3, K);
41}
42
43} // namespace
44
45void BOTAN_FN_ISA_SM4 SM4::sm4_armv8_encrypt(const uint8_t input[], uint8_t output[], size_t blocks) const {
46 const uint32x4_t K0 = vld1q_u32(&m_RK[0]); // NOLINT(*-container-data-pointer)
47 const uint32x4_t K1 = vld1q_u32(&m_RK[4]);
48 const uint32x4_t K2 = vld1q_u32(&m_RK[8]);
49 const uint32x4_t K3 = vld1q_u32(&m_RK[12]);
50 const uint32x4_t K4 = vld1q_u32(&m_RK[16]);
51 const uint32x4_t K5 = vld1q_u32(&m_RK[20]);
52 const uint32x4_t K6 = vld1q_u32(&m_RK[24]);
53 const uint32x4_t K7 = vld1q_u32(&m_RK[28]);
54
55 while(blocks >= 4) {
56 uint32x4_t B0 = bswap_32(vreinterpretq_u32_u8(vld1q_u8(input)));
57 uint32x4_t B1 = bswap_32(vreinterpretq_u32_u8(vld1q_u8(input + 16)));
58 uint32x4_t B2 = bswap_32(vreinterpretq_u32_u8(vld1q_u8(input + 32)));
59 uint32x4_t B3 = bswap_32(vreinterpretq_u32_u8(vld1q_u8(input + 48)));
60
61 SM4_E(B0, B1, B2, B3, K0);
62 SM4_E(B0, B1, B2, B3, K1);
63 SM4_E(B0, B1, B2, B3, K2);
64 SM4_E(B0, B1, B2, B3, K3);
65 SM4_E(B0, B1, B2, B3, K4);
66 SM4_E(B0, B1, B2, B3, K5);
67 SM4_E(B0, B1, B2, B3, K6);
68 SM4_E(B0, B1, B2, B3, K7);
69
70 vst1q_u8(output, vreinterpretq_u8_u32(bqswap_32(B0)));
71 vst1q_u8(output + 16, vreinterpretq_u8_u32(bqswap_32(B1)));
72 vst1q_u8(output + 32, vreinterpretq_u8_u32(bqswap_32(B2)));
73 vst1q_u8(output + 48, vreinterpretq_u8_u32(bqswap_32(B3)));
74
75 input += 64;
76 output += 64;
77 blocks -= 4;
78 }
79
80 for(size_t i = 0; i != blocks; ++i) {
81 uint32x4_t B = bswap_32(vreinterpretq_u32_u8(vld1q_u8(input)));
82
83 B = vsm4eq_u32(B, K0);
84 B = vsm4eq_u32(B, K1);
85 B = vsm4eq_u32(B, K2);
86 B = vsm4eq_u32(B, K3);
87 B = vsm4eq_u32(B, K4);
88 B = vsm4eq_u32(B, K5);
89 B = vsm4eq_u32(B, K6);
90 B = vsm4eq_u32(B, K7);
91
92 vst1q_u8(output, vreinterpretq_u8_u32(bqswap_32(B)));
93
94 input += 16;
95 output += 16;
96 }
97}
98
99void BOTAN_FN_ISA_SM4 SM4::sm4_armv8_decrypt(const uint8_t input[], uint8_t output[], size_t blocks) const {
100 const uint32x4_t K0 = qswap_32(vld1q_u32(&m_RK[0])); // NOLINT(*-container-data-pointer)
101 const uint32x4_t K1 = qswap_32(vld1q_u32(&m_RK[4]));
102 const uint32x4_t K2 = qswap_32(vld1q_u32(&m_RK[8]));
103 const uint32x4_t K3 = qswap_32(vld1q_u32(&m_RK[12]));
104 const uint32x4_t K4 = qswap_32(vld1q_u32(&m_RK[16]));
105 const uint32x4_t K5 = qswap_32(vld1q_u32(&m_RK[20]));
106 const uint32x4_t K6 = qswap_32(vld1q_u32(&m_RK[24]));
107 const uint32x4_t K7 = qswap_32(vld1q_u32(&m_RK[28]));
108
109 while(blocks >= 4) {
110 uint32x4_t B0 = bswap_32(vreinterpretq_u32_u8(vld1q_u8(input)));
111 uint32x4_t B1 = bswap_32(vreinterpretq_u32_u8(vld1q_u8(input + 16)));
112 uint32x4_t B2 = bswap_32(vreinterpretq_u32_u8(vld1q_u8(input + 32)));
113 uint32x4_t B3 = bswap_32(vreinterpretq_u32_u8(vld1q_u8(input + 48)));
114
115 SM4_E(B0, B1, B2, B3, K7);
116 SM4_E(B0, B1, B2, B3, K6);
117 SM4_E(B0, B1, B2, B3, K5);
118 SM4_E(B0, B1, B2, B3, K4);
119 SM4_E(B0, B1, B2, B3, K3);
120 SM4_E(B0, B1, B2, B3, K2);
121 SM4_E(B0, B1, B2, B3, K1);
122 SM4_E(B0, B1, B2, B3, K0);
123
124 vst1q_u8(output, vreinterpretq_u8_u32(bqswap_32(B0)));
125 vst1q_u8(output + 16, vreinterpretq_u8_u32(bqswap_32(B1)));
126 vst1q_u8(output + 32, vreinterpretq_u8_u32(bqswap_32(B2)));
127 vst1q_u8(output + 48, vreinterpretq_u8_u32(bqswap_32(B3)));
128
129 input += 64;
130 output += 64;
131 blocks -= 4;
132 }
133
134 for(size_t i = 0; i != blocks; ++i) {
135 uint32x4_t B = bswap_32(vreinterpretq_u32_u8(vld1q_u8(input)));
136
137 B = vsm4eq_u32(B, K7);
138 B = vsm4eq_u32(B, K6);
139 B = vsm4eq_u32(B, K5);
140 B = vsm4eq_u32(B, K4);
141 B = vsm4eq_u32(B, K3);
142 B = vsm4eq_u32(B, K2);
143 B = vsm4eq_u32(B, K1);
144 B = vsm4eq_u32(B, K0);
145
146 vst1q_u8(output, vreinterpretq_u8_u32(bqswap_32(B)));
147
148 input += 16;
149 output += 16;
150 }
151}
152
153} // namespace Botan
constexpr uint32_t K1
Definition sha1_f.h:16
constexpr uint32_t K4
Definition sha1_f.h:19
constexpr uint32_t K3
Definition sha1_f.h:18
constexpr uint32_t K2
Definition sha1_f.h:17