diff options
author | Daiki Ueno <dueno@redhat.com> | 2020-03-14 06:09:56 +0100 |
---|---|---|
committer | Daiki Ueno <dueno@redhat.com> | 2020-03-19 09:28:31 +0100 |
commit | 15ec7e3c698531935fe09fdf4d6133629ae00688 (patch) | |
tree | 2a3c708198be57a3d42255e69440f6af3c369e89 | |
parent | 252a4dd5090083ede6d8fdecbd2241b2b8a001b5 (diff) | |
download | gnutls-15ec7e3c698531935fe09fdf4d6133629ae00688.tar.gz |
cipher: allow setting ChaCha20 initial block counter
This also introduces GNUTLS_CIPHER_CHACHA20_32, which is a 96-bit
nonce variant of GNUTLS_CIPHER_CHACHA20_64.
Signed-off-by: Daiki Ueno <dueno@redhat.com>
-rw-r--r-- | lib/algorithms/ciphers.c | 11 | ||||
-rw-r--r-- | lib/crypto-selftests.c | 20 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 4 | ||||
-rw-r--r-- | lib/nettle/cipher.c | 39 |
4 files changed, 68 insertions, 6 deletions
diff --git a/lib/algorithms/ciphers.c b/lib/algorithms/ciphers.c index 207b0483fa..1318c88caf 100644 --- a/lib/algorithms/ciphers.c +++ b/lib/algorithms/ciphers.c @@ -136,13 +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, - .cipher_iv = 8}, + /* 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 e88fe86918..3592d3c071 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -113,7 +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_64: Chacha20 cipher with 64-bit nonces. + * @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. @@ -176,6 +177,7 @@ typedef enum gnutls_cipher_algorithm { 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/cipher.c b/lib/nettle/cipher.c index e46ce4afe4..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,10 +253,19 @@ _ccm_decrypt(struct nettle_cipher_ctx *ctx, } static void -_chacha_set_nonce (struct chacha_poly1305_ctx *ctx, - size_t length, const uint8_t *nonce) +_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_nonce(ctx, nonce); + chacha_set_nonce96(ctx, nonce + CHACHA_COUNTER32_SIZE); + chacha_set_counter32(ctx, nonce); } static void @@ -614,6 +629,21 @@ 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, @@ -626,7 +656,8 @@ static const struct nettle_cipher_st builtin_ciphers[] = { .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, - .max_iv_size = CHACHA_NONCE_SIZE, + /* 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, |