qemu/include/crypto/ivgen.h
<<
>>
Prefs
   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 initialiation 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_IVGEN_ALG_ESSIV,
  48 *                                         QCRYPTO_CIPHER_ALG_AES_128,
  49 *                                         QCRYPTO_HASH_ALG_SHA256,
  50 *                                         key, nkey, errp);
  51 * if (!ivgen) {
  52 *    return -1;
  53 * }
  54 *
  55 * QCryptoCipher *cipher = qcrypto_cipher_new(QCRYPTO_CIPHER_ALG_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_ALG_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
  98typedef struct QCryptoIVGen QCryptoIVGen;
  99
 100/* See also QCryptoIVGenAlgorithm 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_IVGEN_ALG_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_IVGEN_ALG_PLAIN64
 124 *
 125 * The IVs are generated by the 64-bit sector number.
 126 * All the other parameters are unused.
 127 *
 128 * - QCRYPTO_IVGEN_ALG_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 */
 136QCryptoIVGen *qcrypto_ivgen_new(QCryptoIVGenAlgorithm alg,
 137                                QCryptoCipherAlgorithm cipheralg,
 138                                QCryptoHashAlgorithm 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 initialiation 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 */
 156int 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 */
 170QCryptoIVGenAlgorithm 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 */
 182QCryptoCipherAlgorithm 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 */
 194QCryptoHashAlgorithm 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 */
 204void qcrypto_ivgen_free(QCryptoIVGen *ivgen);
 205
 206#endif /* QCRYPTO_IVGEN_H */
 207