1 /* 2 * QEMU Crypto block IV generator 3 * 4 * Copyright (c) 2015-2016 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 #ifndef QCRYPTO_IVGEN_H 22 #define QCRYPTO_IVGEN_H 23 24 #include "crypto/cipher.h" 25 #include "crypto/hash.h" 26 27 /** 28 * This module provides a framework for generating initialization 29 * vectors for block encryption schemes using chained cipher modes 30 * CBC. The principle is that each disk sector is assigned a unique 31 * initialization vector for use for encryption of data in that 32 * sector. 33 * 34 * <example> 35 * <title>Encrypting block data with initialization vectors</title> 36 * <programlisting> 37 * uint8_t *data = ....data to encrypt... 38 * size_t ndata = XXX; 39 * uint8_t *key = ....some encryption key... 40 * size_t nkey = XXX; 41 * uint8_t *iv; 42 * size_t niv; 43 * size_t sector = 0; 44 * 45 * g_assert((ndata % 512) == 0); 46 * 47 * QCryptoIVGen *ivgen = qcrypto_ivgen_new(QCRYPTO_IV_GEN_ALGO_ESSIV, 48 * QCRYPTO_CIPHER_ALGO_AES_128, 49 * QCRYPTO_HASH_ALGO_SHA256, 50 * key, nkey, errp); 51 * if (!ivgen) { 52 * return -1; 53 * } 54 * 55 * QCryptoCipher *cipher = qcrypto_cipher_new(QCRYPTO_CIPHER_ALGO_AES_128, 56 * QCRYPTO_CIPHER_MODE_CBC, 57 * key, nkey, errp); 58 * if (!cipher) { 59 * goto error; 60 * } 61 * 62 * niv = qcrypto_cipher_get_iv_len(QCRYPTO_CIPHER_ALGO_AES_128, 63 * QCRYPTO_CIPHER_MODE_CBC); 64 * iv = g_new0(uint8_t, niv); 65 * 66 * 67 * while (ndata) { 68 * if (qcrypto_ivgen_calculate(ivgen, sector, iv, niv, errp) < 0) { 69 * goto error; 70 * } 71 * if (qcrypto_cipher_setiv(cipher, iv, niv, errp) < 0) { 72 * goto error; 73 * } 74 * if (qcrypto_cipher_encrypt(cipher, 75 * data + (sector * 512), 76 * data + (sector * 512), 77 * 512, errp) < 0) { 78 * goto error; 79 * } 80 * sector++; 81 * ndata -= 512; 82 * } 83 * 84 * g_free(iv); 85 * qcrypto_ivgen_free(ivgen); 86 * qcrypto_cipher_free(cipher); 87 * return 0; 88 * 89 *error: 90 * g_free(iv); 91 * qcrypto_ivgen_free(ivgen); 92 * qcrypto_cipher_free(cipher); 93 * return -1; 94 * </programlisting> 95 * </example> 96 */ 97 98 typedef struct QCryptoIVGen QCryptoIVGen; 99 100 /* See also QCryptoIVGenAlgo enum in qapi/crypto.json */ 101 102 103 /** 104 * qcrypto_ivgen_new: 105 * @alg: the initialization vector generation algorithm 106 * @cipheralg: the cipher algorithm or 0 107 * @hash: the hash algorithm or 0 108 * @key: the encryption key or NULL 109 * @nkey: the size of @key in bytes 110 * 111 * Create a new initialization vector generator that uses 112 * the algorithm @alg. Whether the remaining parameters 113 * are required or not depends on the choice of @alg 114 * requested. 115 * 116 * - QCRYPTO_IV_GEN_ALGO_PLAIN 117 * 118 * The IVs are generated by the 32-bit truncated sector 119 * number. This should never be used for block devices 120 * that are larger than 2^32 sectors in size. 121 * All the other parameters are unused. 122 * 123 * - QCRYPTO_IV_GEN_ALGO_PLAIN64 124 * 125 * The IVs are generated by the 64-bit sector number. 126 * All the other parameters are unused. 127 * 128 * - QCRYPTO_IV_GEN_ALGO_ESSIV: 129 * 130 * The IVs are generated by encrypting the 64-bit sector 131 * number with a hash of an encryption key. The @cipheralg, 132 * @hash, @key and @nkey parameters are all required. 133 * 134 * Returns: a new IV generator, or NULL on error 135 */ 136 QCryptoIVGen *qcrypto_ivgen_new(QCryptoIVGenAlgo alg, 137 QCryptoCipherAlgo cipheralg, 138 QCryptoHashAlgo hash, 139 const uint8_t *key, size_t nkey, 140 Error **errp); 141 142 /** 143 * qcrypto_ivgen_calculate: 144 * @ivgen: the IV generator object 145 * @sector: the 64-bit sector number 146 * @iv: a pre-allocated buffer to hold the generated IV 147 * @niv: the number of bytes in @iv 148 * @errp: pointer to a NULL-initialized error object 149 * 150 * Calculate a new initialization vector for the data 151 * to be stored in sector @sector. The IV will be 152 * written into the buffer @iv of size @niv. 153 * 154 * Returns: 0 on success, -1 on error 155 */ 156 int qcrypto_ivgen_calculate(QCryptoIVGen *ivgen, 157 uint64_t sector, 158 uint8_t *iv, size_t niv, 159 Error **errp); 160 161 162 /** 163 * qcrypto_ivgen_get_algorithm: 164 * @ivgen: the IV generator object 165 * 166 * Get the algorithm used by this IV generator 167 * 168 * Returns: the IV generator algorithm 169 */ 170 QCryptoIVGenAlgo qcrypto_ivgen_get_algorithm(QCryptoIVGen *ivgen); 171 172 173 /** 174 * qcrypto_ivgen_get_cipher: 175 * @ivgen: the IV generator object 176 * 177 * Get the cipher algorithm used by this IV generator (if 178 * applicable) 179 * 180 * Returns: the cipher algorithm 181 */ 182 QCryptoCipherAlgo qcrypto_ivgen_get_cipher(QCryptoIVGen *ivgen); 183 184 185 /** 186 * qcrypto_ivgen_get_hash: 187 * @ivgen: the IV generator object 188 * 189 * Get the hash algorithm used by this IV generator (if 190 * applicable) 191 * 192 * Returns: the hash algorithm 193 */ 194 QCryptoHashAlgo qcrypto_ivgen_get_hash(QCryptoIVGen *ivgen); 195 196 197 /** 198 * qcrypto_ivgen_free: 199 * @ivgen: the IV generator object 200 * 201 * Release all resources associated with @ivgen, or a no-op 202 * if @ivgen is NULL 203 */ 204 void qcrypto_ivgen_free(QCryptoIVGen *ivgen); 205 206 G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoIVGen, qcrypto_ivgen_free) 207 208 #endif /* QCRYPTO_IVGEN_H */ 209