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 */ 20 21#ifdef CONFIG_QEMU_PRIVATE_XTS 22#include "crypto/xts.h" 23#endif 24 25#include <gcrypt.h> 26 27bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, 28 QCryptoCipherMode mode) 29{ 30 switch (alg) { 31 case QCRYPTO_CIPHER_ALG_DES_RFB: 32 case QCRYPTO_CIPHER_ALG_3DES: 33 case QCRYPTO_CIPHER_ALG_AES_128: 34 case QCRYPTO_CIPHER_ALG_AES_192: 35 case QCRYPTO_CIPHER_ALG_AES_256: 36 case QCRYPTO_CIPHER_ALG_CAST5_128: 37 case QCRYPTO_CIPHER_ALG_SERPENT_128: 38 case QCRYPTO_CIPHER_ALG_SERPENT_192: 39 case QCRYPTO_CIPHER_ALG_SERPENT_256: 40 case QCRYPTO_CIPHER_ALG_TWOFISH_128: 41 case QCRYPTO_CIPHER_ALG_TWOFISH_256: 42 break; 43 default: 44 return false; 45 } 46 47 switch (mode) { 48 case QCRYPTO_CIPHER_MODE_ECB: 49 case QCRYPTO_CIPHER_MODE_CBC: 50 case QCRYPTO_CIPHER_MODE_XTS: 51 case QCRYPTO_CIPHER_MODE_CTR: 52 return true; 53 default: 54 return false; 55 } 56} 57 58typedef struct QCryptoCipherGcrypt { 59 QCryptoCipher base; 60 gcry_cipher_hd_t handle; 61 size_t blocksize; 62#ifdef CONFIG_QEMU_PRIVATE_XTS 63 gcry_cipher_hd_t tweakhandle; 64 uint8_t iv[XTS_BLOCK_SIZE]; 65#endif 66} QCryptoCipherGcrypt; 67 68 69static void qcrypto_gcrypt_ctx_free(QCryptoCipher *cipher) 70{ 71 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base); 72 73 gcry_cipher_close(ctx->handle); 74 g_free(ctx); 75} 76 77static int qcrypto_gcrypt_encrypt(QCryptoCipher *cipher, const void *in, 78 void *out, size_t len, Error **errp) 79{ 80 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base); 81 gcry_error_t err; 82 83 if (len & (ctx->blocksize - 1)) { 84 error_setg(errp, "Length %zu must be a multiple of block size %zu", 85 len, ctx->blocksize); 86 return -1; 87 } 88 89 err = gcry_cipher_encrypt(ctx->handle, out, len, in, len); 90 if (err != 0) { 91 error_setg(errp, "Cannot encrypt data: %s", gcry_strerror(err)); 92 return -1; 93 } 94 95 return 0; 96} 97 98 99static int qcrypto_gcrypt_decrypt(QCryptoCipher *cipher, const void *in, 100 void *out, size_t len, Error **errp) 101{ 102 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base); 103 gcry_error_t err; 104 105 if (len & (ctx->blocksize - 1)) { 106 error_setg(errp, "Length %zu must be a multiple of block size %zu", 107 len, ctx->blocksize); 108 return -1; 109 } 110 111 err = gcry_cipher_decrypt(ctx->handle, out, len, in, len); 112 if (err != 0) { 113 error_setg(errp, "Cannot decrypt data: %s", 114 gcry_strerror(err)); 115 return -1; 116 } 117 118 return 0; 119} 120 121static int qcrypto_gcrypt_setiv(QCryptoCipher *cipher, 122 const uint8_t *iv, size_t niv, 123 Error **errp) 124{ 125 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base); 126 gcry_error_t err; 127 128 if (niv != ctx->blocksize) { 129 error_setg(errp, "Expected IV size %zu not %zu", 130 ctx->blocksize, niv); 131 return -1; 132 } 133 134 gcry_cipher_reset(ctx->handle); 135 err = gcry_cipher_setiv(ctx->handle, iv, niv); 136 if (err != 0) { 137 error_setg(errp, "Cannot set IV: %s", gcry_strerror(err)); 138 return -1; 139 } 140 141 return 0; 142} 143 144static int qcrypto_gcrypt_ctr_setiv(QCryptoCipher *cipher, 145 const uint8_t *iv, size_t niv, 146 Error **errp) 147{ 148 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base); 149 gcry_error_t err; 150 151 if (niv != ctx->blocksize) { 152 error_setg(errp, "Expected IV size %zu not %zu", 153 ctx->blocksize, niv); 154 return -1; 155 } 156 157 err = gcry_cipher_setctr(ctx->handle, iv, niv); 158 if (err != 0) { 159 error_setg(errp, "Cannot set Counter: %s", gcry_strerror(err)); 160 return -1; 161 } 162 163 return 0; 164} 165 166 167static const struct QCryptoCipherDriver qcrypto_gcrypt_driver = { 168 .cipher_encrypt = qcrypto_gcrypt_encrypt, 169 .cipher_decrypt = qcrypto_gcrypt_decrypt, 170 .cipher_setiv = qcrypto_gcrypt_setiv, 171 .cipher_free = qcrypto_gcrypt_ctx_free, 172}; 173 174static const struct QCryptoCipherDriver qcrypto_gcrypt_ctr_driver = { 175 .cipher_encrypt = qcrypto_gcrypt_encrypt, 176 .cipher_decrypt = qcrypto_gcrypt_decrypt, 177 .cipher_setiv = qcrypto_gcrypt_ctr_setiv, 178 .cipher_free = qcrypto_gcrypt_ctx_free, 179}; 180 181#ifdef CONFIG_QEMU_PRIVATE_XTS 182static void qcrypto_gcrypt_xts_ctx_free(QCryptoCipher *cipher) 183{ 184 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base); 185 186 gcry_cipher_close(ctx->tweakhandle); 187 qcrypto_gcrypt_ctx_free(cipher); 188} 189 190static void qcrypto_gcrypt_xts_wrape(const void *ctx, size_t length, 191 uint8_t *dst, const uint8_t *src) 192{ 193 gcry_error_t err; 194 err = gcry_cipher_encrypt((gcry_cipher_hd_t)ctx, dst, length, src, length); 195 g_assert(err == 0); 196} 197 198static void qcrypto_gcrypt_xts_wrapd(const void *ctx, size_t length, 199 uint8_t *dst, const uint8_t *src) 200{ 201 gcry_error_t err; 202 err = gcry_cipher_decrypt((gcry_cipher_hd_t)ctx, dst, length, src, length); 203 g_assert(err == 0); 204} 205 206static int qcrypto_gcrypt_xts_encrypt(QCryptoCipher *cipher, const void *in, 207 void *out, size_t len, Error **errp) 208{ 209 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base); 210 211 if (len & (ctx->blocksize - 1)) { 212 error_setg(errp, "Length %zu must be a multiple of block size %zu", 213 len, ctx->blocksize); 214 return -1; 215 } 216 217 xts_encrypt(ctx->handle, ctx->tweakhandle, 218 qcrypto_gcrypt_xts_wrape, qcrypto_gcrypt_xts_wrapd, 219 ctx->iv, len, out, in); 220 return 0; 221} 222 223static int qcrypto_gcrypt_xts_decrypt(QCryptoCipher *cipher, const void *in, 224 void *out, size_t len, Error **errp) 225{ 226 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base); 227 228 if (len & (ctx->blocksize - 1)) { 229 error_setg(errp, "Length %zu must be a multiple of block size %zu", 230 len, ctx->blocksize); 231 return -1; 232 } 233 234 xts_decrypt(ctx->handle, ctx->tweakhandle, 235 qcrypto_gcrypt_xts_wrape, qcrypto_gcrypt_xts_wrapd, 236 ctx->iv, len, out, in); 237 return 0; 238} 239 240static int qcrypto_gcrypt_xts_setiv(QCryptoCipher *cipher, 241 const uint8_t *iv, size_t niv, 242 Error **errp) 243{ 244 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base); 245 246 if (niv != ctx->blocksize) { 247 error_setg(errp, "Expected IV size %zu not %zu", 248 ctx->blocksize, niv); 249 return -1; 250 } 251 252 memcpy(ctx->iv, iv, niv); 253 return 0; 254} 255 256static const struct QCryptoCipherDriver qcrypto_gcrypt_xts_driver = { 257 .cipher_encrypt = qcrypto_gcrypt_xts_encrypt, 258 .cipher_decrypt = qcrypto_gcrypt_xts_decrypt, 259 .cipher_setiv = qcrypto_gcrypt_xts_setiv, 260 .cipher_free = qcrypto_gcrypt_xts_ctx_free, 261}; 262#endif /* CONFIG_QEMU_PRIVATE_XTS */ 263 264 265static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, 266 QCryptoCipherMode mode, 267 const uint8_t *key, 268 size_t nkey, 269 Error **errp) 270{ 271 QCryptoCipherGcrypt *ctx; 272 const QCryptoCipherDriver *drv; 273 gcry_error_t err; 274 int gcryalg, gcrymode; 275 276 if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) { 277 return NULL; 278 } 279 280 switch (alg) { 281 case QCRYPTO_CIPHER_ALG_DES_RFB: 282 gcryalg = GCRY_CIPHER_DES; 283 break; 284 case QCRYPTO_CIPHER_ALG_3DES: 285 gcryalg = GCRY_CIPHER_3DES; 286 break; 287 case QCRYPTO_CIPHER_ALG_AES_128: 288 gcryalg = GCRY_CIPHER_AES128; 289 break; 290 case QCRYPTO_CIPHER_ALG_AES_192: 291 gcryalg = GCRY_CIPHER_AES192; 292 break; 293 case QCRYPTO_CIPHER_ALG_AES_256: 294 gcryalg = GCRY_CIPHER_AES256; 295 break; 296 case QCRYPTO_CIPHER_ALG_CAST5_128: 297 gcryalg = GCRY_CIPHER_CAST5; 298 break; 299 case QCRYPTO_CIPHER_ALG_SERPENT_128: 300 gcryalg = GCRY_CIPHER_SERPENT128; 301 break; 302 case QCRYPTO_CIPHER_ALG_SERPENT_192: 303 gcryalg = GCRY_CIPHER_SERPENT192; 304 break; 305 case QCRYPTO_CIPHER_ALG_SERPENT_256: 306 gcryalg = GCRY_CIPHER_SERPENT256; 307 break; 308 case QCRYPTO_CIPHER_ALG_TWOFISH_128: 309 gcryalg = GCRY_CIPHER_TWOFISH128; 310 break; 311 case QCRYPTO_CIPHER_ALG_TWOFISH_256: 312 gcryalg = GCRY_CIPHER_TWOFISH; 313 break; 314 default: 315 error_setg(errp, "Unsupported cipher algorithm %s", 316 QCryptoCipherAlgorithm_str(alg)); 317 return NULL; 318 } 319 320 drv = &qcrypto_gcrypt_driver; 321 switch (mode) { 322 case QCRYPTO_CIPHER_MODE_ECB: 323 gcrymode = GCRY_CIPHER_MODE_ECB; 324 break; 325 case QCRYPTO_CIPHER_MODE_XTS: 326#ifdef CONFIG_QEMU_PRIVATE_XTS 327 drv = &qcrypto_gcrypt_xts_driver; 328 gcrymode = GCRY_CIPHER_MODE_ECB; 329#else 330 gcrymode = GCRY_CIPHER_MODE_XTS; 331#endif 332 break; 333 case QCRYPTO_CIPHER_MODE_CBC: 334 gcrymode = GCRY_CIPHER_MODE_CBC; 335 break; 336 case QCRYPTO_CIPHER_MODE_CTR: 337 drv = &qcrypto_gcrypt_ctr_driver; 338 gcrymode = GCRY_CIPHER_MODE_CTR; 339 break; 340 default: 341 error_setg(errp, "Unsupported cipher mode %s", 342 QCryptoCipherMode_str(mode)); 343 return NULL; 344 } 345 346 ctx = g_new0(QCryptoCipherGcrypt, 1); 347 ctx->base.driver = drv; 348 349 err = gcry_cipher_open(&ctx->handle, gcryalg, gcrymode, 0); 350 if (err != 0) { 351 error_setg(errp, "Cannot initialize cipher: %s", 352 gcry_strerror(err)); 353 goto error; 354 } 355 ctx->blocksize = gcry_cipher_get_algo_blklen(gcryalg); 356 357#ifdef CONFIG_QEMU_PRIVATE_XTS 358 if (mode == QCRYPTO_CIPHER_MODE_XTS) { 359 if (ctx->blocksize != XTS_BLOCK_SIZE) { 360 error_setg(errp, 361 "Cipher block size %zu must equal XTS block size %d", 362 ctx->blocksize, XTS_BLOCK_SIZE); 363 goto error; 364 } 365 err = gcry_cipher_open(&ctx->tweakhandle, gcryalg, gcrymode, 0); 366 if (err != 0) { 367 error_setg(errp, "Cannot initialize cipher: %s", 368 gcry_strerror(err)); 369 goto error; 370 } 371 } 372#endif 373 374 if (alg == QCRYPTO_CIPHER_ALG_DES_RFB) { 375 /* We're using standard DES cipher from gcrypt, so we need 376 * to munge the key so that the results are the same as the 377 * bizarre RFB variant of DES :-) 378 */ 379 uint8_t *rfbkey = qcrypto_cipher_munge_des_rfb_key(key, nkey); 380 err = gcry_cipher_setkey(ctx->handle, rfbkey, nkey); 381 g_free(rfbkey); 382 } else { 383#ifdef CONFIG_QEMU_PRIVATE_XTS 384 if (mode == QCRYPTO_CIPHER_MODE_XTS) { 385 nkey /= 2; 386 err = gcry_cipher_setkey(ctx->tweakhandle, key + nkey, nkey); 387 if (err != 0) { 388 error_setg(errp, "Cannot set key: %s", gcry_strerror(err)); 389 goto error; 390 } 391 } 392#endif 393 err = gcry_cipher_setkey(ctx->handle, key, nkey); 394 } 395 if (err != 0) { 396 error_setg(errp, "Cannot set key: %s", gcry_strerror(err)); 397 goto error; 398 } 399 400 return &ctx->base; 401 402 error: 403#ifdef CONFIG_QEMU_PRIVATE_XTS 404 gcry_cipher_close(ctx->tweakhandle); 405#endif 406 gcry_cipher_close(ctx->handle); 407 g_free(ctx); 408 return NULL; 409} 410