From dd2bf9eb95f875f0ad6a15aecb48cfc8b739fcbc Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Fri, 23 Oct 2015 16:13:50 +0100 Subject: [PATCH] crypto: add additional query accessors for cipher instances Adds new methods to allow querying the length of the cipher key, block size and initialization vectors. Reviewed-by: Eric Blake Signed-off-by: Daniel P. Berrange --- crypto/cipher.c | 48 ++++++++++++++++++++++++++++++++++++++ include/crypto/cipher.h | 37 +++++++++++++++++++++++++++++ tests/test-crypto-cipher.c | 10 ++++++++ 3 files changed, 95 insertions(+) diff --git a/crypto/cipher.c b/crypto/cipher.c index c8bd180532..d02bb322b7 100644 --- a/crypto/cipher.c +++ b/crypto/cipher.c @@ -28,6 +28,54 @@ static size_t alg_key_len[QCRYPTO_CIPHER_ALG_LAST] = { [QCRYPTO_CIPHER_ALG_DES_RFB] = 8, }; +static size_t alg_block_len[QCRYPTO_CIPHER_ALG_LAST] = { + [QCRYPTO_CIPHER_ALG_AES_128] = 16, + [QCRYPTO_CIPHER_ALG_AES_192] = 16, + [QCRYPTO_CIPHER_ALG_AES_256] = 16, + [QCRYPTO_CIPHER_ALG_DES_RFB] = 8, +}; + +static bool mode_need_iv[QCRYPTO_CIPHER_MODE_LAST] = { + [QCRYPTO_CIPHER_MODE_ECB] = false, + [QCRYPTO_CIPHER_MODE_CBC] = true, +}; + + +size_t qcrypto_cipher_get_block_len(QCryptoCipherAlgorithm alg) +{ + if (alg >= G_N_ELEMENTS(alg_key_len)) { + return 0; + } + return alg_block_len[alg]; +} + + +size_t qcrypto_cipher_get_key_len(QCryptoCipherAlgorithm alg) +{ + if (alg >= G_N_ELEMENTS(alg_key_len)) { + return 0; + } + return alg_key_len[alg]; +} + + +size_t qcrypto_cipher_get_iv_len(QCryptoCipherAlgorithm alg, + QCryptoCipherMode mode) +{ + if (alg >= G_N_ELEMENTS(alg_block_len)) { + return 0; + } + if (mode >= G_N_ELEMENTS(mode_need_iv)) { + return 0; + } + + if (mode_need_iv[mode]) { + return alg_block_len[alg]; + } + return 0; +} + + static bool qcrypto_cipher_validate_key_length(QCryptoCipherAlgorithm alg, size_t nkey, diff --git a/include/crypto/cipher.h b/include/crypto/cipher.h index b4d714f269..aa51c89f8e 100644 --- a/include/crypto/cipher.h +++ b/include/crypto/cipher.h @@ -107,6 +107,43 @@ struct QCryptoCipher { */ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg); +/** + * qcrypto_cipher_get_block_len: + * @alg: the cipher algorithm + * + * Get the required data block size in bytes. When + * encrypting data, it must be a multiple of the + * block size. + * + * Returns: the block size in bytes + */ +size_t qcrypto_cipher_get_block_len(QCryptoCipherAlgorithm alg); + + +/** + * qcrypto_cipher_get_key_len: + * @alg: the cipher algorithm + * + * Get the required key size in bytes. + * + * Returns: the key size in bytes + */ +size_t qcrypto_cipher_get_key_len(QCryptoCipherAlgorithm alg); + + +/** + * qcrypto_cipher_get_iv_len: + * @alg: the cipher algorithm + * @mode: the cipher mode + * + * Get the required initialization vector size + * in bytes, if one is required. + * + * Returns: the IV size in bytes, or 0 if no IV is permitted + */ +size_t qcrypto_cipher_get_iv_len(QCryptoCipherAlgorithm alg, + QCryptoCipherMode mode); + /** * qcrypto_cipher_new: diff --git a/tests/test-crypto-cipher.c b/tests/test-crypto-cipher.c index f4946a0af0..c687307bcd 100644 --- a/tests/test-crypto-cipher.c +++ b/tests/test-crypto-cipher.c @@ -229,6 +229,7 @@ static void test_cipher(const void *opaque) uint8_t *key, *iv, *ciphertext, *plaintext, *outtext; size_t nkey, niv, nciphertext, nplaintext; char *outtexthex; + size_t ivsize, keysize, blocksize; nkey = unhex_string(data->key, &key); niv = unhex_string(data->iv, &iv); @@ -245,6 +246,15 @@ static void test_cipher(const void *opaque) &error_abort); g_assert(cipher != NULL); + keysize = qcrypto_cipher_get_key_len(data->alg); + blocksize = qcrypto_cipher_get_block_len(data->alg); + ivsize = qcrypto_cipher_get_iv_len(data->alg, data->mode); + + g_assert_cmpint(keysize, ==, nkey); + g_assert_cmpint(ivsize, ==, niv); + if (niv) { + g_assert_cmpint(blocksize, ==, niv); + } if (iv) { g_assert(qcrypto_cipher_setiv(cipher,