Skip to content

Commit

Permalink
Merge pull request #323
Browse files Browse the repository at this point in the history
Confidentiality and integrity limits for AEAD
  • Loading branch information
kazuho committed Sep 12, 2020
2 parents adf6fa1 + 14c00c0 commit 2464ada
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 30 deletions.
14 changes: 14 additions & 0 deletions include/picotls.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,17 @@ extern "C" {
#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
Expand Down Expand Up @@ -335,6 +341,14 @@ typedef const struct st_ptls_aead_algorithm_t {
* name (following the convention of `openssl ciphers -v ALL`)
*/
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
*/
Expand Down
13 changes: 10 additions & 3 deletions lib/cifra/aes128.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,15 @@ ptls_cipher_algorithm_t ptls_minicrypto_aes128ecb = {
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};
13 changes: 10 additions & 3 deletions lib/cifra/aes256.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,15 @@ ptls_cipher_algorithm_t ptls_minicrypto_aes256ecb = {
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};
2 changes: 2 additions & 0 deletions lib/cifra/chacha20.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ ptls_cipher_algorithm_t ptls_minicrypto_chacha20 = {
"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,
Expand Down
12 changes: 8 additions & 4 deletions lib/fusion.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
* IN THE SOFTWARE.
*/
#include <stdint.h>

#include <stdlib.h>
#include <string.h>
#include <immintrin.h>
Expand Down Expand Up @@ -294,7 +294,7 @@ void ptls_fusion_aesgcm_encrypt(ptls_fusion_aesgcm_context_t *ctx, void *output,

__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);

Expand Down Expand Up @@ -492,7 +492,7 @@ int ptls_fusion_aesgcm_decrypt(ptls_fusion_aesgcm_context_t *ctx, void *output,
{
__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;
Expand Down Expand Up @@ -968,6 +968,8 @@ ptls_cipher_algorithm_t ptls_fusion_aes256ctr = {"AES256-CTR",
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,
Expand All @@ -976,6 +978,8 @@ ptls_aead_algorithm_t ptls_fusion_aes128gcm = {"AES128-GCM",
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,
Expand Down Expand Up @@ -1005,7 +1009,7 @@ int ptls_fusion_is_supported_by_cpu(void)
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);
Expand Down
6 changes: 6 additions & 0 deletions lib/openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1429,6 +1429,8 @@ ptls_cipher_algorithm_t ptls_openssl_aes128ecb = {
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,
Expand All @@ -1443,6 +1445,8 @@ ptls_cipher_algorithm_t ptls_openssl_aes256ctr = {
"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,
Expand All @@ -1463,6 +1467,8 @@ ptls_cipher_algorithm_t ptls_openssl_chacha20 = {
"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,
Expand Down
44 changes: 24 additions & 20 deletions lib/ptlsbcrypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ void ptls_bcrypt_random_bytes(void *buf, size_t len)

/*
* Support for symmetric ciphers
*/
*/

struct ptls_bcrypt_symmetric_param_t {
HANDLE hKey;
Expand Down Expand Up @@ -215,7 +215,7 @@ static int ptls_bcrypt_cipher_setup_crypto(ptls_cipher_context_t *_ctx, int is_e
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;
Expand All @@ -236,7 +236,6 @@ static int ptls_bcrypt_cipher_setup_crypto_aes_ctr(ptls_cipher_context_t *_ctx,
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
Expand All @@ -248,7 +247,7 @@ static int ptls_bcrypt_cipher_setup_crypto_aes_ctr(ptls_cipher_context_t *_ctx,
* - 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
Expand All @@ -266,10 +265,10 @@ static int ptls_bcrypt_cipher_setup_crypto_aes_ctr(ptls_cipher_context_t *_ctx,
* 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.)
Expand All @@ -284,7 +283,7 @@ static int ptls_bcrypt_cipher_setup_crypto_aes_ctr(ptls_cipher_context_t *_ctx,
* 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 {
Expand Down Expand Up @@ -347,9 +346,9 @@ static void ptls_bcrypt_aead_do_encrypt_init(struct st_ptls_aead_context_t *_ctx
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;
}
Expand All @@ -368,14 +367,15 @@ static size_t ptls_bcrypt_aead_do_encrypt_update(struct st_ptls_aead_context_t *

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)) {
Expand Down Expand Up @@ -414,8 +414,8 @@ static size_t ptls_bcrypt_aead_do_encrypt_final(struct st_ptls_aead_context_t *_

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)) {
Expand Down Expand Up @@ -450,8 +450,8 @@ static size_t ptls_bcrypt_aead_do_decrypt(struct st_ptls_aead_context_t *_ctx, v
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;
Expand All @@ -460,8 +460,8 @@ static size_t ptls_bcrypt_aead_do_decrypt(struct st_ptls_aead_context_t *_ctx, v
}
}

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;
Expand Down Expand Up @@ -533,7 +533,7 @@ static int ptls_bcrypt_aead_setup_crypto(ptls_aead_context_t *_ctx, int is_enc,
}
}

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));
Expand Down Expand Up @@ -619,7 +619,7 @@ static void ptls_bcrypt_hash_final(struct st_ptls_hash_context_t *_ctx, void *md
}
assert(BCRYPT_SUCCESS(ret));
if (!BCRYPT_SUCCESS(ret)) {
ctx->ctx.hHash = NULL;
ctx->ctx.hHash = NULL;
}
break;
}
Expand Down Expand Up @@ -750,6 +750,8 @@ ptls_cipher_algorithm_t ptls_bcrypt_aes256ctr = {"AES256-CTR",
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,
Expand All @@ -759,6 +761,8 @@ ptls_aead_algorithm_t ptls_bcrypt_aes128gcm = {"AES128-GCM",
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,
Expand Down

0 comments on commit 2464ada

Please sign in to comment.