1 /*
2 * QEMU Crypto XTS cipher mode
3 *
4 * Copyright (c) 2015-2016 Red Hat, Inc.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 *
19 * This code is originally derived from public domain / WTFPL code in
20 * LibTomCrypt crytographic library http://libtom.org. The XTS code
21 * was donated by Elliptic Semiconductor Inc (www.ellipticsemi.com)
22 * to the LibTom Projects
23 *
24 */
25
26 #include "qemu/osdep.h"
27 #include "qemu/bswap.h"
28 #include "crypto/xts.h"
29
30 typedef union {
31 uint8_t b[XTS_BLOCK_SIZE];
32 uint64_t u[2];
33 } xts_uint128;
34
xts_uint128_xor(xts_uint128 * D,const xts_uint128 * S1,const xts_uint128 * S2)35 static 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
xts_uint128_cpu_to_les(xts_uint128 * v)43 static 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
xts_uint128_le_to_cpus(xts_uint128 * v)49 static 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
xts_mult_x(xts_uint128 * I)55 static 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 * xts_tweak_encdec:
76 * @param ctxt: the cipher context
77 * @param func: the cipher function
78 * @src: buffer providing the input text of XTS_BLOCK_SIZE bytes
79 * @dst: buffer to output the output text of XTS_BLOCK_SIZE bytes
80 * @iv: the initialization vector tweak of XTS_BLOCK_SIZE bytes
81 *
82 * Encrypt/decrypt data with a tweak
83 */
xts_tweak_encdec(const void * ctx,xts_cipher_func * func,const xts_uint128 * src,xts_uint128 * dst,xts_uint128 * iv)84 static 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 /* tweak encrypt block i */
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 /* LFSR the tweak */
98 xts_mult_x(iv);
99 }
100
101
xts_decrypt(const void * datactx,const void * tweakctx,xts_cipher_func * encfunc,xts_cipher_func * decfunc,uint8_t * iv,size_t length,uint8_t * dst,const uint8_t * src)102 void 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 /* get number of blocks */
115 m = length >> 4;
116 mo = length & 15;
117
118 /* must have at least one full block */
119 g_assert(m != 0);
120
121 if (mo == 0) {
122 lim = m;
123 } else {
124 lim = m - 1;
125 }
126
127 /* encrypt the iv */
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 /* if length is not a multiple of XTS_BLOCK_SIZE then */
150 if (mo > 0) {
151 xts_uint128 S, D;
152 memcpy(&CC, &T, XTS_BLOCK_SIZE);
153 xts_mult_x(&CC);
154
155 /* PP = tweak decrypt block m-1 */
156 memcpy(&S, src, XTS_BLOCK_SIZE);
157 xts_tweak_encdec(datactx, decfunc, &S, &PP, &CC);
158
159 /* Pm = first length % XTS_BLOCK_SIZE bytes of PP */
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 /* Pm-1 = Tweak uncrypt CC */
169 xts_tweak_encdec(datactx, decfunc, &CC, &D, &T);
170 memcpy(dst, &D, XTS_BLOCK_SIZE);
171 }
172
173 /* Decrypt the iv back */
174 decfunc(tweakctx, XTS_BLOCK_SIZE, iv, T.b);
175 }
176
177
xts_encrypt(const void * datactx,const void * tweakctx,xts_cipher_func * encfunc,xts_cipher_func * decfunc,uint8_t * iv,size_t length,uint8_t * dst,const uint8_t * src)178 void 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 /* get number of blocks */
191 m = length >> 4;
192 mo = length & 15;
193
194 /* must have at least one full block */
195 g_assert(m != 0);
196
197 if (mo == 0) {
198 lim = m;
199 } else {
200 lim = m - 1;
201 }
202
203 /* encrypt the iv */
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 /* if length is not a multiple of XTS_BLOCK_SIZE then */
227 if (mo > 0) {
228 xts_uint128 S, D;
229 /* CC = tweak encrypt block m-1 */
230 memcpy(&S, src, XTS_BLOCK_SIZE);
231 xts_tweak_encdec(datactx, encfunc, &S, &CC, &T);
232
233 /* Cm = first length % XTS_BLOCK_SIZE bytes of CC */
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 /* Cm-1 = Tweak encrypt PP */
244 xts_tweak_encdec(datactx, encfunc, &PP, &D, &T);
245 memcpy(dst, &D, XTS_BLOCK_SIZE);
246 }
247
248 /* Decrypt the iv back */
249 decfunc(tweakctx, XTS_BLOCK_SIZE, iv, T.b);
250 }
251