xref: /openbmc/qemu/include/crypto/ivgen.h (revision b8eada54b2ad8a7d98d93d5ab4d3e888c5880097)
1cb730894SDaniel P. Berrange /*
2cb730894SDaniel P. Berrange  * QEMU Crypto block IV generator
3cb730894SDaniel P. Berrange  *
4cb730894SDaniel P. Berrange  * Copyright (c) 2015-2016 Red Hat, Inc.
5cb730894SDaniel P. Berrange  *
6cb730894SDaniel P. Berrange  * This library is free software; you can redistribute it and/or
7cb730894SDaniel P. Berrange  * modify it under the terms of the GNU Lesser General Public
8cb730894SDaniel P. Berrange  * License as published by the Free Software Foundation; either
9b7cbb874SThomas Huth  * version 2.1 of the License, or (at your option) any later version.
10cb730894SDaniel P. Berrange  *
11cb730894SDaniel P. Berrange  * This library is distributed in the hope that it will be useful,
12cb730894SDaniel P. Berrange  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13cb730894SDaniel P. Berrange  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14cb730894SDaniel P. Berrange  * Lesser General Public License for more details.
15cb730894SDaniel P. Berrange  *
16cb730894SDaniel P. Berrange  * You should have received a copy of the GNU Lesser General Public
17cb730894SDaniel P. Berrange  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18cb730894SDaniel P. Berrange  *
19cb730894SDaniel P. Berrange  */
20cb730894SDaniel P. Berrange 
212a6a4076SMarkus Armbruster #ifndef QCRYPTO_IVGEN_H
222a6a4076SMarkus Armbruster #define QCRYPTO_IVGEN_H
23cb730894SDaniel P. Berrange 
24cb730894SDaniel P. Berrange #include "crypto/cipher.h"
25cb730894SDaniel P. Berrange #include "crypto/hash.h"
26cb730894SDaniel P. Berrange 
27cb730894SDaniel P. Berrange /**
28cb730894SDaniel P. Berrange  * This module provides a framework for generating initialization
29cb730894SDaniel P. Berrange  * vectors for block encryption schemes using chained cipher modes
30cb730894SDaniel P. Berrange  * CBC. The principle is that each disk sector is assigned a unique
31cb730894SDaniel P. Berrange  * initialization vector for use for encryption of data in that
32cb730894SDaniel P. Berrange  * sector.
33cb730894SDaniel P. Berrange  *
34cb730894SDaniel P. Berrange  * <example>
35a1a62cedSMichael Tokarev  *   <title>Encrypting block data with initialization vectors</title>
36cb730894SDaniel P. Berrange  *   <programlisting>
37cb730894SDaniel P. Berrange  * uint8_t *data = ....data to encrypt...
38cb730894SDaniel P. Berrange  * size_t ndata = XXX;
39cb730894SDaniel P. Berrange  * uint8_t *key = ....some encryption key...
40cb730894SDaniel P. Berrange  * size_t nkey = XXX;
41cb730894SDaniel P. Berrange  * uint8_t *iv;
42cb730894SDaniel P. Berrange  * size_t niv;
43cb730894SDaniel P. Berrange  * size_t sector = 0;
44cb730894SDaniel P. Berrange  *
45cb730894SDaniel P. Berrange  * g_assert((ndata % 512) == 0);
46cb730894SDaniel P. Berrange  *
47*5e0e5102SMarkus Armbruster  * QCryptoIVGen *ivgen = qcrypto_ivgen_new(QCRYPTO_IV_GEN_ALGO_ESSIV,
48a092c513SMarkus Armbruster  *                                         QCRYPTO_CIPHER_ALGO_AES_128,
49ef834aa2SMarkus Armbruster  *                                         QCRYPTO_HASH_ALGO_SHA256,
50cb730894SDaniel P. Berrange  *                                         key, nkey, errp);
51cb730894SDaniel P. Berrange  * if (!ivgen) {
52cb730894SDaniel P. Berrange  *    return -1;
53cb730894SDaniel P. Berrange  * }
54cb730894SDaniel P. Berrange  *
55a092c513SMarkus Armbruster  * QCryptoCipher *cipher = qcrypto_cipher_new(QCRYPTO_CIPHER_ALGO_AES_128,
56cb730894SDaniel P. Berrange  *                                            QCRYPTO_CIPHER_MODE_CBC,
57cb730894SDaniel P. Berrange  *                                            key, nkey, errp);
58cb730894SDaniel P. Berrange  * if (!cipher) {
59cb730894SDaniel P. Berrange  *     goto error;
60cb730894SDaniel P. Berrange  * }
61cb730894SDaniel P. Berrange  *
62a092c513SMarkus Armbruster  * niv =  qcrypto_cipher_get_iv_len(QCRYPTO_CIPHER_ALGO_AES_128,
63cb730894SDaniel P. Berrange  *                                  QCRYPTO_CIPHER_MODE_CBC);
64cb730894SDaniel P. Berrange  * iv = g_new0(uint8_t, niv);
65cb730894SDaniel P. Berrange  *
66cb730894SDaniel P. Berrange  *
67cb730894SDaniel P. Berrange  * while (ndata) {
68cb730894SDaniel P. Berrange  *     if (qcrypto_ivgen_calculate(ivgen, sector, iv, niv, errp) < 0) {
69cb730894SDaniel P. Berrange  *         goto error;
70cb730894SDaniel P. Berrange  *     }
71cb730894SDaniel P. Berrange  *     if (qcrypto_cipher_setiv(cipher, iv, niv, errp) < 0) {
72cb730894SDaniel P. Berrange  *         goto error;
73cb730894SDaniel P. Berrange  *     }
74cb730894SDaniel P. Berrange  *     if (qcrypto_cipher_encrypt(cipher,
75cb730894SDaniel P. Berrange  *                                data + (sector * 512),
76cb730894SDaniel P. Berrange  *                                data + (sector * 512),
77cb730894SDaniel P. Berrange  *                                512, errp) < 0) {
78cb730894SDaniel P. Berrange  *         goto error;
79cb730894SDaniel P. Berrange  *     }
80cb730894SDaniel P. Berrange  *     sector++;
81cb730894SDaniel P. Berrange  *     ndata -= 512;
82cb730894SDaniel P. Berrange  * }
83cb730894SDaniel P. Berrange  *
84cb730894SDaniel P. Berrange  * g_free(iv);
85cb730894SDaniel P. Berrange  * qcrypto_ivgen_free(ivgen);
86cb730894SDaniel P. Berrange  * qcrypto_cipher_free(cipher);
87cb730894SDaniel P. Berrange  * return 0;
88cb730894SDaniel P. Berrange  *
89cb730894SDaniel P. Berrange  *error:
90cb730894SDaniel P. Berrange  * g_free(iv);
91cb730894SDaniel P. Berrange  * qcrypto_ivgen_free(ivgen);
92cb730894SDaniel P. Berrange  * qcrypto_cipher_free(cipher);
93cb730894SDaniel P. Berrange  * return -1;
94cb730894SDaniel P. Berrange  *   </programlisting>
95cb730894SDaniel P. Berrange  * </example>
96cb730894SDaniel P. Berrange  */
97cb730894SDaniel P. Berrange 
98cb730894SDaniel P. Berrange typedef struct QCryptoIVGen QCryptoIVGen;
99cb730894SDaniel P. Berrange 
100*5e0e5102SMarkus Armbruster /* See also QCryptoIVGenAlgo enum in qapi/crypto.json */
101cb730894SDaniel P. Berrange 
102cb730894SDaniel P. Berrange 
103cb730894SDaniel P. Berrange /**
104cb730894SDaniel P. Berrange  * qcrypto_ivgen_new:
105cb730894SDaniel P. Berrange  * @alg: the initialization vector generation algorithm
106cb730894SDaniel P. Berrange  * @cipheralg: the cipher algorithm or 0
107cb730894SDaniel P. Berrange  * @hash: the hash algorithm or 0
108cb730894SDaniel P. Berrange  * @key: the encryption key or NULL
109cb730894SDaniel P. Berrange  * @nkey: the size of @key in bytes
110cb730894SDaniel P. Berrange  *
111cb730894SDaniel P. Berrange  * Create a new initialization vector generator that uses
112cb730894SDaniel P. Berrange  * the algorithm @alg. Whether the remaining parameters
113cb730894SDaniel P. Berrange  * are required or not depends on the choice of @alg
114cb730894SDaniel P. Berrange  * requested.
115cb730894SDaniel P. Berrange  *
116*5e0e5102SMarkus Armbruster  * - QCRYPTO_IV_GEN_ALGO_PLAIN
117cb730894SDaniel P. Berrange  *
118cb730894SDaniel P. Berrange  * The IVs are generated by the 32-bit truncated sector
119cb730894SDaniel P. Berrange  * number. This should never be used for block devices
120cb730894SDaniel P. Berrange  * that are larger than 2^32 sectors in size.
121cb730894SDaniel P. Berrange  * All the other parameters are unused.
122cb730894SDaniel P. Berrange  *
123*5e0e5102SMarkus Armbruster  * - QCRYPTO_IV_GEN_ALGO_PLAIN64
124cb730894SDaniel P. Berrange  *
125cb730894SDaniel P. Berrange  * The IVs are generated by the 64-bit sector number.
126cb730894SDaniel P. Berrange  * All the other parameters are unused.
127cb730894SDaniel P. Berrange  *
128*5e0e5102SMarkus Armbruster  * - QCRYPTO_IV_GEN_ALGO_ESSIV:
129cb730894SDaniel P. Berrange  *
130cb730894SDaniel P. Berrange  * The IVs are generated by encrypting the 64-bit sector
131cb730894SDaniel P. Berrange  * number with a hash of an encryption key. The @cipheralg,
132cb730894SDaniel P. Berrange  * @hash, @key and @nkey parameters are all required.
133cb730894SDaniel P. Berrange  *
134cb730894SDaniel P. Berrange  * Returns: a new IV generator, or NULL on error
135cb730894SDaniel P. Berrange  */
136*5e0e5102SMarkus Armbruster QCryptoIVGen *qcrypto_ivgen_new(QCryptoIVGenAlgo alg,
137a092c513SMarkus Armbruster                                 QCryptoCipherAlgo cipheralg,
138ef834aa2SMarkus Armbruster                                 QCryptoHashAlgo hash,
139cb730894SDaniel P. Berrange                                 const uint8_t *key, size_t nkey,
140cb730894SDaniel P. Berrange                                 Error **errp);
141cb730894SDaniel P. Berrange 
142cb730894SDaniel P. Berrange /**
143cb730894SDaniel P. Berrange  * qcrypto_ivgen_calculate:
144cb730894SDaniel P. Berrange  * @ivgen: the IV generator object
145cb730894SDaniel P. Berrange  * @sector: the 64-bit sector number
146cb730894SDaniel P. Berrange  * @iv: a pre-allocated buffer to hold the generated IV
147cb730894SDaniel P. Berrange  * @niv: the number of bytes in @iv
148cb730894SDaniel P. Berrange  * @errp: pointer to a NULL-initialized error object
149cb730894SDaniel P. Berrange  *
150a1a62cedSMichael Tokarev  * Calculate a new initialization vector for the data
151cb730894SDaniel P. Berrange  * to be stored in sector @sector. The IV will be
152cb730894SDaniel P. Berrange  * written into the buffer @iv of size @niv.
153cb730894SDaniel P. Berrange  *
154cb730894SDaniel P. Berrange  * Returns: 0 on success, -1 on error
155cb730894SDaniel P. Berrange  */
156cb730894SDaniel P. Berrange int qcrypto_ivgen_calculate(QCryptoIVGen *ivgen,
157cb730894SDaniel P. Berrange                             uint64_t sector,
158cb730894SDaniel P. Berrange                             uint8_t *iv, size_t niv,
159cb730894SDaniel P. Berrange                             Error **errp);
160cb730894SDaniel P. Berrange 
161cb730894SDaniel P. Berrange 
162cb730894SDaniel P. Berrange /**
163cb730894SDaniel P. Berrange  * qcrypto_ivgen_get_algorithm:
164cb730894SDaniel P. Berrange  * @ivgen: the IV generator object
165cb730894SDaniel P. Berrange  *
166cb730894SDaniel P. Berrange  * Get the algorithm used by this IV generator
167cb730894SDaniel P. Berrange  *
168cb730894SDaniel P. Berrange  * Returns: the IV generator algorithm
169cb730894SDaniel P. Berrange  */
170*5e0e5102SMarkus Armbruster QCryptoIVGenAlgo qcrypto_ivgen_get_algorithm(QCryptoIVGen *ivgen);
171cb730894SDaniel P. Berrange 
172cb730894SDaniel P. Berrange 
173cb730894SDaniel P. Berrange /**
174cb730894SDaniel P. Berrange  * qcrypto_ivgen_get_cipher:
175cb730894SDaniel P. Berrange  * @ivgen: the IV generator object
176cb730894SDaniel P. Berrange  *
177cb730894SDaniel P. Berrange  * Get the cipher algorithm used by this IV generator (if
178cb730894SDaniel P. Berrange  * applicable)
179cb730894SDaniel P. Berrange  *
180cb730894SDaniel P. Berrange  * Returns: the cipher algorithm
181cb730894SDaniel P. Berrange  */
182a092c513SMarkus Armbruster QCryptoCipherAlgo qcrypto_ivgen_get_cipher(QCryptoIVGen *ivgen);
183cb730894SDaniel P. Berrange 
184cb730894SDaniel P. Berrange 
185cb730894SDaniel P. Berrange /**
186cb730894SDaniel P. Berrange  * qcrypto_ivgen_get_hash:
187cb730894SDaniel P. Berrange  * @ivgen: the IV generator object
188cb730894SDaniel P. Berrange  *
189cb730894SDaniel P. Berrange  * Get the hash algorithm used by this IV generator (if
190cb730894SDaniel P. Berrange  * applicable)
191cb730894SDaniel P. Berrange  *
192cb730894SDaniel P. Berrange  * Returns: the hash algorithm
193cb730894SDaniel P. Berrange  */
194ef834aa2SMarkus Armbruster QCryptoHashAlgo qcrypto_ivgen_get_hash(QCryptoIVGen *ivgen);
195cb730894SDaniel P. Berrange 
196cb730894SDaniel P. Berrange 
197cb730894SDaniel P. Berrange /**
198cb730894SDaniel P. Berrange  * qcrypto_ivgen_free:
199cb730894SDaniel P. Berrange  * @ivgen: the IV generator object
200cb730894SDaniel P. Berrange  *
201cb730894SDaniel P. Berrange  * Release all resources associated with @ivgen, or a no-op
202cb730894SDaniel P. Berrange  * if @ivgen is NULL
203cb730894SDaniel P. Berrange  */
204cb730894SDaniel P. Berrange void qcrypto_ivgen_free(QCryptoIVGen *ivgen);
205cb730894SDaniel P. Berrange 
206133cf1e5SDaniel P. Berrangé G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoIVGen, qcrypto_ivgen_free)
207133cf1e5SDaniel P. Berrangé 
2082a6a4076SMarkus Armbruster #endif /* QCRYPTO_IVGEN_H */
209