]> Git Repo - qemu.git/blob - crypto/cipher-builtin.c
Merge remote-tracking branch 'remotes/rth/tags/pull-tile-20151030' into staging
[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 }
This page took 0.050783 seconds and 4 git commands to generate.