]> git.proxmox.com Git - mirror_qemu.git/blame - crypto/cipher-nettle.c
crypto: add support for the serpent cipher algorithm
[mirror_qemu.git] / crypto / cipher-nettle.c
CommitLineData
ed754746
DB
1/*
2 * QEMU Crypto cipher nettle 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
42f7a448 21#include "qemu/osdep.h"
ed754746
DB
22#include <nettle/nettle-types.h>
23#include <nettle/aes.h>
24#include <nettle/des.h>
25#include <nettle/cbc.h>
084a85ee 26#include <nettle/cast128.h>
94318522 27#include <nettle/serpent.h>
ed754746 28
becaeb72
RK
29#if CONFIG_NETTLE_VERSION_MAJOR < 3
30typedef nettle_crypt_func nettle_cipher_func;
d3462e37
RK
31
32typedef void * cipher_ctx_t;
33typedef unsigned cipher_length_t;
34#else
35typedef const void * cipher_ctx_t;
36typedef size_t cipher_length_t;
becaeb72
RK
37#endif
38
d3462e37
RK
39static nettle_cipher_func aes_encrypt_wrapper;
40static nettle_cipher_func aes_decrypt_wrapper;
41static nettle_cipher_func des_encrypt_wrapper;
42static nettle_cipher_func des_decrypt_wrapper;
43
44static void aes_encrypt_wrapper(cipher_ctx_t ctx, cipher_length_t length,
45 uint8_t *dst, const uint8_t *src)
46{
47 aes_encrypt(ctx, length, dst, src);
48}
49
50static void aes_decrypt_wrapper(cipher_ctx_t ctx, cipher_length_t length,
51 uint8_t *dst, const uint8_t *src)
52{
bd095946 53 aes_decrypt(ctx, length, dst, src);
d3462e37
RK
54}
55
56static void des_encrypt_wrapper(cipher_ctx_t ctx, cipher_length_t length,
57 uint8_t *dst, const uint8_t *src)
58{
59 des_encrypt(ctx, length, dst, src);
60}
61
62static void des_decrypt_wrapper(cipher_ctx_t ctx, cipher_length_t length,
63 uint8_t *dst, const uint8_t *src)
64{
65 des_decrypt(ctx, length, dst, src);
66}
67
084a85ee
DB
68static void cast128_encrypt_wrapper(cipher_ctx_t ctx, cipher_length_t length,
69 uint8_t *dst, const uint8_t *src)
70{
71 cast128_encrypt(ctx, length, dst, src);
72}
73
74static void cast128_decrypt_wrapper(cipher_ctx_t ctx, cipher_length_t length,
75 uint8_t *dst, const uint8_t *src)
76{
77 cast128_decrypt(ctx, length, dst, src);
78}
79
94318522
DB
80static void serpent_encrypt_wrapper(cipher_ctx_t ctx, cipher_length_t length,
81 uint8_t *dst, const uint8_t *src)
82{
83 serpent_encrypt(ctx, length, dst, src);
84}
85
86static void serpent_decrypt_wrapper(cipher_ctx_t ctx, cipher_length_t length,
87 uint8_t *dst, const uint8_t *src)
88{
89 serpent_decrypt(ctx, length, dst, src);
90}
91
ed754746
DB
92typedef struct QCryptoCipherNettle QCryptoCipherNettle;
93struct QCryptoCipherNettle {
94 void *ctx_encrypt;
95 void *ctx_decrypt;
becaeb72
RK
96 nettle_cipher_func *alg_encrypt;
97 nettle_cipher_func *alg_decrypt;
ed754746 98 uint8_t *iv;
3a661f1e 99 size_t blocksize;
ed754746
DB
100};
101
102bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg)
103{
104 switch (alg) {
105 case QCRYPTO_CIPHER_ALG_DES_RFB:
106 case QCRYPTO_CIPHER_ALG_AES_128:
107 case QCRYPTO_CIPHER_ALG_AES_192:
108 case QCRYPTO_CIPHER_ALG_AES_256:
084a85ee 109 case QCRYPTO_CIPHER_ALG_CAST5_128:
94318522
DB
110 case QCRYPTO_CIPHER_ALG_SERPENT_128:
111 case QCRYPTO_CIPHER_ALG_SERPENT_192:
112 case QCRYPTO_CIPHER_ALG_SERPENT_256:
ed754746
DB
113 return true;
114 default:
115 return false;
116 }
117}
118
119
120QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
121 QCryptoCipherMode mode,
122 const uint8_t *key, size_t nkey,
123 Error **errp)
124{
125 QCryptoCipher *cipher;
126 QCryptoCipherNettle *ctx;
127 uint8_t *rfbkey;
128
129 switch (mode) {
130 case QCRYPTO_CIPHER_MODE_ECB:
131 case QCRYPTO_CIPHER_MODE_CBC:
132 break;
133 default:
134 error_setg(errp, "Unsupported cipher mode %d", mode);
135 return NULL;
136 }
137
138 if (!qcrypto_cipher_validate_key_length(alg, nkey, errp)) {
139 return NULL;
140 }
141
142 cipher = g_new0(QCryptoCipher, 1);
143 cipher->alg = alg;
144 cipher->mode = mode;
145
146 ctx = g_new0(QCryptoCipherNettle, 1);
147
148 switch (alg) {
149 case QCRYPTO_CIPHER_ALG_DES_RFB:
150 ctx->ctx_encrypt = g_new0(struct des_ctx, 1);
151 ctx->ctx_decrypt = NULL; /* 1 ctx can do both */
152 rfbkey = qcrypto_cipher_munge_des_rfb_key(key, nkey);
153 des_set_key(ctx->ctx_encrypt, rfbkey);
154 g_free(rfbkey);
155
d3462e37
RK
156 ctx->alg_encrypt = des_encrypt_wrapper;
157 ctx->alg_decrypt = des_decrypt_wrapper;
ed754746 158
3a661f1e 159 ctx->blocksize = DES_BLOCK_SIZE;
ed754746
DB
160 break;
161
162 case QCRYPTO_CIPHER_ALG_AES_128:
163 case QCRYPTO_CIPHER_ALG_AES_192:
164 case QCRYPTO_CIPHER_ALG_AES_256:
165 ctx->ctx_encrypt = g_new0(struct aes_ctx, 1);
166 ctx->ctx_decrypt = g_new0(struct aes_ctx, 1);
167
168 aes_set_encrypt_key(ctx->ctx_encrypt, nkey, key);
169 aes_set_decrypt_key(ctx->ctx_decrypt, nkey, key);
170
d3462e37
RK
171 ctx->alg_encrypt = aes_encrypt_wrapper;
172 ctx->alg_decrypt = aes_decrypt_wrapper;
ed754746 173
3a661f1e 174 ctx->blocksize = AES_BLOCK_SIZE;
ed754746 175 break;
084a85ee
DB
176
177 case QCRYPTO_CIPHER_ALG_CAST5_128:
178 ctx->ctx_encrypt = g_new0(struct cast128_ctx, 1);
179 ctx->ctx_decrypt = NULL; /* 1 ctx can do both */
180
181 cast5_set_key(ctx->ctx_encrypt, nkey, key);
182
183 ctx->alg_encrypt = cast128_encrypt_wrapper;
184 ctx->alg_decrypt = cast128_decrypt_wrapper;
185
186 ctx->blocksize = CAST128_BLOCK_SIZE;
187 break;
94318522
DB
188
189 case QCRYPTO_CIPHER_ALG_SERPENT_128:
190 case QCRYPTO_CIPHER_ALG_SERPENT_192:
191 case QCRYPTO_CIPHER_ALG_SERPENT_256:
192 ctx->ctx_encrypt = g_new0(struct serpent_ctx, 1);
193 ctx->ctx_decrypt = NULL; /* 1 ctx can do both */
194
195 serpent_set_key(ctx->ctx_encrypt, nkey, key);
196
197 ctx->alg_encrypt = serpent_encrypt_wrapper;
198 ctx->alg_decrypt = serpent_decrypt_wrapper;
199
200 ctx->blocksize = SERPENT_BLOCK_SIZE;
201 break;
202
ed754746
DB
203 default:
204 error_setg(errp, "Unsupported cipher algorithm %d", alg);
205 goto error;
206 }
207
3a661f1e 208 ctx->iv = g_new0(uint8_t, ctx->blocksize);
ed754746
DB
209 cipher->opaque = ctx;
210
211 return cipher;
212
213 error:
214 g_free(cipher);
215 g_free(ctx);
216 return NULL;
217}
218
219
220void qcrypto_cipher_free(QCryptoCipher *cipher)
221{
222 QCryptoCipherNettle *ctx;
223
224 if (!cipher) {
225 return;
226 }
227
228 ctx = cipher->opaque;
229 g_free(ctx->iv);
230 g_free(ctx->ctx_encrypt);
231 g_free(ctx->ctx_decrypt);
232 g_free(ctx);
233 g_free(cipher);
234}
235
236
237int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
238 const void *in,
239 void *out,
240 size_t len,
241 Error **errp)
242{
243 QCryptoCipherNettle *ctx = cipher->opaque;
244
3a661f1e
DB
245 if (len % ctx->blocksize) {
246 error_setg(errp, "Length %zu must be a multiple of block size %zu",
247 len, ctx->blocksize);
248 return -1;
249 }
250
ed754746
DB
251 switch (cipher->mode) {
252 case QCRYPTO_CIPHER_MODE_ECB:
253 ctx->alg_encrypt(ctx->ctx_encrypt, len, out, in);
254 break;
255
256 case QCRYPTO_CIPHER_MODE_CBC:
257 cbc_encrypt(ctx->ctx_encrypt, ctx->alg_encrypt,
3a661f1e 258 ctx->blocksize, ctx->iv,
ed754746
DB
259 len, out, in);
260 break;
261 default:
262 error_setg(errp, "Unsupported cipher algorithm %d",
263 cipher->alg);
264 return -1;
265 }
266 return 0;
267}
268
269
270int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
271 const void *in,
272 void *out,
273 size_t len,
274 Error **errp)
275{
276 QCryptoCipherNettle *ctx = cipher->opaque;
277
3a661f1e
DB
278 if (len % ctx->blocksize) {
279 error_setg(errp, "Length %zu must be a multiple of block size %zu",
280 len, ctx->blocksize);
281 return -1;
282 }
283
ed754746
DB
284 switch (cipher->mode) {
285 case QCRYPTO_CIPHER_MODE_ECB:
286 ctx->alg_decrypt(ctx->ctx_decrypt ? ctx->ctx_decrypt : ctx->ctx_encrypt,
287 len, out, in);
288 break;
289
290 case QCRYPTO_CIPHER_MODE_CBC:
291 cbc_decrypt(ctx->ctx_decrypt ? ctx->ctx_decrypt : ctx->ctx_encrypt,
3a661f1e 292 ctx->alg_decrypt, ctx->blocksize, ctx->iv,
ed754746
DB
293 len, out, in);
294 break;
295 default:
296 error_setg(errp, "Unsupported cipher algorithm %d",
297 cipher->alg);
298 return -1;
299 }
300 return 0;
301}
302
303int qcrypto_cipher_setiv(QCryptoCipher *cipher,
304 const uint8_t *iv, size_t niv,
305 Error **errp)
306{
307 QCryptoCipherNettle *ctx = cipher->opaque;
3a661f1e 308 if (niv != ctx->blocksize) {
ed754746 309 error_setg(errp, "Expected IV size %zu not %zu",
3a661f1e 310 ctx->blocksize, niv);
ed754746
DB
311 return -1;
312 }
313 memcpy(ctx->iv, iv, niv);
314 return 0;
315}