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 %d", options->format); 63 g_free(block); 64 return NULL; 65 } 66 67 block->driver = qcrypto_block_drivers[options->format]; 68 69 if (block->driver->open(block, options, 70 readfunc, opaque, flags, errp) < 0) { 71 g_free(block); 72 return NULL; 73 } 74 75 return block; 76 } 77 78 79 QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options, 80 QCryptoBlockInitFunc initfunc, 81 QCryptoBlockWriteFunc writefunc, 82 void *opaque, 83 Error **errp) 84 { 85 QCryptoBlock *block = g_new0(QCryptoBlock, 1); 86 87 block->format = options->format; 88 89 if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) || 90 !qcrypto_block_drivers[options->format]) { 91 error_setg(errp, "Unsupported block driver %d", options->format); 92 g_free(block); 93 return NULL; 94 } 95 96 block->driver = qcrypto_block_drivers[options->format]; 97 98 if (block->driver->create(block, options, initfunc, 99 writefunc, opaque, errp) < 0) { 100 g_free(block); 101 return NULL; 102 } 103 104 return block; 105 } 106 107 108 QCryptoBlockInfo *qcrypto_block_get_info(QCryptoBlock *block, 109 Error **errp) 110 { 111 QCryptoBlockInfo *info = g_new0(QCryptoBlockInfo, 1); 112 113 info->format = block->format; 114 115 if (block->driver->get_info && 116 block->driver->get_info(block, info, errp) < 0) { 117 g_free(info); 118 return NULL; 119 } 120 121 return info; 122 } 123 124 125 int qcrypto_block_decrypt(QCryptoBlock *block, 126 uint64_t startsector, 127 uint8_t *buf, 128 size_t len, 129 Error **errp) 130 { 131 return block->driver->decrypt(block, startsector, buf, len, errp); 132 } 133 134 135 int qcrypto_block_encrypt(QCryptoBlock *block, 136 uint64_t startsector, 137 uint8_t *buf, 138 size_t len, 139 Error **errp) 140 { 141 return block->driver->encrypt(block, startsector, buf, len, errp); 142 } 143 144 145 QCryptoCipher *qcrypto_block_get_cipher(QCryptoBlock *block) 146 { 147 return block->cipher; 148 } 149 150 151 QCryptoIVGen *qcrypto_block_get_ivgen(QCryptoBlock *block) 152 { 153 return block->ivgen; 154 } 155 156 157 QCryptoHashAlgorithm qcrypto_block_get_kdf_hash(QCryptoBlock *block) 158 { 159 return block->kdfhash; 160 } 161 162 163 uint64_t qcrypto_block_get_payload_offset(QCryptoBlock *block) 164 { 165 return block->payload_offset; 166 } 167 168 169 void qcrypto_block_free(QCryptoBlock *block) 170 { 171 if (!block) { 172 return; 173 } 174 175 block->driver->cleanup(block); 176 177 qcrypto_cipher_free(block->cipher); 178 qcrypto_ivgen_free(block->ivgen); 179 g_free(block); 180 } 181 182 183 int qcrypto_block_decrypt_helper(QCryptoCipher *cipher, 184 size_t niv, 185 QCryptoIVGen *ivgen, 186 int sectorsize, 187 uint64_t startsector, 188 uint8_t *buf, 189 size_t len, 190 Error **errp) 191 { 192 uint8_t *iv; 193 int ret = -1; 194 195 iv = niv ? g_new0(uint8_t, niv) : NULL; 196 197 while (len > 0) { 198 size_t nbytes; 199 if (niv) { 200 if (qcrypto_ivgen_calculate(ivgen, 201 startsector, 202 iv, niv, 203 errp) < 0) { 204 goto cleanup; 205 } 206 207 if (qcrypto_cipher_setiv(cipher, 208 iv, niv, 209 errp) < 0) { 210 goto cleanup; 211 } 212 } 213 214 nbytes = len > sectorsize ? sectorsize : len; 215 if (qcrypto_cipher_decrypt(cipher, buf, buf, 216 nbytes, errp) < 0) { 217 goto cleanup; 218 } 219 220 startsector++; 221 buf += nbytes; 222 len -= nbytes; 223 } 224 225 ret = 0; 226 cleanup: 227 g_free(iv); 228 return ret; 229 } 230 231 232 int qcrypto_block_encrypt_helper(QCryptoCipher *cipher, 233 size_t niv, 234 QCryptoIVGen *ivgen, 235 int sectorsize, 236 uint64_t startsector, 237 uint8_t *buf, 238 size_t len, 239 Error **errp) 240 { 241 uint8_t *iv; 242 int ret = -1; 243 244 iv = niv ? g_new0(uint8_t, niv) : NULL; 245 246 while (len > 0) { 247 size_t nbytes; 248 if (niv) { 249 if (qcrypto_ivgen_calculate(ivgen, 250 startsector, 251 iv, niv, 252 errp) < 0) { 253 goto cleanup; 254 } 255 256 if (qcrypto_cipher_setiv(cipher, 257 iv, niv, 258 errp) < 0) { 259 goto cleanup; 260 } 261 } 262 263 nbytes = len > sectorsize ? sectorsize : len; 264 if (qcrypto_cipher_encrypt(cipher, buf, buf, 265 nbytes, errp) < 0) { 266 goto cleanup; 267 } 268 269 startsector++; 270 buf += nbytes; 271 len -= nbytes; 272 } 273 274 ret = 0; 275 cleanup: 276 g_free(iv); 277 return ret; 278 } 279