Merge pull request #323
Confidentiality and integrity limits for AEAD
diff --git a/include/picotls.h b/include/picotls.h
index 3012ab8..0ffe7d7 100644
--- a/include/picotls.h
+++ b/include/picotls.h
@@ -78,11 +78,17 @@
#define PTLS_AES_IV_SIZE 16
#define PTLS_AESGCM_IV_SIZE 12
#define PTLS_AESGCM_TAG_SIZE 16
+#define PTLS_AESGCM_CONFIDENTIALITY_LIMIT 0x2000000 /* 2^25 */
+#define PTLS_AESGCM_INTEGRITY_LIMIT UINT64_C(0x40000000000000) /* 2^54 */
+#define PTLS_AESCCM_CONFIDENTIALITY_LIMIT 0xB504F3 /* 2^23.5 */
+#define PTLS_AESCCM_INTEGRITY_LIMIT 0xB504F3 /* 2^23.5 */
#define PTLS_CHACHA20_KEY_SIZE 32
#define PTLS_CHACHA20_IV_SIZE 16
#define PTLS_CHACHA20POLY1305_IV_SIZE 12
#define PTLS_CHACHA20POLY1305_TAG_SIZE 16
+#define PTLS_CHACHA20POLY1305_CONFIDENTIALITY_LIMIT UINT64_MAX /* at least 2^64 */
+#define PTLS_CHACHA20POLY1305_INTEGRITY_LIMIT UINT64_C(0x1000000000) /* 2^36 */
#define PTLS_BLOWFISH_KEY_SIZE 16
#define PTLS_BLOWFISH_BLOCK_SIZE 8
@@ -336,6 +342,14 @@
*/
const char *name;
/**
+ * confidentiality_limit (max records / packets sent before re-key)
+ */
+ const uint64_t confidentiality_limit;
+ /**
+ * integrity_limit (max decryption failure records / packets before re-key)
+ */
+ const uint64_t integrity_limit;
+ /**
* the underlying key stream
*/
ptls_cipher_algorithm_t *ctr_cipher;
diff --git a/lib/cifra/aes128.c b/lib/cifra/aes128.c
index 7f6817f..26bd9e4 100644
--- a/lib/cifra/aes128.c
+++ b/lib/cifra/aes128.c
@@ -47,8 +47,15 @@
ptls_cipher_algorithm_t ptls_minicrypto_aes128ctr = {
"AES128-CTR", PTLS_AES128_KEY_SIZE, 1 /* block size */, PTLS_AES_IV_SIZE, sizeof(struct aesctr_context_t),
aes128ctr_setup_crypto};
-ptls_aead_algorithm_t ptls_minicrypto_aes128gcm = {
- "AES128-GCM", &ptls_minicrypto_aes128ctr, &ptls_minicrypto_aes128ecb, PTLS_AES128_KEY_SIZE,
- PTLS_AESGCM_IV_SIZE, PTLS_AESGCM_TAG_SIZE, sizeof(struct aesgcm_context_t), aead_aes128gcm_setup_crypto};
+ptls_aead_algorithm_t ptls_minicrypto_aes128gcm = {"AES128-GCM",
+ PTLS_AESGCM_CONFIDENTIALITY_LIMIT,
+ PTLS_AESGCM_INTEGRITY_LIMIT,
+ &ptls_minicrypto_aes128ctr,
+ &ptls_minicrypto_aes128ecb,
+ PTLS_AES128_KEY_SIZE,
+ PTLS_AESGCM_IV_SIZE,
+ PTLS_AESGCM_TAG_SIZE,
+ sizeof(struct aesgcm_context_t),
+ aead_aes128gcm_setup_crypto};
ptls_cipher_suite_t ptls_minicrypto_aes128gcmsha256 = {PTLS_CIPHER_SUITE_AES_128_GCM_SHA256, &ptls_minicrypto_aes128gcm,
&ptls_minicrypto_sha256};
diff --git a/lib/cifra/aes256.c b/lib/cifra/aes256.c
index 5b925be..d0568d5 100644
--- a/lib/cifra/aes256.c
+++ b/lib/cifra/aes256.c
@@ -47,8 +47,15 @@
ptls_cipher_algorithm_t ptls_minicrypto_aes256ctr = {
"AES256-CTR", PTLS_AES256_KEY_SIZE, 1 /* block size */, PTLS_AES_IV_SIZE, sizeof(struct aesctr_context_t),
aes256ctr_setup_crypto};
-ptls_aead_algorithm_t ptls_minicrypto_aes256gcm = {
- "AES256-GCM", &ptls_minicrypto_aes256ctr, &ptls_minicrypto_aes256ecb, PTLS_AES256_KEY_SIZE,
- PTLS_AESGCM_IV_SIZE, PTLS_AESGCM_TAG_SIZE, sizeof(struct aesgcm_context_t), aead_aes256gcm_setup_crypto};
+ptls_aead_algorithm_t ptls_minicrypto_aes256gcm = {"AES256-GCM",
+ PTLS_AESGCM_CONFIDENTIALITY_LIMIT,
+ PTLS_AESGCM_INTEGRITY_LIMIT,
+ &ptls_minicrypto_aes256ctr,
+ &ptls_minicrypto_aes256ecb,
+ PTLS_AES256_KEY_SIZE,
+ PTLS_AESGCM_IV_SIZE,
+ PTLS_AESGCM_TAG_SIZE,
+ sizeof(struct aesgcm_context_t),
+ aead_aes256gcm_setup_crypto};
ptls_cipher_suite_t ptls_minicrypto_aes256gcmsha384 = {PTLS_CIPHER_SUITE_AES_256_GCM_SHA384, &ptls_minicrypto_aes256gcm,
&ptls_minicrypto_sha384};
diff --git a/lib/cifra/chacha20.c b/lib/cifra/chacha20.c
index a5f302f..57a6c39 100644
--- a/lib/cifra/chacha20.c
+++ b/lib/cifra/chacha20.c
@@ -206,6 +206,8 @@
"CHACHA20", PTLS_CHACHA20_KEY_SIZE, 1 /* block size */, PTLS_CHACHA20_IV_SIZE, sizeof(struct chacha20_context_t),
chacha20_setup_crypto};
ptls_aead_algorithm_t ptls_minicrypto_chacha20poly1305 = {"CHACHA20-POLY1305",
+ PTLS_CHACHA20POLY1305_CONFIDENTIALITY_LIMIT,
+ PTLS_CHACHA20POLY1305_INTEGRITY_LIMIT,
&ptls_minicrypto_chacha20,
NULL,
PTLS_CHACHA20_KEY_SIZE,
diff --git a/lib/fusion.c b/lib/fusion.c
index b86205f..1610447 100644
--- a/lib/fusion.c
+++ b/lib/fusion.c
@@ -38,7 +38,7 @@
* IN THE SOFTWARE.
*/
#include <stdint.h>
-
+
#include <stdlib.h>
#include <string.h>
#include <immintrin.h>
@@ -294,7 +294,7 @@
__m128i ek0, bits0, bits1, bits2, bits3, bits4, bits5 = _mm_setzero_si128();
const __m128i *bits4keys = ctx->ecb.keys; /* is changed to supp->ctx.keys when calcurating suppout */
- struct ptls_fusion_gfmul_state gstate = { 0 };
+ struct ptls_fusion_gfmul_state gstate = {0};
__m128i gdatabuf[6];
__m128i ac = _mm_shuffle_epi8(_mm_set_epi32(0, (int)aadlen * 8, 0, (int)inlen * 8), bswap8);
@@ -492,7 +492,7 @@
{
__m128i ek0 = _mm_setzero_si128(), bits0, bits1 = _mm_setzero_si128(), bits2 = _mm_setzero_si128(), bits3 = _mm_setzero_si128(),
bits4 = _mm_setzero_si128(), bits5 = _mm_setzero_si128();
- struct ptls_fusion_gfmul_state gstate = { 0 };
+ struct ptls_fusion_gfmul_state gstate = {0};
__m128i gdatabuf[6];
__m128i ac = _mm_shuffle_epi8(_mm_set_epi32(0, (int)aadlen * 8, 0, (int)inlen * 8), bswap8);
struct ptls_fusion_aesgcm_ghash_precompute *ghash_precompute = ctx->ghash + (aadlen + 15) / 16 + (inlen + 15) / 16 + 1;
@@ -968,6 +968,8 @@
sizeof(struct ctr_context),
aes256ctr_setup};
ptls_aead_algorithm_t ptls_fusion_aes128gcm = {"AES128-GCM",
+ PTLS_AESGCM_CONFIDENTIALITY_LIMIT,
+ PTLS_AESGCM_INTEGRITY_LIMIT,
&ptls_fusion_aes128ctr,
NULL, // &ptls_fusion_aes128ecb,
PTLS_AES128_KEY_SIZE,
@@ -976,6 +978,8 @@
sizeof(struct aesgcm_context),
aes128gcm_setup};
ptls_aead_algorithm_t ptls_fusion_aes256gcm = {"AES256-GCM",
+ PTLS_AESGCM_CONFIDENTIALITY_LIMIT,
+ PTLS_AESGCM_INTEGRITY_LIMIT,
&ptls_fusion_aes256ctr,
NULL, // &ptls_fusion_aes256ecb,
PTLS_AES256_KEY_SIZE,
@@ -1005,7 +1009,7 @@
uint32_t leaf1_ecx;
__cpuid(cpu_info, 1);
leaf1_ecx = cpu_info[2];
-
+
if (/* PCLMUL */ (leaf1_ecx & (1 << 5)) != 0 && /* AES */ (leaf1_ecx & (1 << 25)) != 0) {
uint32_t leaf7_ebx;
__cpuid(cpu_info, 7);
diff --git a/lib/openssl.c b/lib/openssl.c
index c55ba93..c7ba115 100644
--- a/lib/openssl.c
+++ b/lib/openssl.c
@@ -1429,6 +1429,8 @@
ptls_cipher_algorithm_t ptls_openssl_aes128ctr = {
"AES128-CTR", PTLS_AES128_KEY_SIZE, 1, PTLS_AES_IV_SIZE, sizeof(struct cipher_context_t), aes128ctr_setup_crypto};
ptls_aead_algorithm_t ptls_openssl_aes128gcm = {"AES128-GCM",
+ PTLS_AESGCM_CONFIDENTIALITY_LIMIT,
+ PTLS_AESGCM_INTEGRITY_LIMIT,
&ptls_openssl_aes128ctr,
&ptls_openssl_aes128ecb,
PTLS_AES128_KEY_SIZE,
@@ -1443,6 +1445,8 @@
"AES256-CTR", PTLS_AES256_KEY_SIZE, 1 /* block size */, PTLS_AES_IV_SIZE, sizeof(struct cipher_context_t),
aes256ctr_setup_crypto};
ptls_aead_algorithm_t ptls_openssl_aes256gcm = {"AES256-GCM",
+ PTLS_AESGCM_CONFIDENTIALITY_LIMIT,
+ PTLS_AESGCM_INTEGRITY_LIMIT,
&ptls_openssl_aes256ctr,
&ptls_openssl_aes256ecb,
PTLS_AES256_KEY_SIZE,
@@ -1463,6 +1467,8 @@
"CHACHA20", PTLS_CHACHA20_KEY_SIZE, 1 /* block size */, PTLS_CHACHA20_IV_SIZE, sizeof(struct cipher_context_t),
chacha20_setup_crypto};
ptls_aead_algorithm_t ptls_openssl_chacha20poly1305 = {"CHACHA20-POLY1305",
+ PTLS_CHACHA20POLY1305_CONFIDENTIALITY_LIMIT,
+ PTLS_CHACHA20POLY1305_INTEGRITY_LIMIT,
&ptls_openssl_chacha20,
NULL,
PTLS_CHACHA20_KEY_SIZE,
diff --git a/lib/ptlsbcrypt.c b/lib/ptlsbcrypt.c
index 1035c69..2a9a4d0 100644
--- a/lib/ptlsbcrypt.c
+++ b/lib/ptlsbcrypt.c
@@ -65,7 +65,7 @@
/*
* Support for symmetric ciphers
-*/
+ */
struct ptls_bcrypt_symmetric_param_t {
HANDLE hKey;
@@ -215,7 +215,7 @@
ctx->super.do_init = ptls_bcrypt_cipher_init_ctr;
ctx->super.do_transform = ptls_bcrypt_cipher_transform_ctr;
} else {
- ctx->super.do_init = NULL;
+ ctx->super.do_init = NULL;
ctx->super.do_transform = ptls_bcrypt_cipher_transform_ecb;
}
ctx->bctx.is_enc = is_enc;
@@ -236,7 +236,6 @@
return ptls_bcrypt_cipher_setup_crypto(_ctx, is_enc, key, BCRYPT_AES_ALGORITHM, 1);
}
-
/* Picotls assumes that AEAD encryption works as:
* - an "init" call that prepares the encryption context.
* - a series of "update" calls that encrypt segments of the message
@@ -248,7 +247,7 @@
* - the "padding info" points to a BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
* structure
* - the "IV" parameter points to a buffer holding intermediate updates
- * of the IV. That buffer shall be initialize to zero before the
+ * of the IV. That buffer shall be initialize to zero before the
* first call.
* The documentation of the AEAD mode on MSDN is slightly obscure, and
* also slightly wrong. After trial and errors and web searches, we find
@@ -266,10 +265,10 @@
* initialized to zero before first call.
* - The Mac Context parameter (pbMacContext, cbMacContext) contains
* a working buffer for the computation of the tag. The size
- * must be the maxLength parameter returned retrieved in the
+ * must be the maxLength parameter returned retrieved in the
* BCRYPT_AUTH_TAG_LENGTH property of the algorithm. It must be
* initialized to zero before first call.
- * - The dwflag parameters must be set to
+ * - The dwflag parameters must be set to
* BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG on first call. (The
* MSDN documentation says BCRYPT_AUTH_MODE_IN_PROGRESS_FLAG,
* but that's an error.)
@@ -284,7 +283,7 @@
* error STATUS_INVALID_BUFFER_SIZE if the length passed in the
* chained calls is not an integer multiple of block size. This forces
* us to maintain an intermediate buffer of "extra bytes".
- *
+ *
*/
struct ptls_bcrypt_aead_param_t {
@@ -347,9 +346,9 @@
ctx->bctx.aead_params.pbAuthData = (PUCHAR)aad;
ctx->bctx.aead_params.cbAuthData = (ULONG)aadlen;
ctx->bctx.aead_params.pbTag = (PUCHAR)ctx->bctx.tag;
- ctx->bctx.aead_params.cbTag = (ULONG) ctx->super.algo->tag_size;
+ ctx->bctx.aead_params.cbTag = (ULONG)ctx->super.algo->tag_size;
// ctx->bctx.aead_params.cbAAD = (ULONG)aadlen;
- ctx->bctx.aead_params.pbMacContext = (PUCHAR) ctx->bctx.auth_tag;
+ ctx->bctx.aead_params.pbMacContext = (PUCHAR)ctx->bctx.auth_tag;
ctx->bctx.aead_params.cbMacContext = (ULONG)ctx->bctx.maxTagLength;
ctx->bctx.aead_params.dwFlags = BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG;
}
@@ -368,14 +367,15 @@
if (inlen < requiredBytes) {
memcpy(&ctx->bctx.extraBytes[ctx->bctx.nbExtraBytes], input, inlen);
- ctx->bctx.nbExtraBytes += (ULONG) inlen;
+ ctx->bctx.nbExtraBytes += (ULONG)inlen;
inlen = 0;
} else {
memcpy(&ctx->bctx.extraBytes[ctx->bctx.nbExtraBytes], input, requiredBytes);
inlen -= requiredBytes;
- input = (void*)(((uint8_t *)input) + requiredBytes);
+ input = (void *)(((uint8_t *)input) + requiredBytes);
ret = BCryptEncrypt(ctx->bctx.hKey, (PUCHAR)ctx->bctx.extraBytes, (ULONG)ctx->super.algo->ecb_cipher->block_size,
- (void *)&ctx->bctx.aead_params, ctx->bctx.ivbuf, (ULONG)ctx->super.algo->iv_size, output, (ULONG)outlenMax, &cbResult1, 0);
+ (void *)&ctx->bctx.aead_params, ctx->bctx.ivbuf, (ULONG)ctx->super.algo->iv_size, output,
+ (ULONG)outlenMax, &cbResult1, 0);
assert(BCRYPT_SUCCESS(ret));
if (!BCRYPT_SUCCESS(ret)) {
@@ -414,8 +414,8 @@
ctx->bctx.aead_params.dwFlags &= ~BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG;
- ret = BCryptEncrypt(ctx->bctx.hKey, (PUCHAR)ctx->bctx.extraBytes, (ULONG)ctx->bctx.nbExtraBytes, (void *)&ctx->bctx.aead_params, ctx->bctx.ivbuf,
- (ULONG)ctx->super.algo->iv_size, output, (ULONG)outlenMax, &cbResult, 0);
+ ret = BCryptEncrypt(ctx->bctx.hKey, (PUCHAR)ctx->bctx.extraBytes, (ULONG)ctx->bctx.nbExtraBytes, (void *)&ctx->bctx.aead_params,
+ ctx->bctx.ivbuf, (ULONG)ctx->super.algo->iv_size, output, (ULONG)outlenMax, &cbResult, 0);
assert(BCRYPT_SUCCESS(ret));
if (BCRYPT_SUCCESS(ret)) {
@@ -450,8 +450,8 @@
ctx->bctx.aead_params.cbTag = (ULONG)(ULONG)ctx->super.algo->tag_size;
/* Call the decryption */
- ret = BCryptDecrypt(ctx->bctx.hKey, (PUCHAR)input, (ULONG)textLen, (void *)&ctx->bctx.aead_params,
- NULL, 0, (PUCHAR)output, (ULONG)textLen, &cbResult, 0);
+ ret = BCryptDecrypt(ctx->bctx.hKey, (PUCHAR)input, (ULONG)textLen, (void *)&ctx->bctx.aead_params, NULL, 0, (PUCHAR)output,
+ (ULONG)textLen, &cbResult, 0);
if (BCRYPT_SUCCESS(ret)) {
return (size_t)cbResult;
@@ -460,8 +460,8 @@
}
}
-static int ptls_bcrypt_aead_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, const void *key,
- const void * iv, wchar_t const *bcrypt_name, wchar_t const *bcrypt_mode, size_t bcrypt_mode_size)
+static int ptls_bcrypt_aead_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, const void *key, const void *iv,
+ wchar_t const *bcrypt_name, wchar_t const *bcrypt_mode, size_t bcrypt_mode_size)
{
struct ptls_bcrypt_aead_context_t *ctx = (struct ptls_bcrypt_aead_context_t *)_ctx;
HANDLE hAlgorithm = NULL;
@@ -533,7 +533,7 @@
}
}
-static int ptls_bcrypt_aead_setup_crypto_aesgcm(ptls_aead_context_t *_ctx, int is_enc, const void *key, const void * iv)
+static int ptls_bcrypt_aead_setup_crypto_aesgcm(ptls_aead_context_t *_ctx, int is_enc, const void *key, const void *iv)
{
return ptls_bcrypt_aead_setup_crypto(_ctx, is_enc, key, iv, BCRYPT_AES_ALGORITHM, BCRYPT_CHAIN_MODE_GCM,
sizeof(BCRYPT_CHAIN_MODE_GCM));
@@ -619,7 +619,7 @@
}
assert(BCRYPT_SUCCESS(ret));
if (!BCRYPT_SUCCESS(ret)) {
- ctx->ctx.hHash = NULL;
+ ctx->ctx.hHash = NULL;
}
break;
}
@@ -750,6 +750,8 @@
ptls_bcrypt_cipher_setup_crypto_aes_ctr};
ptls_aead_algorithm_t ptls_bcrypt_aes128gcm = {"AES128-GCM",
+ PTLS_AESGCM_CONFIDENTIALITY_LIMIT,
+ PTLS_AESGCM_INTEGRITY_LIMIT,
&ptls_bcrypt_aes128ecb,
&ptls_bcrypt_aes128ctr,
PTLS_AES128_KEY_SIZE,
@@ -759,6 +761,8 @@
ptls_bcrypt_aead_setup_crypto_aesgcm};
ptls_aead_algorithm_t ptls_bcrypt_aes256gcm = {"AES256-GCM",
+ PTLS_AESGCM_CONFIDENTIALITY_LIMIT,
+ PTLS_AESGCM_INTEGRITY_LIMIT,
&ptls_bcrypt_aes256ecb,
&ptls_bcrypt_aes256ctr,
PTLS_AES256_KEY_SIZE,