Merge branch 'master' into kazuho/offload
diff --git a/include/picotls.h b/include/picotls.h
index 2396852..f63b311 100644
--- a/include/picotls.h
+++ b/include/picotls.h
@@ -337,6 +337,8 @@
/**
* AEAD context. AEAD implementations are allowed to stuff data at the end of the struct. The size of the memory allocated for the
* struct is governed by ptls_aead_algorithm_t::context_size.
+ * Ciphers for TLS over TCP MUST implement `do_encrypt`, `do_encrypt_v`, `do_decrypt`. `do_encrypt_init`, `~update`, `~final` are
+ * obsolete, and therefore may not be available.
*/
typedef struct st_ptls_aead_context_t {
const struct st_ptls_aead_algorithm_t *algo;
@@ -348,6 +350,8 @@
size_t (*do_encrypt_final)(struct st_ptls_aead_context_t *ctx, void *output);
void (*do_encrypt)(struct st_ptls_aead_context_t *ctx, void *output, const void *input, size_t inlen, uint64_t seq,
const void *aad, size_t aadlen, ptls_aead_supplementary_encryption_t *supp);
+ void (*do_encrypt_v)(struct st_ptls_aead_context_t *ctx, void *output, ptls_iovec_t *input, size_t incnt, uint64_t seq,
+ const void *aad, size_t aadlen);
size_t (*do_decrypt)(struct st_ptls_aead_context_t *ctx, void *output, const void *input, size_t inlen, uint64_t seq,
const void *aad, size_t aadlen);
} ptls_aead_context_t;
@@ -1301,24 +1305,31 @@
*/
static void ptls_aead_xor_iv(ptls_aead_context_t *ctx, const void *bytes, size_t len);
/**
- *
+ * Encrypts one AEAD block, given input and output vectors.
*/
static size_t ptls_aead_encrypt(ptls_aead_context_t *ctx, void *output, const void *input, size_t inlen, uint64_t seq,
const void *aad, size_t aadlen);
+/**
+ * Encrypts one AEAD block, as well as one block of ECB (for QUIC / DTLS packet number encryption). Depending on the AEAD engine
+ * being used, the two operations might run simultaneously.
+ */
static void ptls_aead_encrypt_s(ptls_aead_context_t *ctx, void *output, const void *input, size_t inlen, uint64_t seq,
const void *aad, size_t aadlen, ptls_aead_supplementary_encryption_t *supp);
/**
- * initializes the internal state of the encryptor
+ * Encrypts one AEAD block, given a vector of vectors.
+ */
+static void ptls_aead_encrypt_v(ptls_aead_context_t *ctx, void *output, ptls_iovec_t *input, size_t incnt, uint64_t seq,
+ const void *aad, size_t aadlen);
+/**
+ * Obsolete; new applications should use one of: `ptls_aead_encrypt`, `ptls_aead_encrypt_s`, `ptls_aead_encrypt_v`.
*/
static void ptls_aead_encrypt_init(ptls_aead_context_t *ctx, uint64_t seq, const void *aad, size_t aadlen);
/**
- * encrypts the input and updates the GCM state
- * @return number of bytes emitted to output
+ * Obsolete; see `ptls_aead_encrypt_init`.
*/
static size_t ptls_aead_encrypt_update(ptls_aead_context_t *ctx, void *output, const void *input, size_t inlen);
/**
- * emits buffered data (if any) and the GCM tag
- * @return number of bytes emitted to output
+ * Obsolete; see `ptls_aead_encrypt_init`.
*/
static size_t ptls_aead_encrypt_final(ptls_aead_context_t *ctx, void *output);
/**
@@ -1364,6 +1375,11 @@
static void ptls_aead__do_encrypt(ptls_aead_context_t *ctx, void *output, const void *input, size_t inlen, uint64_t seq,
const void *aad, size_t aadlen, ptls_aead_supplementary_encryption_t *supp);
/**
+ *
+ */
+static void ptls_aead__do_encrypt_v(ptls_aead_context_t *ctx, void *_output, ptls_iovec_t *input, size_t incnt, uint64_t seq,
+ const void *aad, size_t aadlen);
+/**
* internal
*/
void ptls__key_schedule_update_hash(ptls_key_schedule_t *sched, const uint8_t *msg, size_t msglen);
@@ -1499,6 +1515,12 @@
ctx->do_encrypt(ctx, output, input, inlen, seq, aad, aadlen, supp);
}
+inline void ptls_aead_encrypt_v(ptls_aead_context_t *ctx, void *output, ptls_iovec_t *input, size_t incnt, uint64_t seq,
+ const void *aad, size_t aadlen)
+{
+ ctx->do_encrypt_v(ctx, output, input, incnt, seq, aad, aadlen);
+}
+
inline void ptls_aead_encrypt_init(ptls_aead_context_t *ctx, uint64_t seq, const void *aad, size_t aadlen)
{
ctx->do_encrypt_init(ctx, seq, aad, aadlen);
@@ -1517,9 +1539,8 @@
inline void ptls_aead__do_encrypt(ptls_aead_context_t *ctx, void *output, const void *input, size_t inlen, uint64_t seq,
const void *aad, size_t aadlen, ptls_aead_supplementary_encryption_t *supp)
{
- ctx->do_encrypt_init(ctx, seq, aad, aadlen);
- ctx->do_encrypt_update(ctx, output, input, inlen);
- ctx->do_encrypt_final(ctx, (uint8_t *)output + inlen);
+ ptls_iovec_t invec = ptls_iovec_init(input, inlen);
+ ctx->do_encrypt_v(ctx, output, &invec, 1, seq, aad, aadlen);
if (supp != NULL) {
ptls_cipher_init(supp->ctx, supp->input);
@@ -1528,6 +1549,17 @@
}
}
+inline void ptls_aead__do_encrypt_v(ptls_aead_context_t *ctx, void *_output, ptls_iovec_t *input, size_t incnt, uint64_t seq,
+ const void *aad, size_t aadlen)
+{
+ uint8_t *output = _output;
+
+ ctx->do_encrypt_init(ctx, seq, aad, aadlen);
+ for (size_t i = 0; i < incnt; ++i)
+ output += ctx->do_encrypt_update(ctx, output, input[i].base, input[i].len);
+ ctx->do_encrypt_final(ctx, output);
+}
+
inline size_t ptls_aead_decrypt(ptls_aead_context_t *ctx, void *output, const void *input, size_t inlen, uint64_t seq,
const void *aad, size_t aadlen)
{
diff --git a/lib/cifra/aes-common.h b/lib/cifra/aes-common.h
index dfb620a..234e647 100644
--- a/lib/cifra/aes-common.h
+++ b/lib/cifra/aes-common.h
@@ -174,11 +174,14 @@
ctx->super.do_encrypt_update = aesgcm_encrypt_update;
ctx->super.do_encrypt_final = aesgcm_encrypt_final;
ctx->super.do_encrypt = ptls_aead__do_encrypt;
+ ctx->super.do_encrypt_v = ptls_aead__do_encrypt_v;
ctx->super.do_decrypt = NULL;
} else {
ctx->super.do_encrypt_init = NULL;
ctx->super.do_encrypt_update = NULL;
ctx->super.do_encrypt_final = NULL;
+ ctx->super.do_encrypt = NULL;
+ ctx->super.do_encrypt_v = NULL;
ctx->super.do_decrypt = aesgcm_decrypt;
}
diff --git a/lib/cifra/chacha20.c b/lib/cifra/chacha20.c
index 8db3a18..2e35843 100644
--- a/lib/cifra/chacha20.c
+++ b/lib/cifra/chacha20.c
@@ -199,11 +199,14 @@
ctx->super.do_encrypt_update = chacha20poly1305_encrypt_update;
ctx->super.do_encrypt_final = chacha20poly1305_encrypt_final;
ctx->super.do_encrypt = ptls_aead__do_encrypt;
+ ctx->super.do_encrypt_v = ptls_aead__do_encrypt_v;
ctx->super.do_decrypt = NULL;
} else {
ctx->super.do_encrypt_init = NULL;
ctx->super.do_encrypt_update = NULL;
ctx->super.do_encrypt_final = NULL;
+ ctx->super.do_encrypt = NULL;
+ ctx->super.do_encrypt_v = NULL;
ctx->super.do_decrypt = chacha20poly1305_decrypt;
}
diff --git a/lib/fusion.c b/lib/fusion.c
index e77e8ba..e0d977c 100644
--- a/lib/fusion.c
+++ b/lib/fusion.c
@@ -914,6 +914,12 @@
ptls_fusion_aesgcm_encrypt(ctx->aesgcm, output, input, inlen, calc_counter(ctx, seq), aad, aadlen, supp);
}
+static void aead_do_encrypt_v(struct st_ptls_aead_context_t *ctx, void *output, ptls_iovec_t *input, size_t incnt, uint64_t seq,
+ const void *aad, size_t aadlen)
+{
+ assert(!"FIXME");
+}
+
static size_t aead_do_decrypt(ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen, uint64_t seq,
const void *aad, size_t aadlen)
{
@@ -954,6 +960,7 @@
ctx->super.do_encrypt_update = aead_do_encrypt_update;
ctx->super.do_encrypt_final = aead_do_encrypt_final;
ctx->super.do_encrypt = aead_do_encrypt;
+ ctx->super.do_encrypt_v = aead_do_encrypt_v;
ctx->super.do_decrypt = aead_do_decrypt;
ctx->aesgcm = ptls_fusion_aesgcm_new(key, key_size, 1500 /* assume ordinary packet size */);
diff --git a/lib/openssl.c b/lib/openssl.c
index 85327a2..95356a1 100644
--- a/lib/openssl.c
+++ b/lib/openssl.c
@@ -980,11 +980,14 @@
ctx->super.do_encrypt_update = aead_do_encrypt_update;
ctx->super.do_encrypt_final = aead_do_encrypt_final;
ctx->super.do_encrypt = ptls_aead__do_encrypt;
+ ctx->super.do_encrypt_v = ptls_aead__do_encrypt_v;
ctx->super.do_decrypt = NULL;
} else {
ctx->super.do_encrypt_init = NULL;
ctx->super.do_encrypt_update = NULL;
ctx->super.do_encrypt_final = NULL;
+ ctx->super.do_encrypt = NULL;
+ ctx->super.do_encrypt_v = NULL;
ctx->super.do_decrypt = aead_do_decrypt;
}
ctx->evp_ctx = NULL;
diff --git a/lib/picotls.c b/lib/picotls.c
index b9c74e9..8bb5b13 100644
--- a/lib/picotls.c
+++ b/lib/picotls.c
@@ -638,16 +638,13 @@
static size_t aead_encrypt(struct st_ptls_traffic_protection_t *ctx, void *output, const void *input, size_t inlen,
uint8_t content_type)
{
+ ptls_iovec_t invec[2] = {ptls_iovec_init(input, inlen), ptls_iovec_init(&content_type, 1)};
uint8_t aad[5];
- size_t off = 0;
build_aad(aad, inlen + 1 + ctx->aead->algo->tag_size);
- ptls_aead_encrypt_init(ctx->aead, ctx->seq++, aad, sizeof(aad));
- off += ptls_aead_encrypt_update(ctx->aead, ((uint8_t *)output) + off, input, inlen);
- off += ptls_aead_encrypt_update(ctx->aead, ((uint8_t *)output) + off, &content_type, 1);
- off += ptls_aead_encrypt_final(ctx->aead, ((uint8_t *)output) + off);
+ ptls_aead_encrypt_v(ctx->aead, output, invec, PTLS_ELEMENTSOF(invec), ctx->seq++, aad, sizeof(aad));
- return off;
+ return inlen + 1 + ctx->aead->algo->tag_size;
}
static int aead_decrypt(struct st_ptls_traffic_protection_t *ctx, void *output, size_t *outlen, const void *input, size_t inlen)
diff --git a/lib/ptlsbcrypt.c b/lib/ptlsbcrypt.c
index 92e26fd..41e6a73 100644
--- a/lib/ptlsbcrypt.c
+++ b/lib/ptlsbcrypt.c
@@ -545,12 +545,15 @@
ctx->super.do_encrypt_update = ptls_bcrypt_aead_do_encrypt_update;
ctx->super.do_encrypt_final = ptls_bcrypt_aead_do_encrypt_final;
ctx->super.do_encrypt = ptls_bcrypt_do_encrypt;
+ ctx->super.do_encrypt_v = ptls_aead__do_encrypt_v;
} else {
ctx->super.dispose_crypto = ptls_bcrypt_aead_dispose_crypto;
ctx->super.do_decrypt = ptls_bcrypt_aead_do_decrypt;
ctx->super.do_encrypt_init = NULL;
ctx->super.do_encrypt_update = NULL;
ctx->super.do_encrypt_final = NULL;
+ ctx->super.do_encrypt = NULL;
+ ctx->super.do_encrypt_v = NULL;
}
return 0;
} else {
@@ -830,4 +833,4 @@
ptls_key_exchange_algorithm_t *ptls_bcrypt_key_exchanges[] = {&ptls_bcrypt_secp256r1, NULL};
#endif
-#endif /* _WINDOWS */
\ No newline at end of file
+#endif /* _WINDOWS */
diff --git a/picotlsvs/bcrypt-test/bcrypt-test.c b/picotlsvs/bcrypt-test/bcrypt-test.c
index 513a344..f45c497 100644
--- a/picotlsvs/bcrypt-test/bcrypt-test.c
+++ b/picotlsvs/bcrypt-test/bcrypt-test.c
@@ -374,6 +374,78 @@
return ret;
}
+int test_encrypt_vector(ptls_aead_algorithm_t *aead, wchar_t *name, wchar_t *chain_mode, size_t chain_mode_sz)
+{
+ BYTE key[32];
+ BYTE iv[PTLS_MAX_IV_SIZE];
+ BYTE data[123];
+ uint64_t nonce;
+ BYTE authData[9];
+ BYTE encryptedRef[256];
+ ULONG encryptedRefLength;
+ BYTE encrypted[256];
+ size_t encryptedLength;
+ ULONG authTagLength = (ULONG)aead->tag_size;
+ ptls_aead_context_t *ctx = NULL;
+ int ret = 0;
+
+ assert(sizeof(key) >= aead->key_size);
+ assert(sizeof(iv) >= aead->iv_size);
+ assert(sizeof(data) + authTagLength <= sizeof(encrypted));
+ assert(sizeof(data) + authTagLength <= sizeof(encryptedRef));
+
+ memset(key, 'k', sizeof(key));
+ memset(iv, 'n', sizeof(iv));
+ memset(data, 'd', sizeof(data));
+ nonce = 0;
+ memset(authData, 'a', sizeof(authData));
+
+ /* Create an encryption context */
+ ctx = new_test_aead_context(aead, 1, key, iv);
+ if (ctx == NULL) {
+ ret = -1;
+ }
+
+ if (ret == 0) {
+ ret = EncodeOneShot(aead, name, chain_mode, chain_mode_sz, key, (ULONG)aead->key_size, iv, (ULONG)aead->iv_size, data, 123,
+ nonce, authData, 9, authTagLength, encryptedRef, 256, &encryptedRefLength);
+ }
+
+ /* Try encrypt with vector procedure */
+ if (ret == 0) {
+ ptls_iovec_t input_vec[2];
+
+ input_vec[0].base = data;
+ input_vec[0].len = 23;
+ input_vec[1].base = data + 23;
+ input_vec[1].len = 100;
+
+ ptls_aead_encrypt_v(ctx, encrypted, input_vec, 2, nonce, authData, 9);
+ encryptedLength = 123 + authTagLength;
+
+ if (encryptedLength != encryptedRefLength) {
+ printf("For %s, encrypt_v returns %d instead of %d\n", aead->name, (int)encryptedLength, encryptedRefLength);
+ ret = -1;
+ } else if (memcmp(encryptedRef, encrypted, encryptedRefLength) != 0) {
+ printf("For %s, vector encrypted does not match ref\n", aead->name);
+ for (ULONG i = 0; i < encryptedRefLength; i++) {
+ if (encryptedRef[i] != encrypted[i]) {
+ printf("For %s, vector encrypted[%d] = 0x%02x vs encryptedRef[%d] = 0x%02x\n", aead->name, i, encrypted[i], i,
+ encryptedRef[i]);
+ break;
+ }
+ }
+ ret = -1;
+ } else {
+ printf("For %s, vector encrypting test passes.\n", aead->name);
+ }
+ }
+
+ delete_test_aead_context(ctx);
+
+ return ret;
+}
+
int test_for_size(ptls_aead_algorithm_t *aead, wchar_t *name, wchar_t *chain_mode, size_t chain_mode_sz)
{
BYTE key[32];
@@ -482,6 +554,13 @@
}
if (ret == 0) {
+ ret = test_encrypt_vector(aead, name, chain_mode, chain_mode_sz);
+
+ printf("For %s, test encrypt returns %d\n", aead->name, ret);
+ }
+
+
+ if (ret == 0) {
ret = test_for_size(aead, name, chain_mode, chain_mode_sz);
printf("For %s, test packet sizes returns %d\n", aead->name, ret);