Merge pull request #382 from devnexen/openssl3_silencing
openssl 3 build fix proposal.
diff --git a/include/picotls.h b/include/picotls.h
index aadd671..cad1206 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;
@@ -1149,6 +1153,12 @@
*/
ptls_cipher_suite_t *ptls_get_cipher(ptls_t *tls);
/**
+ * Returns current state of traffic keys. The cipher-suite being used, as well as the length of the traffic keys, can be obtained
+ * via `ptls_get_cipher`.
+ * TODO: Even in case of offloading just the TX side, there should be API for handling key updates, sending Close aleart.
+ */
+int ptls_get_traffic_keys(ptls_t *tls, int is_enc, uint8_t *key, uint8_t *iv, uint64_t *seq);
+/**
* returns the server-name (NULL if SNI is not used or failed to negotiate)
*/
const char *ptls_get_server_name(ptls_t *tls);
@@ -1296,24 +1306,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);
/**
@@ -1359,6 +1376,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);
@@ -1494,6 +1516,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);
@@ -1512,9 +1540,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);
@@ -1523,6 +1550,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 = (uint8_t *)_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 93a74d3..f891e04 100644
--- a/lib/openssl.c
+++ b/lib/openssl.c
@@ -981,11 +981,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 8ea30b6..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)
@@ -1195,6 +1192,20 @@
label_prefix);
}
+static int get_traffic_keys(ptls_aead_algorithm_t *aead, ptls_hash_algorithm_t *hash, void *key, void *iv, const void *secret,
+ ptls_iovec_t hash_value, const char *label_prefix)
+{
+ int ret;
+
+ if ((ret = get_traffic_key(hash, key, aead->key_size, 0, secret, hash_value, label_prefix)) != 0 ||
+ (ret = get_traffic_key(hash, iv, aead->iv_size, 1, secret, hash_value, label_prefix)) != 0) {
+ ptls_clear_memory(key, aead->key_size);
+ ptls_clear_memory(iv, aead->iv_size);
+ }
+
+ return ret;
+}
+
static int setup_traffic_protection(ptls_t *tls, int is_enc, const char *secret_label, size_t epoch, int skip_notify)
{
static const char *log_labels[2][4] = {
@@ -4425,6 +4436,18 @@
return tls->cipher_suite;
}
+int ptls_get_traffic_keys(ptls_t *tls, int is_enc, uint8_t *key, uint8_t *iv, uint64_t *seq)
+{
+ struct st_ptls_traffic_protection_t *ctx = is_enc ? &tls->traffic_protection.enc : &tls->traffic_protection.dec;
+ int ret;
+
+ if ((ret = get_traffic_keys(tls->cipher_suite->aead, tls->cipher_suite->hash, key, iv, ctx->secret, ptls_iovec_init(NULL, 0),
+ NULL)) != 0)
+ return ret;
+ *seq = ctx->seq;
+ return 0;
+}
+
const char *ptls_get_server_name(ptls_t *tls)
{
return tls->server_name;
@@ -5218,17 +5241,18 @@
ptls_iovec_t hash_value, const char *label_prefix)
{
ptls_aead_context_t *ctx = NULL;
- uint8_t key_iv[PTLS_MAX_SECRET_SIZE + PTLS_MAX_IV_SIZE];
+ struct {
+ uint8_t key[PTLS_MAX_SECRET_SIZE];
+ uint8_t iv[PTLS_MAX_IV_SIZE];
+ } key_iv;
int ret;
- if ((ret = get_traffic_key(hash, key_iv, aead->key_size, 0, secret, hash_value, label_prefix)) != 0)
+ if ((ret = get_traffic_keys(aead, hash, key_iv.key, key_iv.iv, secret, hash_value, label_prefix)) != 0)
goto Exit;
- if ((ret = get_traffic_key(hash, key_iv + aead->key_size, aead->iv_size, 1, secret, hash_value, label_prefix)) != 0)
- goto Exit;
- ctx = ptls_aead_new_direct(aead, is_enc, key_iv, key_iv + aead->key_size);
+ ctx = ptls_aead_new_direct(aead, is_enc, key_iv.key, key_iv.iv);
Exit:
- ptls_clear_memory(key_iv, sizeof(key_iv));
+ ptls_clear_memory(&key_iv, sizeof(key_iv));
return ctx;
}
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);