1cb730894SDaniel P. Berrange /* 2cb730894SDaniel P. Berrange * QEMU Crypto block IV generator 3cb730894SDaniel P. Berrange * 4cb730894SDaniel P. Berrange * Copyright (c) 2015-2016 Red Hat, Inc. 5cb730894SDaniel P. Berrange * 6cb730894SDaniel P. Berrange * This library is free software; you can redistribute it and/or 7cb730894SDaniel P. Berrange * modify it under the terms of the GNU Lesser General Public 8cb730894SDaniel P. Berrange * License as published by the Free Software Foundation; either 9b7cbb874SThomas Huth * version 2.1 of the License, or (at your option) any later version. 10cb730894SDaniel P. Berrange * 11cb730894SDaniel P. Berrange * This library is distributed in the hope that it will be useful, 12cb730894SDaniel P. Berrange * but WITHOUT ANY WARRANTY; without even the implied warranty of 13cb730894SDaniel P. Berrange * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14cb730894SDaniel P. Berrange * Lesser General Public License for more details. 15cb730894SDaniel P. Berrange * 16cb730894SDaniel P. Berrange * You should have received a copy of the GNU Lesser General Public 17cb730894SDaniel P. Berrange * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18cb730894SDaniel P. Berrange * 19cb730894SDaniel P. Berrange */ 20cb730894SDaniel P. Berrange 212a6a4076SMarkus Armbruster #ifndef QCRYPTO_IVGEN_H 222a6a4076SMarkus Armbruster #define QCRYPTO_IVGEN_H 23cb730894SDaniel P. Berrange 24cb730894SDaniel P. Berrange #include "crypto/cipher.h" 25cb730894SDaniel P. Berrange #include "crypto/hash.h" 26cb730894SDaniel P. Berrange 27cb730894SDaniel P. Berrange /** 28cb730894SDaniel P. Berrange * This module provides a framework for generating initialization 29cb730894SDaniel P. Berrange * vectors for block encryption schemes using chained cipher modes 30cb730894SDaniel P. Berrange * CBC. The principle is that each disk sector is assigned a unique 31cb730894SDaniel P. Berrange * initialization vector for use for encryption of data in that 32cb730894SDaniel P. Berrange * sector. 33cb730894SDaniel P. Berrange * 34cb730894SDaniel P. Berrange * <example> 35a1a62cedSMichael Tokarev * <title>Encrypting block data with initialization vectors</title> 36cb730894SDaniel P. Berrange * <programlisting> 37cb730894SDaniel P. Berrange * uint8_t *data = ....data to encrypt... 38cb730894SDaniel P. Berrange * size_t ndata = XXX; 39cb730894SDaniel P. Berrange * uint8_t *key = ....some encryption key... 40cb730894SDaniel P. Berrange * size_t nkey = XXX; 41cb730894SDaniel P. Berrange * uint8_t *iv; 42cb730894SDaniel P. Berrange * size_t niv; 43cb730894SDaniel P. Berrange * size_t sector = 0; 44cb730894SDaniel P. Berrange * 45cb730894SDaniel P. Berrange * g_assert((ndata % 512) == 0); 46cb730894SDaniel P. Berrange * 47*5e0e5102SMarkus Armbruster * QCryptoIVGen *ivgen = qcrypto_ivgen_new(QCRYPTO_IV_GEN_ALGO_ESSIV, 48a092c513SMarkus Armbruster * QCRYPTO_CIPHER_ALGO_AES_128, 49ef834aa2SMarkus Armbruster * QCRYPTO_HASH_ALGO_SHA256, 50cb730894SDaniel P. Berrange * key, nkey, errp); 51cb730894SDaniel P. Berrange * if (!ivgen) { 52cb730894SDaniel P. Berrange * return -1; 53cb730894SDaniel P. Berrange * } 54cb730894SDaniel P. Berrange * 55a092c513SMarkus Armbruster * QCryptoCipher *cipher = qcrypto_cipher_new(QCRYPTO_CIPHER_ALGO_AES_128, 56cb730894SDaniel P. Berrange * QCRYPTO_CIPHER_MODE_CBC, 57cb730894SDaniel P. Berrange * key, nkey, errp); 58cb730894SDaniel P. Berrange * if (!cipher) { 59cb730894SDaniel P. Berrange * goto error; 60cb730894SDaniel P. Berrange * } 61cb730894SDaniel P. Berrange * 62a092c513SMarkus Armbruster * niv = qcrypto_cipher_get_iv_len(QCRYPTO_CIPHER_ALGO_AES_128, 63cb730894SDaniel P. Berrange * QCRYPTO_CIPHER_MODE_CBC); 64cb730894SDaniel P. Berrange * iv = g_new0(uint8_t, niv); 65cb730894SDaniel P. Berrange * 66cb730894SDaniel P. Berrange * 67cb730894SDaniel P. Berrange * while (ndata) { 68cb730894SDaniel P. Berrange * if (qcrypto_ivgen_calculate(ivgen, sector, iv, niv, errp) < 0) { 69cb730894SDaniel P. Berrange * goto error; 70cb730894SDaniel P. Berrange * } 71cb730894SDaniel P. Berrange * if (qcrypto_cipher_setiv(cipher, iv, niv, errp) < 0) { 72cb730894SDaniel P. Berrange * goto error; 73cb730894SDaniel P. Berrange * } 74cb730894SDaniel P. Berrange * if (qcrypto_cipher_encrypt(cipher, 75cb730894SDaniel P. Berrange * data + (sector * 512), 76cb730894SDaniel P. Berrange * data + (sector * 512), 77cb730894SDaniel P. Berrange * 512, errp) < 0) { 78cb730894SDaniel P. Berrange * goto error; 79cb730894SDaniel P. Berrange * } 80cb730894SDaniel P. Berrange * sector++; 81cb730894SDaniel P. Berrange * ndata -= 512; 82cb730894SDaniel P. Berrange * } 83cb730894SDaniel P. Berrange * 84cb730894SDaniel P. Berrange * g_free(iv); 85cb730894SDaniel P. Berrange * qcrypto_ivgen_free(ivgen); 86cb730894SDaniel P. Berrange * qcrypto_cipher_free(cipher); 87cb730894SDaniel P. Berrange * return 0; 88cb730894SDaniel P. Berrange * 89cb730894SDaniel P. Berrange *error: 90cb730894SDaniel P. Berrange * g_free(iv); 91cb730894SDaniel P. Berrange * qcrypto_ivgen_free(ivgen); 92cb730894SDaniel P. Berrange * qcrypto_cipher_free(cipher); 93cb730894SDaniel P. Berrange * return -1; 94cb730894SDaniel P. Berrange * </programlisting> 95cb730894SDaniel P. Berrange * </example> 96cb730894SDaniel P. Berrange */ 97cb730894SDaniel P. Berrange 98cb730894SDaniel P. Berrange typedef struct QCryptoIVGen QCryptoIVGen; 99cb730894SDaniel P. Berrange 100*5e0e5102SMarkus Armbruster /* See also QCryptoIVGenAlgo enum in qapi/crypto.json */ 101cb730894SDaniel P. Berrange 102cb730894SDaniel P. Berrange 103cb730894SDaniel P. Berrange /** 104cb730894SDaniel P. Berrange * qcrypto_ivgen_new: 105cb730894SDaniel P. Berrange * @alg: the initialization vector generation algorithm 106cb730894SDaniel P. Berrange * @cipheralg: the cipher algorithm or 0 107cb730894SDaniel P. Berrange * @hash: the hash algorithm or 0 108cb730894SDaniel P. Berrange * @key: the encryption key or NULL 109cb730894SDaniel P. Berrange * @nkey: the size of @key in bytes 110cb730894SDaniel P. Berrange * 111cb730894SDaniel P. Berrange * Create a new initialization vector generator that uses 112cb730894SDaniel P. Berrange * the algorithm @alg. Whether the remaining parameters 113cb730894SDaniel P. Berrange * are required or not depends on the choice of @alg 114cb730894SDaniel P. Berrange * requested. 115cb730894SDaniel P. Berrange * 116*5e0e5102SMarkus Armbruster * - QCRYPTO_IV_GEN_ALGO_PLAIN 117cb730894SDaniel P. Berrange * 118cb730894SDaniel P. Berrange * The IVs are generated by the 32-bit truncated sector 119cb730894SDaniel P. Berrange * number. This should never be used for block devices 120cb730894SDaniel P. Berrange * that are larger than 2^32 sectors in size. 121cb730894SDaniel P. Berrange * All the other parameters are unused. 122cb730894SDaniel P. Berrange * 123*5e0e5102SMarkus Armbruster * - QCRYPTO_IV_GEN_ALGO_PLAIN64 124cb730894SDaniel P. Berrange * 125cb730894SDaniel P. Berrange * The IVs are generated by the 64-bit sector number. 126cb730894SDaniel P. Berrange * All the other parameters are unused. 127cb730894SDaniel P. Berrange * 128*5e0e5102SMarkus Armbruster * - QCRYPTO_IV_GEN_ALGO_ESSIV: 129cb730894SDaniel P. Berrange * 130cb730894SDaniel P. Berrange * The IVs are generated by encrypting the 64-bit sector 131cb730894SDaniel P. Berrange * number with a hash of an encryption key. The @cipheralg, 132cb730894SDaniel P. Berrange * @hash, @key and @nkey parameters are all required. 133cb730894SDaniel P. Berrange * 134cb730894SDaniel P. Berrange * Returns: a new IV generator, or NULL on error 135cb730894SDaniel P. Berrange */ 136*5e0e5102SMarkus Armbruster QCryptoIVGen *qcrypto_ivgen_new(QCryptoIVGenAlgo alg, 137a092c513SMarkus Armbruster QCryptoCipherAlgo cipheralg, 138ef834aa2SMarkus Armbruster QCryptoHashAlgo hash, 139cb730894SDaniel P. Berrange const uint8_t *key, size_t nkey, 140cb730894SDaniel P. Berrange Error **errp); 141cb730894SDaniel P. Berrange 142cb730894SDaniel P. Berrange /** 143cb730894SDaniel P. Berrange * qcrypto_ivgen_calculate: 144cb730894SDaniel P. Berrange * @ivgen: the IV generator object 145cb730894SDaniel P. Berrange * @sector: the 64-bit sector number 146cb730894SDaniel P. Berrange * @iv: a pre-allocated buffer to hold the generated IV 147cb730894SDaniel P. Berrange * @niv: the number of bytes in @iv 148cb730894SDaniel P. Berrange * @errp: pointer to a NULL-initialized error object 149cb730894SDaniel P. Berrange * 150a1a62cedSMichael Tokarev * Calculate a new initialization vector for the data 151cb730894SDaniel P. Berrange * to be stored in sector @sector. The IV will be 152cb730894SDaniel P. Berrange * written into the buffer @iv of size @niv. 153cb730894SDaniel P. Berrange * 154cb730894SDaniel P. Berrange * Returns: 0 on success, -1 on error 155cb730894SDaniel P. Berrange */ 156cb730894SDaniel P. Berrange int qcrypto_ivgen_calculate(QCryptoIVGen *ivgen, 157cb730894SDaniel P. Berrange uint64_t sector, 158cb730894SDaniel P. Berrange uint8_t *iv, size_t niv, 159cb730894SDaniel P. Berrange Error **errp); 160cb730894SDaniel P. Berrange 161cb730894SDaniel P. Berrange 162cb730894SDaniel P. Berrange /** 163cb730894SDaniel P. Berrange * qcrypto_ivgen_get_algorithm: 164cb730894SDaniel P. Berrange * @ivgen: the IV generator object 165cb730894SDaniel P. Berrange * 166cb730894SDaniel P. Berrange * Get the algorithm used by this IV generator 167cb730894SDaniel P. Berrange * 168cb730894SDaniel P. Berrange * Returns: the IV generator algorithm 169cb730894SDaniel P. Berrange */ 170*5e0e5102SMarkus Armbruster QCryptoIVGenAlgo qcrypto_ivgen_get_algorithm(QCryptoIVGen *ivgen); 171cb730894SDaniel P. Berrange 172cb730894SDaniel P. Berrange 173cb730894SDaniel P. Berrange /** 174cb730894SDaniel P. Berrange * qcrypto_ivgen_get_cipher: 175cb730894SDaniel P. Berrange * @ivgen: the IV generator object 176cb730894SDaniel P. Berrange * 177cb730894SDaniel P. Berrange * Get the cipher algorithm used by this IV generator (if 178cb730894SDaniel P. Berrange * applicable) 179cb730894SDaniel P. Berrange * 180cb730894SDaniel P. Berrange * Returns: the cipher algorithm 181cb730894SDaniel P. Berrange */ 182a092c513SMarkus Armbruster QCryptoCipherAlgo qcrypto_ivgen_get_cipher(QCryptoIVGen *ivgen); 183cb730894SDaniel P. Berrange 184cb730894SDaniel P. Berrange 185cb730894SDaniel P. Berrange /** 186cb730894SDaniel P. Berrange * qcrypto_ivgen_get_hash: 187cb730894SDaniel P. Berrange * @ivgen: the IV generator object 188cb730894SDaniel P. Berrange * 189cb730894SDaniel P. Berrange * Get the hash algorithm used by this IV generator (if 190cb730894SDaniel P. Berrange * applicable) 191cb730894SDaniel P. Berrange * 192cb730894SDaniel P. Berrange * Returns: the hash algorithm 193cb730894SDaniel P. Berrange */ 194ef834aa2SMarkus Armbruster QCryptoHashAlgo qcrypto_ivgen_get_hash(QCryptoIVGen *ivgen); 195cb730894SDaniel P. Berrange 196cb730894SDaniel P. Berrange 197cb730894SDaniel P. Berrange /** 198cb730894SDaniel P. Berrange * qcrypto_ivgen_free: 199cb730894SDaniel P. Berrange * @ivgen: the IV generator object 200cb730894SDaniel P. Berrange * 201cb730894SDaniel P. Berrange * Release all resources associated with @ivgen, or a no-op 202cb730894SDaniel P. Berrange * if @ivgen is NULL 203cb730894SDaniel P. Berrange */ 204cb730894SDaniel P. Berrange void qcrypto_ivgen_free(QCryptoIVGen *ivgen); 205cb730894SDaniel P. Berrange 206133cf1e5SDaniel P. Berrangé G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoIVGen, qcrypto_ivgen_free) 207133cf1e5SDaniel P. Berrangé 2082a6a4076SMarkus Armbruster #endif /* QCRYPTO_IVGEN_H */ 209