]>
Commit | Line | Data |
---|---|---|
84f7f180 DB |
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 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 "crypto/xts.h" | |
28 | ||
29 | static void xts_mult_x(uint8_t *I) | |
30 | { | |
31 | int x; | |
32 | uint8_t t, tt; | |
33 | ||
34 | for (x = t = 0; x < 16; x++) { | |
35 | tt = I[x] >> 7; | |
36 | I[x] = ((I[x] << 1) | t) & 0xFF; | |
37 | t = tt; | |
38 | } | |
39 | if (tt) { | |
40 | I[0] ^= 0x87; | |
41 | } | |
42 | } | |
43 | ||
44 | ||
45 | /** | |
46 | * xts_tweak_uncrypt: | |
47 | * @param ctxt: the cipher context | |
48 | * @param func: the cipher function | |
49 | * @src: buffer providing the cipher text of XTS_BLOCK_SIZE bytes | |
50 | * @dst: buffer to output the plain text of XTS_BLOCK_SIZE bytes | |
51 | * @iv: the initialization vector tweak of XTS_BLOCK_SIZE bytes | |
52 | * | |
53 | * Decrypt data with a tweak | |
54 | */ | |
55 | static void xts_tweak_decrypt(const void *ctx, | |
56 | xts_cipher_func *func, | |
57 | const uint8_t *src, | |
58 | uint8_t *dst, | |
59 | uint8_t *iv) | |
60 | { | |
61 | unsigned long x; | |
62 | ||
63 | /* tweak encrypt block i */ | |
64 | for (x = 0; x < XTS_BLOCK_SIZE; x++) { | |
65 | dst[x] = src[x] ^ iv[x]; | |
66 | } | |
67 | ||
68 | func(ctx, XTS_BLOCK_SIZE, dst, dst); | |
69 | ||
70 | for (x = 0; x < XTS_BLOCK_SIZE; x++) { | |
71 | dst[x] = dst[x] ^ iv[x]; | |
72 | } | |
73 | ||
74 | /* LFSR the tweak */ | |
75 | xts_mult_x(iv); | |
76 | } | |
77 | ||
78 | ||
79 | void xts_decrypt(const void *datactx, | |
80 | const void *tweakctx, | |
81 | xts_cipher_func *encfunc, | |
82 | xts_cipher_func *decfunc, | |
83 | uint8_t *iv, | |
84 | size_t length, | |
85 | uint8_t *dst, | |
86 | const uint8_t *src) | |
87 | { | |
88 | uint8_t PP[XTS_BLOCK_SIZE], CC[XTS_BLOCK_SIZE], T[XTS_BLOCK_SIZE]; | |
89 | unsigned long i, m, mo, lim; | |
90 | ||
91 | /* get number of blocks */ | |
92 | m = length >> 4; | |
93 | mo = length & 15; | |
94 | ||
95 | /* must have at least one full block */ | |
96 | g_assert(m != 0); | |
97 | ||
98 | if (mo == 0) { | |
99 | lim = m; | |
100 | } else { | |
101 | lim = m - 1; | |
102 | } | |
103 | ||
104 | /* encrypt the iv */ | |
105 | encfunc(tweakctx, XTS_BLOCK_SIZE, T, iv); | |
106 | ||
107 | for (i = 0; i < lim; i++) { | |
108 | xts_tweak_decrypt(datactx, decfunc, src, dst, T); | |
109 | ||
110 | src += XTS_BLOCK_SIZE; | |
111 | dst += XTS_BLOCK_SIZE; | |
112 | } | |
113 | ||
114 | /* if length is not a multiple of XTS_BLOCK_SIZE then */ | |
115 | if (mo > 0) { | |
116 | memcpy(CC, T, XTS_BLOCK_SIZE); | |
117 | xts_mult_x(CC); | |
118 | ||
119 | /* PP = tweak decrypt block m-1 */ | |
120 | xts_tweak_decrypt(datactx, decfunc, src, PP, CC); | |
121 | ||
122 | /* Pm = first length % XTS_BLOCK_SIZE bytes of PP */ | |
123 | for (i = 0; i < mo; i++) { | |
124 | CC[i] = src[XTS_BLOCK_SIZE + i]; | |
125 | dst[XTS_BLOCK_SIZE + i] = PP[i]; | |
126 | } | |
127 | for (; i < XTS_BLOCK_SIZE; i++) { | |
128 | CC[i] = PP[i]; | |
129 | } | |
130 | ||
131 | /* Pm-1 = Tweak uncrypt CC */ | |
132 | xts_tweak_decrypt(datactx, decfunc, CC, dst, T); | |
133 | } | |
134 | ||
135 | /* Decrypt the iv back */ | |
136 | decfunc(tweakctx, XTS_BLOCK_SIZE, iv, T); | |
137 | } | |
138 | ||
139 | ||
140 | /** | |
141 | * xts_tweak_crypt: | |
142 | * @param ctxt: the cipher context | |
143 | * @param func: the cipher function | |
144 | * @src: buffer providing the plain text of XTS_BLOCK_SIZE bytes | |
145 | * @dst: buffer to output the cipher text of XTS_BLOCK_SIZE bytes | |
146 | * @iv: the initialization vector tweak of XTS_BLOCK_SIZE bytes | |
147 | * | |
148 | * Encrypt data with a tweak | |
149 | */ | |
150 | static void xts_tweak_encrypt(const void *ctx, | |
151 | xts_cipher_func *func, | |
152 | const uint8_t *src, | |
153 | uint8_t *dst, | |
154 | uint8_t *iv) | |
155 | { | |
156 | unsigned long x; | |
157 | ||
158 | /* tweak encrypt block i */ | |
159 | for (x = 0; x < XTS_BLOCK_SIZE; x++) { | |
160 | dst[x] = src[x] ^ iv[x]; | |
161 | } | |
162 | ||
163 | func(ctx, XTS_BLOCK_SIZE, dst, dst); | |
164 | ||
165 | for (x = 0; x < XTS_BLOCK_SIZE; x++) { | |
166 | dst[x] = dst[x] ^ iv[x]; | |
167 | } | |
168 | ||
169 | /* LFSR the tweak */ | |
170 | xts_mult_x(iv); | |
171 | } | |
172 | ||
173 | ||
174 | void xts_encrypt(const void *datactx, | |
175 | const void *tweakctx, | |
176 | xts_cipher_func *encfunc, | |
177 | xts_cipher_func *decfunc, | |
178 | uint8_t *iv, | |
179 | size_t length, | |
180 | uint8_t *dst, | |
181 | const uint8_t *src) | |
182 | { | |
183 | uint8_t PP[XTS_BLOCK_SIZE], CC[XTS_BLOCK_SIZE], T[XTS_BLOCK_SIZE]; | |
184 | unsigned long i, m, mo, lim; | |
185 | ||
186 | /* get number of blocks */ | |
187 | m = length >> 4; | |
188 | mo = length & 15; | |
189 | ||
190 | /* must have at least one full block */ | |
191 | g_assert(m != 0); | |
192 | ||
193 | if (mo == 0) { | |
194 | lim = m; | |
195 | } else { | |
196 | lim = m - 1; | |
197 | } | |
198 | ||
199 | /* encrypt the iv */ | |
200 | encfunc(tweakctx, XTS_BLOCK_SIZE, T, iv); | |
201 | ||
202 | for (i = 0; i < lim; i++) { | |
203 | xts_tweak_encrypt(datactx, encfunc, src, dst, T); | |
204 | ||
205 | dst += XTS_BLOCK_SIZE; | |
206 | src += XTS_BLOCK_SIZE; | |
207 | } | |
208 | ||
209 | /* if length is not a multiple of XTS_BLOCK_SIZE then */ | |
210 | if (mo > 0) { | |
211 | /* CC = tweak encrypt block m-1 */ | |
212 | xts_tweak_encrypt(datactx, encfunc, src, CC, T); | |
213 | ||
214 | /* Cm = first length % XTS_BLOCK_SIZE bytes of CC */ | |
215 | for (i = 0; i < mo; i++) { | |
216 | PP[i] = src[XTS_BLOCK_SIZE + i]; | |
217 | dst[XTS_BLOCK_SIZE + i] = CC[i]; | |
218 | } | |
219 | ||
220 | for (; i < XTS_BLOCK_SIZE; i++) { | |
221 | PP[i] = CC[i]; | |
222 | } | |
223 | ||
224 | /* Cm-1 = Tweak encrypt PP */ | |
225 | xts_tweak_encrypt(datactx, encfunc, PP, dst, T); | |
226 | } | |
227 | ||
228 | /* Decrypt the iv back */ | |
229 | decfunc(tweakctx, XTS_BLOCK_SIZE, iv, T); | |
230 | } |