]> git.proxmox.com Git - mirror_qemu.git/blob - crypto/cipher-builtin.c
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-next-20151023' into staging
[mirror_qemu.git] / crypto / cipher-builtin.c
1 /*
2 * QEMU Crypto cipher built-in 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 "crypto/aes.h"
22 #include "crypto/desrfb.h"
23
24 typedef struct QCryptoCipherBuiltinAES QCryptoCipherBuiltinAES;
25 struct QCryptoCipherBuiltinAES {
26 AES_KEY encrypt_key;
27 AES_KEY decrypt_key;
28 uint8_t iv[AES_BLOCK_SIZE];
29 };
30 typedef struct QCryptoCipherBuiltinDESRFB QCryptoCipherBuiltinDESRFB;
31 struct QCryptoCipherBuiltinDESRFB {
32 uint8_t *key;
33 size_t nkey;
34 };
35
36 typedef struct QCryptoCipherBuiltin QCryptoCipherBuiltin;
37 struct QCryptoCipherBuiltin {
38 union {
39 QCryptoCipherBuiltinAES aes;
40 QCryptoCipherBuiltinDESRFB desrfb;
41 } state;
42 size_t blocksize;
43 void (*free)(QCryptoCipher *cipher);
44 int (*setiv)(QCryptoCipher *cipher,
45 const uint8_t *iv, size_t niv,
46 Error **errp);
47 int (*encrypt)(QCryptoCipher *cipher,
48 const void *in,
49 void *out,
50 size_t len,
51 Error **errp);
52 int (*decrypt)(QCryptoCipher *cipher,
53 const void *in,
54 void *out,
55 size_t len,
56 Error **errp);
57 };
58
59
60 static void qcrypto_cipher_free_aes(QCryptoCipher *cipher)
61 {
62 QCryptoCipherBuiltin *ctxt = cipher->opaque;
63
64 g_free(ctxt);
65 cipher->opaque = NULL;
66 }
67
68
69 static int qcrypto_cipher_encrypt_aes(QCryptoCipher *cipher,
70 const void *in,
71 void *out,
72 size_t len,
73 Error **errp)
74 {
75 QCryptoCipherBuiltin *ctxt = cipher->opaque;
76
77 if (cipher->mode == QCRYPTO_CIPHER_MODE_ECB) {
78 const uint8_t *inptr = in;
79 uint8_t *outptr = out;
80 while (len) {
81 if (len > AES_BLOCK_SIZE) {
82 AES_encrypt(inptr, outptr, &ctxt->state.aes.encrypt_key);
83 inptr += AES_BLOCK_SIZE;
84 outptr += AES_BLOCK_SIZE;
85 len -= AES_BLOCK_SIZE;
86 } else {
87 uint8_t tmp1[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE];
88 memcpy(tmp1, inptr, len);
89 /* Fill with 0 to avoid valgrind uninitialized reads */
90 memset(tmp1 + len, 0, sizeof(tmp1) - len);
91 AES_encrypt(tmp1, tmp2, &ctxt->state.aes.encrypt_key);
92 memcpy(outptr, tmp2, len);
93 len = 0;
94 }
95 }
96 } else {
97 AES_cbc_encrypt(in, out, len,
98 &ctxt->state.aes.encrypt_key,
99 ctxt->state.aes.iv, 1);
100 }
101
102 return 0;
103 }
104
105
106 static int qcrypto_cipher_decrypt_aes(QCryptoCipher *cipher,
107 const void *in,
108 void *out,
109 size_t len,
110 Error **errp)
111 {
112 QCryptoCipherBuiltin *ctxt = cipher->opaque;
113
114 if (cipher->mode == QCRYPTO_CIPHER_MODE_ECB) {
115 const uint8_t *inptr = in;
116 uint8_t *outptr = out;
117 while (len) {
118 if (len > AES_BLOCK_SIZE) {
119 AES_decrypt(inptr, outptr, &ctxt->state.aes.decrypt_key);
120 inptr += AES_BLOCK_SIZE;
121 outptr += AES_BLOCK_SIZE;
122 len -= AES_BLOCK_SIZE;
123 } else {
124 uint8_t tmp1[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE];
125 memcpy(tmp1, inptr, len);
126 /* Fill with 0 to avoid valgrind uninitialized reads */
127 memset(tmp1 + len, 0, sizeof(tmp1) - len);
128 AES_decrypt(tmp1, tmp2, &ctxt->state.aes.decrypt_key);
129 memcpy(outptr, tmp2, len);
130 len = 0;
131 }
132 }
133 } else {
134 AES_cbc_encrypt(in, out, len,
135 &ctxt->state.aes.decrypt_key,
136 ctxt->state.aes.iv, 0);
137 }
138
139 return 0;
140 }
141
142 static int qcrypto_cipher_setiv_aes(QCryptoCipher *cipher,
143 const uint8_t *iv, size_t niv,
144 Error **errp)
145 {
146 QCryptoCipherBuiltin *ctxt = cipher->opaque;
147 if (niv != AES_BLOCK_SIZE) {
148 error_setg(errp, "IV must be %d bytes not %zu",
149 AES_BLOCK_SIZE, niv);
150 return -1;
151 }
152
153 memcpy(ctxt->state.aes.iv, iv, AES_BLOCK_SIZE);
154
155 return 0;
156 }
157
158
159
160
161 static int qcrypto_cipher_init_aes(QCryptoCipher *cipher,
162 const uint8_t *key, size_t nkey,
163 Error **errp)
164 {
165 QCryptoCipherBuiltin *ctxt;
166
167 if (cipher->mode != QCRYPTO_CIPHER_MODE_CBC &&
168 cipher->mode != QCRYPTO_CIPHER_MODE_ECB) {
169 error_setg(errp, "Unsupported cipher mode %d", cipher->mode);
170 return -1;
171 }
172
173 ctxt = g_new0(QCryptoCipherBuiltin, 1);
174
175 if (AES_set_encrypt_key(key, nkey * 8, &ctxt->state.aes.encrypt_key) != 0) {
176 error_setg(errp, "Failed to set encryption key");
177 goto error;
178 }
179
180 if (AES_set_decrypt_key(key, nkey * 8, &ctxt->state.aes.decrypt_key) != 0) {
181 error_setg(errp, "Failed to set decryption key");
182 goto error;
183 }
184
185 ctxt->blocksize = AES_BLOCK_SIZE;
186 ctxt->free = qcrypto_cipher_free_aes;
187 ctxt->setiv = qcrypto_cipher_setiv_aes;
188 ctxt->encrypt = qcrypto_cipher_encrypt_aes;
189 ctxt->decrypt = qcrypto_cipher_decrypt_aes;
190
191 cipher->opaque = ctxt;
192
193 return 0;
194
195 error:
196 g_free(ctxt);
197 return -1;
198 }
199
200
201 static void qcrypto_cipher_free_des_rfb(QCryptoCipher *cipher)
202 {
203 QCryptoCipherBuiltin *ctxt = cipher->opaque;
204
205 g_free(ctxt->state.desrfb.key);
206 g_free(ctxt);
207 cipher->opaque = NULL;
208 }
209
210
211 static int qcrypto_cipher_encrypt_des_rfb(QCryptoCipher *cipher,
212 const void *in,
213 void *out,
214 size_t len,
215 Error **errp)
216 {
217 QCryptoCipherBuiltin *ctxt = cipher->opaque;
218 size_t i;
219
220 if (len % 8) {
221 error_setg(errp, "Buffer size must be multiple of 8 not %zu",
222 len);
223 return -1;
224 }
225
226 deskey(ctxt->state.desrfb.key, EN0);
227
228 for (i = 0; i < len; i += 8) {
229 des((void *)in + i, out + i);
230 }
231
232 return 0;
233 }
234
235
236 static int qcrypto_cipher_decrypt_des_rfb(QCryptoCipher *cipher,
237 const void *in,
238 void *out,
239 size_t len,
240 Error **errp)
241 {
242 QCryptoCipherBuiltin *ctxt = cipher->opaque;
243 size_t i;
244
245 if (len % 8) {
246 error_setg(errp, "Buffer size must be multiple of 8 not %zu",
247 len);
248 return -1;
249 }
250
251 deskey(ctxt->state.desrfb.key, DE1);
252
253 for (i = 0; i < len; i += 8) {
254 des((void *)in + i, out + i);
255 }
256
257 return 0;
258 }
259
260
261 static int qcrypto_cipher_setiv_des_rfb(QCryptoCipher *cipher,
262 const uint8_t *iv, size_t niv,
263 Error **errp)
264 {
265 error_setg(errp, "Setting IV is not supported");
266 return -1;
267 }
268
269
270 static int qcrypto_cipher_init_des_rfb(QCryptoCipher *cipher,
271 const uint8_t *key, size_t nkey,
272 Error **errp)
273 {
274 QCryptoCipherBuiltin *ctxt;
275
276 if (cipher->mode != QCRYPTO_CIPHER_MODE_ECB) {
277 error_setg(errp, "Unsupported cipher mode %d", cipher->mode);
278 return -1;
279 }
280
281 ctxt = g_new0(QCryptoCipherBuiltin, 1);
282
283 ctxt->state.desrfb.key = g_new0(uint8_t, nkey);
284 memcpy(ctxt->state.desrfb.key, key, nkey);
285 ctxt->state.desrfb.nkey = nkey;
286
287 ctxt->blocksize = 8;
288 ctxt->free = qcrypto_cipher_free_des_rfb;
289 ctxt->setiv = qcrypto_cipher_setiv_des_rfb;
290 ctxt->encrypt = qcrypto_cipher_encrypt_des_rfb;
291 ctxt->decrypt = qcrypto_cipher_decrypt_des_rfb;
292
293 cipher->opaque = ctxt;
294
295 return 0;
296 }
297
298
299 bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg)
300 {
301 switch (alg) {
302 case QCRYPTO_CIPHER_ALG_DES_RFB:
303 case QCRYPTO_CIPHER_ALG_AES_128:
304 case QCRYPTO_CIPHER_ALG_AES_192:
305 case QCRYPTO_CIPHER_ALG_AES_256:
306 return true;
307 default:
308 return false;
309 }
310 }
311
312
313 QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
314 QCryptoCipherMode mode,
315 const uint8_t *key, size_t nkey,
316 Error **errp)
317 {
318 QCryptoCipher *cipher;
319
320 cipher = g_new0(QCryptoCipher, 1);
321 cipher->alg = alg;
322 cipher->mode = mode;
323
324 if (!qcrypto_cipher_validate_key_length(alg, nkey, errp)) {
325 goto error;
326 }
327
328 switch (cipher->alg) {
329 case QCRYPTO_CIPHER_ALG_DES_RFB:
330 if (qcrypto_cipher_init_des_rfb(cipher, key, nkey, errp) < 0) {
331 goto error;
332 }
333 break;
334 case QCRYPTO_CIPHER_ALG_AES_128:
335 case QCRYPTO_CIPHER_ALG_AES_192:
336 case QCRYPTO_CIPHER_ALG_AES_256:
337 if (qcrypto_cipher_init_aes(cipher, key, nkey, errp) < 0) {
338 goto error;
339 }
340 break;
341 default:
342 error_setg(errp,
343 "Unsupported cipher algorithm %d", cipher->alg);
344 goto error;
345 }
346
347 return cipher;
348
349 error:
350 g_free(cipher);
351 return NULL;
352 }
353
354 void qcrypto_cipher_free(QCryptoCipher *cipher)
355 {
356 QCryptoCipherBuiltin *ctxt;
357
358 if (!cipher) {
359 return;
360 }
361
362 ctxt = cipher->opaque;
363 ctxt->free(cipher);
364 g_free(cipher);
365 }
366
367
368 int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
369 const void *in,
370 void *out,
371 size_t len,
372 Error **errp)
373 {
374 QCryptoCipherBuiltin *ctxt = cipher->opaque;
375
376 if (len % ctxt->blocksize) {
377 error_setg(errp, "Length %zu must be a multiple of block size %zu",
378 len, ctxt->blocksize);
379 return -1;
380 }
381
382 return ctxt->encrypt(cipher, in, out, len, errp);
383 }
384
385
386 int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
387 const void *in,
388 void *out,
389 size_t len,
390 Error **errp)
391 {
392 QCryptoCipherBuiltin *ctxt = cipher->opaque;
393
394 if (len % ctxt->blocksize) {
395 error_setg(errp, "Length %zu must be a multiple of block size %zu",
396 len, ctxt->blocksize);
397 return -1;
398 }
399
400 return ctxt->decrypt(cipher, in, out, len, errp);
401 }
402
403
404 int qcrypto_cipher_setiv(QCryptoCipher *cipher,
405 const uint8_t *iv, size_t niv,
406 Error **errp)
407 {
408 QCryptoCipherBuiltin *ctxt = cipher->opaque;
409
410 return ctxt->setiv(cipher, iv, niv, errp);
411 }