qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

block.c (14424B)


      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.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 #include "qemu/osdep.h"
     22 #include "qapi/error.h"
     23 #include "blockpriv.h"
     24 #include "block-qcow.h"
     25 #include "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                                  const char *optprefix,
     52                                  QCryptoBlockReadFunc readfunc,
     53                                  void *opaque,
     54                                  unsigned int flags,
     55                                  size_t n_threads,
     56                                  Error **errp)
     57 {
     58     QCryptoBlock *block = g_new0(QCryptoBlock, 1);
     59 
     60     block->format = options->format;
     61 
     62     if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
     63         !qcrypto_block_drivers[options->format]) {
     64         error_setg(errp, "Unsupported block driver %s",
     65                    QCryptoBlockFormat_str(options->format));
     66         g_free(block);
     67         return NULL;
     68     }
     69 
     70     block->driver = qcrypto_block_drivers[options->format];
     71 
     72     if (block->driver->open(block, options, optprefix,
     73                             readfunc, opaque, flags, n_threads, errp) < 0)
     74     {
     75         g_free(block);
     76         return NULL;
     77     }
     78 
     79     qemu_mutex_init(&block->mutex);
     80 
     81     return block;
     82 }
     83 
     84 
     85 QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
     86                                    const char *optprefix,
     87                                    QCryptoBlockInitFunc initfunc,
     88                                    QCryptoBlockWriteFunc writefunc,
     89                                    void *opaque,
     90                                    Error **errp)
     91 {
     92     QCryptoBlock *block = g_new0(QCryptoBlock, 1);
     93 
     94     block->format = options->format;
     95 
     96     if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
     97         !qcrypto_block_drivers[options->format]) {
     98         error_setg(errp, "Unsupported block driver %s",
     99                    QCryptoBlockFormat_str(options->format));
    100         g_free(block);
    101         return NULL;
    102     }
    103 
    104     block->driver = qcrypto_block_drivers[options->format];
    105 
    106     if (block->driver->create(block, options, optprefix, initfunc,
    107                               writefunc, opaque, errp) < 0) {
    108         g_free(block);
    109         return NULL;
    110     }
    111 
    112     qemu_mutex_init(&block->mutex);
    113 
    114     return block;
    115 }
    116 
    117 
    118 static int qcrypto_block_headerlen_hdr_init_func(QCryptoBlock *block,
    119         size_t headerlen, void *opaque, Error **errp)
    120 {
    121     size_t *headerlenp = opaque;
    122 
    123     /* Stash away the payload size */
    124     *headerlenp = headerlen;
    125     return 0;
    126 }
    127 
    128 
    129 static int qcrypto_block_headerlen_hdr_write_func(QCryptoBlock *block,
    130         size_t offset, const uint8_t *buf, size_t buflen,
    131         void *opaque, Error **errp)
    132 {
    133     /* Discard the bytes, we're not actually writing to an image */
    134     return 0;
    135 }
    136 
    137 
    138 bool
    139 qcrypto_block_calculate_payload_offset(QCryptoBlockCreateOptions *create_opts,
    140                                        const char *optprefix,
    141                                        size_t *len,
    142                                        Error **errp)
    143 {
    144     /* Fake LUKS creation in order to determine the payload size */
    145     g_autoptr(QCryptoBlock) crypto =
    146         qcrypto_block_create(create_opts, optprefix,
    147                              qcrypto_block_headerlen_hdr_init_func,
    148                              qcrypto_block_headerlen_hdr_write_func,
    149                              len, errp);
    150     return crypto != NULL;
    151 }
    152 
    153 int qcrypto_block_amend_options(QCryptoBlock *block,
    154                                 QCryptoBlockReadFunc readfunc,
    155                                 QCryptoBlockWriteFunc writefunc,
    156                                 void *opaque,
    157                                 QCryptoBlockAmendOptions *options,
    158                                 bool force,
    159                                 Error **errp)
    160 {
    161     if (options->format != block->format) {
    162         error_setg(errp,
    163                    "Cannot amend encryption format");
    164         return -1;
    165     }
    166 
    167     if (!block->driver->amend) {
    168         error_setg(errp,
    169                    "Crypto format %s doesn't support format options amendment",
    170                    QCryptoBlockFormat_str(block->format));
    171         return -1;
    172     }
    173 
    174     return block->driver->amend(block,
    175                                 readfunc,
    176                                 writefunc,
    177                                 opaque,
    178                                 options,
    179                                 force,
    180                                 errp);
    181 }
    182 
    183 QCryptoBlockInfo *qcrypto_block_get_info(QCryptoBlock *block,
    184                                          Error **errp)
    185 {
    186     QCryptoBlockInfo *info = g_new0(QCryptoBlockInfo, 1);
    187 
    188     info->format = block->format;
    189 
    190     if (block->driver->get_info &&
    191         block->driver->get_info(block, info, errp) < 0) {
    192         g_free(info);
    193         return NULL;
    194     }
    195 
    196     return info;
    197 }
    198 
    199 
    200 int qcrypto_block_decrypt(QCryptoBlock *block,
    201                           uint64_t offset,
    202                           uint8_t *buf,
    203                           size_t len,
    204                           Error **errp)
    205 {
    206     return block->driver->decrypt(block, offset, buf, len, errp);
    207 }
    208 
    209 
    210 int qcrypto_block_encrypt(QCryptoBlock *block,
    211                           uint64_t offset,
    212                           uint8_t *buf,
    213                           size_t len,
    214                           Error **errp)
    215 {
    216     return block->driver->encrypt(block, offset, buf, len, errp);
    217 }
    218 
    219 
    220 QCryptoCipher *qcrypto_block_get_cipher(QCryptoBlock *block)
    221 {
    222     /* Ciphers should be accessed through pop/push method to be thread-safe.
    223      * Better, they should not be accessed externally at all (note, that
    224      * pop/push are static functions)
    225      * This function is used only in test with one thread (it's safe to skip
    226      * pop/push interface), so it's enough to assert it here:
    227      */
    228     assert(block->n_ciphers <= 1);
    229     return block->ciphers ? block->ciphers[0] : NULL;
    230 }
    231 
    232 
    233 static QCryptoCipher *qcrypto_block_pop_cipher(QCryptoBlock *block)
    234 {
    235     QCryptoCipher *cipher;
    236 
    237     qemu_mutex_lock(&block->mutex);
    238 
    239     assert(block->n_free_ciphers > 0);
    240     block->n_free_ciphers--;
    241     cipher = block->ciphers[block->n_free_ciphers];
    242 
    243     qemu_mutex_unlock(&block->mutex);
    244 
    245     return cipher;
    246 }
    247 
    248 
    249 static void qcrypto_block_push_cipher(QCryptoBlock *block,
    250                                       QCryptoCipher *cipher)
    251 {
    252     qemu_mutex_lock(&block->mutex);
    253 
    254     assert(block->n_free_ciphers < block->n_ciphers);
    255     block->ciphers[block->n_free_ciphers] = cipher;
    256     block->n_free_ciphers++;
    257 
    258     qemu_mutex_unlock(&block->mutex);
    259 }
    260 
    261 
    262 int qcrypto_block_init_cipher(QCryptoBlock *block,
    263                               QCryptoCipherAlgorithm alg,
    264                               QCryptoCipherMode mode,
    265                               const uint8_t *key, size_t nkey,
    266                               size_t n_threads, Error **errp)
    267 {
    268     size_t i;
    269 
    270     assert(!block->ciphers && !block->n_ciphers && !block->n_free_ciphers);
    271 
    272     block->ciphers = g_new0(QCryptoCipher *, n_threads);
    273 
    274     for (i = 0; i < n_threads; i++) {
    275         block->ciphers[i] = qcrypto_cipher_new(alg, mode, key, nkey, errp);
    276         if (!block->ciphers[i]) {
    277             qcrypto_block_free_cipher(block);
    278             return -1;
    279         }
    280         block->n_ciphers++;
    281         block->n_free_ciphers++;
    282     }
    283 
    284     return 0;
    285 }
    286 
    287 
    288 void qcrypto_block_free_cipher(QCryptoBlock *block)
    289 {
    290     size_t i;
    291 
    292     if (!block->ciphers) {
    293         return;
    294     }
    295 
    296     assert(block->n_ciphers == block->n_free_ciphers);
    297 
    298     for (i = 0; i < block->n_ciphers; i++) {
    299         qcrypto_cipher_free(block->ciphers[i]);
    300     }
    301 
    302     g_free(block->ciphers);
    303     block->ciphers = NULL;
    304     block->n_ciphers = block->n_free_ciphers = 0;
    305 }
    306 
    307 QCryptoIVGen *qcrypto_block_get_ivgen(QCryptoBlock *block)
    308 {
    309     /* ivgen should be accessed under mutex. However, this function is used only
    310      * in test with one thread, so it's enough to assert it here:
    311      */
    312     assert(block->n_ciphers <= 1);
    313     return block->ivgen;
    314 }
    315 
    316 
    317 QCryptoHashAlgorithm qcrypto_block_get_kdf_hash(QCryptoBlock *block)
    318 {
    319     return block->kdfhash;
    320 }
    321 
    322 
    323 uint64_t qcrypto_block_get_payload_offset(QCryptoBlock *block)
    324 {
    325     return block->payload_offset;
    326 }
    327 
    328 
    329 uint64_t qcrypto_block_get_sector_size(QCryptoBlock *block)
    330 {
    331     return block->sector_size;
    332 }
    333 
    334 
    335 void qcrypto_block_free(QCryptoBlock *block)
    336 {
    337     if (!block) {
    338         return;
    339     }
    340 
    341     block->driver->cleanup(block);
    342 
    343     qcrypto_block_free_cipher(block);
    344     qcrypto_ivgen_free(block->ivgen);
    345     qemu_mutex_destroy(&block->mutex);
    346     g_free(block);
    347 }
    348 
    349 
    350 typedef int (*QCryptoCipherEncDecFunc)(QCryptoCipher *cipher,
    351                                         const void *in,
    352                                         void *out,
    353                                         size_t len,
    354                                         Error **errp);
    355 
    356 static int do_qcrypto_block_cipher_encdec(QCryptoCipher *cipher,
    357                                           size_t niv,
    358                                           QCryptoIVGen *ivgen,
    359                                           QemuMutex *ivgen_mutex,
    360                                           int sectorsize,
    361                                           uint64_t offset,
    362                                           uint8_t *buf,
    363                                           size_t len,
    364                                           QCryptoCipherEncDecFunc func,
    365                                           Error **errp)
    366 {
    367     g_autofree uint8_t *iv = niv ? g_new0(uint8_t, niv) : NULL;
    368     int ret = -1;
    369     uint64_t startsector = offset / sectorsize;
    370 
    371     assert(QEMU_IS_ALIGNED(offset, sectorsize));
    372     assert(QEMU_IS_ALIGNED(len, sectorsize));
    373 
    374     while (len > 0) {
    375         size_t nbytes;
    376         if (niv) {
    377             if (ivgen_mutex) {
    378                 qemu_mutex_lock(ivgen_mutex);
    379             }
    380             ret = qcrypto_ivgen_calculate(ivgen, startsector, iv, niv, errp);
    381             if (ivgen_mutex) {
    382                 qemu_mutex_unlock(ivgen_mutex);
    383             }
    384 
    385             if (ret < 0) {
    386                 return -1;
    387             }
    388 
    389             if (qcrypto_cipher_setiv(cipher,
    390                                      iv, niv,
    391                                      errp) < 0) {
    392                 return -1;
    393             }
    394         }
    395 
    396         nbytes = len > sectorsize ? sectorsize : len;
    397         if (func(cipher, buf, buf, nbytes, errp) < 0) {
    398             return -1;
    399         }
    400 
    401         startsector++;
    402         buf += nbytes;
    403         len -= nbytes;
    404     }
    405 
    406     return 0;
    407 }
    408 
    409 
    410 int qcrypto_block_cipher_decrypt_helper(QCryptoCipher *cipher,
    411                                         size_t niv,
    412                                         QCryptoIVGen *ivgen,
    413                                         int sectorsize,
    414                                         uint64_t offset,
    415                                         uint8_t *buf,
    416                                         size_t len,
    417                                         Error **errp)
    418 {
    419     return do_qcrypto_block_cipher_encdec(cipher, niv, ivgen, NULL, sectorsize,
    420                                           offset, buf, len,
    421                                           qcrypto_cipher_decrypt, errp);
    422 }
    423 
    424 
    425 int qcrypto_block_cipher_encrypt_helper(QCryptoCipher *cipher,
    426                                         size_t niv,
    427                                         QCryptoIVGen *ivgen,
    428                                         int sectorsize,
    429                                         uint64_t offset,
    430                                         uint8_t *buf,
    431                                         size_t len,
    432                                         Error **errp)
    433 {
    434     return do_qcrypto_block_cipher_encdec(cipher, niv, ivgen, NULL, sectorsize,
    435                                           offset, buf, len,
    436                                           qcrypto_cipher_encrypt, errp);
    437 }
    438 
    439 int qcrypto_block_decrypt_helper(QCryptoBlock *block,
    440                                  int sectorsize,
    441                                  uint64_t offset,
    442                                  uint8_t *buf,
    443                                  size_t len,
    444                                  Error **errp)
    445 {
    446     int ret;
    447     QCryptoCipher *cipher = qcrypto_block_pop_cipher(block);
    448 
    449     ret = do_qcrypto_block_cipher_encdec(cipher, block->niv, block->ivgen,
    450                                          &block->mutex, sectorsize, offset, buf,
    451                                          len, qcrypto_cipher_decrypt, errp);
    452 
    453     qcrypto_block_push_cipher(block, cipher);
    454 
    455     return ret;
    456 }
    457 
    458 int qcrypto_block_encrypt_helper(QCryptoBlock *block,
    459                                  int sectorsize,
    460                                  uint64_t offset,
    461                                  uint8_t *buf,
    462                                  size_t len,
    463                                  Error **errp)
    464 {
    465     int ret;
    466     QCryptoCipher *cipher = qcrypto_block_pop_cipher(block);
    467 
    468     ret = do_qcrypto_block_cipher_encdec(cipher, block->niv, block->ivgen,
    469                                          &block->mutex, sectorsize, offset, buf,
    470                                          len, qcrypto_cipher_encrypt, errp);
    471 
    472     qcrypto_block_push_cipher(block, cipher);
    473 
    474     return ret;
    475 }