2 * QEMU Crypto XTS cipher mode
4 * Copyright (c) 2015-2016 Red Hat, Inc.
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 of the License, or (at your option) any later version.
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.
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/>.
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
26 #include "qemu/osdep.h"
27 #include "qemu/bswap.h"
28 #include "crypto/xts.h"
31 uint8_t b
[XTS_BLOCK_SIZE
];
35 static inline void xts_uint128_xor(xts_uint128
*D
,
36 const xts_uint128
*S1
,
37 const xts_uint128
*S2
)
39 D
->u
[0] = S1
->u
[0] ^ S2
->u
[0];
40 D
->u
[1] = S1
->u
[1] ^ S2
->u
[1];
43 static inline void xts_uint128_cpu_to_les(xts_uint128
*v
)
45 cpu_to_le64s(&v
->u
[0]);
46 cpu_to_le64s(&v
->u
[1]);
49 static inline void xts_uint128_le_to_cpus(xts_uint128
*v
)
51 le64_to_cpus(&v
->u
[0]);
52 le64_to_cpus(&v
->u
[1]);
55 static void xts_mult_x(xts_uint128
*I
)
59 xts_uint128_le_to_cpus(I
);
70 xts_uint128_cpu_to_les(I
);
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
82 * Encrypt/decrypt data with a tweak
84 static inline void xts_tweak_encdec(const void *ctx
,
85 xts_cipher_func
*func
,
86 const xts_uint128
*src
,
90 /* tweak encrypt block i */
91 xts_uint128_xor(dst
, src
, iv
);
93 func(ctx
, XTS_BLOCK_SIZE
, dst
->b
, dst
->b
);
95 xts_uint128_xor(dst
, dst
, iv
);
102 void xts_decrypt(const void *datactx
,
103 const void *tweakctx
,
104 xts_cipher_func
*encfunc
,
105 xts_cipher_func
*decfunc
,
111 xts_uint128 PP
, CC
, T
;
112 unsigned long i
, m
, mo
, lim
;
114 /* get number of blocks */
118 /* must have at least one full block */
128 encfunc(tweakctx
, XTS_BLOCK_SIZE
, T
.b
, iv
);
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
);
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
;
149 /* if length is not a multiple of XTS_BLOCK_SIZE then */
152 memcpy(&CC
, &T
, XTS_BLOCK_SIZE
);
155 /* PP = tweak decrypt block m-1 */
156 memcpy(&S
, src
, XTS_BLOCK_SIZE
);
157 xts_tweak_encdec(datactx
, decfunc
, &S
, &PP
, &CC
);
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
];
164 for (; i
< XTS_BLOCK_SIZE
; i
++) {
168 /* Pm-1 = Tweak uncrypt CC */
169 xts_tweak_encdec(datactx
, decfunc
, &CC
, &D
, &T
);
170 memcpy(dst
, &D
, XTS_BLOCK_SIZE
);
173 /* Decrypt the iv back */
174 decfunc(tweakctx
, XTS_BLOCK_SIZE
, iv
, T
.b
);
178 void xts_encrypt(const void *datactx
,
179 const void *tweakctx
,
180 xts_cipher_func
*encfunc
,
181 xts_cipher_func
*decfunc
,
187 xts_uint128 PP
, CC
, T
;
188 unsigned long i
, m
, mo
, lim
;
190 /* get number of blocks */
194 /* must have at least one full block */
204 encfunc(tweakctx
, XTS_BLOCK_SIZE
, T
.b
, iv
);
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
);
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
);
221 dst
+= XTS_BLOCK_SIZE
;
222 src
+= XTS_BLOCK_SIZE
;
226 /* if length is not a multiple of XTS_BLOCK_SIZE then */
229 /* CC = tweak encrypt block m-1 */
230 memcpy(&S
, src
, XTS_BLOCK_SIZE
);
231 xts_tweak_encdec(datactx
, encfunc
, &S
, &CC
, &T
);
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
];
239 for (; i
< XTS_BLOCK_SIZE
; i
++) {
243 /* Cm-1 = Tweak encrypt PP */
244 xts_tweak_encdec(datactx
, encfunc
, &PP
, &D
, &T
);
245 memcpy(dst
, &D
, XTS_BLOCK_SIZE
);
248 /* Decrypt the iv back */
249 decfunc(tweakctx
, XTS_BLOCK_SIZE
, iv
, T
.b
);