xref: /openbmc/qemu/include/crypto/ivgen.h (revision 7f709ce7)
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 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 
98 typedef 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  */
136 QCryptoIVGen *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  */
156 int 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  */
170 QCryptoIVGenAlgorithm 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  */
182 QCryptoCipherAlgorithm 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  */
194 QCryptoHashAlgorithm 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  */
204 void qcrypto_ivgen_free(QCryptoIVGen *ivgen);
205 
206 #endif /* QCRYPTO_IVGEN_H */
207