summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <dueno@redhat.com>2020-03-14 06:09:56 +0100
committerDaiki Ueno <dueno@redhat.com>2020-03-19 09:28:31 +0100
commit15ec7e3c698531935fe09fdf4d6133629ae00688 (patch)
tree2a3c708198be57a3d42255e69440f6af3c369e89
parent252a4dd5090083ede6d8fdecbd2241b2b8a001b5 (diff)
downloadgnutls-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.c11
-rw-r--r--lib/crypto-selftests.c20
-rw-r--r--lib/includes/gnutls/gnutls.h.in4
-rw-r--r--lib/nettle/cipher.c39
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,