summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <ueno@gnu.org>2020-04-26 19:27:11 +0200
committerDaiki Ueno <ueno@gnu.org>2020-05-03 17:25:36 +0200
commit8fa93575dcfbe34c9667ac6b1a0e20ee3a9c5f7f (patch)
treea8c70d6419d2ddcc3104a85e36315cb9cf06636c
parent56d913a1d73b3363ee9781d8cf2aba53661a7fdb (diff)
downloadgnutls-tmp-siv.tar.gz
nettle: expose SIV-CMAC through the AEAD interfacetmp-siv
This adds a couple of new cipher algorithms GNUTLS_CIPHER_AES_128_SIV and GNUTLS_CIPHER_AES_256_SIV, exposing nettle_siv_cmac_aes{128,256}* functions. Note that they can only used with the AEAD interface and authentication tags are prepended (not appended) to the ciphertext. Signed-off-by: Daiki Ueno <ueno@gnu.org>
-rw-r--r--NEWS6
-rw-r--r--devel/libdane-latest-x86_64.abi4
-rw-r--r--devel/libgnutls-latest-x86_64.abi2
-rw-r--r--lib/algorithms/ciphers.c18
-rw-r--r--lib/crypto-selftests.c109
-rw-r--r--lib/includes/gnutls/gnutls.h.in8
-rw-r--r--lib/nettle/cipher.c83
7 files changed, 223 insertions, 7 deletions
diff --git a/NEWS b/NEWS
index 50cb2253a5..fe1c6035af 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,12 @@ Copyright (C) 2000-2016 Free Software Foundation, Inc.
Copyright (C) 2013-2019 Nikos Mavrogiannopoulos
See the end for copying conditions.
+* Version 3.6.14 (unreleased)
+
+** API and ABI modifications:
+GNUTLS_CIPHER_AES_128_SIV: Added
+GNUTLS_CIPHER_AES_256_SIV: Added
+
* Version 3.6.13 (released 2020-03-31)
** libgnutls: Fix a DTLS-protocol regression (caused by TLS1.3 support), since 3.6.3.
diff --git a/devel/libdane-latest-x86_64.abi b/devel/libdane-latest-x86_64.abi
index 6974f143a9..cf25f40e1e 100644
--- a/devel/libdane-latest-x86_64.abi
+++ b/devel/libdane-latest-x86_64.abi
@@ -252,6 +252,10 @@
<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_AES_128_SIV' value='37'/>
+ <enumerator name='GNUTLS_CIPHER_AES_256_SIV' value='38'/>
<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/libgnutls-latest-x86_64.abi b/devel/libgnutls-latest-x86_64.abi
index 8aa81a55dd..cc44d1898e 100644
--- a/devel/libgnutls-latest-x86_64.abi
+++ b/devel/libgnutls-latest-x86_64.abi
@@ -1515,6 +1515,8 @@
<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_AES_128_SIV' value='37'/>
+ <enumerator name='GNUTLS_CIPHER_AES_256_SIV' value='38'/>
<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/lib/algorithms/ciphers.c b/lib/algorithms/ciphers.c
index 1318c88caf..59dc7ea7fb 100644
--- a/lib/algorithms/ciphers.c
+++ b/lib/algorithms/ciphers.c
@@ -270,6 +270,24 @@ static const cipher_entry_st algorithms[] = {
.type = CIPHER_BLOCK,
.explicit_iv = 16,
.cipher_iv = 16},
+ { .name = "AES-128-SIV",
+ .id = GNUTLS_CIPHER_AES_128_SIV,
+ .blocksize = 16,
+ .keysize = 32,
+ .type = CIPHER_AEAD,
+ .explicit_iv = 16,
+ .cipher_iv = 16,
+ .flags = GNUTLS_CIPHER_FLAG_ONLY_AEAD,
+ .tagsize = 16},
+ { .name = "AES-256-SIV",
+ .id = GNUTLS_CIPHER_AES_256_SIV,
+ .blocksize = 16,
+ .keysize = 64,
+ .type = CIPHER_AEAD,
+ .explicit_iv = 16,
+ .cipher_iv = 16,
+ .flags = GNUTLS_CIPHER_FLAG_ONLY_AEAD,
+ .tagsize = 16},
{ .name = "GOST28147-TC26Z-CNT",
.id = GNUTLS_CIPHER_GOST28147_TC26Z_CNT,
.blocksize = 8,
diff --git a/lib/crypto-selftests.c b/lib/crypto-selftests.c
index a1a308f410..f904b029b2 100644
--- a/lib/crypto-selftests.c
+++ b/lib/crypto-selftests.c
@@ -73,6 +73,7 @@ struct cipher_aead_vectors_st {
const uint8_t *iv;
const uint8_t *tag;
unsigned tag_size;
+ unsigned tag_prepended;
};
const struct cipher_aead_vectors_st chacha_poly1305_vectors[] = {
@@ -570,6 +571,60 @@ const struct cipher_vectors_st aes256_xts_vectors[] = {
},
};
+const struct cipher_aead_vectors_st aes128_siv_vectors[] = {
+ {
+ STR(key, key_size,
+ "\x7f\x7e\x7d\x7c\x7b\x7a\x79\x78\x77\x76\x75\x74\x73\x72\x71\x70"
+ "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"),
+ STR(auth, auth_size,
+ "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff"
+ "\xde\xad\xda\xda\xde\xad\xda\xda\xff\xee\xdd\xcc\xbb\xaa\x99\x88"
+ "\x77\x66\x55\x44\x33\x22\x11\x00"),
+ STR(plaintext, plaintext_size,
+ "\x74\x68\x69\x73\x20\x69\x73\x20\x73\x6f\x6d\x65\x20\x70\x6c\x61"
+ "\x69\x6e\x74\x65\x78\x74\x20\x74\x6f\x20\x65\x6e\x63\x72\x79\x70"
+ "\x74\x20\x75\x73\x69\x6e\x67\x20\x53\x49\x56\x2d\x41\x45\x53"),
+ .ciphertext = (uint8_t *)
+ "\xa4\xff\xb8\x7f\xdb\xa9\x7c\x89\x44\xa6\x23\x25\xf1\x33\xb4\xe0"
+ "\x1c\xa5\x52\x76\xe2\x26\x1c\x1a\x1d\x1d\x42\x48\xd1\xda\x30\xba"
+ "\x52\xb9\xc8\xd7\x95\x5d\x65\xc8\xd2\xce\x6e\xb7\xe3\x67\xd0",
+ STR(iv, iv_size,
+ "\x02\x03\x04"),
+ .tag_size = 16,
+ .tag = (void *)
+ "\xf1\xdb\xa3\x3d\xe5\xb3\x36\x9e\x88\x3f\x67\xb6\xfc\x82\x3c\xee",
+ .tag_prepended = 1,
+ }
+};
+
+const struct cipher_aead_vectors_st aes256_siv_vectors[] = {
+ {
+ STR(key, key_size,
+ "\xc2\x7d\xf2\xfd\xae\xc3\x5d\x4a\x2a\x41\x2a\x50\xc3\xe8\xc4\x7d"
+ "\x2d\x56\x8e\x91\xa3\x8e\x54\x14\x8a\xbd\xc0\xb6\xe8\x6c\xaf\x87"
+ "\x69\x5c\x0a\x8a\xdf\x4c\x5f\x8e\xb2\xc6\xc8\xb1\x36\x52\x98\x64"
+ "\xf3\xb8\x4b\x3a\xe8\xe3\x67\x6c\xe7\x60\xc4\x61\xf3\xa1\x3e\x83"),
+ STR(auth, auth_size,
+ "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff"
+ "\xde\xad\xda\xda\xde\xad\xda\xda\xff\xee\xdd\xcc\xbb\xaa\x99\x88"
+ "\x77\x66\x55\x44\x33\x22\x11\x00"),
+ STR(plaintext, plaintext_size,
+ "\x74\x68\x69\x73\x20\x69\x73\x20\x73\x6f\x6d\x65\x20\x70\x6c\x61"
+ "\x69\x6e\x74\x65\x78\x74\x20\x74\x6f\x20\x65\x6e\x63\x72\x79\x70"
+ "\x74\x20\x75\x73\x69\x6e\x67\x20\x53\x49\x56\x2d\x41\x45\x53"),
+ .ciphertext = (uint8_t *)
+ "\x50\x93\x3d\xa8\x04\x7b\xc3\x06\xfa\xba\xf0\xc3\xd9\xfa\x84\x71"
+ "\xc7\x0a\x7d\xef\x39\xa2\xf9\x1d\x68\xa2\x02\x1c\x99\xac\x7e\x2a\x24"
+ "\x53\x5a\x13\x4b\xa2\x3e\xc1\x57\x87\xce\xbe\x5c\x53\xcc",
+ STR(iv, iv_size,
+ "\x09\xf9\x11\x02\x9d\x74\xe3\x5b\xd8\x41\x56\xc5\x63\x56\x88\xc0"),
+ .tag_size = 16,
+ .tag = (void *)
+ "\x5a\x97\x9b\x0d\xa5\x8f\xde\x80\x51\x62\x1a\xe6\xbf\x96\xfe\xda",
+ .tag_prepended = 1,
+ }
+};
+
const struct cipher_vectors_st chacha20_32_vectors[] = { /* RFC8439 */
{
STR(key, key_size,
@@ -1002,6 +1057,8 @@ static int test_cipher_aead_scatter(gnutls_cipher_algorithm_t cipher,
int auth_iov_len;
int iov_len;
giovec_t iov[IOV_PARTS];
+ const uint8_t *tag;
+ uint8_t *ciphertext;
_gnutls_debug_log("running scatter (iovec) tests for: %s\n",
gnutls_cipher_get_name(cipher));
@@ -1055,16 +1112,26 @@ static int test_cipher_aead_scatter(gnutls_cipher_algorithm_t cipher,
(GNUTLS_E_SELF_TEST_ERROR);
}
- if (memcmp(tmp+vectors[i].plaintext_size, vectors[i].tag, tag_size) != 0) {
+ if (vectors[i].tag_prepended)
+ tag = tmp;
+ else
+ tag = tmp+vectors[i].plaintext_size;
+
+ if (memcmp(tag, vectors[i].tag, tag_size) != 0) {
_gnutls_debug_log
("%s test vector %d failed (tag)!\n",
gnutls_cipher_get_name(cipher), i);
return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
}
+ if (vectors[i].tag_prepended)
+ ciphertext = tmp+vectors[i].tag_size;
+ else
+ ciphertext = tmp;
+
if (vectors[i].plaintext_size > 0) {
if (memcmp
- (tmp, vectors[i].ciphertext,
+ (ciphertext, vectors[i].ciphertext,
vectors[i].plaintext_size) != 0) {
_gnutls_debug_log
("%s test vector %d failed!\n",
@@ -1134,16 +1201,26 @@ static int test_cipher_aead_scatter(gnutls_cipher_algorithm_t cipher,
(GNUTLS_E_SELF_TEST_ERROR);
}
- if (memcmp(tmp+vectors[i].plaintext_size, vectors[i].tag, tag_size) != 0) {
+ if (vectors[i].tag_prepended)
+ tag = tmp;
+ else
+ tag = tmp+vectors[i].plaintext_size;
+
+ if (memcmp(tag, vectors[i].tag, tag_size) != 0) {
_gnutls_debug_log
("%s test vector %d failed (tag)!\n",
gnutls_cipher_get_name(cipher), i);
return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
}
+ if (vectors[i].tag_prepended)
+ ciphertext = tmp+vectors[i].tag_size;
+ else
+ ciphertext = tmp;
+
if (vectors[i].plaintext_size > 0) {
if (memcmp
- (tmp, vectors[i].ciphertext,
+ (ciphertext, vectors[i].ciphertext,
vectors[i].plaintext_size) != 0) {
_gnutls_debug_log
("%s test vector %d failed!\n",
@@ -1182,7 +1259,9 @@ static int test_cipher_aead(gnutls_cipher_algorithm_t cipher,
uint8_t tmp2[384];
gnutls_datum_t key, iv;
size_t s, s2;
+ const uint8_t *tag;
unsigned tag_size;
+ uint8_t *ciphertext;
_gnutls_debug_log("running tests for: %s\n",
gnutls_cipher_get_name(cipher));
@@ -1231,16 +1310,26 @@ static int test_cipher_aead(gnutls_cipher_algorithm_t cipher,
(GNUTLS_E_SELF_TEST_ERROR);
}
- if (memcmp(tmp+vectors[i].plaintext_size, vectors[i].tag, tag_size) != 0) {
+ if (vectors[i].tag_prepended)
+ tag = tmp;
+ else
+ tag = tmp+vectors[i].plaintext_size;
+
+ if (memcmp(tag, vectors[i].tag, tag_size) != 0) {
_gnutls_debug_log
("%s test vector %d failed (tag)!\n",
gnutls_cipher_get_name(cipher), i);
return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
}
+ if (vectors[i].tag_prepended)
+ ciphertext = tmp+vectors[i].tag_size;
+ else
+ ciphertext = tmp;
+
if (vectors[i].plaintext_size > 0) {
if (memcmp
- (tmp, vectors[i].ciphertext,
+ (ciphertext, vectors[i].ciphertext,
vectors[i].plaintext_size) != 0) {
_gnutls_debug_log
("%s test vector %d failed!\n",
@@ -1275,7 +1364,7 @@ static int test_cipher_aead(gnutls_cipher_algorithm_t cipher,
/* test tag verification */
if (s > 0) {
- tmp[0]++;
+ (*ciphertext)++;
s2 = sizeof(tmp2);
ret =
@@ -1926,6 +2015,12 @@ int gnutls_cipher_self_test(unsigned flags, gnutls_cipher_algorithm_t cipher)
CASE(GNUTLS_CIPHER_AES_256_XTS, test_cipher,
aes256_xts_vectors);
FALLTHROUGH;
+ NON_FIPS_CASE(GNUTLS_CIPHER_AES_128_SIV, test_cipher_aead,
+ aes128_siv_vectors);
+ FALLTHROUGH;
+ NON_FIPS_CASE(GNUTLS_CIPHER_AES_256_SIV, test_cipher_aead,
+ aes256_siv_vectors);
+ FALLTHROUGH;
NON_FIPS_CASE(GNUTLS_CIPHER_CHACHA20_32, test_cipher,
chacha20_32_vectors);
FALLTHROUGH;
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index fdcf914f42..7d9870996a 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -137,6 +137,12 @@ extern "C" {
* @GNUTLS_CIPHER_AES192_PGP_CFB: AES in CFB mode with 192-bit keys (placeholder - unsupported).
* @GNUTLS_CIPHER_AES256_PGP_CFB: AES in CFB mode with 256-bit keys (placeholder - unsupported).
* @GNUTLS_CIPHER_TWOFISH_PGP_CFB: Twofish in CFB mode (placeholder - unsupported).
+ * @GNUTLS_CIPHER_AES_128_SIV: AES in SIV mode with 128-bit key.
+ * @GNUTLS_CIPHER_AES_256_SIV: AES in SIV mode with 256-bit key.
+ * Note that the SIV ciphers can only be used with
+ * the AEAD interface, and the IV plays a role as
+ * the authentication tag while it is prepended to
+ * the cipher text.
*
* Enumeration of different symmetric encryption algorithms.
*/
@@ -178,6 +184,8 @@ typedef enum gnutls_cipher_algorithm {
GNUTLS_CIPHER_GOST28147_TC26Z_CNT = 34,
GNUTLS_CIPHER_CHACHA20_64 = 35,
GNUTLS_CIPHER_CHACHA20_32 = 36,
+ GNUTLS_CIPHER_AES_128_SIV = 37,
+ GNUTLS_CIPHER_AES_256_SIV = 38,
/* used only for PGP internals. Ignored in TLS/SSL
*/
diff --git a/lib/nettle/cipher.c b/lib/nettle/cipher.c
index 6624e6b84c..70a6509f2b 100644
--- a/lib/nettle/cipher.c
+++ b/lib/nettle/cipher.c
@@ -62,6 +62,11 @@
#else
#include "xts.h"
#endif
+#ifdef HAVE_NETTLE_SIV_CMAC_AES128_SET_KEY
+#include <nettle/siv-cmac.h>
+#else
+#include "siv-cmac.h"
+#endif
#include <fips.h>
struct nettle_cipher_ctx;
@@ -257,6 +262,62 @@ _ccm_decrypt(struct nettle_cipher_ctx *ctx,
}
static void
+_siv_cmac_aes128_encrypt_message(struct nettle_cipher_ctx *ctx,
+ size_t nonce_size, const void *nonce,
+ size_t auth_size, const void *auth,
+ size_t tag_size,
+ size_t length, uint8_t * dst,
+ const uint8_t * src)
+{
+ siv_cmac_aes128_encrypt_message((void*)ctx->ctx_ptr,
+ nonce_size, nonce,
+ auth_size, auth,
+ length, dst, src);
+}
+
+static int
+_siv_cmac_aes128_decrypt_message(struct nettle_cipher_ctx *ctx,
+ size_t nonce_size, const void *nonce,
+ size_t auth_size, const void *auth,
+ size_t tag_size,
+ size_t length, uint8_t * dst,
+ const uint8_t * src)
+{
+ return siv_cmac_aes128_decrypt_message((void*)ctx->ctx_ptr,
+ nonce_size, nonce,
+ auth_size, auth,
+ length, dst, src);
+}
+
+static void
+_siv_cmac_aes256_encrypt_message(struct nettle_cipher_ctx *ctx,
+ size_t nonce_size, const void *nonce,
+ size_t auth_size, const void *auth,
+ size_t tag_size,
+ size_t length, uint8_t * dst,
+ const uint8_t * src)
+{
+ siv_cmac_aes256_encrypt_message((void*)ctx->ctx_ptr,
+ nonce_size, nonce,
+ auth_size, auth,
+ length, dst, src);
+}
+
+static int
+_siv_cmac_aes256_decrypt_message(struct nettle_cipher_ctx *ctx,
+ size_t nonce_size, const void *nonce,
+ size_t auth_size, const void *auth,
+ size_t tag_size,
+ size_t length, uint8_t * dst,
+ const uint8_t * src)
+{
+ return siv_cmac_aes256_decrypt_message((void*)ctx->ctx_ptr,
+ nonce_size, nonce,
+ auth_size, auth,
+ length, dst, src);
+}
+
+static void
_chacha_set_nonce(struct chacha_ctx *ctx,
size_t length, const uint8_t *nonce)
{
@@ -865,6 +926,28 @@ static const struct nettle_cipher_st builtin_ciphers[] = {
.set_decrypt_key = (nettle_set_key_func*)_xts_aes256_set_decrypt_key,
.max_iv_size = AES_BLOCK_SIZE,
},
+ { .algo = GNUTLS_CIPHER_AES_128_SIV,
+ .block_size = SIV_BLOCK_SIZE,
+ .key_size = SIV_CMAC_AES128_KEY_SIZE,
+
+ .ctx_size = sizeof(struct siv_cmac_aes128_ctx),
+ .aead_encrypt = (aead_encrypt_func)_siv_cmac_aes128_encrypt_message,
+ .aead_decrypt = (aead_decrypt_func)_siv_cmac_aes128_decrypt_message,
+ .set_encrypt_key = (nettle_set_key_func*)siv_cmac_aes128_set_key,
+ .set_decrypt_key = (nettle_set_key_func*)siv_cmac_aes128_set_key,
+ .max_iv_size = SIV_DIGEST_SIZE,
+ },
+ { .algo = GNUTLS_CIPHER_AES_256_SIV,
+ .block_size = SIV_BLOCK_SIZE,
+ .key_size = SIV_CMAC_AES256_KEY_SIZE,
+
+ .ctx_size = sizeof(struct siv_cmac_aes256_ctx),
+ .aead_encrypt = (aead_encrypt_func)_siv_cmac_aes256_encrypt_message,
+ .aead_decrypt = (aead_decrypt_func)_siv_cmac_aes256_decrypt_message,
+ .set_encrypt_key = (nettle_set_key_func*)siv_cmac_aes256_set_key,
+ .set_decrypt_key = (nettle_set_key_func*)siv_cmac_aes256_set_key,
+ .max_iv_size = SIV_DIGEST_SIZE,
+ },
};
static int wrap_nettle_cipher_exists(gnutls_cipher_algorithm_t algo)