These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / crypto / cipher-gcrypt.c
1 /*
2  * QEMU Crypto cipher libgcrypt 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/xts.h"
23
24 #include <gcrypt.h>
25
26
27 bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg)
28 {
29     switch (alg) {
30     case QCRYPTO_CIPHER_ALG_DES_RFB:
31     case QCRYPTO_CIPHER_ALG_AES_128:
32     case QCRYPTO_CIPHER_ALG_AES_192:
33     case QCRYPTO_CIPHER_ALG_AES_256:
34     case QCRYPTO_CIPHER_ALG_CAST5_128:
35     case QCRYPTO_CIPHER_ALG_SERPENT_128:
36     case QCRYPTO_CIPHER_ALG_SERPENT_192:
37     case QCRYPTO_CIPHER_ALG_SERPENT_256:
38     case QCRYPTO_CIPHER_ALG_TWOFISH_128:
39     case QCRYPTO_CIPHER_ALG_TWOFISH_256:
40         return true;
41     default:
42         return false;
43     }
44 }
45
46 typedef struct QCryptoCipherGcrypt QCryptoCipherGcrypt;
47 struct QCryptoCipherGcrypt {
48     gcry_cipher_hd_t handle;
49     gcry_cipher_hd_t tweakhandle;
50     size_t blocksize;
51     uint8_t *iv;
52 };
53
54 QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
55                                   QCryptoCipherMode mode,
56                                   const uint8_t *key, size_t nkey,
57                                   Error **errp)
58 {
59     QCryptoCipher *cipher;
60     QCryptoCipherGcrypt *ctx;
61     gcry_error_t err;
62     int gcryalg, gcrymode;
63
64     switch (mode) {
65     case QCRYPTO_CIPHER_MODE_ECB:
66     case QCRYPTO_CIPHER_MODE_XTS:
67         gcrymode = GCRY_CIPHER_MODE_ECB;
68         break;
69     case QCRYPTO_CIPHER_MODE_CBC:
70         gcrymode = GCRY_CIPHER_MODE_CBC;
71         break;
72     default:
73         error_setg(errp, "Unsupported cipher mode %d", mode);
74         return NULL;
75     }
76
77     if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) {
78         return NULL;
79     }
80
81     switch (alg) {
82     case QCRYPTO_CIPHER_ALG_DES_RFB:
83         gcryalg = GCRY_CIPHER_DES;
84         break;
85
86     case QCRYPTO_CIPHER_ALG_AES_128:
87         gcryalg = GCRY_CIPHER_AES128;
88         break;
89
90     case QCRYPTO_CIPHER_ALG_AES_192:
91         gcryalg = GCRY_CIPHER_AES192;
92         break;
93
94     case QCRYPTO_CIPHER_ALG_AES_256:
95         gcryalg = GCRY_CIPHER_AES256;
96         break;
97
98     case QCRYPTO_CIPHER_ALG_CAST5_128:
99         gcryalg = GCRY_CIPHER_CAST5;
100         break;
101
102     case QCRYPTO_CIPHER_ALG_SERPENT_128:
103         gcryalg = GCRY_CIPHER_SERPENT128;
104         break;
105
106     case QCRYPTO_CIPHER_ALG_SERPENT_192:
107         gcryalg = GCRY_CIPHER_SERPENT192;
108         break;
109
110     case QCRYPTO_CIPHER_ALG_SERPENT_256:
111         gcryalg = GCRY_CIPHER_SERPENT256;
112         break;
113
114     case QCRYPTO_CIPHER_ALG_TWOFISH_128:
115         gcryalg = GCRY_CIPHER_TWOFISH128;
116         break;
117
118     case QCRYPTO_CIPHER_ALG_TWOFISH_256:
119         gcryalg = GCRY_CIPHER_TWOFISH;
120         break;
121
122     default:
123         error_setg(errp, "Unsupported cipher algorithm %d", alg);
124         return NULL;
125     }
126
127     cipher = g_new0(QCryptoCipher, 1);
128     cipher->alg = alg;
129     cipher->mode = mode;
130
131     ctx = g_new0(QCryptoCipherGcrypt, 1);
132
133     err = gcry_cipher_open(&ctx->handle, gcryalg, gcrymode, 0);
134     if (err != 0) {
135         error_setg(errp, "Cannot initialize cipher: %s",
136                    gcry_strerror(err));
137         goto error;
138     }
139     if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
140         err = gcry_cipher_open(&ctx->tweakhandle, gcryalg, gcrymode, 0);
141         if (err != 0) {
142             error_setg(errp, "Cannot initialize cipher: %s",
143                        gcry_strerror(err));
144             goto error;
145         }
146     }
147
148     if (cipher->alg == QCRYPTO_CIPHER_ALG_DES_RFB) {
149         /* We're using standard DES cipher from gcrypt, so we need
150          * to munge the key so that the results are the same as the
151          * bizarre RFB variant of DES :-)
152          */
153         uint8_t *rfbkey = qcrypto_cipher_munge_des_rfb_key(key, nkey);
154         err = gcry_cipher_setkey(ctx->handle, rfbkey, nkey);
155         g_free(rfbkey);
156         ctx->blocksize = 8;
157     } else {
158         if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
159             nkey /= 2;
160             err = gcry_cipher_setkey(ctx->handle, key, nkey);
161             if (err != 0) {
162                 error_setg(errp, "Cannot set key: %s",
163                            gcry_strerror(err));
164                 goto error;
165             }
166             err = gcry_cipher_setkey(ctx->tweakhandle, key + nkey, nkey);
167         } else {
168             err = gcry_cipher_setkey(ctx->handle, key, nkey);
169         }
170         if (err != 0) {
171             error_setg(errp, "Cannot set key: %s",
172                        gcry_strerror(err));
173             goto error;
174         }
175         switch (cipher->alg) {
176         case QCRYPTO_CIPHER_ALG_AES_128:
177         case QCRYPTO_CIPHER_ALG_AES_192:
178         case QCRYPTO_CIPHER_ALG_AES_256:
179         case QCRYPTO_CIPHER_ALG_SERPENT_128:
180         case QCRYPTO_CIPHER_ALG_SERPENT_192:
181         case QCRYPTO_CIPHER_ALG_SERPENT_256:
182         case QCRYPTO_CIPHER_ALG_TWOFISH_128:
183         case QCRYPTO_CIPHER_ALG_TWOFISH_256:
184             ctx->blocksize = 16;
185             break;
186         case QCRYPTO_CIPHER_ALG_CAST5_128:
187             ctx->blocksize = 8;
188             break;
189         default:
190             g_assert_not_reached();
191         }
192     }
193
194     if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
195         ctx->iv = g_new0(uint8_t, ctx->blocksize);
196     }
197
198     cipher->opaque = ctx;
199     return cipher;
200
201  error:
202     gcry_cipher_close(ctx->handle);
203     if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
204         gcry_cipher_close(ctx->tweakhandle);
205     }
206     g_free(ctx);
207     g_free(cipher);
208     return NULL;
209 }
210
211
212 void qcrypto_cipher_free(QCryptoCipher *cipher)
213 {
214     QCryptoCipherGcrypt *ctx;
215     if (!cipher) {
216         return;
217     }
218     ctx = cipher->opaque;
219     gcry_cipher_close(ctx->handle);
220     if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
221         gcry_cipher_close(ctx->tweakhandle);
222     }
223     g_free(ctx->iv);
224     g_free(ctx);
225     g_free(cipher);
226 }
227
228
229 static void qcrypto_gcrypt_xts_encrypt(const void *ctx,
230                                        size_t length,
231                                        uint8_t *dst,
232                                        const uint8_t *src)
233 {
234     gcry_error_t err;
235     err = gcry_cipher_encrypt((gcry_cipher_hd_t)ctx, dst, length, src, length);
236     g_assert(err == 0);
237 }
238
239 static void qcrypto_gcrypt_xts_decrypt(const void *ctx,
240                                        size_t length,
241                                        uint8_t *dst,
242                                        const uint8_t *src)
243 {
244     gcry_error_t err;
245     err = gcry_cipher_decrypt((gcry_cipher_hd_t)ctx, dst, length, src, length);
246     g_assert(err == 0);
247 }
248
249 int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
250                            const void *in,
251                            void *out,
252                            size_t len,
253                            Error **errp)
254 {
255     QCryptoCipherGcrypt *ctx = cipher->opaque;
256     gcry_error_t err;
257
258     if (len % ctx->blocksize) {
259         error_setg(errp, "Length %zu must be a multiple of block size %zu",
260                    len, ctx->blocksize);
261         return -1;
262     }
263
264     if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
265         xts_encrypt(ctx->handle, ctx->tweakhandle,
266                     qcrypto_gcrypt_xts_encrypt,
267                     qcrypto_gcrypt_xts_decrypt,
268                     ctx->iv, len, out, in);
269     } else {
270         err = gcry_cipher_encrypt(ctx->handle,
271                                   out, len,
272                                   in, len);
273         if (err != 0) {
274             error_setg(errp, "Cannot encrypt data: %s",
275                        gcry_strerror(err));
276             return -1;
277         }
278     }
279
280     return 0;
281 }
282
283
284 int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
285                            const void *in,
286                            void *out,
287                            size_t len,
288                            Error **errp)
289 {
290     QCryptoCipherGcrypt *ctx = cipher->opaque;
291     gcry_error_t err;
292
293     if (len % ctx->blocksize) {
294         error_setg(errp, "Length %zu must be a multiple of block size %zu",
295                    len, ctx->blocksize);
296         return -1;
297     }
298
299     if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
300         xts_decrypt(ctx->handle, ctx->tweakhandle,
301                     qcrypto_gcrypt_xts_encrypt,
302                     qcrypto_gcrypt_xts_decrypt,
303                     ctx->iv, len, out, in);
304     } else {
305         err = gcry_cipher_decrypt(ctx->handle,
306                                   out, len,
307                                   in, len);
308         if (err != 0) {
309             error_setg(errp, "Cannot decrypt data: %s",
310                        gcry_strerror(err));
311             return -1;
312         }
313     }
314
315     return 0;
316 }
317
318 int qcrypto_cipher_setiv(QCryptoCipher *cipher,
319                          const uint8_t *iv, size_t niv,
320                          Error **errp)
321 {
322     QCryptoCipherGcrypt *ctx = cipher->opaque;
323     gcry_error_t err;
324
325     if (niv != ctx->blocksize) {
326         error_setg(errp, "Expected IV size %zu not %zu",
327                    ctx->blocksize, niv);
328         return -1;
329     }
330
331     if (ctx->iv) {
332         memcpy(ctx->iv, iv, niv);
333     } else {
334         gcry_cipher_reset(ctx->handle);
335         err = gcry_cipher_setiv(ctx->handle, iv, niv);
336         if (err != 0) {
337             error_setg(errp, "Cannot set IV: %s",
338                    gcry_strerror(err));
339             return -1;
340         }
341     }
342
343     return 0;
344 }