]>
Commit | Line | Data |
---|---|---|
ed754746 DB |
1 | /* |
2 | * QEMU Crypto cipher nettle algorithms | |
3 | * | |
4 | * Copyright (c) 2015 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 | */ | |
20 | ||
42f7a448 | 21 | #include "qemu/osdep.h" |
eaec903c DB |
22 | #include "crypto/xts.h" |
23 | ||
ed754746 DB |
24 | #include <nettle/nettle-types.h> |
25 | #include <nettle/aes.h> | |
26 | #include <nettle/des.h> | |
27 | #include <nettle/cbc.h> | |
084a85ee | 28 | #include <nettle/cast128.h> |
94318522 | 29 | #include <nettle/serpent.h> |
50f6753e | 30 | #include <nettle/twofish.h> |
ed754746 | 31 | |
becaeb72 RK |
32 | #if CONFIG_NETTLE_VERSION_MAJOR < 3 |
33 | typedef nettle_crypt_func nettle_cipher_func; | |
d3462e37 RK |
34 | |
35 | typedef void * cipher_ctx_t; | |
36 | typedef unsigned cipher_length_t; | |
37 | #else | |
38 | typedef const void * cipher_ctx_t; | |
39 | typedef size_t cipher_length_t; | |
becaeb72 RK |
40 | #endif |
41 | ||
d3462e37 RK |
42 | static nettle_cipher_func aes_encrypt_wrapper; |
43 | static nettle_cipher_func aes_decrypt_wrapper; | |
44 | static nettle_cipher_func des_encrypt_wrapper; | |
45 | static nettle_cipher_func des_decrypt_wrapper; | |
46 | ||
e3ba0b67 DB |
47 | typedef struct QCryptoNettleAES { |
48 | struct aes_ctx enc; | |
49 | struct aes_ctx dec; | |
50 | } QCryptoNettleAES; | |
51 | ||
d3462e37 RK |
52 | static void aes_encrypt_wrapper(cipher_ctx_t ctx, cipher_length_t length, |
53 | uint8_t *dst, const uint8_t *src) | |
54 | { | |
e3ba0b67 DB |
55 | const QCryptoNettleAES *aesctx = ctx; |
56 | aes_encrypt(&aesctx->enc, length, dst, src); | |
d3462e37 RK |
57 | } |
58 | ||
59 | static void aes_decrypt_wrapper(cipher_ctx_t ctx, cipher_length_t length, | |
60 | uint8_t *dst, const uint8_t *src) | |
61 | { | |
e3ba0b67 DB |
62 | const QCryptoNettleAES *aesctx = ctx; |
63 | aes_decrypt(&aesctx->dec, length, dst, src); | |
d3462e37 RK |
64 | } |
65 | ||
66 | static void des_encrypt_wrapper(cipher_ctx_t ctx, cipher_length_t length, | |
67 | uint8_t *dst, const uint8_t *src) | |
68 | { | |
69 | des_encrypt(ctx, length, dst, src); | |
70 | } | |
71 | ||
72 | static void des_decrypt_wrapper(cipher_ctx_t ctx, cipher_length_t length, | |
73 | uint8_t *dst, const uint8_t *src) | |
74 | { | |
75 | des_decrypt(ctx, length, dst, src); | |
76 | } | |
77 | ||
084a85ee DB |
78 | static void cast128_encrypt_wrapper(cipher_ctx_t ctx, cipher_length_t length, |
79 | uint8_t *dst, const uint8_t *src) | |
80 | { | |
81 | cast128_encrypt(ctx, length, dst, src); | |
82 | } | |
83 | ||
84 | static void cast128_decrypt_wrapper(cipher_ctx_t ctx, cipher_length_t length, | |
85 | uint8_t *dst, const uint8_t *src) | |
86 | { | |
87 | cast128_decrypt(ctx, length, dst, src); | |
88 | } | |
89 | ||
94318522 DB |
90 | static void serpent_encrypt_wrapper(cipher_ctx_t ctx, cipher_length_t length, |
91 | uint8_t *dst, const uint8_t *src) | |
92 | { | |
93 | serpent_encrypt(ctx, length, dst, src); | |
94 | } | |
95 | ||
96 | static void serpent_decrypt_wrapper(cipher_ctx_t ctx, cipher_length_t length, | |
97 | uint8_t *dst, const uint8_t *src) | |
98 | { | |
99 | serpent_decrypt(ctx, length, dst, src); | |
100 | } | |
101 | ||
50f6753e DB |
102 | static void twofish_encrypt_wrapper(cipher_ctx_t ctx, cipher_length_t length, |
103 | uint8_t *dst, const uint8_t *src) | |
104 | { | |
105 | twofish_encrypt(ctx, length, dst, src); | |
106 | } | |
107 | ||
108 | static void twofish_decrypt_wrapper(cipher_ctx_t ctx, cipher_length_t length, | |
109 | uint8_t *dst, const uint8_t *src) | |
110 | { | |
111 | twofish_decrypt(ctx, length, dst, src); | |
112 | } | |
113 | ||
ed754746 DB |
114 | typedef struct QCryptoCipherNettle QCryptoCipherNettle; |
115 | struct QCryptoCipherNettle { | |
eaec903c | 116 | /* Primary cipher context for all modes */ |
e3ba0b67 | 117 | void *ctx; |
eaec903c DB |
118 | /* Second cipher context for XTS mode only */ |
119 | void *ctx_tweak; | |
120 | /* Cipher callbacks for both contexts */ | |
becaeb72 RK |
121 | nettle_cipher_func *alg_encrypt; |
122 | nettle_cipher_func *alg_decrypt; | |
eaec903c | 123 | |
ed754746 | 124 | uint8_t *iv; |
3a661f1e | 125 | size_t blocksize; |
ed754746 DB |
126 | }; |
127 | ||
128 | bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg) | |
129 | { | |
130 | switch (alg) { | |
131 | case QCRYPTO_CIPHER_ALG_DES_RFB: | |
132 | case QCRYPTO_CIPHER_ALG_AES_128: | |
133 | case QCRYPTO_CIPHER_ALG_AES_192: | |
134 | case QCRYPTO_CIPHER_ALG_AES_256: | |
084a85ee | 135 | case QCRYPTO_CIPHER_ALG_CAST5_128: |
94318522 DB |
136 | case QCRYPTO_CIPHER_ALG_SERPENT_128: |
137 | case QCRYPTO_CIPHER_ALG_SERPENT_192: | |
138 | case QCRYPTO_CIPHER_ALG_SERPENT_256: | |
50f6753e DB |
139 | case QCRYPTO_CIPHER_ALG_TWOFISH_128: |
140 | case QCRYPTO_CIPHER_ALG_TWOFISH_192: | |
141 | case QCRYPTO_CIPHER_ALG_TWOFISH_256: | |
ed754746 DB |
142 | return true; |
143 | default: | |
144 | return false; | |
145 | } | |
146 | } | |
147 | ||
148 | ||
149 | QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg, | |
150 | QCryptoCipherMode mode, | |
151 | const uint8_t *key, size_t nkey, | |
152 | Error **errp) | |
153 | { | |
154 | QCryptoCipher *cipher; | |
155 | QCryptoCipherNettle *ctx; | |
156 | uint8_t *rfbkey; | |
157 | ||
158 | switch (mode) { | |
159 | case QCRYPTO_CIPHER_MODE_ECB: | |
160 | case QCRYPTO_CIPHER_MODE_CBC: | |
eaec903c | 161 | case QCRYPTO_CIPHER_MODE_XTS: |
ed754746 DB |
162 | break; |
163 | default: | |
164 | error_setg(errp, "Unsupported cipher mode %d", mode); | |
165 | return NULL; | |
166 | } | |
167 | ||
eaec903c | 168 | if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) { |
ed754746 DB |
169 | return NULL; |
170 | } | |
171 | ||
172 | cipher = g_new0(QCryptoCipher, 1); | |
173 | cipher->alg = alg; | |
174 | cipher->mode = mode; | |
175 | ||
176 | ctx = g_new0(QCryptoCipherNettle, 1); | |
177 | ||
178 | switch (alg) { | |
179 | case QCRYPTO_CIPHER_ALG_DES_RFB: | |
e3ba0b67 | 180 | ctx->ctx = g_new0(struct des_ctx, 1); |
ed754746 | 181 | rfbkey = qcrypto_cipher_munge_des_rfb_key(key, nkey); |
e3ba0b67 | 182 | des_set_key(ctx->ctx, rfbkey); |
ed754746 DB |
183 | g_free(rfbkey); |
184 | ||
d3462e37 RK |
185 | ctx->alg_encrypt = des_encrypt_wrapper; |
186 | ctx->alg_decrypt = des_decrypt_wrapper; | |
ed754746 | 187 | |
3a661f1e | 188 | ctx->blocksize = DES_BLOCK_SIZE; |
ed754746 DB |
189 | break; |
190 | ||
191 | case QCRYPTO_CIPHER_ALG_AES_128: | |
192 | case QCRYPTO_CIPHER_ALG_AES_192: | |
193 | case QCRYPTO_CIPHER_ALG_AES_256: | |
e3ba0b67 | 194 | ctx->ctx = g_new0(QCryptoNettleAES, 1); |
ed754746 | 195 | |
eaec903c DB |
196 | if (mode == QCRYPTO_CIPHER_MODE_XTS) { |
197 | ctx->ctx_tweak = g_new0(QCryptoNettleAES, 1); | |
198 | ||
199 | nkey /= 2; | |
200 | aes_set_encrypt_key(&((QCryptoNettleAES *)ctx->ctx)->enc, | |
201 | nkey, key); | |
202 | aes_set_decrypt_key(&((QCryptoNettleAES *)ctx->ctx)->dec, | |
203 | nkey, key); | |
204 | ||
205 | aes_set_encrypt_key(&((QCryptoNettleAES *)ctx->ctx_tweak)->enc, | |
206 | nkey, key + nkey); | |
207 | aes_set_decrypt_key(&((QCryptoNettleAES *)ctx->ctx_tweak)->dec, | |
208 | nkey, key + nkey); | |
209 | } else { | |
210 | aes_set_encrypt_key(&((QCryptoNettleAES *)ctx->ctx)->enc, | |
211 | nkey, key); | |
212 | aes_set_decrypt_key(&((QCryptoNettleAES *)ctx->ctx)->dec, | |
213 | nkey, key); | |
214 | } | |
ed754746 | 215 | |
d3462e37 RK |
216 | ctx->alg_encrypt = aes_encrypt_wrapper; |
217 | ctx->alg_decrypt = aes_decrypt_wrapper; | |
ed754746 | 218 | |
3a661f1e | 219 | ctx->blocksize = AES_BLOCK_SIZE; |
ed754746 | 220 | break; |
084a85ee DB |
221 | |
222 | case QCRYPTO_CIPHER_ALG_CAST5_128: | |
e3ba0b67 | 223 | ctx->ctx = g_new0(struct cast128_ctx, 1); |
084a85ee | 224 | |
eaec903c DB |
225 | if (mode == QCRYPTO_CIPHER_MODE_XTS) { |
226 | ctx->ctx_tweak = g_new0(struct cast128_ctx, 1); | |
227 | ||
228 | nkey /= 2; | |
229 | cast5_set_key(ctx->ctx, nkey, key); | |
230 | cast5_set_key(ctx->ctx_tweak, nkey, key + nkey); | |
231 | } else { | |
232 | cast5_set_key(ctx->ctx, nkey, key); | |
233 | } | |
084a85ee DB |
234 | |
235 | ctx->alg_encrypt = cast128_encrypt_wrapper; | |
236 | ctx->alg_decrypt = cast128_decrypt_wrapper; | |
237 | ||
238 | ctx->blocksize = CAST128_BLOCK_SIZE; | |
239 | break; | |
94318522 DB |
240 | |
241 | case QCRYPTO_CIPHER_ALG_SERPENT_128: | |
242 | case QCRYPTO_CIPHER_ALG_SERPENT_192: | |
243 | case QCRYPTO_CIPHER_ALG_SERPENT_256: | |
e3ba0b67 | 244 | ctx->ctx = g_new0(struct serpent_ctx, 1); |
94318522 | 245 | |
eaec903c DB |
246 | if (mode == QCRYPTO_CIPHER_MODE_XTS) { |
247 | ctx->ctx_tweak = g_new0(struct serpent_ctx, 1); | |
248 | ||
249 | nkey /= 2; | |
250 | serpent_set_key(ctx->ctx, nkey, key); | |
251 | serpent_set_key(ctx->ctx_tweak, nkey, key + nkey); | |
252 | } else { | |
253 | serpent_set_key(ctx->ctx, nkey, key); | |
254 | } | |
94318522 DB |
255 | |
256 | ctx->alg_encrypt = serpent_encrypt_wrapper; | |
257 | ctx->alg_decrypt = serpent_decrypt_wrapper; | |
258 | ||
259 | ctx->blocksize = SERPENT_BLOCK_SIZE; | |
260 | break; | |
261 | ||
50f6753e DB |
262 | case QCRYPTO_CIPHER_ALG_TWOFISH_128: |
263 | case QCRYPTO_CIPHER_ALG_TWOFISH_192: | |
264 | case QCRYPTO_CIPHER_ALG_TWOFISH_256: | |
e3ba0b67 | 265 | ctx->ctx = g_new0(struct twofish_ctx, 1); |
50f6753e | 266 | |
eaec903c DB |
267 | if (mode == QCRYPTO_CIPHER_MODE_XTS) { |
268 | ctx->ctx_tweak = g_new0(struct twofish_ctx, 1); | |
269 | ||
270 | nkey /= 2; | |
271 | twofish_set_key(ctx->ctx, nkey, key); | |
272 | twofish_set_key(ctx->ctx_tweak, nkey, key + nkey); | |
273 | } else { | |
274 | twofish_set_key(ctx->ctx, nkey, key); | |
275 | } | |
50f6753e DB |
276 | |
277 | ctx->alg_encrypt = twofish_encrypt_wrapper; | |
278 | ctx->alg_decrypt = twofish_decrypt_wrapper; | |
279 | ||
280 | ctx->blocksize = TWOFISH_BLOCK_SIZE; | |
281 | break; | |
282 | ||
ed754746 DB |
283 | default: |
284 | error_setg(errp, "Unsupported cipher algorithm %d", alg); | |
285 | goto error; | |
286 | } | |
287 | ||
3a661f1e | 288 | ctx->iv = g_new0(uint8_t, ctx->blocksize); |
ed754746 DB |
289 | cipher->opaque = ctx; |
290 | ||
291 | return cipher; | |
292 | ||
293 | error: | |
294 | g_free(cipher); | |
295 | g_free(ctx); | |
296 | return NULL; | |
297 | } | |
298 | ||
299 | ||
300 | void qcrypto_cipher_free(QCryptoCipher *cipher) | |
301 | { | |
302 | QCryptoCipherNettle *ctx; | |
303 | ||
304 | if (!cipher) { | |
305 | return; | |
306 | } | |
307 | ||
308 | ctx = cipher->opaque; | |
309 | g_free(ctx->iv); | |
e3ba0b67 | 310 | g_free(ctx->ctx); |
eaec903c | 311 | g_free(ctx->ctx_tweak); |
ed754746 DB |
312 | g_free(ctx); |
313 | g_free(cipher); | |
314 | } | |
315 | ||
316 | ||
317 | int qcrypto_cipher_encrypt(QCryptoCipher *cipher, | |
318 | const void *in, | |
319 | void *out, | |
320 | size_t len, | |
321 | Error **errp) | |
322 | { | |
323 | QCryptoCipherNettle *ctx = cipher->opaque; | |
324 | ||
3a661f1e DB |
325 | if (len % ctx->blocksize) { |
326 | error_setg(errp, "Length %zu must be a multiple of block size %zu", | |
327 | len, ctx->blocksize); | |
328 | return -1; | |
329 | } | |
330 | ||
ed754746 DB |
331 | switch (cipher->mode) { |
332 | case QCRYPTO_CIPHER_MODE_ECB: | |
e3ba0b67 | 333 | ctx->alg_encrypt(ctx->ctx, len, out, in); |
ed754746 DB |
334 | break; |
335 | ||
336 | case QCRYPTO_CIPHER_MODE_CBC: | |
e3ba0b67 | 337 | cbc_encrypt(ctx->ctx, ctx->alg_encrypt, |
3a661f1e | 338 | ctx->blocksize, ctx->iv, |
ed754746 DB |
339 | len, out, in); |
340 | break; | |
e3ba0b67 | 341 | |
eaec903c DB |
342 | case QCRYPTO_CIPHER_MODE_XTS: |
343 | xts_encrypt(ctx->ctx, ctx->ctx_tweak, | |
344 | ctx->alg_encrypt, ctx->alg_encrypt, | |
345 | ctx->iv, len, out, in); | |
346 | break; | |
347 | ||
ed754746 DB |
348 | default: |
349 | error_setg(errp, "Unsupported cipher algorithm %d", | |
350 | cipher->alg); | |
351 | return -1; | |
352 | } | |
353 | return 0; | |
354 | } | |
355 | ||
356 | ||
357 | int qcrypto_cipher_decrypt(QCryptoCipher *cipher, | |
358 | const void *in, | |
359 | void *out, | |
360 | size_t len, | |
361 | Error **errp) | |
362 | { | |
363 | QCryptoCipherNettle *ctx = cipher->opaque; | |
364 | ||
3a661f1e DB |
365 | if (len % ctx->blocksize) { |
366 | error_setg(errp, "Length %zu must be a multiple of block size %zu", | |
367 | len, ctx->blocksize); | |
368 | return -1; | |
369 | } | |
370 | ||
ed754746 DB |
371 | switch (cipher->mode) { |
372 | case QCRYPTO_CIPHER_MODE_ECB: | |
e3ba0b67 | 373 | ctx->alg_decrypt(ctx->ctx, len, out, in); |
ed754746 DB |
374 | break; |
375 | ||
376 | case QCRYPTO_CIPHER_MODE_CBC: | |
e3ba0b67 DB |
377 | cbc_decrypt(ctx->ctx, ctx->alg_decrypt, |
378 | ctx->blocksize, ctx->iv, | |
ed754746 DB |
379 | len, out, in); |
380 | break; | |
e3ba0b67 | 381 | |
eaec903c DB |
382 | case QCRYPTO_CIPHER_MODE_XTS: |
383 | if (ctx->blocksize != XTS_BLOCK_SIZE) { | |
384 | error_setg(errp, "Block size must be %d not %zu", | |
385 | XTS_BLOCK_SIZE, ctx->blocksize); | |
386 | return -1; | |
387 | } | |
388 | xts_decrypt(ctx->ctx, ctx->ctx_tweak, | |
389 | ctx->alg_encrypt, ctx->alg_decrypt, | |
390 | ctx->iv, len, out, in); | |
391 | break; | |
392 | ||
ed754746 DB |
393 | default: |
394 | error_setg(errp, "Unsupported cipher algorithm %d", | |
395 | cipher->alg); | |
396 | return -1; | |
397 | } | |
398 | return 0; | |
399 | } | |
400 | ||
401 | int qcrypto_cipher_setiv(QCryptoCipher *cipher, | |
402 | const uint8_t *iv, size_t niv, | |
403 | Error **errp) | |
404 | { | |
405 | QCryptoCipherNettle *ctx = cipher->opaque; | |
3a661f1e | 406 | if (niv != ctx->blocksize) { |
ed754746 | 407 | error_setg(errp, "Expected IV size %zu not %zu", |
3a661f1e | 408 | ctx->blocksize, niv); |
ed754746 DB |
409 | return -1; |
410 | } | |
411 | memcpy(ctx->iv, iv, niv); | |
412 | return 0; | |
413 | } |