]> Git Repo - qemu.git/blob - crypto/cipher-builtin.c
crypto: cipher: add cipher driver framework
[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 "qemu/osdep.h"
22 #include "crypto/aes.h"
23 #include "crypto/desrfb.h"
24 #include "crypto/xts.h"
25 #include "cipherpriv.h"
26
27 typedef struct QCryptoCipherBuiltinAESContext QCryptoCipherBuiltinAESContext;
28 struct QCryptoCipherBuiltinAESContext {
29     AES_KEY enc;
30     AES_KEY dec;
31 };
32 typedef struct QCryptoCipherBuiltinAES QCryptoCipherBuiltinAES;
33 struct QCryptoCipherBuiltinAES {
34     QCryptoCipherBuiltinAESContext key;
35     QCryptoCipherBuiltinAESContext key_tweak;
36     uint8_t iv[AES_BLOCK_SIZE];
37 };
38 typedef struct QCryptoCipherBuiltinDESRFB QCryptoCipherBuiltinDESRFB;
39 struct QCryptoCipherBuiltinDESRFB {
40     uint8_t *key;
41     size_t nkey;
42 };
43
44 typedef struct QCryptoCipherBuiltin QCryptoCipherBuiltin;
45 struct QCryptoCipherBuiltin {
46     union {
47         QCryptoCipherBuiltinAES aes;
48         QCryptoCipherBuiltinDESRFB desrfb;
49     } state;
50     size_t blocksize;
51     void (*free)(QCryptoCipher *cipher);
52     int (*setiv)(QCryptoCipher *cipher,
53                  const uint8_t *iv, size_t niv,
54                  Error **errp);
55     int (*encrypt)(QCryptoCipher *cipher,
56                    const void *in,
57                    void *out,
58                    size_t len,
59                    Error **errp);
60     int (*decrypt)(QCryptoCipher *cipher,
61                    const void *in,
62                    void *out,
63                    size_t len,
64                    Error **errp);
65 };
66
67
68 static void qcrypto_cipher_free_aes(QCryptoCipher *cipher)
69 {
70     QCryptoCipherBuiltin *ctxt = cipher->opaque;
71
72     g_free(ctxt);
73     cipher->opaque = NULL;
74 }
75
76
77 static void qcrypto_cipher_aes_ecb_encrypt(AES_KEY *key,
78                                            const void *in,
79                                            void *out,
80                                            size_t len)
81 {
82     const uint8_t *inptr = in;
83     uint8_t *outptr = out;
84     while (len) {
85         if (len > AES_BLOCK_SIZE) {
86             AES_encrypt(inptr, outptr, key);
87             inptr += AES_BLOCK_SIZE;
88             outptr += AES_BLOCK_SIZE;
89             len -= AES_BLOCK_SIZE;
90         } else {
91             uint8_t tmp1[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE];
92             memcpy(tmp1, inptr, len);
93             /* Fill with 0 to avoid valgrind uninitialized reads */
94             memset(tmp1 + len, 0, sizeof(tmp1) - len);
95             AES_encrypt(tmp1, tmp2, key);
96             memcpy(outptr, tmp2, len);
97             len = 0;
98         }
99     }
100 }
101
102
103 static void qcrypto_cipher_aes_ecb_decrypt(AES_KEY *key,
104                                            const void *in,
105                                            void *out,
106                                            size_t len)
107 {
108     const uint8_t *inptr = in;
109     uint8_t *outptr = out;
110     while (len) {
111         if (len > AES_BLOCK_SIZE) {
112             AES_decrypt(inptr, outptr, key);
113             inptr += AES_BLOCK_SIZE;
114             outptr += AES_BLOCK_SIZE;
115             len -= AES_BLOCK_SIZE;
116         } else {
117             uint8_t tmp1[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE];
118             memcpy(tmp1, inptr, len);
119             /* Fill with 0 to avoid valgrind uninitialized reads */
120             memset(tmp1 + len, 0, sizeof(tmp1) - len);
121             AES_decrypt(tmp1, tmp2, key);
122             memcpy(outptr, tmp2, len);
123             len = 0;
124         }
125     }
126 }
127
128
129 static void qcrypto_cipher_aes_xts_encrypt(const void *ctx,
130                                            size_t length,
131                                            uint8_t *dst,
132                                            const uint8_t *src)
133 {
134     const QCryptoCipherBuiltinAESContext *aesctx = ctx;
135
136     qcrypto_cipher_aes_ecb_encrypt((AES_KEY *)&aesctx->enc,
137                                    src, dst, length);
138 }
139
140
141 static void qcrypto_cipher_aes_xts_decrypt(const void *ctx,
142                                            size_t length,
143                                            uint8_t *dst,
144                                            const uint8_t *src)
145 {
146     const QCryptoCipherBuiltinAESContext *aesctx = ctx;
147
148     qcrypto_cipher_aes_ecb_decrypt((AES_KEY *)&aesctx->dec,
149                                    src, dst, length);
150 }
151
152
153 static int qcrypto_cipher_encrypt_aes(QCryptoCipher *cipher,
154                                       const void *in,
155                                       void *out,
156                                       size_t len,
157                                       Error **errp)
158 {
159     QCryptoCipherBuiltin *ctxt = cipher->opaque;
160
161     switch (cipher->mode) {
162     case QCRYPTO_CIPHER_MODE_ECB:
163         qcrypto_cipher_aes_ecb_encrypt(&ctxt->state.aes.key.enc,
164                                        in, out, len);
165         break;
166     case QCRYPTO_CIPHER_MODE_CBC:
167         AES_cbc_encrypt(in, out, len,
168                         &ctxt->state.aes.key.enc,
169                         ctxt->state.aes.iv, 1);
170         break;
171     case QCRYPTO_CIPHER_MODE_XTS:
172         xts_encrypt(&ctxt->state.aes.key,
173                     &ctxt->state.aes.key_tweak,
174                     qcrypto_cipher_aes_xts_encrypt,
175                     qcrypto_cipher_aes_xts_decrypt,
176                     ctxt->state.aes.iv,
177                     len, out, in);
178         break;
179     default:
180         g_assert_not_reached();
181     }
182
183     return 0;
184 }
185
186
187 static int qcrypto_cipher_decrypt_aes(QCryptoCipher *cipher,
188                                       const void *in,
189                                       void *out,
190                                       size_t len,
191                                       Error **errp)
192 {
193     QCryptoCipherBuiltin *ctxt = cipher->opaque;
194
195     switch (cipher->mode) {
196     case QCRYPTO_CIPHER_MODE_ECB:
197         qcrypto_cipher_aes_ecb_decrypt(&ctxt->state.aes.key.dec,
198                                        in, out, len);
199         break;
200     case QCRYPTO_CIPHER_MODE_CBC:
201         AES_cbc_encrypt(in, out, len,
202                         &ctxt->state.aes.key.dec,
203                         ctxt->state.aes.iv, 0);
204         break;
205     case QCRYPTO_CIPHER_MODE_XTS:
206         xts_decrypt(&ctxt->state.aes.key,
207                     &ctxt->state.aes.key_tweak,
208                     qcrypto_cipher_aes_xts_encrypt,
209                     qcrypto_cipher_aes_xts_decrypt,
210                     ctxt->state.aes.iv,
211                     len, out, in);
212         break;
213     default:
214         g_assert_not_reached();
215     }
216
217     return 0;
218 }
219
220 static int qcrypto_cipher_setiv_aes(QCryptoCipher *cipher,
221                                      const uint8_t *iv, size_t niv,
222                                      Error **errp)
223 {
224     QCryptoCipherBuiltin *ctxt = cipher->opaque;
225     if (niv != AES_BLOCK_SIZE) {
226         error_setg(errp, "IV must be %d bytes not %zu",
227                    AES_BLOCK_SIZE, niv);
228         return -1;
229     }
230
231     memcpy(ctxt->state.aes.iv, iv, AES_BLOCK_SIZE);
232
233     return 0;
234 }
235
236
237
238
239 static QCryptoCipherBuiltin *
240 qcrypto_cipher_init_aes(QCryptoCipherMode mode,
241                         const uint8_t *key, size_t nkey,
242                         Error **errp)
243 {
244     QCryptoCipherBuiltin *ctxt;
245
246     if (mode != QCRYPTO_CIPHER_MODE_CBC &&
247         mode != QCRYPTO_CIPHER_MODE_ECB &&
248         mode != QCRYPTO_CIPHER_MODE_XTS) {
249         error_setg(errp, "Unsupported cipher mode %s",
250                    QCryptoCipherMode_lookup[mode]);
251         return NULL;
252     }
253
254     ctxt = g_new0(QCryptoCipherBuiltin, 1);
255
256     if (mode == QCRYPTO_CIPHER_MODE_XTS) {
257         if (AES_set_encrypt_key(key, nkey * 4, &ctxt->state.aes.key.enc) != 0) {
258             error_setg(errp, "Failed to set encryption key");
259             goto error;
260         }
261
262         if (AES_set_decrypt_key(key, nkey * 4, &ctxt->state.aes.key.dec) != 0) {
263             error_setg(errp, "Failed to set decryption key");
264             goto error;
265         }
266
267         if (AES_set_encrypt_key(key + (nkey / 2), nkey * 4,
268                                 &ctxt->state.aes.key_tweak.enc) != 0) {
269             error_setg(errp, "Failed to set encryption key");
270             goto error;
271         }
272
273         if (AES_set_decrypt_key(key + (nkey / 2), nkey * 4,
274                                 &ctxt->state.aes.key_tweak.dec) != 0) {
275             error_setg(errp, "Failed to set decryption key");
276             goto error;
277         }
278     } else {
279         if (AES_set_encrypt_key(key, nkey * 8, &ctxt->state.aes.key.enc) != 0) {
280             error_setg(errp, "Failed to set encryption key");
281             goto error;
282         }
283
284         if (AES_set_decrypt_key(key, nkey * 8, &ctxt->state.aes.key.dec) != 0) {
285             error_setg(errp, "Failed to set decryption key");
286             goto error;
287         }
288     }
289
290     ctxt->blocksize = AES_BLOCK_SIZE;
291     ctxt->free = qcrypto_cipher_free_aes;
292     ctxt->setiv = qcrypto_cipher_setiv_aes;
293     ctxt->encrypt = qcrypto_cipher_encrypt_aes;
294     ctxt->decrypt = qcrypto_cipher_decrypt_aes;
295
296     return ctxt;
297
298  error:
299     g_free(ctxt);
300     return NULL;
301 }
302
303
304 static void qcrypto_cipher_free_des_rfb(QCryptoCipher *cipher)
305 {
306     QCryptoCipherBuiltin *ctxt = cipher->opaque;
307
308     g_free(ctxt->state.desrfb.key);
309     g_free(ctxt);
310     cipher->opaque = NULL;
311 }
312
313
314 static int qcrypto_cipher_encrypt_des_rfb(QCryptoCipher *cipher,
315                                           const void *in,
316                                           void *out,
317                                           size_t len,
318                                           Error **errp)
319 {
320     QCryptoCipherBuiltin *ctxt = cipher->opaque;
321     size_t i;
322
323     if (len % 8) {
324         error_setg(errp, "Buffer size must be multiple of 8 not %zu",
325                    len);
326         return -1;
327     }
328
329     deskey(ctxt->state.desrfb.key, EN0);
330
331     for (i = 0; i < len; i += 8) {
332         des((void *)in + i, out + i);
333     }
334
335     return 0;
336 }
337
338
339 static int qcrypto_cipher_decrypt_des_rfb(QCryptoCipher *cipher,
340                                           const void *in,
341                                           void *out,
342                                           size_t len,
343                                           Error **errp)
344 {
345     QCryptoCipherBuiltin *ctxt = cipher->opaque;
346     size_t i;
347
348     if (len % 8) {
349         error_setg(errp, "Buffer size must be multiple of 8 not %zu",
350                    len);
351         return -1;
352     }
353
354     deskey(ctxt->state.desrfb.key, DE1);
355
356     for (i = 0; i < len; i += 8) {
357         des((void *)in + i, out + i);
358     }
359
360     return 0;
361 }
362
363
364 static int qcrypto_cipher_setiv_des_rfb(QCryptoCipher *cipher,
365                                         const uint8_t *iv, size_t niv,
366                                         Error **errp)
367 {
368     error_setg(errp, "Setting IV is not supported");
369     return -1;
370 }
371
372
373 static QCryptoCipherBuiltin *
374 qcrypto_cipher_init_des_rfb(QCryptoCipherMode mode,
375                             const uint8_t *key, size_t nkey,
376                             Error **errp)
377 {
378     QCryptoCipherBuiltin *ctxt;
379
380     if (mode != QCRYPTO_CIPHER_MODE_ECB) {
381         error_setg(errp, "Unsupported cipher mode %s",
382                    QCryptoCipherMode_lookup[mode]);
383         return NULL;
384     }
385
386     ctxt = g_new0(QCryptoCipherBuiltin, 1);
387
388     ctxt->state.desrfb.key = g_new0(uint8_t, nkey);
389     memcpy(ctxt->state.desrfb.key, key, nkey);
390     ctxt->state.desrfb.nkey = nkey;
391
392     ctxt->blocksize = 8;
393     ctxt->free = qcrypto_cipher_free_des_rfb;
394     ctxt->setiv = qcrypto_cipher_setiv_des_rfb;
395     ctxt->encrypt = qcrypto_cipher_encrypt_des_rfb;
396     ctxt->decrypt = qcrypto_cipher_decrypt_des_rfb;
397
398     return ctxt;
399 }
400
401
402 bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
403                              QCryptoCipherMode mode)
404 {
405     switch (alg) {
406     case QCRYPTO_CIPHER_ALG_DES_RFB:
407     case QCRYPTO_CIPHER_ALG_AES_128:
408     case QCRYPTO_CIPHER_ALG_AES_192:
409     case QCRYPTO_CIPHER_ALG_AES_256:
410         break;
411     default:
412         return false;
413     }
414
415     switch (mode) {
416     case QCRYPTO_CIPHER_MODE_ECB:
417     case QCRYPTO_CIPHER_MODE_CBC:
418     case QCRYPTO_CIPHER_MODE_XTS:
419         return true;
420     case QCRYPTO_CIPHER_MODE_CTR:
421         return false;
422     default:
423         return false;
424     }
425 }
426
427
428 static QCryptoCipherBuiltin *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
429                                                     QCryptoCipherMode mode,
430                                                     const uint8_t *key,
431                                                     size_t nkey,
432                                                     Error **errp)
433 {
434     QCryptoCipherBuiltin *ctxt;
435
436     switch (mode) {
437     case QCRYPTO_CIPHER_MODE_ECB:
438     case QCRYPTO_CIPHER_MODE_CBC:
439     case QCRYPTO_CIPHER_MODE_XTS:
440         break;
441     default:
442         error_setg(errp, "Unsupported cipher mode %s",
443                    QCryptoCipherMode_lookup[mode]);
444         return NULL;
445     }
446
447     if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) {
448         return NULL;
449     }
450
451     switch (alg) {
452     case QCRYPTO_CIPHER_ALG_DES_RFB:
453         ctxt = qcrypto_cipher_init_des_rfb(mode, key, nkey, errp);
454         break;
455     case QCRYPTO_CIPHER_ALG_AES_128:
456     case QCRYPTO_CIPHER_ALG_AES_192:
457     case QCRYPTO_CIPHER_ALG_AES_256:
458         ctxt = qcrypto_cipher_init_aes(mode, key, nkey, errp);
459         break;
460     default:
461         error_setg(errp,
462                    "Unsupported cipher algorithm %s",
463                    QCryptoCipherAlgorithm_lookup[alg]);
464         return NULL;
465     }
466
467     return ctxt;
468 }
469
470 static void
471 qcrypto_builtin_cipher_ctx_free(QCryptoCipher *cipher)
472 {
473     QCryptoCipherBuiltin *ctxt;
474
475     ctxt = cipher->opaque;
476     ctxt->free(cipher);
477 }
478
479
480 static int
481 qcrypto_builtin_cipher_encrypt(QCryptoCipher *cipher,
482                                const void *in,
483                                void *out,
484                                size_t len,
485                                Error **errp)
486 {
487     QCryptoCipherBuiltin *ctxt = cipher->opaque;
488
489     if (len % ctxt->blocksize) {
490         error_setg(errp, "Length %zu must be a multiple of block size %zu",
491                    len, ctxt->blocksize);
492         return -1;
493     }
494
495     return ctxt->encrypt(cipher, in, out, len, errp);
496 }
497
498
499 static int
500 qcrypto_builtin_cipher_decrypt(QCryptoCipher *cipher,
501                                const void *in,
502                                void *out,
503                                size_t len,
504                                Error **errp)
505 {
506     QCryptoCipherBuiltin *ctxt = cipher->opaque;
507
508     if (len % ctxt->blocksize) {
509         error_setg(errp, "Length %zu must be a multiple of block size %zu",
510                    len, ctxt->blocksize);
511         return -1;
512     }
513
514     return ctxt->decrypt(cipher, in, out, len, errp);
515 }
516
517
518 static int
519 qcrypto_builtin_cipher_setiv(QCryptoCipher *cipher,
520                              const uint8_t *iv, size_t niv,
521                              Error **errp)
522 {
523     QCryptoCipherBuiltin *ctxt = cipher->opaque;
524
525     return ctxt->setiv(cipher, iv, niv, errp);
526 }
527
528
529 static struct QCryptoCipherDriver qcrypto_cipher_lib_driver = {
530     .cipher_encrypt = qcrypto_builtin_cipher_encrypt,
531     .cipher_decrypt = qcrypto_builtin_cipher_decrypt,
532     .cipher_setiv = qcrypto_builtin_cipher_setiv,
533     .cipher_free = qcrypto_builtin_cipher_ctx_free,
534 };
This page took 0.051978 seconds and 4 git commands to generate.