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