2 * QEMU Crypto cipher built-in algorithms
4 * Copyright (c) 2015 Red Hat, Inc.
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.
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.
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/>.
21 #include "qemu/osdep.h"
22 #include "crypto/aes.h"
23 #include "crypto/desrfb.h"
25 typedef struct QCryptoCipherBuiltinAESContext QCryptoCipherBuiltinAESContext
;
26 struct QCryptoCipherBuiltinAESContext
{
30 typedef struct QCryptoCipherBuiltinAES QCryptoCipherBuiltinAES
;
31 struct QCryptoCipherBuiltinAES
{
32 QCryptoCipherBuiltinAESContext key
;
33 uint8_t iv
[AES_BLOCK_SIZE
];
35 typedef struct QCryptoCipherBuiltinDESRFB QCryptoCipherBuiltinDESRFB
;
36 struct QCryptoCipherBuiltinDESRFB
{
41 typedef struct QCryptoCipherBuiltin QCryptoCipherBuiltin
;
42 struct QCryptoCipherBuiltin
{
44 QCryptoCipherBuiltinAES aes
;
45 QCryptoCipherBuiltinDESRFB desrfb
;
48 void (*free
)(QCryptoCipher
*cipher
);
49 int (*setiv
)(QCryptoCipher
*cipher
,
50 const uint8_t *iv
, size_t niv
,
52 int (*encrypt
)(QCryptoCipher
*cipher
,
57 int (*decrypt
)(QCryptoCipher
*cipher
,
65 static void qcrypto_cipher_free_aes(QCryptoCipher
*cipher
)
67 QCryptoCipherBuiltin
*ctxt
= cipher
->opaque
;
70 cipher
->opaque
= NULL
;
74 static void qcrypto_cipher_aes_ecb_encrypt(AES_KEY
*key
,
79 const uint8_t *inptr
= in
;
80 uint8_t *outptr
= out
;
82 if (len
> AES_BLOCK_SIZE
) {
83 AES_encrypt(inptr
, outptr
, key
);
84 inptr
+= AES_BLOCK_SIZE
;
85 outptr
+= AES_BLOCK_SIZE
;
86 len
-= AES_BLOCK_SIZE
;
88 uint8_t tmp1
[AES_BLOCK_SIZE
], tmp2
[AES_BLOCK_SIZE
];
89 memcpy(tmp1
, inptr
, len
);
90 /* Fill with 0 to avoid valgrind uninitialized reads */
91 memset(tmp1
+ len
, 0, sizeof(tmp1
) - len
);
92 AES_encrypt(tmp1
, tmp2
, key
);
93 memcpy(outptr
, tmp2
, len
);
100 static void qcrypto_cipher_aes_ecb_decrypt(AES_KEY
*key
,
105 const uint8_t *inptr
= in
;
106 uint8_t *outptr
= out
;
108 if (len
> AES_BLOCK_SIZE
) {
109 AES_decrypt(inptr
, outptr
, key
);
110 inptr
+= AES_BLOCK_SIZE
;
111 outptr
+= AES_BLOCK_SIZE
;
112 len
-= AES_BLOCK_SIZE
;
114 uint8_t tmp1
[AES_BLOCK_SIZE
], tmp2
[AES_BLOCK_SIZE
];
115 memcpy(tmp1
, inptr
, len
);
116 /* Fill with 0 to avoid valgrind uninitialized reads */
117 memset(tmp1
+ len
, 0, sizeof(tmp1
) - len
);
118 AES_decrypt(tmp1
, tmp2
, key
);
119 memcpy(outptr
, tmp2
, len
);
126 static int qcrypto_cipher_encrypt_aes(QCryptoCipher
*cipher
,
132 QCryptoCipherBuiltin
*ctxt
= cipher
->opaque
;
134 switch (cipher
->mode
) {
135 case QCRYPTO_CIPHER_MODE_ECB
:
136 qcrypto_cipher_aes_ecb_encrypt(&ctxt
->state
.aes
.key
.enc
,
139 case QCRYPTO_CIPHER_MODE_CBC
:
140 AES_cbc_encrypt(in
, out
, len
,
141 &ctxt
->state
.aes
.key
.enc
,
142 ctxt
->state
.aes
.iv
, 1);
145 g_assert_not_reached();
152 static int qcrypto_cipher_decrypt_aes(QCryptoCipher
*cipher
,
158 QCryptoCipherBuiltin
*ctxt
= cipher
->opaque
;
160 switch (cipher
->mode
) {
161 case QCRYPTO_CIPHER_MODE_ECB
:
162 qcrypto_cipher_aes_ecb_decrypt(&ctxt
->state
.aes
.key
.dec
,
165 case QCRYPTO_CIPHER_MODE_CBC
:
166 AES_cbc_encrypt(in
, out
, len
,
167 &ctxt
->state
.aes
.key
.dec
,
168 ctxt
->state
.aes
.iv
, 0);
171 g_assert_not_reached();
177 static int qcrypto_cipher_setiv_aes(QCryptoCipher
*cipher
,
178 const uint8_t *iv
, size_t niv
,
181 QCryptoCipherBuiltin
*ctxt
= cipher
->opaque
;
182 if (niv
!= AES_BLOCK_SIZE
) {
183 error_setg(errp
, "IV must be %d bytes not %zu",
184 AES_BLOCK_SIZE
, niv
);
188 memcpy(ctxt
->state
.aes
.iv
, iv
, AES_BLOCK_SIZE
);
196 static int qcrypto_cipher_init_aes(QCryptoCipher
*cipher
,
197 const uint8_t *key
, size_t nkey
,
200 QCryptoCipherBuiltin
*ctxt
;
202 if (cipher
->mode
!= QCRYPTO_CIPHER_MODE_CBC
&&
203 cipher
->mode
!= QCRYPTO_CIPHER_MODE_ECB
) {
204 error_setg(errp
, "Unsupported cipher mode %d", cipher
->mode
);
208 ctxt
= g_new0(QCryptoCipherBuiltin
, 1);
210 if (AES_set_encrypt_key(key
, nkey
* 8, &ctxt
->state
.aes
.key
.enc
) != 0) {
211 error_setg(errp
, "Failed to set encryption key");
215 if (AES_set_decrypt_key(key
, nkey
* 8, &ctxt
->state
.aes
.key
.dec
) != 0) {
216 error_setg(errp
, "Failed to set decryption key");
220 ctxt
->blocksize
= AES_BLOCK_SIZE
;
221 ctxt
->free
= qcrypto_cipher_free_aes
;
222 ctxt
->setiv
= qcrypto_cipher_setiv_aes
;
223 ctxt
->encrypt
= qcrypto_cipher_encrypt_aes
;
224 ctxt
->decrypt
= qcrypto_cipher_decrypt_aes
;
226 cipher
->opaque
= ctxt
;
236 static void qcrypto_cipher_free_des_rfb(QCryptoCipher
*cipher
)
238 QCryptoCipherBuiltin
*ctxt
= cipher
->opaque
;
240 g_free(ctxt
->state
.desrfb
.key
);
242 cipher
->opaque
= NULL
;
246 static int qcrypto_cipher_encrypt_des_rfb(QCryptoCipher
*cipher
,
252 QCryptoCipherBuiltin
*ctxt
= cipher
->opaque
;
256 error_setg(errp
, "Buffer size must be multiple of 8 not %zu",
261 deskey(ctxt
->state
.desrfb
.key
, EN0
);
263 for (i
= 0; i
< len
; i
+= 8) {
264 des((void *)in
+ i
, out
+ i
);
271 static int qcrypto_cipher_decrypt_des_rfb(QCryptoCipher
*cipher
,
277 QCryptoCipherBuiltin
*ctxt
= cipher
->opaque
;
281 error_setg(errp
, "Buffer size must be multiple of 8 not %zu",
286 deskey(ctxt
->state
.desrfb
.key
, DE1
);
288 for (i
= 0; i
< len
; i
+= 8) {
289 des((void *)in
+ i
, out
+ i
);
296 static int qcrypto_cipher_setiv_des_rfb(QCryptoCipher
*cipher
,
297 const uint8_t *iv
, size_t niv
,
300 error_setg(errp
, "Setting IV is not supported");
305 static int qcrypto_cipher_init_des_rfb(QCryptoCipher
*cipher
,
306 const uint8_t *key
, size_t nkey
,
309 QCryptoCipherBuiltin
*ctxt
;
311 if (cipher
->mode
!= QCRYPTO_CIPHER_MODE_ECB
) {
312 error_setg(errp
, "Unsupported cipher mode %d", cipher
->mode
);
316 ctxt
= g_new0(QCryptoCipherBuiltin
, 1);
318 ctxt
->state
.desrfb
.key
= g_new0(uint8_t, nkey
);
319 memcpy(ctxt
->state
.desrfb
.key
, key
, nkey
);
320 ctxt
->state
.desrfb
.nkey
= nkey
;
323 ctxt
->free
= qcrypto_cipher_free_des_rfb
;
324 ctxt
->setiv
= qcrypto_cipher_setiv_des_rfb
;
325 ctxt
->encrypt
= qcrypto_cipher_encrypt_des_rfb
;
326 ctxt
->decrypt
= qcrypto_cipher_decrypt_des_rfb
;
328 cipher
->opaque
= ctxt
;
334 bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg
)
337 case QCRYPTO_CIPHER_ALG_DES_RFB
:
338 case QCRYPTO_CIPHER_ALG_AES_128
:
339 case QCRYPTO_CIPHER_ALG_AES_192
:
340 case QCRYPTO_CIPHER_ALG_AES_256
:
348 QCryptoCipher
*qcrypto_cipher_new(QCryptoCipherAlgorithm alg
,
349 QCryptoCipherMode mode
,
350 const uint8_t *key
, size_t nkey
,
353 QCryptoCipher
*cipher
;
355 cipher
= g_new0(QCryptoCipher
, 1);
359 if (!qcrypto_cipher_validate_key_length(alg
, nkey
, errp
)) {
363 switch (cipher
->alg
) {
364 case QCRYPTO_CIPHER_ALG_DES_RFB
:
365 if (qcrypto_cipher_init_des_rfb(cipher
, key
, nkey
, errp
) < 0) {
369 case QCRYPTO_CIPHER_ALG_AES_128
:
370 case QCRYPTO_CIPHER_ALG_AES_192
:
371 case QCRYPTO_CIPHER_ALG_AES_256
:
372 if (qcrypto_cipher_init_aes(cipher
, key
, nkey
, errp
) < 0) {
378 "Unsupported cipher algorithm %d", cipher
->alg
);
389 void qcrypto_cipher_free(QCryptoCipher
*cipher
)
391 QCryptoCipherBuiltin
*ctxt
;
397 ctxt
= cipher
->opaque
;
403 int qcrypto_cipher_encrypt(QCryptoCipher
*cipher
,
409 QCryptoCipherBuiltin
*ctxt
= cipher
->opaque
;
411 if (len
% ctxt
->blocksize
) {
412 error_setg(errp
, "Length %zu must be a multiple of block size %zu",
413 len
, ctxt
->blocksize
);
417 return ctxt
->encrypt(cipher
, in
, out
, len
, errp
);
421 int qcrypto_cipher_decrypt(QCryptoCipher
*cipher
,
427 QCryptoCipherBuiltin
*ctxt
= cipher
->opaque
;
429 if (len
% ctxt
->blocksize
) {
430 error_setg(errp
, "Length %zu must be a multiple of block size %zu",
431 len
, ctxt
->blocksize
);
435 return ctxt
->decrypt(cipher
, in
, out
, len
, errp
);
439 int qcrypto_cipher_setiv(QCryptoCipher
*cipher
,
440 const uint8_t *iv
, size_t niv
,
443 QCryptoCipherBuiltin
*ctxt
= cipher
->opaque
;
445 return ctxt
->setiv(cipher
, iv
, niv
, errp
);