16d92bdf4SRichard Henderson/* 26d92bdf4SRichard Henderson * QEMU Crypto cipher built-in algorithms 36d92bdf4SRichard Henderson * 46d92bdf4SRichard Henderson * Copyright (c) 2015 Red Hat, Inc. 56d92bdf4SRichard Henderson * 66d92bdf4SRichard Henderson * This library is free software; you can redistribute it and/or 76d92bdf4SRichard Henderson * modify it under the terms of the GNU Lesser General Public 86d92bdf4SRichard Henderson * License as published by the Free Software Foundation; either 96d92bdf4SRichard Henderson * version 2.1 of the License, or (at your option) any later version. 106d92bdf4SRichard Henderson * 116d92bdf4SRichard Henderson * This library is distributed in the hope that it will be useful, 126d92bdf4SRichard Henderson * but WITHOUT ANY WARRANTY; without even the implied warranty of 136d92bdf4SRichard Henderson * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 146d92bdf4SRichard Henderson * Lesser General Public License for more details. 156d92bdf4SRichard Henderson * 166d92bdf4SRichard Henderson * You should have received a copy of the GNU Lesser General Public 176d92bdf4SRichard Henderson * License along with this library; if not, see <http://www.gnu.org/licenses/>. 186d92bdf4SRichard Henderson * 196d92bdf4SRichard Henderson */ 206d92bdf4SRichard Henderson 216d92bdf4SRichard Henderson#include "crypto/aes.h" 226d92bdf4SRichard Henderson 236d92bdf4SRichard Hendersontypedef struct QCryptoCipherBuiltinAESContext QCryptoCipherBuiltinAESContext; 246d92bdf4SRichard Hendersonstruct QCryptoCipherBuiltinAESContext { 256d92bdf4SRichard Henderson AES_KEY enc; 266d92bdf4SRichard Henderson AES_KEY dec; 276d92bdf4SRichard Henderson}; 28a3db31b8SRichard Henderson 296d92bdf4SRichard Hendersontypedef struct QCryptoCipherBuiltinAES QCryptoCipherBuiltinAES; 306d92bdf4SRichard Hendersonstruct QCryptoCipherBuiltinAES { 31a3db31b8SRichard Henderson QCryptoCipher base; 326d92bdf4SRichard Henderson QCryptoCipherBuiltinAESContext key; 336d92bdf4SRichard Henderson uint8_t iv[AES_BLOCK_SIZE]; 346d92bdf4SRichard Henderson}; 356d92bdf4SRichard Henderson 366d92bdf4SRichard Henderson 37a3db31b8SRichard Hendersonstatic inline bool qcrypto_length_check(size_t len, size_t blocksize, 38a3db31b8SRichard Henderson Error **errp) 39a3db31b8SRichard Henderson{ 40a3db31b8SRichard Henderson if (unlikely(len & (blocksize - 1))) { 41a3db31b8SRichard Henderson error_setg(errp, "Length %zu must be a multiple of block size %zu", 42a3db31b8SRichard Henderson len, blocksize); 43a3db31b8SRichard Henderson return false; 44a3db31b8SRichard Henderson } 45a3db31b8SRichard Henderson return true; 46a3db31b8SRichard Henderson} 47a3db31b8SRichard Henderson 48a3db31b8SRichard Hendersonstatic void qcrypto_cipher_ctx_free(QCryptoCipher *cipher) 496d92bdf4SRichard Henderson{ 503eedf5ccSRichard Henderson g_free(cipher); 516d92bdf4SRichard Henderson} 526d92bdf4SRichard Henderson 53a3db31b8SRichard Hendersonstatic int qcrypto_cipher_no_setiv(QCryptoCipher *cipher, 54a3db31b8SRichard Henderson const uint8_t *iv, size_t niv, 55a3db31b8SRichard Henderson Error **errp) 56a3db31b8SRichard Henderson{ 57a3db31b8SRichard Henderson error_setg(errp, "Setting IV is not supported"); 58a3db31b8SRichard Henderson return -1; 59a3db31b8SRichard Henderson} 60a3db31b8SRichard Henderson 618ee47cddSRichard Hendersonstatic void do_aes_encrypt_ecb(const void *vctx, 628ee47cddSRichard Henderson size_t len, 638ee47cddSRichard Henderson uint8_t *out, 648ee47cddSRichard Henderson const uint8_t *in) 656d92bdf4SRichard Henderson{ 668ee47cddSRichard Henderson const QCryptoCipherBuiltinAESContext *ctx = vctx; 67838e4631SRichard Henderson 68838e4631SRichard Henderson /* We have already verified that len % AES_BLOCK_SIZE == 0. */ 696d92bdf4SRichard Henderson while (len) { 708ee47cddSRichard Henderson AES_encrypt(in, out, &ctx->enc); 718ee47cddSRichard Henderson in += AES_BLOCK_SIZE; 728ee47cddSRichard Henderson out += AES_BLOCK_SIZE; 736d92bdf4SRichard Henderson len -= AES_BLOCK_SIZE; 746d92bdf4SRichard Henderson } 756d92bdf4SRichard Henderson} 766d92bdf4SRichard Henderson 778ee47cddSRichard Hendersonstatic void do_aes_decrypt_ecb(const void *vctx, 788ee47cddSRichard Henderson size_t len, 798ee47cddSRichard Henderson uint8_t *out, 808ee47cddSRichard Henderson const uint8_t *in) 816d92bdf4SRichard Henderson{ 828ee47cddSRichard Henderson const QCryptoCipherBuiltinAESContext *ctx = vctx; 83838e4631SRichard Henderson 84838e4631SRichard Henderson /* We have already verified that len % AES_BLOCK_SIZE == 0. */ 856d92bdf4SRichard Henderson while (len) { 868ee47cddSRichard Henderson AES_decrypt(in, out, &ctx->dec); 878ee47cddSRichard Henderson in += AES_BLOCK_SIZE; 888ee47cddSRichard Henderson out += AES_BLOCK_SIZE; 896d92bdf4SRichard Henderson len -= AES_BLOCK_SIZE; 906d92bdf4SRichard Henderson } 916d92bdf4SRichard Henderson} 926d92bdf4SRichard Henderson 93ef186f4bSRichard Hendersonstatic void do_aes_encrypt_cbc(const AES_KEY *key, 94ef186f4bSRichard Henderson size_t len, 95ef186f4bSRichard Henderson uint8_t *out, 96ef186f4bSRichard Henderson const uint8_t *in, 97ef186f4bSRichard Henderson uint8_t *ivec) 98a2d76b6bSRichard Henderson{ 99ef186f4bSRichard Henderson uint8_t tmp[AES_BLOCK_SIZE]; 100ef186f4bSRichard Henderson size_t n; 101a2d76b6bSRichard Henderson 102ef186f4bSRichard Henderson /* We have already verified that len % AES_BLOCK_SIZE == 0. */ 103ef186f4bSRichard Henderson while (len) { 104a2d76b6bSRichard Henderson for (n = 0; n < AES_BLOCK_SIZE; ++n) { 105a2d76b6bSRichard Henderson tmp[n] = in[n] ^ ivec[n]; 106a2d76b6bSRichard Henderson } 107a2d76b6bSRichard Henderson AES_encrypt(tmp, out, key); 108a2d76b6bSRichard Henderson memcpy(ivec, out, AES_BLOCK_SIZE); 109a2d76b6bSRichard Henderson len -= AES_BLOCK_SIZE; 110a2d76b6bSRichard Henderson in += AES_BLOCK_SIZE; 111a2d76b6bSRichard Henderson out += AES_BLOCK_SIZE; 112a2d76b6bSRichard Henderson } 113a2d76b6bSRichard Henderson} 114ef186f4bSRichard Henderson 115ef186f4bSRichard Hendersonstatic void do_aes_decrypt_cbc(const AES_KEY *key, 116ef186f4bSRichard Henderson size_t len, 117ef186f4bSRichard Henderson uint8_t *out, 118ef186f4bSRichard Henderson const uint8_t *in, 119ef186f4bSRichard Henderson uint8_t *ivec) 120ef186f4bSRichard Henderson{ 121ef186f4bSRichard Henderson uint8_t tmp[AES_BLOCK_SIZE]; 122ef186f4bSRichard Henderson size_t n; 123ef186f4bSRichard Henderson 124ef186f4bSRichard Henderson /* We have already verified that len % AES_BLOCK_SIZE == 0. */ 125ef186f4bSRichard Henderson while (len) { 126a2d76b6bSRichard Henderson memcpy(tmp, in, AES_BLOCK_SIZE); 127a2d76b6bSRichard Henderson AES_decrypt(in, out, key); 128a2d76b6bSRichard Henderson for (n = 0; n < AES_BLOCK_SIZE; ++n) { 129a2d76b6bSRichard Henderson out[n] ^= ivec[n]; 130a2d76b6bSRichard Henderson } 131a2d76b6bSRichard Henderson memcpy(ivec, tmp, AES_BLOCK_SIZE); 132a2d76b6bSRichard Henderson len -= AES_BLOCK_SIZE; 133a2d76b6bSRichard Henderson in += AES_BLOCK_SIZE; 134a2d76b6bSRichard Henderson out += AES_BLOCK_SIZE; 135a2d76b6bSRichard Henderson } 136a2d76b6bSRichard Henderson} 137a2d76b6bSRichard Henderson 138a3db31b8SRichard Hendersonstatic int qcrypto_cipher_aes_encrypt_ecb(QCryptoCipher *cipher, 139a3db31b8SRichard Henderson const void *in, void *out, 140a3db31b8SRichard Henderson size_t len, Error **errp) 1416d92bdf4SRichard Henderson{ 142a3db31b8SRichard Henderson QCryptoCipherBuiltinAES *ctx 143a3db31b8SRichard Henderson = container_of(cipher, QCryptoCipherBuiltinAES, base); 1446d92bdf4SRichard Henderson 145a3db31b8SRichard Henderson if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) { 146a3db31b8SRichard Henderson return -1; 147a3db31b8SRichard Henderson } 148a3db31b8SRichard Henderson do_aes_encrypt_ecb(&ctx->key, len, out, in); 149a3db31b8SRichard Henderson return 0; 1506d92bdf4SRichard Henderson} 1516d92bdf4SRichard Henderson 152a3db31b8SRichard Hendersonstatic int qcrypto_cipher_aes_decrypt_ecb(QCryptoCipher *cipher, 153a3db31b8SRichard Henderson const void *in, void *out, 154a3db31b8SRichard Henderson size_t len, Error **errp) 155a3db31b8SRichard Henderson{ 156a3db31b8SRichard Henderson QCryptoCipherBuiltinAES *ctx 157a3db31b8SRichard Henderson = container_of(cipher, QCryptoCipherBuiltinAES, base); 158a3db31b8SRichard Henderson 159a3db31b8SRichard Henderson if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) { 160a3db31b8SRichard Henderson return -1; 161a3db31b8SRichard Henderson } 162a3db31b8SRichard Henderson do_aes_decrypt_ecb(&ctx->key, len, out, in); 163a3db31b8SRichard Henderson return 0; 164a3db31b8SRichard Henderson} 165a3db31b8SRichard Henderson 166a3db31b8SRichard Hendersonstatic int qcrypto_cipher_aes_encrypt_cbc(QCryptoCipher *cipher, 167a3db31b8SRichard Henderson const void *in, void *out, 168a3db31b8SRichard Henderson size_t len, Error **errp) 169a3db31b8SRichard Henderson{ 170a3db31b8SRichard Henderson QCryptoCipherBuiltinAES *ctx 171a3db31b8SRichard Henderson = container_of(cipher, QCryptoCipherBuiltinAES, base); 172a3db31b8SRichard Henderson 173a3db31b8SRichard Henderson if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) { 174a3db31b8SRichard Henderson return -1; 175a3db31b8SRichard Henderson } 176a3db31b8SRichard Henderson do_aes_encrypt_cbc(&ctx->key.enc, len, out, in, ctx->iv); 177a3db31b8SRichard Henderson return 0; 178a3db31b8SRichard Henderson} 179a3db31b8SRichard Henderson 180a3db31b8SRichard Hendersonstatic int qcrypto_cipher_aes_decrypt_cbc(QCryptoCipher *cipher, 181a3db31b8SRichard Henderson const void *in, void *out, 182a3db31b8SRichard Henderson size_t len, Error **errp) 183a3db31b8SRichard Henderson{ 184a3db31b8SRichard Henderson QCryptoCipherBuiltinAES *ctx 185a3db31b8SRichard Henderson = container_of(cipher, QCryptoCipherBuiltinAES, base); 186a3db31b8SRichard Henderson 187a3db31b8SRichard Henderson if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) { 188a3db31b8SRichard Henderson return -1; 189a3db31b8SRichard Henderson } 190a3db31b8SRichard Henderson do_aes_decrypt_cbc(&ctx->key.dec, len, out, in, ctx->iv); 191a3db31b8SRichard Henderson return 0; 192a3db31b8SRichard Henderson} 193a3db31b8SRichard Henderson 194a3db31b8SRichard Hendersonstatic int qcrypto_cipher_aes_setiv(QCryptoCipher *cipher, const uint8_t *iv, 195a3db31b8SRichard Henderson size_t niv, Error **errp) 1966d92bdf4SRichard Henderson{ 197a3db31b8SRichard Henderson QCryptoCipherBuiltinAES *ctx 198a3db31b8SRichard Henderson = container_of(cipher, QCryptoCipherBuiltinAES, base); 1993eedf5ccSRichard Henderson 2006d92bdf4SRichard Henderson if (niv != AES_BLOCK_SIZE) { 2016d92bdf4SRichard Henderson error_setg(errp, "IV must be %d bytes not %zu", 2026d92bdf4SRichard Henderson AES_BLOCK_SIZE, niv); 2036d92bdf4SRichard Henderson return -1; 2046d92bdf4SRichard Henderson } 2056d92bdf4SRichard Henderson 206a3db31b8SRichard Henderson memcpy(ctx->iv, iv, AES_BLOCK_SIZE); 2076d92bdf4SRichard Henderson return 0; 2086d92bdf4SRichard Henderson} 2096d92bdf4SRichard Henderson 210a3db31b8SRichard Hendersonstatic const struct QCryptoCipherDriver qcrypto_cipher_aes_driver_ecb = { 211a3db31b8SRichard Henderson .cipher_encrypt = qcrypto_cipher_aes_encrypt_ecb, 212a3db31b8SRichard Henderson .cipher_decrypt = qcrypto_cipher_aes_decrypt_ecb, 213a3db31b8SRichard Henderson .cipher_setiv = qcrypto_cipher_no_setiv, 214a3db31b8SRichard Henderson .cipher_free = qcrypto_cipher_ctx_free, 215a3db31b8SRichard Henderson}; 216a3db31b8SRichard Henderson 217a3db31b8SRichard Hendersonstatic const struct QCryptoCipherDriver qcrypto_cipher_aes_driver_cbc = { 218a3db31b8SRichard Henderson .cipher_encrypt = qcrypto_cipher_aes_encrypt_cbc, 219a3db31b8SRichard Henderson .cipher_decrypt = qcrypto_cipher_aes_decrypt_cbc, 220a3db31b8SRichard Henderson .cipher_setiv = qcrypto_cipher_aes_setiv, 221a3db31b8SRichard Henderson .cipher_free = qcrypto_cipher_ctx_free, 222a3db31b8SRichard Henderson}; 223a3db31b8SRichard Henderson 224*a092c513SMarkus Armbrusterbool qcrypto_cipher_supports(QCryptoCipherAlgo alg, 2256d92bdf4SRichard Henderson QCryptoCipherMode mode) 2266d92bdf4SRichard Henderson{ 2276d92bdf4SRichard Henderson switch (alg) { 228*a092c513SMarkus Armbruster case QCRYPTO_CIPHER_ALGO_AES_128: 229*a092c513SMarkus Armbruster case QCRYPTO_CIPHER_ALGO_AES_192: 230*a092c513SMarkus Armbruster case QCRYPTO_CIPHER_ALGO_AES_256: 2316d92bdf4SRichard Henderson switch (mode) { 2326d92bdf4SRichard Henderson case QCRYPTO_CIPHER_MODE_ECB: 2336d92bdf4SRichard Henderson case QCRYPTO_CIPHER_MODE_CBC: 2346d92bdf4SRichard Henderson return true; 235a3db31b8SRichard Henderson default: 2366d92bdf4SRichard Henderson return false; 237a3db31b8SRichard Henderson } 238a3db31b8SRichard Henderson break; 2396d92bdf4SRichard Henderson default: 2406d92bdf4SRichard Henderson return false; 2416d92bdf4SRichard Henderson } 2426d92bdf4SRichard Henderson} 2436d92bdf4SRichard Henderson 244*a092c513SMarkus Armbrusterstatic QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgo alg, 2456d92bdf4SRichard Henderson QCryptoCipherMode mode, 2466d92bdf4SRichard Henderson const uint8_t *key, 2476d92bdf4SRichard Henderson size_t nkey, 2486d92bdf4SRichard Henderson Error **errp) 2496d92bdf4SRichard Henderson{ 2506d92bdf4SRichard Henderson if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) { 2516d92bdf4SRichard Henderson return NULL; 2526d92bdf4SRichard Henderson } 2536d92bdf4SRichard Henderson 2546d92bdf4SRichard Henderson switch (alg) { 255*a092c513SMarkus Armbruster case QCRYPTO_CIPHER_ALGO_AES_128: 256*a092c513SMarkus Armbruster case QCRYPTO_CIPHER_ALGO_AES_192: 257*a092c513SMarkus Armbruster case QCRYPTO_CIPHER_ALGO_AES_256: 258a3db31b8SRichard Henderson { 259a3db31b8SRichard Henderson QCryptoCipherBuiltinAES *ctx; 260a3db31b8SRichard Henderson const QCryptoCipherDriver *drv; 261a3db31b8SRichard Henderson 262a3db31b8SRichard Henderson switch (mode) { 263a3db31b8SRichard Henderson case QCRYPTO_CIPHER_MODE_ECB: 264a3db31b8SRichard Henderson drv = &qcrypto_cipher_aes_driver_ecb; 265a3db31b8SRichard Henderson break; 266a3db31b8SRichard Henderson case QCRYPTO_CIPHER_MODE_CBC: 267a3db31b8SRichard Henderson drv = &qcrypto_cipher_aes_driver_cbc; 268a3db31b8SRichard Henderson break; 269a3db31b8SRichard Henderson default: 270a3db31b8SRichard Henderson goto bad_mode; 271a3db31b8SRichard Henderson } 272a3db31b8SRichard Henderson 273a3db31b8SRichard Henderson ctx = g_new0(QCryptoCipherBuiltinAES, 1); 274a3db31b8SRichard Henderson ctx->base.driver = drv; 275a3db31b8SRichard Henderson 276a3db31b8SRichard Henderson if (AES_set_encrypt_key(key, nkey * 8, &ctx->key.enc)) { 277a3db31b8SRichard Henderson error_setg(errp, "Failed to set encryption key"); 278a3db31b8SRichard Henderson goto error; 279a3db31b8SRichard Henderson } 280a3db31b8SRichard Henderson if (AES_set_decrypt_key(key, nkey * 8, &ctx->key.dec)) { 281a3db31b8SRichard Henderson error_setg(errp, "Failed to set decryption key"); 282a3db31b8SRichard Henderson goto error; 283a3db31b8SRichard Henderson } 284a3db31b8SRichard Henderson 285a3db31b8SRichard Henderson return &ctx->base; 286a3db31b8SRichard Henderson 287a3db31b8SRichard Henderson error: 288a3db31b8SRichard Henderson g_free(ctx); 289a3db31b8SRichard Henderson return NULL; 290a3db31b8SRichard Henderson } 291a3db31b8SRichard Henderson 2926d92bdf4SRichard Henderson default: 2936d92bdf4SRichard Henderson error_setg(errp, 2946d92bdf4SRichard Henderson "Unsupported cipher algorithm %s", 295*a092c513SMarkus Armbruster QCryptoCipherAlgo_str(alg)); 2966d92bdf4SRichard Henderson return NULL; 2976d92bdf4SRichard Henderson } 298a3db31b8SRichard Henderson 299a3db31b8SRichard Henderson bad_mode: 300a3db31b8SRichard Henderson error_setg(errp, "Unsupported cipher mode %s", 301a3db31b8SRichard Henderson QCryptoCipherMode_str(mode)); 302a3db31b8SRichard Henderson return NULL; 3036d92bdf4SRichard Henderson} 304