Revision | d8d5fefd8657d4f7b380b3a1533340434b5b9def (tree) |
---|---|
Time | 2018-12-14 03:45:18 |
Author | Peter Maydell <peter.maydell@lina...> |
Commiter | Peter Maydell |
Merge remote-tracking branch 'remotes/berrange/tags/qcrypto-next-pull-request' into staging
Merge crypto patches 2018/12/12
# gpg: Signature made Wed 12 Dec 2018 11:21:52 GMT
# gpg: using RSA key BE86EBB415104FDF
# gpg: Good signature from "Daniel P. Berrange <dan@berrange.com>"
# gpg: aka "Daniel P. Berrange <berrange@redhat.com>"
# Primary key fingerprint: DAF3 A6FD B26B 6291 2D0E 8E3F BE86 EBB4 1510 4FDF
* remotes/berrange/tags/qcrypto-next-pull-request:
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
@@ -229,6 +229,7 @@ static int block_crypto_open_generic(QCryptoBlockFormat format, | ||
229 | 229 | block_crypto_read_func, |
230 | 230 | bs, |
231 | 231 | cflags, |
232 | + 1, | |
232 | 233 | errp); |
233 | 234 | |
234 | 235 | if (!crypto->block) { |
@@ -213,7 +213,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags, | ||
213 | 213 | cflags |= QCRYPTO_BLOCK_OPEN_NO_IO; |
214 | 214 | } |
215 | 215 | s->crypto = qcrypto_block_open(crypto_opts, "encrypt.", |
216 | - NULL, NULL, cflags, errp); | |
216 | + NULL, NULL, cflags, 1, errp); | |
217 | 217 | if (!s->crypto) { |
218 | 218 | ret = -EINVAL; |
219 | 219 | goto fail; |
@@ -294,7 +294,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset, | ||
294 | 294 | } |
295 | 295 | s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.", |
296 | 296 | qcow2_crypto_hdr_read_func, |
297 | - bs, cflags, errp); | |
297 | + bs, cflags, 1, errp); | |
298 | 298 | if (!s->crypto) { |
299 | 299 | return -EINVAL; |
300 | 300 | } |
@@ -1445,7 +1445,7 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, | ||
1445 | 1445 | cflags |= QCRYPTO_BLOCK_OPEN_NO_IO; |
1446 | 1446 | } |
1447 | 1447 | s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.", |
1448 | - NULL, NULL, cflags, errp); | |
1448 | + NULL, NULL, cflags, 1, errp); | |
1449 | 1449 | if (!s->crypto) { |
1450 | 1450 | ret = -EINVAL; |
1451 | 1451 | goto fail; |
@@ -504,14 +504,14 @@ qcrypto_block_luks_load_key(QCryptoBlock *block, | ||
504 | 504 | * to reset the encryption cipher every time the master |
505 | 505 | * key crosses a sector boundary. |
506 | 506 | */ |
507 | - if (qcrypto_block_decrypt_helper(cipher, | |
508 | - niv, | |
509 | - ivgen, | |
510 | - QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, | |
511 | - 0, | |
512 | - splitkey, | |
513 | - splitkeylen, | |
514 | - errp) < 0) { | |
507 | + if (qcrypto_block_cipher_decrypt_helper(cipher, | |
508 | + niv, | |
509 | + ivgen, | |
510 | + QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, | |
511 | + 0, | |
512 | + splitkey, | |
513 | + splitkeylen, | |
514 | + errp) < 0) { | |
515 | 515 | goto cleanup; |
516 | 516 | } |
517 | 517 |
@@ -636,6 +636,7 @@ qcrypto_block_luks_open(QCryptoBlock *block, | ||
636 | 636 | QCryptoBlockReadFunc readfunc, |
637 | 637 | void *opaque, |
638 | 638 | unsigned int flags, |
639 | + size_t n_threads, | |
639 | 640 | Error **errp) |
640 | 641 | { |
641 | 642 | QCryptoBlockLUKS *luks; |
@@ -836,11 +837,10 @@ qcrypto_block_luks_open(QCryptoBlock *block, | ||
836 | 837 | goto fail; |
837 | 838 | } |
838 | 839 | |
839 | - block->cipher = qcrypto_cipher_new(cipheralg, | |
840 | - ciphermode, | |
841 | - masterkey, masterkeylen, | |
842 | - errp); | |
843 | - if (!block->cipher) { | |
840 | + ret = qcrypto_block_init_cipher(block, cipheralg, ciphermode, | |
841 | + masterkey, masterkeylen, n_threads, | |
842 | + errp); | |
843 | + if (ret < 0) { | |
844 | 844 | ret = -ENOTSUP; |
845 | 845 | goto fail; |
846 | 846 | } |
@@ -863,7 +863,7 @@ qcrypto_block_luks_open(QCryptoBlock *block, | ||
863 | 863 | |
864 | 864 | fail: |
865 | 865 | g_free(masterkey); |
866 | - qcrypto_cipher_free(block->cipher); | |
866 | + qcrypto_block_free_cipher(block); | |
867 | 867 | qcrypto_ivgen_free(block->ivgen); |
868 | 868 | g_free(luks); |
869 | 869 | g_free(password); |
@@ -1030,11 +1030,9 @@ qcrypto_block_luks_create(QCryptoBlock *block, | ||
1030 | 1030 | |
1031 | 1031 | |
1032 | 1032 | /* Setup the block device payload encryption objects */ |
1033 | - block->cipher = qcrypto_cipher_new(luks_opts.cipher_alg, | |
1034 | - luks_opts.cipher_mode, | |
1035 | - masterkey, luks->header.key_bytes, | |
1036 | - errp); | |
1037 | - if (!block->cipher) { | |
1033 | + if (qcrypto_block_init_cipher(block, luks_opts.cipher_alg, | |
1034 | + luks_opts.cipher_mode, masterkey, | |
1035 | + luks->header.key_bytes, 1, errp) < 0) { | |
1038 | 1036 | goto error; |
1039 | 1037 | } |
1040 | 1038 |
@@ -1219,12 +1217,12 @@ qcrypto_block_luks_create(QCryptoBlock *block, | ||
1219 | 1217 | |
1220 | 1218 | /* Now we encrypt the split master key with the key generated |
1221 | 1219 | * from the user's password, before storing it */ |
1222 | - if (qcrypto_block_encrypt_helper(cipher, block->niv, ivgen, | |
1223 | - QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, | |
1224 | - 0, | |
1225 | - splitkey, | |
1226 | - splitkeylen, | |
1227 | - errp) < 0) { | |
1220 | + if (qcrypto_block_cipher_encrypt_helper(cipher, block->niv, ivgen, | |
1221 | + QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, | |
1222 | + 0, | |
1223 | + splitkey, | |
1224 | + splitkeylen, | |
1225 | + errp) < 0) { | |
1228 | 1226 | goto error; |
1229 | 1227 | } |
1230 | 1228 |
@@ -1341,6 +1339,9 @@ qcrypto_block_luks_create(QCryptoBlock *block, | ||
1341 | 1339 | qcrypto_ivgen_free(ivgen); |
1342 | 1340 | qcrypto_cipher_free(cipher); |
1343 | 1341 | |
1342 | + qcrypto_block_free_cipher(block); | |
1343 | + qcrypto_ivgen_free(block->ivgen); | |
1344 | + | |
1344 | 1345 | g_free(luks); |
1345 | 1346 | return -1; |
1346 | 1347 | } |
@@ -1406,8 +1407,7 @@ qcrypto_block_luks_decrypt(QCryptoBlock *block, | ||
1406 | 1407 | { |
1407 | 1408 | assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); |
1408 | 1409 | assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); |
1409 | - return qcrypto_block_decrypt_helper(block->cipher, | |
1410 | - block->niv, block->ivgen, | |
1410 | + return qcrypto_block_decrypt_helper(block, | |
1411 | 1411 | QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, |
1412 | 1412 | offset, buf, len, errp); |
1413 | 1413 | } |
@@ -1422,8 +1422,7 @@ qcrypto_block_luks_encrypt(QCryptoBlock *block, | ||
1422 | 1422 | { |
1423 | 1423 | assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); |
1424 | 1424 | assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); |
1425 | - return qcrypto_block_encrypt_helper(block->cipher, | |
1426 | - block->niv, block->ivgen, | |
1425 | + return qcrypto_block_encrypt_helper(block, | |
1427 | 1426 | QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, |
1428 | 1427 | offset, buf, len, errp); |
1429 | 1428 | } |
@@ -44,6 +44,7 @@ qcrypto_block_qcow_has_format(const uint8_t *buf G_GNUC_UNUSED, | ||
44 | 44 | static int |
45 | 45 | qcrypto_block_qcow_init(QCryptoBlock *block, |
46 | 46 | const char *keysecret, |
47 | + size_t n_threads, | |
47 | 48 | Error **errp) |
48 | 49 | { |
49 | 50 | char *password; |
@@ -71,11 +72,11 @@ qcrypto_block_qcow_init(QCryptoBlock *block, | ||
71 | 72 | goto fail; |
72 | 73 | } |
73 | 74 | |
74 | - block->cipher = qcrypto_cipher_new(QCRYPTO_CIPHER_ALG_AES_128, | |
75 | - QCRYPTO_CIPHER_MODE_CBC, | |
76 | - keybuf, G_N_ELEMENTS(keybuf), | |
77 | - errp); | |
78 | - if (!block->cipher) { | |
75 | + ret = qcrypto_block_init_cipher(block, QCRYPTO_CIPHER_ALG_AES_128, | |
76 | + QCRYPTO_CIPHER_MODE_CBC, | |
77 | + keybuf, G_N_ELEMENTS(keybuf), | |
78 | + n_threads, errp); | |
79 | + if (ret < 0) { | |
79 | 80 | ret = -ENOTSUP; |
80 | 81 | goto fail; |
81 | 82 | } |
@@ -86,7 +87,7 @@ qcrypto_block_qcow_init(QCryptoBlock *block, | ||
86 | 87 | return 0; |
87 | 88 | |
88 | 89 | fail: |
89 | - qcrypto_cipher_free(block->cipher); | |
90 | + qcrypto_block_free_cipher(block); | |
90 | 91 | qcrypto_ivgen_free(block->ivgen); |
91 | 92 | return ret; |
92 | 93 | } |
@@ -99,6 +100,7 @@ qcrypto_block_qcow_open(QCryptoBlock *block, | ||
99 | 100 | QCryptoBlockReadFunc readfunc G_GNUC_UNUSED, |
100 | 101 | void *opaque G_GNUC_UNUSED, |
101 | 102 | unsigned int flags, |
103 | + size_t n_threads, | |
102 | 104 | Error **errp) |
103 | 105 | { |
104 | 106 | if (flags & QCRYPTO_BLOCK_OPEN_NO_IO) { |
@@ -112,8 +114,8 @@ qcrypto_block_qcow_open(QCryptoBlock *block, | ||
112 | 114 | optprefix ? optprefix : ""); |
113 | 115 | return -1; |
114 | 116 | } |
115 | - return qcrypto_block_qcow_init(block, | |
116 | - options->u.qcow.key_secret, errp); | |
117 | + return qcrypto_block_qcow_init(block, options->u.qcow.key_secret, | |
118 | + n_threads, errp); | |
117 | 119 | } |
118 | 120 | } |
119 | 121 |
@@ -133,7 +135,7 @@ qcrypto_block_qcow_create(QCryptoBlock *block, | ||
133 | 135 | return -1; |
134 | 136 | } |
135 | 137 | /* QCow2 has no special header, since everything is hardwired */ |
136 | - return qcrypto_block_qcow_init(block, options->u.qcow.key_secret, errp); | |
138 | + return qcrypto_block_qcow_init(block, options->u.qcow.key_secret, 1, errp); | |
137 | 139 | } |
138 | 140 | |
139 | 141 |
@@ -152,8 +154,7 @@ qcrypto_block_qcow_decrypt(QCryptoBlock *block, | ||
152 | 154 | { |
153 | 155 | assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_QCOW_SECTOR_SIZE)); |
154 | 156 | assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_QCOW_SECTOR_SIZE)); |
155 | - return qcrypto_block_decrypt_helper(block->cipher, | |
156 | - block->niv, block->ivgen, | |
157 | + return qcrypto_block_decrypt_helper(block, | |
157 | 158 | QCRYPTO_BLOCK_QCOW_SECTOR_SIZE, |
158 | 159 | offset, buf, len, errp); |
159 | 160 | } |
@@ -168,8 +169,7 @@ qcrypto_block_qcow_encrypt(QCryptoBlock *block, | ||
168 | 169 | { |
169 | 170 | assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_QCOW_SECTOR_SIZE)); |
170 | 171 | assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_QCOW_SECTOR_SIZE)); |
171 | - return qcrypto_block_encrypt_helper(block->cipher, | |
172 | - block->niv, block->ivgen, | |
172 | + return qcrypto_block_encrypt_helper(block, | |
173 | 173 | QCRYPTO_BLOCK_QCOW_SECTOR_SIZE, |
174 | 174 | offset, buf, len, errp); |
175 | 175 | } |
@@ -52,6 +52,7 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options, | ||
52 | 52 | QCryptoBlockReadFunc readfunc, |
53 | 53 | void *opaque, |
54 | 54 | unsigned int flags, |
55 | + size_t n_threads, | |
55 | 56 | Error **errp) |
56 | 57 | { |
57 | 58 | QCryptoBlock *block = g_new0(QCryptoBlock, 1); |
@@ -69,11 +70,14 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options, | ||
69 | 70 | block->driver = qcrypto_block_drivers[options->format]; |
70 | 71 | |
71 | 72 | if (block->driver->open(block, options, optprefix, |
72 | - readfunc, opaque, flags, errp) < 0) { | |
73 | + readfunc, opaque, flags, n_threads, errp) < 0) | |
74 | + { | |
73 | 75 | g_free(block); |
74 | 76 | return NULL; |
75 | 77 | } |
76 | 78 | |
79 | + qemu_mutex_init(&block->mutex); | |
80 | + | |
77 | 81 | return block; |
78 | 82 | } |
79 | 83 |
@@ -105,6 +109,8 @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options, | ||
105 | 109 | return NULL; |
106 | 110 | } |
107 | 111 | |
112 | + qemu_mutex_init(&block->mutex); | |
113 | + | |
108 | 114 | return block; |
109 | 115 | } |
110 | 116 |
@@ -148,12 +154,97 @@ int qcrypto_block_encrypt(QCryptoBlock *block, | ||
148 | 154 | |
149 | 155 | QCryptoCipher *qcrypto_block_get_cipher(QCryptoBlock *block) |
150 | 156 | { |
151 | - return block->cipher; | |
157 | + /* Ciphers should be accessed through pop/push method to be thread-safe. | |
158 | + * Better, they should not be accessed externally at all (note, that | |
159 | + * pop/push are static functions) | |
160 | + * This function is used only in test with one thread (it's safe to skip | |
161 | + * pop/push interface), so it's enough to assert it here: | |
162 | + */ | |
163 | + assert(block->n_ciphers <= 1); | |
164 | + return block->ciphers ? block->ciphers[0] : NULL; | |
165 | +} | |
166 | + | |
167 | + | |
168 | +static QCryptoCipher *qcrypto_block_pop_cipher(QCryptoBlock *block) | |
169 | +{ | |
170 | + QCryptoCipher *cipher; | |
171 | + | |
172 | + qemu_mutex_lock(&block->mutex); | |
173 | + | |
174 | + assert(block->n_free_ciphers > 0); | |
175 | + block->n_free_ciphers--; | |
176 | + cipher = block->ciphers[block->n_free_ciphers]; | |
177 | + | |
178 | + qemu_mutex_unlock(&block->mutex); | |
179 | + | |
180 | + return cipher; | |
181 | +} | |
182 | + | |
183 | + | |
184 | +static void qcrypto_block_push_cipher(QCryptoBlock *block, | |
185 | + QCryptoCipher *cipher) | |
186 | +{ | |
187 | + qemu_mutex_lock(&block->mutex); | |
188 | + | |
189 | + assert(block->n_free_ciphers < block->n_ciphers); | |
190 | + block->ciphers[block->n_free_ciphers] = cipher; | |
191 | + block->n_free_ciphers++; | |
192 | + | |
193 | + qemu_mutex_unlock(&block->mutex); | |
152 | 194 | } |
153 | 195 | |
154 | 196 | |
197 | +int qcrypto_block_init_cipher(QCryptoBlock *block, | |
198 | + QCryptoCipherAlgorithm alg, | |
199 | + QCryptoCipherMode mode, | |
200 | + const uint8_t *key, size_t nkey, | |
201 | + size_t n_threads, Error **errp) | |
202 | +{ | |
203 | + size_t i; | |
204 | + | |
205 | + assert(!block->ciphers && !block->n_ciphers && !block->n_free_ciphers); | |
206 | + | |
207 | + block->ciphers = g_new0(QCryptoCipher *, n_threads); | |
208 | + | |
209 | + for (i = 0; i < n_threads; i++) { | |
210 | + block->ciphers[i] = qcrypto_cipher_new(alg, mode, key, nkey, errp); | |
211 | + if (!block->ciphers[i]) { | |
212 | + qcrypto_block_free_cipher(block); | |
213 | + return -1; | |
214 | + } | |
215 | + block->n_ciphers++; | |
216 | + block->n_free_ciphers++; | |
217 | + } | |
218 | + | |
219 | + return 0; | |
220 | +} | |
221 | + | |
222 | + | |
223 | +void qcrypto_block_free_cipher(QCryptoBlock *block) | |
224 | +{ | |
225 | + size_t i; | |
226 | + | |
227 | + if (!block->ciphers) { | |
228 | + return; | |
229 | + } | |
230 | + | |
231 | + assert(block->n_ciphers == block->n_free_ciphers); | |
232 | + | |
233 | + for (i = 0; i < block->n_ciphers; i++) { | |
234 | + qcrypto_cipher_free(block->ciphers[i]); | |
235 | + } | |
236 | + | |
237 | + g_free(block->ciphers); | |
238 | + block->ciphers = NULL; | |
239 | + block->n_ciphers = block->n_free_ciphers = 0; | |
240 | +} | |
241 | + | |
155 | 242 | QCryptoIVGen *qcrypto_block_get_ivgen(QCryptoBlock *block) |
156 | 243 | { |
244 | + /* ivgen should be accessed under mutex. However, this function is used only | |
245 | + * in test with one thread, so it's enough to assert it here: | |
246 | + */ | |
247 | + assert(block->n_ciphers <= 1); | |
157 | 248 | return block->ivgen; |
158 | 249 | } |
159 | 250 |
@@ -184,20 +275,29 @@ void qcrypto_block_free(QCryptoBlock *block) | ||
184 | 275 | |
185 | 276 | block->driver->cleanup(block); |
186 | 277 | |
187 | - qcrypto_cipher_free(block->cipher); | |
278 | + qcrypto_block_free_cipher(block); | |
188 | 279 | qcrypto_ivgen_free(block->ivgen); |
280 | + qemu_mutex_destroy(&block->mutex); | |
189 | 281 | g_free(block); |
190 | 282 | } |
191 | 283 | |
192 | 284 | |
193 | -int qcrypto_block_decrypt_helper(QCryptoCipher *cipher, | |
194 | - size_t niv, | |
195 | - QCryptoIVGen *ivgen, | |
196 | - int sectorsize, | |
197 | - uint64_t offset, | |
198 | - uint8_t *buf, | |
199 | - size_t len, | |
200 | - Error **errp) | |
285 | +typedef int (*QCryptoCipherEncDecFunc)(QCryptoCipher *cipher, | |
286 | + const void *in, | |
287 | + void *out, | |
288 | + size_t len, | |
289 | + Error **errp); | |
290 | + | |
291 | +static int do_qcrypto_block_cipher_encdec(QCryptoCipher *cipher, | |
292 | + size_t niv, | |
293 | + QCryptoIVGen *ivgen, | |
294 | + QemuMutex *ivgen_mutex, | |
295 | + int sectorsize, | |
296 | + uint64_t offset, | |
297 | + uint8_t *buf, | |
298 | + size_t len, | |
299 | + QCryptoCipherEncDecFunc func, | |
300 | + Error **errp) | |
201 | 301 | { |
202 | 302 | uint8_t *iv; |
203 | 303 | int ret = -1; |
@@ -211,10 +311,15 @@ int qcrypto_block_decrypt_helper(QCryptoCipher *cipher, | ||
211 | 311 | while (len > 0) { |
212 | 312 | size_t nbytes; |
213 | 313 | if (niv) { |
214 | - if (qcrypto_ivgen_calculate(ivgen, | |
215 | - startsector, | |
216 | - iv, niv, | |
217 | - errp) < 0) { | |
314 | + if (ivgen_mutex) { | |
315 | + qemu_mutex_lock(ivgen_mutex); | |
316 | + } | |
317 | + ret = qcrypto_ivgen_calculate(ivgen, startsector, iv, niv, errp); | |
318 | + if (ivgen_mutex) { | |
319 | + qemu_mutex_unlock(ivgen_mutex); | |
320 | + } | |
321 | + | |
322 | + if (ret < 0) { | |
218 | 323 | goto cleanup; |
219 | 324 | } |
220 | 325 |
@@ -226,8 +331,7 @@ int qcrypto_block_decrypt_helper(QCryptoCipher *cipher, | ||
226 | 331 | } |
227 | 332 | |
228 | 333 | nbytes = len > sectorsize ? sectorsize : len; |
229 | - if (qcrypto_cipher_decrypt(cipher, buf, buf, | |
230 | - nbytes, errp) < 0) { | |
334 | + if (func(cipher, buf, buf, nbytes, errp) < 0) { | |
231 | 335 | goto cleanup; |
232 | 336 | } |
233 | 337 |
@@ -243,54 +347,69 @@ int qcrypto_block_decrypt_helper(QCryptoCipher *cipher, | ||
243 | 347 | } |
244 | 348 | |
245 | 349 | |
246 | -int qcrypto_block_encrypt_helper(QCryptoCipher *cipher, | |
247 | - size_t niv, | |
248 | - QCryptoIVGen *ivgen, | |
350 | +int qcrypto_block_cipher_decrypt_helper(QCryptoCipher *cipher, | |
351 | + size_t niv, | |
352 | + QCryptoIVGen *ivgen, | |
353 | + int sectorsize, | |
354 | + uint64_t offset, | |
355 | + uint8_t *buf, | |
356 | + size_t len, | |
357 | + Error **errp) | |
358 | +{ | |
359 | + return do_qcrypto_block_cipher_encdec(cipher, niv, ivgen, NULL, sectorsize, | |
360 | + offset, buf, len, | |
361 | + qcrypto_cipher_decrypt, errp); | |
362 | +} | |
363 | + | |
364 | + | |
365 | +int qcrypto_block_cipher_encrypt_helper(QCryptoCipher *cipher, | |
366 | + size_t niv, | |
367 | + QCryptoIVGen *ivgen, | |
368 | + int sectorsize, | |
369 | + uint64_t offset, | |
370 | + uint8_t *buf, | |
371 | + size_t len, | |
372 | + Error **errp) | |
373 | +{ | |
374 | + return do_qcrypto_block_cipher_encdec(cipher, niv, ivgen, NULL, sectorsize, | |
375 | + offset, buf, len, | |
376 | + qcrypto_cipher_encrypt, errp); | |
377 | +} | |
378 | + | |
379 | +int qcrypto_block_decrypt_helper(QCryptoBlock *block, | |
249 | 380 | int sectorsize, |
250 | 381 | uint64_t offset, |
251 | 382 | uint8_t *buf, |
252 | 383 | size_t len, |
253 | 384 | Error **errp) |
254 | 385 | { |
255 | - uint8_t *iv; | |
256 | - int ret = -1; | |
257 | - uint64_t startsector = offset / sectorsize; | |
386 | + int ret; | |
387 | + QCryptoCipher *cipher = qcrypto_block_pop_cipher(block); | |
258 | 388 | |
259 | - assert(QEMU_IS_ALIGNED(offset, sectorsize)); | |
260 | - assert(QEMU_IS_ALIGNED(len, sectorsize)); | |
389 | + ret = do_qcrypto_block_cipher_encdec(cipher, block->niv, block->ivgen, | |
390 | + &block->mutex, sectorsize, offset, buf, | |
391 | + len, qcrypto_cipher_decrypt, errp); | |
261 | 392 | |
262 | - iv = niv ? g_new0(uint8_t, niv) : NULL; | |
393 | + qcrypto_block_push_cipher(block, cipher); | |
263 | 394 | |
264 | - while (len > 0) { | |
265 | - size_t nbytes; | |
266 | - if (niv) { | |
267 | - if (qcrypto_ivgen_calculate(ivgen, | |
268 | - startsector, | |
269 | - iv, niv, | |
270 | - errp) < 0) { | |
271 | - goto cleanup; | |
272 | - } | |
395 | + return ret; | |
396 | +} | |
273 | 397 | |
274 | - if (qcrypto_cipher_setiv(cipher, | |
275 | - iv, niv, | |
276 | - errp) < 0) { | |
277 | - goto cleanup; | |
278 | - } | |
279 | - } | |
398 | +int qcrypto_block_encrypt_helper(QCryptoBlock *block, | |
399 | + int sectorsize, | |
400 | + uint64_t offset, | |
401 | + uint8_t *buf, | |
402 | + size_t len, | |
403 | + Error **errp) | |
404 | +{ | |
405 | + int ret; | |
406 | + QCryptoCipher *cipher = qcrypto_block_pop_cipher(block); | |
280 | 407 | |
281 | - nbytes = len > sectorsize ? sectorsize : len; | |
282 | - if (qcrypto_cipher_encrypt(cipher, buf, buf, | |
283 | - nbytes, errp) < 0) { | |
284 | - goto cleanup; | |
285 | - } | |
408 | + ret = do_qcrypto_block_cipher_encdec(cipher, block->niv, block->ivgen, | |
409 | + &block->mutex, sectorsize, offset, buf, | |
410 | + len, qcrypto_cipher_encrypt, errp); | |
286 | 411 | |
287 | - startsector++; | |
288 | - buf += nbytes; | |
289 | - len -= nbytes; | |
290 | - } | |
412 | + qcrypto_block_push_cipher(block, cipher); | |
291 | 413 | |
292 | - ret = 0; | |
293 | - cleanup: | |
294 | - g_free(iv); | |
295 | 414 | return ret; |
296 | 415 | } |
@@ -22,6 +22,7 @@ | ||
22 | 22 | #define QCRYPTO_BLOCKPRIV_H |
23 | 23 | |
24 | 24 | #include "crypto/block.h" |
25 | +#include "qemu/thread.h" | |
25 | 26 | |
26 | 27 | typedef struct QCryptoBlockDriver QCryptoBlockDriver; |
27 | 28 |
@@ -31,8 +32,12 @@ struct QCryptoBlock { | ||
31 | 32 | const QCryptoBlockDriver *driver; |
32 | 33 | void *opaque; |
33 | 34 | |
34 | - QCryptoCipher *cipher; | |
35 | + QCryptoCipher **ciphers; | |
36 | + size_t n_ciphers; | |
37 | + size_t n_free_ciphers; | |
35 | 38 | QCryptoIVGen *ivgen; |
39 | + QemuMutex mutex; | |
40 | + | |
36 | 41 | QCryptoHashAlgorithm kdfhash; |
37 | 42 | size_t niv; |
38 | 43 | uint64_t payload_offset; /* In bytes */ |
@@ -46,6 +51,7 @@ struct QCryptoBlockDriver { | ||
46 | 51 | QCryptoBlockReadFunc readfunc, |
47 | 52 | void *opaque, |
48 | 53 | unsigned int flags, |
54 | + size_t n_threads, | |
49 | 55 | Error **errp); |
50 | 56 | |
51 | 57 | int (*create)(QCryptoBlock *block, |
@@ -78,22 +84,44 @@ struct QCryptoBlockDriver { | ||
78 | 84 | }; |
79 | 85 | |
80 | 86 | |
81 | -int qcrypto_block_decrypt_helper(QCryptoCipher *cipher, | |
82 | - size_t niv, | |
83 | - QCryptoIVGen *ivgen, | |
87 | +int qcrypto_block_cipher_decrypt_helper(QCryptoCipher *cipher, | |
88 | + size_t niv, | |
89 | + QCryptoIVGen *ivgen, | |
90 | + int sectorsize, | |
91 | + uint64_t offset, | |
92 | + uint8_t *buf, | |
93 | + size_t len, | |
94 | + Error **errp); | |
95 | + | |
96 | +int qcrypto_block_cipher_encrypt_helper(QCryptoCipher *cipher, | |
97 | + size_t niv, | |
98 | + QCryptoIVGen *ivgen, | |
99 | + int sectorsize, | |
100 | + uint64_t offset, | |
101 | + uint8_t *buf, | |
102 | + size_t len, | |
103 | + Error **errp); | |
104 | + | |
105 | +int qcrypto_block_decrypt_helper(QCryptoBlock *block, | |
84 | 106 | int sectorsize, |
85 | 107 | uint64_t offset, |
86 | 108 | uint8_t *buf, |
87 | 109 | size_t len, |
88 | 110 | Error **errp); |
89 | 111 | |
90 | -int qcrypto_block_encrypt_helper(QCryptoCipher *cipher, | |
91 | - size_t niv, | |
92 | - QCryptoIVGen *ivgen, | |
112 | +int qcrypto_block_encrypt_helper(QCryptoBlock *block, | |
93 | 113 | int sectorsize, |
94 | 114 | uint64_t offset, |
95 | 115 | uint8_t *buf, |
96 | 116 | size_t len, |
97 | 117 | Error **errp); |
98 | 118 | |
119 | +int qcrypto_block_init_cipher(QCryptoBlock *block, | |
120 | + QCryptoCipherAlgorithm alg, | |
121 | + QCryptoCipherMode mode, | |
122 | + const uint8_t *key, size_t nkey, | |
123 | + size_t n_threads, Error **errp); | |
124 | + | |
125 | +void qcrypto_block_free_cipher(QCryptoBlock *block); | |
126 | + | |
99 | 127 | #endif /* QCRYPTO_BLOCKPRIV_H */ |
@@ -75,6 +75,7 @@ typedef enum { | ||
75 | 75 | * @readfunc: callback for reading data from the volume |
76 | 76 | * @opaque: data to pass to @readfunc |
77 | 77 | * @flags: bitmask of QCryptoBlockOpenFlags values |
78 | + * @n_threads: allow concurrent I/O from up to @n_threads threads | |
78 | 79 | * @errp: pointer to a NULL-initialized error object |
79 | 80 | * |
80 | 81 | * Create a new block encryption object for an existing |
@@ -107,6 +108,7 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options, | ||
107 | 108 | QCryptoBlockReadFunc readfunc, |
108 | 109 | void *opaque, |
109 | 110 | unsigned int flags, |
111 | + size_t n_threads, | |
110 | 112 | Error **errp); |
111 | 113 | |
112 | 114 | /** |
@@ -181,11 +181,11 @@ | ||
181 | 181 | # The options that apply to LUKS encryption format initialization |
182 | 182 | # |
183 | 183 | # @cipher-alg: the cipher algorithm for data encryption |
184 | -# Currently defaults to 'aes'. | |
184 | +# Currently defaults to 'aes-256'. | |
185 | 185 | # @cipher-mode: the cipher mode for data encryption |
186 | -# Currently defaults to 'cbc' | |
186 | +# Currently defaults to 'xts' | |
187 | 187 | # @ivgen-alg: the initialization vector generator |
188 | -# Currently defaults to 'essiv' | |
188 | +# Currently defaults to 'plain64' | |
189 | 189 | # @ivgen-hash-alg: the initialization vector generator hash |
190 | 190 | # Currently defaults to 'sha256' |
191 | 191 | # @hash-alg: the master key hash algorithm |
@@ -305,6 +305,7 @@ static void test_block(gconstpointer opaque) | ||
305 | 305 | test_block_read_func, |
306 | 306 | &header, |
307 | 307 | 0, |
308 | + 1, | |
308 | 309 | NULL); |
309 | 310 | g_assert(blk == NULL); |
310 | 311 |
@@ -313,6 +314,7 @@ static void test_block(gconstpointer opaque) | ||
313 | 314 | test_block_read_func, |
314 | 315 | &header, |
315 | 316 | QCRYPTO_BLOCK_OPEN_NO_IO, |
317 | + 1, | |
316 | 318 | &error_abort); |
317 | 319 | |
318 | 320 | g_assert(qcrypto_block_get_cipher(blk) == NULL); |
@@ -327,6 +329,7 @@ static void test_block(gconstpointer opaque) | ||
327 | 329 | test_block_read_func, |
328 | 330 | &header, |
329 | 331 | 0, |
332 | + 1, | |
330 | 333 | &error_abort); |
331 | 334 | g_assert(blk); |
332 | 335 |