summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <ueno@gnu.org>2019-11-08 12:38:54 +0000
committerDaiki Ueno <ueno@gnu.org>2019-11-08 12:38:54 +0000
commitb5029c0a57ba881e1db4a8c7d5c680f0f2df8dc4 (patch)
tree291a4f72c3ae59ba60a85f99858a89686c829285
parent570a13f5eeeb1ffcf2c4d57b2f5230560d0950fa (diff)
parent30baf001da482d090b15329d1bcad48cb4f32944 (diff)
downloadgnutls-b5029c0a57ba881e1db4a8c7d5c680f0f2df8dc4.tar.gz
Merge branch 'tmp-cfb8-fixes' into 'master'
nettle: backport fixes to cfb8_decrypt See merge request gnutls/gnutls!1117
-rw-r--r--.gitlab-ci.yml2
-rw-r--r--configure.ac8
-rw-r--r--lib/crypto-selftests.c124
-rw-r--r--lib/nettle/backport/cfb8.c10
-rw-r--r--lib/nettle/backport/cfb8.h3
5 files changed, 136 insertions, 11 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index a754c56974..0abe46ae7d 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -7,7 +7,7 @@ stages:
# name to allow expiration of old caches.
cache:
- key: "$CI_JOB_NAME-ver12"
+ key: "$CI_JOB_NAME-ver13"
paths:
- cache/
diff --git a/configure.ac b/configure.ac
index 4e7a8ece55..73c560406e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -597,6 +597,14 @@ AC_CHECK_FUNCS(nettle_rsa_sec_decrypt,
LIBS=$save_LIBS
# Check if nettle has CFB8 support
+if test -z "$ac_cv_func_nettle_cfb8_encrypt"; then
+ # nettle_cfb8_decrypt in nettle 3.5 is known to be broken
+ ver=`$PKG_CONFIG --modversion nettle`
+ if expr "$ver" : '^3\.5\b' >/dev/null; then
+ ac_cv_func_nettle_cfb8_encrypt=no
+ fi
+fi
+
save_LIBS=$LIBS
LIBS="$LIBS $NETTLE_LIBS"
AC_CHECK_FUNCS(nettle_cfb8_encrypt)
diff --git a/lib/crypto-selftests.c b/lib/crypto-selftests.c
index 6caf817e82..5f0a4ec8be 100644
--- a/lib/crypto-selftests.c
+++ b/lib/crypto-selftests.c
@@ -710,6 +710,107 @@ static int test_cipher(gnutls_cipher_algorithm_t cipher,
return 0;
}
+static int test_cipher_all_block_sizes(gnutls_cipher_algorithm_t cipher,
+ const struct cipher_vectors_st *vectors,
+ size_t vectors_size, unsigned flags)
+{
+ gnutls_cipher_hd_t hd;
+ int ret;
+ unsigned int i;
+ uint8_t tmp[384];
+ gnutls_datum_t key, iv = {NULL, 0};
+ size_t block;
+ size_t offset;
+
+ for (i = 0; i < vectors_size; i++) {
+ for (block = 1; block <= vectors[i].plaintext_size; block++) {
+ key.data = (void *) vectors[i].key;
+ key.size = vectors[i].key_size;
+
+ iv.data = (void *) vectors[i].iv;
+ iv.size = gnutls_cipher_get_iv_size(cipher);
+
+ if (iv.size != vectors[i].iv_size)
+ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+
+ ret = gnutls_cipher_init(&hd, cipher, &key, &iv);
+ if (ret < 0) {
+ _gnutls_debug_log("error initializing: %s\n",
+ gnutls_cipher_get_name(cipher));
+ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ }
+
+ for (offset = 0;
+ offset < vectors[i].plaintext_size;
+ offset += block) {
+ ret =
+ gnutls_cipher_encrypt2(hd,
+ vectors[i].plaintext + offset,
+ MIN(block, vectors[i].plaintext_size - offset),
+ tmp + offset,
+ sizeof(tmp) - offset);
+ if (ret < 0)
+ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ }
+
+ if (memcmp
+ (tmp, vectors[i].ciphertext,
+ vectors[i].plaintext_size) != 0) {
+ _gnutls_debug_log("%s encryption of test vector %d failed with block size %d/%d!\n",
+ gnutls_cipher_get_name(cipher),
+ i, (int)block, (int)vectors[i].plaintext_size);
+ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ }
+
+ gnutls_cipher_deinit(hd);
+ }
+ }
+
+ for (i = 0; i < vectors_size; i++) {
+ for (block = 1; block <= vectors[i].plaintext_size; block++) {
+ key.data = (void *) vectors[i].key;
+ key.size = vectors[i].key_size;
+
+ iv.data = (void *) vectors[i].iv;
+ iv.size = gnutls_cipher_get_iv_size(cipher);
+
+ ret = gnutls_cipher_init(&hd, cipher, &key, &iv);
+ if (ret < 0)
+ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+
+ for (offset = 0;
+ offset + block <= vectors[i].plaintext_size;
+ offset += block) {
+ ret =
+ gnutls_cipher_decrypt2(hd,
+ vectors[i].ciphertext + offset,
+ MIN(block, vectors[i].plaintext_size - offset),
+ tmp + offset,
+ sizeof(tmp) - offset);
+ if (ret < 0)
+ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ }
+
+ if (memcmp
+ (tmp, vectors[i].plaintext,
+ vectors[i].plaintext_size) != 0) {
+ _gnutls_debug_log("%s decryption of test vector %d failed with block size %d!\n",
+ gnutls_cipher_get_name(cipher),
+ i, (int)block);
+ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ }
+
+ gnutls_cipher_deinit(hd);
+ }
+ }
+
+ _gnutls_debug_log
+ ("%s self check succeeded\n",
+ gnutls_cipher_get_name(cipher));
+
+ return 0;
+}
+
/* AEAD modes (compat APIs) */
static int test_cipher_aead_compat(gnutls_cipher_algorithm_t cipher,
const struct cipher_aead_vectors_st *vectors,
@@ -1721,6 +1822,14 @@ static int test_mac(gnutls_mac_algorithm_t mac,
if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL) || ret < 0) \
return ret
+#define CASE2(x, func, func2, vectors) case x: \
+ ret = func(x, V(vectors), flags); \
+ if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL) || ret < 0) \
+ return ret; \
+ ret = func2(x, V(vectors), flags); \
+ if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL) || ret < 0) \
+ return ret
+
#define NON_FIPS_CASE(x, func, vectors) case x: \
if (_gnutls_fips_mode_enabled() == 0) { \
ret = func(x, V(vectors), flags); \
@@ -1786,14 +1895,17 @@ int gnutls_cipher_self_test(unsigned flags, gnutls_cipher_algorithm_t cipher)
NON_FIPS_CASE(GNUTLS_CIPHER_CHACHA20_POLY1305, test_cipher_aead,
chacha_poly1305_vectors);
FALLTHROUGH;
- CASE(GNUTLS_CIPHER_AES_128_CFB8, test_cipher,
- aes128_cfb8_vectors);
+ CASE2(GNUTLS_CIPHER_AES_128_CFB8, test_cipher,
+ test_cipher_all_block_sizes,
+ aes128_cfb8_vectors);
FALLTHROUGH;
- CASE(GNUTLS_CIPHER_AES_192_CFB8, test_cipher,
- aes192_cfb8_vectors);
+ CASE2(GNUTLS_CIPHER_AES_192_CFB8, test_cipher,
+ test_cipher_all_block_sizes,
+ aes192_cfb8_vectors);
FALLTHROUGH;
- CASE(GNUTLS_CIPHER_AES_256_CFB8, test_cipher,
- aes256_cfb8_vectors);
+ CASE2(GNUTLS_CIPHER_AES_256_CFB8, test_cipher,
+ test_cipher_all_block_sizes,
+ aes256_cfb8_vectors);
FALLTHROUGH;
CASE(GNUTLS_CIPHER_AES_128_XTS, test_cipher,
aes128_xts_vectors);
diff --git a/lib/nettle/backport/cfb8.c b/lib/nettle/backport/cfb8.c
index e9816feb78..1762192f44 100644
--- a/lib/nettle/backport/cfb8.c
+++ b/lib/nettle/backport/cfb8.c
@@ -110,10 +110,12 @@ cfb8_decrypt(const void *ctx, nettle_cipher_func *f,
src += i;
dst += i;
- memcpy(buffer, buffer + block_size, block_size);
- memcpy(buffer + block_size, src,
- length < block_size ? length : block_size);
-
+ if (i == block_size)
+ {
+ memcpy(buffer, buffer + block_size, block_size);
+ memcpy(buffer + block_size, src,
+ length < block_size ? length : block_size);
+ }
}
memcpy(iv, buffer + i, block_size);
diff --git a/lib/nettle/backport/cfb8.h b/lib/nettle/backport/cfb8.h
index 351b46f73f..9aa7559a65 100644
--- a/lib/nettle/backport/cfb8.h
+++ b/lib/nettle/backport/cfb8.h
@@ -55,6 +55,9 @@
extern "C" {
#endif
+#undef cfb8_encrypt
+#undef cfb8_decrypt
+
/* Name mangling */
#define cfb8_encrypt _gnutls_backport_nettle_cfb8_encrypt
#define cfb8_decrypt _gnutls_backport_nettle_cfb8_decrypt