gitlab-ci: Add cross-compiling build tests
[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.1 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(const 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(const 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(&aesctx->enc, src, dst, length);
137 }
138
139
140 static void qcrypto_cipher_aes_xts_decrypt(const void *ctx,
141                                            size_t length,
142                                            uint8_t *dst,
143                                            const uint8_t *src)
144 {
145     const QCryptoCipherBuiltinAESContext *aesctx = ctx;
146
147     qcrypto_cipher_aes_ecb_decrypt(&aesctx->dec, src, dst, length);
148 }
149
150
151 static int qcrypto_cipher_encrypt_aes(QCryptoCipher *cipher,
152                                       const void *in,
153                                       void *out,
154                                       size_t len,
155                                       Error **errp)
156 {
157     QCryptoCipherBuiltin *ctxt = cipher->opaque;
158
159     switch (cipher->mode) {
160     case QCRYPTO_CIPHER_MODE_ECB:
161         qcrypto_cipher_aes_ecb_encrypt(&ctxt->state.aes.key.enc,
162                                        in, out, len);
163         break;
164     case QCRYPTO_CIPHER_MODE_CBC:
165         AES_cbc_encrypt(in, out, len,
166                         &ctxt->state.aes.key.enc,
167                         ctxt->state.aes.iv, 1);
168         break;
169     case QCRYPTO_CIPHER_MODE_XTS:
170         xts_encrypt(&ctxt->state.aes.key,
171                     &ctxt->state.aes.key_tweak,
172                     qcrypto_cipher_aes_xts_encrypt,
173                     qcrypto_cipher_aes_xts_decrypt,
174                     ctxt->state.aes.iv,
175                     len, out, in);
176         break;
177     default:
178         g_assert_not_reached();
179     }
180
181     return 0;
182 }
183
184
185 static int qcrypto_cipher_decrypt_aes(QCryptoCipher *cipher,
186                                       const void *in,
187                                       void *out,
188                                       size_t len,
189                                       Error **errp)
190 {
191     QCryptoCipherBuiltin *ctxt = cipher->opaque;
192
193     switch (cipher->mode) {
194     case QCRYPTO_CIPHER_MODE_ECB:
195         qcrypto_cipher_aes_ecb_decrypt(&ctxt->state.aes.key.dec,
196                                        in, out, len);
197         break;
198     case QCRYPTO_CIPHER_MODE_CBC:
199         AES_cbc_encrypt(in, out, len,
200                         &ctxt->state.aes.key.dec,
201                         ctxt->state.aes.iv, 0);
202         break;
203     case QCRYPTO_CIPHER_MODE_XTS:
204         xts_decrypt(&ctxt->state.aes.key,
205                     &ctxt->state.aes.key_tweak,
206                     qcrypto_cipher_aes_xts_encrypt,
207                     qcrypto_cipher_aes_xts_decrypt,
208                     ctxt->state.aes.iv,
209                     len, out, in);
210         break;
211     default:
212         g_assert_not_reached();
213     }
214
215     return 0;
216 }
217
218 static int qcrypto_cipher_setiv_aes(QCryptoCipher *cipher,
219                                      const uint8_t *iv, size_t niv,
220                                      Error **errp)
221 {
222     QCryptoCipherBuiltin *ctxt = cipher->opaque;
223     if (niv != AES_BLOCK_SIZE) {
224         error_setg(errp, "IV must be %d bytes not %zu",
225                    AES_BLOCK_SIZE, niv);
226         return -1;
227     }
228
229     memcpy(ctxt->state.aes.iv, iv, AES_BLOCK_SIZE);
230
231     return 0;
232 }
233
234
235
236
237 static QCryptoCipherBuiltin *
238 qcrypto_cipher_init_aes(QCryptoCipherMode mode,
239                         const uint8_t *key, size_t nkey,
240                         Error **errp)
241 {
242     QCryptoCipherBuiltin *ctxt;
243
244     if (mode != QCRYPTO_CIPHER_MODE_CBC &&
245         mode != QCRYPTO_CIPHER_MODE_ECB &&
246         mode != QCRYPTO_CIPHER_MODE_XTS) {
247         error_setg(errp, "Unsupported cipher mode %s",
248                    QCryptoCipherMode_str(mode));
249         return NULL;
250     }
251
252     ctxt = g_new0(QCryptoCipherBuiltin, 1);
253
254     if (mode == QCRYPTO_CIPHER_MODE_XTS) {
255         if (AES_set_encrypt_key(key, nkey * 4, &ctxt->state.aes.key.enc) != 0) {
256             error_setg(errp, "Failed to set encryption key");
257             goto error;
258         }
259
260         if (AES_set_decrypt_key(key, nkey * 4, &ctxt->state.aes.key.dec) != 0) {
261             error_setg(errp, "Failed to set decryption key");
262             goto error;
263         }
264
265         if (AES_set_encrypt_key(key + (nkey / 2), nkey * 4,
266                                 &ctxt->state.aes.key_tweak.enc) != 0) {
267             error_setg(errp, "Failed to set encryption key");
268             goto error;
269         }
270
271         if (AES_set_decrypt_key(key + (nkey / 2), nkey * 4,
272                                 &ctxt->state.aes.key_tweak.dec) != 0) {
273             error_setg(errp, "Failed to set decryption key");
274             goto error;
275         }
276     } else {
277         if (AES_set_encrypt_key(key, nkey * 8, &ctxt->state.aes.key.enc) != 0) {
278             error_setg(errp, "Failed to set encryption key");
279             goto error;
280         }
281
282         if (AES_set_decrypt_key(key, nkey * 8, &ctxt->state.aes.key.dec) != 0) {
283             error_setg(errp, "Failed to set decryption key");
284             goto error;
285         }
286     }
287
288     ctxt->blocksize = AES_BLOCK_SIZE;
289     ctxt->free = qcrypto_cipher_free_aes;
290     ctxt->setiv = qcrypto_cipher_setiv_aes;
291     ctxt->encrypt = qcrypto_cipher_encrypt_aes;
292     ctxt->decrypt = qcrypto_cipher_decrypt_aes;
293
294     return ctxt;
295
296  error:
297     g_free(ctxt);
298     return NULL;
299 }
300
301
302 static void qcrypto_cipher_free_des_rfb(QCryptoCipher *cipher)
303 {
304     QCryptoCipherBuiltin *ctxt = cipher->opaque;
305
306     g_free(ctxt->state.desrfb.key);
307     g_free(ctxt);
308     cipher->opaque = NULL;
309 }
310
311
312 static int qcrypto_cipher_encrypt_des_rfb(QCryptoCipher *cipher,
313                                           const void *in,
314                                           void *out,
315                                           size_t len,
316                                           Error **errp)
317 {
318     QCryptoCipherBuiltin *ctxt = cipher->opaque;
319     size_t i;
320
321     if (len % 8) {
322         error_setg(errp, "Buffer size must be multiple of 8 not %zu",
323                    len);
324         return -1;
325     }
326
327     deskey(ctxt->state.desrfb.key, EN0);
328
329     for (i = 0; i < len; i += 8) {
330         des((void *)in + i, out + i);
331     }
332
333     return 0;
334 }
335
336
337 static int qcrypto_cipher_decrypt_des_rfb(QCryptoCipher *cipher,
338                                           const void *in,
339                                           void *out,
340                                           size_t len,
341                                           Error **errp)
342 {
343     QCryptoCipherBuiltin *ctxt = cipher->opaque;
344     size_t i;
345
346     if (len % 8) {
347         error_setg(errp, "Buffer size must be multiple of 8 not %zu",
348                    len);
349         return -1;
350     }
351
352     deskey(ctxt->state.desrfb.key, DE1);
353
354     for (i = 0; i < len; i += 8) {
355         des((void *)in + i, out + i);
356     }
357
358     return 0;
359 }
360
361
362 static int qcrypto_cipher_setiv_des_rfb(QCryptoCipher *cipher,
363                                         const uint8_t *iv, size_t niv,
364                                         Error **errp)
365 {
366     error_setg(errp, "Setting IV is not supported");
367     return -1;
368 }
369
370
371 static QCryptoCipherBuiltin *
372 qcrypto_cipher_init_des_rfb(QCryptoCipherMode mode,
373                             const uint8_t *key, size_t nkey,
374                             Error **errp)
375 {
376     QCryptoCipherBuiltin *ctxt;
377
378     if (mode != QCRYPTO_CIPHER_MODE_ECB) {
379         error_setg(errp, "Unsupported cipher mode %s",
380                    QCryptoCipherMode_str(mode));
381         return NULL;
382     }
383
384     ctxt = g_new0(QCryptoCipherBuiltin, 1);
385
386     ctxt->state.desrfb.key = g_new0(uint8_t, nkey);
387     memcpy(ctxt->state.desrfb.key, key, nkey);
388     ctxt->state.desrfb.nkey = nkey;
389
390     ctxt->blocksize = 8;
391     ctxt->free = qcrypto_cipher_free_des_rfb;
392     ctxt->setiv = qcrypto_cipher_setiv_des_rfb;
393     ctxt->encrypt = qcrypto_cipher_encrypt_des_rfb;
394     ctxt->decrypt = qcrypto_cipher_decrypt_des_rfb;
395
396     return ctxt;
397 }
398
399
400 bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
401                              QCryptoCipherMode mode)
402 {
403     switch (alg) {
404     case QCRYPTO_CIPHER_ALG_DES_RFB:
405     case QCRYPTO_CIPHER_ALG_AES_128:
406     case QCRYPTO_CIPHER_ALG_AES_192:
407     case QCRYPTO_CIPHER_ALG_AES_256:
408         break;
409     default:
410         return false;
411     }
412
413     switch (mode) {
414     case QCRYPTO_CIPHER_MODE_ECB:
415     case QCRYPTO_CIPHER_MODE_CBC:
416     case QCRYPTO_CIPHER_MODE_XTS:
417         return true;
418     case QCRYPTO_CIPHER_MODE_CTR:
419         return false;
420     default:
421         return false;
422     }
423 }
424
425
426 static QCryptoCipherBuiltin *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
427                                                     QCryptoCipherMode mode,
428                                                     const uint8_t *key,
429                                                     size_t nkey,
430                                                     Error **errp)
431 {
432     QCryptoCipherBuiltin *ctxt;
433
434     switch (mode) {
435     case QCRYPTO_CIPHER_MODE_ECB:
436     case QCRYPTO_CIPHER_MODE_CBC:
437     case QCRYPTO_CIPHER_MODE_XTS:
438         break;
439     default:
440         error_setg(errp, "Unsupported cipher mode %s",
441                    QCryptoCipherMode_str(mode));
442         return NULL;
443     }
444
445     if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) {
446         return NULL;
447     }
448
449     switch (alg) {
450     case QCRYPTO_CIPHER_ALG_DES_RFB:
451         ctxt = qcrypto_cipher_init_des_rfb(mode, key, nkey, errp);
452         break;
453     case QCRYPTO_CIPHER_ALG_AES_128:
454     case QCRYPTO_CIPHER_ALG_AES_192:
455     case QCRYPTO_CIPHER_ALG_AES_256:
456         ctxt = qcrypto_cipher_init_aes(mode, key, nkey, errp);
457         break;
458     default:
459         error_setg(errp,
460                    "Unsupported cipher algorithm %s",
461                    QCryptoCipherAlgorithm_str(alg));
462         return NULL;
463     }
464
465     return ctxt;
466 }
467
468 static void
469 qcrypto_builtin_cipher_ctx_free(QCryptoCipher *cipher)
470 {
471     QCryptoCipherBuiltin *ctxt;
472
473     ctxt = cipher->opaque;
474     ctxt->free(cipher);
475 }
476
477
478 static int
479 qcrypto_builtin_cipher_encrypt(QCryptoCipher *cipher,
480                                const void *in,
481                                void *out,
482                                size_t len,
483                                Error **errp)
484 {
485     QCryptoCipherBuiltin *ctxt = cipher->opaque;
486
487     if (len % ctxt->blocksize) {
488         error_setg(errp, "Length %zu must be a multiple of block size %zu",
489                    len, ctxt->blocksize);
490         return -1;
491     }
492
493     return ctxt->encrypt(cipher, in, out, len, errp);
494 }
495
496
497 static int
498 qcrypto_builtin_cipher_decrypt(QCryptoCipher *cipher,
499                                const void *in,
500                                void *out,
501                                size_t len,
502                                Error **errp)
503 {
504     QCryptoCipherBuiltin *ctxt = cipher->opaque;
505
506     if (len % ctxt->blocksize) {
507         error_setg(errp, "Length %zu must be a multiple of block size %zu",
508                    len, ctxt->blocksize);
509         return -1;
510     }
511
512     return ctxt->decrypt(cipher, in, out, len, errp);
513 }
514
515
516 static int
517 qcrypto_builtin_cipher_setiv(QCryptoCipher *cipher,
518                              const uint8_t *iv, size_t niv,
519                              Error **errp)
520 {
521     QCryptoCipherBuiltin *ctxt = cipher->opaque;
522
523     return ctxt->setiv(cipher, iv, niv, errp);
524 }
525
526
527 static struct QCryptoCipherDriver qcrypto_cipher_lib_driver = {
528     .cipher_encrypt = qcrypto_builtin_cipher_encrypt,
529     .cipher_decrypt = qcrypto_builtin_cipher_decrypt,
530     .cipher_setiv = qcrypto_builtin_cipher_setiv,
531     .cipher_free = qcrypto_builtin_cipher_ctx_free,
532 };
This page took 0.055673 seconds and 4 git commands to generate.