aboutsummaryrefslogtreecommitdiff
path: root/crypto/cipher.c
diff options
context:
space:
mode:
authorDaniel P. Berrange <berrange@redhat.com>2016-02-11 14:05:21 +0000
committerDaniel P. Berrange <berrange@redhat.com>2016-03-17 14:41:15 +0000
commiteaec903c5b830ed9d9610ba72072b97763c2f996 (patch)
treeec12b0ae205a401562ad92ada361c31a7a5cf6df /crypto/cipher.c
parente3ba0b67014b9fa15239f99bfcc227200e89024b (diff)
crypto: wire up XTS mode for cipher APIs
Introduce 'XTS' as a permitted mode for the cipher APIs. With XTS the key provided must be twice the size of the key normally required for any given algorithm. This is because the key will be split into two pieces for use in XTS mode. Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Diffstat (limited to 'crypto/cipher.c')
-rw-r--r--crypto/cipher.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/crypto/cipher.c b/crypto/cipher.c
index 89fa5a2c70..5402d18525 100644
--- a/crypto/cipher.c
+++ b/crypto/cipher.c
@@ -53,6 +53,7 @@ static size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = {
static bool mode_need_iv[QCRYPTO_CIPHER_MODE__MAX] = {
[QCRYPTO_CIPHER_MODE_ECB] = false,
[QCRYPTO_CIPHER_MODE_CBC] = true,
+ [QCRYPTO_CIPHER_MODE_XTS] = true,
};
@@ -93,6 +94,7 @@ size_t qcrypto_cipher_get_iv_len(QCryptoCipherAlgorithm alg,
static bool
qcrypto_cipher_validate_key_length(QCryptoCipherAlgorithm alg,
+ QCryptoCipherMode mode,
size_t nkey,
Error **errp)
{
@@ -102,10 +104,27 @@ qcrypto_cipher_validate_key_length(QCryptoCipherAlgorithm alg,
return false;
}
- if (alg_key_len[alg] != nkey) {
- error_setg(errp, "Cipher key length %zu should be %zu",
- nkey, alg_key_len[alg]);
- return false;
+ if (mode == QCRYPTO_CIPHER_MODE_XTS) {
+ if (alg == QCRYPTO_CIPHER_ALG_DES_RFB) {
+ error_setg(errp, "XTS mode not compatible with DES-RFB");
+ return false;
+ }
+ if (nkey % 2) {
+ error_setg(errp, "XTS cipher key length should be a multiple of 2");
+ return false;
+ }
+
+ if (alg_key_len[alg] != (nkey / 2)) {
+ error_setg(errp, "Cipher key length %zu should be %zu",
+ nkey, alg_key_len[alg] * 2);
+ return false;
+ }
+ } else {
+ if (alg_key_len[alg] != nkey) {
+ error_setg(errp, "Cipher key length %zu should be %zu",
+ nkey, alg_key_len[alg]);
+ return false;
+ }
}
return true;
}