summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2018-10-26 14:15:16 +0000
committerDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2018-10-26 14:15:16 +0000
commit18dcc771ec4439b5451fd372941629a80d51baa2 (patch)
treeb36ca2468b70fcbcbf5fc5185d8f9c460add61b7
parent4c239816a19e84ed8faa06c69b5af8efa2a7c904 (diff)
parent297aa769c3fc779848f8eb7dbd82ef3690483969 (diff)
downloadgnutls-18dcc771ec4439b5451fd372941629a80d51baa2.tar.gz
Merge branch 'cfb8' into 'master'
Add support for AES CFB8 cipher Closes #357 See merge request gnutls/gnutls!783
-rw-r--r--configure.ac6
-rw-r--r--lib/algorithms/ciphers.c21
-rw-r--r--lib/crypto-selftests.c56
-rw-r--r--lib/fips.h3
-rw-r--r--lib/includes/gnutls/gnutls.h.in6
-rw-r--r--lib/nettle/Makefile.am2
-rw-r--r--lib/nettle/backport/cfb8.c117
-rw-r--r--lib/nettle/backport/cfb8.h96
-rw-r--r--lib/nettle/cipher.c63
9 files changed, 369 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index 95c756e8bd..7b50f548d2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -559,6 +559,12 @@ if test "$enable_non_suiteb" = "yes";then
fi
AM_CONDITIONAL(ENABLE_NON_SUITEB_CURVES, test "$enable_non_suiteb" = "yes")
+# Check if nettle has CFB8 support
+save_LIBS=$LIBS
+LIBS="$LIBS $NETTLE_LIBS"
+AC_CHECK_FUNCS(nettle_cfb8_encrypt)
+LIBS=$save_LIBS
+
AC_MSG_CHECKING([whether to build libdane])
AC_ARG_ENABLE(libdane,
AS_HELP_STRING([--disable-libdane],
diff --git a/lib/algorithms/ciphers.c b/lib/algorithms/ciphers.c
index bbdb1c8524..1a8704be25 100644
--- a/lib/algorithms/ciphers.c
+++ b/lib/algorithms/ciphers.c
@@ -219,6 +219,27 @@ static const cipher_entry_st algorithms[] = {
.type = CIPHER_STREAM,
.implicit_iv = 8,
.cipher_iv = 8},
+ { .name = "AES-128-CFB8",
+ .id = GNUTLS_CIPHER_AES_128_CFB8,
+ .blocksize = 16,
+ .keysize = 16,
+ .type = CIPHER_BLOCK,
+ .explicit_iv = 16,
+ .cipher_iv = 16},
+ { .name = "AES-192-CFB8",
+ .id = GNUTLS_CIPHER_AES_192_CFB8,
+ .blocksize = 16,
+ .keysize = 24,
+ .type = CIPHER_BLOCK,
+ .explicit_iv = 16,
+ .cipher_iv = 16},
+ { .name = "AES-256-CFB8",
+ .id = GNUTLS_CIPHER_AES_256_CFB8,
+ .blocksize = 16,
+ .keysize = 32,
+ .type = CIPHER_BLOCK,
+ .explicit_iv = 16,
+ .cipher_iv = 16},
{ .name = "3DES-CBC",
.id = GNUTLS_CIPHER_3DES_CBC,
.blocksize = 8,
diff --git a/lib/crypto-selftests.c b/lib/crypto-selftests.c
index 1e51dfd6c3..19b8210b4e 100644
--- a/lib/crypto-selftests.c
+++ b/lib/crypto-selftests.c
@@ -373,6 +373,53 @@ const struct cipher_vectors_st arcfour_vectors[] = { /* RFC6229 */
},
};
+const struct cipher_vectors_st aes128_cfb8_vectors[] = { /* NIST 800-38a */
+ {
+ STR(key, key_size,
+ "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c"),
+ STR(plaintext, plaintext_size,
+ "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+ "\xae\x2d"),
+ .ciphertext = (uint8_t *)
+ "\x3b\x79\x42\x4c\x9c\x0d\xd4\x36\xba\xce\x9e\x0e\xd4\x58\x6a\x4f"
+ "\x32\xb9",
+ STR(iv, iv_size,
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"),
+ },
+};
+
+const struct cipher_vectors_st aes192_cfb8_vectors[] = { /* NIST 800-38a */
+ {
+ STR(key, key_size,
+ "\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5"
+ "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b"),
+ STR(plaintext, plaintext_size,
+ "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+ "\xae\x2d"),
+ .ciphertext = (uint8_t *)
+ "\xcd\xa2\x52\x1e\xf0\xa9\x05\xca\x44\xcd\x05\x7c\xbf\x0d\x47\xa0"
+ "\x67\x8a",
+ STR(iv, iv_size,
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"),
+ },
+};
+
+const struct cipher_vectors_st aes256_cfb8_vectors[] = { /* NIST 800-38a */
+ {
+ STR(key, key_size,
+ "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81"
+ "\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4"),
+ STR(plaintext, plaintext_size,
+ "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+ "\xae\x2d"),
+ .ciphertext = (uint8_t *)
+ "\xdc\x1f\x1a\x85\x20\xa6\x4d\xb5\x5f\xcc\x8a\xc5\x54\x84\x4e\x88"
+ "\x97\x00",
+ STR(iv, iv_size,
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"),
+ },
+};
+
static int test_cipher(gnutls_cipher_algorithm_t cipher,
const struct cipher_vectors_st *vectors,
size_t vectors_size, unsigned flags)
@@ -1339,6 +1386,15 @@ int gnutls_cipher_self_test(unsigned flags, gnutls_cipher_algorithm_t cipher)
FALLTHROUGH;
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);
+ FALLTHROUGH;
+ CASE(GNUTLS_CIPHER_AES_192_CFB8, test_cipher,
+ aes192_cfb8_vectors);
+ FALLTHROUGH;
+ CASE(GNUTLS_CIPHER_AES_256_CFB8, test_cipher,
+ aes256_cfb8_vectors);
break;
default:
return gnutls_assert_val(GNUTLS_E_NO_SELF_TEST);
diff --git a/lib/fips.h b/lib/fips.h
index 7d3f3cfd39..4e09916ac4 100644
--- a/lib/fips.h
+++ b/lib/fips.h
@@ -139,6 +139,9 @@ static unsigned is_cipher_algo_forbidden(gnutls_cipher_algorithm_t algo)
case GNUTLS_CIPHER_3DES_CBC:
case GNUTLS_CIPHER_AES_128_CCM_8:
case GNUTLS_CIPHER_AES_256_CCM_8:
+ case GNUTLS_CIPHER_AES_128_CFB8:
+ case GNUTLS_CIPHER_AES_192_CFB8:
+ case GNUTLS_CIPHER_AES_256_CFB8:
return 0;
default:
if (mode == GNUTLS_FIPS140_LAX)
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index a5439cce56..786dcdf055 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -97,6 +97,9 @@ extern "C" {
* @GNUTLS_CIPHER_AES_128_CBC: AES in CBC mode with 128-bit keys.
* @GNUTLS_CIPHER_AES_192_CBC: AES in CBC mode with 192-bit keys.
* @GNUTLS_CIPHER_AES_256_CBC: AES in CBC mode with 256-bit keys.
+ * @GNUTLS_CIPHER_AES_128_CFB8: AES in CFB8 mode with 128-bit keys.
+ * @GNUTLS_CIPHER_AES_192_CFB8: AES in CFB8 mode with 192-bit keys.
+ * @GNUTLS_CIPHER_AES_256_CFB8: AES in CFB8 mode with 256-bit keys.
* @GNUTLS_CIPHER_ARCFOUR_40: ARCFOUR stream cipher with 40-bit keys.
* @GNUTLS_CIPHER_CAMELLIA_128_CBC: Camellia in CBC mode with 128-bit keys.
* @GNUTLS_CIPHER_CAMELLIA_192_CBC: Camellia in CBC mode with 192-bit keys.
@@ -161,6 +164,9 @@ typedef enum gnutls_cipher_algorithm {
GNUTLS_CIPHER_GOST28147_CPB_CFB = 26,
GNUTLS_CIPHER_GOST28147_CPC_CFB = 27,
GNUTLS_CIPHER_GOST28147_CPD_CFB = 28,
+ GNUTLS_CIPHER_AES_128_CFB8 = 29,
+ GNUTLS_CIPHER_AES_192_CFB8 = 30,
+ GNUTLS_CIPHER_AES_256_CFB8 = 31,
/* used only for PGP internals. Ignored in TLS/SSL
*/
diff --git a/lib/nettle/Makefile.am b/lib/nettle/Makefile.am
index bd5ec45901..7bb88b8c8f 100644
--- a/lib/nettle/Makefile.am
+++ b/lib/nettle/Makefile.am
@@ -24,6 +24,7 @@ AM_CFLAGS += $(HOGWEED_CFLAGS) $(GMP_CFLAGS)
AM_CPPFLAGS = \
-I$(srcdir)/int \
+ -I$(srcdir)/backport \
-I$(srcdir)/../../gl \
-I$(builddir)/../../gl \
-I$(srcdir)/../includes \
@@ -39,6 +40,7 @@ noinst_LTLIBRARIES = libcrypto.la
libcrypto_la_SOURCES = pk.c mpi.c mac.c cipher.c init.c \
gnettle.h rnd-common.h prf.c \
+ backport/cfb8.c backport/cfb8.h \
rnd.c int/rsa-fips.h int/rsa-keygen-fips186.c int/provable-prime.c \
int/dsa-fips.h int/dsa-keygen-fips186.c int/dsa-validate.c \
int/tls1-prf.c int/tls1-prf.h
diff --git a/lib/nettle/backport/cfb8.c b/lib/nettle/backport/cfb8.c
new file mode 100644
index 0000000000..30e48322fd
--- /dev/null
+++ b/lib/nettle/backport/cfb8.c
@@ -0,0 +1,117 @@
+/* backport of cfb.c for CFB8
+
+ Cipher feedback mode.
+
+ Copyright (C) 2015, 2017 Dmitry Eremin-Solenikov
+ Copyright (C) 2001, 2011 Niels Möller
+
+ This file is part of GNU Nettle.
+
+ GNU Nettle is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+
+ GNU Nettle is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see http://www.gnu.org/licenses/.
+*/
+
+/* #############################################
+ * THIS IS A BACKPORT FROM NETTLE, DO NOT MODIFY
+ * #############################################
+ */
+
+#ifndef HAVE_NETTLE_CFB8_ENCRYPT
+
+#include "cfb8.h"
+#include <string.h>
+#include <nettle/memxor.h>
+
+/* CFB-8 uses slight optimization: it encrypts or decrypts up to block_size
+ * bytes and does memcpy/memxor afterwards */
+void
+cfb8_encrypt(const void *ctx, nettle_cipher_func *f,
+ size_t block_size, uint8_t *iv,
+ size_t length, uint8_t *dst,
+ const uint8_t *src)
+{
+ TMP_DECL(buffer, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE * 2);
+ TMP_DECL(outbuf, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE);
+ TMP_ALLOC(buffer, block_size * 2);
+ TMP_ALLOC(outbuf, block_size);
+ uint8_t pos;
+
+ memcpy(buffer, iv, block_size);
+ pos = 0;
+ while (length)
+ {
+ uint8_t t;
+
+ if (pos == block_size)
+ {
+ memcpy(buffer, buffer + block_size, block_size);
+ pos = 0;
+ }
+
+ f(ctx, block_size, outbuf, buffer + pos);
+ t = *(dst++) = *(src++) ^ outbuf[0];
+ buffer[pos + block_size] = t;
+ length--;
+ pos ++;
+ }
+ memcpy(iv, buffer + pos, block_size);
+}
+
+void
+cfb8_decrypt(const void *ctx, nettle_cipher_func *f,
+ size_t block_size, uint8_t *iv,
+ size_t length, uint8_t *dst,
+ const uint8_t *src)
+{
+ TMP_DECL(buffer, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE * 2);
+ TMP_DECL(outbuf, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE * 2);
+ TMP_ALLOC(buffer, block_size * 2);
+ TMP_ALLOC(outbuf, block_size * 2);
+ uint8_t i = 0;
+
+ memcpy(buffer, iv, block_size);
+ memcpy(buffer + block_size, src,
+ length < block_size ? length : block_size);
+
+ while (length)
+ {
+
+ for (i = 0; i < length && i < block_size; i++)
+ f(ctx, block_size, outbuf + i, buffer + i);
+
+ memxor3(dst, src, outbuf, i);
+
+ length -= i;
+ src += i;
+ dst += i;
+
+ memcpy(buffer, buffer + block_size, block_size);
+ memcpy(buffer + block_size, src,
+ length < block_size ? length : block_size);
+
+ }
+
+ memcpy(iv, buffer + i, block_size);
+}
+#endif /* HAVE_NETTLE_CFB8_ENCRYPT */
diff --git a/lib/nettle/backport/cfb8.h b/lib/nettle/backport/cfb8.h
new file mode 100644
index 0000000000..595c367edc
--- /dev/null
+++ b/lib/nettle/backport/cfb8.h
@@ -0,0 +1,96 @@
+/* backport of cfb.h for CFB8
+
+ Cipher feedback mode.
+
+ Copyright (C) 2015, 2017 Dmitry Eremin-Solenikov
+ Copyright (C) 2001 Niels Möller
+
+ This file is part of GNU Nettle.
+
+ GNU Nettle is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+
+ GNU Nettle is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see http://www.gnu.org/licenses/.
+*/
+
+#ifndef NETTLE_CFB8_H_INCLUDED
+#define NETTLE_CFB8_H_INCLUDED
+
+#include <nettle/cfb.h>
+
+#ifndef NETTLE_INTERNAL_H_INCLUDED
+#define NETTLE_INTERNAL_H_INCLUDED
+#if HAVE_ALLOCA
+# define TMP_DECL(name, type, max) type *name
+# define TMP_ALLOC(name, size) (name = alloca(sizeof (*name) * (size)))
+#else /* !HAVE_ALLOCA */
+# define TMP_DECL(name, type, max) type name[max]
+# define TMP_ALLOC(name, size) \
+ do { if ((size) > (sizeof(name) / sizeof(name[0]))) abort(); } while (0)
+#endif
+
+#define NETTLE_MAX_CIPHER_BLOCK_SIZE 32
+#endif /* NETTLE_INTERNAL_H_INCLUDED */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Name mangling */
+#define cfb8_encrypt _gnutls_backport_nettle_cfb8_encrypt
+#define cfb8_decrypt _gnutls_backport_nettle_cfb8_decrypt
+
+void
+cfb8_encrypt(const void *ctx, nettle_cipher_func *f,
+ size_t block_size, uint8_t *iv,
+ size_t length, uint8_t *dst,
+ const uint8_t *src);
+
+void
+cfb8_decrypt(const void *ctx, nettle_cipher_func *f,
+ size_t block_size, uint8_t *iv,
+ size_t length, uint8_t *dst,
+ const uint8_t *src);
+
+#define CFB8_CTX CFB_CTX
+#define CFB8_SET_IV CFB_SET_IV
+
+#define CFB8_ENCRYPT(self, f, length, dst, src) \
+ (0 ? ((f)(&(self)->ctx, ~(size_t) 0, \
+ (uint8_t *) 0, (const uint8_t *) 0)) \
+ : cfb8_encrypt((void *) &(self)->ctx, \
+ (nettle_cipher_func *) (f), \
+ sizeof((self)->iv), (self)->iv, \
+ (length), (dst), (src)))
+
+#define CFB8_DECRYPT(self, f, length, dst, src) \
+ (0 ? ((f)(&(self)->ctx, ~(size_t) 0, \
+ (uint8_t *) 0, (const uint8_t *) 0)) \
+ : cfb8_decrypt((void *) &(self)->ctx, \
+ (nettle_cipher_func *) (f), \
+ sizeof((self)->iv), (self)->iv, \
+ (length), (dst), (src)))
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* NETTLE_CFB8_H_INCLUDED */
diff --git a/lib/nettle/cipher.c b/lib/nettle/cipher.c
index 24ecf8ded3..eab1a03588 100644
--- a/lib/nettle/cipher.c
+++ b/lib/nettle/cipher.c
@@ -36,13 +36,17 @@
#include <nettle/version.h>
#if ENABLE_GOST
#include "gost/gost28147.h"
-#include <nettle/cfb.h>
#endif
#include <nettle/nettle-meta.h>
#include <nettle/cbc.h>
#include <nettle/gcm.h>
#include <nettle/ccm.h>
#include <nettle/chacha-poly1305.h>
+#ifdef HAVE_NETTLE_CFB8_ENCRYPT
+#include <nettle/cfb.h>
+#else
+#include "cfb8.h"
+#endif /* HAVE_NETTLE_CFB8_ENCRYPT */
#include <fips.h>
struct nettle_cipher_ctx;
@@ -258,6 +262,24 @@ static void _des3_set_key(struct des3_ctx *ctx, const uint8_t *key)
des3_set_key(ctx, key);
}
+static void
+_cfb8_encrypt(struct nettle_cipher_ctx *ctx, size_t length, uint8_t * dst,
+ const uint8_t * src)
+{
+ cfb8_encrypt(ctx->ctx_ptr, ctx->cipher->encrypt_block,
+ ctx->iv_size, ctx->iv,
+ length, dst, src);
+}
+
+static void
+_cfb8_decrypt(struct nettle_cipher_ctx *ctx, size_t length, uint8_t * dst,
+ const uint8_t * src)
+{
+ cfb8_decrypt(ctx->ctx_ptr, ctx->cipher->encrypt_block,
+ ctx->iv_size, ctx->iv,
+ length, dst, src);
+}
+
static const struct nettle_cipher_st builtin_ciphers[] = {
{ .algo = GNUTLS_CIPHER_AES_128_GCM,
.block_size = AES_BLOCK_SIZE,
@@ -616,6 +638,45 @@ static const struct nettle_cipher_st builtin_ciphers[] = {
.set_decrypt_key = _gost28147_set_key_cpd,
},
#endif
+ { .algo = GNUTLS_CIPHER_AES_128_CFB8,
+ .block_size = AES_BLOCK_SIZE,
+ .key_size = AES128_KEY_SIZE,
+ .encrypt_block = (nettle_cipher_func*)aes128_encrypt,
+ .decrypt_block = (nettle_cipher_func*)aes128_encrypt,
+
+ .ctx_size = sizeof(struct CFB8_CTX(struct aes128_ctx, AES_BLOCK_SIZE)),
+ .encrypt = _cfb8_encrypt,
+ .decrypt = _cfb8_decrypt,
+ .set_encrypt_key = (nettle_set_key_func*)aes128_set_encrypt_key,
+ .set_decrypt_key = (nettle_set_key_func*)aes128_set_encrypt_key,
+ .max_iv_size = AES_BLOCK_SIZE,
+ },
+ { .algo = GNUTLS_CIPHER_AES_192_CFB8,
+ .block_size = AES_BLOCK_SIZE,
+ .key_size = AES192_KEY_SIZE,
+ .encrypt_block = (nettle_cipher_func*)aes192_encrypt,
+ .decrypt_block = (nettle_cipher_func*)aes192_encrypt,
+
+ .ctx_size = sizeof(struct CFB8_CTX(struct aes192_ctx, AES_BLOCK_SIZE)),
+ .encrypt = _cfb8_encrypt,
+ .decrypt = _cfb8_decrypt,
+ .set_encrypt_key = (nettle_set_key_func*)aes192_set_encrypt_key,
+ .set_decrypt_key = (nettle_set_key_func*)aes192_set_encrypt_key,
+ .max_iv_size = AES_BLOCK_SIZE,
+ },
+ { .algo = GNUTLS_CIPHER_AES_256_CFB8,
+ .block_size = AES_BLOCK_SIZE,
+ .key_size = AES256_KEY_SIZE,
+ .encrypt_block = (nettle_cipher_func*)aes256_encrypt,
+ .decrypt_block = (nettle_cipher_func*)aes256_encrypt,
+
+ .ctx_size = sizeof(struct CFB8_CTX(struct aes256_ctx, AES_BLOCK_SIZE)),
+ .encrypt = _cfb8_encrypt,
+ .decrypt = _cfb8_decrypt,
+ .set_encrypt_key = (nettle_set_key_func*)aes256_set_encrypt_key,
+ .set_decrypt_key = (nettle_set_key_func*)aes256_set_encrypt_key,
+ .max_iv_size = AES_BLOCK_SIZE,
+ },
};
static int wrap_nettle_cipher_exists(gnutls_cipher_algorithm_t algo)