Merge tag 'v9.0.0-rc3'
[qemu/ar7.git] / crypto / cipher-gcrypt.c.inc
blob4a8314746dbbfb6d602bef8510a79efafdde4000
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 static int qcrypto_cipher_alg_to_gcry_alg(QCryptoCipherAlgorithm alg)
25     switch (alg) {
26     case QCRYPTO_CIPHER_ALG_DES:
27         return GCRY_CIPHER_DES;
28     case QCRYPTO_CIPHER_ALG_3DES:
29         return GCRY_CIPHER_3DES;
30     case QCRYPTO_CIPHER_ALG_AES_128:
31         return GCRY_CIPHER_AES128;
32     case QCRYPTO_CIPHER_ALG_AES_192:
33         return GCRY_CIPHER_AES192;
34     case QCRYPTO_CIPHER_ALG_AES_256:
35         return GCRY_CIPHER_AES256;
36     case QCRYPTO_CIPHER_ALG_CAST5_128:
37         return GCRY_CIPHER_CAST5;
38     case QCRYPTO_CIPHER_ALG_SERPENT_128:
39         return GCRY_CIPHER_SERPENT128;
40     case QCRYPTO_CIPHER_ALG_SERPENT_192:
41         return GCRY_CIPHER_SERPENT192;
42     case QCRYPTO_CIPHER_ALG_SERPENT_256:
43         return GCRY_CIPHER_SERPENT256;
44     case QCRYPTO_CIPHER_ALG_TWOFISH_128:
45         return GCRY_CIPHER_TWOFISH128;
46     case QCRYPTO_CIPHER_ALG_TWOFISH_256:
47         return GCRY_CIPHER_TWOFISH;
48 #ifdef CONFIG_CRYPTO_SM4
49     case QCRYPTO_CIPHER_ALG_SM4:
50         return GCRY_CIPHER_SM4;
51 #endif
52     default:
53         return GCRY_CIPHER_NONE;
54     }
57 static int qcrypto_cipher_mode_to_gcry_mode(QCryptoCipherMode mode)
59     switch (mode) {
60     case QCRYPTO_CIPHER_MODE_ECB:
61         return GCRY_CIPHER_MODE_ECB;
62     case QCRYPTO_CIPHER_MODE_XTS:
63         return GCRY_CIPHER_MODE_XTS;
64     case QCRYPTO_CIPHER_MODE_CBC:
65         return GCRY_CIPHER_MODE_CBC;
66     case QCRYPTO_CIPHER_MODE_CTR:
67         return GCRY_CIPHER_MODE_CTR;
68     default:
69         return GCRY_CIPHER_MODE_NONE;
70     }
73 bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
74                              QCryptoCipherMode mode)
76     switch (alg) {
77     case QCRYPTO_CIPHER_ALG_DES:
78     case QCRYPTO_CIPHER_ALG_3DES:
79     case QCRYPTO_CIPHER_ALG_AES_128:
80     case QCRYPTO_CIPHER_ALG_AES_192:
81     case QCRYPTO_CIPHER_ALG_AES_256:
82     case QCRYPTO_CIPHER_ALG_CAST5_128:
83     case QCRYPTO_CIPHER_ALG_SERPENT_128:
84     case QCRYPTO_CIPHER_ALG_SERPENT_192:
85     case QCRYPTO_CIPHER_ALG_SERPENT_256:
86     case QCRYPTO_CIPHER_ALG_TWOFISH_128:
87     case QCRYPTO_CIPHER_ALG_TWOFISH_256:
88 #ifdef CONFIG_CRYPTO_SM4
89     case QCRYPTO_CIPHER_ALG_SM4:
90 #endif
91         break;
92     default:
93         return false;
94     }
96     if (gcry_cipher_algo_info(qcrypto_cipher_alg_to_gcry_alg(alg),
97                               GCRYCTL_TEST_ALGO, NULL, NULL) != 0) {
98         return false;
99     }
101     switch (mode) {
102     case QCRYPTO_CIPHER_MODE_ECB:
103     case QCRYPTO_CIPHER_MODE_CBC:
104     case QCRYPTO_CIPHER_MODE_XTS:
105     case QCRYPTO_CIPHER_MODE_CTR:
106         return true;
107     default:
108         return false;
109     }
112 typedef struct QCryptoCipherGcrypt {
113     QCryptoCipher base;
114     gcry_cipher_hd_t handle;
115     size_t blocksize;
116 } QCryptoCipherGcrypt;
119 static void qcrypto_gcrypt_ctx_free(QCryptoCipher *cipher)
121     QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
123     gcry_cipher_close(ctx->handle);
124     g_free(ctx);
127 static int qcrypto_gcrypt_encrypt(QCryptoCipher *cipher, const void *in,
128                                   void *out, size_t len, Error **errp)
130     QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
131     gcry_error_t err;
133     if (len & (ctx->blocksize - 1)) {
134         error_setg(errp, "Length %zu must be a multiple of block size %zu",
135                    len, ctx->blocksize);
136         return -1;
137     }
139     err = gcry_cipher_encrypt(ctx->handle, out, len, in, len);
140     if (err != 0) {
141         error_setg(errp, "Cannot encrypt data: %s", gcry_strerror(err));
142         return -1;
143     }
145     return 0;
149 static int qcrypto_gcrypt_decrypt(QCryptoCipher *cipher, const void *in,
150                                   void *out, size_t len, Error **errp)
152     QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
153     gcry_error_t err;
155     if (len & (ctx->blocksize - 1)) {
156         error_setg(errp, "Length %zu must be a multiple of block size %zu",
157                    len, ctx->blocksize);
158         return -1;
159     }
161     err = gcry_cipher_decrypt(ctx->handle, out, len, in, len);
162     if (err != 0) {
163         error_setg(errp, "Cannot decrypt data: %s",
164                    gcry_strerror(err));
165         return -1;
166     }
168     return 0;
171 static int qcrypto_gcrypt_setiv(QCryptoCipher *cipher,
172                                 const uint8_t *iv, size_t niv,
173                                 Error **errp)
175     QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
176     gcry_error_t err;
178     if (niv != ctx->blocksize) {
179         error_setg(errp, "Expected IV size %zu not %zu",
180                    ctx->blocksize, niv);
181         return -1;
182     }
184     gcry_cipher_reset(ctx->handle);
185     err = gcry_cipher_setiv(ctx->handle, iv, niv);
186     if (err != 0) {
187         error_setg(errp, "Cannot set IV: %s", gcry_strerror(err));
188         return -1;
189     }
191     return 0;
194 static int qcrypto_gcrypt_ctr_setiv(QCryptoCipher *cipher,
195                                     const uint8_t *iv, size_t niv,
196                                     Error **errp)
198     QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
199     gcry_error_t err;
201     if (niv != ctx->blocksize) {
202         error_setg(errp, "Expected IV size %zu not %zu",
203                    ctx->blocksize, niv);
204         return -1;
205     }
207     err = gcry_cipher_setctr(ctx->handle, iv, niv);
208     if (err != 0) {
209         error_setg(errp, "Cannot set Counter: %s", gcry_strerror(err));
210         return -1;
211     }
213     return 0;
217 static const struct QCryptoCipherDriver qcrypto_gcrypt_driver = {
218     .cipher_encrypt = qcrypto_gcrypt_encrypt,
219     .cipher_decrypt = qcrypto_gcrypt_decrypt,
220     .cipher_setiv = qcrypto_gcrypt_setiv,
221     .cipher_free = qcrypto_gcrypt_ctx_free,
224 static const struct QCryptoCipherDriver qcrypto_gcrypt_ctr_driver = {
225     .cipher_encrypt = qcrypto_gcrypt_encrypt,
226     .cipher_decrypt = qcrypto_gcrypt_decrypt,
227     .cipher_setiv = qcrypto_gcrypt_ctr_setiv,
228     .cipher_free = qcrypto_gcrypt_ctx_free,
231 static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
232                                              QCryptoCipherMode mode,
233                                              const uint8_t *key,
234                                              size_t nkey,
235                                              Error **errp)
237     QCryptoCipherGcrypt *ctx;
238     const QCryptoCipherDriver *drv;
239     gcry_error_t err;
240     int gcryalg, gcrymode;
242     if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) {
243         return NULL;
244     }
246     gcryalg = qcrypto_cipher_alg_to_gcry_alg(alg);
247     if (gcryalg == GCRY_CIPHER_NONE) {
248         error_setg(errp, "Unsupported cipher algorithm %s",
249                    QCryptoCipherAlgorithm_str(alg));
250         return NULL;
251     }
253     gcrymode = qcrypto_cipher_mode_to_gcry_mode(mode);
254     if (gcrymode == GCRY_CIPHER_MODE_NONE) {
255         error_setg(errp, "Unsupported cipher mode %s",
256                    QCryptoCipherMode_str(mode));
257         return NULL;
258     }
260     if (mode == QCRYPTO_CIPHER_MODE_CTR) {
261         drv = &qcrypto_gcrypt_ctr_driver;
262     } else {
263         drv = &qcrypto_gcrypt_driver;
264     }
266     ctx = g_new0(QCryptoCipherGcrypt, 1);
267     ctx->base.driver = drv;
269     err = gcry_cipher_open(&ctx->handle, gcryalg, gcrymode, 0);
270     if (err != 0) {
271         error_setg(errp, "Cannot initialize cipher: %s",
272                    gcry_strerror(err));
273         goto error;
274     }
275     ctx->blocksize = gcry_cipher_get_algo_blklen(gcryalg);
277     err = gcry_cipher_setkey(ctx->handle, key, nkey);
278     if (err != 0) {
279         error_setg(errp, "Cannot set key: %s", gcry_strerror(err));
280         goto error;
281     }
283     return &ctx->base;
285  error:
286     gcry_cipher_close(ctx->handle);
287     g_free(ctx);
288     return NULL;