1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include "qemu/osdep.h"
27#include "qemu/bswap.h"
28#include "crypto/xts.h"
29
30typedef union {
31 uint8_t b[XTS_BLOCK_SIZE];
32 uint64_t u[2];
33} xts_uint128;
34
35static inline void xts_uint128_xor(xts_uint128 *D,
36 const xts_uint128 *S1,
37 const xts_uint128 *S2)
38{
39 D->u[0] = S1->u[0] ^ S2->u[0];
40 D->u[1] = S1->u[1] ^ S2->u[1];
41}
42
43static inline void xts_uint128_cpu_to_les(xts_uint128 *v)
44{
45 cpu_to_le64s(&v->u[0]);
46 cpu_to_le64s(&v->u[1]);
47}
48
49static inline void xts_uint128_le_to_cpus(xts_uint128 *v)
50{
51 le64_to_cpus(&v->u[0]);
52 le64_to_cpus(&v->u[1]);
53}
54
55static void xts_mult_x(xts_uint128 *I)
56{
57 uint64_t tt;
58
59 xts_uint128_le_to_cpus(I);
60
61 tt = I->u[0] >> 63;
62 I->u[0] <<= 1;
63
64 if (I->u[1] >> 63) {
65 I->u[0] ^= 0x87;
66 }
67 I->u[1] <<= 1;
68 I->u[1] |= tt;
69
70 xts_uint128_cpu_to_les(I);
71}
72
73
74
75
76
77
78
79
80
81
82
83
84static inline void xts_tweak_encdec(const void *ctx,
85 xts_cipher_func *func,
86 const xts_uint128 *src,
87 xts_uint128 *dst,
88 xts_uint128 *iv)
89{
90
91 xts_uint128_xor(dst, src, iv);
92
93 func(ctx, XTS_BLOCK_SIZE, dst->b, dst->b);
94
95 xts_uint128_xor(dst, dst, iv);
96
97
98 xts_mult_x(iv);
99}
100
101
102void xts_decrypt(const void *datactx,
103 const void *tweakctx,
104 xts_cipher_func *encfunc,
105 xts_cipher_func *decfunc,
106 uint8_t *iv,
107 size_t length,
108 uint8_t *dst,
109 const uint8_t *src)
110{
111 xts_uint128 PP, CC, T;
112 unsigned long i, m, mo, lim;
113
114
115 m = length >> 4;
116 mo = length & 15;
117
118
119 g_assert(m != 0);
120
121 if (mo == 0) {
122 lim = m;
123 } else {
124 lim = m - 1;
125 }
126
127
128 encfunc(tweakctx, XTS_BLOCK_SIZE, T.b, iv);
129
130 if (QEMU_PTR_IS_ALIGNED(src, sizeof(uint64_t)) &&
131 QEMU_PTR_IS_ALIGNED(dst, sizeof(uint64_t))) {
132 xts_uint128 *S = (xts_uint128 *)src;
133 xts_uint128 *D = (xts_uint128 *)dst;
134 for (i = 0; i < lim; i++, S++, D++) {
135 xts_tweak_encdec(datactx, decfunc, S, D, &T);
136 }
137 } else {
138 xts_uint128 D;
139
140 for (i = 0; i < lim; i++) {
141 memcpy(&D, src, XTS_BLOCK_SIZE);
142 xts_tweak_encdec(datactx, decfunc, &D, &D, &T);
143 memcpy(dst, &D, XTS_BLOCK_SIZE);
144 src += XTS_BLOCK_SIZE;
145 dst += XTS_BLOCK_SIZE;
146 }
147 }
148
149
150 if (mo > 0) {
151 xts_uint128 S, D;
152 memcpy(&CC, &T, XTS_BLOCK_SIZE);
153 xts_mult_x(&CC);
154
155
156 memcpy(&S, src, XTS_BLOCK_SIZE);
157 xts_tweak_encdec(datactx, decfunc, &S, &PP, &CC);
158
159
160 for (i = 0; i < mo; i++) {
161 CC.b[i] = src[XTS_BLOCK_SIZE + i];
162 dst[XTS_BLOCK_SIZE + i] = PP.b[i];
163 }
164 for (; i < XTS_BLOCK_SIZE; i++) {
165 CC.b[i] = PP.b[i];
166 }
167
168
169 xts_tweak_encdec(datactx, decfunc, &CC, &D, &T);
170 memcpy(dst, &D, XTS_BLOCK_SIZE);
171 }
172
173
174 decfunc(tweakctx, XTS_BLOCK_SIZE, iv, T.b);
175}
176
177
178void xts_encrypt(const void *datactx,
179 const void *tweakctx,
180 xts_cipher_func *encfunc,
181 xts_cipher_func *decfunc,
182 uint8_t *iv,
183 size_t length,
184 uint8_t *dst,
185 const uint8_t *src)
186{
187 xts_uint128 PP, CC, T;
188 unsigned long i, m, mo, lim;
189
190
191 m = length >> 4;
192 mo = length & 15;
193
194
195 g_assert(m != 0);
196
197 if (mo == 0) {
198 lim = m;
199 } else {
200 lim = m - 1;
201 }
202
203
204 encfunc(tweakctx, XTS_BLOCK_SIZE, T.b, iv);
205
206 if (QEMU_PTR_IS_ALIGNED(src, sizeof(uint64_t)) &&
207 QEMU_PTR_IS_ALIGNED(dst, sizeof(uint64_t))) {
208 xts_uint128 *S = (xts_uint128 *)src;
209 xts_uint128 *D = (xts_uint128 *)dst;
210 for (i = 0; i < lim; i++, S++, D++) {
211 xts_tweak_encdec(datactx, encfunc, S, D, &T);
212 }
213 } else {
214 xts_uint128 D;
215
216 for (i = 0; i < lim; i++) {
217 memcpy(&D, src, XTS_BLOCK_SIZE);
218 xts_tweak_encdec(datactx, encfunc, &D, &D, &T);
219 memcpy(dst, &D, XTS_BLOCK_SIZE);
220
221 dst += XTS_BLOCK_SIZE;
222 src += XTS_BLOCK_SIZE;
223 }
224 }
225
226
227 if (mo > 0) {
228 xts_uint128 S, D;
229
230 memcpy(&S, src, XTS_BLOCK_SIZE);
231 xts_tweak_encdec(datactx, encfunc, &S, &CC, &T);
232
233
234 for (i = 0; i < mo; i++) {
235 PP.b[i] = src[XTS_BLOCK_SIZE + i];
236 dst[XTS_BLOCK_SIZE + i] = CC.b[i];
237 }
238
239 for (; i < XTS_BLOCK_SIZE; i++) {
240 PP.b[i] = CC.b[i];
241 }
242
243
244 xts_tweak_encdec(datactx, encfunc, &PP, &D, &T);
245 memcpy(dst, &D, XTS_BLOCK_SIZE);
246 }
247
248
249 decfunc(tweakctx, XTS_BLOCK_SIZE, iv, T.b);
250}
251