diff options
author | Daiki Ueno <ueno@gnu.org> | 2020-03-19 12:49:08 +0000 |
---|---|---|
committer | Daiki Ueno <ueno@gnu.org> | 2020-03-19 12:49:08 +0000 |
commit | f523ca002e8ce823bca376e7fefe6169c1bdb636 (patch) | |
tree | 126d66686f58ff81664af15a181bb2b885be0481 | |
parent | ea2a81e5bd115826d2ecd0b0ecc634c95b285a48 (diff) | |
parent | a682bdd288a03408a99f2cc215f89f31970b4dfa (diff) | |
download | gnutls-f523ca002e8ce823bca376e7fefe6169c1bdb636.tar.gz |
Merge branch 'tmp-chacha' into 'master'
cipher: expose raw ChaCha20 cipher
See merge request gnutls/gnutls!1210
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | bootstrap.conf | 1 | ||||
-rw-r--r-- | configure.ac | 9 | ||||
-rwxr-xr-x | devel/import-chacha-from-nettle.sh | 83 | ||||
-rw-r--r-- | devel/libgnutls-latest-x86_64.abi | 2 | ||||
m--------- | devel/nettle | 0 | ||||
-rw-r--r-- | lib/algorithms/ciphers.c | 16 | ||||
-rw-r--r-- | lib/crypto-selftests.c | 20 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 4 | ||||
-rw-r--r-- | lib/nettle/Makefile.am | 8 | ||||
-rw-r--r-- | lib/nettle/cipher.c | 52 |
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, |