target/mips: Prefer fast cpu_env() over slower CPU QOM cast macro
[qemu/ar7.git] / crypto / cipher-gcrypt.c.inc
blob1377cbaf147a019e4b0a6899cb14d5046c15ef2c
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.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  */
21 #include <gcrypt.h>
23 bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
24                              QCryptoCipherMode mode)
26     switch (alg) {
27     case QCRYPTO_CIPHER_ALG_DES:
28     case QCRYPTO_CIPHER_ALG_3DES:
29     case QCRYPTO_CIPHER_ALG_AES_128:
30     case QCRYPTO_CIPHER_ALG_AES_192:
31     case QCRYPTO_CIPHER_ALG_AES_256:
32     case QCRYPTO_CIPHER_ALG_CAST5_128:
33     case QCRYPTO_CIPHER_ALG_SERPENT_128:
34     case QCRYPTO_CIPHER_ALG_SERPENT_192:
35     case QCRYPTO_CIPHER_ALG_SERPENT_256:
36     case QCRYPTO_CIPHER_ALG_TWOFISH_128:
37     case QCRYPTO_CIPHER_ALG_TWOFISH_256:
38 #ifdef CONFIG_CRYPTO_SM4
39     case QCRYPTO_CIPHER_ALG_SM4:
40 #endif
41         break;
42     default:
43         return false;
44     }
46     switch (mode) {
47     case QCRYPTO_CIPHER_MODE_ECB:
48     case QCRYPTO_CIPHER_MODE_CBC:
49     case QCRYPTO_CIPHER_MODE_XTS:
50     case QCRYPTO_CIPHER_MODE_CTR:
51         return true;
52     default:
53         return false;
54     }
57 typedef struct QCryptoCipherGcrypt {
58     QCryptoCipher base;
59     gcry_cipher_hd_t handle;
60     size_t blocksize;
61 } QCryptoCipherGcrypt;
64 static void qcrypto_gcrypt_ctx_free(QCryptoCipher *cipher)
66     QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
68     gcry_cipher_close(ctx->handle);
69     g_free(ctx);
72 static int qcrypto_gcrypt_encrypt(QCryptoCipher *cipher, const void *in,
73                                   void *out, size_t len, Error **errp)
75     QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
76     gcry_error_t err;
78     if (len & (ctx->blocksize - 1)) {
79         error_setg(errp, "Length %zu must be a multiple of block size %zu",
80                    len, ctx->blocksize);
81         return -1;
82     }
84     err = gcry_cipher_encrypt(ctx->handle, out, len, in, len);
85     if (err != 0) {
86         error_setg(errp, "Cannot encrypt data: %s", gcry_strerror(err));
87         return -1;
88     }
90     return 0;
94 static int qcrypto_gcrypt_decrypt(QCryptoCipher *cipher, const void *in,
95                                   void *out, size_t len, Error **errp)
97     QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
98     gcry_error_t err;
100     if (len & (ctx->blocksize - 1)) {
101         error_setg(errp, "Length %zu must be a multiple of block size %zu",
102                    len, ctx->blocksize);
103         return -1;
104     }
106     err = gcry_cipher_decrypt(ctx->handle, out, len, in, len);
107     if (err != 0) {
108         error_setg(errp, "Cannot decrypt data: %s",
109                    gcry_strerror(err));
110         return -1;
111     }
113     return 0;
116 static int qcrypto_gcrypt_setiv(QCryptoCipher *cipher,
117                                 const uint8_t *iv, size_t niv,
118                                 Error **errp)
120     QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
121     gcry_error_t err;
123     if (niv != ctx->blocksize) {
124         error_setg(errp, "Expected IV size %zu not %zu",
125                    ctx->blocksize, niv);
126         return -1;
127     }
129     gcry_cipher_reset(ctx->handle);
130     err = gcry_cipher_setiv(ctx->handle, iv, niv);
131     if (err != 0) {
132         error_setg(errp, "Cannot set IV: %s", gcry_strerror(err));
133         return -1;
134     }
136     return 0;
139 static int qcrypto_gcrypt_ctr_setiv(QCryptoCipher *cipher,
140                                     const uint8_t *iv, size_t niv,
141                                     Error **errp)
143     QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
144     gcry_error_t err;
146     if (niv != ctx->blocksize) {
147         error_setg(errp, "Expected IV size %zu not %zu",
148                    ctx->blocksize, niv);
149         return -1;
150     }
152     err = gcry_cipher_setctr(ctx->handle, iv, niv);
153     if (err != 0) {
154         error_setg(errp, "Cannot set Counter: %s", gcry_strerror(err));
155         return -1;
156     }
158     return 0;
162 static const struct QCryptoCipherDriver qcrypto_gcrypt_driver = {
163     .cipher_encrypt = qcrypto_gcrypt_encrypt,
164     .cipher_decrypt = qcrypto_gcrypt_decrypt,
165     .cipher_setiv = qcrypto_gcrypt_setiv,
166     .cipher_free = qcrypto_gcrypt_ctx_free,
169 static const struct QCryptoCipherDriver qcrypto_gcrypt_ctr_driver = {
170     .cipher_encrypt = qcrypto_gcrypt_encrypt,
171     .cipher_decrypt = qcrypto_gcrypt_decrypt,
172     .cipher_setiv = qcrypto_gcrypt_ctr_setiv,
173     .cipher_free = qcrypto_gcrypt_ctx_free,
176 static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
177                                              QCryptoCipherMode mode,
178                                              const uint8_t *key,
179                                              size_t nkey,
180                                              Error **errp)
182     QCryptoCipherGcrypt *ctx;
183     const QCryptoCipherDriver *drv;
184     gcry_error_t err;
185     int gcryalg, gcrymode;
187     if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) {
188         return NULL;
189     }
191     switch (alg) {
192     case QCRYPTO_CIPHER_ALG_DES:
193         gcryalg = GCRY_CIPHER_DES;
194         break;
195     case QCRYPTO_CIPHER_ALG_3DES:
196         gcryalg = GCRY_CIPHER_3DES;
197         break;
198     case QCRYPTO_CIPHER_ALG_AES_128:
199         gcryalg = GCRY_CIPHER_AES128;
200         break;
201     case QCRYPTO_CIPHER_ALG_AES_192:
202         gcryalg = GCRY_CIPHER_AES192;
203         break;
204     case QCRYPTO_CIPHER_ALG_AES_256:
205         gcryalg = GCRY_CIPHER_AES256;
206         break;
207     case QCRYPTO_CIPHER_ALG_CAST5_128:
208         gcryalg = GCRY_CIPHER_CAST5;
209         break;
210     case QCRYPTO_CIPHER_ALG_SERPENT_128:
211         gcryalg = GCRY_CIPHER_SERPENT128;
212         break;
213     case QCRYPTO_CIPHER_ALG_SERPENT_192:
214         gcryalg = GCRY_CIPHER_SERPENT192;
215         break;
216     case QCRYPTO_CIPHER_ALG_SERPENT_256:
217         gcryalg = GCRY_CIPHER_SERPENT256;
218         break;
219     case QCRYPTO_CIPHER_ALG_TWOFISH_128:
220         gcryalg = GCRY_CIPHER_TWOFISH128;
221         break;
222     case QCRYPTO_CIPHER_ALG_TWOFISH_256:
223         gcryalg = GCRY_CIPHER_TWOFISH;
224         break;
225 #ifdef CONFIG_CRYPTO_SM4
226     case QCRYPTO_CIPHER_ALG_SM4:
227         gcryalg = GCRY_CIPHER_SM4;
228         break;
229 #endif
230     default:
231         error_setg(errp, "Unsupported cipher algorithm %s",
232                    QCryptoCipherAlgorithm_str(alg));
233         return NULL;
234     }
236     drv = &qcrypto_gcrypt_driver;
237     switch (mode) {
238     case QCRYPTO_CIPHER_MODE_ECB:
239         gcrymode = GCRY_CIPHER_MODE_ECB;
240         break;
241     case QCRYPTO_CIPHER_MODE_XTS:
242         gcrymode = GCRY_CIPHER_MODE_XTS;
243         break;
244     case QCRYPTO_CIPHER_MODE_CBC:
245         gcrymode = GCRY_CIPHER_MODE_CBC;
246         break;
247     case QCRYPTO_CIPHER_MODE_CTR:
248         drv = &qcrypto_gcrypt_ctr_driver;
249         gcrymode = GCRY_CIPHER_MODE_CTR;
250         break;
251     default:
252         error_setg(errp, "Unsupported cipher mode %s",
253                    QCryptoCipherMode_str(mode));
254         return NULL;
255     }
257     ctx = g_new0(QCryptoCipherGcrypt, 1);
258     ctx->base.driver = drv;
260     err = gcry_cipher_open(&ctx->handle, gcryalg, gcrymode, 0);
261     if (err != 0) {
262         error_setg(errp, "Cannot initialize cipher: %s",
263                    gcry_strerror(err));
264         goto error;
265     }
266     ctx->blocksize = gcry_cipher_get_algo_blklen(gcryalg);
268     err = gcry_cipher_setkey(ctx->handle, key, nkey);
269     if (err != 0) {
270         error_setg(errp, "Cannot set key: %s", gcry_strerror(err));
271         goto error;
272     }
274     return &ctx->base;
276  error:
277     gcry_cipher_close(ctx->handle);
278     g_free(ctx);
279     return NULL;