]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
cipher: allow setting ChaCha20 initial block counter
authorDaiki Ueno <dueno@redhat.com>
Sat, 14 Mar 2020 05:09:56 +0000 (06:09 +0100)
committerDaiki Ueno <dueno@redhat.com>
Thu, 19 Mar 2020 08:28:31 +0000 (09:28 +0100)
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>
lib/algorithms/ciphers.c
lib/crypto-selftests.c
lib/includes/gnutls/gnutls.h.in
lib/nettle/cipher.c

index 207b0483fa190f3fd60e8bfc4f442642cbc03be3..1318c88cafddb8b2069c2f37dd592eac9f890138 100644 (file)
@@ -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,
index 5f0a4ec8bed8a17dc521a3ec32a569c71b353911..a1a308f4107035760a47103285a8208d7dc18a9f 100644 (file)
@@ -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,
index e88fe86918ddce48012ec2656de0fd64b4afb7d5..3592d3c071b1f5153262c1ff2b33eabfcbbc4d56 100644 (file)
@@ -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
         */
index e46ce4afe4e3c0c16f8ef31c776c5e0f9de34b9d..5a8836bbf5345838ce7157a2323c4a6d691ac94f 100644 (file)
 #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,