1 /* 2 * QEMU Crypto block device encryption 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 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 #include "qemu/osdep.h" 22 #include "qapi/error.h" 23 #include "crypto/blockpriv.h" 24 #include "crypto/block-qcow.h" 25 #include "crypto/block-luks.h" 26 27 static const QCryptoBlockDriver *qcrypto_block_drivers[] = { 28 [Q_CRYPTO_BLOCK_FORMAT_QCOW] = &qcrypto_block_driver_qcow, 29 [Q_CRYPTO_BLOCK_FORMAT_LUKS] = &qcrypto_block_driver_luks, 30 }; 31 32 33 bool qcrypto_block_has_format(QCryptoBlockFormat format, 34 const uint8_t *buf, 35 size_t len) 36 { 37 const QCryptoBlockDriver *driver; 38 39 if (format >= G_N_ELEMENTS(qcrypto_block_drivers) || 40 !qcrypto_block_drivers[format]) { 41 return false; 42 } 43 44 driver = qcrypto_block_drivers[format]; 45 46 return driver->has_format(buf, len); 47 } 48 49 50 QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options, 51 QCryptoBlockReadFunc readfunc, 52 void *opaque, 53 unsigned int flags, 54 Error **errp) 55 { 56 QCryptoBlock *block = g_new0(QCryptoBlock, 1); 57 58 block->format = options->format; 59 60 if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) || 61 !qcrypto_block_drivers[options->format]) { 62 error_setg(errp, "Unsupported block driver %s", 63 QCryptoBlockFormat_lookup[options->format]); 64 g_free(block); 65 return NULL; 66 } 67 68 block->driver = qcrypto_block_drivers[options->format]; 69 70 if (block->driver->open(block, options, 71 readfunc, opaque, flags, errp) < 0) { 72 g_free(block); 73 return NULL; 74 } 75 76 return block; 77 } 78 79 80 QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options, 81 QCryptoBlockInitFunc initfunc, 82 QCryptoBlockWriteFunc writefunc, 83 void *opaque, 84 Error **errp) 85 { 86 QCryptoBlock *block = g_new0(QCryptoBlock, 1); 87 88 block->format = options->format; 89 90 if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) || 91 !qcrypto_block_drivers[options->format]) { 92 error_setg(errp, "Unsupported block driver %s", 93 QCryptoBlockFormat_lookup[options->format]); 94 g_free(block); 95 return NULL; 96 } 97 98 block->driver = qcrypto_block_drivers[options->format]; 99 100 if (block->driver->create(block, options, initfunc, 101 writefunc, opaque, errp) < 0) { 102 g_free(block); 103 return NULL; 104 } 105 106 return block; 107 } 108 109 110 QCryptoBlockInfo *qcrypto_block_get_info(QCryptoBlock *block, 111 Error **errp) 112 { 113 QCryptoBlockInfo *info = g_new0(QCryptoBlockInfo, 1); 114 115 info->format = block->format; 116 117 if (block->driver->get_info && 118 block->driver->get_info(block, info, errp) < 0) { 119 g_free(info); 120 return NULL; 121 } 122 123 return info; 124 } 125 126 127 int qcrypto_block_decrypt(QCryptoBlock *block, 128 uint64_t startsector, 129 uint8_t *buf, 130 size_t len, 131 Error **errp) 132 { 133 return block->driver->decrypt(block, startsector, buf, len, errp); 134 } 135 136 137 int qcrypto_block_encrypt(QCryptoBlock *block, 138 uint64_t startsector, 139 uint8_t *buf, 140 size_t len, 141 Error **errp) 142 { 143 return block->driver->encrypt(block, startsector, buf, len, errp); 144 } 145 146 147 QCryptoCipher *qcrypto_block_get_cipher(QCryptoBlock *block) 148 { 149 return block->cipher; 150 } 151 152 153 QCryptoIVGen *qcrypto_block_get_ivgen(QCryptoBlock *block) 154 { 155 return block->ivgen; 156 } 157 158 159 QCryptoHashAlgorithm qcrypto_block_get_kdf_hash(QCryptoBlock *block) 160 { 161 return block->kdfhash; 162 } 163 164 165 uint64_t qcrypto_block_get_payload_offset(QCryptoBlock *block) 166 { 167 return block->payload_offset; 168 } 169 170 171 void qcrypto_block_free(QCryptoBlock *block) 172 { 173 if (!block) { 174 return; 175 } 176 177 block->driver->cleanup(block); 178 179 qcrypto_cipher_free(block->cipher); 180 qcrypto_ivgen_free(block->ivgen); 181 g_free(block); 182 } 183 184 185 int qcrypto_block_decrypt_helper(QCryptoCipher *cipher, 186 size_t niv, 187 QCryptoIVGen *ivgen, 188 int sectorsize, 189 uint64_t startsector, 190 uint8_t *buf, 191 size_t len, 192 Error **errp) 193 { 194 uint8_t *iv; 195 int ret = -1; 196 197 iv = niv ? g_new0(uint8_t, niv) : NULL; 198 199 while (len > 0) { 200 size_t nbytes; 201 if (niv) { 202 if (qcrypto_ivgen_calculate(ivgen, 203 startsector, 204 iv, niv, 205 errp) < 0) { 206 goto cleanup; 207 } 208 209 if (qcrypto_cipher_setiv(cipher, 210 iv, niv, 211 errp) < 0) { 212 goto cleanup; 213 } 214 } 215 216 nbytes = len > sectorsize ? sectorsize : len; 217 if (qcrypto_cipher_decrypt(cipher, buf, buf, 218 nbytes, errp) < 0) { 219 goto cleanup; 220 } 221 222 startsector++; 223 buf += nbytes; 224 len -= nbytes; 225 } 226 227 ret = 0; 228 cleanup: 229 g_free(iv); 230 return ret; 231 } 232 233 234 int qcrypto_block_encrypt_helper(QCryptoCipher *cipher, 235 size_t niv, 236 QCryptoIVGen *ivgen, 237 int sectorsize, 238 uint64_t startsector, 239 uint8_t *buf, 240 size_t len, 241 Error **errp) 242 { 243 uint8_t *iv; 244 int ret = -1; 245 246 iv = niv ? g_new0(uint8_t, niv) : NULL; 247 248 while (len > 0) { 249 size_t nbytes; 250 if (niv) { 251 if (qcrypto_ivgen_calculate(ivgen, 252 startsector, 253 iv, niv, 254 errp) < 0) { 255 goto cleanup; 256 } 257 258 if (qcrypto_cipher_setiv(cipher, 259 iv, niv, 260 errp) < 0) { 261 goto cleanup; 262 } 263 } 264 265 nbytes = len > sectorsize ? sectorsize : len; 266 if (qcrypto_cipher_encrypt(cipher, buf, buf, 267 nbytes, errp) < 0) { 268 goto cleanup; 269 } 270 271 startsector++; 272 buf += nbytes; 273 len -= nbytes; 274 } 275 276 ret = 0; 277 cleanup: 278 g_free(iv); 279 return ret; 280 } 281