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 | |
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 | |
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 | |
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 | |
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 | */ |
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 | |
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 | |
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 | |