summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <ueno@gnu.org>2020-03-19 12:49:08 +0000
committerDaiki Ueno <ueno@gnu.org>2020-03-19 12:49:08 +0000
commitf523ca002e8ce823bca376e7fefe6169c1bdb636 (patch)
tree126d66686f58ff81664af15a181bb2b885be0481
parentea2a81e5bd115826d2ecd0b0ecc634c95b285a48 (diff)
parenta682bdd288a03408a99f2cc215f89f31970b4dfa (diff)
downloadgnutls-f523ca002e8ce823bca376e7fefe6169c1bdb636.tar.gz
Merge branch 'tmp-chacha' into 'master'
cipher: expose raw ChaCha20 cipher See merge request gnutls/gnutls!1210
-rw-r--r--.gitignore1
-rw-r--r--bootstrap.conf1
-rw-r--r--configure.ac9
-rwxr-xr-xdevel/import-chacha-from-nettle.sh83
-rw-r--r--devel/libgnutls-latest-x86_64.abi2
m---------devel/nettle0
-rw-r--r--lib/algorithms/ciphers.c16
-rw-r--r--lib/crypto-selftests.c20
-rw-r--r--lib/includes/gnutls/gnutls.h.in4
-rw-r--r--lib/nettle/Makefile.am8
-rw-r--r--lib/nettle/cipher.c52
11 files changed, 196 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index de27a2fc9a..7c397c517c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -232,6 +232,7 @@ lib/minitasn1/Makefile
lib/minitasn1/Makefile.in
lib/nettle/libcrypto.la
lib/nettle/curve448
+lib/nettle/chacha
lib/opencdk/libminiopencdk.la
lib/opencdk/Makefile
lib/opencdk/Makefile.in
diff --git a/bootstrap.conf b/bootstrap.conf
index 9216ab6cf3..a2e9ae661d 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -103,4 +103,5 @@ bootstrap_post_import_hook ()
touch ChangeLog || return 1
devel/import-curve448-from-nettle.sh
+ devel/import-chacha-from-nettle.sh
}
diff --git a/configure.ac b/configure.ac
index 09acf8b22f..99cb4091ef 100644
--- a/configure.ac
+++ b/configure.ac
@@ -669,6 +669,15 @@ LIBS=$save_LIBS
AS_IF([test "$have_gostdsa" != "yes"], AC_DEFINE([NEED_GOSTDSA], 1, [Use backported GOST R 34.10 DSA support]))
AM_CONDITIONAL(NEED_GOSTDSA, [test "$have_gostdsa" != "yes"])
+# Check if nettle has ChaCha20 initial block counter support
+have_chacha_set_counter=no
+save_LIBS=$LIBS
+LIBS="$LIBS $NETTLE_LIBS"
+AC_CHECK_FUNCS([nettle_chacha_set_counter],
+ [have_chacha_set_counter=yes])
+LIBS=$save_LIBS
+AM_CONDITIONAL(NEED_CHACHA, [test "$have_chacha_set_counter" != "yes"])
+
AC_MSG_CHECKING([whether to build libdane])
AC_ARG_ENABLE(libdane,
AS_HELP_STRING([--disable-libdane],
diff --git a/devel/import-chacha-from-nettle.sh b/devel/import-chacha-from-nettle.sh
new file mode 100755
index 0000000000..c79f8b8c32
--- /dev/null
+++ b/devel/import-chacha-from-nettle.sh
@@ -0,0 +1,83 @@
+#!/bin/sh
+
+# This script copies the ChaCha20 implementation from the
+# nettle upstream, with necessary adjustments for bundling in GnuTLS.
+
+set +e
+
+: ${srcdir=.}
+SRC=$srcdir/devel/nettle
+DST=$srcdir/lib/nettle/chacha
+
+IMPORTS="
+chacha-core-internal.c
+chacha-crypt.c
+chacha-internal.h
+chacha-poly1305.c
+chacha-poly1305.h
+chacha-set-key.c
+chacha-set-nonce.c
+chacha.h
+"
+
+PUBLIC="
+bignum.h
+ecc-curve.h
+ecc.h
+macros.h
+memxor.h
+nettle-meta.h
+nettle-types.h
+poly1305.h
+"
+
+test -d $DST || mkdir $DST
+
+for f in $IMPORTS; do
+ src=$SRC/$f
+ dst=$DST/$f
+ if test -f $src; then
+ if test -f $dst; then
+ echo "Replacing $dst (existing file backed up in $dst~)"
+ mv $dst $dst~
+ else
+ echo "Copying file $dst"
+ fi
+ cp $src $dst
+ # Use <nettle/*.h> for public headers.
+ for h in $PUBLIC; do
+ p=$(echo $h | sed 's/\./\\./g')
+ if grep '^#include "'$p'"' $dst 2>&1 >/dev/null; then
+ sed 's!^#include "'$p'"!#include <nettle/'$h'>!' $dst > $dst-t && \
+ mv $dst-t $dst
+ fi
+ done
+ # Remove unused <assert.h>.
+ if grep '^#include <assert\.h>' $dst 2>&1 >/dev/null; then
+ if ! grep 'assert *(' $dst 2>&1 >/dev/null; then
+ sed '/^#include <assert\.h>/d' $dst > $dst-t && mv $dst-t $dst
+ fi
+ fi
+ case $dst in
+ *.h)
+ # Rename header guard so as not to conflict with the public ones.
+ if grep '^#ifndef NETTLE_.*_H\(_INCLUDED\)*' $dst 2>&1 >/dev/null; then
+ g=$(sed -n 's/^#ifndef NETTLE_\(.*_H\(_INCLUDED\)*\)/\1/p' $dst)
+ sed 's/\(NETTLE_'$g'\)/GNUTLS_LIB_NETTLE_CHACHA_\1/' $dst > $dst-t && \
+ mv $dst-t $dst
+ fi
+ ;;
+ esac
+ case $dst in
+ *.h)
+ # Add prefix to function symbols avoid clashing with the public ones.
+ sed -e 's/^#define \(.*\) nettle_\1/#define \1 gnutls_nettle_chacha_\1/' \
+ -e 's/^#define \(.*\) _nettle_\1/#define \1 _gnutls_nettle_chacha_\1/' $dst > $dst-t && \
+ mv $dst-t $dst
+ ;;
+ esac
+ else
+ echo "Error: $src not found" 1>&2
+ exit 1
+ fi
+done
diff --git a/devel/libgnutls-latest-x86_64.abi b/devel/libgnutls-latest-x86_64.abi
index 6fa8640926..78d61778e4 100644
--- a/devel/libgnutls-latest-x86_64.abi
+++ b/devel/libgnutls-latest-x86_64.abi
@@ -1506,6 +1506,8 @@
<enumerator name='GNUTLS_CIPHER_AES_128_XTS' value='32'/>
<enumerator name='GNUTLS_CIPHER_AES_256_XTS' value='33'/>
<enumerator name='GNUTLS_CIPHER_GOST28147_TC26Z_CNT' value='34'/>
+ <enumerator name='GNUTLS_CIPHER_CHACHA20_64' value='35'/>
+ <enumerator name='GNUTLS_CIPHER_CHACHA20_32' value='36'/>
<enumerator name='GNUTLS_CIPHER_IDEA_PGP_CFB' value='200'/>
<enumerator name='GNUTLS_CIPHER_3DES_PGP_CFB' value='201'/>
<enumerator name='GNUTLS_CIPHER_CAST5_PGP_CFB' value='202'/>
diff --git a/devel/nettle b/devel/nettle
-Subproject d1dbba1e7fcf4ad54e5d3435e381ae336c36cf2
+Subproject dedba6ff09f78b96dbc5a2b3a13fb8825f438d3
diff --git a/lib/algorithms/ciphers.c b/lib/algorithms/ciphers.c
index fd47c13b66..1318c88caf 100644
--- a/lib/algorithms/ciphers.c
+++ b/lib/algorithms/ciphers.c
@@ -136,6 +136,22 @@ static const cipher_entry_st algorithms[] = {
.type = CIPHER_STREAM,
.explicit_iv = 0,
.cipher_iv = 8},
+ { .name = "CHACHA20-32",
+ .id = GNUTLS_CIPHER_CHACHA20_32,
+ .blocksize = 64,
+ .keysize = 32,
+ .type = CIPHER_STREAM,
+ .explicit_iv = 0,
+ /* IV includes counter */
+ .cipher_iv = 16},
+ { .name = "CHACHA20-64",
+ .id = GNUTLS_CIPHER_CHACHA20_64,
+ .blocksize = 64,
+ .keysize = 32,
+ .type = CIPHER_STREAM,
+ .explicit_iv = 0,
+ /* IV includes counter */
+ .cipher_iv = 16},
{ .name = "CAMELLIA-256-CBC",
.id = GNUTLS_CIPHER_CAMELLIA_256_CBC,
.blocksize = 16,
diff --git a/lib/crypto-selftests.c b/lib/crypto-selftests.c
index 5f0a4ec8be..a1a308f410 100644
--- a/lib/crypto-selftests.c
+++ b/lib/crypto-selftests.c
@@ -570,6 +570,19 @@ const struct cipher_vectors_st aes256_xts_vectors[] = {
},
};
+const struct cipher_vectors_st chacha20_32_vectors[] = { /* RFC8439 */
+ {
+ STR(key, key_size,
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"),
+ STR(plaintext, plaintext_size,
+ "\x4c\x61\x64\x69\x65\x73\x20\x61\x6e\x64\x20\x47\x65\x6e\x74\x6c\x65\x6d\x65\x6e\x20\x6f\x66\x20\x74\x68\x65\x20\x63\x6c\x61\x73\x73\x20\x6f\x66\x20\x27\x39\x39\x3a\x20\x49\x66\x20\x49\x20\x63\x6f\x75\x6c\x64\x20\x6f\x66\x66\x65\x72\x20\x79\x6f\x75\x20\x6f\x6e\x6c\x79\x20\x6f\x6e\x65\x20\x74\x69\x70\x20\x66\x6f\x72\x20\x74\x68\x65\x20\x66\x75\x74\x75\x72\x65\x2c\x20\x73\x75\x6e\x73\x63\x72\x65\x65\x6e\x20\x77\x6f\x75\x6c\x64\x20\x62\x65\x20\x69\x74\x2e"),
+ .ciphertext = (uint8_t *)
+ "\x6e\x2e\x35\x9a\x25\x68\xf9\x80\x41\xba\x07\x28\xdd\x0d\x69\x81\xe9\x7e\x7a\xec\x1d\x43\x60\xc2\x0a\x27\xaf\xcc\xfd\x9f\xae\x0b\xf9\x1b\x65\xc5\x52\x47\x33\xab\x8f\x59\x3d\xab\xcd\x62\xb3\x57\x16\x39\xd6\x24\xe6\x51\x52\xab\x8f\x53\x0c\x35\x9f\x08\x61\xd8\x07\xca\x0d\xbf\x50\x0d\x6a\x61\x56\xa3\x8e\x08\x8a\x22\xb6\x5e\x52\xbc\x51\x4d\x16\xcc\xf8\x06\x81\x8c\xe9\x1a\xb7\x79\x37\x36\x5a\xf9\x0b\xbf\x74\xa3\x5b\xe6\xb4\x0b\x8e\xed\xf2\x78\x5e\x42\x87\x4d",
+ STR(iv, iv_size,
+ "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4a\x00\x00\x00\x00")
+ },
+};
+
static int test_cipher(gnutls_cipher_algorithm_t cipher,
const struct cipher_vectors_st *vectors,
size_t vectors_size, unsigned flags)
@@ -1912,6 +1925,13 @@ int gnutls_cipher_self_test(unsigned flags, gnutls_cipher_algorithm_t cipher)
FALLTHROUGH;
CASE(GNUTLS_CIPHER_AES_256_XTS, test_cipher,
aes256_xts_vectors);
+ FALLTHROUGH;
+ NON_FIPS_CASE(GNUTLS_CIPHER_CHACHA20_32, test_cipher,
+ chacha20_32_vectors);
+ FALLTHROUGH;
+ /* The same test vector for _32 variant should work */
+ NON_FIPS_CASE(GNUTLS_CIPHER_CHACHA20_64, test_cipher,
+ chacha20_32_vectors);
#if ENABLE_GOST
FALLTHROUGH;
NON_FIPS_CASE(GNUTLS_CIPHER_GOST28147_CPA_CFB, test_cipher,
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index cfc1f35e92..3592d3c071 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -113,6 +113,8 @@ extern "C" {
* @GNUTLS_CIPHER_CAMELLIA_256_GCM: CAMELLIA in GCM mode with 256-bit keys (AEAD).
* @GNUTLS_CIPHER_SALSA20_256: Salsa20 with 256-bit keys.
* @GNUTLS_CIPHER_ESTREAM_SALSA20_256: Estream's Salsa20 variant with 256-bit keys.
+ * @GNUTLS_CIPHER_CHACHA20_32: Chacha20 cipher with 96-bit nonces and 32-bit block counters.
+ * @GNUTLS_CIPHER_CHACHA20_64: Chacha20 cipher with 64-bit nonces and 64-bit block counters.
* @GNUTLS_CIPHER_CHACHA20_POLY1305: The Chacha20 cipher with the Poly1305 authenticator (AEAD).
* @GNUTLS_CIPHER_GOST28147_TC26Z_CFB: GOST 28147-89 (Magma) cipher in CFB mode with TC26 Z S-box.
* @GNUTLS_CIPHER_GOST28147_CPA_CFB: GOST 28147-89 (Magma) cipher in CFB mode with CryptoPro A S-box.
@@ -174,6 +176,8 @@ typedef enum gnutls_cipher_algorithm {
GNUTLS_CIPHER_AES_128_XTS = 32,
GNUTLS_CIPHER_AES_256_XTS = 33,
GNUTLS_CIPHER_GOST28147_TC26Z_CNT = 34,
+ GNUTLS_CIPHER_CHACHA20_64 = 35,
+ GNUTLS_CIPHER_CHACHA20_32 = 36,
/* used only for PGP internals. Ignored in TLS/SSL
*/
diff --git a/lib/nettle/Makefile.am b/lib/nettle/Makefile.am
index ab49f7baed..84bb90a247 100644
--- a/lib/nettle/Makefile.am
+++ b/lib/nettle/Makefile.am
@@ -148,3 +148,11 @@ libcrypto_la_SOURCES += \
curve448/ed448-shake256.c curve448/ed448-shake256-pubkey.c \
curve448/ed448-shake256-sign.c curve448/ed448-shake256-verify.c
endif
+
+if NEED_CHACHA
+libcrypto_la_SOURCES += \
+ chacha/chacha-core-internal.c chacha/chacha-crypt.c \
+ chacha/chacha-internal.h chacha/chacha-poly1305.c \
+ chacha/chacha-poly1305.h chacha/chacha-set-key.c \
+ chacha/chacha-set-nonce.c chacha/chacha.h
+endif
diff --git a/lib/nettle/cipher.c b/lib/nettle/cipher.c
index 5e9f25b2ec..5a8836bbf5 100644
--- a/lib/nettle/cipher.c
+++ b/lib/nettle/cipher.c
@@ -45,7 +45,13 @@
#include <nettle/cbc.h>
#include <nettle/gcm.h>
#include <nettle/ccm.h>
+#ifdef HAVE_NETTLE_CHACHA_SET_COUNTER
+#include <nettle/chacha.h>
#include <nettle/chacha-poly1305.h>
+#else
+#include "chacha/chacha.h"
+#include "chacha/chacha-poly1305.h"
+#endif
#ifdef HAVE_NETTLE_CFB8_ENCRYPT
#include <nettle/cfb.h>
#else
@@ -247,6 +253,22 @@ _ccm_decrypt(struct nettle_cipher_ctx *ctx,
}
static void
+_chacha_set_nonce(struct chacha_ctx *ctx,
+ size_t length, const uint8_t *nonce)
+{
+ chacha_set_nonce(ctx, nonce + CHACHA_COUNTER_SIZE);
+ chacha_set_counter(ctx, nonce);
+}
+
+static void
+_chacha_set_nonce96(struct chacha_ctx *ctx,
+ size_t length, const uint8_t *nonce)
+{
+ chacha_set_nonce96(ctx, nonce + CHACHA_COUNTER32_SIZE);
+ chacha_set_counter32(ctx, nonce);
+}
+
+static void
_chacha_poly1305_set_nonce (struct chacha_poly1305_ctx *ctx,
size_t length, const uint8_t *nonce)
{
@@ -607,6 +629,36 @@ static const struct nettle_cipher_st builtin_ciphers[] = {
.set_decrypt_key = (nettle_set_key_func*)salsa20_256_set_key,
.max_iv_size = SALSA20_NONCE_SIZE,
},
+ { .algo = GNUTLS_CIPHER_CHACHA20_32,
+ .block_size = 1,
+ .key_size = CHACHA_KEY_SIZE,
+ .encrypt_block = (nettle_cipher_func*)chacha_crypt32,
+ .decrypt_block = (nettle_cipher_func*)chacha_crypt32,
+
+ .ctx_size = sizeof(struct chacha_ctx),
+ .encrypt = _stream_encrypt,
+ .decrypt = _stream_encrypt,
+ .set_encrypt_key = (nettle_set_key_func*)chacha_set_key,
+ .set_decrypt_key = (nettle_set_key_func*)chacha_set_key,
+ .set_iv = (setiv_func)_chacha_set_nonce96,
+ /* we allow setting the initial block counter as part of nonce */
+ .max_iv_size = CHACHA_NONCE96_SIZE + CHACHA_COUNTER32_SIZE,
+ },
+ { .algo = GNUTLS_CIPHER_CHACHA20_64,
+ .block_size = 1,
+ .key_size = CHACHA_KEY_SIZE,
+ .encrypt_block = (nettle_cipher_func*)chacha_crypt,
+ .decrypt_block = (nettle_cipher_func*)chacha_crypt,
+
+ .ctx_size = sizeof(struct chacha_ctx),
+ .encrypt = _stream_encrypt,
+ .decrypt = _stream_encrypt,
+ .set_encrypt_key = (nettle_set_key_func*)chacha_set_key,
+ .set_decrypt_key = (nettle_set_key_func*)chacha_set_key,
+ .set_iv = (setiv_func)_chacha_set_nonce,
+ /* we allow setting the initial block counter as part of nonce */
+ .max_iv_size = CHACHA_NONCE_SIZE + CHACHA_COUNTER_SIZE,
+ },
{ .algo = GNUTLS_CIPHER_CHACHA20_POLY1305,
.block_size = CHACHA_POLY1305_BLOCK_SIZE,
.key_size = CHACHA_POLY1305_KEY_SIZE,