Android OpenSSL => 3.2.0.

git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4643 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
Cory McWilliams 2023-11-25 17:30:55 +00:00
parent 13ab9786f7
commit d02751ee08
693 changed files with 54409 additions and 5021 deletions

View File

@ -90,7 +90,7 @@ void gcm_ghash_p8(u64 Xi[2],const u128 Htable[16],const u8 *inp, size_t len);
# endif /* OPENSSL_SYS_AIX || OPENSSL_SYS_MACOSX */
# endif /* PPC */
# if (defined(__arm__) || defined(__arm) || defined(__aarch64__))
# if (defined(__arm__) || defined(__arm) || defined(__aarch64__) || defined(_M_ARM64))
# include "arm_arch.h"
# if __ARM_MAX_ARCH__>=7
# if defined(BSAES_ASM)
@ -106,7 +106,7 @@ void gcm_ghash_p8(u64 Xi[2],const u128 Htable[16],const u8 *inp, size_t len);
# define HWAES_decrypt aes_v8_decrypt
# define HWAES_cbc_encrypt aes_v8_cbc_encrypt
# define HWAES_ecb_encrypt aes_v8_ecb_encrypt
# if __ARM_MAX_ARCH__>=8 && defined(__aarch64__)
# if __ARM_MAX_ARCH__>=8 && (defined(__aarch64__) || defined(_M_ARM64))
# define HWAES_xts_encrypt aes_v8_xts_encrypt
# define HWAES_xts_decrypt aes_v8_xts_decrypt
# endif
@ -114,7 +114,7 @@ void gcm_ghash_p8(u64 Xi[2],const u128 Htable[16],const u8 *inp, size_t len);
# define AES_PMULL_CAPABLE ((OPENSSL_armcap_P & ARMV8_PMULL) && (OPENSSL_armcap_P & ARMV8_AES))
# define AES_GCM_ENC_BYTES 512
# define AES_GCM_DEC_BYTES 512
# if __ARM_MAX_ARCH__>=8 && defined(__aarch64__)
# if __ARM_MAX_ARCH__>=8 && (defined(__aarch64__) || defined(_M_ARM64))
# define AES_gcm_encrypt armv8_aes_gcm_encrypt
# define AES_gcm_decrypt armv8_aes_gcm_decrypt
# define AES_GCM_ASM(gctx) ((gctx)->ctr==aes_v8_ctr32_encrypt_blocks && \
@ -434,7 +434,6 @@ void aes256_t4_xts_decrypt(const unsigned char *in, unsigned char *out,
# elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64
/* RISC-V 64 support */
# include "riscv_arch.h"
# define RV64I_ZKND_ZKNE_CAPABLE (RISCV_HAS_ZKND() && RISCV_HAS_ZKNE())
int rv64i_zkne_set_encrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
@ -447,8 +446,6 @@ void rv64i_zknd_decrypt(const unsigned char *in, unsigned char *out,
# elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32
/* RISC-V 32 support */
# include "riscv_arch.h"
# define RV32I_ZKND_ZKNE_CAPABLE (RISCV_HAS_ZKND() && RISCV_HAS_ZKNE())
# define RV32I_ZBKB_ZKND_ZKNE_CAPABLE (RV32I_ZKND_ZKNE_CAPABLE && RISCV_HAS_ZBKB())
int rv32i_zkne_set_encrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -145,5 +145,9 @@ int ossl_asn1_time_print_ex(BIO *bp, const ASN1_TIME *tm, unsigned long flags);
EVP_PKEY *ossl_d2i_PrivateKey_legacy(int keytype, EVP_PKEY **a,
const unsigned char **pp, long length,
OSSL_LIB_CTX *libctx, const char *propq);
X509_ALGOR *ossl_X509_ALGOR_from_nid(int nid, int ptype, void *pval);
time_t ossl_asn1_string_to_time_t(const char *asn1_string);
void ossl_asn1_string_set_bits_left(ASN1_STRING *str, unsigned int num);
#endif /* ndef OSSL_CRYPTO_ASN1_H */

View File

@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy

View File

@ -116,4 +116,13 @@ OSSL_LIB_CTX *ossl_bn_get_libctx(BN_CTX *ctx);
extern const BIGNUM ossl_bn_inv_sqrt_2;
#if defined(OPENSSL_SYS_LINUX) && !defined(FIPS_MODULE) && defined (__s390x__)
# define S390X_MOD_EXP
#endif
int s390x_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
int s390x_crt(BIGNUM *r, const BIGNUM *i, const BIGNUM *p, const BIGNUM *q,
const BIGNUM *dmp, const BIGNUM *dmq, const BIGNUM *iqmp);
#endif

View File

@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy

View File

@ -24,6 +24,9 @@ void *ossl_rand_crng_ctx_new(OSSL_LIB_CTX *);
int ossl_thread_register_fips(OSSL_LIB_CTX *);
void *ossl_thread_event_ctx_new(OSSL_LIB_CTX *);
void *ossl_fips_prov_ossl_ctx_new(OSSL_LIB_CTX *);
#if defined(OPENSSL_THREADS)
void *ossl_threads_ctx_new(OSSL_LIB_CTX *);
#endif
void ossl_provider_store_free(void *);
void ossl_property_string_data_free(void *);
@ -40,3 +43,6 @@ void ossl_rand_crng_ctx_free(void *);
void ossl_thread_event_ctx_free(void *);
void ossl_fips_prov_ossl_ctx_free(void *);
void ossl_release_default_drbg_ctx(void);
#if defined(OPENSSL_THREADS)
void ossl_threads_ctx_free(void *);
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -25,16 +25,16 @@ void *ossl_decoder_from_algorithm(int id, const OSSL_ALGORITHM *algodef,
OSSL_DECODER_INSTANCE *
ossl_decoder_instance_new(OSSL_DECODER *decoder, void *decoderctx);
void ossl_decoder_instance_free(OSSL_DECODER_INSTANCE *decoder_inst);
OSSL_DECODER_INSTANCE *ossl_decoder_instance_dup(const OSSL_DECODER_INSTANCE *src);
int ossl_decoder_ctx_add_decoder_inst(OSSL_DECODER_CTX *ctx,
OSSL_DECODER_INSTANCE *di);
int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX *ctx,
EVP_PKEY **pkey, const char *keytype,
OSSL_LIB_CTX *libctx,
const char *propquery);
int ossl_decoder_get_number(const OSSL_DECODER *encoder);
int ossl_decoder_store_cache_flush(OSSL_LIB_CTX *libctx);
int ossl_decoder_store_remove_all_provided(const OSSL_PROVIDER *prov);
void *ossl_decoder_cache_new(OSSL_LIB_CTX *ctx);
void ossl_decoder_cache_free(void *vcache);
int ossl_decoder_cache_flush(OSSL_LIB_CTX *libctx);
#endif

View File

@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy

View File

@ -26,7 +26,9 @@ int ossl_dsa_generate_ffc_parameters(DSA *dsa, int type, int pbits, int qbits,
BN_GENCB *cb);
int ossl_dsa_sign_int(int type, const unsigned char *dgst, int dlen,
unsigned char *sig, unsigned int *siglen, DSA *dsa);
unsigned char *sig, unsigned int *siglen, DSA *dsa,
unsigned int nonce_type, const char *digestname,
OSSL_LIB_CTX *libctx, const char *propq);
FFC_PARAMS *ossl_dsa_get0_params(DSA *dsa);
int ossl_dsa_ffc_params_fromdata(DSA *dsa, const OSSL_PARAM params[]);

View File

@ -95,6 +95,12 @@ char *ossl_ec_pt_format_id2name(int id);
char *ossl_ec_check_group_type_id2name(int flags);
int ossl_ec_set_check_group_type_from_name(EC_KEY *ec, const char *name);
int ossl_ec_generate_key_dhkem(EC_KEY *eckey,
const unsigned char *ikm, size_t ikmlen);
int ossl_ecdsa_deterministic_sign(const unsigned char *dgst, int dlen,
unsigned char *sig, unsigned int *siglen,
EC_KEY *eckey, unsigned int nonce_type,
const char *digestname,
OSSL_LIB_CTX *libctx, const char *propq);
# endif /* OPENSSL_NO_EC */
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -15,7 +15,7 @@
# include <openssl/opensslconf.h>
# ifndef OPENSSL_NO_EC
# ifndef OPENSSL_NO_ECX
# include <openssl/core.h>
# include <openssl/e_os2.h>
@ -72,7 +72,6 @@ struct ecx_key_st {
size_t keylen;
ECX_KEY_TYPE type;
CRYPTO_REF_COUNT references;
CRYPTO_RWLOCK *lock;
};
size_t ossl_ecx_key_length(ECX_KEY_TYPE type);
@ -83,6 +82,9 @@ unsigned char *ossl_ecx_key_allocate_privkey(ECX_KEY *key);
void ossl_ecx_key_free(ECX_KEY *key);
int ossl_ecx_key_up_ref(ECX_KEY *key);
ECX_KEY *ossl_ecx_key_dup(const ECX_KEY *key, int selection);
int ossl_ecx_compute_key(ECX_KEY *peer, ECX_KEY *priv, size_t keylen,
unsigned char *secret, size_t *secretlen,
size_t outlen);
int ossl_x25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
const uint8_t peer_public_value[32]);
@ -94,27 +96,33 @@ ossl_ed25519_public_from_private(OSSL_LIB_CTX *ctx, uint8_t out_public_key[32],
const uint8_t private_key[32],
const char *propq);
int
ossl_ed25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
ossl_ed25519_sign(uint8_t *out_sig, const uint8_t *tbs, size_t tbs_len,
const uint8_t public_key[32], const uint8_t private_key[32],
const uint8_t dom2flag, const uint8_t phflag, const uint8_t csflag,
const uint8_t *context, size_t context_len,
OSSL_LIB_CTX *libctx, const char *propq);
int
ossl_ed25519_verify(const uint8_t *message, size_t message_len,
ossl_ed25519_verify(const uint8_t *tbs, size_t tbs_len,
const uint8_t signature[64], const uint8_t public_key[32],
const uint8_t dom2flag, const uint8_t phflag, const uint8_t csflag,
const uint8_t *context, size_t context_len,
OSSL_LIB_CTX *libctx, const char *propq);
int
ossl_ed448_public_from_private(OSSL_LIB_CTX *ctx, uint8_t out_public_key[57],
const uint8_t private_key[57], const char *propq);
int
ossl_ed448_sign(OSSL_LIB_CTX *ctx, uint8_t *out_sig, const uint8_t *message,
size_t message_len, const uint8_t public_key[57],
const uint8_t private_key[57], const uint8_t *context,
size_t context_len, const char *propq);
ossl_ed448_sign(OSSL_LIB_CTX *ctx, uint8_t *out_sig,
const uint8_t *message, size_t message_len,
const uint8_t public_key[57], const uint8_t private_key[57],
const uint8_t *context, size_t context_len,
const uint8_t phflag, const char *propq);
int
ossl_ed448_verify(OSSL_LIB_CTX *ctx, const uint8_t *message, size_t message_len,
ossl_ed448_verify(OSSL_LIB_CTX *ctx,
const uint8_t *message, size_t message_len,
const uint8_t signature[114], const uint8_t public_key[57],
const uint8_t *context, size_t context_len, const char *propq);
const uint8_t *context, size_t context_len,
const uint8_t phflag, const char *propq);
int
ossl_x448(uint8_t out_shared_key[56], const uint8_t private_key[56],
@ -146,5 +154,5 @@ ECX_KEY *ossl_evp_pkey_get1_X25519(EVP_PKEY *pkey);
ECX_KEY *ossl_evp_pkey_get1_X448(EVP_PKEY *pkey);
ECX_KEY *ossl_evp_pkey_get1_ED25519(EVP_PKEY *pkey);
ECX_KEY *ossl_evp_pkey_get1_ED448(EVP_PKEY *pkey);
# endif /* OPENSSL_NO_EC */
# endif /* OPENSSL_NO_ECX */
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy

View File

@ -16,11 +16,21 @@
# include "internal/refcount.h"
# include "crypto/ecx.h"
/*
* Default PKCS5 PBE KDF salt lengths
* In RFC 8018, PBE1 uses 8 bytes (64 bits) for its salt length.
* It also specifies to use at least 8 bytes for PBES2.
* The NIST requirement for PBKDF2 is 128 bits so we use this as the
* default for PBE2 (scrypt and HKDF2)
*/
# define PKCS5_DEFAULT_PBE1_SALT_LEN PKCS5_SALT_LEN
# define PKCS5_DEFAULT_PBE2_SALT_LEN 16
/*
* Don't free up md_ctx->pctx in EVP_MD_CTX_reset, use the reserved flag
* values in evp.h
*/
#define EVP_MD_CTX_FLAG_KEEP_PKEY_CTX 0x0400
#define EVP_MD_CTX_FLAG_FINALISED 0x0800
#define evp_pkey_ctx_is_legacy(ctx) \
((ctx)->keymgmt == NULL)
@ -203,7 +213,6 @@ struct evp_mac_st {
const char *description;
CRYPTO_REF_COUNT refcnt;
CRYPTO_RWLOCK *lock;
OSSL_FUNC_mac_newctx_fn *newctx;
OSSL_FUNC_mac_dupctx_fn *dupctx;
@ -225,7 +234,6 @@ struct evp_kdf_st {
char *type_name;
const char *description;
CRYPTO_REF_COUNT refcnt;
CRYPTO_RWLOCK *lock;
OSSL_FUNC_kdf_newctx_fn *newctx;
OSSL_FUNC_kdf_dupctx_fn *dupctx;
@ -270,7 +278,6 @@ struct evp_md_st {
const char *description;
OSSL_PROVIDER *prov;
CRYPTO_REF_COUNT refcnt;
CRYPTO_RWLOCK *lock;
OSSL_FUNC_digest_newctx_fn *newctx;
OSSL_FUNC_digest_init_fn *dinit;
OSSL_FUNC_digest_update_fn *dupdate;
@ -326,7 +333,6 @@ struct evp_cipher_st {
const char *description;
OSSL_PROVIDER *prov;
CRYPTO_REF_COUNT refcnt;
CRYPTO_RWLOCK *lock;
OSSL_FUNC_cipher_newctx_fn *newctx;
OSSL_FUNC_cipher_encrypt_init_fn *einit;
OSSL_FUNC_cipher_decrypt_init_fn *dinit;
@ -646,8 +652,10 @@ union legacy_pkey_st {
# endif
# ifndef OPENSSL_NO_EC
struct ec_key_st *ec; /* ECC */
# ifndef OPENSSL_NO_ECX
ECX_KEY *ecx; /* X25519, X448, Ed25519, Ed448 */
# endif
# endif
};
struct evp_pkey_st {
@ -784,7 +792,7 @@ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
OP_CACHE_ELEM *evp_keymgmt_util_find_operation_cache(EVP_PKEY *pk,
EVP_KEYMGMT *keymgmt,
int selection);
int evp_keymgmt_util_clear_operation_cache(EVP_PKEY *pk, int locking);
int evp_keymgmt_util_clear_operation_cache(EVP_PKEY *pk);
int evp_keymgmt_util_cache_keydata(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
void *keydata, int selection);
void evp_keymgmt_util_cache_keyinfo(EVP_PKEY *pk);
@ -813,7 +821,7 @@ int evp_keymgmt_set_params(const EVP_KEYMGMT *keymgmt,
void *evp_keymgmt_gen_init(const EVP_KEYMGMT *keymgmt, int selection,
const OSSL_PARAM params[]);
int evp_keymgmt_gen_set_template(const EVP_KEYMGMT *keymgmt, void *genctx,
void *template);
void *templ);
int evp_keymgmt_gen_set_params(const EVP_KEYMGMT *keymgmt, void *genctx,
const OSSL_PARAM params[]);
void *evp_keymgmt_gen(const EVP_KEYMGMT *keymgmt, void *genctx,
@ -892,10 +900,6 @@ EVP_MD_CTX *evp_md_ctx_new_ex(EVP_PKEY *pkey, const ASN1_OCTET_STRING *id,
int evp_pkey_name2type(const char *name);
const char *evp_pkey_type2name(int type);
int evp_pkey_ctx_set1_id_prov(EVP_PKEY_CTX *ctx, const void *id, int len);
int evp_pkey_ctx_get1_id_prov(EVP_PKEY_CTX *ctx, void *id);
int evp_pkey_ctx_get1_id_len_prov(EVP_PKEY_CTX *ctx, size_t *id_len);
int evp_pkey_ctx_use_cached_data(EVP_PKEY_CTX *ctx);
# endif /* !defined(FIPS_MODULE) */
@ -959,4 +963,8 @@ void evp_rand_clear_seed(EVP_RAND_CTX *ctx,
unsigned char *buffer, size_t b_len);
int evp_signature_get_number(const EVP_SIGNATURE *signature);
int evp_pkey_decrypt_alloc(EVP_PKEY_CTX *ctx, unsigned char **outp,
size_t *outlenp, size_t expected_outlen,
const unsigned char *in, size_t inlen);
#endif /* OSSL_CRYPTO_EVP_H */

View File

@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy

View File

@ -63,6 +63,10 @@
* #define HASH_BLOCK_DATA_ORDER md5_block_data_order
*/
#ifndef OSSL_CRYPTO_MD32_COMMON_H
# define OSSL_CRYPTO_MD32_COMMON_H
# pragma once
# include <openssl/crypto.h>
# if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
@ -276,3 +280,5 @@ int HASH_FINAL(unsigned char *md, HASH_CTX *c)
# define MD32_REG_T int
# endif
# endif
#endif

View File

@ -138,6 +138,12 @@ struct gcm128_context {
#endif
};
/* GHASH functions */
void ossl_gcm_init_4bit(u128 Htable[16], const u64 H[2]);
void ossl_gcm_ghash_4bit(u64 Xi[2], const u128 Htable[16],
const u8 *inp, size_t len);
void ossl_gcm_gmult_4bit(u64 Xi[2], const u128 Htable[16]);
/*
* The maximum permitted number of cipher blocks per data unit in XTS mode.
* Reference IEEE Std 1619-2018.
@ -149,6 +155,12 @@ struct xts128_context {
block128_f block1, block2;
};
/* XTS mode for SM4 algorithm specified by GB/T 17964-2021 */
int ossl_crypto_xts128gb_encrypt(const XTS128_CONTEXT *ctx,
const unsigned char iv[16],
const unsigned char *inp, unsigned char *out,
size_t len, int enc);
struct ccm128_context {
union {
u64 u[2];

View File

@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -22,6 +22,4 @@ int ossl_punycode_decode (
int ossl_a2ulabel(const char *in, char *out, size_t outlen);
int ossl_a2ucompare(const char *a, const char *u);
#endif

View File

@ -140,4 +140,15 @@ EVP_RAND_CTX *ossl_rand_get0_private_noncreating(OSSL_LIB_CTX *ctx);
# else
EVP_RAND_CTX *ossl_rand_get0_seed_noncreating(OSSL_LIB_CTX *ctx);
# endif
/* Generate a uniformly distributed random integer in the interval [0, upper) */
uint32_t ossl_rand_uniform_uint32(OSSL_LIB_CTX *ctx, uint32_t upper, int *err);
/*
* Generate a uniformly distributed random integer in the interval
* [lower, upper).
*/
uint32_t ossl_rand_range_uint32(OSSL_LIB_CTX *ctx, uint32_t lower, uint32_t upper,
int *err);
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -56,4 +56,9 @@ static const size_t kRISCVNumCaps =
# include "riscv_arch.def"
;
/* Extension combination tests. */
#define RISCV_HAS_ZBB_AND_ZBC() (RISCV_HAS_ZBB() && RISCV_HAS_ZBC())
#define RISCV_HAS_ZBKB_AND_ZKND_AND_ZKNE() (RISCV_HAS_ZBKB() && RISCV_HAS_ZKND() && RISCV_HAS_ZKNE())
#define RISCV_HAS_ZKND_AND_ZKNE() (RISCV_HAS_ZKND() && RISCV_HAS_ZKNE())
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -34,8 +34,6 @@ int ossl_rsa_pss_params_30_copy(RSA_PSS_PARAMS_30 *to,
int ossl_rsa_pss_params_30_is_unrestricted(const RSA_PSS_PARAMS_30 *rsa_pss_params);
int ossl_rsa_pss_params_30_set_hashalg(RSA_PSS_PARAMS_30 *rsa_pss_params,
int hashalg_nid);
int ossl_rsa_pss_params_30_set_maskgenalg(RSA_PSS_PARAMS_30 *rsa_pss_params,
int maskgenalg_nid);
int ossl_rsa_pss_params_30_set_maskgenhashalg(RSA_PSS_PARAMS_30 *rsa_pss_params,
int maskgenhashalg_nid);
int ossl_rsa_pss_params_30_set_saltlen(RSA_PSS_PARAMS_30 *rsa_pss_params,
@ -83,6 +81,10 @@ int ossl_rsa_param_decode(RSA *rsa, const X509_ALGOR *alg);
RSA *ossl_rsa_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
OSSL_LIB_CTX *libctx, const char *propq);
int ossl_rsa_padding_check_PKCS1_type_2(OSSL_LIB_CTX *ctx,
unsigned char *to, int tlen,
const unsigned char *from, int flen,
int num, unsigned char *kdk);
int ossl_rsa_padding_check_PKCS1_type_2_TLS(OSSL_LIB_CTX *ctx, unsigned char *to,
size_t tlen,
const unsigned char *from,

View File

@ -1,5 +1,5 @@
/*
* Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2018-2023 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
@ -14,6 +14,7 @@
# include <openssl/sha.h>
int ossl_sha256_192_init(SHA256_CTX *c);
int sha512_224_init(SHA512_CTX *);
int sha512_256_init(SHA512_CTX *);
int ossl_sha1_ctrl(SHA_CTX *ctx, int cmd, int mslen, void *ms);

View File

@ -12,7 +12,7 @@
# pragma once
# if defined(OPENSSL_CPUID_OBJ)
# if defined(__aarch64__)
# if defined(__aarch64__) || defined (_M_ARM64)
# include "arm_arch.h"
extern unsigned int OPENSSL_arm_midr;
static inline int vpsm4_capable(void)
@ -21,8 +21,14 @@ static inline int vpsm4_capable(void)
(MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V1) ||
MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N1));
}
static inline int vpsm4_ex_capable(void)
{
return (OPENSSL_armcap_P & ARMV8_CPUID) &&
(MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, HISI_CPU_IMP, HISI_CPU_PART_KP920));
}
# if defined(VPSM4_ASM)
# define VPSM4_CAPABLE vpsm4_capable()
# define VPSM4_EX_CAPABLE vpsm4_ex_capable()
# endif
# define HWSM4_CAPABLE (OPENSSL_armcap_P & ARMV8_SM4)
# define HWSM4_set_encrypt_key sm4_v8_set_encrypt_key
@ -69,7 +75,37 @@ void vpsm4_ecb_encrypt(const unsigned char *in, unsigned char *out,
void vpsm4_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out,
size_t len, const void *key,
const unsigned char ivec[16]);
void vpsm4_xts_encrypt(const unsigned char *in, unsigned char *out,
size_t len, const SM4_KEY *key1, const SM4_KEY *key2,
const unsigned char ivec[16], const int enc);
void vpsm4_xts_encrypt_gb(const unsigned char *in, unsigned char *out,
size_t len, const SM4_KEY *key1, const SM4_KEY *key2,
const unsigned char ivec[16], const int enc);
# endif /* VPSM4_CAPABLE */
# ifdef VPSM4_EX_CAPABLE
int vpsm4_ex_set_encrypt_key(const unsigned char *userKey, SM4_KEY *key);
int vpsm4_ex_set_decrypt_key(const unsigned char *userKey, SM4_KEY *key);
void vpsm4_ex_encrypt(const unsigned char *in, unsigned char *out,
const SM4_KEY *key);
void vpsm4_ex_decrypt(const unsigned char *in, unsigned char *out,
const SM4_KEY *key);
void vpsm4_ex_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const SM4_KEY *key,
unsigned char *ivec, const int enc);
void vpsm4_ex_ecb_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const SM4_KEY *key,
const int enc);
void vpsm4_ex_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out,
size_t len, const void *key,
const unsigned char ivec[16]);
void vpsm4_ex_xts_encrypt(const unsigned char *in, unsigned char *out,
size_t len, const SM4_KEY *key1, const SM4_KEY *key2,
const unsigned char ivec[16], const int enc);
void vpsm4_ex_xts_encrypt_gb(const unsigned char *in, unsigned char *out,
size_t len, const SM4_KEY *key1,
const SM4_KEY *key2, const unsigned char ivec[16],
const int enc);
# endif /* VPSM4_EX_CAPABLE */
#endif /* OSSL_SM4_PLATFORM_H */

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy

View File

@ -278,6 +278,8 @@ struct x509_store_ctx_st { /* X509_STORE_CTX */
SSL_DANE *dane;
/* signed via bare TA public key, rather than CA certificate */
int bare_ta_signed;
/* Raw Public Key */
EVP_PKEY *rpk;
OSSL_LIB_CTX *libctx;
char *propq;
@ -309,7 +311,7 @@ struct x509_object_st {
};
int ossl_a2i_ipadd(unsigned char *ipout, const char *ipasc);
int ossl_x509_set1_time(ASN1_TIME **ptm, const ASN1_TIME *tm);
int ossl_x509_set1_time(int *modified, ASN1_TIME **ptm, const ASN1_TIME *tm);
int ossl_x509_print_ex_brief(BIO *bio, X509 *cert, unsigned long neg_cflags);
int ossl_x509v3_cache_extensions(X509 *x);
int ossl_x509_init_sig_info(X509 *x);
@ -334,7 +336,8 @@ int ossl_x509_PUBKEY_get0_libctx(OSSL_LIB_CTX **plibctx, const char **ppropq,
ASN1_OCTET_STRING *ossl_x509_pubkey_hash(X509_PUBKEY *pubkey);
X509_PUBKEY *ossl_d2i_X509_PUBKEY_INTERNAL(const unsigned char **pp,
long len, OSSL_LIB_CTX *libctx);
long len, OSSL_LIB_CTX *libctx,
const char *propq);
void ossl_X509_PUBKEY_INTERNAL_free(X509_PUBKEY *xpub);
RSA *ossl_d2i_RSA_PSS_PUBKEY(RSA **a, const unsigned char **pp, long length);
@ -364,6 +367,7 @@ int ossl_i2d_X448_PUBKEY(const ECX_KEY *a, unsigned char **pp);
# endif /* OPENSSL_NO_EC */
EVP_PKEY *ossl_d2i_PUBKEY_legacy(EVP_PKEY **a, const unsigned char **pp,
long length);
int ossl_x509_check_private_key(const EVP_PKEY *k, const EVP_PKEY *pkey);
int x509v3_add_len_value_uchar(const char *name, const unsigned char *value,
size_t vallen, STACK_OF(CONF_VALUE) **extlist);

View File

@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy

View File

@ -11,6 +11,8 @@
# define OSSL_INTERNAL_ASN1_H
# pragma once
# include <openssl/bio.h>
int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb);
#endif

View File

@ -27,6 +27,8 @@ struct bio_method_st {
int (*create) (BIO *);
int (*destroy) (BIO *);
long (*callback_ctrl) (BIO *, int, BIO_info_cb *);
int (*bsendmmsg) (BIO *, BIO_MSG *, size_t, size_t, uint64_t, size_t *);
int (*brecvmmsg) (BIO *, BIO_MSG *, size_t, size_t, uint64_t, size_t *);
};
void bio_free_ex_data(BIO *bio);
@ -41,16 +43,20 @@ int bread_conv(BIO *bio, char *data, size_t datal, size_t *read);
# define BIO_CTRL_SET_KTLS 72
# define BIO_CTRL_SET_KTLS_TX_SEND_CTRL_MSG 74
# define BIO_CTRL_CLEAR_KTLS_TX_CTRL_MSG 75
# define BIO_CTRL_SET_KTLS_TX_ZEROCOPY_SENDFILE 90
/*
* This is used with socket BIOs:
* BIO_FLAGS_KTLS_TX means we are using ktls with this BIO for sending.
* BIO_FLAGS_KTLS_TX_CTRL_MSG means we are about to send a ctrl message next.
* BIO_FLAGS_KTLS_RX means we are using ktls with this BIO for receiving.
* BIO_FLAGS_KTLS_TX_ZEROCOPY_SENDFILE means we are using the zerocopy mode with
* this BIO for sending using sendfile.
*/
# define BIO_FLAGS_KTLS_TX_CTRL_MSG 0x1000
# define BIO_FLAGS_KTLS_RX 0x2000
# define BIO_FLAGS_KTLS_TX 0x4000
# define BIO_FLAGS_KTLS_TX_ZEROCOPY_SENDFILE 0x8000
/* KTLS related controls and flags */
# define BIO_set_ktls_flag(b, is_tx) \
@ -63,6 +69,8 @@ int bread_conv(BIO *bio, char *data, size_t datal, size_t *read);
BIO_test_flags(b, BIO_FLAGS_KTLS_TX_CTRL_MSG)
# define BIO_clear_ktls_ctrl_msg_flag(b) \
BIO_clear_flags(b, BIO_FLAGS_KTLS_TX_CTRL_MSG)
# define BIO_set_ktls_zerocopy_sendfile_flag(b) \
BIO_set_flags(b, BIO_FLAGS_KTLS_TX_ZEROCOPY_SENDFILE)
# define BIO_set_ktls(b, keyblob, is_tx) \
BIO_ctrl(b, BIO_CTRL_SET_KTLS, is_tx, keyblob)
@ -70,6 +78,8 @@ int bread_conv(BIO *bio, char *data, size_t datal, size_t *read);
BIO_ctrl(b, BIO_CTRL_SET_KTLS_TX_SEND_CTRL_MSG, record_type, NULL)
# define BIO_clear_ktls_ctrl_msg(b) \
BIO_ctrl(b, BIO_CTRL_CLEAR_KTLS_TX_CTRL_MSG, 0, NULL)
# define BIO_set_ktls_tx_zerocopy_sendfile(b) \
BIO_ctrl(b, BIO_CTRL_SET_KTLS_TX_ZEROCOPY_SENDFILE, 0, NULL)
/* Functions to allow the core to offer the CORE_BIO type to providers */
OSSL_CORE_BIO *ossl_core_bio_new_from_bio(BIO *bio);

View File

@ -0,0 +1,29 @@
/*
* Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_BIO_ADDR_H
# define OSSL_BIO_ADDR_H
# include "internal/e_os.h"
# include "internal/sockets.h"
# ifndef OPENSSL_NO_SOCK
union bio_addr_st {
struct sockaddr sa;
# if OPENSSL_USE_IPV6
struct sockaddr_in6 s_in6;
# endif
struct sockaddr_in s_in;
# ifndef OPENSSL_NO_UNIX_SOCK
struct sockaddr_un s_un;
# endif
};
# endif
#endif

View File

@ -0,0 +1,151 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* Contains definitions for simplifying the use of TCP Fast Open
* (RFC7413) in OpenSSL socket BIOs.
*/
/* If a supported OS is added here, update test/bio_tfo_test.c */
#if defined(TCP_FASTOPEN) && !defined(OPENSSL_NO_TFO)
# if defined(OPENSSL_SYS_MACOSX) || defined(__FreeBSD__)
# include <sys/sysctl.h>
# endif
/*
* OSSL_TFO_SYSCTL is used to determine if TFO is supported by
* this kernel, and if supported, if it is enabled. This is more of
* a problem on FreeBSD 10.3 ~ 11.4, where TCP_FASTOPEN was defined,
* but not enabled by default in the kernel, and only for the server.
* Linux does not have sysctlbyname(), and the closest equivalent
* is to go into the /proc filesystem, but I'm not sure it's
* worthwhile.
*
* On MacOS and Linux:
* These operating systems use a single parameter to control TFO.
* The OSSL_TFO_CLIENT_FLAG and OSSL_TFO_SERVER_FLAGS are used to
* determine if TFO is enabled for the client and server respectively.
*
* OSSL_TFO_CLIENT_FLAG = 1 = client TFO enabled
* OSSL_TFO_SERVER_FLAG = 2 = server TFO enabled
*
* Such that:
* 0 = TFO disabled
* 3 = server and client TFO enabled
*
* macOS 10.14 and later support TFO.
* Linux kernel 3.6 added support for client TFO.
* Linux kernel 3.7 added support for server TFO.
* Linux kernel 3.13 enabled TFO by default.
* Linux kernel 4.11 added the TCP_FASTOPEN_CONNECT option.
*
* On FreeBSD:
* FreeBSD 10.3 ~ 11.4 uses a single sysctl for server enable.
* FreeBSD 12.0 and later uses separate sysctls for server and
* client enable.
*
* Some options are purposely NOT defined per-platform
*
* OSSL_TFO_SYSCTL
* Defined as a sysctlbyname() option to determine if
* TFO is enabled in the kernel (macOS, FreeBSD)
*
* OSSL_TFO_SERVER_SOCKOPT
* Defined to indicate the socket option used to enable
* TFO on a server socket (all)
*
* OSSL_TFO_SERVER_SOCKOPT_VALUE
* Value to be used with OSSL_TFO_SERVER_SOCKOPT
*
* OSSL_TFO_CONNECTX
* Use the connectx() function to make a client connection
* (macOS)
*
* OSSL_TFO_CLIENT_SOCKOPT
* Defined to indicate the socket option used to enable
* TFO on a client socket (FreeBSD, Linux 4.14 and later)
*
* OSSL_TFO_SENDTO
* Defined to indicate the sendto() message type to
* be used to initiate a TFO connection (FreeBSD,
* Linux pre-4.14)
*
* OSSL_TFO_DO_NOT_CONNECT
* Defined to skip calling connect() when creating a
* client socket (macOS, FreeBSD, Linux pre-4.14)
*/
# if defined(OPENSSL_SYS_WINDOWS)
/*
* NO WINDOWS SUPPORT
*
* But this is what would be used on the server:
*
* define OSSL_TFO_SERVER_SOCKOPT TCP_FASTOPEN
* define OSSL_TFO_SERVER_SOCKOPT_VALUE 1
*
* Still have to figure out client support
*/
# undef TCP_FASTOPEN
# endif
/* NO VMS SUPPORT */
# if defined(OPENSSL_SYS_VMS)
# undef TCP_FASTOPEN
# endif
# if defined(OPENSSL_SYS_MACOSX)
# define OSSL_TFO_SYSCTL "net.inet.tcp.fastopen"
# define OSSL_TFO_SERVER_SOCKOPT TCP_FASTOPEN
# define OSSL_TFO_SERVER_SOCKOPT_VALUE 1
# define OSSL_TFO_CONNECTX 1
# define OSSL_TFO_DO_NOT_CONNECT 1
# define OSSL_TFO_CLIENT_FLAG 1
# define OSSL_TFO_SERVER_FLAG 2
# endif
# if defined(__FreeBSD__)
# if defined(TCP_FASTOPEN_PSK_LEN)
/* As of 12.0 these are the SYSCTLs */
# define OSSL_TFO_SYSCTL_SERVER "net.inet.tcp.fastopen.server_enable"
# define OSSL_TFO_SYSCTL_CLIENT "net.inet.tcp.fastopen.client_enable"
# define OSSL_TFO_SERVER_SOCKOPT TCP_FASTOPEN
# define OSSL_TFO_SERVER_SOCKOPT_VALUE MAX_LISTEN
# define OSSL_TFO_CLIENT_SOCKOPT TCP_FASTOPEN
# define OSSL_TFO_DO_NOT_CONNECT 1
# define OSSL_TFO_SENDTO 0
/* These are the same because the sysctl are client/server-specific */
# define OSSL_TFO_CLIENT_FLAG 1
# define OSSL_TFO_SERVER_FLAG 1
# else
/* 10.3 through 11.4 SYSCTL - ONLY SERVER SUPPORT */
# define OSSL_TFO_SYSCTL "net.inet.tcp.fastopen.enabled"
# define OSSL_TFO_SERVER_SOCKOPT TCP_FASTOPEN
# define OSSL_TFO_SERVER_SOCKOPT_VALUE MAX_LISTEN
# define OSSL_TFO_SERVER_FLAG 1
# endif
# endif
# if defined(OPENSSL_SYS_LINUX)
/* OSSL_TFO_PROC not used, but of interest */
# define OSSL_TFO_PROC "/proc/sys/net/ipv4/tcp_fastopen"
# define OSSL_TFO_SERVER_SOCKOPT TCP_FASTOPEN
# define OSSL_TFO_SERVER_SOCKOPT_VALUE MAX_LISTEN
# if defined(TCP_FASTOPEN_CONNECT)
# define OSSL_TFO_CLIENT_SOCKOPT TCP_FASTOPEN_CONNECT
# else
# define OSSL_TFO_SENDTO MSG_FASTOPEN
# define OSSL_TFO_DO_NOT_CONNECT 1
# endif
# define OSSL_TFO_CLIENT_FLAG 1
# define OSSL_TFO_SERVER_FLAG 2
# endif
#endif

View File

@ -0,0 +1,217 @@
/*
* Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_INTERNAL_COMMON_H
# define OSSL_INTERNAL_COMMON_H
# pragma once
# include <stdlib.h>
# include <string.h>
# include "openssl/configuration.h"
# include "internal/e_os.h" /* ossl_inline in many files */
# include "internal/nelem.h"
# if defined(__GNUC__) || defined(__clang__)
# define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0)
# else
# define likely(x) x
# define unlikely(x) x
# endif
# if defined(__GNUC__) || defined(__clang__)
# define ALIGN32 __attribute((aligned(32)))
# define ALIGN64 __attribute((aligned(64)))
# elif defined(_MSC_VER)
# define ALIGN32 __declspec(align(32))
# define ALIGN64 __declspec(align(64))
# else
# define ALIGN32
# define ALIGN64
# endif
# ifdef NDEBUG
# define ossl_assert(x) ((x) != 0)
# else
__owur static ossl_inline int ossl_assert_int(int expr, const char *exprstr,
const char *file, int line)
{
if (!expr)
OPENSSL_die(exprstr, file, line);
return expr;
}
# define ossl_assert(x) ossl_assert_int((x) != 0, "Assertion failed: "#x, \
__FILE__, __LINE__)
# endif
/* Check if |pre|, which must be a string literal, is a prefix of |str| */
#define HAS_PREFIX(str, pre) (strncmp(str, pre "", sizeof(pre) - 1) == 0)
/* As before, and if check succeeds, advance |str| past the prefix |pre| */
#define CHECK_AND_SKIP_PREFIX(str, pre) \
(HAS_PREFIX(str, pre) ? ((str) += sizeof(pre) - 1, 1) : 0)
/* Check if the string literal |p| is a case-insensitive prefix of |s| */
#define HAS_CASE_PREFIX(s, p) (OPENSSL_strncasecmp(s, p "", sizeof(p) - 1) == 0)
/* As before, and if check succeeds, advance |str| past the prefix |pre| */
#define CHECK_AND_SKIP_CASE_PREFIX(str, pre) \
(HAS_CASE_PREFIX(str, pre) ? ((str) += sizeof(pre) - 1, 1) : 0)
/* Check if the string literal |suffix| is a case-insensitive suffix of |str| */
#define HAS_CASE_SUFFIX(str, suffix) (strlen(str) < sizeof(suffix) - 1 ? 0 : \
OPENSSL_strcasecmp(str + strlen(str) - sizeof(suffix) + 1, suffix "") == 0)
/*
* Use this inside a union with the field that needs to be aligned to a
* reasonable boundary for the platform. The most pessimistic alignment
* of the listed types will be used by the compiler.
*/
# define OSSL_UNION_ALIGN \
double align; \
ossl_uintmax_t align_int; \
void *align_ptr
# define OPENSSL_CONF "openssl.cnf"
# ifndef OPENSSL_SYS_VMS
# define X509_CERT_AREA OPENSSLDIR
# define X509_CERT_DIR OPENSSLDIR "/certs"
# define X509_CERT_FILE OPENSSLDIR "/cert.pem"
# define X509_PRIVATE_DIR OPENSSLDIR "/private"
# define CTLOG_FILE OPENSSLDIR "/ct_log_list.cnf"
# else
# define X509_CERT_AREA "OSSL$DATAROOT:[000000]"
# define X509_CERT_DIR "OSSL$DATAROOT:[CERTS]"
# define X509_CERT_FILE "OSSL$DATAROOT:[000000]cert.pem"
# define X509_PRIVATE_DIR "OSSL$DATAROOT:[PRIVATE]"
# define CTLOG_FILE "OSSL$DATAROOT:[000000]ct_log_list.cnf"
# endif
# define X509_CERT_DIR_EVP "SSL_CERT_DIR"
# define X509_CERT_FILE_EVP "SSL_CERT_FILE"
# define CTLOG_FILE_EVP "CTLOG_FILE"
/* size of string representations */
# define DECIMAL_SIZE(type) ((sizeof(type)*8+2)/3+1)
# define HEX_SIZE(type) (sizeof(type)*2)
# define c2l(c,l) (l = ((unsigned long)(*((c)++))) , \
l|=(((unsigned long)(*((c)++)))<< 8), \
l|=(((unsigned long)(*((c)++)))<<16), \
l|=(((unsigned long)(*((c)++)))<<24))
/* NOTE - c is not incremented as per c2l */
# define c2ln(c,l1,l2,n) { \
c+=n; \
l1=l2=0; \
switch (n) { \
case 8: l2 =((unsigned long)(*(--(c))))<<24; \
case 7: l2|=((unsigned long)(*(--(c))))<<16; \
case 6: l2|=((unsigned long)(*(--(c))))<< 8; \
case 5: l2|=((unsigned long)(*(--(c)))); \
case 4: l1 =((unsigned long)(*(--(c))))<<24; \
case 3: l1|=((unsigned long)(*(--(c))))<<16; \
case 2: l1|=((unsigned long)(*(--(c))))<< 8; \
case 1: l1|=((unsigned long)(*(--(c)))); \
} \
}
# define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
*((c)++)=(unsigned char)(((l)>> 8)&0xff), \
*((c)++)=(unsigned char)(((l)>>16)&0xff), \
*((c)++)=(unsigned char)(((l)>>24)&0xff))
# define n2l(c,l) (l =((unsigned long)(*((c)++)))<<24, \
l|=((unsigned long)(*((c)++)))<<16, \
l|=((unsigned long)(*((c)++)))<< 8, \
l|=((unsigned long)(*((c)++))))
# define n2l8(c,l) (l =((uint64_t)(*((c)++)))<<56, \
l|=((uint64_t)(*((c)++)))<<48, \
l|=((uint64_t)(*((c)++)))<<40, \
l|=((uint64_t)(*((c)++)))<<32, \
l|=((uint64_t)(*((c)++)))<<24, \
l|=((uint64_t)(*((c)++)))<<16, \
l|=((uint64_t)(*((c)++)))<< 8, \
l|=((uint64_t)(*((c)++))))
# define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \
*((c)++)=(unsigned char)(((l)>>16)&0xff), \
*((c)++)=(unsigned char)(((l)>> 8)&0xff), \
*((c)++)=(unsigned char)(((l) )&0xff))
# define l2n8(l,c) (*((c)++)=(unsigned char)(((l)>>56)&0xff), \
*((c)++)=(unsigned char)(((l)>>48)&0xff), \
*((c)++)=(unsigned char)(((l)>>40)&0xff), \
*((c)++)=(unsigned char)(((l)>>32)&0xff), \
*((c)++)=(unsigned char)(((l)>>24)&0xff), \
*((c)++)=(unsigned char)(((l)>>16)&0xff), \
*((c)++)=(unsigned char)(((l)>> 8)&0xff), \
*((c)++)=(unsigned char)(((l) )&0xff))
/* NOTE - c is not incremented as per l2c */
# define l2cn(l1,l2,c,n) { \
c+=n; \
switch (n) { \
case 8: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \
case 7: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \
case 6: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \
case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \
case 4: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \
case 3: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \
case 2: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \
case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \
} \
}
# define n2s(c,s) ((s=(((unsigned int)((c)[0]))<< 8)| \
(((unsigned int)((c)[1])) )),(c)+=2)
# define s2n(s,c) (((c)[0]=(unsigned char)(((s)>> 8)&0xff), \
(c)[1]=(unsigned char)(((s) )&0xff)),(c)+=2)
# define n2l3(c,l) ((l =(((unsigned long)((c)[0]))<<16)| \
(((unsigned long)((c)[1]))<< 8)| \
(((unsigned long)((c)[2])) )),(c)+=3)
# define l2n3(l,c) (((c)[0]=(unsigned char)(((l)>>16)&0xff), \
(c)[1]=(unsigned char)(((l)>> 8)&0xff), \
(c)[2]=(unsigned char)(((l) )&0xff)),(c)+=3)
static ossl_inline int ossl_ends_with_dirsep(const char *path)
{
if (*path != '\0')
path += strlen(path) - 1;
# if defined __VMS
if (*path == ']' || *path == '>' || *path == ':')
return 1;
# elif defined _WIN32
if (*path == '\\')
return 1;
# endif
return *path == '/';
}
static ossl_inline int ossl_is_absolute_path(const char *path)
{
# if defined __VMS
if (strchr(path, ':') != NULL
|| ((path[0] == '[' || path[0] == '<')
&& path[1] != '.' && path[1] != '-'
&& path[1] != ']' && path[1] != '>'))
return 1;
# elif defined _WIN32
if (path[0] == '\\'
|| (path[0] != '\0' && path[1] == ':'))
return 1;
# endif
return path[0] == '/';
}
#endif

View File

@ -10,3 +10,5 @@
#include <openssl/comp.h>
void ossl_comp_zlib_cleanup(void);
void ossl_comp_brotli_cleanup(void);
void ossl_comp_zstd_cleanup(void);

View File

@ -1,5 +1,5 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -11,9 +11,6 @@
# define OSSL_INTERNAL_CRYPTLIB_H
# pragma once
# include <stdlib.h>
# include <string.h>
# ifdef OPENSSL_USE_APPLINK
# define BIO_FLAGS_UPLINK_INTERNAL 0x8000
# include "ms/uplink.h"
@ -21,39 +18,13 @@
# define BIO_FLAGS_UPLINK_INTERNAL 0
# endif
# include "internal/common.h"
# include <openssl/crypto.h>
# include <openssl/buffer.h>
# include <openssl/bio.h>
# include <openssl/asn1.h>
# include <openssl/err.h>
# include "internal/nelem.h"
#ifdef NDEBUG
# define ossl_assert(x) ((x) != 0)
#else
__owur static ossl_inline int ossl_assert_int(int expr, const char *exprstr,
const char *file, int line)
{
if (!expr)
OPENSSL_die(exprstr, file, line);
return expr;
}
# define ossl_assert(x) ossl_assert_int((x) != 0, "Assertion failed: "#x, \
__FILE__, __LINE__)
#endif
/*
* Use this inside a union with the field that needs to be aligned to a
* reasonable boundary for the platform. The most pessimistic alignment
* of the listed types will be used by the compiler.
*/
# define OSSL_UNION_ALIGN \
double align; \
ossl_uintmax_t align_int; \
void *align_ptr
typedef struct ex_callback_st EX_CALLBACK;
DEFINE_STACK_OF(EX_CALLBACK)
@ -61,30 +32,6 @@ DEFINE_STACK_OF(EX_CALLBACK)
typedef struct mem_st MEM;
DEFINE_LHASH_OF_EX(MEM);
# define OPENSSL_CONF "openssl.cnf"
# ifndef OPENSSL_SYS_VMS
# define X509_CERT_AREA OPENSSLDIR
# define X509_CERT_DIR OPENSSLDIR "/certs"
# define X509_CERT_FILE OPENSSLDIR "/cert.pem"
# define X509_PRIVATE_DIR OPENSSLDIR "/private"
# define CTLOG_FILE OPENSSLDIR "/ct_log_list.cnf"
# else
# define X509_CERT_AREA "OSSL$DATAROOT:[000000]"
# define X509_CERT_DIR "OSSL$DATAROOT:[CERTS]"
# define X509_CERT_FILE "OSSL$DATAROOT:[000000]cert.pem"
# define X509_PRIVATE_DIR "OSSL$DATAROOT:[PRIVATE]"
# define CTLOG_FILE "OSSL$DATAROOT:[000000]ct_log_list.cnf"
# endif
# define X509_CERT_DIR_EVP "SSL_CERT_DIR"
# define X509_CERT_FILE_EVP "SSL_CERT_FILE"
# define CTLOG_FILE_EVP "CTLOG_FILE"
/* size of string representations */
# define DECIMAL_SIZE(type) ((sizeof(type)*8+2)/3+1)
# define HEX_SIZE(type) (sizeof(type)*2)
void OPENSSL_cpuid_setup(void);
#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
defined(__x86_64) || defined(__x86_64__) || \
@ -168,7 +115,9 @@ typedef struct ossl_ex_data_global_st {
# define OSSL_LIB_CTX_PROVIDER_CONF_INDEX 16
# define OSSL_LIB_CTX_BIO_CORE_INDEX 17
# define OSSL_LIB_CTX_CHILD_PROVIDER_INDEX 18
# define OSSL_LIB_CTX_MAX_INDEXES 19
# define OSSL_LIB_CTX_THREAD_INDEX 19
# define OSSL_LIB_CTX_DECODER_CACHE_INDEX 20
# define OSSL_LIB_CTX_MAX_INDEXES 20
OSSL_LIB_CTX *ossl_lib_ctx_get_concrete(OSSL_LIB_CTX *ctx);
int ossl_lib_ctx_is_default(OSSL_LIB_CTX *ctx);
@ -211,34 +160,4 @@ char *ossl_buf2hexstr_sep(const unsigned char *buf, long buflen, char sep);
unsigned char *ossl_hexstr2buf_sep(const char *str, long *buflen,
const char sep);
static ossl_inline int ossl_ends_with_dirsep(const char *path)
{
if (*path != '\0')
path += strlen(path) - 1;
# if defined __VMS
if (*path == ']' || *path == '>' || *path == ':')
return 1;
# elif defined _WIN32
if (*path == '\\')
return 1;
# endif
return *path == '/';
}
static ossl_inline int ossl_is_absolute_path(const char *path)
{
# if defined __VMS
if (strchr(path, ':') != NULL
|| ((path[0] == '[' || path[0] == '<')
&& path[1] != '.' && path[1] != '-'
&& path[1] != ']' && path[1] != '>'))
return 1;
# elif defined _WIN32
if (path[0] == '\\'
|| (path[0] != '\0' && path[1] == ':'))
return 1;
# endif
return path[0] == '/';
}
#endif

View File

@ -7,6 +7,10 @@
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_INTERNAL_DER_H
# define OSSL_INTERNAL_DER_H
# pragma once
# include <openssl/bn.h>
# include "internal/packet.h"
@ -86,3 +90,5 @@ int ossl_DER_w_octet_string_uint32(WPACKET *pkt, int tag, uint32_t value);
*/
int ossl_DER_w_begin_sequence(WPACKET *pkt, int tag);
int ossl_DER_w_end_sequence(WPACKET *pkt, int tag);
#endif

View File

@ -0,0 +1,24 @@
/*
* Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_INTERNAL_DETERMINISTIC_NONCE_H
# define OSSL_INTERNAL_DETERMINISTIC_NONCE_H
# pragma once
# include <openssl/bn.h>
int ossl_gen_deterministic_nonce_rfc6979(BIGNUM *out, const BIGNUM *q,
const BIGNUM *priv,
const unsigned char *message,
size_t message_len,
const char *digestname,
OSSL_LIB_CTX *libctx,
const char *propq);
#endif /*OSSL_INTERNAL_DETERMINISTIC_NONCE_H */

View File

@ -1,5 +1,5 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -143,7 +143,7 @@ static __inline unsigned int _strlen31(const char *str)
# undef stdin
# undef stdout
# undef stderr
FILE *__iob_func();
FILE *__iob_func(void);
# define stdin (&__iob_func()[0])
# define stdout (&__iob_func()[1])
# define stderr (&__iob_func()[2])
@ -249,7 +249,7 @@ FILE *__iob_func();
/***********************************************/
# if defined(OPENSSL_SYS_WINDOWS)
# if (_MSC_VER >= 1310) && !defined(_WIN32_WCE)
# if defined(_MSC_VER) && (_MSC_VER >= 1310) && !defined(_WIN32_WCE)
# define open _open
# define fdopen _fdopen
# define close _close
@ -286,54 +286,6 @@ struct servent *getservbyname(const char *name, const char *proto);
# endif
/* end vxworks */
/* system-specific variants defining ossl_sleep() */
#if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__)
# include <unistd.h>
static ossl_inline void ossl_sleep(unsigned long millis)
{
# ifdef OPENSSL_SYS_VXWORKS
struct timespec ts;
ts.tv_sec = (long int) (millis / 1000);
ts.tv_nsec = (long int) (millis % 1000) * 1000000ul;
nanosleep(&ts, NULL);
# elif defined(__TANDEM)
# if !defined(_REENTRANT)
# include <cextdecs.h(PROCESS_DELAY_)>
/* HPNS does not support usleep for non threaded apps */
PROCESS_DELAY_(millis * 1000);
# elif defined(_SPT_MODEL_)
# include <spthread.h>
# include <spt_extensions.h>
usleep(millis * 1000);
# else
usleep(millis * 1000);
# endif
# else
usleep(millis * 1000);
# endif
}
#elif defined(_WIN32)
# include <windows.h>
static ossl_inline void ossl_sleep(unsigned long millis)
{
Sleep(millis);
}
#else
/* Fallback to a busy wait */
static ossl_inline void ossl_sleep(unsigned long millis)
{
struct timeval start, now;
unsigned long elapsedms;
gettimeofday(&start, NULL);
do {
gettimeofday(&now, NULL);
elapsedms = (((now.tv_sec - start.tv_sec) * 1000000)
+ now.tv_usec - start.tv_usec) / 1000;
} while (elapsedms < millis);
}
#endif /* defined OPENSSL_SYS_UNIX */
/* ----------------------------- HP NonStop -------------------------------- */
/* Required to support platform variant without getpid() and pid_t. */
# if defined(__TANDEM) && defined(_GUARDIAN_TARGET)
@ -343,12 +295,12 @@ static ossl_inline void ossl_sleep(unsigned long millis)
# define gethostbyname(name) gethostbyname((char*)name)
# define ioctlsocket(a,b,c) ioctl(a,b,c)
# ifdef NO_GETPID
inline int nssgetpid();
inline int nssgetpid(void);
# ifndef NSSGETPID_MACRO
# define NSSGETPID_MACRO
# include <cextdecs.h(PROCESSHANDLE_GETMINE_)>
# include <cextdecs.h(PROCESSHANDLE_DECOMPOSE_)>
inline int nssgetpid()
inline int nssgetpid(void)
{
short phandle[10]={0};
union pseudo_pid {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -12,7 +12,7 @@
# pragma once
/*
* IS_LITTLE_ENDIAN and IS_BIG_ENDIAN can be used to detect the endiannes
* IS_LITTLE_ENDIAN and IS_BIG_ENDIAN can be used to detect the endianness
* at compile time. To use it, DECLARE_IS_ENDIAN must be used to declare
* a variable.
*

View File

@ -0,0 +1,163 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_INTERNAL_EVENT_QUEUE_H
# define OSSL_INTERNAL_EVENT_QUEUE_H
# pragma once
# include "internal/priority_queue.h"
# include "internal/time.h"
/*
* Opaque type holding an event.
*/
typedef struct ossl_event_st OSSL_EVENT;
DEFINE_PRIORITY_QUEUE_OF(OSSL_EVENT);
/*
* Public type representing an event queue, the underlying structure being
* opaque.
*/
typedef struct ossl_event_queue_st OSSL_EVENT_QUEUE;
/*
* Public type representing a event queue entry.
* It is (internally) public so that it can be embedded into other structures,
* it should otherwise be treated as opaque.
*/
struct ossl_event_st {
uint32_t type; /* What type of event this is */
uint32_t priority; /* What priority this event has */
OSSL_TIME when; /* When the event is scheduled to happen */
void *ctx; /* User argument passed to call backs */
void *payload; /* Event specific data of unknown kind */
size_t payload_size; /* Length (in bytes) of event specific data */
/* These fields are for internal use only */
PRIORITY_QUEUE_OF(OSSL_EVENT) *queue; /* Queue containing this event */
size_t ref; /* ID for this event */
unsigned int flag_dynamic : 1; /* Malloced or not? */
};
/*
* Utility function to populate an event structure and add it to the queue
*/
int ossl_event_queue_add(OSSL_EVENT_QUEUE *queue, OSSL_EVENT *event,
uint32_t type, uint32_t priority,
OSSL_TIME when, void *ctx,
void *payload, size_t payload_size);
/*
* Utility functions to extract event fields
*/
static ossl_unused ossl_inline
uint32_t ossl_event_get_type(const OSSL_EVENT *event)
{
return event->type;
}
static ossl_unused ossl_inline
uint32_t ossl_event_get_priority(const OSSL_EVENT *event)
{
return event->priority;
}
static ossl_unused ossl_inline
OSSL_TIME ossl_event_get_when(const OSSL_EVENT *event)
{
return event->when;
}
static ossl_unused ossl_inline
void *ossl_event_get0_ctx(const OSSL_EVENT *event)
{
return event->ctx;
}
static ossl_unused ossl_inline
void *ossl_event_get0_payload(const OSSL_EVENT *event, size_t *length)
{
if (length != NULL)
*length = event->payload_size;
return event->payload;
}
/*
* Create and free a queue.
*/
OSSL_EVENT_QUEUE *ossl_event_queue_new(void);
void ossl_event_queue_free(OSSL_EVENT_QUEUE *queue);
/*
* Schedule a new event into an event queue.
*
* The event parameters are taken from the function arguments.
*
* The function returns NULL on failure and the added event on success.
*/
OSSL_EVENT *ossl_event_queue_add_new(OSSL_EVENT_QUEUE *queue,
uint32_t type, uint32_t priority,
OSSL_TIME when, void *ctx,
void *payload, size_t payload_size)
;
/*
* Schedule an event into an event queue.
*
* The event parameters are taken from the function arguments.
*
* The function returns 0 on failure and 1 on success.
*/
int ossl_event_queue_add(OSSL_EVENT_QUEUE *queue, OSSL_EVENT *event,
uint32_t type, uint32_t priority,
OSSL_TIME when, void *ctx,
void *payload, size_t payload_size);
/*
* Delete an event from the queue.
* This will cause the early deletion function to be called if it is non-NULL.
* A pointer to the event structure is returned.
*/
int ossl_event_queue_remove(OSSL_EVENT_QUEUE *queue, OSSL_EVENT *event);
/*
* Free a dynamic event.
* Is a NOP for a static event.
*/
void ossl_event_free(OSSL_EVENT *event);
/*
* Return the time until the next event for the specified event, if the event's
* time is past, zero is returned. Once activated, the event reference becomes
* invalid and this function becomes undefined.
*/
OSSL_TIME ossl_event_time_until(const OSSL_EVENT *event);
/*
* Return the time until the next event in the queue.
* If the next event is in the past, zero is returned.
*/
OSSL_TIME ossl_event_queue_time_until_next(const OSSL_EVENT_QUEUE *queue);
/*
* Postpone an event to trigger at the specified time.
* If the event has triggered, this function's behaviour is undefined.
*/
int ossl_event_queue_postpone_until(OSSL_EVENT_QUEUE *queue,
OSSL_EVENT *event,
OSSL_TIME when);
/*
* Return the next event to process.
*/
int ossl_event_queue_get1_next_event(OSSL_EVENT_QUEUE *queue,
OSSL_EVENT **event);
#endif

View File

@ -58,8 +58,11 @@
# define FFC_CHECK_INVALID_Q_VALUE 0x00020
# define FFC_CHECK_INVALID_J_VALUE 0x00040
# define FFC_CHECK_BAD_LN_PAIR 0x00080
# define FFC_CHECK_INVALID_SEED_SIZE 0x00100
/*
* 0x80, 0x100 reserved by include/openssl/dh.h with check bits that are not
* relevant for FFC.
*/
# define FFC_CHECK_MISSING_SEED_OR_COUNTER 0x00200
# define FFC_CHECK_INVALID_G 0x00400
# define FFC_CHECK_INVALID_PQ 0x00800
@ -68,6 +71,8 @@
# define FFC_CHECK_Q_MISMATCH 0x04000
# define FFC_CHECK_G_MISMATCH 0x08000
# define FFC_CHECK_COUNTER_MISMATCH 0x10000
# define FFC_CHECK_BAD_LN_PAIR 0x20000
# define FFC_CHECK_INVALID_SEED_SIZE 0x40000
/* Validation Return codes */
# define FFC_ERROR_PUBKEY_TOO_SMALL 0x01
@ -132,7 +137,7 @@ void ossl_ffc_params_set_h(FFC_PARAMS *params, int index);
void ossl_ffc_params_set_flags(FFC_PARAMS *params, unsigned int flags);
void ossl_ffc_params_enable_flags(FFC_PARAMS *params, unsigned int flags,
int enable);
int ossl_ffc_set_digest(FFC_PARAMS *params, const char *alg, const char *props);
void ossl_ffc_set_digest(FFC_PARAMS *params, const char *alg, const char *props);
int ossl_ffc_params_set_validate_params(FFC_PARAMS *params,
const unsigned char *seed,

View File

@ -0,0 +1,100 @@
/*
* Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_INTERNAL_HPKE_UTIL_H
# define OSSL_INTERNAL_HPKE_UTIL_H
# pragma once
/* Constants from RFC 9180 Section 7.1 and 7.3 */
# define OSSL_HPKE_MAX_SECRET 64
# define OSSL_HPKE_MAX_PUBLIC 133
# define OSSL_HPKE_MAX_PRIVATE 66
# define OSSL_HPKE_MAX_KDF_INPUTLEN 64
/*
* max length of a base-nonce (the Nn field from OSSL_HPKE_AEAD_INFO), this
* is used for a local stack array size
*/
# define OSSL_HPKE_MAX_NONCELEN 12
/*
* @brief info about a KEM
* Used to store constants from Section 7.1 "Table 2 KEM IDs"
* and the bitmask for EC curves described in Section 7.1.3 DeriveKeyPair
*/
typedef struct {
uint16_t kem_id; /* code point for key encipherment method */
const char *keytype; /* string form of algtype "EC"/"X25519"/"X448" */
const char *groupname; /* string form of EC group for NIST curves */
const char *mdname; /* hash alg name for the HKDF */
size_t Nsecret; /* size of secrets */
size_t Nenc; /* length of encapsulated key */
size_t Npk; /* length of public key */
size_t Nsk; /* length of raw private key */
uint8_t bitmask;
} OSSL_HPKE_KEM_INFO;
/*
* @brief info about a KDF
*/
typedef struct {
uint16_t kdf_id; /* code point for KDF */
const char *mdname; /* hash alg name for the HKDF */
size_t Nh; /* length of hash/extract output */
} OSSL_HPKE_KDF_INFO;
/*
* @brief info about an AEAD
*/
typedef struct {
uint16_t aead_id; /* code point for aead alg */
const char *name; /* alg name */
size_t taglen; /* aead tag len */
size_t Nk; /* size of a key for this aead */
size_t Nn; /* length of a nonce for this aead */
} OSSL_HPKE_AEAD_INFO;
const OSSL_HPKE_KEM_INFO *ossl_HPKE_KEM_INFO_find_curve(const char *curve);
const OSSL_HPKE_KEM_INFO *ossl_HPKE_KEM_INFO_find_id(uint16_t kemid);
const OSSL_HPKE_KEM_INFO *ossl_HPKE_KEM_INFO_find_random(OSSL_LIB_CTX *ctx);
const OSSL_HPKE_KDF_INFO *ossl_HPKE_KDF_INFO_find_id(uint16_t kdfid);
const OSSL_HPKE_KDF_INFO *ossl_HPKE_KDF_INFO_find_random(OSSL_LIB_CTX *ctx);
const OSSL_HPKE_AEAD_INFO *ossl_HPKE_AEAD_INFO_find_id(uint16_t aeadid);
const OSSL_HPKE_AEAD_INFO *ossl_HPKE_AEAD_INFO_find_random(OSSL_LIB_CTX *ctx);
int ossl_hpke_kdf_extract(EVP_KDF_CTX *kctx,
unsigned char *prk, size_t prklen,
const unsigned char *salt, size_t saltlen,
const unsigned char *ikm, size_t ikmlen);
int ossl_hpke_kdf_expand(EVP_KDF_CTX *kctx,
unsigned char *okm, size_t okmlen,
const unsigned char *prk, size_t prklen,
const unsigned char *info, size_t infolen);
int ossl_hpke_labeled_extract(EVP_KDF_CTX *kctx,
unsigned char *prk, size_t prklen,
const unsigned char *salt, size_t saltlen,
const char *protocol_label,
const unsigned char *suiteid, size_t suiteidlen,
const char *label,
const unsigned char *ikm, size_t ikmlen);
int ossl_hpke_labeled_expand(EVP_KDF_CTX *kctx,
unsigned char *okm, size_t okmlen,
const unsigned char *prk, size_t prklen,
const char *protocol_label,
const unsigned char *suiteid, size_t suiteidlen,
const char *label,
const unsigned char *info, size_t infolen);
EVP_KDF_CTX *ossl_kdf_ctx_create(const char *kdfname, const char *mdname,
OSSL_LIB_CTX *libctx, const char *propq);
int ossl_hpke_str2suite(const char *suitestr, OSSL_HPKE_SUITE *suite);
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -40,6 +40,11 @@
# define OPENSSL_KTLS_AES_GCM_128
# define OPENSSL_KTLS_AES_GCM_256
# define OPENSSL_KTLS_TLS13
# ifdef TLS_CHACHA20_IV_LEN
# ifndef OPENSSL_NO_CHACHA
# define OPENSSL_KTLS_CHACHA20_POLY1305
# endif
# endif
typedef struct tls_enable ktls_crypto_info_t;
@ -209,6 +214,13 @@ static ossl_inline ossl_ssize_t ktls_sendfile(int s, int fd, off_t off,
# warning "Skipping Compilation of KTLS receive data path"
# endif
# endif
# if LINUX_VERSION_CODE < KERNEL_VERSION(5, 19, 0)
# define OPENSSL_NO_KTLS_ZC_TX
# ifndef PEDANTIC
# warning "KTLS requires Kernel Headers >= 5.19.0 for zerocopy sendfile"
# warning "Skipping Compilation of KTLS zerocopy sendfile"
# endif
# endif
# define OPENSSL_KTLS_AES_GCM_128
# if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0)
# define OPENSSL_KTLS_AES_GCM_256
@ -288,6 +300,18 @@ static ossl_inline int ktls_start(int fd, ktls_crypto_info_t *crypto_info,
crypto_info, crypto_info->tls_crypto_info_len) ? 0 : 1;
}
static ossl_inline int ktls_enable_tx_zerocopy_sendfile(int fd)
{
#ifndef OPENSSL_NO_KTLS_ZC_TX
int enable = 1;
return setsockopt(fd, SOL_TLS, TLS_TX_ZEROCOPY_RO,
&enable, sizeof(enable)) ? 0 : 1;
#else
return 0;
#endif
}
/*
* Send a TLS record using the crypto_info provided in ktls_start and use
* record_type instead of the default SSL3_RT_APPLICATION_DATA.

View File

@ -0,0 +1,169 @@
/*
* Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_INTERNAL_LIST_H
# define OSSL_INTERNAL_LIST_H
# pragma once
# include <string.h>
# include <assert.h>
# ifdef NDEBUG
# define OSSL_LIST_DBG(x)
# else
# define OSSL_LIST_DBG(x) x;
# endif
/* Define a list structure */
# define OSSL_LIST(name) OSSL_LIST_ ## name
/* Define fields to include an element of a list */
# define OSSL_LIST_MEMBER(name, type) \
struct { \
type *next, *prev; \
OSSL_LIST_DBG(struct ossl_list_st_ ## name *list) \
} ossl_list_ ## name
# define DEFINE_LIST_OF(name, type) \
typedef struct ossl_list_st_ ## name OSSL_LIST(name); \
struct ossl_list_st_ ## name { \
type *alpha, *omega; \
size_t num_elems; \
}; \
static ossl_unused ossl_inline void \
ossl_list_##name##_init(OSSL_LIST(name) *list) \
{ \
memset(list, 0, sizeof(*list)); \
} \
static ossl_unused ossl_inline void \
ossl_list_##name##_init_elem(type *elem) \
{ \
memset(&elem->ossl_list_ ## name, 0, \
sizeof(elem->ossl_list_ ## name)); \
} \
static ossl_unused ossl_inline int \
ossl_list_##name##_is_empty(const OSSL_LIST(name) *list) \
{ \
return list->num_elems == 0; \
} \
static ossl_unused ossl_inline size_t \
ossl_list_##name##_num(const OSSL_LIST(name) *list) \
{ \
return list->num_elems; \
} \
static ossl_unused ossl_inline type * \
ossl_list_##name##_head(const OSSL_LIST(name) *list) \
{ \
assert(list->alpha == NULL \
|| list->alpha->ossl_list_ ## name.list == list); \
return list->alpha; \
} \
static ossl_unused ossl_inline type * \
ossl_list_##name##_tail(const OSSL_LIST(name) *list) \
{ \
assert(list->omega == NULL \
|| list->omega->ossl_list_ ## name.list == list); \
return list->omega; \
} \
static ossl_unused ossl_inline type * \
ossl_list_##name##_next(const type *elem) \
{ \
assert(elem->ossl_list_ ## name.next == NULL \
|| elem->ossl_list_ ## name.next \
->ossl_list_ ## name.prev == elem); \
return elem->ossl_list_ ## name.next; \
} \
static ossl_unused ossl_inline type * \
ossl_list_##name##_prev(const type *elem) \
{ \
assert(elem->ossl_list_ ## name.prev == NULL \
|| elem->ossl_list_ ## name.prev \
->ossl_list_ ## name.next == elem); \
return elem->ossl_list_ ## name.prev; \
} \
static ossl_unused ossl_inline void \
ossl_list_##name##_remove(OSSL_LIST(name) *list, type *elem) \
{ \
assert(elem->ossl_list_ ## name.list == list); \
OSSL_LIST_DBG(elem->ossl_list_ ## name.list = NULL) \
if (list->alpha == elem) \
list->alpha = elem->ossl_list_ ## name.next; \
if (list->omega == elem) \
list->omega = elem->ossl_list_ ## name.prev; \
if (elem->ossl_list_ ## name.prev != NULL) \
elem->ossl_list_ ## name.prev->ossl_list_ ## name.next = \
elem->ossl_list_ ## name.next; \
if (elem->ossl_list_ ## name.next != NULL) \
elem->ossl_list_ ## name.next->ossl_list_ ## name.prev = \
elem->ossl_list_ ## name.prev; \
list->num_elems--; \
memset(&elem->ossl_list_ ## name, 0, \
sizeof(elem->ossl_list_ ## name)); \
} \
static ossl_unused ossl_inline void \
ossl_list_##name##_insert_head(OSSL_LIST(name) *list, type *elem) \
{ \
assert(elem->ossl_list_ ## name.list == NULL); \
OSSL_LIST_DBG(elem->ossl_list_ ## name.list = list) \
if (list->alpha != NULL) \
list->alpha->ossl_list_ ## name.prev = elem; \
elem->ossl_list_ ## name.next = list->alpha; \
elem->ossl_list_ ## name.prev = NULL; \
list->alpha = elem; \
if (list->omega == NULL) \
list->omega = elem; \
list->num_elems++; \
} \
static ossl_unused ossl_inline void \
ossl_list_##name##_insert_tail(OSSL_LIST(name) *list, type *elem) \
{ \
assert(elem->ossl_list_ ## name.list == NULL); \
OSSL_LIST_DBG(elem->ossl_list_ ## name.list = list) \
if (list->omega != NULL) \
list->omega->ossl_list_ ## name.next = elem; \
elem->ossl_list_ ## name.prev = list->omega; \
elem->ossl_list_ ## name.next = NULL; \
list->omega = elem; \
if (list->alpha == NULL) \
list->alpha = elem; \
list->num_elems++; \
} \
static ossl_unused ossl_inline void \
ossl_list_##name##_insert_before(OSSL_LIST(name) *list, type *e, \
type *elem) \
{ \
assert(elem->ossl_list_ ## name.list == NULL); \
OSSL_LIST_DBG(elem->ossl_list_ ## name.list = list) \
elem->ossl_list_ ## name.next = e; \
elem->ossl_list_ ## name.prev = e->ossl_list_ ## name.prev; \
if (e->ossl_list_ ## name.prev != NULL) \
e->ossl_list_ ## name.prev->ossl_list_ ## name.next = elem; \
e->ossl_list_ ## name.prev = elem; \
if (list->alpha == e) \
list->alpha = elem; \
list->num_elems++; \
} \
static ossl_unused ossl_inline void \
ossl_list_##name##_insert_after(OSSL_LIST(name) *list, type *e, \
type *elem) \
{ \
assert(elem->ossl_list_ ## name.list == NULL); \
OSSL_LIST_DBG(elem->ossl_list_ ## name.list = list) \
elem->ossl_list_ ## name.prev = e; \
elem->ossl_list_ ## name.next = e->ossl_list_ ## name.next; \
if (e->ossl_list_ ## name.next != NULL) \
e->ossl_list_ ## name.next->ossl_list_ ## name.prev = elem; \
e->ossl_list_ ## name.next = elem; \
if (list->omega == e) \
list->omega = elem; \
list->num_elems++; \
} \
struct ossl_list_st_ ## name
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy

View File

@ -1,5 +1,5 @@
/*
* Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -61,6 +61,31 @@
# define UINT64_MAX __MAXUINT__(uint64_t)
# endif
/*
* 64-bit processor with LP64 ABI
*/
# ifdef SIXTY_FOUR_BIT_LONG
# ifndef UINT32_C
# define UINT32_C(c) (c)
# endif
# ifndef UINT64_C
# define UINT64_C(c) (c##UL)
# endif
# endif
/*
* 64-bit processor other than LP64 ABI
*/
# ifdef SIXTY_FOUR_BIT
# ifndef UINT32_C
# define UINT32_C(c) (c##UL)
# endif
# ifndef UINT64_C
# define UINT64_C(c) (c##ULL)
# endif
# endif
# ifndef INT128_MAX
# if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16
typedef __int128_t int128_t;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -691,6 +691,8 @@ struct wpacket_st {
*/
#define WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH 2
/* QUIC variable-length integer length prefix */
#define WPACKET_FLAGS_QUIC_VLINT 4
/*
* Initialise a WPACKET with the buffer in |buf|. The buffer must exist

View File

@ -0,0 +1,150 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_INTERNAL_PACKET_QUIC_H
# define OSSL_INTERNAL_PACKET_QUIC_H
# pragma once
# include "internal/packet.h"
# include "internal/quic_vlint.h"
# ifndef OPENSSL_NO_QUIC
/*
* Decodes a QUIC variable-length integer in |pkt| and stores the result in
* |data|.
*/
__owur static ossl_inline int PACKET_get_quic_vlint(PACKET *pkt,
uint64_t *data)
{
size_t enclen;
if (PACKET_remaining(pkt) < 1)
return 0;
enclen = ossl_quic_vlint_decode_len(*pkt->curr);
if (PACKET_remaining(pkt) < enclen)
return 0;
*data = ossl_quic_vlint_decode_unchecked(pkt->curr);
packet_forward(pkt, enclen);
return 1;
}
/*
* Decodes a QUIC variable-length integer in |pkt| and stores the result in
* |data|. Unlike PACKET_get_quic_vlint, this does not advance the current
* position. If was_minimal is non-NULL, *was_minimal is set to 1 if the integer
* was encoded using the minimal possible number of bytes and 0 otherwise.
*/
__owur static ossl_inline int PACKET_peek_quic_vlint_ex(PACKET *pkt,
uint64_t *data,
int *was_minimal)
{
size_t enclen;
if (PACKET_remaining(pkt) < 1)
return 0;
enclen = ossl_quic_vlint_decode_len(*pkt->curr);
if (PACKET_remaining(pkt) < enclen)
return 0;
*data = ossl_quic_vlint_decode_unchecked(pkt->curr);
if (was_minimal != NULL)
*was_minimal = (enclen == ossl_quic_vlint_encode_len(*data));
return 1;
}
__owur static ossl_inline int PACKET_peek_quic_vlint(PACKET *pkt,
uint64_t *data)
{
return PACKET_peek_quic_vlint_ex(pkt, data, NULL);
}
/*
* Skips over a QUIC variable-length integer in |pkt| without decoding it.
*/
__owur static ossl_inline int PACKET_skip_quic_vlint(PACKET *pkt)
{
size_t enclen;
if (PACKET_remaining(pkt) < 1)
return 0;
enclen = ossl_quic_vlint_decode_len(*pkt->curr);
if (PACKET_remaining(pkt) < enclen)
return 0;
packet_forward(pkt, enclen);
return 1;
}
/*
* Reads a variable-length vector prefixed with a QUIC variable-length integer
* denoting the length, and stores the contents in |subpkt|. |pkt| can equal
* |subpkt|. Data is not copied: the |subpkt| packet will share its underlying
* buffer with the original |pkt|, so data wrapped by |pkt| must outlive the
* |subpkt|. Upon failure, the original |pkt| and |subpkt| are not modified.
*/
__owur static ossl_inline int PACKET_get_quic_length_prefixed(PACKET *pkt,
PACKET *subpkt)
{
uint64_t length;
const unsigned char *data;
PACKET tmp = *pkt;
if (!PACKET_get_quic_vlint(&tmp, &length) ||
length > SIZE_MAX ||
!PACKET_get_bytes(&tmp, &data, (size_t)length)) {
return 0;
}
*pkt = tmp;
subpkt->curr = data;
subpkt->remaining = (size_t)length;
return 1;
}
/*
* Starts a QUIC sub-packet headed by a QUIC variable-length integer. A 4-byte
* representation is used.
*/
__owur int WPACKET_start_quic_sub_packet(WPACKET *pkt);
/*
* Starts a QUIC sub-packet headed by a QUIC variable-length integer. max_len
* specifies the upper bound for the sub-packet size at the time the sub-packet
* is closed, which determines the encoding size for the variable-length
* integer header. max_len can be a precise figure or a worst-case bound
* if a precise figure is not available.
*/
__owur int WPACKET_start_quic_sub_packet_bound(WPACKET *pkt, size_t max_len);
/*
* Allocates a QUIC sub-packet with exactly len bytes of payload, headed by a
* QUIC variable-length integer. The pointer to the payload buffer is output and
* must be filled by the caller. This function assures optimal selection of
* variable-length integer encoding length.
*/
__owur int WPACKET_quic_sub_allocate_bytes(WPACKET *pkt, size_t len,
unsigned char **bytes);
/*
* Write a QUIC variable-length integer to the packet.
*/
__owur int WPACKET_quic_write_vlint(WPACKET *pkt, uint64_t v);
# endif /* OPENSSL_NO_QUIC */
#endif /* OSSL_INTERNAL_PACKET_QUIC_H */

View File

@ -1,5 +1,5 @@
/*
* Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -39,6 +39,11 @@ int ossl_param_build_set_bn(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
const char *key, const BIGNUM *bn);
int ossl_param_build_set_bn_pad(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
const char *key, const BIGNUM *bn, size_t sz);
int ossl_param_build_set_signed_bn(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
const char *key, const BIGNUM *bn);
int ossl_param_build_set_signed_bn_pad(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
const char *key, const BIGNUM *bn,
size_t sz);
int ossl_param_build_set_multi_key_bn(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
const char *names[],
STACK_OF(BIGNUM_const) *stk);

View File

@ -0,0 +1,376 @@
/*
* WARNING: do not edit!
* Generated by Makefile from include/internal/param_names.h.in
*
* Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
int ossl_param_find_pidx(const char *s);
/* Parameter name definitions - generated by util/perl/OpenSSL/paramnames.pm */
#define NUM_PIDX 290
#define PIDX_ALG_PARAM_CIPHER 0
#define PIDX_ALG_PARAM_DIGEST 1
#define PIDX_ALG_PARAM_ENGINE 2
#define PIDX_ALG_PARAM_MAC 3
#define PIDX_ALG_PARAM_PROPERTIES 4
#define PIDX_ASYM_CIPHER_PARAM_DIGEST PIDX_PKEY_PARAM_DIGEST
#define PIDX_ASYM_CIPHER_PARAM_ENGINE PIDX_PKEY_PARAM_ENGINE
#define PIDX_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION 5
#define PIDX_ASYM_CIPHER_PARAM_MGF1_DIGEST PIDX_PKEY_PARAM_MGF1_DIGEST
#define PIDX_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS PIDX_PKEY_PARAM_MGF1_PROPERTIES
#define PIDX_ASYM_CIPHER_PARAM_OAEP_DIGEST PIDX_ALG_PARAM_DIGEST
#define PIDX_ASYM_CIPHER_PARAM_OAEP_DIGEST_PROPS 6
#define PIDX_ASYM_CIPHER_PARAM_OAEP_LABEL 7
#define PIDX_ASYM_CIPHER_PARAM_PAD_MODE PIDX_PKEY_PARAM_PAD_MODE
#define PIDX_ASYM_CIPHER_PARAM_PROPERTIES PIDX_PKEY_PARAM_PROPERTIES
#define PIDX_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION 8
#define PIDX_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION 9
#define PIDX_CAPABILITY_TLS_GROUP_ALG 10
#define PIDX_CAPABILITY_TLS_GROUP_ID 11
#define PIDX_CAPABILITY_TLS_GROUP_IS_KEM 12
#define PIDX_CAPABILITY_TLS_GROUP_MAX_DTLS 13
#define PIDX_CAPABILITY_TLS_GROUP_MAX_TLS 14
#define PIDX_CAPABILITY_TLS_GROUP_MIN_DTLS 15
#define PIDX_CAPABILITY_TLS_GROUP_MIN_TLS 16
#define PIDX_CAPABILITY_TLS_GROUP_NAME 17
#define PIDX_CAPABILITY_TLS_GROUP_NAME_INTERNAL 18
#define PIDX_CAPABILITY_TLS_GROUP_SECURITY_BITS 19
#define PIDX_CAPABILITY_TLS_SIGALG_CODE_POINT 20
#define PIDX_CAPABILITY_TLS_SIGALG_HASH_NAME 21
#define PIDX_CAPABILITY_TLS_SIGALG_HASH_OID 22
#define PIDX_CAPABILITY_TLS_SIGALG_IANA_NAME 23
#define PIDX_CAPABILITY_TLS_SIGALG_KEYTYPE 24
#define PIDX_CAPABILITY_TLS_SIGALG_KEYTYPE_OID 25
#define PIDX_CAPABILITY_TLS_SIGALG_MAX_TLS 14
#define PIDX_CAPABILITY_TLS_SIGALG_MIN_TLS 16
#define PIDX_CAPABILITY_TLS_SIGALG_NAME 26
#define PIDX_CAPABILITY_TLS_SIGALG_OID 27
#define PIDX_CAPABILITY_TLS_SIGALG_SECURITY_BITS 28
#define PIDX_CAPABILITY_TLS_SIGALG_SIG_NAME 29
#define PIDX_CAPABILITY_TLS_SIGALG_SIG_OID 30
#define PIDX_CIPHER_PARAM_AEAD 31
#define PIDX_CIPHER_PARAM_AEAD_IVLEN PIDX_CIPHER_PARAM_IVLEN
#define PIDX_CIPHER_PARAM_AEAD_MAC_KEY 32
#define PIDX_CIPHER_PARAM_AEAD_TAG 33
#define PIDX_CIPHER_PARAM_AEAD_TAGLEN 34
#define PIDX_CIPHER_PARAM_AEAD_TLS1_AAD 35
#define PIDX_CIPHER_PARAM_AEAD_TLS1_AAD_PAD 36
#define PIDX_CIPHER_PARAM_AEAD_TLS1_GET_IV_GEN 37
#define PIDX_CIPHER_PARAM_AEAD_TLS1_IV_FIXED 38
#define PIDX_CIPHER_PARAM_AEAD_TLS1_SET_IV_INV 39
#define PIDX_CIPHER_PARAM_ALGORITHM_ID_PARAMS 40
#define PIDX_CIPHER_PARAM_BLOCK_SIZE 41
#define PIDX_CIPHER_PARAM_CTS 42
#define PIDX_CIPHER_PARAM_CTS_MODE 43
#define PIDX_CIPHER_PARAM_CUSTOM_IV 44
#define PIDX_CIPHER_PARAM_HAS_RAND_KEY 45
#define PIDX_CIPHER_PARAM_IV 46
#define PIDX_CIPHER_PARAM_IVLEN 47
#define PIDX_CIPHER_PARAM_KEYLEN 48
#define PIDX_CIPHER_PARAM_MODE 49
#define PIDX_CIPHER_PARAM_NUM 50
#define PIDX_CIPHER_PARAM_PADDING 51
#define PIDX_CIPHER_PARAM_RANDOM_KEY 52
#define PIDX_CIPHER_PARAM_RC2_KEYBITS 53
#define PIDX_CIPHER_PARAM_ROUNDS 54
#define PIDX_CIPHER_PARAM_SPEED 55
#define PIDX_CIPHER_PARAM_TLS1_MULTIBLOCK 56
#define PIDX_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD 57
#define PIDX_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD_PACKLEN 58
#define PIDX_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC 59
#define PIDX_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_IN 60
#define PIDX_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_LEN 61
#define PIDX_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE 62
#define PIDX_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_BUFSIZE 63
#define PIDX_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_SEND_FRAGMENT 64
#define PIDX_CIPHER_PARAM_TLS_MAC 65
#define PIDX_CIPHER_PARAM_TLS_MAC_SIZE 66
#define PIDX_CIPHER_PARAM_TLS_VERSION 67
#define PIDX_CIPHER_PARAM_UPDATED_IV 68
#define PIDX_CIPHER_PARAM_USE_BITS 69
#define PIDX_CIPHER_PARAM_XTS_STANDARD 70
#define PIDX_DECODER_PARAM_PROPERTIES PIDX_ALG_PARAM_PROPERTIES
#define PIDX_DIGEST_PARAM_ALGID_ABSENT 71
#define PIDX_DIGEST_PARAM_BLOCK_SIZE 41
#define PIDX_DIGEST_PARAM_MICALG 72
#define PIDX_DIGEST_PARAM_PAD_TYPE 73
#define PIDX_DIGEST_PARAM_SIZE 74
#define PIDX_DIGEST_PARAM_SSL3_MS 75
#define PIDX_DIGEST_PARAM_XOF 76
#define PIDX_DIGEST_PARAM_XOFLEN 77
#define PIDX_DRBG_PARAM_CIPHER PIDX_ALG_PARAM_CIPHER
#define PIDX_DRBG_PARAM_DIGEST PIDX_ALG_PARAM_DIGEST
#define PIDX_DRBG_PARAM_ENTROPY_REQUIRED 78
#define PIDX_DRBG_PARAM_MAC PIDX_ALG_PARAM_MAC
#define PIDX_DRBG_PARAM_MAX_ADINLEN 79
#define PIDX_DRBG_PARAM_MAX_ENTROPYLEN 80
#define PIDX_DRBG_PARAM_MAX_LENGTH 81
#define PIDX_DRBG_PARAM_MAX_NONCELEN 82
#define PIDX_DRBG_PARAM_MAX_PERSLEN 83
#define PIDX_DRBG_PARAM_MIN_ENTROPYLEN 84
#define PIDX_DRBG_PARAM_MIN_LENGTH 85
#define PIDX_DRBG_PARAM_MIN_NONCELEN 86
#define PIDX_DRBG_PARAM_PREDICTION_RESISTANCE 87
#define PIDX_DRBG_PARAM_PROPERTIES PIDX_ALG_PARAM_PROPERTIES
#define PIDX_DRBG_PARAM_RANDOM_DATA 88
#define PIDX_DRBG_PARAM_RESEED_COUNTER 89
#define PIDX_DRBG_PARAM_RESEED_REQUESTS 90
#define PIDX_DRBG_PARAM_RESEED_TIME 91
#define PIDX_DRBG_PARAM_RESEED_TIME_INTERVAL 92
#define PIDX_DRBG_PARAM_SIZE 74
#define PIDX_DRBG_PARAM_USE_DF 93
#define PIDX_ENCODER_PARAM_CIPHER PIDX_ALG_PARAM_CIPHER
#define PIDX_ENCODER_PARAM_ENCRYPT_LEVEL 94
#define PIDX_ENCODER_PARAM_PROPERTIES PIDX_ALG_PARAM_PROPERTIES
#define PIDX_ENCODER_PARAM_SAVE_PARAMETERS 95
#define PIDX_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE 96
#define PIDX_EXCHANGE_PARAM_KDF_DIGEST 97
#define PIDX_EXCHANGE_PARAM_KDF_DIGEST_PROPS 98
#define PIDX_EXCHANGE_PARAM_KDF_OUTLEN 99
#define PIDX_EXCHANGE_PARAM_KDF_TYPE 100
#define PIDX_EXCHANGE_PARAM_KDF_UKM 101
#define PIDX_EXCHANGE_PARAM_PAD 102
#define PIDX_GEN_PARAM_ITERATION 103
#define PIDX_GEN_PARAM_POTENTIAL 104
#define PIDX_KDF_PARAM_ARGON2_AD 105
#define PIDX_KDF_PARAM_ARGON2_LANES 106
#define PIDX_KDF_PARAM_ARGON2_MEMCOST 107
#define PIDX_KDF_PARAM_ARGON2_VERSION 108
#define PIDX_KDF_PARAM_CEK_ALG 109
#define PIDX_KDF_PARAM_CIPHER PIDX_ALG_PARAM_CIPHER
#define PIDX_KDF_PARAM_CONSTANT 110
#define PIDX_KDF_PARAM_DATA 111
#define PIDX_KDF_PARAM_DIGEST PIDX_ALG_PARAM_DIGEST
#define PIDX_KDF_PARAM_EARLY_CLEAN 112
#define PIDX_KDF_PARAM_HMACDRBG_ENTROPY 113
#define PIDX_KDF_PARAM_HMACDRBG_NONCE 114
#define PIDX_KDF_PARAM_INFO 115
#define PIDX_KDF_PARAM_ITER 116
#define PIDX_KDF_PARAM_KBKDF_R 117
#define PIDX_KDF_PARAM_KBKDF_USE_L 118
#define PIDX_KDF_PARAM_KBKDF_USE_SEPARATOR 119
#define PIDX_KDF_PARAM_KEY 120
#define PIDX_KDF_PARAM_LABEL 121
#define PIDX_KDF_PARAM_MAC PIDX_ALG_PARAM_MAC
#define PIDX_KDF_PARAM_MAC_SIZE 122
#define PIDX_KDF_PARAM_MODE 49
#define PIDX_KDF_PARAM_PASSWORD 123
#define PIDX_KDF_PARAM_PKCS12_ID 124
#define PIDX_KDF_PARAM_PKCS5 125
#define PIDX_KDF_PARAM_PREFIX 126
#define PIDX_KDF_PARAM_PROPERTIES PIDX_ALG_PARAM_PROPERTIES
#define PIDX_KDF_PARAM_SALT 127
#define PIDX_KDF_PARAM_SCRYPT_MAXMEM 128
#define PIDX_KDF_PARAM_SCRYPT_N 129
#define PIDX_KDF_PARAM_SCRYPT_P 130
#define PIDX_KDF_PARAM_SCRYPT_R 117
#define PIDX_KDF_PARAM_SECRET 131
#define PIDX_KDF_PARAM_SEED 132
#define PIDX_KDF_PARAM_SIZE 74
#define PIDX_KDF_PARAM_SSHKDF_SESSION_ID 133
#define PIDX_KDF_PARAM_SSHKDF_TYPE 134
#define PIDX_KDF_PARAM_SSHKDF_XCGHASH 135
#define PIDX_KDF_PARAM_THREADS 136
#define PIDX_KDF_PARAM_UKM 137
#define PIDX_KDF_PARAM_X942_ACVPINFO 138
#define PIDX_KDF_PARAM_X942_PARTYUINFO 139
#define PIDX_KDF_PARAM_X942_PARTYVINFO 140
#define PIDX_KDF_PARAM_X942_SUPP_PRIVINFO 141
#define PIDX_KDF_PARAM_X942_SUPP_PUBINFO 142
#define PIDX_KDF_PARAM_X942_USE_KEYBITS 143
#define PIDX_KEM_PARAM_IKME 144
#define PIDX_KEM_PARAM_OPERATION 145
#define PIDX_LIBSSL_RECORD_LAYER_PARAM_BLOCK_PADDING 146
#define PIDX_LIBSSL_RECORD_LAYER_PARAM_MAX_EARLY_DATA 147
#define PIDX_LIBSSL_RECORD_LAYER_PARAM_MAX_FRAG_LEN 148
#define PIDX_LIBSSL_RECORD_LAYER_PARAM_MODE 49
#define PIDX_LIBSSL_RECORD_LAYER_PARAM_OPTIONS 149
#define PIDX_LIBSSL_RECORD_LAYER_PARAM_READ_AHEAD 150
#define PIDX_LIBSSL_RECORD_LAYER_PARAM_STREAM_MAC 151
#define PIDX_LIBSSL_RECORD_LAYER_PARAM_TLSTREE 152
#define PIDX_LIBSSL_RECORD_LAYER_PARAM_USE_ETM 153
#define PIDX_LIBSSL_RECORD_LAYER_READ_BUFFER_LEN 154
#define PIDX_MAC_PARAM_BLOCK_SIZE 155
#define PIDX_MAC_PARAM_CIPHER PIDX_ALG_PARAM_CIPHER
#define PIDX_MAC_PARAM_CUSTOM 156
#define PIDX_MAC_PARAM_C_ROUNDS 157
#define PIDX_MAC_PARAM_DIGEST PIDX_ALG_PARAM_DIGEST
#define PIDX_MAC_PARAM_DIGEST_NOINIT 158
#define PIDX_MAC_PARAM_DIGEST_ONESHOT 159
#define PIDX_MAC_PARAM_D_ROUNDS 160
#define PIDX_MAC_PARAM_IV 46
#define PIDX_MAC_PARAM_KEY 120
#define PIDX_MAC_PARAM_PROPERTIES PIDX_ALG_PARAM_PROPERTIES
#define PIDX_MAC_PARAM_SALT 127
#define PIDX_MAC_PARAM_SIZE 74
#define PIDX_MAC_PARAM_TLS_DATA_SIZE 161
#define PIDX_MAC_PARAM_XOF 76
#define PIDX_OBJECT_PARAM_DATA 111
#define PIDX_OBJECT_PARAM_DATA_STRUCTURE 162
#define PIDX_OBJECT_PARAM_DATA_TYPE 163
#define PIDX_OBJECT_PARAM_DESC 164
#define PIDX_OBJECT_PARAM_REFERENCE 165
#define PIDX_OBJECT_PARAM_TYPE 134
#define PIDX_PASSPHRASE_PARAM_INFO 115
#define PIDX_PKEY_PARAM_BITS 166
#define PIDX_PKEY_PARAM_CIPHER PIDX_ALG_PARAM_CIPHER
#define PIDX_PKEY_PARAM_DEFAULT_DIGEST 167
#define PIDX_PKEY_PARAM_DHKEM_IKM 168
#define PIDX_PKEY_PARAM_DH_GENERATOR 169
#define PIDX_PKEY_PARAM_DH_PRIV_LEN 170
#define PIDX_PKEY_PARAM_DIGEST PIDX_ALG_PARAM_DIGEST
#define PIDX_PKEY_PARAM_DIGEST_SIZE 171
#define PIDX_PKEY_PARAM_DIST_ID 172
#define PIDX_PKEY_PARAM_EC_A 173
#define PIDX_PKEY_PARAM_EC_B 174
#define PIDX_PKEY_PARAM_EC_CHAR2_M 175
#define PIDX_PKEY_PARAM_EC_CHAR2_PP_K1 176
#define PIDX_PKEY_PARAM_EC_CHAR2_PP_K2 177
#define PIDX_PKEY_PARAM_EC_CHAR2_PP_K3 178
#define PIDX_PKEY_PARAM_EC_CHAR2_TP_BASIS 179
#define PIDX_PKEY_PARAM_EC_CHAR2_TYPE 180
#define PIDX_PKEY_PARAM_EC_COFACTOR 181
#define PIDX_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS 182
#define PIDX_PKEY_PARAM_EC_ENCODING 183
#define PIDX_PKEY_PARAM_EC_FIELD_TYPE 184
#define PIDX_PKEY_PARAM_EC_GENERATOR 185
#define PIDX_PKEY_PARAM_EC_GROUP_CHECK_TYPE 186
#define PIDX_PKEY_PARAM_EC_INCLUDE_PUBLIC 187
#define PIDX_PKEY_PARAM_EC_ORDER 188
#define PIDX_PKEY_PARAM_EC_P 130
#define PIDX_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT 189
#define PIDX_PKEY_PARAM_EC_PUB_X 190
#define PIDX_PKEY_PARAM_EC_PUB_Y 191
#define PIDX_PKEY_PARAM_EC_SEED 132
#define PIDX_PKEY_PARAM_ENCODED_PUBLIC_KEY 192
#define PIDX_PKEY_PARAM_ENGINE PIDX_ALG_PARAM_ENGINE
#define PIDX_PKEY_PARAM_FFC_COFACTOR 193
#define PIDX_PKEY_PARAM_FFC_DIGEST PIDX_PKEY_PARAM_DIGEST
#define PIDX_PKEY_PARAM_FFC_DIGEST_PROPS PIDX_PKEY_PARAM_PROPERTIES
#define PIDX_PKEY_PARAM_FFC_G 194
#define PIDX_PKEY_PARAM_FFC_GINDEX 195
#define PIDX_PKEY_PARAM_FFC_H 196
#define PIDX_PKEY_PARAM_FFC_P 130
#define PIDX_PKEY_PARAM_FFC_PBITS 197
#define PIDX_PKEY_PARAM_FFC_PCOUNTER 198
#define PIDX_PKEY_PARAM_FFC_Q 199
#define PIDX_PKEY_PARAM_FFC_QBITS 200
#define PIDX_PKEY_PARAM_FFC_SEED 132
#define PIDX_PKEY_PARAM_FFC_TYPE 134
#define PIDX_PKEY_PARAM_FFC_VALIDATE_G 201
#define PIDX_PKEY_PARAM_FFC_VALIDATE_LEGACY 202
#define PIDX_PKEY_PARAM_FFC_VALIDATE_PQ 203
#define PIDX_PKEY_PARAM_GROUP_NAME 204
#define PIDX_PKEY_PARAM_IMPLICIT_REJECTION 5
#define PIDX_PKEY_PARAM_MANDATORY_DIGEST 205
#define PIDX_PKEY_PARAM_MASKGENFUNC 206
#define PIDX_PKEY_PARAM_MAX_SIZE 207
#define PIDX_PKEY_PARAM_MGF1_DIGEST 208
#define PIDX_PKEY_PARAM_MGF1_PROPERTIES 209
#define PIDX_PKEY_PARAM_PAD_MODE 210
#define PIDX_PKEY_PARAM_PRIV_KEY 211
#define PIDX_PKEY_PARAM_PROPERTIES PIDX_ALG_PARAM_PROPERTIES
#define PIDX_PKEY_PARAM_PUB_KEY 212
#define PIDX_PKEY_PARAM_RSA_BITS PIDX_PKEY_PARAM_BITS
#define PIDX_PKEY_PARAM_RSA_COEFFICIENT 213
#define PIDX_PKEY_PARAM_RSA_COEFFICIENT1 214
#define PIDX_PKEY_PARAM_RSA_COEFFICIENT2 215
#define PIDX_PKEY_PARAM_RSA_COEFFICIENT3 216
#define PIDX_PKEY_PARAM_RSA_COEFFICIENT4 217
#define PIDX_PKEY_PARAM_RSA_COEFFICIENT5 218
#define PIDX_PKEY_PARAM_RSA_COEFFICIENT6 219
#define PIDX_PKEY_PARAM_RSA_COEFFICIENT7 220
#define PIDX_PKEY_PARAM_RSA_COEFFICIENT8 221
#define PIDX_PKEY_PARAM_RSA_COEFFICIENT9 222
#define PIDX_PKEY_PARAM_RSA_D 223
#define PIDX_PKEY_PARAM_RSA_DIGEST PIDX_PKEY_PARAM_DIGEST
#define PIDX_PKEY_PARAM_RSA_DIGEST_PROPS PIDX_PKEY_PARAM_PROPERTIES
#define PIDX_PKEY_PARAM_RSA_E 224
#define PIDX_PKEY_PARAM_RSA_EXPONENT 225
#define PIDX_PKEY_PARAM_RSA_EXPONENT1 226
#define PIDX_PKEY_PARAM_RSA_EXPONENT10 227
#define PIDX_PKEY_PARAM_RSA_EXPONENT2 228
#define PIDX_PKEY_PARAM_RSA_EXPONENT3 229
#define PIDX_PKEY_PARAM_RSA_EXPONENT4 230
#define PIDX_PKEY_PARAM_RSA_EXPONENT5 231
#define PIDX_PKEY_PARAM_RSA_EXPONENT6 232
#define PIDX_PKEY_PARAM_RSA_EXPONENT7 233
#define PIDX_PKEY_PARAM_RSA_EXPONENT8 234
#define PIDX_PKEY_PARAM_RSA_EXPONENT9 235
#define PIDX_PKEY_PARAM_RSA_FACTOR 236
#define PIDX_PKEY_PARAM_RSA_FACTOR1 237
#define PIDX_PKEY_PARAM_RSA_FACTOR10 238
#define PIDX_PKEY_PARAM_RSA_FACTOR2 239
#define PIDX_PKEY_PARAM_RSA_FACTOR3 240
#define PIDX_PKEY_PARAM_RSA_FACTOR4 241
#define PIDX_PKEY_PARAM_RSA_FACTOR5 242
#define PIDX_PKEY_PARAM_RSA_FACTOR6 243
#define PIDX_PKEY_PARAM_RSA_FACTOR7 244
#define PIDX_PKEY_PARAM_RSA_FACTOR8 245
#define PIDX_PKEY_PARAM_RSA_FACTOR9 246
#define PIDX_PKEY_PARAM_RSA_MASKGENFUNC PIDX_PKEY_PARAM_MASKGENFUNC
#define PIDX_PKEY_PARAM_RSA_MGF1_DIGEST PIDX_PKEY_PARAM_MGF1_DIGEST
#define PIDX_PKEY_PARAM_RSA_N 129
#define PIDX_PKEY_PARAM_RSA_PRIMES 247
#define PIDX_PKEY_PARAM_RSA_PSS_SALTLEN 248
#define PIDX_PKEY_PARAM_RSA_TEST_P1 249
#define PIDX_PKEY_PARAM_RSA_TEST_P2 250
#define PIDX_PKEY_PARAM_RSA_TEST_Q1 251
#define PIDX_PKEY_PARAM_RSA_TEST_Q2 252
#define PIDX_PKEY_PARAM_RSA_TEST_XP 253
#define PIDX_PKEY_PARAM_RSA_TEST_XP1 254
#define PIDX_PKEY_PARAM_RSA_TEST_XP2 255
#define PIDX_PKEY_PARAM_RSA_TEST_XQ 256
#define PIDX_PKEY_PARAM_RSA_TEST_XQ1 257
#define PIDX_PKEY_PARAM_RSA_TEST_XQ2 258
#define PIDX_PKEY_PARAM_SECURITY_BITS 259
#define PIDX_PKEY_PARAM_USE_COFACTOR_ECDH PIDX_PKEY_PARAM_USE_COFACTOR_FLAG
#define PIDX_PKEY_PARAM_USE_COFACTOR_FLAG 260
#define PIDX_PROV_PARAM_BUILDINFO 261
#define PIDX_PROV_PARAM_CORE_MODULE_FILENAME 262
#define PIDX_PROV_PARAM_CORE_PROV_NAME 263
#define PIDX_PROV_PARAM_CORE_VERSION 264
#define PIDX_PROV_PARAM_DRBG_TRUNC_DIGEST 265
#define PIDX_PROV_PARAM_NAME 266
#define PIDX_PROV_PARAM_SECURITY_CHECKS 267
#define PIDX_PROV_PARAM_SELF_TEST_DESC 268
#define PIDX_PROV_PARAM_SELF_TEST_PHASE 269
#define PIDX_PROV_PARAM_SELF_TEST_TYPE 270
#define PIDX_PROV_PARAM_STATUS 271
#define PIDX_PROV_PARAM_TLS1_PRF_EMS_CHECK 272
#define PIDX_PROV_PARAM_VERSION 108
#define PIDX_RAND_PARAM_GENERATE 273
#define PIDX_RAND_PARAM_MAX_REQUEST 274
#define PIDX_RAND_PARAM_STATE 275
#define PIDX_RAND_PARAM_STRENGTH 276
#define PIDX_RAND_PARAM_TEST_ENTROPY 277
#define PIDX_RAND_PARAM_TEST_NONCE 278
#define PIDX_SIGNATURE_PARAM_ALGORITHM_ID 279
#define PIDX_SIGNATURE_PARAM_CONTEXT_STRING 280
#define PIDX_SIGNATURE_PARAM_DIGEST PIDX_PKEY_PARAM_DIGEST
#define PIDX_SIGNATURE_PARAM_DIGEST_SIZE PIDX_PKEY_PARAM_DIGEST_SIZE
#define PIDX_SIGNATURE_PARAM_INSTANCE 281
#define PIDX_SIGNATURE_PARAM_KAT 282
#define PIDX_SIGNATURE_PARAM_MGF1_DIGEST PIDX_PKEY_PARAM_MGF1_DIGEST
#define PIDX_SIGNATURE_PARAM_MGF1_PROPERTIES PIDX_PKEY_PARAM_MGF1_PROPERTIES
#define PIDX_SIGNATURE_PARAM_NONCE_TYPE 283
#define PIDX_SIGNATURE_PARAM_PAD_MODE PIDX_PKEY_PARAM_PAD_MODE
#define PIDX_SIGNATURE_PARAM_PROPERTIES PIDX_PKEY_PARAM_PROPERTIES
#define PIDX_SIGNATURE_PARAM_PSS_SALTLEN 248
#define PIDX_STORE_PARAM_ALIAS 284
#define PIDX_STORE_PARAM_DIGEST 1
#define PIDX_STORE_PARAM_EXPECT 285
#define PIDX_STORE_PARAM_FINGERPRINT 286
#define PIDX_STORE_PARAM_INPUT_TYPE 287
#define PIDX_STORE_PARAM_ISSUER 266
#define PIDX_STORE_PARAM_PROPERTIES 4
#define PIDX_STORE_PARAM_SERIAL 288
#define PIDX_STORE_PARAM_SUBJECT 289

View File

@ -0,0 +1,18 @@
/*
* {- join("\n * ", @autowarntext) -}
*
* Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
{-
use OpenSSL::paramnames qw(generate_internal_macros);
-}
int ossl_param_find_pidx(const char *s);
/* Parameter name definitions - generated by util/perl/OpenSSL/paramnames.pm */
{- generate_internal_macros(); -}

View File

@ -0,0 +1,38 @@
/*
* Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stddef.h>
#include <openssl/params.h>
/*
* Extract the parameter into an allocated buffer.
* Any existing allocation in *out is cleared and freed.
*
* Returns 1 on success, 0 on failure and -1 if there are no matching params.
*
* *out and *out_len are guaranteed to be untouched if this function
* doesn't return success.
*/
int ossl_param_get1_octet_string(const OSSL_PARAM *params, const char *name,
unsigned char **out, size_t *out_len);
/*
* Concatenate all of the matching params together.
* *out will point to an allocated buffer on successful return.
* Any existing allocation in *out is cleared and freed.
*
* Passing 0 for maxsize means unlimited size output.
*
* Returns 1 on success, 0 on failure and -1 if there are no matching params.
*
* *out and *out_len are guaranteed to be untouched if this function
* doesn't return success.
*/
int ossl_param_get1_concat_octet_string(const OSSL_PARAM *params, const char *name,
unsigned char **out, size_t *out_len,
size_t maxsize);

View File

@ -0,0 +1,88 @@
/*
* Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_INTERNAL_PRIORITY_QUEUE_H
# define OSSL_INTERNAL_PRIORITY_QUEUE_H
# pragma once
# include <stdlib.h>
# include <openssl/e_os2.h>
# define PRIORITY_QUEUE_OF(type) OSSL_PRIORITY_QUEUE_ ## type
# define DEFINE_PRIORITY_QUEUE_OF_INTERNAL(type, ctype) \
typedef struct ossl_priority_queue_st_ ## type PRIORITY_QUEUE_OF(type); \
static ossl_unused ossl_inline PRIORITY_QUEUE_OF(type) * \
ossl_pqueue_##type##_new(int (*compare)(const ctype *, const ctype *)) \
{ \
return (PRIORITY_QUEUE_OF(type) *)ossl_pqueue_new( \
(int (*)(const void *, const void *))compare); \
} \
static ossl_unused ossl_inline void \
ossl_pqueue_##type##_free(PRIORITY_QUEUE_OF(type) *pq) \
{ \
ossl_pqueue_free((OSSL_PQUEUE *)pq); \
} \
static ossl_unused ossl_inline void \
ossl_pqueue_##type##_pop_free(PRIORITY_QUEUE_OF(type) *pq, \
void (*freefunc)(ctype *)) \
{ \
ossl_pqueue_pop_free((OSSL_PQUEUE *)pq, (void (*)(void *))freefunc);\
} \
static ossl_unused ossl_inline int \
ossl_pqueue_##type##_reserve(PRIORITY_QUEUE_OF(type) *pq, size_t n) \
{ \
return ossl_pqueue_reserve((OSSL_PQUEUE *)pq, n); \
} \
static ossl_unused ossl_inline size_t \
ossl_pqueue_##type##_num(const PRIORITY_QUEUE_OF(type) *pq) \
{ \
return ossl_pqueue_num((OSSL_PQUEUE *)pq); \
} \
static ossl_unused ossl_inline int \
ossl_pqueue_##type##_push(PRIORITY_QUEUE_OF(type) *pq, \
ctype *data, size_t *elem) \
{ \
return ossl_pqueue_push((OSSL_PQUEUE *)pq, (void *)data, elem); \
} \
static ossl_unused ossl_inline ctype * \
ossl_pqueue_##type##_peek(const PRIORITY_QUEUE_OF(type) *pq) \
{ \
return (type *)ossl_pqueue_peek((OSSL_PQUEUE *)pq); \
} \
static ossl_unused ossl_inline ctype * \
ossl_pqueue_##type##_pop(PRIORITY_QUEUE_OF(type) *pq) \
{ \
return (type *)ossl_pqueue_pop((OSSL_PQUEUE *)pq); \
} \
static ossl_unused ossl_inline ctype * \
ossl_pqueue_##type##_remove(PRIORITY_QUEUE_OF(type) *pq, \
size_t elem) \
{ \
return (type *)ossl_pqueue_remove((OSSL_PQUEUE *)pq, elem); \
} \
struct ossl_priority_queue_st_ ## type
# define DEFINE_PRIORITY_QUEUE_OF(type) \
DEFINE_PRIORITY_QUEUE_OF_INTERNAL(type, type)
typedef struct ossl_pqueue_st OSSL_PQUEUE;
OSSL_PQUEUE *ossl_pqueue_new(int (*compare)(const void *, const void *));
void ossl_pqueue_free(OSSL_PQUEUE *pq);
void ossl_pqueue_pop_free(OSSL_PQUEUE *pq, void (*freefunc)(void *));
int ossl_pqueue_reserve(OSSL_PQUEUE *pq, size_t n);
size_t ossl_pqueue_num(const OSSL_PQUEUE *pq);
int ossl_pqueue_push(OSSL_PQUEUE *pq, void *data, size_t *elem);
void *ossl_pqueue_peek(const OSSL_PQUEUE *pq);
void *ossl_pqueue_pop(OSSL_PQUEUE *pq);
void *ossl_pqueue_remove(OSSL_PQUEUE *pq, size_t elem);
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -32,7 +32,7 @@ OSSL_PROVIDER *ossl_provider_find(OSSL_LIB_CTX *libctx, const char *name,
int noconfig);
OSSL_PROVIDER *ossl_provider_new(OSSL_LIB_CTX *libctx, const char *name,
OSSL_provider_init_fn *init_function,
int noconfig);
OSSL_PARAM *params, int noconfig);
int ossl_provider_up_ref(OSSL_PROVIDER *prov);
void ossl_provider_free(OSSL_PROVIDER *prov);

View File

@ -0,0 +1,297 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_QUIC_ACKM_H
# define OSSL_QUIC_ACKM_H
# include "internal/quic_statm.h"
# include "internal/quic_cc.h"
# include "internal/quic_types.h"
# include "internal/quic_wire.h"
# include "internal/time.h"
# include "internal/list.h"
# ifndef OPENSSL_NO_QUIC
typedef struct ossl_ackm_st OSSL_ACKM;
OSSL_ACKM *ossl_ackm_new(OSSL_TIME (*now)(void *arg),
void *now_arg,
OSSL_STATM *statm,
const OSSL_CC_METHOD *cc_method,
OSSL_CC_DATA *cc_data);
void ossl_ackm_free(OSSL_ACKM *ackm);
void ossl_ackm_set_loss_detection_deadline_callback(OSSL_ACKM *ackm,
void (*fn)(OSSL_TIME deadline,
void *arg),
void *arg);
void ossl_ackm_set_ack_deadline_callback(OSSL_ACKM *ackm,
void (*fn)(OSSL_TIME deadline,
int pkt_space,
void *arg),
void *arg);
/*
* Configures the RX-side maximum ACK delay. This is the maximum amount of time
* the peer is allowed to delay sending an ACK frame after receiving an
* ACK-eliciting packet. The peer communicates this value via a transport
* parameter and it must be provided to the ACKM.
*/
void ossl_ackm_set_rx_max_ack_delay(OSSL_ACKM *ackm, OSSL_TIME rx_max_ack_delay);
/*
* Configures the TX-side maximum ACK delay. This is the maximum amount of time
* we are allowed to delay sending an ACK frame after receiving an ACK-eliciting
* packet. Note that this cannot be changed after a connection is established as
* it must be accurately reported in the transport parameters we send to our
* peer.
*/
void ossl_ackm_set_tx_max_ack_delay(OSSL_ACKM *ackm, OSSL_TIME tx_max_ack_delay);
typedef struct ossl_ackm_tx_pkt_st OSSL_ACKM_TX_PKT;
struct ossl_ackm_tx_pkt_st {
/* The packet number of the transmitted packet. */
QUIC_PN pkt_num;
/* The number of bytes in the packet which was sent. */
size_t num_bytes;
/* The time at which the packet was sent. */
OSSL_TIME time;
/*
* If the packet being described by this structure contains an ACK frame,
* this must be set to the largest PN ACK'd by that frame.
*
* Otherwise, it should be set to QUIC_PN_INVALID.
*
* This is necessary to bound the number of PNs we have to keep track of on
* the RX side (RFC 9000 s. 13.2.4). It allows older PN tracking information
* on the RX side to be discarded.
*/
QUIC_PN largest_acked;
/*
* One of the QUIC_PN_SPACE_* values. This qualifies the pkt_num field
* into a packet number space.
*/
unsigned int pkt_space :2;
/*
* 1 if the packet is in flight. A packet is considered 'in flight' if it is
* counted for purposes of congestion control and 'bytes in flight' counts.
* Most packets are considered in flight. The only circumstance where a
* numbered packet is not considered in flight is if it contains only ACK
* frames (not even PADDING frames), as these frames can bypass CC.
*/
unsigned int is_inflight :1;
/*
* 1 if the packet has one or more ACK-eliciting frames.
* Note that if this is set, is_inflight must be set.
*/
unsigned int is_ack_eliciting :1;
/* 1 if the packet is a PTO probe. */
unsigned int is_pto_probe :1;
/* 1 if the packet is an MTU probe. */
unsigned int is_mtu_probe :1;
/* Callback called if frames in this packet are lost. arg is cb_arg. */
void (*on_lost)(void *arg);
/* Callback called if frames in this packet are acked. arg is cb_arg. */
void (*on_acked)(void *arg);
/*
* Callback called if frames in this packet are neither acked nor lost. arg
* is cb_arg.
*/
void (*on_discarded)(void *arg);
void *cb_arg;
/*
* (Internal use fields; must be zero-initialized.)
*
* Keep a TX history list, anext is used to manifest
* a singly-linked list of newly-acknowledged packets, and lnext is used to
* manifest a singly-linked list of newly lost packets.
*/
OSSL_LIST_MEMBER(tx_history, OSSL_ACKM_TX_PKT);
struct ossl_ackm_tx_pkt_st *anext;
struct ossl_ackm_tx_pkt_st *lnext;
};
int ossl_ackm_on_tx_packet(OSSL_ACKM *ackm, OSSL_ACKM_TX_PKT *pkt);
int ossl_ackm_on_rx_datagram(OSSL_ACKM *ackm, size_t num_bytes);
# define OSSL_ACKM_ECN_NONE 0
# define OSSL_ACKM_ECN_ECT1 1
# define OSSL_ACKM_ECN_ECT0 2
# define OSSL_ACKM_ECN_ECNCE 3
typedef struct ossl_ackm_rx_pkt_st {
/* The packet number of the received packet. */
QUIC_PN pkt_num;
/* The time at which the packet was received. */
OSSL_TIME time;
/*
* One of the QUIC_PN_SPACE_* values. This qualifies the pkt_num field
* into a packet number space.
*/
unsigned int pkt_space :2;
/* 1 if the packet has one or more ACK-eliciting frames. */
unsigned int is_ack_eliciting :1;
/*
* One of the OSSL_ACKM_ECN_* values. This is the ECN labelling applied to
* the received packet. If unknown, use OSSL_ACKM_ECN_NONE.
*/
unsigned int ecn :2;
} OSSL_ACKM_RX_PKT;
int ossl_ackm_on_rx_packet(OSSL_ACKM *ackm, const OSSL_ACKM_RX_PKT *pkt);
int ossl_ackm_on_rx_ack_frame(OSSL_ACKM *ackm, const OSSL_QUIC_FRAME_ACK *ack,
int pkt_space, OSSL_TIME rx_time);
/*
* Discards a PN space. This must be called for a PN space before freeing the
* ACKM if you want in-flight packets to have their discarded callbacks called.
* This should never be called in ordinary QUIC usage for the Application Data
* PN space, but it may be called for the Application Data PN space prior to
* freeing the ACKM to simplify teardown implementations.
*/
int ossl_ackm_on_pkt_space_discarded(OSSL_ACKM *ackm, int pkt_space);
int ossl_ackm_on_handshake_confirmed(OSSL_ACKM *ackm);
int ossl_ackm_on_timeout(OSSL_ACKM *ackm);
OSSL_TIME ossl_ackm_get_loss_detection_deadline(OSSL_ACKM *ackm);
/*
* Generates an ACK frame, regardless of whether the ACK manager thinks
* one should currently be sent.
*
* This clears the flag returned by ossl_ackm_is_ack_desired and the deadline
* returned by ossl_ackm_get_ack_deadline.
*/
const OSSL_QUIC_FRAME_ACK *ossl_ackm_get_ack_frame(OSSL_ACKM *ackm,
int pkt_space);
/*
* Returns the deadline after which an ACK frame should be generated by calling
* ossl_ackm_get_ack_frame, or OSSL_TIME_INFINITY if no deadline is currently
* applicable. If the deadline has already passed, this function may return that
* deadline, or may return OSSL_TIME_ZERO.
*/
OSSL_TIME ossl_ackm_get_ack_deadline(OSSL_ACKM *ackm, int pkt_space);
/*
* Returns 1 if the ACK manager thinks an ACK frame ought to be generated and
* sent at this time. ossl_ackm_get_ack_frame will always provide an ACK frame
* whether or not this returns 1, so it is suggested that you call this function
* first to determine whether you need to generate an ACK frame.
*
* The return value of this function can change based on calls to
* ossl_ackm_on_rx_packet and based on the passage of time (see
* ossl_ackm_get_ack_deadline).
*/
int ossl_ackm_is_ack_desired(OSSL_ACKM *ackm, int pkt_space);
/*
* Returns 1 if the given RX PN is 'processable'. A processable PN is one that
* is not either
*
* - duplicate, meaning that we have already been passed such a PN in a call
* to ossl_ackm_on_rx_packet; or
*
* - written off, meaning that the PN is so old we have stopped tracking state
* for it (meaning that we cannot tell whether it is a duplicate and cannot
* process it safely).
*
* This should be called for a packet before attempting to process its contents.
* Failure to do so may result in processing a duplicated packet in violation of
* the RFC.
*
* The return value of this function transitions from 1 to 0 for a given PN once
* that PN is passed to ossl_ackm_on_rx_packet, thus this function must be used
* before calling ossl_ackm_on_rx_packet.
*/
int ossl_ackm_is_rx_pn_processable(OSSL_ACKM *ackm, QUIC_PN pn, int pkt_space);
typedef struct ossl_ackm_probe_info_st {
/*
* The following two probe request types are used only for anti-deadlock
* purposes in relation to the anti-amplification logic, by generating
* packets to buy ourselves more anti-amplification credit with the server
* until a client address is verified. Note that like all Initial packets,
* any Initial probes are padded.
*
* Note: The ACKM will only ever increase these by one at a time,
* as only one probe packet should be generated for these cases.
*/
uint32_t anti_deadlock_initial, anti_deadlock_handshake;
/*
* Send an ACK-eliciting packet for each count here.
*
* Note: The ACKM may increase this by either one or two for each probe
* request, depending on how many probe packets it thinks should be
* generated.
*/
uint32_t pto[QUIC_PN_SPACE_NUM];
} OSSL_ACKM_PROBE_INFO;
/*
* Returns a pointer to a structure counting any pending probe requests which
* have been generated by the ACKM. The fields in the structure are incremented
* by one every time the ACKM wants another probe of the given type to be sent.
* If the ACKM thinks two packets should be generated for a probe, it will
* increment the field twice.
*
* It is permissible for the caller to decrement or zero these fields to keep
* track of when it has generated a probe as asked. The returned structure
* has the same lifetime as the ACKM.
*
* This function should be called after calling e.g. ossl_ackm_on_timeout
* to determine if any probe requests have been generated.
*/
OSSL_ACKM_PROBE_INFO *ossl_ackm_get0_probe_request(OSSL_ACKM *ackm);
int ossl_ackm_get_largest_unacked(OSSL_ACKM *ackm, int pkt_space, QUIC_PN *pn);
/*
* Forces the ACKM to consider a packet with the given PN in the given PN space
* as having been pseudo-lost. The main reason to use this is during a Retry, to
* force any resources sent in the first Initial packet to be resent.
*
* The lost callback is called for the packet, but the packet is NOT considered
* lost for congestion control purposes. Thus this is not exactly the same as a
* true loss situation.
*/
int ossl_ackm_mark_packet_pseudo_lost(OSSL_ACKM *ackm,
int pkt_space, QUIC_PN pn);
/*
* Returns the PTO duration as currently calculated. This is a quantity of time.
* This duration is used in various parts of QUIC besides the ACKM.
*/
OSSL_TIME ossl_ackm_get_pto_duration(OSSL_ACKM *ackm);
/* Returns the largest acked PN in the given PN space. */
QUIC_PN ossl_ackm_get_largest_acked(OSSL_ACKM *ackm, int pkt_space);
# endif
#endif

View File

@ -0,0 +1,219 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_QUIC_CC_H
# define OSSL_QUIC_CC_H
#include "openssl/params.h"
#include "internal/time.h"
# ifndef OPENSSL_NO_QUIC
typedef struct ossl_cc_data_st OSSL_CC_DATA;
typedef struct ossl_cc_ack_info_st {
/* The time the packet being acknowledged was originally sent. */
OSSL_TIME tx_time;
/* The size in bytes of the packet being acknowledged. */
size_t tx_size;
} OSSL_CC_ACK_INFO;
typedef struct ossl_cc_loss_info_st {
/* The time the packet being lost was originally sent. */
OSSL_TIME tx_time;
/* The size in bytes of the packet which has been determined lost. */
size_t tx_size;
} OSSL_CC_LOSS_INFO;
typedef struct ossl_cc_ecn_info_st {
/*
* The time at which the largest acked PN (in the incoming ACK frame) was
* sent.
*/
OSSL_TIME largest_acked_time;
} OSSL_CC_ECN_INFO;
/* Parameter (read-write): Maximum datagram payload length in bytes. */
#define OSSL_CC_OPTION_MAX_DGRAM_PAYLOAD_LEN "max_dgram_payload_len"
/* Diagnostic (read-only): current congestion window size in bytes. */
#define OSSL_CC_OPTION_CUR_CWND_SIZE "cur_cwnd_size"
/* Diagnostic (read-only): minimum congestion window size in bytes. */
#define OSSL_CC_OPTION_MIN_CWND_SIZE "min_cwnd_size"
/* Diagnostic (read-only): current net bytes in flight. */
#define OSSL_CC_OPTION_CUR_BYTES_IN_FLIGHT "bytes_in_flight"
/* Diagnostic (read-only): method-specific state value. */
#define OSSL_CC_OPTION_CUR_STATE "cur_state"
/*
* Congestion control abstract interface.
*
* This interface is broadly based on the design described in RFC 9002. However,
* the demarcation between the ACKM and the congestion controller does not
* exactly match that delineated in the RFC 9002 pseudocode. Where aspects of
* the demarcation involve the congestion controller accessing internal state of
* the ACKM, the interface has been revised where possible to provide the
* information needed by the congestion controller and avoid needing to give the
* congestion controller access to the ACKM's internal data structures.
*
* Particular changes include:
*
* - In our implementation, it is the responsibility of the ACKM to determine
* if a loss event constitutes persistent congestion.
*
* - In our implementation, it is the responsibility of the ACKM to determine
* if the ECN-CE counter has increased. The congestion controller is simply
* informed when an ECN-CE event occurs.
*
* All of these changes are intended to avoid having a congestion controller
* have to access ACKM internal state.
*/
#define OSSL_CC_LOST_FLAG_PERSISTENT_CONGESTION (1U << 0)
typedef struct ossl_cc_method_st {
/*
* Instantiation.
*/
OSSL_CC_DATA *(*new)(OSSL_TIME (*now_cb)(void *arg),
void *now_cb_arg);
void (*free)(OSSL_CC_DATA *ccdata);
/*
* Reset of state.
*/
void (*reset)(OSSL_CC_DATA *ccdata);
/*
* Escape hatch for option configuration.
*
* params is an array of OSSL_PARAM structures.
*
* Returns 1 on success and 0 on failure.
*/
int (*set_input_params)(OSSL_CC_DATA *ccdata,
const OSSL_PARAM *params);
/*
* (Re)bind output (diagnostic) information.
*
* params is an array of OSSL_PARAM structures used to output values. The
* storage locations associated with each parameter are stored internally
* and updated whenever the state of the congestion controller is updated;
* thus, the storage locations associated with the OSSL_PARAMs passed in the
* call to this function must remain valid until the congestion controller
* is freed or those parameters are unbound. A given parameter name may be
* bound to only one location at a time. The params structures themselves
* do not need to remain allocated after this call returns.
*
* Returns 1 on success and 0 on failure.
*/
int (*bind_diagnostics)(OSSL_CC_DATA *ccdata,
OSSL_PARAM *params);
/*
* Unbind diagnostic information. The parameters with the given names are
* unbound, cancelling the effects of a previous call to bind_diagnostic().
* params is an array of OSSL_PARAMs. The values of the parameters are
* ignored. If a parameter is already unbound, there is no effect for that
* parameter but other parameters are still unbound.
*
* Returns 1 on success or 0 on failure.
*/
int (*unbind_diagnostics)(OSSL_CC_DATA *ccdata,
OSSL_PARAM *params);
/*
* Returns the amount of additional data (above and beyond the data
* currently in flight) which can be sent in bytes. Returns 0 if no more
* data can be sent at this time. The return value of this method
* can vary as time passes.
*/
uint64_t (*get_tx_allowance)(OSSL_CC_DATA *ccdata);
/*
* Returns the time at which the return value of get_tx_allowance might be
* higher than its current value. This is not a guarantee and spurious
* wakeups are allowed. Returns ossl_time_infinite() if there is no current
* wakeup deadline.
*/
OSSL_TIME (*get_wakeup_deadline)(OSSL_CC_DATA *ccdata);
/*
* The On Data Sent event. num_bytes should be the size of the packet in
* bytes (or the aggregate size of multiple packets which have just been
* sent).
*/
int (*on_data_sent)(OSSL_CC_DATA *ccdata,
uint64_t num_bytes);
/*
* The On Data Acked event. See OSSL_CC_ACK_INFO structure for details
* of the information to be passed.
*/
int (*on_data_acked)(OSSL_CC_DATA *ccdata,
const OSSL_CC_ACK_INFO *info);
/*
* The On Data Lost event. See OSSL_CC_LOSS_INFO structure for details
* of the information to be passed.
*
* Note: When the ACKM determines that a set of multiple packets has been
* lost, it is useful for a congestion control algorithm to be able to
* process this as a single loss event rather than multiple loss events.
* Thus, calling this function may cause the congestion controller to defer
* state updates under the assumption that subsequent calls to
* on_data_lost() representing further lost packets in the same loss event
* may be forthcoming. Always call on_data_lost_finished() after one or more
* calls to on_data_lost().
*/
int (*on_data_lost)(OSSL_CC_DATA *ccdata,
const OSSL_CC_LOSS_INFO *info);
/*
* To be called after a sequence of one or more on_data_lost() calls
* representing multiple packets in a single loss detection incident.
*
* Flags may be 0 or OSSL_CC_LOST_FLAG_PERSISTENT_CONGESTION.
*/
int (*on_data_lost_finished)(OSSL_CC_DATA *ccdata, uint32_t flags);
/*
* For use when a PN space is invalidated or a packet must otherwise be
* 'undone' for congestion control purposes without acting as a loss signal.
* Only the size of the packet is needed.
*/
int (*on_data_invalidated)(OSSL_CC_DATA *ccdata,
uint64_t num_bytes);
/*
* Called from the ACKM when detecting an increased ECN-CE value in an ACK
* frame. This indicates congestion.
*
* Note that this differs from the RFC's conceptual segregation of the loss
* detection and congestion controller functions, as in our implementation
* the ACKM is responsible for detecting increases to ECN-CE and simply
* tells the congestion controller when ECN-triggered congestion has
* occurred. This allows a slightly more efficient implementation and
* narrower interface between the ACKM and CC.
*/
int (*on_ecn)(OSSL_CC_DATA *ccdata,
const OSSL_CC_ECN_INFO *info);
} OSSL_CC_METHOD;
extern const OSSL_CC_METHOD ossl_cc_dummy_method;
extern const OSSL_CC_METHOD ossl_cc_newreno_method;
# endif
#endif

View File

@ -0,0 +1,154 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_QUIC_CFQ_H
# define OSSL_QUIC_CFQ_H
# include <openssl/ssl.h>
# include "internal/quic_types.h"
# ifndef OPENSSL_NO_QUIC
/*
* QUIC Control Frame Queue Item
* =============================
*
* The CFQ item structure has a public and a private part. This structure
* documents the public part.
*/
typedef struct quic_cfq_item_st QUIC_CFQ_ITEM;
struct quic_cfq_item_st {
/*
* These fields are not used by the CFQ, but are a convenience to assist the
* TXPIM in keeping a list of GCR control frames which were sent in a
* packet. They may be used for any purpose.
*/
QUIC_CFQ_ITEM *pkt_prev, *pkt_next;
/* All other fields are private; use ossl_quic_cfq_item_* accessors. */
};
# define QUIC_CFQ_STATE_NEW 0
# define QUIC_CFQ_STATE_TX 1
/* If set, do not retransmit on loss */
#define QUIC_CFQ_ITEM_FLAG_UNRELIABLE (1U << 0)
/* Returns the frame type of a CFQ item. */
uint64_t ossl_quic_cfq_item_get_frame_type(const QUIC_CFQ_ITEM *item);
/* Returns a pointer to the encoded buffer of a CFQ item. */
const unsigned char *ossl_quic_cfq_item_get_encoded(const QUIC_CFQ_ITEM *item);
/* Returns the length of the encoded buffer in bytes. */
size_t ossl_quic_cfq_item_get_encoded_len(const QUIC_CFQ_ITEM *item);
/* Returns the CFQ item state, a QUIC_CFQ_STATE_* value. */
int ossl_quic_cfq_item_get_state(const QUIC_CFQ_ITEM *item);
/* Returns the PN space for the CFQ item. */
uint32_t ossl_quic_cfq_item_get_pn_space(const QUIC_CFQ_ITEM *item);
/* Returns 1 if this is an unreliable frame. */
int ossl_quic_cfq_item_is_unreliable(const QUIC_CFQ_ITEM *item);
/*
* QUIC Control Frame Queue
* ========================
*/
typedef struct quic_cfq_st QUIC_CFQ;
QUIC_CFQ *ossl_quic_cfq_new(void);
void ossl_quic_cfq_free(QUIC_CFQ *cfq);
/*
* Input Side
* ----------
*/
/*
* Enqueue a frame to the CFQ.
*
* encoded points to the opaque encoded frame.
*
* free_cb is called by the CFQ when the buffer is no longer needed;
* free_cb_arg is an opaque value passed to free_cb.
*
* priority determines the relative ordering of control frames in a packet.
* Lower numerical values for priority mean that a frame should come earlier in
* a packet. pn_space is a QUIC_PN_SPACE_* value.
*
* On success, returns a QUIC_CFQ_ITEM pointer which acts as a handle to
* the queued frame. On failure, returns NULL.
*
* The frame is initially in the TX state, so there is no need to call
* ossl_quic_cfq_mark_tx() immediately after calling this function.
*
* The frame type is duplicated as the frame_type argument here, even though it
* is also encoded into the buffer. This allows the caller to determine the
* frame type if desired without having to decode the frame.
*
* flags is zero or more QUIC_CFQ_ITEM_FLAG values.
*/
typedef void (cfq_free_cb)(unsigned char *buf, size_t buf_len, void *arg);
QUIC_CFQ_ITEM *ossl_quic_cfq_add_frame(QUIC_CFQ *cfq,
uint32_t priority,
uint32_t pn_space,
uint64_t frame_type,
uint32_t flags,
const unsigned char *encoded,
size_t encoded_len,
cfq_free_cb *free_cb,
void *free_cb_arg);
/*
* Effects an immediate transition of the given CFQ item to the TX state.
*/
void ossl_quic_cfq_mark_tx(QUIC_CFQ *cfq, QUIC_CFQ_ITEM *item);
/*
* Effects an immediate transition of the given CFQ item to the NEW state,
* allowing the frame to be retransmitted. If priority is not UINT32_MAX,
* the priority is changed to the given value.
*/
void ossl_quic_cfq_mark_lost(QUIC_CFQ *cfq, QUIC_CFQ_ITEM *item,
uint32_t priority);
/*
* Releases a CFQ item. The item may be in either state (NEW or TX) prior to the
* call. The QUIC_CFQ_ITEM pointer must not be used following this call.
*/
void ossl_quic_cfq_release(QUIC_CFQ *cfq, QUIC_CFQ_ITEM *item);
/*
* Output Side
* -----------
*/
/*
* Gets the highest priority CFQ item in the given PN space awaiting
* transmission. If there are none, returns NULL.
*/
QUIC_CFQ_ITEM *ossl_quic_cfq_get_priority_head(const QUIC_CFQ *cfq,
uint32_t pn_space);
/*
* Given a CFQ item, gets the next CFQ item awaiting transmission in priority
* order in the given PN space. In other words, given the return value of
* ossl_quic_cfq_get_priority_head(), returns the next-lower priority item.
* Returns NULL if the given item is the last item in priority order.
*/
QUIC_CFQ_ITEM *ossl_quic_cfq_item_get_priority_next(const QUIC_CFQ_ITEM *item,
uint32_t pn_space);
# endif
#endif

View File

@ -0,0 +1,429 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_QUIC_CHANNEL_H
# define OSSL_QUIC_CHANNEL_H
# include <openssl/ssl.h>
# include "internal/quic_types.h"
# include "internal/quic_stream_map.h"
# include "internal/quic_reactor.h"
# include "internal/quic_statm.h"
# include "internal/time.h"
# include "internal/thread.h"
# ifndef OPENSSL_NO_QUIC
/*
* QUIC Channel
* ============
*
* A QUIC channel (QUIC_CHANNEL) is an object which binds together all of the
* various pieces of QUIC into a single top-level object, and handles connection
* state which is not specific to the client or server roles. In particular, it
* is strictly separated from the libssl front end I/O API personality layer,
* and is not an SSL object.
*
* The name QUIC_CHANNEL is chosen because QUIC_CONNECTION is already in use,
* but functionally these relate to the same thing (a QUIC connection). The use
* of two separate objects ensures clean separation between the API personality
* layer and common code for handling connections, and between the functionality
* which is specific to clients and which is specific to servers, and the
* functionality which is common to both.
*
* The API personality layer provides SSL objects (e.g. a QUIC_CONNECTION) which
* consume a QUIC channel and implement a specific public API. Things which are
* handled by the API personality layer include emulation of blocking semantics,
* handling of SSL object mode flags like non-partial write mode, etc.
*
* Where the QUIC_CHANNEL is used in a server role, there is one QUIC_CHANNEL
* per connection. In the future a QUIC Channel Manager will probably be defined
* to handle ownership of resources which are shared between connections (e.g.
* demuxers). Since we only use server-side functionality for dummy test servers
* for now, which only need to handle one connection at a time, this is not
* currently modelled.
*
* Synchronisation
* ---------------
*
* To support thread assisted mode, QUIC_CHANNEL can be used by multiple
* threads. **It is the caller's responsibility to ensure that the QUIC_CHANNEL
* is only accessed (whether via its methods or via direct access to its state)
* while the channel mutex is held**, except for methods explicitly marked as
* not requiring prior locking. This is an unchecked precondition.
*
* The instantiator of the channel is responsible for providing a suitable
* mutex which then serves as the channel mutex; see QUIC_CHANNEL_ARGS.
*/
/*
* The function does not acquire the channel mutex and assumes it is already
* held by the calling thread.
*
* Any function tagged with this has the following precondition:
*
* Precondition: must hold channel mutex (unchecked)
*/
# define QUIC_NEEDS_LOCK
/*
* The function acquires the channel mutex and releases it before returning in
* all circumstances.
*
* Any function tagged with this has the following precondition and
* postcondition:
*
* Precondition: must not hold channel mutex (unchecked)
* Postcondition: channel mutex is not held (by calling thread)
*/
# define QUIC_TAKES_LOCK
/*
* The function acquires the channel mutex and leaves it acquired
* when returning success.
*
* Any function tagged with this has the following precondition and
* postcondition:
*
* Precondition: must not hold channel mutex (unchecked)
* Postcondition: channel mutex is held by calling thread
* or function returned failure
*/
# define QUIC_ACQUIRES_LOCK
# define QUIC_TODO_LOCK
# define QUIC_CHANNEL_STATE_IDLE 0
# define QUIC_CHANNEL_STATE_ACTIVE 1
# define QUIC_CHANNEL_STATE_TERMINATING_CLOSING 2
# define QUIC_CHANNEL_STATE_TERMINATING_DRAINING 3
# define QUIC_CHANNEL_STATE_TERMINATED 4
typedef struct quic_channel_args_st {
OSSL_LIB_CTX *libctx;
const char *propq;
int is_server;
SSL *tls;
/*
* This must be a mutex the lifetime of which will exceed that of the
* channel. The instantiator of the channel is responsible for providing a
* mutex as this makes it easier to handle instantiation and teardown of
* channels in situations potentially requiring locking.
*
* Note that this is a MUTEX not a RWLOCK as it needs to be an OS mutex for
* compatibility with an OS's condition variable wait API, whereas RWLOCK
* may, depending on the build configuration, be implemented using an OS's
* mutex primitive or using its RW mutex primitive.
*/
CRYPTO_MUTEX *mutex;
/*
* Optional function pointer to use to retrieve the current time. If NULL,
* ossl_time_now() is used.
*/
OSSL_TIME (*now_cb)(void *arg);
void *now_cb_arg;
} QUIC_CHANNEL_ARGS;
typedef struct quic_channel_st QUIC_CHANNEL;
/* Represents the cause for a connection's termination. */
typedef struct quic_terminate_cause_st {
/*
* If we are in a TERMINATING or TERMINATED state, this is the error code
* associated with the error. This field is valid iff we are in the
* TERMINATING or TERMINATED states.
*/
uint64_t error_code;
/*
* If terminate_app is set and this is nonzero, this is the frame type which
* caused the connection to be terminated.
*/
uint64_t frame_type;
/*
* Optional reason string. When calling ossl_quic_channel_local_close, if a
* reason string pointer is passed, it is copied and stored inside
* QUIC_CHANNEL for the remainder of the lifetime of the channel object.
* Thus the string pointed to by this value, if non-NULL, is valid for the
* lifetime of the QUIC_CHANNEL object.
*/
const char *reason;
/*
* Length of reason in bytes. The reason is supposed to contain a UTF-8
* string but may be arbitrary data if the reason came from the network.
*/
size_t reason_len;
/* Is this error code in the transport (0) or application (1) space? */
unsigned int app : 1;
/*
* If set, the cause of the termination is a received CONNECTION_CLOSE
* frame. Otherwise, we decided to terminate ourselves and sent a
* CONNECTION_CLOSE frame (regardless of whether the peer later also sends
* one).
*/
unsigned int remote : 1;
} QUIC_TERMINATE_CAUSE;
/*
* Create a new QUIC channel using the given arguments. The argument structure
* does not need to remain allocated. Returns NULL on failure.
*/
QUIC_CHANNEL *ossl_quic_channel_new(const QUIC_CHANNEL_ARGS *args);
/* No-op if ch is NULL. */
void ossl_quic_channel_free(QUIC_CHANNEL *ch);
/* Set mutator callbacks for test framework support */
int ossl_quic_channel_set_mutator(QUIC_CHANNEL *ch,
ossl_mutate_packet_cb mutatecb,
ossl_finish_mutate_cb finishmutatecb,
void *mutatearg);
/*
* Connection Lifecycle Events
* ===========================
*
* Various events that can be raised on the channel by other parts of the QUIC
* implementation. Some of these are suitable for general use by any part of the
* code (e.g. ossl_quic_channel_raise_protocol_error), others are for very
* specific use by particular components only (e.g.
* ossl_quic_channel_on_handshake_confirmed).
*/
/*
* To be used by a QUIC connection. Starts the channel. For a client-mode
* channel, this starts sending the first handshake layer message, etc. Can only
* be called in the idle state; successive calls are ignored.
*/
int ossl_quic_channel_start(QUIC_CHANNEL *ch);
/* Start a locally initiated connection shutdown. */
void ossl_quic_channel_local_close(QUIC_CHANNEL *ch, uint64_t app_error_code,
const char *app_reason);
/*
* Called when the handshake is confirmed.
*/
int ossl_quic_channel_on_handshake_confirmed(QUIC_CHANNEL *ch);
/*
* Raises a protocol error. This is intended to be the universal call suitable
* for handling of all peer-triggered protocol violations or errors detected by
* us. We specify a QUIC transport-scope error code and optional frame type
* which was responsible. If a frame type is not applicable, specify zero. The
* reason string is not currently handled, but should be a string of static
* storage duration. If the connection has already terminated due to a previous
* protocol error, this is a no-op; first error wins.
*
* Usually the ossl_quic_channel_raise_protocol_error() function should be used.
* The ossl_quic_channel_raise_protocol_error_loc() function can be used
* directly for passing through existing call site information from an existing
* error.
*/
void ossl_quic_channel_raise_protocol_error_loc(QUIC_CHANNEL *ch,
uint64_t error_code,
uint64_t frame_type,
const char *reason,
ERR_STATE *err_state,
const char *src_file,
int src_line,
const char *src_func);
#define ossl_quic_channel_raise_protocol_error(ch, error_code, frame_type, reason) \
ossl_quic_channel_raise_protocol_error_loc((ch), (error_code), \
(frame_type), \
(reason), \
NULL, \
OPENSSL_FILE, \
OPENSSL_LINE, \
OPENSSL_FUNC)
#define ossl_quic_channel_raise_protocol_error_state(ch, error_code, frame_type, reason, state) \
ossl_quic_channel_raise_protocol_error_loc((ch), (error_code), \
(frame_type), \
(reason), \
(state), \
OPENSSL_FILE, \
OPENSSL_LINE, \
OPENSSL_FUNC)
/*
* Returns 1 if permanent net error was detected on the QUIC_CHANNEL,
* 0 otherwise.
*/
int ossl_quic_channel_net_error(QUIC_CHANNEL *ch);
/* Restore saved error state (best effort) */
void ossl_quic_channel_restore_err_state(QUIC_CHANNEL *ch);
/* For RXDP use. */
void ossl_quic_channel_on_remote_conn_close(QUIC_CHANNEL *ch,
OSSL_QUIC_FRAME_CONN_CLOSE *f);
void ossl_quic_channel_on_new_conn_id(QUIC_CHANNEL *ch,
OSSL_QUIC_FRAME_NEW_CONN_ID *f);
/*
* Queries and Accessors
* =====================
*/
/* Gets the reactor which can be used to tick/poll on the channel. */
QUIC_REACTOR *ossl_quic_channel_get_reactor(QUIC_CHANNEL *ch);
/* Gets the QSM used with the channel. */
QUIC_STREAM_MAP *ossl_quic_channel_get_qsm(QUIC_CHANNEL *ch);
/* Gets the statistics manager used with the channel. */
OSSL_STATM *ossl_quic_channel_get_statm(QUIC_CHANNEL *ch);
/*
* Gets/sets the current peer address. Generally this should be used before
* starting a channel in client mode.
*/
int ossl_quic_channel_get_peer_addr(QUIC_CHANNEL *ch, BIO_ADDR *peer_addr);
int ossl_quic_channel_set_peer_addr(QUIC_CHANNEL *ch, const BIO_ADDR *peer_addr);
/* Gets/sets the underlying network read and write BIOs. */
BIO *ossl_quic_channel_get_net_rbio(QUIC_CHANNEL *ch);
BIO *ossl_quic_channel_get_net_wbio(QUIC_CHANNEL *ch);
int ossl_quic_channel_set_net_rbio(QUIC_CHANNEL *ch, BIO *net_rbio);
int ossl_quic_channel_set_net_wbio(QUIC_CHANNEL *ch, BIO *net_wbio);
/*
* Re-poll the network BIOs already set to determine if their support
* for polling has changed.
*/
int ossl_quic_channel_update_poll_descriptors(QUIC_CHANNEL *ch);
/*
* Returns an existing stream by stream ID. Returns NULL if the stream does not
* exist.
*/
QUIC_STREAM *ossl_quic_channel_get_stream_by_id(QUIC_CHANNEL *ch,
uint64_t stream_id);
/* Returns 1 if channel is terminating or terminated. */
int ossl_quic_channel_is_term_any(const QUIC_CHANNEL *ch);
const QUIC_TERMINATE_CAUSE *
ossl_quic_channel_get_terminate_cause(const QUIC_CHANNEL *ch);
int ossl_quic_channel_is_closing(const QUIC_CHANNEL *ch);
int ossl_quic_channel_is_terminated(const QUIC_CHANNEL *ch);
int ossl_quic_channel_is_active(const QUIC_CHANNEL *ch);
int ossl_quic_channel_is_handshake_complete(const QUIC_CHANNEL *ch);
int ossl_quic_channel_is_handshake_confirmed(const QUIC_CHANNEL *ch);
QUIC_DEMUX *ossl_quic_channel_get0_demux(QUIC_CHANNEL *ch);
SSL *ossl_quic_channel_get0_ssl(QUIC_CHANNEL *ch);
/*
* Retrieves a pointer to the channel mutex which was provided at the time the
* channel was instantiated. In order to allow locks to be acquired and released
* with the correct granularity, it is the caller's responsibility to ensure
* this lock is held for write while calling any QUIC_CHANNEL method, except for
* methods explicitly designed otherwise.
*
* This method is thread safe and does not require prior locking. It can also be
* called while the lock is already held. Note that this is simply a convenience
* function to access the mutex which was passed to the channel at instantiation
* time; it does not belong to the channel but rather is presumed to belong to
* the owner of the channel.
*/
CRYPTO_MUTEX *ossl_quic_channel_get_mutex(QUIC_CHANNEL *ch);
/*
* Creates a new locally-initiated stream in the stream mapper, choosing an
* appropriate stream ID. If is_uni is 1, creates a unidirectional stream, else
* creates a bidirectional stream. Returns NULL on failure.
*/
QUIC_STREAM *ossl_quic_channel_new_stream_local(QUIC_CHANNEL *ch, int is_uni);
/*
* Creates a new remotely-initiated stream in the stream mapper. The stream ID
* is used to confirm the initiator and determine the stream type. The stream is
* automatically added to the QSM's accept queue. A pointer to the stream is
* also returned. Returns NULL on failure.
*/
QUIC_STREAM *ossl_quic_channel_new_stream_remote(QUIC_CHANNEL *ch,
uint64_t stream_id);
/*
* Configures incoming stream auto-reject. If enabled, incoming streams have
* both their sending and receiving parts automatically rejected using
* STOP_SENDING and STREAM_RESET frames. aec is the application error
* code to be used for those frames.
*/
void ossl_quic_channel_set_incoming_stream_auto_reject(QUIC_CHANNEL *ch,
int enable,
uint64_t aec);
/*
* Causes the channel to reject the sending and receiving parts of a stream,
* as though autorejected. Can be used if a stream has already been
* accepted.
*/
void ossl_quic_channel_reject_stream(QUIC_CHANNEL *ch, QUIC_STREAM *qs);
/* Replace local connection ID in TXP and DEMUX for testing purposes. */
int ossl_quic_channel_replace_local_cid(QUIC_CHANNEL *ch,
const QUIC_CONN_ID *conn_id);
/* Setters for the msg_callback and msg_callback_arg */
void ossl_quic_channel_set_msg_callback(QUIC_CHANNEL *ch,
ossl_msg_cb msg_callback,
SSL *msg_callback_ssl);
void ossl_quic_channel_set_msg_callback_arg(QUIC_CHANNEL *ch,
void *msg_callback_arg);
/* Testing use only - sets a TXKU threshold packet count override value. */
void ossl_quic_channel_set_txku_threshold_override(QUIC_CHANNEL *ch,
uint64_t tx_pkt_threshold);
/* Testing use only - gets current 1-RTT key epochs for QTX and QRX. */
uint64_t ossl_quic_channel_get_tx_key_epoch(QUIC_CHANNEL *ch);
uint64_t ossl_quic_channel_get_rx_key_epoch(QUIC_CHANNEL *ch);
/* Artificially trigger a spontaneous TXKU if possible. */
int ossl_quic_channel_trigger_txku(QUIC_CHANNEL *ch);
int ossl_quic_channel_has_pending(const QUIC_CHANNEL *ch);
/* Force transmission of an ACK-eliciting packet. */
int ossl_quic_channel_ping(QUIC_CHANNEL *ch);
/* For testing use. While enabled, ticking is not performed. */
void ossl_quic_channel_set_inhibit_tick(QUIC_CHANNEL *ch, int inhibit);
/*
* These queries exist for diagnostic purposes only. They may roll over.
* Do not rely on them for non-testing purposes.
*/
uint16_t ossl_quic_channel_get_diag_num_rx_ack(QUIC_CHANNEL *ch);
/*
* Diagnostic use only. Gets the current local CID.
*/
void ossl_quic_channel_get_diag_local_cid(QUIC_CHANNEL *ch, QUIC_CONN_ID *cid);
/*
* Returns 1 if stream count flow control allows us to create a new
* locally-initiated stream.
*/
int ossl_quic_channel_is_new_local_stream_admissible(QUIC_CHANNEL *ch, int is_uni);
# endif
#endif

View File

@ -0,0 +1,364 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_QUIC_DEMUX_H
# define OSSL_QUIC_DEMUX_H
# include <openssl/ssl.h>
# include "internal/quic_types.h"
# include "internal/bio_addr.h"
# include "internal/time.h"
# include "internal/list.h"
# ifndef OPENSSL_NO_QUIC
/*
* QUIC Demuxer
* ============
*
* The QUIC connection demuxer is the entity responsible for receiving datagrams
* from the network via a datagram BIO. It parses packet headers to determine
* each packet's destination connection ID (DCID) and hands off processing of
* the packet to the correct QUIC Record Layer (QRL)'s RX side (known as the
* QRX).
*
* A QRX is instantiated per QUIC connection and contains the cryptographic
* resources needed to decrypt QUIC packets for that connection. Received
* datagrams are passed from the demuxer to the QRX via a callback registered
* for a specific DCID by the QRX; thus the demuxer has no specific knowledge of
* the QRX and is not coupled to it.
*
* A connection may have multiple connection IDs associated with it; a QRX
* handles this simply by registering multiple connection IDs with the demuxer
* via multiple register calls.
*
* URX Queue
* ---------
*
* Since the demuxer must handle the initial reception of datagrams from the OS,
* RX queue management for new, unprocessed datagrams is also handled by the
* demuxer.
*
* The demuxer maintains a queue of Unprocessed RX Entries (URXEs), which store
* unprocessed (i.e., encrypted, unvalidated) data received from the network.
* The URXE queue is designed to allow multiple datagrams to be received in a
* single call to BIO_recvmmsg, where supported.
*
* One URXE is used per received datagram. Each datagram may contain multiple
* packets, however, this is not the demuxer's concern. QUIC prohibits different
* packets in the same datagram from containing different DCIDs; the demuxer
* only considers the DCID of the first packet in a datagram when deciding how
* to route a received datagram, and it is the responsibility of the QRX to
* enforce this rule. Packets other than the first packet in a datagram are not
* examined by the demuxer, and the demuxer does not perform validation of
* packet headers other than to the minimum extent necessary to extract the
* DCID; further parsing and validation of packet headers is the responsibility
* of the QRX.
*
* Rather than defining an opaque interface, the URXE structure internals
* are exposed. Since the demuxer is only exposed to other parts of the QUIC
* implementation internals, this poses no problem, and has a number of
* advantages:
*
* - Fields in the URXE can be allocated to support requirements in other
* components, like the QRX, which would otherwise have to allocate extra
* memory corresponding to each URXE.
*
* - Other components, like the QRX, can keep the URXE in queues of its own
* when it is not being managed by the demuxer.
*
* URX Queue Structure
* -------------------
*
* The URXE queue is maintained as a simple doubly-linked list. URXE entries are
* moved between different lists in their lifecycle (for example, from a free
* list to a pending list and vice versa). The buffer into which datagrams are
* received immediately follows this URXE header structure and is part of the
* same allocation.
*/
typedef struct quic_urxe_st QUIC_URXE;
/* Maximum number of packets we allow to exist in one datagram. */
#define QUIC_MAX_PKT_PER_URXE (sizeof(uint64_t) * 8)
struct quic_urxe_st {
OSSL_LIST_MEMBER(urxe, QUIC_URXE);
/*
* The URXE data starts after this structure so we don't need a pointer.
* data_len stores the current length (i.e., the length of the received
* datagram) and alloc_len stores the allocation length. The URXE will be
* reallocated if we need a larger allocation than is available, though this
* should not be common as we will have a good idea of worst-case MTUs up
* front.
*/
size_t data_len, alloc_len;
/*
* Bitfields per packet. processed indicates the packet has been processed
* and must not be processed again, hpr_removed indicates header protection
* has already been removed. Used by QRX only; not used by the demuxer.
*/
uint64_t processed, hpr_removed;
/*
* Address of peer we received the datagram from, and the local interface
* address we received it on. If local address support is not enabled, local
* is zeroed.
*/
BIO_ADDR peer, local;
/*
* Time at which datagram was received (or ossl_time_zero()) if a now
* function was not provided).
*/
OSSL_TIME time;
/*
* Used by the QRX to mark whether a datagram has been deferred. Used by the
* QRX only; not used by the demuxer.
*/
char deferred;
/*
* Used by the DEMUX to track if a URXE has been handed out. Used primarily
* for debugging purposes.
*/
char demux_state;
};
/* Accessors for URXE buffer. */
static ossl_unused ossl_inline unsigned char *
ossl_quic_urxe_data(const QUIC_URXE *e)
{
return (unsigned char *)&e[1];
}
static ossl_unused ossl_inline unsigned char *
ossl_quic_urxe_data_end(const QUIC_URXE *e)
{
return ossl_quic_urxe_data(e) + e->data_len;
}
/* List structure tracking a queue of URXEs. */
DEFINE_LIST_OF(urxe, QUIC_URXE);
typedef OSSL_LIST(urxe) QUIC_URXE_LIST;
/*
* List management helpers. These are used by the demuxer but can also be used
* by users of the demuxer to manage URXEs.
*/
void ossl_quic_urxe_remove(QUIC_URXE_LIST *l, QUIC_URXE *e);
void ossl_quic_urxe_insert_head(QUIC_URXE_LIST *l, QUIC_URXE *e);
void ossl_quic_urxe_insert_tail(QUIC_URXE_LIST *l, QUIC_URXE *e);
/* Opaque type representing a demuxer. */
typedef struct quic_demux_st QUIC_DEMUX;
/*
* Called when a datagram is received for a given connection ID.
*
* e is a URXE containing the datagram payload. It is permissible for the callee
* to mutate this buffer; once the demuxer calls this callback, it will never
* read the buffer again.
*
* The callee must arrange for ossl_quic_demux_release_urxe or
* ossl_quic_demux_reinject_urxe to be called on the URXE at some point in the
* future (this need not be before the callback returns).
*
* At the time the callback is made, the URXE will not be in any queue,
* therefore the callee can use the prev and next fields as it wishes.
*/
typedef void (ossl_quic_demux_cb_fn)(QUIC_URXE *e, void *arg);
/*
* Called when a datagram is received.
* Returns 1 if the datagram ends with a stateless reset token and
* 0 if not.
*/
typedef int (ossl_quic_stateless_reset_cb_fn)(const unsigned char *data,
size_t data_len, void *arg);
/*
* Creates a new demuxer. The given BIO is used to receive datagrams from the
* network using BIO_recvmmsg. short_conn_id_len is the length of destination
* connection IDs used in RX'd packets; it must have the same value for all
* connections used on a socket. default_urxe_alloc_len is the buffer size to
* receive datagrams into; it should be a value large enough to contain any
* received datagram according to local MTUs, etc.
*
* now is an optional function used to determine the time a datagram was
* received. now_arg is an opaque argument passed to the function. If now is
* NULL, ossl_time_zero() is used as the datagram reception time.
*/
QUIC_DEMUX *ossl_quic_demux_new(BIO *net_bio,
size_t short_conn_id_len,
OSSL_TIME (*now)(void *arg),
void *now_arg);
/*
* Destroy a demuxer. All URXEs must have been released back to the demuxer
* before calling this. No-op if demux is NULL.
*/
void ossl_quic_demux_free(QUIC_DEMUX *demux);
/*
* Changes the BIO which the demuxer reads from. This also sets the MTU if the
* BIO supports querying the MTU.
*/
void ossl_quic_demux_set_bio(QUIC_DEMUX *demux, BIO *net_bio);
/*
* Changes the MTU in bytes we use to receive datagrams.
*/
int ossl_quic_demux_set_mtu(QUIC_DEMUX *demux, unsigned int mtu);
/*
* Register a datagram handler callback for a connection ID.
*
* ossl_quic_demux_pump will call the specified function if it receives a datagram
* the first packet of which has the specified destination connection ID.
*
* It is assumed all packets in a datagram have the same destination connection
* ID (as QUIC mandates this), but it is the user's responsibility to check for
* this and reject subsequent packets in a datagram that violate this rule.
*
* dst_conn_id is a destination connection ID; it is copied and need not remain
* valid after this function returns.
*
* cb_arg is passed to cb when it is called. For information on the callback,
* see its typedef above.
*
* Only one handler can be set for a given connection ID. If a handler is
* already set for the given connection ID, returns 0.
*
* Returns 1 on success or 0 on failure.
*/
int ossl_quic_demux_register(QUIC_DEMUX *demux,
const QUIC_CONN_ID *dst_conn_id,
ossl_quic_demux_cb_fn *cb,
void *cb_arg);
/*
* Unregisters any datagram handler callback set for the given connection ID.
* Fails if no handler is registered for the given connection ID.
*
* Returns 1 on success or 0 on failure.
*/
int ossl_quic_demux_unregister(QUIC_DEMUX *demux,
const QUIC_CONN_ID *dst_conn_id);
/*
* Unregisters any datagram handler callback from all connection IDs it is used
* for. cb and cb_arg must both match the values passed to
* ossl_quic_demux_register.
*/
void ossl_quic_demux_unregister_by_cb(QUIC_DEMUX *demux,
ossl_quic_demux_cb_fn *cb,
void *cb_arg);
/*
* Set the default packet handler. This is used for incoming packets which don't
* match a registered DCID. This is only needed for servers. If a default packet
* handler is not set, a packet which doesn't match a registered DCID is
* silently dropped. A default packet handler may be unset by passing NULL.
*
* The handler is responsible for ensuring that ossl_quic_demux_reinject_urxe or
* ossl_quic_demux_release_urxe is called on the passed packet at some point in
* the future, which may or may not be before the handler returns.
*/
void ossl_quic_demux_set_default_handler(QUIC_DEMUX *demux,
ossl_quic_demux_cb_fn *cb,
void *cb_arg);
/*
* Sets a callback for stateless reset processing.
*
* If set, this callback is called for datagrams for which we cannot identify
* a CID. This function should return 1 if there is a stateless reset token
* present and 0 if not. If there is a token present, the connection should
* also be reset.
*/
void ossl_quic_demux_set_stateless_reset_handler(
QUIC_DEMUX *demux,
ossl_quic_stateless_reset_cb_fn *cb, void *cb_arg);
/*
* Releases a URXE back to the demuxer. No reference must be made to the URXE or
* its buffer after calling this function. The URXE must not be in any queue;
* that is, its prev and next pointers must be NULL.
*/
void ossl_quic_demux_release_urxe(QUIC_DEMUX *demux,
QUIC_URXE *e);
/*
* Reinjects a URXE which was issued to a registered DCID callback or the
* default packet handler callback back into the pending queue. This is useful
* when a packet has been handled by the default packet handler callback such
* that a DCID has now been registered and can be dispatched normally by DCID.
* Once this has been called, the caller must not touch the URXE anymore and
* must not also call ossl_quic_demux_release_urxe().
*
* The URXE is reinjected at the head of the queue, so it will be reprocessed
* immediately.
*/
void ossl_quic_demux_reinject_urxe(QUIC_DEMUX *demux,
QUIC_URXE *e);
/*
* Process any unprocessed RX'd datagrams, by calling registered callbacks by
* connection ID, reading more datagrams from the BIO if necessary.
*
* Returns one of the following values:
*
* QUIC_DEMUX_PUMP_RES_OK
* At least one incoming datagram was processed.
*
* QUIC_DEMUX_PUMP_RES_TRANSIENT_FAIL
* No more incoming datagrams are currently available.
* Call again later.
*
* QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL
* Either the network read BIO has failed in a non-transient fashion, or
* the QUIC implementation has encountered an internal state, assertion
* or allocation error. The caller should tear down the connection
* similarly to in the case of a protocol violation.
*
*/
#define QUIC_DEMUX_PUMP_RES_OK 1
#define QUIC_DEMUX_PUMP_RES_TRANSIENT_FAIL (-1)
#define QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL (-2)
#define QUIC_DEMUX_PUMP_RES_STATELESS_RESET (-3)
int ossl_quic_demux_pump(QUIC_DEMUX *demux);
/*
* Artificially inject a packet into the demuxer for testing purposes. The
* buffer must not exceed the URXE size being used by the demuxer.
*
* If peer or local are NULL, their respective fields are zeroed in the injected
* URXE.
*
* Returns 1 on success or 0 on failure.
*/
int ossl_quic_demux_inject(QUIC_DEMUX *demux,
const unsigned char *buf,
size_t buf_len,
const BIO_ADDR *peer,
const BIO_ADDR *local);
/*
* Returns 1 if there are any pending URXEs.
*/
int ossl_quic_demux_has_pending(const QUIC_DEMUX *demux);
# endif
#endif

View File

@ -0,0 +1,56 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_QUIC_ERROR_H
# define OSSL_QUIC_ERROR_H
# include <openssl/ssl.h>
# ifndef OPENSSL_NO_QUIC
/* RFC 9000 Section 20.1 */
# define QUIC_ERR_NO_ERROR 0x00
# define QUIC_ERR_INTERNAL_ERROR 0x01
# define QUIC_ERR_CONNECTION_REFUSED 0x02
# define QUIC_ERR_FLOW_CONTROL_ERROR 0x03
# define QUIC_ERR_STREAM_LIMIT_ERROR 0x04
# define QUIC_ERR_STREAM_STATE_ERROR 0x05
# define QUIC_ERR_FINAL_SIZE_ERROR 0x06
# define QUIC_ERR_FRAME_ENCODING_ERROR 0x07
# define QUIC_ERR_TRANSPORT_PARAMETER_ERROR 0x08
# define QUIC_ERR_CONNECTION_ID_LIMIT_ERROR 0x09
# define QUIC_ERR_PROTOCOL_VIOLATION 0x0A
# define QUIC_ERR_INVALID_TOKEN 0x0B
# define QUIC_ERR_APPLICATION_ERROR 0x0C
# define QUIC_ERR_CRYPTO_BUFFER_EXCEEDED 0x0D
# define QUIC_ERR_KEY_UPDATE_ERROR 0x0E
# define QUIC_ERR_AEAD_LIMIT_REACHED 0x0F
# define QUIC_ERR_NO_VIABLE_PATH 0x10
/* Inclusive range for handshake-specific errors. */
# define QUIC_ERR_CRYPTO_ERR_BEGIN 0x0100
# define QUIC_ERR_CRYPTO_ERR_END 0x01FF
# define QUIC_ERR_CRYPTO_ERR(X) \
(QUIC_ERR_CRYPTO_ERR_BEGIN + (X))
# define QUIC_ERR_CRYPTO_UNEXPECTED_MESSAGE \
QUIC_ERR_CRYPTO_ERR(SSL3_AD_UNEXPECTED_MESSAGE)
# define QUIC_ERR_CRYPTO_MISSING_EXT \
QUIC_ERR_CRYPTO_ERR(TLS13_AD_MISSING_EXTENSION)
# define QUIC_ERR_CRYPTO_NO_APP_PROTO \
QUIC_ERR_CRYPTO_ERR(TLS1_AD_NO_APPLICATION_PROTOCOL)
const char *ossl_quic_err_to_string(uint64_t error_code);
# endif
#endif

View File

@ -0,0 +1,277 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_QUIC_FC_H
# define OSSL_QUIC_FC_H
# include <openssl/ssl.h>
# include "internal/time.h"
# ifndef OPENSSL_NO_QUIC
/*
* TX Flow Controller (TXFC)
* =========================
*
* For discussion, see doc/designs/quic-design/quic-fc.md.
*/
typedef struct quic_txfc_st QUIC_TXFC;
struct quic_txfc_st {
QUIC_TXFC *parent; /* stream-level iff non-NULL */
uint64_t swm, cwm;
char has_become_blocked;
};
/*
* Initialises a TX flow controller. conn_txfc should be non-NULL and point to
* the connection-level flow controller if the TXFC is for stream-level flow
* control, and NULL otherwise.
*/
int ossl_quic_txfc_init(QUIC_TXFC *txfc, QUIC_TXFC *conn_txfc);
/*
* Gets the parent (i.e., connection-level) TX flow controller. Returns NULL if
* called on a connection-level TX flow controller.
*/
QUIC_TXFC *ossl_quic_txfc_get_parent(QUIC_TXFC *txfc);
/*
* Bump the credit watermark (CWM) value. This is the 'On TX Window Updated'
* operation. This function is a no-op if it has already been called with an
* equal or higher CWM value.
*
* It returns 1 iff the call resulted in the CWM being bumped and 0 if it was
* not increased because it has already been called with an equal or higher CWM
* value. This is not an error per se but may indicate a local programming error
* or a protocol error in a remote peer.
*/
int ossl_quic_txfc_bump_cwm(QUIC_TXFC *txfc, uint64_t cwm);
/*
* Get the number of bytes by which we are in credit. This is the number of
* controlled bytes we are allowed to send. (Thus if this function returns 0, we
* are currently blocked.)
*
* If called on a stream-level TXFC, ossl_quic_txfc_get_credit is called on
* the connection-level TXFC as well, and the lesser of the two values is
* returned. The consumed value is the amount already consumed on the connection
* level TXFC.
*/
uint64_t ossl_quic_txfc_get_credit(QUIC_TXFC *txfc, uint64_t consumed);
/*
* Like ossl_quic_txfc_get_credit(), but when called on a stream-level TXFC,
* retrieves only the stream-level credit value and does not clamp it based on
* connection-level flow control. Any credit value is reduced by the consumed
* amount.
*/
uint64_t ossl_quic_txfc_get_credit_local(QUIC_TXFC *txfc, uint64_t consumed);
/*
* Consume num_bytes of credit. This is the 'On TX' operation. This should be
* called when we transmit any controlled bytes. Calling this with an argument
* of 0 is a no-op.
*
* We must never transmit more controlled bytes than we are in credit for (see
* the return value of ossl_quic_txfc_get_credit()). If you call this function
* with num_bytes greater than our current credit, this function consumes the
* remainder of the credit and returns 0. This indicates a serious programming
* error on the caller's part. Otherwise, the function returns 1.
*
* If called on a stream-level TXFC, ossl_quic_txfc_consume_credit() is called
* on the connection-level TXFC also. If the call to that function on the
* connection-level TXFC returns zero, this function will also return zero.
*/
int ossl_quic_txfc_consume_credit(QUIC_TXFC *txfc, uint64_t num_bytes);
/*
* Like ossl_quic_txfc_consume_credit(), but when called on a stream-level TXFC,
* consumes only from the stream-level credit and does not inform the
* connection-level TXFC.
*/
int ossl_quic_txfc_consume_credit_local(QUIC_TXFC *txfc, uint64_t num_bytes);
/*
* This flag is provided for convenience. A caller is not required to use it. It
* is a boolean flag set whenever our credit drops to zero. If clear is 1, the
* flag is cleared. The old value of the flag is returned. Callers may use this
* to determine if they need to send a DATA_BLOCKED or STREAM_DATA_BLOCKED
* frame, which should contain the value returned by ossl_quic_txfc_get_cwm().
*/
int ossl_quic_txfc_has_become_blocked(QUIC_TXFC *txfc, int clear);
/*
* Get the current CWM value. This is mainly only needed when generating a
* DATA_BLOCKED or STREAM_DATA_BLOCKED frame, or for diagnostic purposes.
*/
uint64_t ossl_quic_txfc_get_cwm(QUIC_TXFC *txfc);
/*
* Get the current spent watermark (SWM) value. This is purely for diagnostic
* use and should not be needed in normal circumstances.
*/
uint64_t ossl_quic_txfc_get_swm(QUIC_TXFC *txfc);
/*
* RX Flow Controller (RXFC)
* =========================
*/
typedef struct quic_rxfc_st QUIC_RXFC;
struct quic_rxfc_st {
/*
* swm is the sent/received watermark, which tracks how much we have
* received from the peer. rwm is the retired watermark, which tracks how
* much has been passed to the application. esrwm is the rwm value at which
* the current auto-tuning epoch started. hwm is the highest stream length
* (STREAM frame offset + payload length) we have seen from a STREAM frame
* yet.
*/
uint64_t cwm, swm, rwm, esrwm, hwm, cur_window_size, max_window_size;
OSSL_TIME epoch_start;
OSSL_TIME (*now)(void *arg);
void *now_arg;
QUIC_RXFC *parent;
unsigned char error_code, has_cwm_changed, is_fin, standalone;
};
/*
* Initialises an RX flow controller. conn_rxfc should be non-NULL and point to
* a connection-level RXFC if the RXFC is for stream-level flow control, and
* NULL otherwise. initial_window_size and max_window_size specify the initial
* and absolute maximum window sizes, respectively. Window size values are
* expressed in bytes and determine how much credit the RXFC extends to the peer
* to transmit more data at a time.
*/
int ossl_quic_rxfc_init(QUIC_RXFC *rxfc, QUIC_RXFC *conn_rxfc,
uint64_t initial_window_size,
uint64_t max_window_size,
OSSL_TIME (*now)(void *arg),
void *now_arg);
/*
* Initialises an RX flow controller which is used by itself and not under a
* connection-level RX flow controller. This can be used for stream count
* enforcement as well as CRYPTO buffer enforcement.
*/
int ossl_quic_rxfc_init_standalone(QUIC_RXFC *rxfc,
uint64_t initial_window_size,
OSSL_TIME (*now)(void *arg),
void *now_arg);
/*
* Gets the parent (i.e., connection-level) RXFC. Returns NULL if called on a
* connection-level RXFC.
*/
QUIC_RXFC *ossl_quic_rxfc_get_parent(QUIC_RXFC *rxfc);
/*
* Changes the current maximum window size value.
*/
void ossl_quic_rxfc_set_max_window_size(QUIC_RXFC *rxfc,
size_t max_window_size);
/*
* To be called whenever a STREAM frame is received.
*
* end is the value (offset + len), where offset is the offset field of the
* STREAM frame and len is the length of the STREAM frame's payload in bytes.
*
* is_fin should be 1 if the STREAM frame had the FIN flag set and 0 otherwise.
*
* This function may be used on a stream-level RXFC only. The connection-level
* RXFC will have its state updated by the stream-level RXFC.
*
* You should check ossl_quic_rxfc_has_error() on both connection-level and
* stream-level RXFCs after calling this function, as an incoming STREAM frame
* may cause flow control limits to be exceeded by an errant peer. This
* function still returns 1 in this case, as this is not a caller error.
*
* Returns 1 on success or 0 on failure.
*/
int ossl_quic_rxfc_on_rx_stream_frame(QUIC_RXFC *rxfc,
uint64_t end, int is_fin);
/*
* To be called whenever controlled bytes are retired, i.e. when bytes are
* dequeued from a QUIC stream and passed to the application. num_bytes
* is the number of bytes which were passed to the application.
*
* You should call this only on a stream-level RXFC. This function will update
* the connection-level RXFC automatically.
*
* rtt should be the current best understanding of the RTT to the peer, as
* offered by the Statistics Manager.
*
* You should check ossl_quic_rxfc_has_cwm_changed() after calling this
* function, as it may have caused the RXFC to decide to grant more flow control
* credit to the peer.
*
* Returns 1 on success and 0 on failure.
*/
int ossl_quic_rxfc_on_retire(QUIC_RXFC *rxfc,
uint64_t num_bytes,
OSSL_TIME rtt);
/*
* Returns the current CWM which the RXFC thinks the peer should have.
*
* Note that the RXFC will increase this value in response to events, at which
* time a MAX_DATA or MAX_STREAM_DATA frame must be generated. Use
* ossl_quic_rxfc_has_cwm_changed() to detect this condition.
*
* This value increases monotonically.
*/
uint64_t ossl_quic_rxfc_get_cwm(QUIC_RXFC *rxfc);
/*
* Returns the current SWM. This is the total number of bytes the peer has
* transmitted to us. This is intended for diagnostic use only; you should
* not need it.
*/
uint64_t ossl_quic_rxfc_get_swm(QUIC_RXFC *rxfc);
/*
* Returns the current RWM. This is the total number of bytes that has been
* retired. This is intended for diagnostic use only; you should not need it.
*/
uint64_t ossl_quic_rxfc_get_rwm(QUIC_RXFC *rxfc);
/*
* Returns the CWM changed flag. If clear is 1, the flag is cleared and the old
* value is returned.
*/
int ossl_quic_rxfc_has_cwm_changed(QUIC_RXFC *rxfc, int clear);
/*
* Returns a QUIC_ERR_* error code if a flow control error has been detected.
* Otherwise, returns QUIC_ERR_NO_ERROR. If clear is 1, the error is cleared
* and the old value is returned.
*
* May return one of the following values:
*
* QUIC_ERR_FLOW_CONTROL_ERROR:
* This indicates a flow control protocol violation by the remote peer; the
* connection should be terminated in this event.
* QUIC_ERR_FINAL_SIZE:
* The peer attempted to change the stream length after ending the stream.
*/
int ossl_quic_rxfc_get_error(QUIC_RXFC *rxfc, int clear);
/*
* Returns 1 if the RXFC is a stream-level RXFC and the RXFC knows the final
* size for the stream in bytes. If this is the case and final_size is non-NULL,
* writes the final size to *final_size. Otherwise, returns 0.
*/
int ossl_quic_rxfc_get_final_size(const QUIC_RXFC *rxfc, uint64_t *final_size);
# endif
#endif

View File

@ -0,0 +1,80 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_QUIC_FIFD_H
# define OSSL_QUIC_FIFD_H
# include <openssl/ssl.h>
# include "internal/quic_types.h"
# include "internal/quic_cfq.h"
# include "internal/quic_ackm.h"
# include "internal/quic_txpim.h"
# include "internal/quic_stream.h"
# ifndef OPENSSL_NO_QUIC
/*
* QUIC Frame-in-Flight Dispatcher (FIFD)
* ======================================
*/
struct quic_fifd_st {
/* Internal data; use the ossl_quic_fifd functions. */
QUIC_CFQ *cfq;
OSSL_ACKM *ackm;
QUIC_TXPIM *txpim;
QUIC_SSTREAM *(*get_sstream_by_id)(uint64_t stream_id,
uint32_t pn_space,
void *arg);
void *get_sstream_by_id_arg;
void (*regen_frame)(uint64_t frame_type,
uint64_t stream_id,
QUIC_TXPIM_PKT *pkt,
void *arg);
void *regen_frame_arg;
void (*confirm_frame)(uint64_t frame_type,
uint64_t stream_id,
QUIC_TXPIM_PKT *pkt,
void *arg);
void *confirm_frame_arg;
void (*sstream_updated)(uint64_t stream_id,
void *arg);
void *sstream_updated_arg;
};
int ossl_quic_fifd_init(QUIC_FIFD *fifd,
QUIC_CFQ *cfq,
OSSL_ACKM *ackm,
QUIC_TXPIM *txpim,
/* stream_id is UINT64_MAX for the crypto stream */
QUIC_SSTREAM *(*get_sstream_by_id)(uint64_t stream_id,
uint32_t pn_space,
void *arg),
void *get_sstream_by_id_arg,
/* stream_id is UINT64_MAX if not applicable */
void (*regen_frame)(uint64_t frame_type,
uint64_t stream_id,
QUIC_TXPIM_PKT *pkt,
void *arg),
void *regen_frame_arg,
void (*confirm_frame)(uint64_t frame_type,
uint64_t stream_id,
QUIC_TXPIM_PKT *pkt,
void *arg),
void *confirm_frame_arg,
void (*sstream_updated)(uint64_t stream_id,
void *arg),
void *sstream_updated_arg);
void ossl_quic_fifd_cleanup(QUIC_FIFD *fifd); /* (no-op) */
int ossl_quic_fifd_pkt_commit(QUIC_FIFD *fifd, QUIC_TXPIM_PKT *pkt);
# endif
#endif

View File

@ -0,0 +1,188 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_QUIC_REACTOR_H
# define OSSL_QUIC_REACTOR_H
# include "internal/time.h"
# include "internal/sockets.h"
# include <openssl/bio.h>
# ifndef OPENSSL_NO_QUIC
/*
* Core I/O Reactor Framework
* ==========================
*
* Manages use of async network I/O which the QUIC stack is built on. The core
* mechanic looks like this:
*
* - There is a pollable FD for both the read and write side respectively.
* Readability and writeability of these FDs respectively determines when
* network I/O is available.
*
* - The reactor can export these FDs to the user, as well as flags indicating
* whether the user should listen for readability, writeability, or neither.
*
* - The reactor can export a timeout indication to the user, indicating when
* the reactor should be called (via libssl APIs) regardless of whether
* the network socket has become ready.
*
* The reactor is based around a tick callback which is essentially the mutator
* function. The mutator attempts to do whatever it can, attempting to perform
* network I/O to the extent currently feasible. When done, the mutator returns
* information to the reactor indicating when it should be woken up again:
*
* - Should it be woken up when network RX is possible?
* - Should it be woken up when network TX is possible?
* - Should it be woken up no later than some deadline X?
*
* The intention is that ALL I/O-related SSL_* functions with side effects (e.g.
* SSL_read/SSL_write) consist of three phases:
*
* - Optionally mutate the QUIC machine's state.
* - Optionally tick the QUIC reactor.
* - Optionally mutate the QUIC machine's state.
*
* For example, SSL_write is a mutation (appending to a stream buffer) followed
* by an optional tick (generally expected as we may want to send the data
* immediately, though not strictly needed if transmission is being deferred due
* to Nagle's algorithm, etc.).
*
* SSL_read is also a mutation and in principle does not need to tick the
* reactor, but it generally will anyway to ensure that the reactor is regularly
* ticked by an application which is only reading and not writing.
*
* If the SSL object is being used in blocking mode, SSL_read may need to block
* if no data is available yet, and SSL_write may need to block if buffers
* are full.
*
* The internals of the QUIC I/O engine always use asynchronous I/O. If the
* application desires blocking semantics, we handle this by adding a blocking
* adaptation layer on top of our internal asynchronous I/O API as exposed by
* the reactor interface.
*/
typedef struct quic_tick_result_st {
char net_read_desired;
char net_write_desired;
OSSL_TIME tick_deadline;
} QUIC_TICK_RESULT;
typedef struct quic_reactor_st {
/*
* BIO poll descriptors which can be polled. poll_r is a poll descriptor
* which becomes readable when the QUIC state machine can potentially do
* work, and poll_w is a poll descriptor which becomes writable when the
* QUIC state machine can potentially do work. Generally, either of these
* conditions means that SSL_tick() should be called, or another SSL
* function which implicitly calls SSL_tick() (e.g. SSL_read/SSL_write()).
*/
BIO_POLL_DESCRIPTOR poll_r, poll_w;
OSSL_TIME tick_deadline; /* ossl_time_infinite() if none currently applicable */
void (*tick_cb)(QUIC_TICK_RESULT *res, void *arg, uint32_t flags);
void *tick_cb_arg;
/*
* These are true if we would like to know when we can read or write from
* the network respectively.
*/
unsigned int net_read_desired : 1;
unsigned int net_write_desired : 1;
/*
* Are the read and write poll descriptors we are currently configured with
* things we can actually poll?
*/
unsigned int can_poll_r : 1;
unsigned int can_poll_w : 1;
} QUIC_REACTOR;
void ossl_quic_reactor_init(QUIC_REACTOR *rtor,
void (*tick_cb)(QUIC_TICK_RESULT *res, void *arg,
uint32_t flags),
void *tick_cb_arg,
OSSL_TIME initial_tick_deadline);
void ossl_quic_reactor_set_poll_r(QUIC_REACTOR *rtor,
const BIO_POLL_DESCRIPTOR *r);
void ossl_quic_reactor_set_poll_w(QUIC_REACTOR *rtor,
const BIO_POLL_DESCRIPTOR *w);
const BIO_POLL_DESCRIPTOR *ossl_quic_reactor_get_poll_r(const QUIC_REACTOR *rtor);
const BIO_POLL_DESCRIPTOR *ossl_quic_reactor_get_poll_w(const QUIC_REACTOR *rtor);
int ossl_quic_reactor_can_poll_r(const QUIC_REACTOR *rtor);
int ossl_quic_reactor_can_poll_w(const QUIC_REACTOR *rtor);
int ossl_quic_reactor_can_support_poll_descriptor(const QUIC_REACTOR *rtor,
const BIO_POLL_DESCRIPTOR *d);
int ossl_quic_reactor_net_read_desired(QUIC_REACTOR *rtor);
int ossl_quic_reactor_net_write_desired(QUIC_REACTOR *rtor);
OSSL_TIME ossl_quic_reactor_get_tick_deadline(QUIC_REACTOR *rtor);
/*
* Do whatever work can be done, and as much work as can be done. This involves
* e.g. seeing if we can read anything from the network (if we want to), seeing
* if we can write anything to the network (if we want to), etc.
*
* If the CHANNEL_ONLY flag is set, this indicates that we should only
* touch state which is synchronised by the channel mutex.
*/
#define QUIC_REACTOR_TICK_FLAG_CHANNEL_ONLY (1U << 0)
int ossl_quic_reactor_tick(QUIC_REACTOR *rtor, uint32_t flags);
/*
* Blocking I/O Adaptation Layer
* =============================
*
* The blocking I/O adaptation layer implements blocking I/O on top of our
* asynchronous core.
*
* The core mechanism is block_until_pred(), which does not return until pred()
* returns a value other than 0. The blocker uses OS I/O synchronisation
* primitives (e.g. poll(2)) and ticks the reactor until the predicate is
* satisfied. The blocker is not required to call pred() more than once between
* tick calls.
*
* When pred returns a non-zero value, that value is returned by this function.
* This can be used to allow pred() to indicate error conditions and short
* circuit the blocking process.
*
* A return value of -1 is reserved for network polling errors. Therefore this
* return value should not be used by pred() if ambiguity is not desired. Note
* that the predicate function can always arrange its own output mechanism, for
* example by passing a structure of its own as the argument.
*
* If the SKIP_FIRST_TICK flag is set, the first call to reactor_tick() before
* the first call to pred() is skipped. This is useful if it is known that
* ticking the reactor again will not be useful (e.g. because it has already
* been done).
*
* This function assumes a write lock is held for the entire QUIC_CHANNEL. If
* mutex is non-NULL, it must be a lock currently held for write; it will be
* unlocked during any sleep, and then relocked for write afterwards.
*
* Precondition: mutex is NULL or is held for write (unchecked)
* Postcondition: mutex is NULL or is held for write (unless
* CRYPTO_THREAD_write_lock fails)
*/
#define SKIP_FIRST_TICK (1U << 0)
int ossl_quic_reactor_block_until_pred(QUIC_REACTOR *rtor,
int (*pred)(void *arg), void *pred_arg,
uint32_t flags,
CRYPTO_RWLOCK *mutex);
# endif
#endif

View File

@ -0,0 +1,569 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_QUIC_RECORD_RX_H
# define OSSL_QUIC_RECORD_RX_H
# include <openssl/ssl.h>
# include "internal/quic_wire_pkt.h"
# include "internal/quic_types.h"
# include "internal/quic_record_util.h"
# include "internal/quic_demux.h"
# ifndef OPENSSL_NO_QUIC
/*
* QUIC Record Layer - RX
* ======================
*/
typedef struct ossl_qrx_st OSSL_QRX;
typedef struct ossl_qrx_args_st {
OSSL_LIB_CTX *libctx;
const char *propq;
/* Demux to receive datagrams from. */
QUIC_DEMUX *demux;
/* Length of connection IDs used in short-header packets in bytes. */
size_t short_conn_id_len;
/*
* Maximum number of deferred datagrams buffered at any one time.
* Suggested value: 32.
*/
size_t max_deferred;
/* Initial reference PN used for RX. */
QUIC_PN init_largest_pn[QUIC_PN_SPACE_NUM];
/* Initial key phase. For debugging use only; always 0 in real use. */
unsigned char init_key_phase_bit;
} OSSL_QRX_ARGS;
/* Instantiates a new QRX. */
OSSL_QRX *ossl_qrx_new(const OSSL_QRX_ARGS *args);
/*
* Frees the QRX. All packets obtained using ossl_qrx_read_pkt must already
* have been released by calling ossl_qrx_release_pkt.
*
* You do not need to call ossl_qrx_remove_dst_conn_id first; this function will
* unregister the QRX from the demuxer for all registered destination connection
* IDs (DCIDs) automatically.
*/
void ossl_qrx_free(OSSL_QRX *qrx);
/* Setters for the msg_callback and msg_callback_arg */
void ossl_qrx_set_msg_callback(OSSL_QRX *qrx, ossl_msg_cb msg_callback,
SSL *msg_callback_ssl);
void ossl_qrx_set_msg_callback_arg(OSSL_QRX *qrx,
void *msg_callback_arg);
/*
* DCID Management
* ===============
*/
/*
* Adds a given DCID to the QRX. The QRX will register the DCID with the demuxer
* so that incoming packets with that DCID are passed to the given QRX. Multiple
* DCIDs may be associated with a QRX at any one time. You will need to add at
* least one DCID after instantiating the QRX. A zero-length DCID is a valid
* input to this function. This function fails if the DCID is already
* registered.
*
* Returns 1 on success or 0 on error.
*/
int ossl_qrx_add_dst_conn_id(OSSL_QRX *qrx,
const QUIC_CONN_ID *dst_conn_id);
/*
* Remove a DCID previously registered with ossl_qrx_add_dst_conn_id. The DCID
* is unregistered from the demuxer. Fails if the DCID is not registered with
* the demuxer.
*
* Returns 1 on success or 0 on error.
*/
int ossl_qrx_remove_dst_conn_id(OSSL_QRX *qrx,
const QUIC_CONN_ID *dst_conn_id);
/*
* Secret Management
* =================
*
* A QRX has several encryption levels (Initial, Handshake, 0-RTT, 1-RTT) and
* two directions (RX, TX). At any given time, key material is managed for each
* (EL, RX/TX) combination.
*
* Broadly, for a given (EL, RX/TX), the following state machine is applicable:
*
* WAITING_FOR_KEYS --[Provide]--> HAVE_KEYS --[Discard]--> | DISCARDED |
* \-------------------------------------[Discard]--> | |
*
* To transition the RX side of an EL from WAITING_FOR_KEYS to HAVE_KEYS, call
* ossl_qrx_provide_secret (for the INITIAL EL, use of
* ossl_quic_provide_initial_secret is recommended).
*
* Once keys have been provisioned for an EL, you call
* ossl_qrx_discard_enc_level to transition the EL to the DISCARDED state. You
* can also call this function to transition directly to the DISCARDED state
* even before any keys have been provisioned for that EL.
*
* The DISCARDED state is terminal for a given EL; you cannot provide a secret
* again for that EL after reaching it.
*
* Incoming packets cannot be processed and decrypted if they target an EL
* not in the HAVE_KEYS state. However, there is a distinction between
* the WAITING_FOR_KEYS and DISCARDED states:
*
* - In the WAITING_FOR_KEYS state, the QRX assumes keys for the given
* EL will eventually arrive. Therefore, if it receives any packet
* for an EL in this state, it buffers it and tries to process it
* again once the EL reaches HAVE_KEYS.
*
* - In the DISCARDED state, the QRX assumes no keys for the given
* EL will ever arrive again. If it receives any packet for an EL
* in this state, it is simply discarded.
*
* If the user wishes to instantiate a new QRX to replace an old one for
* whatever reason, for example to take over for an already established QUIC
* connection, it is important that all ELs no longer being used (i.e., INITIAL,
* 0-RTT, 1-RTT) are transitioned to the DISCARDED state. Otherwise, the QRX
* will assume that keys for these ELs will arrive in future, and will buffer
* any received packets for those ELs perpetually. This can be done by calling
* ossl_qrx_discard_enc_level for all non-1-RTT ELs immediately after
* instantiating the QRX.
*
* The INITIAL EL is not setup automatically when the QRX is instantiated. This
* allows the caller to instead discard it immediately after instantiation of
* the QRX if it is not needed, for example if the QRX is being instantiated to
* take over handling of an existing connection which has already passed the
* INITIAL phase. This avoids the unnecessary derivation of INITIAL keys where
* they are not needed. In the ordinary case, ossl_quic_provide_initial_secret
* should be called immediately after instantiation.
*/
/*
* Provides a secret to the QRX, which arises due to an encryption level change.
* enc_level is a QUIC_ENC_LEVEL_* value. To initialise the INITIAL encryption
* level, it is recommended to use ossl_quic_provide_initial_secret instead.
*
* You should seek to call this function for a given EL before packets of that
* EL arrive and are processed by the QRX. However, if packets have already
* arrived for a given EL, the QRX will defer processing of them and perform
* processing of them when this function is eventually called for the EL in
* question.
*
* suite_id is a QRL_SUITE_* value which determines the AEAD function used for
* the QRX.
*
* The secret passed is used directly to derive the "quic key", "quic iv" and
* "quic hp" values.
*
* secret_len is the length of the secret buffer in bytes. The buffer must be
* sized correctly to the chosen suite, else the function fails.
*
* This function can only be called once for a given EL, except for the INITIAL
* EL, which can need rekeying when a connection retry occurs. Subsequent calls
* for non-INITIAL ELs fail, as do calls made after a corresponding call to
* ossl_qrx_discard_enc_level for that EL. The secret for a non-INITIAL EL
* cannot be changed after it is set because QUIC has no facility for
* introducing additional key material after an EL is setup. QUIC key updates
* are managed semi-automatically by the QRX but do require some caller handling
* (see below).
*
* md is for internal use and should be NULL.
*
* Returns 1 on success or 0 on failure.
*/
int ossl_qrx_provide_secret(OSSL_QRX *qrx,
uint32_t enc_level,
uint32_t suite_id,
EVP_MD *md,
const unsigned char *secret,
size_t secret_len);
/*
* Informs the QRX that it can now discard key material for a given EL. The QRX
* will no longer be able to process incoming packets received at that
* encryption level. This function is idempotent and succeeds if the EL has
* already been discarded.
*
* Returns 1 on success and 0 on failure.
*/
int ossl_qrx_discard_enc_level(OSSL_QRX *qrx, uint32_t enc_level);
/*
* Packet Reception
* ================
*/
/* Information about a received packet. */
typedef struct ossl_qrx_pkt_st {
/*
* Points to a logical representation of the decoded QUIC packet header. The
* data and len fields point to the decrypted QUIC payload (i.e., to a
* sequence of zero or more (potentially malformed) frames to be decoded).
*/
QUIC_PKT_HDR *hdr;
/*
* Address the packet was received from. If this is not available for this
* packet, this field is NULL (but this can only occur for manually injected
* packets).
*/
const BIO_ADDR *peer;
/*
* Local address the packet was sent to. If this is not available for this
* packet, this field is NULL.
*/
const BIO_ADDR *local;
/*
* This is the length of the datagram which contained this packet. Note that
* the datagram may have contained other packets than this. The intended use
* for this is so that the user can enforce minimum datagram sizes (e.g. for
* datagrams containing INITIAL packets), as required by RFC 9000.
*/
size_t datagram_len;
/* The PN which was decoded for the packet, if the packet has a PN field. */
QUIC_PN pn;
/*
* Time the packet was received, or ossl_time_zero() if the demuxer is not
* using a now() function.
*/
OSSL_TIME time;
/* The QRX which was used to receive the packet. */
OSSL_QRX *qrx;
/*
* The key epoch the packet was received with. Always 0 for non-1-RTT
* packets.
*/
uint64_t key_epoch;
} OSSL_QRX_PKT;
/*
* Tries to read a new decrypted packet from the QRX.
*
* On success, *pkt points to a OSSL_QRX_PKT structure. The structure should be
* freed when no longer needed by calling ossl_qrx_pkt_release(). The structure
* is refcounted; to gain extra references, call ossl_qrx_pkt_up_ref(). This
* will cause a corresponding number of calls to ossl_qrx_pkt_release() to be
* ignored.
*
* The resources referenced by (*pkt)->hdr, (*pkt)->hdr->data and (*pkt)->peer
* have the same lifetime as *pkt.
*
* Returns 1 on success and 0 on failure.
*/
int ossl_qrx_read_pkt(OSSL_QRX *qrx, OSSL_QRX_PKT **pkt);
/*
* Decrement the reference count for the given packet and frees it if the
* reference count drops to zero. No-op if pkt is NULL.
*/
void ossl_qrx_pkt_release(OSSL_QRX_PKT *pkt);
/* Increments the reference count for the given packet. */
void ossl_qrx_pkt_up_ref(OSSL_QRX_PKT *pkt);
/*
* Returns 1 if there are any already processed (i.e. decrypted) packets waiting
* to be read from the QRX.
*/
int ossl_qrx_processed_read_pending(OSSL_QRX *qrx);
/*
* Returns 1 if there are any unprocessed (i.e. not yet decrypted) packets
* waiting to be processed by the QRX. These may or may not result in
* successfully decrypted packets once processed. This indicates whether
* unprocessed data is buffered by the QRX, not whether any data is available in
* a kernel socket buffer.
*/
int ossl_qrx_unprocessed_read_pending(OSSL_QRX *qrx);
/*
* Returns the number of UDP payload bytes received from the network so far
* since the last time this counter was cleared. If clear is 1, clears the
* counter and returns the old value.
*
* The intended use of this is to allow callers to determine how much credit to
* add to their anti-amplification budgets. This is reported separately instead
* of in the OSSL_QRX_PKT structure so that a caller can apply
* anti-amplification credit as soon as a datagram is received, before it has
* necessarily read all processed packets contained within that datagram from
* the QRX.
*/
uint64_t ossl_qrx_get_bytes_received(OSSL_QRX *qrx, int clear);
/*
* Sets a callback which is called when a packet is received and being validated
* before being queued in the read queue. This is called after packet body
* decryption and authentication to prevent exposing side channels. pn_space is
* a QUIC_PN_SPACE_* value denoting which PN space the PN belongs to.
*
* If this callback returns 1, processing continues normally.
* If this callback returns 0, the packet is discarded.
*
* Other packets in the same datagram will still be processed where possible.
*
* The callback is optional and can be unset by passing NULL for cb.
* cb_arg is an opaque value passed to cb.
*/
typedef int (ossl_qrx_late_validation_cb)(QUIC_PN pn, int pn_space,
void *arg);
int ossl_qrx_set_late_validation_cb(OSSL_QRX *qrx,
ossl_qrx_late_validation_cb *cb,
void *cb_arg);
/*
* Forcibly injects a URXE which has been issued by the DEMUX into the QRX for
* processing. This can be used to pass a received datagram to the QRX if it
* would not be correctly routed to the QRX via standard DCID-based routing; for
* example, when handling an incoming Initial packet which is attempting to
* establish a new connection.
*/
void ossl_qrx_inject_urxe(OSSL_QRX *qrx, QUIC_URXE *e);
/*
* Decryption of 1-RTT packets must be explicitly enabled by calling this
* function. This is to comply with the requirement that we not process 1-RTT
* packets until the handshake is complete, even if we already have 1-RTT
* secrets. Even if a 1-RTT secret is provisioned for the QRX, incoming 1-RTT
* packets will be handled as though no key is available until this function is
* called. Calling this function will then requeue any such deferred packets for
* processing.
*/
void ossl_qrx_allow_1rtt_processing(OSSL_QRX *qrx);
/*
* Key Update (RX)
* ===============
*
* Key update on the RX side is a largely but not entirely automatic process.
*
* Key update is initially triggered by receiving a 1-RTT packet with a
* different Key Phase value. This could be caused by an attacker in the network
* flipping random bits, therefore such a key update is tentative until the
* packet payload is successfully decrypted and authenticated by the AEAD with
* the 'next' keys. These 'next' keys then become the 'current' keys and the
* 'current' keys then become the 'previous' keys. The 'previous' keys must be
* kept around temporarily as some packets may still be in flight in the network
* encrypted with the old keys. If the old Key Phase value is X and the new Key
* Phase Value is Y (where obviously X != Y), this creates an ambiguity as any
* new packet received with a KP of X could either be an attempt to initiate yet
* another key update right after the last one, or an old packet encrypted
* before the key update.
*
* RFC 9001 provides some guidance on handling this issue:
*
* Strategy 1:
* Three keys, disambiguation using packet numbers
*
* "A recovered PN that is lower than any PN from the current KP uses the
* previous packet protection keys; a recovered PN that is higher than any
* PN from the current KP requires use of the next packet protection
* keys."
*
* Strategy 2:
* Two keys and a timer
*
* "Alternatively, endpoints can retain only two sets of packet protection
* keys, swapping previous keys for next after enough time has passed to
* allow for reordering in the network. In this case, the KP bit alone can
* be used to select keys."
*
* Strategy 2 is more efficient (we can keep fewer cipher contexts around) and
* should cover all actually possible network conditions. It also allows a delay
* after we make the 'next' keys our 'current' keys before we generate new
* 'next' keys, which allows us to mitigate against malicious peers who try to
* initiate an excessive number of key updates.
*
* We therefore model the following state machine:
*
*
* PROVISIONED
* _______________________________
* | |
* UNPROVISIONED --|----> NORMAL <----------\ |------> DISCARDED
* | | | |
* | | | |
* | v | |
* | UPDATING | |
* | | | |
* | | | |
* | v | |
* | COOLDOWN | |
* | | | |
* | | | |
* | \---------------| |
* |_______________________________|
*
*
* The RX starts (once a secret has been provisioned) in the NORMAL state. In
* the NORMAL state, the current expected value of the Key Phase bit is
* recorded. When a flipped Key Phase bit is detected, the RX attempts to
* decrypt and authenticate the received packet with the 'next' keys rather than
* the 'current' keys. If (and only if) this authentication is successful, we
* move to the UPDATING state. (An attacker in the network could flip
* the Key Phase bit randomly, so it is essential we do nothing until AEAD
* authentication is complete.)
*
* In the UPDATING state, we know a key update is occurring and record
* the new Key Phase bit value as the newly current value, but we still keep the
* old keys around so that we can still process any packets which were still in
* flight when the key update was initiated. In the UPDATING state, a
* Key Phase bit value different to the current expected value is treated not as
* the initiation of another key update, but a reference to our old keys.
*
* Eventually we will be reasonably sure we are not going to receive any more
* packets with the old keys. At this point, we can transition to the COOLDOWN
* state. This transition occurs automatically after a certain amount of time;
* RFC 9001 recommends it be the PTO interval, which relates to our RTT to the
* peer. The duration also SHOULD NOT exceed three times the PTO to assist with
* maintaining PFS.
*
* In the COOLDOWN phase, the old keys have been securely erased and only one
* set of keys can be used: the current keys. If a packet is received with a Key
* Phase bit value different to the current Key Phase Bit value, this is treated
* as a request for a Key Update, but this request is ignored and the packet is
* treated as malformed. We do this to allow mitigation against malicious peers
* trying to initiate an excessive number of Key Updates. The timeout for the
* transition from UPDATING to COOLDOWN is recommended as adequate for
* this purpose in itself by the RFC, so the normal additional timeout value for
* the transition from COOLDOWN to normal is zero (immediate transition).
*
* A summary of each state:
*
* Epoch Exp KP Uses Keys KS0 KS1 If Non-Expected KP Bit
* ----- ------ --------- ------ ----- ----------------------
* NORMAL 0 0 Keyset 0 Gen 0 Gen 1 UPDATING
* UPDATING 1 1 Keyset 1 Gen 0 Gen 1 Use Keyset 0
* COOLDOWN 1 1 Keyset 1 Erased Gen 1 Ignore Packet (*)
*
* NORMAL 1 1 Keyset 1 Gen 2 Gen 1 UPDATING
* UPDATING 2 0 Keyset 0 Gen 2 Gen 1 Use Keyset 1
* COOLDOWN 2 0 Keyset 0 Gen 2 Erased Ignore Packet (*)
*
* (*) Actually implemented by attempting to decrypt the packet with the
* wrong keys (which ultimately has the same outcome), as recommended
* by RFC 9001 to avoid creating timing channels.
*
* Note that the key material for the next key generation ("key epoch") is
* always kept in the NORMAL state (necessary to avoid side-channel attacks).
* This material is derived during the transition from COOLDOWN to NORMAL.
*
* Note that when a peer initiates a Key Update, we MUST also initiate a Key
* Update as per the RFC. The caller is responsible for detecting this condition
* and making the necessary calls to the TX side by detecting changes to the
* return value of ossl_qrx_get_key_epoch().
*
* The above states (NORMAL, UPDATING, COOLDOWN) can themselves be
* considered substates of the PROVISIONED state. Providing a secret to the QRX
* for an EL transitions from UNPROVISIONED, the initial state, to PROVISIONED
* (NORMAL). Dropping key material for an EL transitions from whatever the
* current substate of the PROVISIONED state is to the DISCARDED state, which is
* the terminal state.
*
* Note that non-1RTT ELs cannot undergo key update, therefore a non-1RTT EL is
* always in the NORMAL substate if it is in the PROVISIONED state.
*/
/*
* Return the current RX key epoch for the 1-RTT encryption level. This is
* initially zero and is incremented by one for every Key Update successfully
* signalled by the peer. If the 1-RTT EL has not yet been provisioned or has
* been discarded, returns UINT64_MAX.
*
* A necessary implication of this API is that the least significant bit of the
* returned value corresponds to the currently expected Key Phase bit, though
* callers are not anticipated to have any need of this information.
*
* It is not possible for the returned value to overflow, as a QUIC connection
* cannot support more than 2**62 packet numbers, and a connection must be
* terminated if this limit is reached.
*
* The caller should use this function to detect when the key epoch has changed
* and use it to initiate a key update on the TX side.
*
* The value returned by this function increments specifically at the transition
* from the NORMAL to the UPDATING state discussed above.
*/
uint64_t ossl_qrx_get_key_epoch(OSSL_QRX *qrx);
/*
* Sets an optional callback which will be called when the key epoch changes.
*
* The callback is optional and can be unset by passing NULL for cb.
* cb_arg is an opaque value passed to cb. pn is the PN of the packet.
* Since key update is only supported for 1-RTT packets, the PN is always
* in the Application Data PN space.
*/
typedef void (ossl_qrx_key_update_cb)(QUIC_PN pn, void *arg);
int ossl_qrx_set_key_update_cb(OSSL_QRX *qrx,
ossl_qrx_key_update_cb *cb, void *cb_arg);
/*
* Relates to the 1-RTT encryption level. The caller should call this after the
* UPDATING state is reached, after a timeout to be determined by the caller.
*
* This transitions from the UPDATING state to the COOLDOWN state (if
* still in the UPDATING state). If normal is 1, then transitions from
* the COOLDOWN state to the NORMAL state. Both transitions can be performed at
* once if desired.
*
* If in the normal state, or if in the COOLDOWN state and normal is 0, this is
* a no-op and returns 1. Returns 0 if the 1-RTT EL has not been provisioned or
* has been dropped.
*
* It is essential that the caller call this within a few PTO intervals of a key
* update occurring (as detected by the caller in a call to
* ossl_qrx_key_get_key_epoch()), as otherwise the peer will not be able to
* perform a Key Update ever again.
*/
int ossl_qrx_key_update_timeout(OSSL_QRX *qrx, int normal);
/*
* Key Expiration
* ==============
*/
/*
* Returns the number of seemingly forged packets which have been received by
* the QRX. If this value reaches the value returned by
* ossl_qrx_get_max_epoch_forged_pkt_count() for a given EL, all further
* received encrypted packets for that EL will be discarded without processing.
*
* Note that the forged packet limit is for the connection lifetime, thus it is
* not reset by a key update. It is suggested that the caller terminate the
* connection a reasonable margin before the limit is reached. However, the
* exact limit imposed does vary by EL due to the possibility that different ELs
* use different AEADs.
*/
uint64_t ossl_qrx_get_cur_forged_pkt_count(OSSL_QRX *qrx);
/*
* Returns the maximum number of forged packets which the record layer will
* permit to be verified using this QRX instance.
*/
uint64_t ossl_qrx_get_max_forged_pkt_count(OSSL_QRX *qrx,
uint32_t enc_level);
# endif
#endif

View File

@ -0,0 +1,383 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_QUIC_RECORD_TX_H
# define OSSL_QUIC_RECORD_TX_H
# include <openssl/ssl.h>
# include "internal/quic_wire_pkt.h"
# include "internal/quic_types.h"
# include "internal/quic_record_util.h"
# ifndef OPENSSL_NO_QUIC
/*
* QUIC Record Layer - TX
* ======================
*/
typedef struct ossl_qtx_iovec_st {
const unsigned char *buf;
size_t buf_len;
} OSSL_QTX_IOVEC;
typedef struct ossl_qtx_st OSSL_QTX;
typedef int (*ossl_mutate_packet_cb)(const QUIC_PKT_HDR *hdrin,
const OSSL_QTX_IOVEC *iovecin, size_t numin,
QUIC_PKT_HDR **hdrout,
const OSSL_QTX_IOVEC **iovecout,
size_t *numout,
void *arg);
typedef void (*ossl_finish_mutate_cb)(void *arg);
typedef struct ossl_qtx_args_st {
OSSL_LIB_CTX *libctx;
const char *propq;
/* BIO to transmit to. */
BIO *bio;
/* Maximum datagram payload length (MDPL) for TX purposes. */
size_t mdpl;
} OSSL_QTX_ARGS;
/* Instantiates a new QTX. */
OSSL_QTX *ossl_qtx_new(const OSSL_QTX_ARGS *args);
/* Frees the QTX. */
void ossl_qtx_free(OSSL_QTX *qtx);
/* Set mutator callbacks for test framework support */
void ossl_qtx_set_mutator(OSSL_QTX *qtx, ossl_mutate_packet_cb mutatecb,
ossl_finish_mutate_cb finishmutatecb, void *mutatearg);
/* Setters for the msg_callback and the msg_callback_arg */
void ossl_qtx_set_msg_callback(OSSL_QTX *qtx, ossl_msg_cb msg_callback,
SSL *msg_callback_ssl);
void ossl_qtx_set_msg_callback_arg(OSSL_QTX *qtx, void *msg_callback_arg);
/*
* Secret Management
* -----------------
*/
/*
* Provides a secret to the QTX, which arises due to an encryption level change.
* enc_level is a QUIC_ENC_LEVEL_* value.
*
* This function can be used to initialise the INITIAL encryption level, but you
* should not do so directly; see the utility function
* ossl_qrl_provide_initial_secret() instead, which can initialise the INITIAL
* encryption level of a QRX and QTX simultaneously without duplicating certain
* key derivation steps.
*
* You must call this function for a given EL before transmitting packets at
* that EL using this QTX, otherwise ossl_qtx_write_pkt will fail.
*
* suite_id is a QRL_SUITE_* value which determines the AEAD function used for
* the QTX.
*
* The secret passed is used directly to derive the "quic key", "quic iv" and
* "quic hp" values.
*
* secret_len is the length of the secret buffer in bytes. The buffer must be
* sized correctly to the chosen suite, else the function fails.
*
* This function can only be called once for a given EL, except for the INITIAL
* EL, as the INITIAL EL can need to be rekeyed if connection retry occurs.
* Subsequent calls for non-INITIAL ELs fail. Calls made after a corresponding
* call to ossl_qtx_discard_enc_level for a given EL also fail, including for
* the INITIAL EL. The secret for a non-INITIAL EL cannot be changed after it is
* set because QUIC has no facility for introducing additional key material
* after an EL is setup. (QUIC key updates generate new keys from existing key
* material and do not introduce new entropy into a connection's key material.)
*
* Returns 1 on success or 0 on failure.
*/
int ossl_qtx_provide_secret(OSSL_QTX *qtx,
uint32_t enc_level,
uint32_t suite_id,
EVP_MD *md,
const unsigned char *secret,
size_t secret_len);
/*
* Informs the QTX that it can now discard key material for a given EL. The QTX
* will no longer be able to generate packets at that EL. This function is
* idempotent and succeeds if the EL has already been discarded.
*
* Returns 1 on success and 0 on failure.
*/
int ossl_qtx_discard_enc_level(OSSL_QTX *qtx, uint32_t enc_level);
/* Returns 1 if the given encryption level is provisioned. */
int ossl_qtx_is_enc_level_provisioned(OSSL_QTX *qtx, uint32_t enc_level);
/*
* Given the value ciphertext_len representing an encrypted packet payload
* length in bytes, determines how many plaintext bytes it will decrypt to.
* Returns 0 if the specified EL is not provisioned or ciphertext_len is too
* small. The result is written to *plaintext_len.
*/
int ossl_qtx_calculate_plaintext_payload_len(OSSL_QTX *qtx, uint32_t enc_level,
size_t ciphertext_len,
size_t *plaintext_len);
/*
* Given the value plaintext_len represented a plaintext packet payload length
* in bytes, determines how many ciphertext bytes it will encrypt to. The value
* output does not include packet headers. Returns 0 if the specified EL is not
* provisioned. The result is written to *ciphertext_len.
*/
int ossl_qtx_calculate_ciphertext_payload_len(OSSL_QTX *qtx, uint32_t enc_level,
size_t plaintext_len,
size_t *ciphertext_len);
uint32_t ossl_qrl_get_suite_cipher_tag_len(uint32_t suite_id);
/*
* Packet Transmission
* -------------------
*/
typedef struct ossl_qtx_pkt_st {
/* Logical packet header to be serialized. */
QUIC_PKT_HDR *hdr;
/*
* iovecs expressing the logical packet payload buffer. Zero-length entries
* are permitted.
*/
const OSSL_QTX_IOVEC *iovec;
size_t num_iovec;
/* Destination address. Will be passed through to the BIO if non-NULL. */
const BIO_ADDR *peer;
/*
* Local address (optional). Specify as non-NULL only if TX BIO
* has local address support enabled.
*/
const BIO_ADDR *local;
/*
* Logical PN. Used for encryption. This will automatically be encoded to
* hdr->pn, which need not be initialized.
*/
QUIC_PN pn;
/* Packet flags. Zero or more OSSL_QTX_PKT_FLAG_* values. */
uint32_t flags;
} OSSL_QTX_PKT;
/*
* More packets will be written which should be coalesced into a single
* datagram; do not send this packet yet. To use this, set this flag for all
* packets but the final packet in a datagram, then send the final packet
* without this flag set.
*
* This flag is not a guarantee and the QTX may transmit immediately anyway if
* it is not possible to fit any more packets in the current datagram.
*
* If the caller change its mind and needs to cause a packet queued with
* COALESCE after having passed it to this function but without writing another
* packet, it should call ossl_qtx_flush_pkt().
*/
#define OSSL_QTX_PKT_FLAG_COALESCE (1U << 0)
/*
* Writes a packet.
*
* *pkt need be valid only for the duration of the call to this function.
*
* pkt->hdr->data and pkt->hdr->len are unused. The payload buffer is specified
* via an array of OSSL_QTX_IOVEC structures. The API is designed to support
* single-copy transmission; data is copied from the iovecs as it is encrypted
* into an internal staging buffer for transmission.
*
* The function may modify and clobber pkt->hdr->data, pkt->hdr->len,
* pkt->hdr->key_phase and pkt->hdr->pn for its own internal use. No other
* fields of pkt or pkt->hdr will be modified.
*
* It is the callers responsibility to determine how long the PN field in the
* encoded packet should be by setting pkt->hdr->pn_len. This function takes
* care of the PN encoding. Set pkt->pn to the desired PN.
*
* Note that 1-RTT packets do not have a DCID Length field, therefore the DCID
* length must be understood contextually. This function assumes the caller
* knows what it is doing and will serialize a DCID of whatever length is given.
* It is the caller's responsibility to ensure it uses a consistent DCID length
* for communication with any given set of remote peers.
*
* The packet is queued regardless of whether it is able to be sent immediately.
* This enables packets to be batched and sent at once on systems which support
* system calls to send multiple datagrams in a single system call (see
* BIO_sendmmsg). To flush queued datagrams to the network, see
* ossl_qtx_flush_net().
*
* Returns 1 on success or 0 on failure.
*/
int ossl_qtx_write_pkt(OSSL_QTX *qtx, const OSSL_QTX_PKT *pkt);
/*
* Finish any incomplete datagrams for transmission which were flagged for
* coalescing. If there is no current coalescing datagram, this is a no-op.
*/
void ossl_qtx_finish_dgram(OSSL_QTX *qtx);
/*
* (Attempt to) flush any datagrams which are queued for transmission. Note that
* this does not cancel coalescing; call ossl_qtx_finish_dgram() first if that
* is desired. The queue is drained into the OS's sockets as much as possible.
* To determine if there is still data to be sent after calling this function,
* use ossl_qtx_get_queue_len_bytes().
*
* Returns one of the following values:
*
* QTX_FLUSH_NET_RES_OK
* Either no packets are currently queued for transmission,
* or at least one packet was successfully submitted.
*
* QTX_FLUSH_NET_RES_TRANSIENT_FAIL
* The underlying network write BIO indicated a transient error
* (e.g. buffers full).
*
* QTX_FLUSH_NET_RES_PERMANENT_FAIL
* Internal error (e.g. assertion or allocation error)
* or the underlying network write BIO indicated a non-transient
* error.
*/
#define QTX_FLUSH_NET_RES_OK 1
#define QTX_FLUSH_NET_RES_TRANSIENT_FAIL (-1)
#define QTX_FLUSH_NET_RES_PERMANENT_FAIL (-2)
int ossl_qtx_flush_net(OSSL_QTX *qtx);
/*
* Diagnostic function. If there is any datagram pending transmission, pops it
* and writes the details of the datagram as they would have been passed to
* *msg. Returns 1, or 0 if there are no datagrams pending. For test use only.
*/
int ossl_qtx_pop_net(OSSL_QTX *qtx, BIO_MSG *msg);
/* Returns number of datagrams which are fully-formed but not yet sent. */
size_t ossl_qtx_get_queue_len_datagrams(OSSL_QTX *qtx);
/*
* Returns number of payload bytes across all datagrams which are fully-formed
* but not yet sent. Does not count any incomplete coalescing datagram.
*/
size_t ossl_qtx_get_queue_len_bytes(OSSL_QTX *qtx);
/*
* Returns number of bytes in the current coalescing datagram, or 0 if there is
* no current coalescing datagram. Returns 0 after a call to
* ossl_qtx_finish_dgram().
*/
size_t ossl_qtx_get_cur_dgram_len_bytes(OSSL_QTX *qtx);
/*
* Returns number of queued coalesced packets which have not been put into a
* datagram yet. If this is non-zero, ossl_qtx_flush_pkt() needs to be called.
*/
size_t ossl_qtx_get_unflushed_pkt_count(OSSL_QTX *qtx);
/*
* Change the BIO being used by the QTX. May be NULL if actual transmission is
* not currently required. Does not up-ref the BIO; the caller is responsible
* for ensuring the lifetime of the BIO exceeds the lifetime of the QTX.
*/
void ossl_qtx_set_bio(OSSL_QTX *qtx, BIO *bio);
/* Changes the MDPL. */
int ossl_qtx_set_mdpl(OSSL_QTX *qtx, size_t mdpl);
/* Retrieves the current MDPL. */
size_t ossl_qtx_get_mdpl(OSSL_QTX *qtx);
/*
* Key Update
* ----------
*
* For additional discussion of key update considerations, see QRX header file.
*/
/*
* Triggers a key update. The key update will be started by inverting the Key
* Phase bit of the next packet transmitted; no key update occurs until the next
* packet is transmitted. Thus, this function should generally be called
* immediately before queueing the next packet.
*
* There are substantial requirements imposed by RFC 9001 on under what
* circumstances a key update can be initiated. The caller is responsible for
* meeting most of these requirements. For example, this function cannot be
* called too soon after a previous key update has occurred. Key updates also
* cannot be initiated until the 1-RTT encryption level is reached.
*
* As a sanity check, this function will fail and return 0 if the non-1RTT
* encryption levels have not yet been dropped.
*
* The caller may decide itself to initiate a key update, but it also MUST
* initiate a key update where it detects that the peer has initiated a key
* update. The caller is responsible for initiating a TX key update by calling
* this function in this circumstance; thus, the caller is responsible for
* coupling the RX and TX QUIC record layers in this way.
*/
int ossl_qtx_trigger_key_update(OSSL_QTX *qtx);
/*
* Key Expiration
* --------------
*/
/*
* Returns the number of packets which have been encrypted for transmission with
* the current set of TX keys (the current "TX key epoch"). Reset to zero after
* a key update and incremented for each packet queued. If enc_level is not
* valid or relates to an EL which is not currently available, returns
* UINT64_MAX.
*/
uint64_t ossl_qtx_get_cur_epoch_pkt_count(OSSL_QTX *qtx, uint32_t enc_level);
/*
* Returns the maximum number of packets which the record layer will permit to
* be encrypted using the current set of TX keys. If this limit is reached (that
* is, if the counter returned by ossl_qrx_tx_get_cur_epoch_pkt_count() reaches
* this value), as a safety measure, the QTX will not permit any further packets
* to be queued. All calls to ossl_qrx_write_pkt that try to send packets of a
* kind which need to be encrypted will fail. It is not possible to recover from
* this condition and the QTX must then be destroyed; therefore, callers should
* ensure they always trigger a key update well in advance of reaching this
* limit.
*
* The value returned by this function is based on the ciphersuite configured
* for the given encryption level. If keys have not been provisioned for the
* specified enc_level or the enc_level argument is invalid, this function
* returns UINT64_MAX, which is not a valid value. Note that it is not possible
* to perform a key update at any encryption level other than 1-RTT, therefore
* if this limit is reached at earlier encryption levels (which should not be
* possible) the connection must be terminated. Since this condition precludes
* the transmission of further packets, the only possible signalling of such an
* error condition to a peer is a Stateless Reset packet.
*/
uint64_t ossl_qtx_get_max_epoch_pkt_count(OSSL_QTX *qtx, uint32_t enc_level);
/*
* Get the 1-RTT EL key epoch number for the QTX. This is intended for
* diagnostic purposes. Returns 0 if 1-RTT EL is not provisioned yet.
*/
uint64_t ossl_qtx_get_key_epoch(OSSL_QTX *qtx);
# endif
#endif

View File

@ -0,0 +1,116 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_QUIC_RECORD_UTIL_H
# define OSSL_QUIC_RECORD_UTIL_H
# include <openssl/ssl.h>
# include "internal/quic_types.h"
# ifndef OPENSSL_NO_QUIC
struct ossl_qrx_st;
struct ossl_qtx_st;
/*
* QUIC Key Derivation Utilities
* =============================
*/
/* HKDF-Extract(salt, IKM) (RFC 5869) */
int ossl_quic_hkdf_extract(OSSL_LIB_CTX *libctx,
const char *propq,
const EVP_MD *md,
const unsigned char *salt, size_t salt_len,
const unsigned char *ikm, size_t ikm_len,
unsigned char *out, size_t out_len);
/*
* A QUIC client sends its first INITIAL packet with a random DCID, which
* is used to compute the secrets used for INITIAL packet encryption in both
* directions (both client-to-server and server-to-client).
*
* This function performs the necessary DCID-based key derivation, and then
* provides the derived key material for the INITIAL encryption level to a QRX
* instance, a QTX instance, or both.
*
* This function derives the necessary key material and then:
* - if qrx is non-NULL, provides the appropriate secret to it;
* - if qtx is non-NULL, provides the appropriate secret to it.
*
* If both qrx and qtx are NULL, this is a no-op. This function is equivalent to
* making the appropriate calls to ossl_qrx_provide_secret() and
* ossl_qtx_provide_secret().
*
* It is possible to use a QRX or QTX without ever calling this, for example if
* there is no desire to handle INITIAL packets (e.g. if a QRX/QTX is
* instantiated to succeed a previous QRX/QTX and handle a connection which is
* already established). However in this case you should make sure you call
* ossl_qrx_discard_enc_level(); see the header for that function for more
* details. Calling ossl_qtx_discard_enc_level() is not essential but could
* protect against programming errors.
*
* Returns 1 on success or 0 on error.
*/
int ossl_quic_provide_initial_secret(OSSL_LIB_CTX *libctx,
const char *propq,
const QUIC_CONN_ID *dst_conn_id,
int is_server,
struct ossl_qrx_st *qrx,
struct ossl_qtx_st *qtx);
/*
* QUIC Record Layer Ciphersuite Info
* ==================================
*/
/* Available QUIC Record Layer (QRL) ciphersuites. */
# define QRL_SUITE_AES128GCM 1 /* SHA256 */
# define QRL_SUITE_AES256GCM 2 /* SHA384 */
# define QRL_SUITE_CHACHA20POLY1305 3 /* SHA256 */
/* Returns cipher name in bytes or NULL if suite ID is invalid. */
const char *ossl_qrl_get_suite_cipher_name(uint32_t suite_id);
/* Returns hash function name in bytes or NULL if suite ID is invalid. */
const char *ossl_qrl_get_suite_md_name(uint32_t suite_id);
/* Returns secret length in bytes or 0 if suite ID is invalid. */
uint32_t ossl_qrl_get_suite_secret_len(uint32_t suite_id);
/* Returns key length in bytes or 0 if suite ID is invalid. */
uint32_t ossl_qrl_get_suite_cipher_key_len(uint32_t suite_id);
/* Returns IV length in bytes or 0 if suite ID is invalid. */
uint32_t ossl_qrl_get_suite_cipher_iv_len(uint32_t suite_id);
/* Returns AEAD auth tag length in bytes or 0 if suite ID is invalid. */
uint32_t ossl_qrl_get_suite_cipher_tag_len(uint32_t suite_id);
/* Returns a QUIC_HDR_PROT_CIPHER_* value or 0 if suite ID is invalid. */
uint32_t ossl_qrl_get_suite_hdr_prot_cipher_id(uint32_t suite_id);
/* Returns header protection key length in bytes or 0 if suite ID is invalid. */
uint32_t ossl_qrl_get_suite_hdr_prot_key_len(uint32_t suite_id);
/*
* Returns maximum number of packets which may be safely encrypted with a suite
* or 0 if suite ID is invalid.
*/
uint64_t ossl_qrl_get_suite_max_pkt(uint32_t suite_id);
/*
* Returns maximum number of RX'd packets which may safely fail AEAD decryption
* for a given suite or 0 if suite ID is invalid.
*/
uint64_t ossl_qrl_get_suite_max_forged_pkt(uint32_t suite_id);
# endif
#endif

View File

@ -0,0 +1,21 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_QUIC_RX_DEPACK_H
# define OSSL_QUIC_RX_DEPACK_H
# include "internal/quic_channel.h"
# ifndef OPENSSL_NO_QUIC
int ossl_quic_handle_frames(QUIC_CHANNEL *qc, OSSL_QRX_PKT *qpacket);
# endif
#endif

View File

@ -0,0 +1,151 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_QUIC_SF_LIST_H
# define OSSL_QUIC_SF_LIST_H
#include "internal/common.h"
#include "internal/uint_set.h"
#include "internal/quic_record_rx.h"
/*
* Stream frame list
* =================
*
* This data structure supports similar operations as uint64 set but
* it has slightly different invariants and also carries data associated with
* the ranges in the list.
*
* Operations:
* Insert frame (optimized insertion at the beginning and at the end).
* Iterated peek into the frame(s) from the beginning.
* Dropping frames from the beginning up to an offset (exclusive).
*
* Invariant: The frames in the list are sorted by the start and end bounds.
* Invariant: There are no fully overlapping frames or frames that would
* be fully encompassed by another frame in the list.
* Invariant: No frame has start > end.
* Invariant: The range start is inclusive the end is exclusive to be
* able to mark an empty frame.
* Invariant: The offset never points further than into the first frame.
*/
# ifndef OPENSSL_NO_QUIC
typedef struct stream_frame_st STREAM_FRAME;
typedef struct sframe_list_st {
STREAM_FRAME *head, *tail;
/* Is the tail frame final. */
unsigned int fin;
/* Number of stream frames in the list. */
size_t num_frames;
/* Offset of data not yet dropped */
uint64_t offset;
/* Is head locked ? */
int head_locked;
/* Cleanse data on release? */
int cleanse;
} SFRAME_LIST;
/*
* Initializes the stream frame list fl.
*/
void ossl_sframe_list_init(SFRAME_LIST *fl);
/*
* Destroys the stream frame list fl releasing any data
* still present inside it.
*/
void ossl_sframe_list_destroy(SFRAME_LIST *fl);
/*
* Insert a stream frame data into the list.
* The data covers an offset range (range.start is inclusive,
* range.end is exclusive).
* fin should be set if this is the final frame of the stream.
* Returns an error if a frame cannot be inserted - due to
* STREAM_FRAME allocation error, or in case of erroneous
* fin flag (this is an ossl_assert() check so a caller must
* check it on its own too).
*/
int ossl_sframe_list_insert(SFRAME_LIST *fl, UINT_RANGE *range,
OSSL_QRX_PKT *pkt,
const unsigned char *data, int fin);
/*
* Iterator to peek at the contiguous frames at the beginning
* of the frame list fl.
* The *data covers an offset range (range.start is inclusive,
* range.end is exclusive).
* *fin is set if this is the final frame of the stream.
* Opaque iterator *iter can be used to peek at the subsequent
* frame if there is any without any gap before it.
* Returns 1 on success.
* Returns 0 if there is no further contiguous frame. In that
* case *fin is set, if the end of the stream is reached.
*/
int ossl_sframe_list_peek(const SFRAME_LIST *fl, void **iter,
UINT_RANGE *range, const unsigned char **data,
int *fin);
/*
* Drop all frames up to the offset limit.
* Also unlocks the head frame if locked.
* Returns 1 on success.
* Returns 0 when trying to drop frames at offsets that were not
* received yet. (ossl_assert() is used to check, so this is an invalid call.)
*/
int ossl_sframe_list_drop_frames(SFRAME_LIST *fl, uint64_t limit);
/*
* Locks and returns the head frame of fl if it is readable - read offset is
* at the beginning or middle of the frame.
* range is set to encompass the not yet read part of the head frame,
* data pointer is set to appropriate offset within the frame if the read
* offset points in the middle of the frame,
* fin is set to 1 if the head frame is also the tail frame.
* Returns 1 on success, 0 if there is no readable data or the head
* frame is already locked.
*/
int ossl_sframe_list_lock_head(SFRAME_LIST *fl, UINT_RANGE *range,
const unsigned char **data,
int *fin);
/*
* Just returns whether the head frame is locked by previous
* ossl_sframe_list_lock_head() call.
*/
int ossl_sframe_list_is_head_locked(SFRAME_LIST *fl);
/*
* Callback function type to write stream frame data to some
* side storage before the packet containing the frame data
* is released.
* It should return 1 on success or 0 if there is not enough
* space available in the side storage.
*/
typedef int (sframe_list_write_at_cb)(uint64_t logical_offset,
const unsigned char *buf,
size_t buf_len,
void *cb_arg);
/*
* Move the frame data in all the stream frames in the list fl
* from the packets to the side storage using the write_at_cb
* callback.
* Returns 1 if all the calls to the callback return 1.
* If the callback returns 0, the function stops processing further
* frames and returns 0.
*/
int ossl_sframe_list_move_data(SFRAME_LIST *fl,
sframe_list_write_at_cb *write_at_cb,
void *cb_arg);
# endif
#endif

View File

@ -0,0 +1,132 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_QUIC_SSL_H
# define OSSL_QUIC_SSL_H
# include <openssl/ssl.h>
# include <openssl/bio.h>
# include "internal/quic_record_rx.h" /* OSSL_QRX */
# include "internal/quic_ackm.h" /* OSSL_ACKM */
# include "internal/quic_channel.h" /* QUIC_CHANNEL */
# ifndef OPENSSL_NO_QUIC
__owur SSL *ossl_quic_new(SSL_CTX *ctx);
__owur int ossl_quic_init(SSL *s);
void ossl_quic_deinit(SSL *s);
void ossl_quic_free(SSL *s);
int ossl_quic_reset(SSL *s);
int ossl_quic_clear(SSL *s);
__owur int ossl_quic_accept(SSL *s);
__owur int ossl_quic_connect(SSL *s);
__owur int ossl_quic_read(SSL *s, void *buf, size_t len, size_t *readbytes);
__owur int ossl_quic_peek(SSL *s, void *buf, size_t len, size_t *readbytes);
__owur int ossl_quic_write(SSL *s, const void *buf, size_t len, size_t *written);
__owur long ossl_quic_ctrl(SSL *s, int cmd, long larg, void *parg);
__owur long ossl_quic_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg);
__owur long ossl_quic_callback_ctrl(SSL *s, int cmd, void (*fp) (void));
__owur long ossl_quic_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp) (void));
__owur size_t ossl_quic_pending(const SSL *s);
__owur int ossl_quic_key_update(SSL *s, int update_type);
__owur int ossl_quic_get_key_update_type(const SSL *s);
__owur const SSL_CIPHER *ossl_quic_get_cipher_by_char(const unsigned char *p);
__owur int ossl_quic_num_ciphers(void);
__owur const SSL_CIPHER *ossl_quic_get_cipher(unsigned int u);
int ossl_quic_renegotiate_check(SSL *ssl, int initok);
typedef struct quic_conn_st QUIC_CONNECTION;
typedef struct quic_xso_st QUIC_XSO;
int ossl_quic_do_handshake(SSL *s);
void ossl_quic_set_connect_state(SSL *s);
void ossl_quic_set_accept_state(SSL *s);
__owur int ossl_quic_has_pending(const SSL *s);
__owur int ossl_quic_handle_events(SSL *s);
__owur int ossl_quic_get_event_timeout(SSL *s, struct timeval *tv,
int *is_infinite);
OSSL_TIME ossl_quic_get_event_deadline(SSL *s);
__owur int ossl_quic_get_rpoll_descriptor(SSL *s, BIO_POLL_DESCRIPTOR *d);
__owur int ossl_quic_get_wpoll_descriptor(SSL *s, BIO_POLL_DESCRIPTOR *d);
__owur int ossl_quic_get_net_read_desired(SSL *s);
__owur int ossl_quic_get_net_write_desired(SSL *s);
__owur int ossl_quic_get_error(const SSL *s, int i);
__owur int ossl_quic_want(const SSL *s);
__owur int ossl_quic_conn_get_blocking_mode(const SSL *s);
__owur int ossl_quic_conn_set_blocking_mode(SSL *s, int blocking);
__owur int ossl_quic_conn_shutdown(SSL *s, uint64_t flags,
const SSL_SHUTDOWN_EX_ARGS *args,
size_t args_len);
__owur int ossl_quic_conn_stream_conclude(SSL *s);
void ossl_quic_conn_set0_net_rbio(SSL *s, BIO *net_wbio);
void ossl_quic_conn_set0_net_wbio(SSL *s, BIO *net_wbio);
BIO *ossl_quic_conn_get_net_rbio(const SSL *s);
BIO *ossl_quic_conn_get_net_wbio(const SSL *s);
__owur int ossl_quic_conn_set_initial_peer_addr(SSL *s,
const BIO_ADDR *peer_addr);
__owur SSL *ossl_quic_conn_stream_new(SSL *s, uint64_t flags);
__owur SSL *ossl_quic_get0_connection(SSL *s);
__owur int ossl_quic_get_stream_type(SSL *s);
__owur uint64_t ossl_quic_get_stream_id(SSL *s);
__owur int ossl_quic_is_stream_local(SSL *s);
__owur int ossl_quic_set_default_stream_mode(SSL *s, uint32_t mode);
__owur SSL *ossl_quic_detach_stream(SSL *s);
__owur int ossl_quic_attach_stream(SSL *conn, SSL *stream);
__owur int ossl_quic_set_incoming_stream_policy(SSL *s, int policy,
uint64_t aec);
__owur SSL *ossl_quic_accept_stream(SSL *s, uint64_t flags);
__owur size_t ossl_quic_get_accept_stream_queue_len(SSL *s);
__owur int ossl_quic_stream_reset(SSL *ssl,
const SSL_STREAM_RESET_ARGS *args,
size_t args_len);
__owur int ossl_quic_get_stream_read_state(SSL *ssl);
__owur int ossl_quic_get_stream_write_state(SSL *ssl);
__owur int ossl_quic_get_stream_read_error_code(SSL *ssl,
uint64_t *app_error_code);
__owur int ossl_quic_get_stream_write_error_code(SSL *ssl,
uint64_t *app_error_code);
__owur int ossl_quic_get_conn_close_info(SSL *ssl,
SSL_CONN_CLOSE_INFO *info,
size_t info_len);
uint64_t ossl_quic_set_options(SSL *s, uint64_t opts);
uint64_t ossl_quic_clear_options(SSL *s, uint64_t opts);
uint64_t ossl_quic_get_options(const SSL *s);
/* Modifies write buffer size for a stream. */
__owur int ossl_quic_set_write_buffer_size(SSL *s, size_t size);
/*
* Used to override ossl_time_now() for debug purposes. While this may be
* overridden at any time, expect strange results if you change it after
* connecting.
*/
int ossl_quic_conn_set_override_now_cb(SSL *s,
OSSL_TIME (*now_cb)(void *arg),
void *now_cb_arg);
/*
* Condvar waiting in the assist thread doesn't support time faking as it relies
* on the OS's notion of time, thus this is used in test code to force a
* spurious wakeup instead.
*/
void ossl_quic_conn_force_assist_thread_wake(SSL *s);
/* For use by tests only. */
QUIC_CHANNEL *ossl_quic_conn_get_channel(SSL *s);
int ossl_quic_has_pending(const SSL *s);
int ossl_quic_get_shutdown(const SSL *s);
# endif
#endif

View File

@ -0,0 +1,40 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_QUIC_STATS_H
# define OSSL_QUIC_STATS_H
# include <openssl/ssl.h>
# include "internal/time.h"
# ifndef OPENSSL_NO_QUIC
typedef struct ossl_statm_st {
OSSL_TIME smoothed_rtt, latest_rtt, min_rtt, rtt_variance;
char have_first_sample;
} OSSL_STATM;
typedef struct ossl_rtt_info_st {
/* As defined in RFC 9002. */
OSSL_TIME smoothed_rtt, latest_rtt, rtt_variance, min_rtt;
} OSSL_RTT_INFO;
int ossl_statm_init(OSSL_STATM *statm);
void ossl_statm_destroy(OSSL_STATM *statm);
void ossl_statm_get_rtt_info(OSSL_STATM *statm, OSSL_RTT_INFO *rtt_info);
void ossl_statm_update_rtt(OSSL_STATM *statm,
OSSL_TIME ack_delay,
OSSL_TIME override_latest_rtt);
# endif
#endif

View File

@ -0,0 +1,429 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_INTERNAL_QUIC_STREAM_H
# define OSSL_INTERNAL_QUIC_STREAM_H
# pragma once
#include "internal/e_os.h"
#include "internal/time.h"
#include "internal/quic_types.h"
#include "internal/quic_wire.h"
#include "internal/quic_record_tx.h"
#include "internal/quic_record_rx.h"
#include "internal/quic_fc.h"
#include "internal/quic_statm.h"
# ifndef OPENSSL_NO_QUIC
/*
* QUIC Send Stream
* ================
*
* The QUIC Send Stream Manager (QUIC_SSTREAM) is responsible for:
*
* - accepting octet strings of stream data;
*
* - generating corresponding STREAM frames;
*
* - receiving notifications of lost frames, in order to generate new STREAM
* frames for the lost data;
*
* - receiving notifications of acknowledged frames, in order to internally
* reuse memory used to store acknowledged stream data;
*
* - informing the caller of how much more stream data it can accept into
* its internal buffers, so as to ensure that the amount of unacknowledged
* data which can be written to a stream is not infinite and to allow the
* caller to manifest backpressure conditions to the user.
*
* The QUIC_SSTREAM is instantiated once for every stream with a send component
* (i.e., for a unidirectional send stream or for the send component of a
* bidirectional stream).
*
* Note: The terms 'TX' and 'RX' are used when referring to frames, packets and
* datagrams. The terms 'send' and 'receive' are used when referring to the
* stream abstraction. Applications send; we transmit.
*/
typedef struct quic_sstream_st QUIC_SSTREAM;
/*
* Instantiates a new QUIC_SSTREAM. init_buf_size specifies the initial size of
* the stream data buffer in bytes, which must be positive.
*/
QUIC_SSTREAM *ossl_quic_sstream_new(size_t init_buf_size);
/*
* Frees a QUIC_SSTREAM and associated stream data storage.
*
* Any iovecs returned by ossl_quic_sstream_get_stream_frame cease to be valid after
* calling this function.
*/
void ossl_quic_sstream_free(QUIC_SSTREAM *qss);
/*
* (For TX packetizer use.) Retrieves information about application stream data
* which is ready for transmission.
*
* *hdr is filled with the logical offset, maximum possible length of stream
* data which can be transmitted, and a pointer to the stream data to be
* transmitted. is_fin is set to 1 if hdr->offset + hdr->len is the final size
* of the stream and 0 otherwise. hdr->stream_id is not set; the caller must set
* it.
*
* The caller is not obligated to send all of the data. If the caller does not
* send all of the data, the caller must reduce hdr->len before serializing the
* header structure and must ensure that hdr->is_fin is cleared.
*
* hdr->has_explicit_len is always set. It is the caller's responsibility to
* clear this if it wants to use the optimization of omitting the length field,
* as only the caller can know when this optimization can be performed.
*
* *num_iov must be set to the size of the iov array at call time. When this
* function returns successfully, it is updated to the number of iov entries
* which have been written.
*
* The stream data may be split across up to two IOVs due to internal ring
* buffer organisation. The sum of the lengths of the IOVs and the value written
* to hdr->len will always match. If the caller decides to send less than
* hdr->len of stream data, it must adjust the IOVs accordingly. This may be
* done by updating hdr->len and then calling the utility function
* ossl_quic_sstream_adjust_iov().
*
* After committing one or more bytes returned by ossl_quic_sstream_get_stream_frame to a
* packet, call ossl_quic_sstream_mark_transmitted with the inclusive range of logical
* byte numbers of the transmitted bytes (i.e., hdr->offset, hdr->offset +
* hdr->len - 1). If you do not call ossl_quic_sstream_mark_transmitted, the next call to
* ossl_quic_sstream_get_stream_frame will return the same data (or potentially the same
* and more, if more data has been appended by the application).
*
* It is the caller's responsibility to clamp the length of data which this
* function indicates is available according to other concerns, such as
* stream-level flow control, connection-level flow control, or the applicable
* maximum datagram payload length (MDPL) for a packet under construction.
*
* The skip argument can usually be given as zero. If it is non-zero, this
* function outputs a range which would be output if it were called again after
* calling ossl_quic_sstream_mark_transmitted() with the returned range, repeated 'skip'
* times, and so on. This may be useful for callers which wish to enumerate
* available stream frames and batch their calls to ossl_quic_sstream_mark_transmitted at
* a later time.
*
* On success, this function will never write *num_iov with a value other than
* 0, 1 or 2. A *num_iov value of 0 can only occurs when hdr->is_fin is set (for
* example, when a stream is closed after all existing data has been sent, and
* without sending any more data); otherwise the function returns 0 as there is
* nothing useful to report.
*
* Returns 1 on success and 0 if there is no stream data available for
* transmission, or on other error (such as if the caller provides fewer
* than two IOVs.)
*/
int ossl_quic_sstream_get_stream_frame(QUIC_SSTREAM *qss,
size_t skip,
OSSL_QUIC_FRAME_STREAM *hdr,
OSSL_QTX_IOVEC *iov,
size_t *num_iov);
/*
* Returns 1 if there is data pending transmission. Equivalent to calling
* ossl_quic_sstream_get_stream_frame and seeing if it succeeds.
*/
int ossl_quic_sstream_has_pending(QUIC_SSTREAM *qss);
/*
* Returns the current size of the stream; i.e., the number of bytes which have
* been appended to the stream so far.
*/
uint64_t ossl_quic_sstream_get_cur_size(QUIC_SSTREAM *qss);
/*
* (For TX packetizer use.) Marks a logical range of the send stream as having
* been transmitted.
*
* 0 denotes the first byte ever sent on the stream. The start and end values
* are both inclusive, therefore all calls to this function always mark at least
* one byte as being transmitted; if no bytes have been transmitted, do not call
* this function.
*
* If the STREAM frame sent had the FIN bit set, you must also call
* ossl_quic_sstream_mark_transmitted_fin() after calling this function.
*
* If you sent a zero-length STREAM frame with the FIN bit set, you need only
* call ossl_quic_sstream_mark_transmitted_fin() and must not call this function.
*
* Returns 1 on success and 0 on error (e.g. if end < start).
*/
int ossl_quic_sstream_mark_transmitted(QUIC_SSTREAM *qss,
uint64_t start,
uint64_t end);
/*
* (For TX packetizer use.) Marks a STREAM frame with the FIN bit set as having
* been transmitted. final_size is the final size of the stream (i.e., the value
* offset + len of the transmitted STREAM frame).
*
* This function fails returning 0 if ossl_quic_sstream_fin() has not been called or if
* final_size is not correct. The final_size argument is not strictly needed by
* the QUIC_SSTREAM but is required as a sanity check.
*/
int ossl_quic_sstream_mark_transmitted_fin(QUIC_SSTREAM *qss,
uint64_t final_size);
/*
* (RX/ACKM use.) Marks a logical range of the send stream as having been lost.
* The send stream will return the lost data for retransmission on a future call
* to ossl_quic_sstream_get_stream_frame. The start and end values denote logical byte
* numbers and are inclusive.
*
* If the lost frame had the FIN bit set, you must also call
* ossl_quic_sstream_mark_lost_fin() after calling this function.
*
* Returns 1 on success and 0 on error (e.g. if end < start).
*/
int ossl_quic_sstream_mark_lost(QUIC_SSTREAM *qss,
uint64_t start,
uint64_t end);
/*
* (RX/ACKM use.) Informs the QUIC_SSTREAM that a STREAM frame with the FIN bit
* set was lost.
*
* Returns 1 on success and 0 on error.
*/
int ossl_quic_sstream_mark_lost_fin(QUIC_SSTREAM *qss);
/*
* (RX/ACKM use.) Marks a logical range of the send stream as having been
* acknowledged, meaning that the storage for the data in that range of the
* stream can be now recycled and neither that logical range of the stream nor
* any subset of it can be retransmitted again. The start and end values are
* inclusive.
*
* If the acknowledged frame had the FIN bit set, you must also call
* ossl_quic_sstream_mark_acked_fin() after calling this function.
*
* Returns 1 on success and 0 on error (e.g. if end < start).
*/
int ossl_quic_sstream_mark_acked(QUIC_SSTREAM *qss,
uint64_t start,
uint64_t end);
/*
* (RX/ACKM use.) Informs the QUIC_SSTREAM that a STREAM frame with the FIN bit
* set was acknowledged.
*
* Returns 1 on success and 0 on error.
*/
int ossl_quic_sstream_mark_acked_fin(QUIC_SSTREAM *qss);
/*
* (Front end use.) Appends user data to the stream. The data is copied into the
* stream. The amount of data consumed from buf is written to *consumed on
* success (short writes are possible). The amount of data which can be written
* can be determined in advance by calling the ossl_quic_sstream_get_buffer_avail()
* function; data is copied into an internal ring buffer of finite size.
*
* If the buffer is full, this should be materialised as a backpressure
* condition by the front end. This is not considered a failure condition;
* *consumed is written as 0 and the function returns 1.
*
* Returns 1 on success or 0 on failure.
*/
int ossl_quic_sstream_append(QUIC_SSTREAM *qss,
const unsigned char *buf,
size_t buf_len,
size_t *consumed);
/*
* Marks a stream as finished. ossl_quic_sstream_append() may not be called anymore
* after calling this.
*/
void ossl_quic_sstream_fin(QUIC_SSTREAM *qss);
/*
* If the stream has had ossl_quic_sstream_fin() called, returns 1 and writes
* the final size to *final_size. Otherwise, returns 0.
*/
int ossl_quic_sstream_get_final_size(QUIC_SSTREAM *qss, uint64_t *final_size);
/*
* Returns 1 iff all bytes (and any FIN, if any) which have been appended to the
* QUIC_SSTREAM so far, and any FIN (if any), have been both sent and acked.
*/
int ossl_quic_sstream_is_totally_acked(QUIC_SSTREAM *qss);
/*
* Resizes the internal ring buffer. All stream data is preserved safely.
*
* This can be used to expand or contract the ring buffer, but not to contract
* the ring buffer below the amount of stream data currently stored in it.
* Returns 1 on success and 0 on failure.
*
* IMPORTANT: Any buffers referenced by iovecs output by
* ossl_quic_sstream_get_stream_frame() cease to be valid after calling this function.
*/
int ossl_quic_sstream_set_buffer_size(QUIC_SSTREAM *qss, size_t num_bytes);
/*
* Gets the internal ring buffer size in bytes.
*/
size_t ossl_quic_sstream_get_buffer_size(QUIC_SSTREAM *qss);
/*
* Gets the number of bytes used in the internal ring buffer.
*/
size_t ossl_quic_sstream_get_buffer_used(QUIC_SSTREAM *qss);
/*
* Gets the number of bytes free in the internal ring buffer.
*/
size_t ossl_quic_sstream_get_buffer_avail(QUIC_SSTREAM *qss);
/*
* Utility function to ensure the length of an array of iovecs matches the
* length given as len. Trailing iovecs have their length values reduced or set
* to 0 as necessary.
*/
void ossl_quic_sstream_adjust_iov(size_t len,
OSSL_QTX_IOVEC *iov,
size_t num_iov);
/*
* Sets flag to cleanse the buffered data when it is acked.
*/
void ossl_quic_sstream_set_cleanse(QUIC_SSTREAM *qss, int cleanse);
/*
* QUIC Receive Stream Manager
* ===========================
*
* The QUIC Receive Stream Manager (QUIC_RSTREAM) is responsible for
* storing the received stream data frames until the application
* is able to read the data.
*
* The QUIC_RSTREAM is instantiated once for every stream that can receive data.
* (i.e., for a unidirectional receiving stream or for the receiving component
* of a bidirectional stream).
*/
typedef struct quic_rstream_st QUIC_RSTREAM;
/*
* Create a new instance of QUIC_RSTREAM with pointers to the flow
* controller and statistics module. They can be NULL for unit testing.
* If they are non-NULL, the `rxfc` is called when receive stream data
* is read by application. `statm` is queried for current rtt.
* `rbuf_size` is the initial size of the ring buffer to be used
* when ossl_quic_rstream_move_to_rbuf() is called.
*/
QUIC_RSTREAM *ossl_quic_rstream_new(QUIC_RXFC *rxfc,
OSSL_STATM *statm, size_t rbuf_size);
/*
* Frees a QUIC_RSTREAM and any associated storage.
*/
void ossl_quic_rstream_free(QUIC_RSTREAM *qrs);
/*
* Adds received stream frame data to `qrs`. The `pkt_wrap` refcount is
* incremented if the `data` is queued directly without copying.
* It can be NULL for unit-testing purposes, i.e. if `data` is static or
* never released before calling ossl_quic_rstream_free().
* The `offset` is the absolute offset of the data in the stream.
* `data_len` can be 0 - can be useful for indicating `fin` for empty stream.
* Or to indicate `fin` without any further data added to the stream.
*/
int ossl_quic_rstream_queue_data(QUIC_RSTREAM *qrs, OSSL_QRX_PKT *pkt,
uint64_t offset,
const unsigned char *data, uint64_t data_len,
int fin);
/*
* Copies the data from the stream storage to buffer `buf` of size `size`.
* `readbytes` is set to the number of bytes actually copied.
* `fin` is set to 1 if all the data from the stream were read so the
* stream is finished. It is set to 0 otherwise.
*/
int ossl_quic_rstream_read(QUIC_RSTREAM *qrs, unsigned char *buf, size_t size,
size_t *readbytes, int *fin);
/*
* Peeks at the data in the stream storage. It copies them to buffer `buf`
* of size `size` and sets `readbytes` to the number of bytes actually copied.
* `fin` is set to 1 if the copied data reach end of the stream.
* It is set to 0 otherwise.
*/
int ossl_quic_rstream_peek(QUIC_RSTREAM *qrs, unsigned char *buf, size_t size,
size_t *readbytes, int *fin);
/*
* Returns the size of the data available for reading. `fin` is set to 1 if
* after reading all the available data the stream will be finished,
* set to 0 otherwise.
*/
int ossl_quic_rstream_available(QUIC_RSTREAM *qrs, size_t *avail, int *fin);
/*
* Sets *record to the beginning of the first readable stream data chunk and
* *reclen to the size of the chunk. *fin is set to 1 if the end of the
* chunk is the last of the stream data chunks.
* If there is no record available *record is set to NULL and *rec_len to 0;
* ossl_quic_rstream_release_record() should not be called in that case.
* Returns 1 on success (including calls if no record is available, or
* after end of the stream - in that case *fin will be set to 1 and
* *rec_len to 0), 0 on error.
* It is an error to call ossl_quic_rstream_get_record() multiple times
* without calling ossl_quic_rstream_release_record() in between.
*/
int ossl_quic_rstream_get_record(QUIC_RSTREAM *qrs,
const unsigned char **record, size_t *rec_len,
int *fin);
/*
* Releases (possibly partially) the record returned by
* previous ossl_quic_rstream_get_record() call.
* read_len between previously returned *rec_len and SIZE_MAX indicates
* release of the whole record. Otherwise only part of the record is
* released. The remaining part of the record is unlocked, another
* call to ossl_quic_rstream_get_record() is needed to obtain further
* stream data.
* Returns 1 on success, 0 on error.
* It is an error to call ossl_quic_rstream_release_record() multiple
* times without calling ossl_quic_rstream_get_record() in between.
*/
int ossl_quic_rstream_release_record(QUIC_RSTREAM *qrs, size_t read_len);
/*
* Moves received frame data from decrypted packets to ring buffer.
* This should be called when there are too many decrypted packets allocated.
* Returns 1 on success, 0 when it was not possible to release all
* referenced packets due to an insufficient size of the ring buffer.
* Exception is the packet from the record returned previously by
* ossl_quic_rstream_get_record() - that one will be always skipped.
*/
int ossl_quic_rstream_move_to_rbuf(QUIC_RSTREAM *qrs);
/*
* Resizes the internal ring buffer to a new `rbuf_size` size.
* Returns 1 on success, 0 on error.
* Possible error conditions are an allocation failure, trying to resize
* the ring buffer when ossl_quic_rstream_get_record() was called and
* not yet released, or trying to resize the ring buffer to a smaller size
* than currently occupied.
*/
int ossl_quic_rstream_resize_rbuf(QUIC_RSTREAM *qrs, size_t rbuf_size);
/*
* Sets flag to cleanse the buffered data when user reads it.
*/
void ossl_quic_rstream_set_cleanse(QUIC_RSTREAM *qrs, int cleanse);
# endif
#endif

View File

@ -0,0 +1,878 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_INTERNAL_QUIC_STREAM_MAP_H
# define OSSL_INTERNAL_QUIC_STREAM_MAP_H
# pragma once
# include "internal/e_os.h"
# include "internal/time.h"
# include "internal/common.h"
# include "internal/quic_types.h"
# include "internal/quic_stream.h"
# include "internal/quic_fc.h"
# include <openssl/lhash.h>
# ifndef OPENSSL_NO_QUIC
/*
* QUIC Stream
* ===========
*
* Logical QUIC stream composing all relevant send and receive components.
*/
typedef struct quic_stream_st QUIC_STREAM;
typedef struct quic_stream_list_node_st QUIC_STREAM_LIST_NODE;
struct quic_stream_list_node_st {
QUIC_STREAM_LIST_NODE *prev, *next;
};
/*
* QUIC Send Stream States
* -----------------------
*
* These correspond to the states defined in RFC 9000 s. 3.1, with the
* exception of the NONE state which represents the absence of a send stream
* part.
*
* Invariants in each state are noted in comments below. In particular, once all
* data has been acknowledged received, or we have reset the stream, we don't
* need to keep the QUIC_SSTREAM and data buffers around. Of course, we also
* don't have a QUIC_SSTREAM on a receive-only stream.
*/
#define QUIC_SSTREAM_STATE_NONE 0 /* --- sstream == NULL */
#define QUIC_SSTREAM_STATE_READY 1 /* \ */
#define QUIC_SSTREAM_STATE_SEND 2 /* |-- sstream != NULL */
#define QUIC_SSTREAM_STATE_DATA_SENT 3 /* / */
#define QUIC_SSTREAM_STATE_DATA_RECVD 4 /* \ */
#define QUIC_SSTREAM_STATE_RESET_SENT 5 /* |-- sstream == NULL */
#define QUIC_SSTREAM_STATE_RESET_RECVD 6 /* / */
/*
* QUIC Receive Stream States
* --------------------------
*
* These correspond to the states defined in RFC 9000 s. 3.2, with the exception
* of the NONE state which represents the absence of a receive stream part.
*
* Invariants in each state are noted in comments below. In particular, once all
* data has been read by the application, we don't need to keep the QUIC_RSTREAM
* and data buffers around. If the receive part is instead reset before it is
* finished, we also don't need to keep the QUIC_RSTREAM around. Finally, we
* don't need a QUIC_RSTREAM on a send-only stream.
*/
#define QUIC_RSTREAM_STATE_NONE 0 /* --- rstream == NULL */
#define QUIC_RSTREAM_STATE_RECV 1 /* \ */
#define QUIC_RSTREAM_STATE_SIZE_KNOWN 2 /* |-- rstream != NULL */
#define QUIC_RSTREAM_STATE_DATA_RECVD 3 /* / */
#define QUIC_RSTREAM_STATE_DATA_READ 4 /* \ */
#define QUIC_RSTREAM_STATE_RESET_RECVD 5 /* |-- rstream == NULL */
#define QUIC_RSTREAM_STATE_RESET_READ 6 /* / */
struct quic_stream_st {
QUIC_STREAM_LIST_NODE active_node; /* for use by QUIC_STREAM_MAP */
QUIC_STREAM_LIST_NODE accept_node; /* accept queue of remotely-created streams */
QUIC_STREAM_LIST_NODE ready_for_gc_node; /* queue of streams now ready for GC */
/* Temporary link used by TXP. */
QUIC_STREAM *txp_next;
/*
* QUIC Stream ID. Do not assume that this encodes a type as this is a
* version-specific property and may change between QUIC versions; instead,
* use the type field.
*/
uint64_t id;
/*
* Application Error Code (AEC) used for STOP_SENDING frame.
* This is only valid if stop_sending is 1.
*/
uint64_t stop_sending_aec;
/*
* Application Error Code (AEC) used for RESET_STREAM frame.
* This is only valid if reset_stream is 1.
*/
uint64_t reset_stream_aec;
/*
* Application Error Code (AEC) for incoming STOP_SENDING frame.
* This is only valid if peer_stop_sending is 1.
*/
uint64_t peer_stop_sending_aec;
/*
* Application Error Code (AEC) for incoming RESET_STREAM frame.
* This is only valid if peer_reset_stream is 1.
*/
uint64_t peer_reset_stream_aec;
/* Temporary value used by TXP. */
uint64_t txp_txfc_new_credit_consumed;
/*
* The final size of the send stream. Although this information can be
* discerned from a QUIC_SSTREAM, it is stored separately as we need to keep
* track of this even if we have thrown away the QUIC_SSTREAM. Use
* ossl_quic_stream_send_get_final_size to determine if this contain a
* valid value or if there is no final size yet for a sending part.
*
* For the receive part, the final size is tracked by the stream-level RXFC;
* use ossl_quic_stream_recv_get_final_size or
* ossl_quic_rxfc_get_final_size.
*/
uint64_t send_final_size;
/*
* Send stream part and receive stream part buffer management objects.
*
* DO NOT test these pointers (sstream, rstream) for NULL. Determine the
* state of the send or receive stream part first using the appropriate
* function; then the invariant of that state guarantees that sstream or
* rstream either is or is not NULL respectively, therefore there is no
* valid use case for testing these pointers for NULL. In particular, a
* stream with a send part can still have sstream as NULL, and a stream with
* a receive part can still have rstream as NULL. QUIC_SSTREAM and
* QUIC_RSTREAM are stream buffer resource management objects which exist
* only when they need to for buffer management purposes. The existence or
* non-existence of a QUIC_SSTREAM or QUIC_RSTREAM object does not
* correspond with whether a stream's respective send or receive part
* logically exists or not.
*/
QUIC_SSTREAM *sstream; /* NULL if RX-only */
QUIC_RSTREAM *rstream; /* NULL if TX only */
/* Stream-level flow control managers. */
QUIC_TXFC txfc; /* NULL if RX-only */
QUIC_RXFC rxfc; /* NULL if TX-only */
unsigned int type : 8; /* QUIC_STREAM_INITIATOR_*, QUIC_STREAM_DIR_* */
unsigned int send_state : 8; /* QUIC_SSTREAM_STATE_* */
unsigned int recv_state : 8; /* QUIC_RSTREAM_STATE_* */
/* 1 iff this QUIC_STREAM is on the active queue (invariant). */
unsigned int active : 1;
/*
* This is a copy of the QUIC connection as_server value, indicating
* whether we are locally operating as a server or not. Having this
* significantly simplifies stream type determination relative to our
* perspective. It never changes after a QUIC_STREAM is created and is the
* same for all QUIC_STREAMS under a QUIC_STREAM_MAP.
*/
unsigned int as_server : 1;
/*
* Has STOP_SENDING been requested (by us)? Note that this is not the same
* as want_stop_sending below, as a STOP_SENDING frame may already have been
* sent and fully acknowledged.
*/
unsigned int stop_sending : 1;
/*
* Has RESET_STREAM been requested (by us)? Works identically to
* STOP_SENDING for transmission purposes.
*/
/* Has our peer sent a STOP_SENDING frame? */
unsigned int peer_stop_sending : 1;
/* Temporary flags used by TXP. */
unsigned int txp_sent_fc : 1;
unsigned int txp_sent_stop_sending : 1;
unsigned int txp_sent_reset_stream : 1;
unsigned int txp_drained : 1;
unsigned int txp_blocked : 1;
/* Frame regeneration flags. */
unsigned int want_max_stream_data : 1; /* used for regen only */
unsigned int want_stop_sending : 1; /* used for gen or regen */
unsigned int want_reset_stream : 1; /* used for gen or regen */
/* Flags set when frames *we* sent were acknowledged. */
unsigned int acked_stop_sending : 1;
/*
* The stream's XSO has been deleted. Pending GC.
*
* Here is how stream deletion works:
*
* - A QUIC_STREAM cannot be deleted until it is neither in the accept
* queue nor has an associated XSO. This condition occurs when and only
* when deleted is true.
*
* - Once this is the case (i.e., no user-facing API object exposing the
* stream), we can delete the stream once we determine that all of our
* protocol obligations requiring us to keep the QUIC_STREAM around have
* been met.
*
* The following frames relate to the streams layer for a specific
* stream:
*
* STREAM
*
* RX Obligations:
* Ignore for a deleted stream.
*
* (This is different from our obligation for a
* locally-initiated stream ID we have not created yet,
* which we must treat as a protocol error. This can be
* distinguished via a simple monotonic counter.)
*
* TX Obligations:
* None, once we've decided to (someday) delete the stream.
*
* STOP_SENDING
*
* We cannot delete the stream until we have finished informing
* the peer that we are not going to be listening to it
* anymore.
*
* RX Obligations:
* When we delete a stream we must have already had a FIN
* or RESET_STREAM we transmitted acknowledged by the peer.
* Thus we can ignore STOP_SENDING frames for deleted
* streams (if they occur, they are probably just
* retransmissions).
*
* TX Obligations:
* _Acknowledged_ receipt of a STOP_SENDING frame by the
* peer (unless the peer's send part has already FIN'd).
*
* RESET_STREAM
*
* We cannot delete the stream until we have finished informing
* the peer that we are not going to be transmitting on it
* anymore.
*
* RX Obligations:
* This indicates the peer is not going to send any more
* data on the stream. We don't need to care about this
* since once a stream is marked for deletion we don't care
* about any data it does send. We can ignore this for
* deleted streams. The important criterion is that the
* peer has been successfully delivered our STOP_SENDING
* frame.
*
* TX Obligations:
* _Acknowledged_ receipt of a RESET_STREAM frame or FIN by
* the peer.
*
* MAX_STREAM_DATA
*
* RX Obligations:
* Ignore. Since we are not going to be sending any more
* data on a stream once it has been marked for deletion,
* we don't need to care about flow control information.
*
* TX Obligations:
* None.
*
* In other words, our protocol obligation is simply:
*
* - either:
* - the peer has acknowledged receipt of a STOP_SENDING frame sent
* by us; -or-
* - we have received a FIN and all preceding segments from the peer
*
* [NOTE: The actual criterion required here is simply 'we have
* received a FIN from the peer'. However, due to reordering and
* retransmissions we might subsequently receive non-FIN segments
* out of order. The FIN means we know the peer will stop
* transmitting on the stream at *some* point, but by sending
* STOP_SENDING we can avoid these needless retransmissions we
* will just ignore anyway. In actuality we could just handle all
* cases by sending a STOP_SENDING. The strategy we choose is to
* only avoid sending a STOP_SENDING and rely on a received FIN
* when we have received all preceding data, as this makes it
* reasonably certain no benefit would be gained by sending
* STOP_SENDING.]
*
* TODO(QUIC FUTURE): Implement the latter case (currently we
just always do STOP_SENDING).
*
* and;
*
* - we have drained our send stream (for a finished send stream)
* and got acknowledgement all parts of it including the FIN, or
* sent a RESET_STREAM frame and got acknowledgement of that frame.
*
* Once these conditions are met, we can GC the QUIC_STREAM.
*
*/
unsigned int deleted : 1;
/* Set to 1 once the above conditions are actually met. */
unsigned int ready_for_gc : 1;
/* Set to 1 if this is currently counted in the shutdown flush stream count. */
unsigned int shutdown_flush : 1;
};
#define QUIC_STREAM_INITIATOR_CLIENT 0
#define QUIC_STREAM_INITIATOR_SERVER 1
#define QUIC_STREAM_INITIATOR_MASK 1
#define QUIC_STREAM_DIR_BIDI 0
#define QUIC_STREAM_DIR_UNI 2
#define QUIC_STREAM_DIR_MASK 2
void ossl_quic_stream_check(const QUIC_STREAM *s);
/*
* Returns 1 if the QUIC_STREAM was initiated by the endpoint with the server
* role.
*/
static ossl_inline ossl_unused int ossl_quic_stream_is_server_init(const QUIC_STREAM *s)
{
return (s->type & QUIC_STREAM_INITIATOR_MASK) == QUIC_STREAM_INITIATOR_SERVER;
}
/*
* Returns 1 if the QUIC_STREAM is bidirectional and 0 if it is unidirectional.
*/
static ossl_inline ossl_unused int ossl_quic_stream_is_bidi(const QUIC_STREAM *s)
{
return (s->type & QUIC_STREAM_DIR_MASK) == QUIC_STREAM_DIR_BIDI;
}
/* Returns 1 if the QUIC_STREAM was locally initiated. */
static ossl_inline ossl_unused int ossl_quic_stream_is_local_init(const QUIC_STREAM *s)
{
return ossl_quic_stream_is_server_init(s) == s->as_server;
}
/*
* Returns 1 if the QUIC_STREAM has a sending part, based on its stream type.
*
* Do NOT use (s->sstream != NULL) to test this; use this function. Note that
* even if this function returns 1, s->sstream might be NULL if the QUIC_SSTREAM
* has been deemed no longer needed, for example due to a RESET_STREAM.
*/
static ossl_inline ossl_unused int ossl_quic_stream_has_send(const QUIC_STREAM *s)
{
return s->send_state != QUIC_SSTREAM_STATE_NONE;
}
/*
* Returns 1 if the QUIC_STREAM has a receiving part, based on its stream type.
*
* Do NOT use (s->rstream != NULL) to test this; use this function. Note that
* even if this function returns 1, s->rstream might be NULL if the QUIC_RSTREAM
* has been deemed no longer needed, for example if the receive stream is
* completely finished with.
*/
static ossl_inline ossl_unused int ossl_quic_stream_has_recv(const QUIC_STREAM *s)
{
return s->recv_state != QUIC_RSTREAM_STATE_NONE;
}
/*
* Returns 1 if the QUIC_STREAM has a QUIC_SSTREAM send buffer associated with
* it. If this returns 1, s->sstream is guaranteed to be non-NULL. The converse
* is not necessarily true; erasure of a send stream buffer which is no longer
* required is an optimisation which the QSM may, but is not obliged, to
* perform.
*
* This call should be used where it is desired to do something with the send
* stream buffer but there is no more specific send state restriction which is
* applicable.
*
* Note: This does NOT indicate whether it is suitable to allow an application
* to append to the buffer. DATA_SENT indicates all data (including FIN) has
* been *sent*; the absence of DATA_SENT does not mean a FIN has not been queued
* (meaning no more application data can be appended). This is enforced by
* QUIC_SSTREAM.
*/
static ossl_inline ossl_unused int ossl_quic_stream_has_send_buffer(const QUIC_STREAM *s)
{
switch (s->send_state) {
case QUIC_SSTREAM_STATE_READY:
case QUIC_SSTREAM_STATE_SEND:
case QUIC_SSTREAM_STATE_DATA_SENT:
return 1;
default:
return 0;
}
}
/*
* Returns 1 if the QUIC_STREAM has a sending part which is in one of the reset
* states.
*/
static ossl_inline ossl_unused int ossl_quic_stream_send_is_reset(const QUIC_STREAM *s)
{
return s->send_state == QUIC_SSTREAM_STATE_RESET_SENT
|| s->send_state == QUIC_SSTREAM_STATE_RESET_RECVD;
}
/*
* Returns 1 if the QUIC_STREAM has a QUIC_RSTREAM receive buffer associated
* with it. If this returns 1, s->rstream is guaranteed to be non-NULL. The
* converse is not necessarily true; erasure of a receive stream buffer which is
* no longer required is an optimisation which the QSM may, but is not obliged,
* to perform.
*
* This call should be used where it is desired to do something with the receive
* stream buffer but there is no more specific receive state restriction which is
* applicable.
*/
static ossl_inline ossl_unused int ossl_quic_stream_has_recv_buffer(const QUIC_STREAM *s)
{
switch (s->recv_state) {
case QUIC_RSTREAM_STATE_RECV:
case QUIC_RSTREAM_STATE_SIZE_KNOWN:
case QUIC_RSTREAM_STATE_DATA_RECVD:
return 1;
default:
return 0;
}
}
/*
* Returns 1 if the QUIC_STREAM has a receiving part which is in one of the
* reset states.
*/
static ossl_inline ossl_unused int ossl_quic_stream_recv_is_reset(const QUIC_STREAM *s)
{
return s->recv_state == QUIC_RSTREAM_STATE_RESET_RECVD
|| s->recv_state == QUIC_RSTREAM_STATE_RESET_READ;
}
/*
* Returns 1 if the stream has a send part and that part has a final size.
*
* If final_size is non-NULL, *final_size is the final size (on success) or an
* undefined value otherwise.
*/
static ossl_inline ossl_unused int ossl_quic_stream_send_get_final_size(const QUIC_STREAM *s,
uint64_t *final_size)
{
switch (s->send_state) {
default:
case QUIC_SSTREAM_STATE_NONE:
return 0;
case QUIC_SSTREAM_STATE_SEND:
/*
* SEND may or may not have had a FIN - even if we have a FIN we do not
* move to DATA_SENT until we have actually sent all the data. So
* ask the QUIC_SSTREAM.
*/
return ossl_quic_sstream_get_final_size(s->sstream, final_size);
case QUIC_SSTREAM_STATE_DATA_SENT:
case QUIC_SSTREAM_STATE_DATA_RECVD:
case QUIC_SSTREAM_STATE_RESET_SENT:
case QUIC_SSTREAM_STATE_RESET_RECVD:
if (final_size != NULL)
*final_size = s->send_final_size;
return 1;
}
}
/*
* Returns 1 if the stream has a receive part and that part has a final size.
*
* If final_size is non-NULL, *final_size is the final size (on success) or an
* undefined value otherwise.
*/
static ossl_inline ossl_unused int ossl_quic_stream_recv_get_final_size(const QUIC_STREAM *s,
uint64_t *final_size)
{
switch (s->recv_state) {
default:
case QUIC_RSTREAM_STATE_NONE:
case QUIC_RSTREAM_STATE_RECV:
return 0;
case QUIC_RSTREAM_STATE_SIZE_KNOWN:
case QUIC_RSTREAM_STATE_DATA_RECVD:
case QUIC_RSTREAM_STATE_DATA_READ:
case QUIC_RSTREAM_STATE_RESET_RECVD:
case QUIC_RSTREAM_STATE_RESET_READ:
if (!ossl_assert(ossl_quic_rxfc_get_final_size(&s->rxfc, final_size)))
return 0;
return 1;
}
}
/*
* QUIC Stream Map
* ===============
*
* The QUIC stream map:
*
* - maps stream IDs to QUIC_STREAM objects;
* - tracks which streams are 'active' (currently have data for transmission);
* - allows iteration over the active streams only.
*
*/
typedef struct quic_stream_map_st {
LHASH_OF(QUIC_STREAM) *map;
QUIC_STREAM_LIST_NODE active_list;
QUIC_STREAM_LIST_NODE accept_list;
QUIC_STREAM_LIST_NODE ready_for_gc_list;
size_t rr_stepping, rr_counter;
size_t num_accept, num_shutdown_flush;
QUIC_STREAM *rr_cur;
uint64_t (*get_stream_limit_cb)(int uni, void *arg);
void *get_stream_limit_cb_arg;
QUIC_RXFC *max_streams_bidi_rxfc;
QUIC_RXFC *max_streams_uni_rxfc;
int is_server;
} QUIC_STREAM_MAP;
/*
* get_stream_limit is a callback which is called to retrieve the current stream
* limit for streams created by us. This mechanism is not used for
* peer-initiated streams. If a stream's stream ID is x, a stream is allowed if
* (x >> 2) < returned limit value; i.e., the returned value is exclusive.
*
* If uni is 1, get the limit for locally-initiated unidirectional streams, else
* get the limit for locally-initiated bidirectional streams.
*
* If the callback is NULL, stream limiting is not applied.
* Stream limiting is used to determine if frames can currently be produced for
* a stream.
*/
int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm,
uint64_t (*get_stream_limit_cb)(int uni, void *arg),
void *get_stream_limit_cb_arg,
QUIC_RXFC *max_streams_bidi_rxfc,
QUIC_RXFC *max_streams_uni_rxfc,
int is_server);
/*
* Any streams still in the map will be released as though
* ossl_quic_stream_map_release was called on them.
*/
void ossl_quic_stream_map_cleanup(QUIC_STREAM_MAP *qsm);
/*
* Allocate a new stream. type is a combination of one QUIC_STREAM_INITIATOR_*
* value and one QUIC_STREAM_DIR_* value. Note that clients can e.g. allocate
* server-initiated streams as they will need to allocate a QUIC_STREAM
* structure to track any stream created by the server, etc.
*
* stream_id must be a valid value. Returns NULL if a stream already exists
* with the given ID.
*/
QUIC_STREAM *ossl_quic_stream_map_alloc(QUIC_STREAM_MAP *qsm,
uint64_t stream_id,
int type);
/*
* Releases a stream object. Note that this must only be done once the teardown
* process is entirely complete and the object will never be referenced again.
*/
void ossl_quic_stream_map_release(QUIC_STREAM_MAP *qsm, QUIC_STREAM *stream);
/*
* Calls visit_cb() for each stream in the map. visit_cb_arg is an opaque
* argument which is passed through.
*/
void ossl_quic_stream_map_visit(QUIC_STREAM_MAP *qsm,
void (*visit_cb)(QUIC_STREAM *stream, void *arg),
void *visit_cb_arg);
/*
* Retrieves a stream by stream ID. Returns NULL if it does not exist.
*/
QUIC_STREAM *ossl_quic_stream_map_get_by_id(QUIC_STREAM_MAP *qsm,
uint64_t stream_id);
/*
* Marks the given stream as active or inactive based on its state. Idempotent.
*
* When a stream is marked active, it becomes available in the iteration list,
* and when a stream is marked inactive, it no longer appears in the iteration
* list.
*
* Calling this function invalidates any iterator currently pointing at the
* given stream object, but iterators not currently pointing at the given stream
* object are not invalidated.
*/
void ossl_quic_stream_map_update_state(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s);
/*
* Sets the RR stepping value, n. The RR rotation will be advanced every n
* packets. The default value is 1.
*/
void ossl_quic_stream_map_set_rr_stepping(QUIC_STREAM_MAP *qsm, size_t stepping);
/*
* Returns 1 if the stream ordinal given is allowed by the current stream count
* flow control limit, assuming a locally initiated stream of a type described
* by is_uni.
*
* Note that stream_ordinal is a stream ordinal, not a stream ID.
*/
int ossl_quic_stream_map_is_local_allowed_by_stream_limit(QUIC_STREAM_MAP *qsm,
uint64_t stream_ordinal,
int is_uni);
/*
* Stream Send Part
* ================
*/
/*
* Ensures that the sending part has transitioned out of the READY state (i.e.,
* to SEND, or a subsequent state). This function is named as it is because,
* while on paper the distinction between READY and SEND is whether we have
* started transmitting application data, in practice the meaningful distinction
* between the two states is whether we have allocated a stream ID to the stream
* or not. QUIC permits us to defer stream ID allocation until first STREAM (or
* STREAM_DATA_BLOCKED) frame transmission for locally-initiated streams.
*
* Our implementation does not currently do this and we allocate stream IDs up
* front, however we may revisit this in the future. Calling this represents a
* demand for a stream ID by the caller and ensures one has been allocated to
* the stream, and causes us to transition to SEND if we are still in the READY
* state.
*
* Returns 0 if there is no send part (caller error) and 1 otherwise.
*/
int ossl_quic_stream_map_ensure_send_part_id(QUIC_STREAM_MAP *qsm,
QUIC_STREAM *qs);
/*
* Transitions from SEND to the DATA_SENT state. Note that this is NOT the same
* as the point in time at which the final size of the stream becomes known
* (i.e., the time at which ossl_quic_sstream_fin()) is called as it occurs when
* we have SENT all data on a given stream send part, not merely buffered it.
* Note that this transition is NOT reversed in the event of some of that data
* being lost.
*
* Returns 1 if the state transition was successfully taken. Returns 0 if there
* is no send part (caller error) or if the state transition cannot be taken
* because the send part is not in the SEND state.
*/
int ossl_quic_stream_map_notify_all_data_sent(QUIC_STREAM_MAP *qsm,
QUIC_STREAM *qs);
/*
* Transitions from the DATA_SENT to DATA_RECVD state; should be called
* when all transmitted stream data is ACKed by the peer.
*
* Returns 1 if the state transition was successfully taken. Returns 0 if there
* is no send part (caller error) or the state transition cannot be taken
* because the send part is not in the DATA_SENT state. Because
* ossl_quic_stream_map_notify_all_data_sent() should always be called prior to
* this function, the send state must already be in DATA_SENT in order for this
* function to succeed.
*/
int ossl_quic_stream_map_notify_totally_acked(QUIC_STREAM_MAP *qsm,
QUIC_STREAM *qs);
/*
* Resets the sending part of a stream. This is a transition from the READY,
* SEND or DATA_SENT send stream states to the RESET_SENT state.
*
* This function returns 1 if the transition is taken (i.e., if the send stream
* part was in one of the states above), or if it is already in the RESET_SENT
* state (idempotent operation), or if it has reached the RESET_RECVD state.
*
* It returns 0 if in the DATA_RECVD state, as a send stream cannot be reset
* in this state. It also returns 0 if there is no send part (caller error).
*/
int ossl_quic_stream_map_reset_stream_send_part(QUIC_STREAM_MAP *qsm,
QUIC_STREAM *qs,
uint64_t aec);
/*
* Transitions from the RESET_SENT to the RESET_RECVD state. This should be
* called when a sent RESET_STREAM frame has been acknowledged by the peer.
*
* This function returns 1 if the transition is taken (i.e., if the send stream
* part was in one of the states above) or if it is already in the RESET_RECVD
* state (idempotent operation).
*
* It returns 0 if not in the RESET_SENT or RESET_RECVD states, as this function
* should only be called after we have already sent a RESET_STREAM frame and
* entered the RESET_SENT state. It also returns 0 if there is no send part
* (caller error).
*/
int ossl_quic_stream_map_notify_reset_stream_acked(QUIC_STREAM_MAP *qsm,
QUIC_STREAM *qs);
/*
* Stream Receive Part
* ===================
*/
/*
* Transitions from the RECV receive stream state to the SIZE_KNOWN state. This
* should be called once a STREAM frame is received for the stream with the FIN
* bit set. final_size should be the final size of the stream in bytes.
*
* Returns 1 if the transition was taken.
*/
int ossl_quic_stream_map_notify_size_known_recv_part(QUIC_STREAM_MAP *qsm,
QUIC_STREAM *qs,
uint64_t final_size);
/*
* Transitions from the SIZE_KNOWN receive stream state to the DATA_RECVD state.
* This should be called once all data for a receive stream is received.
*
* Returns 1 if the transition was taken.
*/
int ossl_quic_stream_map_notify_totally_received(QUIC_STREAM_MAP *qsm,
QUIC_STREAM *qs);
/*
* Transitions from the DATA_RECVD receive stream state to the DATA_READ state.
* This should be called once all data for a receive stream is read by the
* application.
*
* Returns 1 if the transition was taken.
*/
int ossl_quic_stream_map_notify_totally_read(QUIC_STREAM_MAP *qsm,
QUIC_STREAM *qs);
/*
* Transitions from the RECV, SIZE_KNOWN or DATA_RECVD receive stream state to
* the RESET_RECVD state. This should be called on RESET_STREAM.
*
* Returns 1 if the transition was taken.
*/
int ossl_quic_stream_map_notify_reset_recv_part(QUIC_STREAM_MAP *qsm,
QUIC_STREAM *qs,
uint64_t app_error_code,
uint64_t final_size);
/*
* Transitions from the RESET_RECVD receive stream state to the RESET_READ
* receive stream state. This should be called when the application is notified
* of a stream reset.
*/
int ossl_quic_stream_map_notify_app_read_reset_recv_part(QUIC_STREAM_MAP *qsm,
QUIC_STREAM *qs);
/*
* Marks the receiving part of a stream for STOP_SENDING. This is orthogonal to
* receive stream state as it does not affect it directly.
*
* Returns 1 if the receiving part of a stream was not already marked for
* STOP_SENDING.
* Returns 0 otherwise, which need not be considered an error.
*/
int ossl_quic_stream_map_stop_sending_recv_part(QUIC_STREAM_MAP *qsm,
QUIC_STREAM *qs,
uint64_t aec);
/*
* Marks the stream as wanting a STOP_SENDING frame transmitted. It is not valid
* to call this if ossl_quic_stream_map_stop_sending_recv_part() has not been
* called. For TXP use.
*/
int ossl_quic_stream_map_schedule_stop_sending(QUIC_STREAM_MAP *qsm,
QUIC_STREAM *qs);
/*
* Accept Queue Management
* =======================
*/
/*
* Adds a stream to the accept queue.
*/
void ossl_quic_stream_map_push_accept_queue(QUIC_STREAM_MAP *qsm,
QUIC_STREAM *s);
/*
* Returns the next item to be popped from the accept queue, or NULL if it is
* empty.
*/
QUIC_STREAM *ossl_quic_stream_map_peek_accept_queue(QUIC_STREAM_MAP *qsm);
/*
* Removes a stream from the accept queue. rtt is the estimated connection RTT.
* The stream is retired for the purposes of MAX_STREAMS RXFC.
*
* Precondition: s is in the accept queue.
*/
void ossl_quic_stream_map_remove_from_accept_queue(QUIC_STREAM_MAP *qsm,
QUIC_STREAM *s,
OSSL_TIME rtt);
/* Returns the length of the accept queue. */
size_t ossl_quic_stream_map_get_accept_queue_len(QUIC_STREAM_MAP *qsm);
/*
* Shutdown Flush and GC
* =====================
*/
/*
* Delete streams ready for GC. Pointers to those QUIC_STREAM objects become
* invalid.
*/
void ossl_quic_stream_map_gc(QUIC_STREAM_MAP *qsm);
/*
* Begins shutdown stream flush triage. Analyses all streams, including deleted
* but not yet GC'd streams, to determine if we should wait for that stream to
* be fully flushed before shutdown. After calling this, call
* ossl_quic_stream_map_is_shutdown_flush_finished() to determine if all
* shutdown flush eligible streams have been flushed.
*/
void ossl_quic_stream_map_begin_shutdown_flush(QUIC_STREAM_MAP *qsm);
/*
* Returns 1 if all shutdown flush eligible streams have finished flushing,
* or if ossl_quic_stream_map_begin_shutdown_flush() has not been called.
*/
int ossl_quic_stream_map_is_shutdown_flush_finished(QUIC_STREAM_MAP *qsm);
/*
* QUIC Stream Iterator
* ====================
*
* Allows the current set of active streams to be walked using a RR-based
* algorithm. Each time ossl_quic_stream_iter_init is called, the RR algorithm
* is stepped. The RR algorithm rotates the iteration order such that the next
* active stream is returned first after n calls to ossl_quic_stream_iter_init,
* where n is the stepping value configured via
* ossl_quic_stream_map_set_rr_stepping.
*
* Suppose there are three active streams and the configured stepping is n:
*
* Iteration 0n: [Stream 1] [Stream 2] [Stream 3]
* Iteration 1n: [Stream 2] [Stream 3] [Stream 1]
* Iteration 2n: [Stream 3] [Stream 1] [Stream 2]
*
*/
typedef struct quic_stream_iter_st {
QUIC_STREAM_MAP *qsm;
QUIC_STREAM *first_stream, *stream;
} QUIC_STREAM_ITER;
/*
* Initialise an iterator, advancing the RR algorithm as necessary (if
* advance_rr is 1). After calling this, it->stream will be the first stream in
* the iteration sequence, or NULL if there are no active streams.
*/
void ossl_quic_stream_iter_init(QUIC_STREAM_ITER *it, QUIC_STREAM_MAP *qsm,
int advance_rr);
/*
* Advances to next stream in iteration sequence. You do not need to call this
* immediately after calling ossl_quic_stream_iter_init(). If the end of the
* list is reached, it->stream will be NULL after calling this.
*/
void ossl_quic_stream_iter_next(QUIC_STREAM_ITER *it);
# endif
#endif

View File

@ -0,0 +1,102 @@
/*
* Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_QUIC_THREAD_ASSIST_H
# define OSSL_QUIC_THREAD_ASSIST_H
# include <openssl/ssl.h>
# include "internal/thread.h"
# include "internal/time.h"
# if defined(OPENSSL_NO_QUIC) || defined(OPENSSL_NO_THREAD_POOL)
# define OPENSSL_NO_QUIC_THREAD_ASSIST
# endif
# ifndef OPENSSL_NO_QUIC_THREAD_ASSIST
/*
* QUIC Thread Assisted Functionality
* ==================================
*
* Where OS threading support is available, QUIC can optionally support a thread
* assisted mode of operation. The purpose of this mode of operation is to
* ensure that assorted timeout events which QUIC expects to be handled in a
* timely manner can be handled without the application needing to ensure that
* SSL_tick() is called on time. This is not needed if the application always
* has a call blocking to SSL_read() or SSL_write() (or another I/O function) on
* a QUIC SSL object, but if the application goes for long periods of time
* without making any such call to a QUIC SSL object, libssl cannot ordinarily
* guarantee that QUIC timeout events will be serviced in a timely fashion.
* Thread assisted mode is therefore of use to applications which do not always
* have an ongoing call to an I/O function on a QUIC SSL object but also do not
* want to have to arrange periodic ticking.
*
* A consequence of this is that the intrusiveness of thread assisted mode upon
* the general architecture of our QUIC engine is actually fairly limited and
* amounts to an automatic ticking of the QUIC engine when timeouts expire,
* synchronised correctly with an application's own threads using locking.
*/
typedef struct quic_thread_assist_st {
QUIC_CHANNEL *ch;
CRYPTO_CONDVAR *cv;
CRYPTO_THREAD *t;
int teardown, joined;
OSSL_TIME (*now_cb)(void *arg);
void *now_cb_arg;
} QUIC_THREAD_ASSIST;
/*
* Initialise the thread assist object. The channel must have a valid mutex
* configured on it which will be retrieved automatically. It is assumed that
* the mutex is currently held when this function is called. This function does
* not affect the state of the mutex.
*/
int ossl_quic_thread_assist_init_start(QUIC_THREAD_ASSIST *qta,
QUIC_CHANNEL *ch,
OSSL_TIME (*now_cb)(void *arg),
void *now_cb_arg);
/*
* Request the thread assist helper to begin stopping the assist thread. This
* returns before the teardown is complete. Idempotent; multiple calls to this
* function are inconsequential.
*
* Precondition: channel mutex must be held (unchecked)
*/
int ossl_quic_thread_assist_stop_async(QUIC_THREAD_ASSIST *qta);
/*
* Wait until the thread assist helper is torn down. This automatically implies
* the effects of ossl_quic_thread_assist_stop_async(). Returns immediately
* if the teardown has already completed.
*
* Precondition: channel mutex must be held (unchecked)
*/
int ossl_quic_thread_assist_wait_stopped(QUIC_THREAD_ASSIST *qta);
/*
* Deallocates state associated with the thread assist helper.
* ossl_quic_thread_assist_wait_stopped() must have returned successfully before
* calling this. It does not matter whether the channel mutex is held or not.
*
* Precondition: ossl_quic_thread_assist_wait_stopped() has returned 1
* (asserted)
*/
int ossl_quic_thread_assist_cleanup(QUIC_THREAD_ASSIST *qta);
/*
* Must be called to notify the assist thread if the channel deadline changes.
*
* Precondition: channel mutex must be held (unchecked)
*/
int ossl_quic_thread_assist_notify_deadline_changed(QUIC_THREAD_ASSIST *qta);
# endif
#endif

View File

@ -0,0 +1,106 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_QUIC_TLS_H
# define OSSL_QUIC_TLS_H
# include <openssl/ssl.h>
# include "internal/quic_stream.h"
typedef struct quic_tls_st QUIC_TLS;
typedef struct quic_tls_args_st {
/*
* The "inner" SSL object for the QUIC Connection. Contains an
* SSL_CONNECTION
*/
SSL *s;
/*
* Called to send data on the crypto stream. We use a callback rather than
* passing the crypto stream QUIC_SSTREAM directly because this lets the CSM
* dynamically select the correct outgoing crypto stream based on the
* current EL.
*/
int (*crypto_send_cb)(const unsigned char *buf, size_t buf_len,
size_t *consumed, void *arg);
void *crypto_send_cb_arg;
/*
* Call to receive crypto stream data. A pointer to the underlying buffer
* is provided, and subsequently released to avoid unnecessary copying of
* data.
*/
int (*crypto_recv_rcd_cb)(const unsigned char **buf, size_t *bytes_read,
void *arg);
void *crypto_recv_rcd_cb_arg;
int (*crypto_release_rcd_cb)(size_t bytes_read, void *arg);
void *crypto_release_rcd_cb_arg;
/* Called when a traffic secret is available for a given encryption level. */
int (*yield_secret_cb)(uint32_t enc_level, int direction /* 0=RX, 1=TX */,
uint32_t suite_id, EVP_MD *md,
const unsigned char *secret, size_t secret_len,
void *arg);
void *yield_secret_cb_arg;
/*
* Called when we receive transport parameters from the peer.
*
* Note: These parameters are not authenticated until the handshake is
* marked as completed.
*/
int (*got_transport_params_cb)(const unsigned char *params,
size_t params_len,
void *arg);
void *got_transport_params_cb_arg;
/*
* Called when the handshake has been completed as far as the handshake
* protocol is concerned, meaning that the connection has been
* authenticated.
*/
int (*handshake_complete_cb)(void *arg);
void *handshake_complete_cb_arg;
/*
* Called when something has gone wrong with the connection as far as the
* handshake layer is concerned, meaning that it should be immediately torn
* down. Note that this may happen at any time, including after a connection
* has been fully established.
*/
int (*alert_cb)(void *arg, unsigned char alert_code);
void *alert_cb_arg;
/* Set to 1 if we are running in the server role. */
int is_server;
} QUIC_TLS_ARGS;
QUIC_TLS *ossl_quic_tls_new(const QUIC_TLS_ARGS *args);
void ossl_quic_tls_free(QUIC_TLS *qtls);
/* Advance the state machine */
int ossl_quic_tls_tick(QUIC_TLS *qtls);
int ossl_quic_tls_set_transport_params(QUIC_TLS *qtls,
const unsigned char *transport_params,
size_t transport_params_len);
int ossl_quic_tls_get_error(QUIC_TLS *qtls,
uint64_t *error_code,
const char **error_msg,
ERR_STATE **error_state);
int ossl_quic_tls_is_cert_request(QUIC_TLS *qtls);
int ossl_quic_tls_has_bad_max_early_data(QUIC_TLS *qtls);
#endif

View File

@ -0,0 +1,220 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_QUIC_TSERVER_H
# define OSSL_QUIC_TSERVER_H
# include <openssl/ssl.h>
# include <openssl/bio.h>
# include "internal/quic_stream.h"
# include "internal/quic_channel.h"
# include "internal/statem.h"
# include "internal/time.h"
# ifndef OPENSSL_NO_QUIC
/*
* QUIC Test Server Module
* =======================
*
* This implements a QUIC test server. Since full QUIC server support is not yet
* implemented this server is limited in features and scope. It exists to
* provide a target for our QUIC client to talk to for testing purposes.
*
* A given QUIC test server instance supports only one client at a time.
*
* Note that this test server is not suitable for production use because it does
* not implement address verification, anti-amplification or retry logic.
*/
typedef struct quic_tserver_st QUIC_TSERVER;
typedef struct quic_tserver_args_st {
OSSL_LIB_CTX *libctx;
const char *propq;
SSL_CTX *ctx;
BIO *net_rbio, *net_wbio;
OSSL_TIME (*now_cb)(void *arg);
void *now_cb_arg;
const unsigned char *alpn;
size_t alpnlen;
} QUIC_TSERVER_ARGS;
QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args,
const char *certfile, const char *keyfile);
void ossl_quic_tserver_free(QUIC_TSERVER *srv);
/* Set mutator callbacks for test framework support */
int ossl_quic_tserver_set_plain_packet_mutator(QUIC_TSERVER *srv,
ossl_mutate_packet_cb mutatecb,
ossl_finish_mutate_cb finishmutatecb,
void *mutatearg);
int ossl_quic_tserver_set_handshake_mutator(QUIC_TSERVER *srv,
ossl_statem_mutate_handshake_cb mutate_handshake_cb,
ossl_statem_finish_mutate_handshake_cb finish_mutate_handshake_cb,
void *mutatearg);
/* Advances the state machine. */
int ossl_quic_tserver_tick(QUIC_TSERVER *srv);
/* Returns 1 if we have a (non-terminated) client. */
int ossl_quic_tserver_is_connected(QUIC_TSERVER *srv);
/*
* Returns 1 if we have finished the TLS handshake
*/
int ossl_quic_tserver_is_handshake_confirmed(const QUIC_TSERVER *srv);
/* Returns 1 if the server is in any terminating or terminated state */
int ossl_quic_tserver_is_term_any(const QUIC_TSERVER *srv);
const QUIC_TERMINATE_CAUSE *
ossl_quic_tserver_get_terminate_cause(const QUIC_TSERVER *srv);
/* Returns 1 if the server is in a terminated state */
int ossl_quic_tserver_is_terminated(const QUIC_TSERVER *srv);
/*
* Attempts to read from stream 0. Writes the number of bytes read to
* *bytes_read and returns 1 on success. If no bytes are available, 0 is written
* to *bytes_read and 1 is returned (this is considered a success case).
*
* Returns 0 if connection is not currently active. If the receive part of
* the stream has reached the end of stream condition, returns 0; call
* ossl_quic_tserver_has_read_ended() to identify this condition.
*/
int ossl_quic_tserver_read(QUIC_TSERVER *srv,
uint64_t stream_id,
unsigned char *buf,
size_t buf_len,
size_t *bytes_read);
/*
* Returns 1 if the read part of the stream has ended normally.
*/
int ossl_quic_tserver_has_read_ended(QUIC_TSERVER *srv, uint64_t stream_id);
/*
* Attempts to write to the given stream. Writes the number of bytes consumed to
* *bytes_written and returns 1 on success. If there is no space currently
* available to write any bytes, 0 is written to *consumed and 1 is returned
* (this is considered a success case).
*
* Note that unlike libssl public APIs, this API always works in a 'partial
* write' mode.
*
* Returns 0 if connection is not currently active.
*/
int ossl_quic_tserver_write(QUIC_TSERVER *srv,
uint64_t stream_id,
const unsigned char *buf,
size_t buf_len,
size_t *bytes_written);
/*
* Signals normal end of the stream.
*/
int ossl_quic_tserver_conclude(QUIC_TSERVER *srv, uint64_t stream_id);
/*
* Create a server-initiated stream. The stream ID of the newly
* created stream is written to *stream_id.
*/
int ossl_quic_tserver_stream_new(QUIC_TSERVER *srv,
int is_uni,
uint64_t *stream_id);
BIO *ossl_quic_tserver_get0_rbio(QUIC_TSERVER *srv);
SSL_CTX *ossl_quic_tserver_get0_ssl_ctx(QUIC_TSERVER *srv);
/*
* Returns 1 if the peer has sent a STOP_SENDING frame for a stream.
* app_error_code is written if this returns 1.
*/
int ossl_quic_tserver_stream_has_peer_stop_sending(QUIC_TSERVER *srv,
uint64_t stream_id,
uint64_t *app_error_code);
/*
* Returns 1 if the peer has sent a RESET_STREAM frame for a stream.
* app_error_code is written if this returns 1.
*/
int ossl_quic_tserver_stream_has_peer_reset_stream(QUIC_TSERVER *srv,
uint64_t stream_id,
uint64_t *app_error_code);
/*
* Replaces existing local connection ID in the underlying QUIC_CHANNEL.
*/
int ossl_quic_tserver_set_new_local_cid(QUIC_TSERVER *srv,
const QUIC_CONN_ID *conn_id);
/*
* Returns the stream ID of the next incoming stream, or UINT64_MAX if there
* currently is none.
*/
uint64_t ossl_quic_tserver_pop_incoming_stream(QUIC_TSERVER *srv);
/*
* Returns 1 if all data sent on the given stream_id has been acked by the peer.
*/
int ossl_quic_tserver_is_stream_totally_acked(QUIC_TSERVER *srv,
uint64_t stream_id);
/* Returns 1 if we are currently interested in reading data from the network */
int ossl_quic_tserver_get_net_read_desired(QUIC_TSERVER *srv);
/* Returns 1 if we are currently interested in writing data to the network */
int ossl_quic_tserver_get_net_write_desired(QUIC_TSERVER *srv);
/* Returns the next event deadline */
OSSL_TIME ossl_quic_tserver_get_deadline(QUIC_TSERVER *srv);
/*
* Shutdown the QUIC connection. Returns 1 if the connection is terminated and
* 0 otherwise.
*/
int ossl_quic_tserver_shutdown(QUIC_TSERVER *srv, uint64_t app_error_code);
/* Force generation of an ACK-eliciting packet. */
int ossl_quic_tserver_ping(QUIC_TSERVER *srv);
/* Set tracing callback on channel. */
void ossl_quic_tserver_set_msg_callback(QUIC_TSERVER *srv,
void (*f)(int write_p, int version,
int content_type,
const void *buf, size_t len,
SSL *ssl, void *arg),
void *arg);
/*
* This is similar to ossl_quic_conn_get_channel; it should be used for test
* instrumentation only and not to bypass QUIC_TSERVER for 'normal' operations.
*/
QUIC_CHANNEL *ossl_quic_tserver_get_channel(QUIC_TSERVER *srv);
/* Send a TLS new session ticket */
int ossl_quic_tserver_new_ticket(QUIC_TSERVER *srv);
/*
* Set the max_early_data value to be sent in NewSessionTickets. Only the
* values 0 and 0xffffffff are valid for use in QUIC.
*/
int ossl_quic_tserver_set_max_early_data(QUIC_TSERVER *srv,
uint32_t max_early_data);
/* Set the find session callback for getting a server PSK */
void ossl_quic_tserver_set_psk_find_session_cb(QUIC_TSERVER *srv,
SSL_psk_find_session_cb_func cb);
# endif
#endif

View File

@ -0,0 +1,209 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_QUIC_TXP_H
# define OSSL_QUIC_TXP_H
# include <openssl/ssl.h>
# include "internal/quic_types.h"
# include "internal/quic_record_tx.h"
# include "internal/quic_cfq.h"
# include "internal/quic_txpim.h"
# include "internal/quic_stream.h"
# include "internal/quic_stream_map.h"
# include "internal/quic_fc.h"
# include "internal/bio_addr.h"
# include "internal/time.h"
# ifndef OPENSSL_NO_QUIC
/*
* QUIC TX Packetiser
* ==================
*/
typedef struct ossl_quic_tx_packetiser_args_st {
/* Configuration Settings */
QUIC_CONN_ID cur_scid; /* Current Source Connection ID we use. */
QUIC_CONN_ID cur_dcid; /* Current Destination Connection ID we use. */
BIO_ADDR peer; /* Current destination L4 address we use. */
uint32_t ack_delay_exponent; /* ACK delay exponent used when encoding. */
/* Injected Dependencies */
OSSL_QTX *qtx; /* QUIC Record Layer TX we are using */
QUIC_TXPIM *txpim; /* QUIC TX'd Packet Information Manager */
QUIC_CFQ *cfq; /* QUIC Control Frame Queue */
OSSL_ACKM *ackm; /* QUIC Acknowledgement Manager */
QUIC_STREAM_MAP *qsm; /* QUIC Streams Map */
QUIC_TXFC *conn_txfc; /* QUIC Connection-Level TX Flow Controller */
QUIC_RXFC *conn_rxfc; /* QUIC Connection-Level RX Flow Controller */
QUIC_RXFC *max_streams_bidi_rxfc; /* QUIC RXFC for MAX_STREAMS generation */
QUIC_RXFC *max_streams_uni_rxfc;
const OSSL_CC_METHOD *cc_method; /* QUIC Congestion Controller */
OSSL_CC_DATA *cc_data; /* QUIC Congestion Controller Instance */
OSSL_TIME (*now)(void *arg); /* Callback to get current time. */
void *now_arg;
/*
* Injected dependencies - crypto streams.
*
* Note: There is no crypto stream for the 0-RTT EL.
* crypto[QUIC_PN_SPACE_APP] is the 1-RTT crypto stream.
*/
QUIC_SSTREAM *crypto[QUIC_PN_SPACE_NUM];
} OSSL_QUIC_TX_PACKETISER_ARGS;
typedef struct ossl_quic_tx_packetiser_st OSSL_QUIC_TX_PACKETISER;
OSSL_QUIC_TX_PACKETISER *ossl_quic_tx_packetiser_new(const OSSL_QUIC_TX_PACKETISER_ARGS *args);
typedef void (ossl_quic_initial_token_free_fn)(const unsigned char *buf,
size_t buf_len, void *arg);
void ossl_quic_tx_packetiser_free(OSSL_QUIC_TX_PACKETISER *txp);
/*
* When in the closing state we need to maintain a count of received bytes
* so that we can limit the number of close connection frames we send.
* Refer RFC 9000 s. 10.2.1 Closing Connection State.
*/
void ossl_quic_tx_packetiser_record_received_closing_bytes(
OSSL_QUIC_TX_PACKETISER *txp, size_t n);
/*
* Generates a datagram by polling the various ELs to determine if they want to
* generate any frames, and generating a datagram which coalesces packets for
* any ELs which do.
*
* Returns 0 on failure (e.g. allocation error or other errors), 1 otherwise.
*
* *status is filled with status information about the generated packet.
* It is always filled even in case of failure. In particular, packets can be
* sent even if failure is later returned.
* See QUIC_TXP_STATUS for details.
*/
typedef struct quic_txp_status_st {
int sent_ack_eliciting; /* Was an ACK-eliciting packet sent? */
int sent_handshake; /* Was a Handshake packet sent? */
size_t sent_pkt; /* Number of packets sent (0 if nothing was sent) */
} QUIC_TXP_STATUS;
int ossl_quic_tx_packetiser_generate(OSSL_QUIC_TX_PACKETISER *txp,
QUIC_TXP_STATUS *status);
/*
* Returns a deadline after which a call to ossl_quic_tx_packetiser_generate()
* might succeed even if it did not previously. This may return
* ossl_time_infinite() if there is no such deadline currently applicable. It
* returns ossl_time_zero() if there is (potentially) more data to be generated
* immediately. The value returned is liable to change after any call to
* ossl_quic_tx_packetiser_generate() (or after ACKM or CC state changes). Note
* that ossl_quic_tx_packetiser_generate() can also start to succeed for other
* non-chronological reasons, such as changes to send stream buffers, etc.
*/
OSSL_TIME ossl_quic_tx_packetiser_get_deadline(OSSL_QUIC_TX_PACKETISER *txp);
/*
* Set the token used in Initial packets. The callback is called when the buffer
* is no longer needed; for example, when the TXP is freed or when this function
* is called again with a new buffer. Fails returning 0 if the token is too big
* to ever be reasonably encapsulated in an outgoing packet based on our current
* understanding of our PMTU.
*/
int ossl_quic_tx_packetiser_set_initial_token(OSSL_QUIC_TX_PACKETISER *txp,
const unsigned char *token,
size_t token_len,
ossl_quic_initial_token_free_fn *free_cb,
void *free_cb_arg);
/* Change the DCID the TXP uses to send outgoing packets. */
int ossl_quic_tx_packetiser_set_cur_dcid(OSSL_QUIC_TX_PACKETISER *txp,
const QUIC_CONN_ID *dcid);
/* Change the SCID the TXP uses to send outgoing (long) packets. */
int ossl_quic_tx_packetiser_set_cur_scid(OSSL_QUIC_TX_PACKETISER *txp,
const QUIC_CONN_ID *scid);
/*
* Change the destination L4 address the TXP uses to send datagrams. Specify
* NULL (or AF_UNSPEC) to disable use of addressed mode.
*/
int ossl_quic_tx_packetiser_set_peer(OSSL_QUIC_TX_PACKETISER *txp,
const BIO_ADDR *peer);
/*
* Inform the TX packetiser that an EL has been discarded. Idempotent.
*
* This does not inform the QTX as well; the caller must also inform the QTX.
*
* The TXP will no longer reference the crypto[enc_level] QUIC_SSTREAM which was
* provided in the TXP arguments. However, it is the callers responsibility to
* free that QUIC_SSTREAM if desired.
*/
int ossl_quic_tx_packetiser_discard_enc_level(OSSL_QUIC_TX_PACKETISER *txp,
uint32_t enc_level);
/*
* Informs the TX packetiser that the handshake is complete. The TX packetiser
* will not send 1-RTT application data until the handshake is complete,
* as the authenticity of the peer is not confirmed until the handshake
* complete event occurs.
*/
void ossl_quic_tx_packetiser_notify_handshake_complete(OSSL_QUIC_TX_PACKETISER *txp);
/* Asks the TXP to generate a HANDSHAKE_DONE frame in the next 1-RTT packet. */
void ossl_quic_tx_packetiser_schedule_handshake_done(OSSL_QUIC_TX_PACKETISER *txp);
/* Asks the TXP to ensure the next packet in the given PN space is ACK-eliciting. */
void ossl_quic_tx_packetiser_schedule_ack_eliciting(OSSL_QUIC_TX_PACKETISER *txp,
uint32_t pn_space);
/*
* Asks the TXP to ensure an ACK is put in the next packet in the given PN
* space.
*/
void ossl_quic_tx_packetiser_schedule_ack(OSSL_QUIC_TX_PACKETISER *txp,
uint32_t pn_space);
/*
* Schedules a connection close. *f and f->reason are copied. This operation is
* irreversible and causes all further packets generated by the TXP to contain a
* CONNECTION_CLOSE frame. This function fails if it has already been called
* successfully; the information in *f cannot be changed after the first
* successful call to this function.
*/
int ossl_quic_tx_packetiser_schedule_conn_close(OSSL_QUIC_TX_PACKETISER *txp,
const OSSL_QUIC_FRAME_CONN_CLOSE *f);
/* Setters for the msg_callback and msg_callback_arg */
void ossl_quic_tx_packetiser_set_msg_callback(OSSL_QUIC_TX_PACKETISER *txp,
ossl_msg_cb msg_callback,
SSL *msg_callback_ssl);
void ossl_quic_tx_packetiser_set_msg_callback_arg(OSSL_QUIC_TX_PACKETISER *txp,
void *msg_callback_arg);
/*
* Determines the next PN which will be used for a given PN space.
*/
QUIC_PN ossl_quic_tx_packetiser_get_next_pn(OSSL_QUIC_TX_PACKETISER *txp,
uint32_t pn_space);
/*
* Sets a callback which is called whenever TXP sends an ACK frame. The callee
* must not modify the ACK frame data. Can be used to snoop on PNs being ACKed.
*/
void ossl_quic_tx_packetiser_set_ack_tx_cb(OSSL_QUIC_TX_PACKETISER *txp,
void (*cb)(const OSSL_QUIC_FRAME_ACK *ack,
uint32_t pn_space,
void *arg),
void *cb_arg);
# endif
#endif

View File

@ -0,0 +1,133 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_QUIC_TXPIM_H
# define OSSL_QUIC_TXPIM_H
# include <openssl/ssl.h>
# include "internal/quic_types.h"
# include "internal/quic_cfq.h"
# include "internal/quic_ackm.h"
# ifndef OPENSSL_NO_QUIC
/*
* QUIC Transmitted Packet Information Manager
* ===========================================
*/
typedef struct quic_txpim_st QUIC_TXPIM;
typedef struct quic_fifd_st QUIC_FIFD;
typedef struct quic_txpim_pkt_st {
/* ACKM-specific data. Caller should fill this. */
OSSL_ACKM_TX_PKT ackm_pkt;
/* Linked list of CFQ items in this packet. */
QUIC_CFQ_ITEM *retx_head;
/* Reserved for FIFD use. */
QUIC_FIFD *fifd;
/* Regenerate-strategy frames. */
unsigned int had_handshake_done_frame : 1;
unsigned int had_max_data_frame : 1;
unsigned int had_max_streams_bidi_frame : 1;
unsigned int had_max_streams_uni_frame : 1;
unsigned int had_ack_frame : 1;
unsigned int had_conn_close : 1;
/* Private data follows. */
} QUIC_TXPIM_PKT;
/* Represents a range of bytes in an application or CRYPTO stream. */
typedef struct quic_txpim_chunk_st {
/* The stream ID, or UINT64_MAX for the CRYPTO stream. */
uint64_t stream_id;
/*
* The inclusive range of bytes in the stream. Exceptionally, if end <
* start, designates a frame of zero length (used for FIN-only frames). In
* this case end is the number of the final byte (i.e., one less than the
* final size of the stream).
*/
uint64_t start, end;
/*
* Whether a FIN was sent for this stream in the packet. Not valid for
* CRYPTO stream.
*/
unsigned int has_fin : 1;
/*
* If set, a STOP_SENDING frame was sent for this stream ID. (If no data was
* sent for the stream, set end < start.)
*/
unsigned int has_stop_sending : 1;
/*
* If set, a RESET_STREAM frame was sent for this stream ID. (If no data was
* sent for the stream, set end < start.)
*/
unsigned int has_reset_stream : 1;
} QUIC_TXPIM_CHUNK;
QUIC_TXPIM *ossl_quic_txpim_new(void);
/*
* Frees the TXPIM. All QUIC_TXPIM_PKTs which have been handed out by the TXPIM
* must be released via a call to ossl_quic_txpim_pkt_release() before calling
* this function.
*/
void ossl_quic_txpim_free(QUIC_TXPIM *txpim);
/*
* Allocates a new QUIC_TXPIM_PKT structure from the pool. Returns NULL on
* failure. The returned structure is cleared of all data and is in a fresh
* initial state.
*/
QUIC_TXPIM_PKT *ossl_quic_txpim_pkt_alloc(QUIC_TXPIM *txpim);
/*
* Releases the TXPIM packet, returning it to the pool.
*/
void ossl_quic_txpim_pkt_release(QUIC_TXPIM *txpim, QUIC_TXPIM_PKT *fpkt);
/* Clears the chunk list of the packet, removing all entries. */
void ossl_quic_txpim_pkt_clear_chunks(QUIC_TXPIM_PKT *fpkt);
/* Appends a chunk to the packet. The structure is copied. */
int ossl_quic_txpim_pkt_append_chunk(QUIC_TXPIM_PKT *fpkt,
const QUIC_TXPIM_CHUNK *chunk);
/* Adds a CFQ item to the packet by prepending it to the retx_head list. */
void ossl_quic_txpim_pkt_add_cfq_item(QUIC_TXPIM_PKT *fpkt,
QUIC_CFQ_ITEM *item);
/*
* Returns a pointer to an array of stream chunk information structures for the
* given packet. The caller must call ossl_quic_txpim_pkt_get_num_chunks() to
* determine the length of this array. The returned pointer is invalidated
* if the chunk list is mutated, for example via a call to
* ossl_quic_txpim_pkt_append_chunk() or ossl_quic_txpim_pkt_clear_chunks().
*
* The chunks are sorted by (stream_id, start) in ascending order.
*/
const QUIC_TXPIM_CHUNK *ossl_quic_txpim_pkt_get_chunks(const QUIC_TXPIM_PKT *fpkt);
/*
* Returns the number of entries in the array returned by
* ossl_quic_txpim_pkt_get_chunks().
*/
size_t ossl_quic_txpim_pkt_get_num_chunks(const QUIC_TXPIM_PKT *fpkt);
/*
* Returns the number of QUIC_TXPIM_PKTs allocated by the given TXPIM that have
* yet to be returned to the TXPIM.
*/
size_t ossl_quic_txpim_get_in_use(const QUIC_TXPIM *txpim);
# endif
#endif

View File

@ -0,0 +1,116 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_QUIC_TYPES_H
# define OSSL_QUIC_TYPES_H
# include <openssl/ssl.h>
# include <internal/ssl.h>
# include <assert.h>
# include <string.h>
# ifndef OPENSSL_NO_QUIC
/* QUIC encryption levels. */
enum {
QUIC_ENC_LEVEL_INITIAL = 0,
QUIC_ENC_LEVEL_HANDSHAKE,
QUIC_ENC_LEVEL_0RTT,
QUIC_ENC_LEVEL_1RTT,
QUIC_ENC_LEVEL_NUM /* Must be the ultimate entry */
};
/* QUIC packet number spaces. */
enum {
QUIC_PN_SPACE_INITIAL = 0,
QUIC_PN_SPACE_HANDSHAKE,
/* New entries must go here, so that QUIC_PN_SPACE_APP is the penultimate */
QUIC_PN_SPACE_APP,
QUIC_PN_SPACE_NUM /* Must be the ultimate entry */
};
static ossl_unused ossl_inline uint32_t
ossl_quic_enc_level_to_pn_space(uint32_t enc_level)
{
switch (enc_level) {
case QUIC_ENC_LEVEL_INITIAL:
return QUIC_PN_SPACE_INITIAL;
case QUIC_ENC_LEVEL_HANDSHAKE:
return QUIC_PN_SPACE_HANDSHAKE;
case QUIC_ENC_LEVEL_0RTT:
case QUIC_ENC_LEVEL_1RTT:
return QUIC_PN_SPACE_APP;
default:
assert(0);
return QUIC_PN_SPACE_APP;
}
}
/* QUIC packet number representation. */
typedef uint64_t QUIC_PN;
# define QUIC_PN_INVALID UINT64_MAX
static ossl_unused ossl_inline QUIC_PN ossl_quic_pn_max(QUIC_PN a, QUIC_PN b)
{
return a > b ? a : b;
}
static ossl_unused ossl_inline QUIC_PN ossl_quic_pn_min(QUIC_PN a, QUIC_PN b)
{
return a < b ? a : b;
}
static ossl_unused ossl_inline int ossl_quic_pn_valid(QUIC_PN pn)
{
return pn < (((QUIC_PN)1) << 62);
}
/* QUIC connection ID representation. */
# define QUIC_MAX_CONN_ID_LEN 20
typedef struct quic_conn_id_st {
unsigned char id_len, id[QUIC_MAX_CONN_ID_LEN];
} QUIC_CONN_ID;
static ossl_unused ossl_inline int ossl_quic_conn_id_eq(const QUIC_CONN_ID *a,
const QUIC_CONN_ID *b)
{
if (a->id_len != b->id_len || a->id_len > QUIC_MAX_CONN_ID_LEN)
return 0;
return memcmp(a->id, b->id, a->id_len) == 0;
}
# define QUIC_MIN_INITIAL_DGRAM_LEN 1200
# define QUIC_DEFAULT_ACK_DELAY_EXP 3
# define QUIC_MAX_ACK_DELAY_EXP 20
# define QUIC_DEFAULT_MAX_ACK_DELAY 25
# define QUIC_MIN_ACTIVE_CONN_ID_LIMIT 2
/* Arbitrary choice of default idle timeout (not an RFC value). */
# define QUIC_DEFAULT_IDLE_TIMEOUT 30000
# define QUIC_STATELESS_RESET_TOKEN_LEN 16
typedef struct {
unsigned char token[QUIC_STATELESS_RESET_TOKEN_LEN];
} QUIC_STATELESS_RESET_TOKEN;
/*
* An encoded preferred_addr transport parameter cannot be shorter or longer
* than these lengths in bytes.
*/
# define QUIC_MIN_ENCODED_PREFERRED_ADDR_LEN 41
# define QUIC_MAX_ENCODED_PREFERRED_ADDR_LEN 61
# endif
#endif

View File

@ -0,0 +1,127 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_INTERNAL_QUIC_VLINT_H
# define OSSL_INTERNAL_QUIC_VLINT_H
# pragma once
# include "internal/e_os.h"
# ifndef OPENSSL_NO_QUIC
/* The smallest value requiring a 1, 2, 4, or 8-byte representation. */
#define OSSL_QUIC_VLINT_1B_MIN 0
#define OSSL_QUIC_VLINT_2B_MIN 64
#define OSSL_QUIC_VLINT_4B_MIN 16384
#define OSSL_QUIC_VLINT_8B_MIN 1073741824
/* The largest value representable in a given number of bytes. */
#define OSSL_QUIC_VLINT_1B_MAX (OSSL_QUIC_VLINT_2B_MIN - 1)
#define OSSL_QUIC_VLINT_2B_MAX (OSSL_QUIC_VLINT_4B_MIN - 1)
#define OSSL_QUIC_VLINT_4B_MAX (OSSL_QUIC_VLINT_8B_MIN - 1)
#define OSSL_QUIC_VLINT_8B_MAX (((uint64_t)1 << 62) - 1)
/* The largest value representable as a variable-length integer. */
#define OSSL_QUIC_VLINT_MAX OSSL_QUIC_VLINT_8B_MAX
/*
* Returns the number of bytes needed to encode v in the QUIC variable-length
* integer encoding.
*
* Returns 0 if v exceeds OSSL_QUIC_VLINT_MAX.
*/
static ossl_unused ossl_inline size_t ossl_quic_vlint_encode_len(uint64_t v)
{
if (v < OSSL_QUIC_VLINT_2B_MIN)
return 1;
if (v < OSSL_QUIC_VLINT_4B_MIN)
return 2;
if (v < OSSL_QUIC_VLINT_8B_MIN)
return 4;
if (v <= OSSL_QUIC_VLINT_MAX)
return 8;
return 0;
}
/*
* This function writes a QUIC varable-length encoded integer to buf.
* The smallest usable representation is used.
*
* It is the caller's responsibility to ensure that the buffer is big enough by
* calling ossl_quic_vlint_encode_len(v) before calling this function.
*
* Precondition: buf is at least ossl_quic_vlint_enc_len(v) bytes in size
* (unchecked)
* Precondition: v does not exceed OSSL_QUIC_VLINT_MAX
* (unchecked)
*/
void ossl_quic_vlint_encode(unsigned char *buf, uint64_t v);
/*
* This function writes a QUIC variable-length encoded integer to buf. The
* specified number of bytes n are used for the encoding, which means that the
* encoded value may take up more space than necessary.
*
* It is the caller's responsibility to ensure that the buffer is of at least n
* bytes, and that v is representable by a n-byte QUIC variable-length integer.
* The representable ranges are:
*
* 1-byte encoding: [0, 2** 6-1]
* 2-byte encoding: [0, 2**14-1]
* 4-byte encoding: [0, 2**30-1]
* 8-byte encoding: [0, 2**62-1]
*
* Precondition: buf is at least n bytes in size (unchecked)
* Precondition: v does not exceed the representable range
* (ossl_quic_vlint_encode_len(v) <= n) (unchecked)
* Precondition: v does not exceed OSSL_QUIC_VLINT_MAX
* (unchecked)
*/
void ossl_quic_vlint_encode_n(unsigned char *buf, uint64_t v, int n);
/*
* Given the first byte of an encoded QUIC variable-length integer, returns
* the number of bytes comprising the encoded integer, including the first
* byte.
*/
static ossl_unused ossl_inline size_t ossl_quic_vlint_decode_len(uint8_t first_byte)
{
return 1U << ((first_byte & 0xC0) >> 6);
}
/*
* Given a buffer containing an encoded QUIC variable-length integer, returns
* the decoded value. The buffer must be of at least
* ossl_quic_vlint_decode_len(buf[0]) bytes in size, and the caller is responsible
* for checking this.
*
* Precondition: buf is at least ossl_quic_vlint_decode_len(buf[0]) bytes in size
* (unchecked)
*/
uint64_t ossl_quic_vlint_decode_unchecked(const unsigned char *buf);
/*
* Given a buffer buf of buf_len bytes in length, attempts to decode an encoded
* QUIC variable-length integer at the start of the buffer and writes the result
* to *v. If buf_len is inadequate, suggesting a truncated encoded integer, the
* function fails and 0 is returned. Otherwise, returns the number of bytes
* consumed.
*
* Precondition: buf is at least buf_len bytes in size
* Precondition: v (unchecked)
*/
int ossl_quic_vlint_decode(const unsigned char *buf, size_t buf_len, uint64_t *v);
# endif
#endif

View File

@ -0,0 +1,784 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_INTERNAL_QUIC_WIRE_H
# define OSSL_INTERNAL_QUIC_WIRE_H
# pragma once
# include "internal/e_os.h"
# include "internal/time.h"
# include "internal/quic_types.h"
# include "internal/packet_quic.h"
# ifndef OPENSSL_NO_QUIC
# define OSSL_QUIC_FRAME_TYPE_PADDING 0x00
# define OSSL_QUIC_FRAME_TYPE_PING 0x01
# define OSSL_QUIC_FRAME_TYPE_ACK_WITHOUT_ECN 0x02
# define OSSL_QUIC_FRAME_TYPE_ACK_WITH_ECN 0x03
# define OSSL_QUIC_FRAME_TYPE_RESET_STREAM 0x04
# define OSSL_QUIC_FRAME_TYPE_STOP_SENDING 0x05
# define OSSL_QUIC_FRAME_TYPE_CRYPTO 0x06
# define OSSL_QUIC_FRAME_TYPE_NEW_TOKEN 0x07
# define OSSL_QUIC_FRAME_TYPE_MAX_DATA 0x10
# define OSSL_QUIC_FRAME_TYPE_MAX_STREAM_DATA 0x11
# define OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_BIDI 0x12
# define OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_UNI 0x13
# define OSSL_QUIC_FRAME_TYPE_DATA_BLOCKED 0x14
# define OSSL_QUIC_FRAME_TYPE_STREAM_DATA_BLOCKED 0x15
# define OSSL_QUIC_FRAME_TYPE_STREAMS_BLOCKED_BIDI 0x16
# define OSSL_QUIC_FRAME_TYPE_STREAMS_BLOCKED_UNI 0x17
# define OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID 0x18
# define OSSL_QUIC_FRAME_TYPE_RETIRE_CONN_ID 0x19
# define OSSL_QUIC_FRAME_TYPE_PATH_CHALLENGE 0x1A
# define OSSL_QUIC_FRAME_TYPE_PATH_RESPONSE 0x1B
# define OSSL_QUIC_FRAME_TYPE_CONN_CLOSE_TRANSPORT 0x1C
# define OSSL_QUIC_FRAME_TYPE_CONN_CLOSE_APP 0x1D
# define OSSL_QUIC_FRAME_TYPE_HANDSHAKE_DONE 0x1E
# define OSSL_QUIC_FRAME_FLAG_STREAM_FIN 0x01
# define OSSL_QUIC_FRAME_FLAG_STREAM_LEN 0x02
# define OSSL_QUIC_FRAME_FLAG_STREAM_OFF 0x04
# define OSSL_QUIC_FRAME_FLAG_STREAM_MASK ((uint64_t)0x07)
/* Low 3 bits of the type contain flags */
# define OSSL_QUIC_FRAME_TYPE_STREAM 0x08 /* base ID */
# define OSSL_QUIC_FRAME_TYPE_STREAM_FIN \
(OSSL_QUIC_FRAME_TYPE_STREAM | \
OSSL_QUIC_FRAME_FLAG_STREAM_FIN)
# define OSSL_QUIC_FRAME_TYPE_STREAM_LEN \
(OSSL_QUIC_FRAME_TYPE_STREAM | \
OSSL_QUIC_FRAME_FLAG_STREAM_LEN)
# define OSSL_QUIC_FRAME_TYPE_STREAM_LEN_FIN \
(OSSL_QUIC_FRAME_TYPE_STREAM | \
OSSL_QUIC_FRAME_FLAG_STREAM_LEN | \
OSSL_QUIC_FRAME_FLAG_STREAM_FIN)
# define OSSL_QUIC_FRAME_TYPE_STREAM_OFF \
(OSSL_QUIC_FRAME_TYPE_STREAM | \
OSSL_QUIC_FRAME_FLAG_STREAM_OFF)
# define OSSL_QUIC_FRAME_TYPE_STREAM_OFF_FIN \
(OSSL_QUIC_FRAME_TYPE_STREAM | \
OSSL_QUIC_FRAME_FLAG_STREAM_OFF | \
OSSL_QUIC_FRAME_FLAG_STREAM_FIN)
# define OSSL_QUIC_FRAME_TYPE_STREAM_OFF_LEN \
(OSSL_QUIC_FRAME_TYPE_STREAM | \
OSSL_QUIC_FRAME_FLAG_STREAM_OFF | \
OSSL_QUIC_FRAME_FLAG_STREAM_LEN)
# define OSSL_QUIC_FRAME_TYPE_STREAM_OFF_LEN_FIN \
(OSSL_QUIC_FRAME_TYPE_STREAM | \
OSSL_QUIC_FRAME_FLAG_STREAM_OFF | \
OSSL_QUIC_FRAME_FLAG_STREAM_LEN | \
OSSL_QUIC_FRAME_FLAG_STREAM_FIN)
# define OSSL_QUIC_FRAME_TYPE_IS_STREAM(x) \
(((x) & ~OSSL_QUIC_FRAME_FLAG_STREAM_MASK) == OSSL_QUIC_FRAME_TYPE_STREAM)
# define OSSL_QUIC_FRAME_TYPE_IS_ACK(x) \
(((x) & ~(uint64_t)1) == OSSL_QUIC_FRAME_TYPE_ACK_WITHOUT_ECN)
# define OSSL_QUIC_FRAME_TYPE_IS_MAX_STREAMS(x) \
(((x) & ~(uint64_t)1) == OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_BIDI)
# define OSSL_QUIC_FRAME_TYPE_IS_STREAMS_BLOCKED(x) \
(((x) & ~(uint64_t)1) == OSSL_QUIC_FRAME_TYPE_STREAMS_BLOCKED_BIDI)
# define OSSL_QUIC_FRAME_TYPE_IS_CONN_CLOSE(x) \
(((x) & ~(uint64_t)1) == OSSL_QUIC_FRAME_TYPE_CONN_CLOSE_TRANSPORT)
const char *ossl_quic_frame_type_to_string(uint64_t frame_type);
static ossl_unused ossl_inline int
ossl_quic_frame_type_is_ack_eliciting(uint64_t frame_type)
{
switch (frame_type) {
case OSSL_QUIC_FRAME_TYPE_PADDING:
case OSSL_QUIC_FRAME_TYPE_ACK_WITHOUT_ECN:
case OSSL_QUIC_FRAME_TYPE_ACK_WITH_ECN:
case OSSL_QUIC_FRAME_TYPE_CONN_CLOSE_TRANSPORT:
case OSSL_QUIC_FRAME_TYPE_CONN_CLOSE_APP:
return 0;
default:
return 1;
}
}
/* QUIC Transport Parameter Types */
# define QUIC_TPARAM_ORIG_DCID 0x00
# define QUIC_TPARAM_MAX_IDLE_TIMEOUT 0x01
# define QUIC_TPARAM_STATELESS_RESET_TOKEN 0x02
# define QUIC_TPARAM_MAX_UDP_PAYLOAD_SIZE 0x03
# define QUIC_TPARAM_INITIAL_MAX_DATA 0x04
# define QUIC_TPARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL 0x05
# define QUIC_TPARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE 0x06
# define QUIC_TPARAM_INITIAL_MAX_STREAM_DATA_UNI 0x07
# define QUIC_TPARAM_INITIAL_MAX_STREAMS_BIDI 0x08
# define QUIC_TPARAM_INITIAL_MAX_STREAMS_UNI 0x09
# define QUIC_TPARAM_ACK_DELAY_EXP 0x0A
# define QUIC_TPARAM_MAX_ACK_DELAY 0x0B
# define QUIC_TPARAM_DISABLE_ACTIVE_MIGRATION 0x0C
# define QUIC_TPARAM_PREFERRED_ADDR 0x0D
# define QUIC_TPARAM_ACTIVE_CONN_ID_LIMIT 0x0E
# define QUIC_TPARAM_INITIAL_SCID 0x0F
# define QUIC_TPARAM_RETRY_SCID 0x10
/*
* QUIC Frame Logical Representations
* ==================================
*/
/* QUIC Frame: ACK */
typedef struct ossl_quic_ack_range_st {
/*
* Represents an inclusive range of packet numbers [start, end].
* start must be <= end.
*/
QUIC_PN start, end;
} OSSL_QUIC_ACK_RANGE;
typedef struct ossl_quic_frame_ack_st {
/*
* A sequence of packet number ranges [[start, end]...].
*
* The ranges must be sorted in descending order, for example:
* [ 95, 100]
* [ 90, 92]
* etc.
*
* As such, ack_ranges[0].end is always the highest packet number
* being acknowledged and ack_ranges[num_ack_ranges-1].start is
* always the lowest packet number being acknowledged.
*
* num_ack_ranges must be greater than zero, as an ACK frame must
* acknowledge at least one packet number.
*/
OSSL_QUIC_ACK_RANGE *ack_ranges;
size_t num_ack_ranges;
OSSL_TIME delay_time;
uint64_t ect0, ect1, ecnce;
unsigned int ecn_present : 1;
} OSSL_QUIC_FRAME_ACK;
/* Returns 1 if the given frame contains the given PN. */
int ossl_quic_frame_ack_contains_pn(const OSSL_QUIC_FRAME_ACK *ack, QUIC_PN pn);
/* QUIC Frame: STREAM */
typedef struct ossl_quic_frame_stream_st {
uint64_t stream_id; /* Stream ID */
uint64_t offset; /* Logical offset in stream */
uint64_t len; /* Length of data in bytes */
const unsigned char *data;
/*
* On encode, this determines whether the len field should be encoded or
* not. If zero, the len field is not encoded and it is assumed the frame
* runs to the end of the packet.
*
* On decode, this determines whether the frame had an explicitly encoded
* length. If not set, the frame runs to the end of the packet and len has
* been set accordingly.
*/
unsigned int has_explicit_len : 1;
/* 1 if this is the end of the stream */
unsigned int is_fin : 1;
} OSSL_QUIC_FRAME_STREAM;
/* QUIC Frame: CRYPTO */
typedef struct ossl_quic_frame_crypto_st {
uint64_t offset; /* Logical offset in stream */
uint64_t len; /* Length of the data in bytes */
const unsigned char *data;
} OSSL_QUIC_FRAME_CRYPTO;
/* QUIC Frame: RESET_STREAM */
typedef struct ossl_quic_frame_reset_stream_st {
uint64_t stream_id;
uint64_t app_error_code;
uint64_t final_size;
} OSSL_QUIC_FRAME_RESET_STREAM;
/* QUIC Frame: STOP_SENDING */
typedef struct ossl_quic_frame_stop_sending_st {
uint64_t stream_id;
uint64_t app_error_code;
} OSSL_QUIC_FRAME_STOP_SENDING;
/* QUIC Frame: NEW_CONNECTION_ID */
typedef struct ossl_quic_frame_new_conn_id_st {
uint64_t seq_num;
uint64_t retire_prior_to;
QUIC_CONN_ID conn_id;
QUIC_STATELESS_RESET_TOKEN stateless_reset;
} OSSL_QUIC_FRAME_NEW_CONN_ID;
/* QUIC Frame: CONNECTION_CLOSE */
typedef struct ossl_quic_frame_conn_close_st {
unsigned int is_app : 1; /* 0: transport error, 1: app error */
uint64_t error_code; /* 62-bit transport or app error code */
uint64_t frame_type; /* transport errors only */
char *reason; /* UTF-8 string, not necessarily zero-terminated */
size_t reason_len; /* Length of reason in bytes */
} OSSL_QUIC_FRAME_CONN_CLOSE;
/*
* QUIC Wire Format Encoding
* =========================
*
* These functions return 1 on success and 0 on failure.
*/
/*
* Encodes zero or more QUIC PADDING frames to the packet writer. Each PADDING
* frame consumes one byte; num_bytes specifies the number of bytes of padding
* to write.
*/
int ossl_quic_wire_encode_padding(WPACKET *pkt, size_t num_bytes);
/*
* Encodes a QUIC PING frame to the packet writer. This frame type takes
* no arguments.
*/
int ossl_quic_wire_encode_frame_ping(WPACKET *pkt);
/*
* Encodes a QUIC ACK frame to the packet writer, given a logical representation
* of the ACK frame.
*
* The ACK ranges passed must be sorted in descending order.
*
* The logical representation stores a list of packet number ranges. The wire
* encoding is slightly different and stores the first range in the list
* in a different manner.
*
* The ack_delay_exponent argument specifies the index of a power of two by
* which the ack->ack_delay field is be divided. This exponent value must match
* the value used when decoding.
*/
int ossl_quic_wire_encode_frame_ack(WPACKET *pkt,
uint32_t ack_delay_exponent,
const OSSL_QUIC_FRAME_ACK *ack);
/*
* Encodes a QUIC RESET_STREAM frame to the packet writer, given a logical
* representation of the RESET_STREAM frame.
*/
int ossl_quic_wire_encode_frame_reset_stream(WPACKET *pkt,
const OSSL_QUIC_FRAME_RESET_STREAM *f);
/*
* Encodes a QUIC STOP_SENDING frame to the packet writer, given a logical
* representation of the STOP_SENDING frame.
*/
int ossl_quic_wire_encode_frame_stop_sending(WPACKET *pkt,
const OSSL_QUIC_FRAME_STOP_SENDING *f);
/*
* Encodes a QUIC CRYPTO frame header to the packet writer.
*
* To create a well-formed frame, the data written using this function must be
* immediately followed by f->len bytes of data.
*/
int ossl_quic_wire_encode_frame_crypto_hdr(WPACKET *hdr,
const OSSL_QUIC_FRAME_CRYPTO *f);
/*
* Returns the number of bytes which will be required to encode the given
* CRYPTO frame header. Does not include the payload bytes in the count.
* Returns 0 if input is invalid.
*/
size_t ossl_quic_wire_get_encoded_frame_len_crypto_hdr(const OSSL_QUIC_FRAME_CRYPTO *f);
/*
* Encodes a QUIC CRYPTO frame to the packet writer.
*
* This function returns a pointer to a buffer of f->len bytes which the caller
* should fill however it wishes. If f->data is non-NULL, it is automatically
* copied to the target buffer, otherwise the caller must fill the returned
* buffer. Returns NULL on failure.
*/
void *ossl_quic_wire_encode_frame_crypto(WPACKET *pkt,
const OSSL_QUIC_FRAME_CRYPTO *f);
/*
* Encodes a QUIC NEW_TOKEN frame to the packet writer.
*/
int ossl_quic_wire_encode_frame_new_token(WPACKET *pkt,
const unsigned char *token,
size_t token_len);
/*
* Encodes a QUIC STREAM frame's header to the packet writer. The f->stream_id,
* f->offset and f->len fields are the values for the respective Stream ID,
* Offset and Length fields.
*
* If f->is_fin is non-zero, the frame is marked as the final frame in the
* stream.
*
* If f->has_explicit_len is zerro, the frame is assumed to be the final frame
* in the packet, which the caller is responsible for ensuring; the Length
* field is then omitted.
*
* To create a well-formed frame, the data written using this function must be
* immediately followed by f->len bytes of stream data.
*/
int ossl_quic_wire_encode_frame_stream_hdr(WPACKET *pkt,
const OSSL_QUIC_FRAME_STREAM *f);
/*
* Returns the number of bytes which will be required to encode the given
* STREAM frame header. Does not include the payload bytes in the count.
* Returns 0 if input is invalid.
*/
size_t ossl_quic_wire_get_encoded_frame_len_stream_hdr(const OSSL_QUIC_FRAME_STREAM *f);
/*
* Functions similarly to ossl_quic_wire_encode_frame_stream_hdr, but it also
* allocates space for f->len bytes of data after the header, creating a
* well-formed QUIC STREAM frame in one call.
*
* A pointer to the bytes allocated for the framme payload is returned,
* which the caller can fill however it wishes. If f->data is non-NULL,
* it is automatically copied to the target buffer, otherwise the caller
* must fill the returned buffer. Returns NULL on failure.
*/
void *ossl_quic_wire_encode_frame_stream(WPACKET *pkt,
const OSSL_QUIC_FRAME_STREAM *f);
/*
* Encodes a QUIC MAX_DATA frame to the packet writer.
*/
int ossl_quic_wire_encode_frame_max_data(WPACKET *pkt,
uint64_t max_data);
/*
* Encodes a QUIC MAX_STREAM_DATA frame to the packet writer.
*/
int ossl_quic_wire_encode_frame_max_stream_data(WPACKET *pkt,
uint64_t stream_id,
uint64_t max_data);
/*
* Encodes a QUIC MAX_STREAMS frame to the packet writer.
*
* If is_uni is 0, the count specifies the maximum number of
* bidirectional streams; else it specifies the maximum number of unidirectional
* streams.
*/
int ossl_quic_wire_encode_frame_max_streams(WPACKET *pkt,
char is_uni,
uint64_t max_streams);
/*
* Encodes a QUIC DATA_BLOCKED frame to the packet writer.
*/
int ossl_quic_wire_encode_frame_data_blocked(WPACKET *pkt,
uint64_t max_data);
/*
* Encodes a QUIC STREAM_DATA_BLOCKED frame to the packet writer.
*/
int ossl_quic_wire_encode_frame_stream_data_blocked(WPACKET *pkt,
uint64_t stream_id,
uint64_t max_stream_data);
/*
* Encodes a QUIC STREAMS_BLOCKED frame to the packet writer.
*
* If is_uni is 0, the count specifies the maximum number of
* bidirectional streams; else it specifies the maximum number of unidirectional
* streams.
*/
int ossl_quic_wire_encode_frame_streams_blocked(WPACKET *pkt,
char is_uni,
uint64_t max_streams);
/*
* Encodes a QUIC NEW_CONNECTION_ID frame to the packet writer, given a logical
* representation of the NEW_CONNECTION_ID frame.
*
* The buffer pointed to by the conn_id field must be valid for the duration of
* the call.
*/
int ossl_quic_wire_encode_frame_new_conn_id(WPACKET *pkt,
const OSSL_QUIC_FRAME_NEW_CONN_ID *f);
/*
* Encodes a QUIC RETIRE_CONNECTION_ID frame to the packet writer.
*/
int ossl_quic_wire_encode_frame_retire_conn_id(WPACKET *pkt,
uint64_t seq_num);
/*
* Encodes a QUIC PATH_CHALLENGE frame to the packet writer.
*/
int ossl_quic_wire_encode_frame_path_challenge(WPACKET *pkt,
uint64_t data);
/*
* Encodes a QUIC PATH_RESPONSE frame to the packet writer.
*/
int ossl_quic_wire_encode_frame_path_response(WPACKET *pkt,
uint64_t data);
/*
* Encodes a QUIC CONNECTION_CLOSE frame to the packet writer, given a logical
* representation of the CONNECTION_CLOSE frame.
*
* The reason field may be NULL, in which case no reason is encoded. If the
* reason field is non-NULL, it must point to a valid UTF-8 string and
* reason_len must be set to the length of the reason string in bytes. The
* reason string need not be zero terminated.
*/
int ossl_quic_wire_encode_frame_conn_close(WPACKET *pkt,
const OSSL_QUIC_FRAME_CONN_CLOSE *f);
/*
* Encodes a QUIC HANDSHAKE_DONE frame to the packet writer. This frame type
* takes no arguiments.
*/
int ossl_quic_wire_encode_frame_handshake_done(WPACKET *pkt);
/*
* Encodes a QUIC transport parameter TLV with the given ID into the WPACKET.
* The payload is an arbitrary buffer.
*
* If value is non-NULL, the value is copied into the packet.
* If it is NULL, value_len bytes are allocated for the payload and the caller
* should fill the buffer using the returned pointer.
*
* Returns a pointer to the start of the payload on success, or NULL on failure.
*/
unsigned char *ossl_quic_wire_encode_transport_param_bytes(WPACKET *pkt,
uint64_t id,
const unsigned char *value,
size_t value_len);
/*
* Encodes a QUIC transport parameter TLV with the given ID into the WPACKET.
* The payload is a QUIC variable-length integer with the given value.
*/
int ossl_quic_wire_encode_transport_param_int(WPACKET *pkt,
uint64_t id,
uint64_t value);
/*
* Encodes a QUIC transport parameter TLV with a given ID into the WPACKET.
* The payload is a QUIC connection ID.
*/
int ossl_quic_wire_encode_transport_param_cid(WPACKET *wpkt,
uint64_t id,
const QUIC_CONN_ID *cid);
/*
* QUIC Wire Format Decoding
* =========================
*
* These functions return 1 on success or 0 for failure. Typical reasons
* why these functions may fail include:
*
* - A frame decode function is called but the frame in the PACKET's buffer
* is not of the correct type.
*
* - A variable-length field in the encoded frame appears to exceed the bounds
* of the PACKET's buffer.
*
* These functions should be called with the PACKET pointing to the start of the
* frame (including the initial type field), and consume an entire frame
* including its type field. The expectation is that the caller will have
* already discerned the frame type using ossl_quic_wire_peek_frame_header().
*/
/*
* Decodes the type field header of a QUIC frame (without advancing the current
* position). This can be used to determine the frame type and determine which
* frame decoding function to call.
*/
int ossl_quic_wire_peek_frame_header(PACKET *pkt, uint64_t *type,
int *was_minimal);
/*
* Like ossl_quic_wire_peek_frame_header, but advances the current position
* so that the type field is consumed. For advanced use only.
*/
int ossl_quic_wire_skip_frame_header(PACKET *pkt, uint64_t *type);
/*
* Determines how many ranges are needed to decode a QUIC ACK frame.
*
* The number of ranges which must be allocated before the call to
* ossl_quic_wire_decode_frame_ack is written to *total_ranges.
*
* The PACKET is not advanced.
*/
int ossl_quic_wire_peek_frame_ack_num_ranges(const PACKET *pkt,
uint64_t *total_ranges);
/*
* Decodes a QUIC ACK frame. The ack_ranges field of the passed structure should
* point to a preallocated array of ACK ranges and the num_ack_ranges field
* should specify the length of allocation.
*
* *total_ranges is written with the number of ranges in the decoded frame,
* which may be greater than the number of ranges which were decoded (i.e. if
* num_ack_ranges was too small to decode all ranges).
*
* On success, this function modifies the num_ack_ranges field to indicate the
* number of ranges in the decoded frame. This is the number of entries in the
* ACK ranges array written by this function; any additional entries are not
* modified.
*
* If the number of ACK ranges in the decoded frame exceeds that in
* num_ack_ranges, as many ACK ranges as possible are decoded into the range
* array. The caller can use the value written to *total_ranges to detect this
* condition, as *total_ranges will exceed num_ack_ranges.
*
* If ack is NULL, the frame is still decoded, but only *total_ranges is
* written. This can be used to determine the number of ranges which must be
* allocated.
*
* The ack_delay_exponent argument specifies the index of a power of two used to
* decode the ack_delay field. This must match the ack_delay_exponent value used
* to encode the frame.
*/
int ossl_quic_wire_decode_frame_ack(PACKET *pkt,
uint32_t ack_delay_exponent,
OSSL_QUIC_FRAME_ACK *ack,
uint64_t *total_ranges);
/*
* Decodes a QUIC RESET_STREAM frame.
*/
int ossl_quic_wire_decode_frame_reset_stream(PACKET *pkt,
OSSL_QUIC_FRAME_RESET_STREAM *f);
/*
* Decodes a QUIC STOP_SENDING frame.
*/
int ossl_quic_wire_decode_frame_stop_sending(PACKET *pkt,
OSSL_QUIC_FRAME_STOP_SENDING *f);
/*
* Decodes a QUIC CRYPTO frame.
*
* f->data is set to point inside the packet buffer inside the PACKET, therefore
* it is safe to access for as long as the packet buffer exists. If nodata is
* set to 1 then reading the PACKET stops after the frame header and f->data is
* set to NULL.
*/
int ossl_quic_wire_decode_frame_crypto(PACKET *pkt, int nodata,
OSSL_QUIC_FRAME_CRYPTO *f);
/*
* Decodes a QUIC NEW_TOKEN frame. *token is written with a pointer to the token
* bytes and *token_len is written with the length of the token in bytes.
*/
int ossl_quic_wire_decode_frame_new_token(PACKET *pkt,
const unsigned char **token,
size_t *token_len);
/*
* Decodes a QUIC STREAM frame.
*
* If nodata is set to 1 then reading the PACKET stops after the frame header
* and f->data is set to NULL. In this case f->len will also be 0 in the event
* that "has_explicit_len" is 0.
*
* If the frame did not contain an offset field, f->offset is set to 0, as the
* absence of an offset field is equivalent to an offset of 0.
*
* If the frame contained a length field, f->has_explicit_len is set to 1 and
* the length of the data is placed in f->len. This function ensures that the
* length does not exceed the packet buffer, thus it is safe to access f->data.
*
* If the frame did not contain a length field, this means that the frame runs
* until the end of the packet. This function sets f->has_explicit_len to zero,
* and f->len to the amount of data remaining in the input buffer. Therefore,
* this function should be used with a PACKET representing a single packet (and
* not e.g. multiple packets).
*
* Note also that this means f->len is always valid after this function returns
* successfully, regardless of the value of f->has_explicit_len.
*
* f->data points inside the packet buffer inside the PACKET, therefore it is
* safe to access for as long as the packet buffer exists.
*
* f->is_fin is set according to whether the frame was marked as ending the
* stream.
*/
int ossl_quic_wire_decode_frame_stream(PACKET *pkt, int nodata,
OSSL_QUIC_FRAME_STREAM *f);
/*
* Decodes a QUIC MAX_DATA frame. The Maximum Data field is written to
* *max_data.
*/
int ossl_quic_wire_decode_frame_max_data(PACKET *pkt,
uint64_t *max_data);
/*
* Decodes a QUIC MAX_STREAM_DATA frame. The Stream ID is written to *stream_id
* and Maximum Stream Data field is written to *max_stream_data.
*/
int ossl_quic_wire_decode_frame_max_stream_data(PACKET *pkt,
uint64_t *stream_id,
uint64_t *max_stream_data);
/*
* Decodes a QUIC MAX_STREAMS frame. The Maximum Streams field is written to
* *max_streams.
*
* Whether the limit concerns bidirectional streams or unidirectional streams is
* denoted by the frame type; the caller should examine the frame type to
* determine this.
*/
int ossl_quic_wire_decode_frame_max_streams(PACKET *pkt,
uint64_t *max_streams);
/*
* Decodes a QUIC DATA_BLOCKED frame. The Maximum Data field is written to
* *max_data.
*/
int ossl_quic_wire_decode_frame_data_blocked(PACKET *pkt,
uint64_t *max_data);
/*
* Decodes a QUIC STREAM_DATA_BLOCKED frame. The Stream ID and Maximum Stream
* Data fields are written to *stream_id and *max_stream_data respectively.
*/
int ossl_quic_wire_decode_frame_stream_data_blocked(PACKET *pkt,
uint64_t *stream_id,
uint64_t *max_stream_data);
/*
* Decodes a QUIC STREAMS_BLOCKED frame. The Maximum Streams field is written to
* *max_streams.
*
* Whether the limit concerns bidirectional streams or unidirectional streams is
* denoted by the frame type; the caller should examine the frame type to
* determine this.
*/
int ossl_quic_wire_decode_frame_streams_blocked(PACKET *pkt,
uint64_t *max_streams);
/*
* Decodes a QUIC NEW_CONNECTION_ID frame. The logical representation of the
* frame is written to *f.
*
* The conn_id field is set to point to the connection ID string inside the
* packet buffer; it is therefore valid for as long as the PACKET's buffer is
* valid. The conn_id_len field is set to the length of the connection ID string
* in bytes.
*/
int ossl_quic_wire_decode_frame_new_conn_id(PACKET *pkt,
OSSL_QUIC_FRAME_NEW_CONN_ID *f);
/*
* Decodes a QUIC RETIRE_CONNECTION_ID frame. The Sequence Number field
* is written to *seq_num.
*/
int ossl_quic_wire_decode_frame_retire_conn_id(PACKET *pkt,
uint64_t *seq_num);
/*
* Decodes a QUIC PATH_CHALLENGE frame. The Data field is written to *data.
*/
int ossl_quic_wire_decode_frame_path_challenge(PACKET *pkt,
uint64_t *data);
/*
* Decodes a QUIC PATH_CHALLENGE frame. The Data field is written to *data.
*/
int ossl_quic_wire_decode_frame_path_response(PACKET *pkt,
uint64_t *data);
/*
* Decodes a QUIC CONNECTION_CLOSE frame. The logical representation
* of the frame is written to *f.
*
* The reason field is set to point to the UTF-8 reason string inside
* the packet buffer; it is therefore valid for as long as the PACKET's
* buffer is valid. The reason_len field is set to the length of the
* reason string in bytes.
*
* IMPORTANT: The reason string is not zero-terminated.
*
* Returns 1 on success or 0 on failure.
*/
int ossl_quic_wire_decode_frame_conn_close(PACKET *pkt,
OSSL_QUIC_FRAME_CONN_CLOSE *f);
/*
* Decodes one or more PADDING frames. PADDING frames have no arguments.
*
* Returns the number of PADDING frames decoded or 0 on error.
*/
size_t ossl_quic_wire_decode_padding(PACKET *pkt);
/*
* Decodes a PING frame. The frame has no arguments.
*/
int ossl_quic_wire_decode_frame_ping(PACKET *pkt);
/*
* Decodes a HANDSHAKE_DONE frame. The frame has no arguments.
*/
int ossl_quic_wire_decode_frame_handshake_done(PACKET *pkt);
/*
* Peeks at the ID of the next QUIC transport parameter TLV in the stream.
* The ID is written to *id.
*/
int ossl_quic_wire_peek_transport_param(PACKET *pkt, uint64_t *id);
/*
* Decodes a QUIC transport parameter TLV. A pointer to the value buffer is
* returned on success. This points inside the PACKET's buffer and is therefore
* valid as long as the PACKET's buffer is valid.
*
* The transport parameter ID is written to *id (if non-NULL) and the length of
* the payload in bytes is written to *len.
*
* Returns NULL on failure.
*/
const unsigned char *ossl_quic_wire_decode_transport_param_bytes(PACKET *pkt,
uint64_t *id,
size_t *len);
/*
* Decodes a QUIC transport parameter TLV containing a variable-length integer.
*
* The transport parameter ID is written to *id (if non-NULL) and the value is
* written to *value.
*/
int ossl_quic_wire_decode_transport_param_int(PACKET *pkt,
uint64_t *id,
uint64_t *value);
/*
* Decodes a QUIC transport parameter TLV containing a connection ID.
*
* The transport parameter ID is written to *id (if non-NULL) and the value is
* written to *value.
*/
int ossl_quic_wire_decode_transport_param_cid(PACKET *pkt,
uint64_t *id,
QUIC_CONN_ID *cid);
/*
* Decodes a QUIC transport parameter TLV containing a preferred_address.
*/
typedef struct quic_preferred_addr_st {
uint16_t ipv4_port, ipv6_port;
unsigned char ipv4[4], ipv6[16];
QUIC_STATELESS_RESET_TOKEN stateless_reset;
QUIC_CONN_ID cid;
} QUIC_PREFERRED_ADDR;
int ossl_quic_wire_decode_transport_param_preferred_addr(PACKET *pkt,
QUIC_PREFERRED_ADDR *p);
# endif
#endif

View File

@ -0,0 +1,629 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_QUIC_WIRE_PKT_H
# define OSSL_QUIC_WIRE_PKT_H
# include <openssl/ssl.h>
# include "internal/packet_quic.h"
# include "internal/quic_types.h"
# ifndef OPENSSL_NO_QUIC
# define QUIC_VERSION_NONE ((uint32_t)0) /* Used for version negotiation */
# define QUIC_VERSION_1 ((uint32_t)1) /* QUIC v1 */
/* QUIC logical packet type. These do not match wire values. */
# define QUIC_PKT_TYPE_INITIAL 1
# define QUIC_PKT_TYPE_0RTT 2
# define QUIC_PKT_TYPE_HANDSHAKE 3
# define QUIC_PKT_TYPE_RETRY 4
# define QUIC_PKT_TYPE_1RTT 5
# define QUIC_PKT_TYPE_VERSION_NEG 6
/*
* Determine encryption level from packet type. Returns QUIC_ENC_LEVEL_NUM if
* the packet is not of a type which is encrypted.
*/
static ossl_inline ossl_unused uint32_t
ossl_quic_pkt_type_to_enc_level(uint32_t pkt_type)
{
switch (pkt_type) {
case QUIC_PKT_TYPE_INITIAL:
return QUIC_ENC_LEVEL_INITIAL;
case QUIC_PKT_TYPE_HANDSHAKE:
return QUIC_ENC_LEVEL_HANDSHAKE;
case QUIC_PKT_TYPE_0RTT:
return QUIC_ENC_LEVEL_0RTT;
case QUIC_PKT_TYPE_1RTT:
return QUIC_ENC_LEVEL_1RTT;
default:
return QUIC_ENC_LEVEL_NUM;
}
}
static ossl_inline ossl_unused uint32_t
ossl_quic_enc_level_to_pkt_type(uint32_t enc_level)
{
switch (enc_level) {
case QUIC_ENC_LEVEL_INITIAL:
return QUIC_PKT_TYPE_INITIAL;
case QUIC_ENC_LEVEL_HANDSHAKE:
return QUIC_PKT_TYPE_HANDSHAKE;
case QUIC_ENC_LEVEL_0RTT:
return QUIC_PKT_TYPE_0RTT;
case QUIC_ENC_LEVEL_1RTT:
return QUIC_PKT_TYPE_1RTT;
default:
return UINT32_MAX;
}
}
/* Determine if a packet type contains an encrypted payload. */
static ossl_inline ossl_unused int
ossl_quic_pkt_type_is_encrypted(uint32_t pkt_type)
{
switch (pkt_type) {
case QUIC_PKT_TYPE_RETRY:
case QUIC_PKT_TYPE_VERSION_NEG:
return 0;
default:
return 1;
}
}
/* Determine if a packet type contains a PN field. */
static ossl_inline ossl_unused int
ossl_quic_pkt_type_has_pn(uint32_t pkt_type)
{
/*
* Currently a packet has a PN iff it is encrypted. This could change
* someday.
*/
return ossl_quic_pkt_type_is_encrypted(pkt_type);
}
/*
* Determine if a packet type can appear with other packets in a datagram. Some
* packet types must be the sole packet in a datagram.
*/
static ossl_inline ossl_unused int
ossl_quic_pkt_type_can_share_dgram(uint32_t pkt_type)
{
/*
* Currently only the encrypted packet types can share a datagram. This
* could change someday.
*/
return ossl_quic_pkt_type_is_encrypted(pkt_type);
}
/*
* Determine if the packet type must come at the end of the datagram (due to the
* lack of a length field).
*/
static ossl_inline ossl_unused int
ossl_quic_pkt_type_must_be_last(uint32_t pkt_type)
{
/*
* Any packet type which cannot share a datagram obviously must come last.
* 1-RTT also must come last as it lacks a length field.
*/
return !ossl_quic_pkt_type_can_share_dgram(pkt_type)
|| pkt_type == QUIC_PKT_TYPE_1RTT;
}
/*
* Determine if the packet type has a version field.
*/
static ossl_inline ossl_unused int
ossl_quic_pkt_type_has_version(uint32_t pkt_type)
{
return pkt_type != QUIC_PKT_TYPE_1RTT && pkt_type != QUIC_PKT_TYPE_VERSION_NEG;
}
/*
* Determine if the packet type has a SCID field.
*/
static ossl_inline ossl_unused int
ossl_quic_pkt_type_has_scid(uint32_t pkt_type)
{
return pkt_type != QUIC_PKT_TYPE_1RTT;
}
/*
* Smallest possible QUIC packet size as per RFC (aside from version negotiation
* packets).
*/
# define QUIC_MIN_VALID_PKT_LEN_CRYPTO 21
# define QUIC_MIN_VALID_PKT_LEN_VERSION_NEG 7
# define QUIC_MIN_VALID_PKT_LEN QUIC_MIN_VALID_PKT_LEN_VERSION_NEG
typedef struct quic_pkt_hdr_ptrs_st QUIC_PKT_HDR_PTRS;
/*
* QUIC Packet Header Protection
* =============================
*
* Functions to apply and remove QUIC packet header protection. A header
* protector is initialised using ossl_quic_hdr_protector_init and must be
* destroyed using ossl_quic_hdr_protector_cleanup when no longer needed.
*/
typedef struct quic_hdr_protector_st {
OSSL_LIB_CTX *libctx;
const char *propq;
EVP_CIPHER_CTX *cipher_ctx;
EVP_CIPHER *cipher;
uint32_t cipher_id;
} QUIC_HDR_PROTECTOR;
# define QUIC_HDR_PROT_CIPHER_AES_128 1
# define QUIC_HDR_PROT_CIPHER_AES_256 2
# define QUIC_HDR_PROT_CIPHER_CHACHA 3
/*
* Initialises a header protector.
*
* cipher_id:
* The header protection cipher method to use. One of
* QUIC_HDR_PROT_CIPHER_*. Must be chosen based on negotiated TLS cipher
* suite.
*
* quic_hp_key:
* This must be the "quic hp" key derived from a traffic secret.
*
* The length of the quic_hp_key must correspond to that expected for the
* given cipher ID.
*
* The header protector performs amortisable initialisation in this function,
* therefore a header protector should be used for as long as possible.
*
* Returns 1 on success and 0 on failure.
*/
int ossl_quic_hdr_protector_init(QUIC_HDR_PROTECTOR *hpr,
OSSL_LIB_CTX *libctx,
const char *propq,
uint32_t cipher_id,
const unsigned char *quic_hp_key,
size_t quic_hp_key_len);
/*
* Destroys a header protector. This is also safe to call on a zero-initialized
* OSSL_QUIC_HDR_PROTECTOR structure which has not been initialized, or which
* has already been destroyed.
*/
void ossl_quic_hdr_protector_cleanup(QUIC_HDR_PROTECTOR *hpr);
/*
* Removes header protection from a packet. The packet payload must currently be
* encrypted (i.e., you must remove header protection before decrypting packets
* received). The function examines the header buffer to determine which bytes
* of the header need to be decrypted.
*
* If this function fails, no data is modified.
*
* This is implemented as a call to ossl_quic_hdr_protector_decrypt_fields().
*
* Returns 1 on success and 0 on failure.
*/
int ossl_quic_hdr_protector_decrypt(QUIC_HDR_PROTECTOR *hpr,
QUIC_PKT_HDR_PTRS *ptrs);
/*
* Applies header protection to a packet. The packet payload must already have
* been encrypted (i.e., you must apply header protection after encrypting
* a packet). The function examines the header buffer to determine which bytes
* of the header need to be encrypted.
*
* This is implemented as a call to ossl_quic_hdr_protector_encrypt_fields().
*
* Returns 1 on success and 0 on failure.
*/
int ossl_quic_hdr_protector_encrypt(QUIC_HDR_PROTECTOR *hpr,
QUIC_PKT_HDR_PTRS *ptrs);
/*
* Removes header protection from a packet. The packet payload must currently
* be encrypted. This is a low-level function which assumes you have already
* determined which parts of the packet header need to be decrypted.
*
* sample:
* The range of bytes in the packet to be used to generate the header
* protection mask. It is permissible to set sample_len to the size of the
* remainder of the packet; this function will only use as many bytes as
* needed. If not enough sample bytes are provided, this function fails.
*
* first_byte:
* The first byte of the QUIC packet header to be decrypted.
*
* pn:
* Pointer to the start of the PN field. The caller is responsible
* for ensuring at least four bytes follow this pointer.
*
* Returns 1 on success and 0 on failure.
*/
int ossl_quic_hdr_protector_decrypt_fields(QUIC_HDR_PROTECTOR *hpr,
const unsigned char *sample,
size_t sample_len,
unsigned char *first_byte,
unsigned char *pn_bytes);
/*
* Works analogously to ossl_hdr_protector_decrypt_fields, but applies header
* protection instead of removing it.
*/
int ossl_quic_hdr_protector_encrypt_fields(QUIC_HDR_PROTECTOR *hpr,
const unsigned char *sample,
size_t sample_len,
unsigned char *first_byte,
unsigned char *pn_bytes);
/*
* QUIC Packet Header
* ==================
*
* This structure provides a logical representation of a QUIC packet header.
*
* QUIC packet formats fall into the following categories:
*
* Long Packets, which is subdivided into five possible packet types:
* Version Negotiation (a special case);
* Initial;
* 0-RTT;
* Handshake; and
* Retry
*
* Short Packets, which comprises only a single packet type (1-RTT).
*
* The packet formats vary and common fields are found in some packets but
* not others. The below table indicates which fields are present in which
* kinds of packet. * indicates header protection is applied.
*
* SLLLLL Legend: 1=1-RTT, i=Initial, 0=0-RTT, h=Handshake
* 1i0hrv r=Retry, v=Version Negotiation
* ------
* 1i0hrv Header Form (0=Short, 1=Long)
* 1i0hr Fixed Bit (always 1)
* 1 Spin Bit
* 1 * Reserved Bits
* 1 * Key Phase
* 1i0h * Packet Number Length
* i0hr? Long Packet Type
* i0h Type-Specific Bits
* i0hr Version (note: always 0 for Version Negotiation packets)
* 1i0hrv Destination Connection ID
* i0hrv Source Connection ID
* 1i0h * Packet Number
* i Token
* i0h Length
* r Retry Token
* r Retry Integrity Tag
*
* For each field below, the conditions under which the field is valid are
* specified. If a field is not currently valid, it is initialized to a zero or
* NULL value.
*/
typedef struct quic_pkt_hdr_st {
/* [ALL] A QUIC_PKT_TYPE_* value. Always valid. */
unsigned int type :8;
/* [S] Value of the spin bit. Valid if (type == 1RTT). */
unsigned int spin_bit :1;
/*
* [S] Value of the Key Phase bit in the short packet.
* Valid if (type == 1RTT && !partial).
*/
unsigned int key_phase :1;
/*
* [1i0h] Length of packet number in bytes. This is the decoded value.
* Valid if ((type == 1RTT || (version && type != RETRY)) && !partial).
*/
unsigned int pn_len :4;
/*
* [ALL] Set to 1 if this is a partial decode because the packet header
* has not yet been deprotected. pn_len, pn and key_phase are not valid if
* this is set.
*/
unsigned int partial :1;
/*
* [ALL] Whether the fixed bit was set. Note that only Version Negotiation
* packets are allowed to have this unset, so this will always be 1 for all
* other packet types (decode will fail if it is not set). Ignored when
* encoding unless encoding a Version Negotiation packet.
*/
unsigned int fixed :1;
/*
* The unused bits in the low 4 bits of a Retry packet header's first byte.
* This is used to ensure that Retry packets have the same bit-for-bit
* representation in their header when decoding and encoding them again.
* This is necessary to validate Retry packet headers.
*/
unsigned int unused :4;
/*
* The 'Reserved' bits in an Initial, Handshake, 0-RTT or 1-RTT packet
* header's first byte. These are provided so that the caller can validate
* that they are zero, as this must be done after packet protection is
* successfully removed to avoid creating a timing channel.
*/
unsigned int reserved :2;
/* [L] Version field. Valid if (type != 1RTT). */
uint32_t version;
/* [ALL] The destination connection ID. Always valid. */
QUIC_CONN_ID dst_conn_id;
/*
* [L] The source connection ID.
* Valid if (type != 1RTT).
*/
QUIC_CONN_ID src_conn_id;
/*
* [1i0h] Relatively-encoded packet number in raw, encoded form. The correct
* decoding of this value is context-dependent. The number of bytes valid in
* this buffer is determined by pn_len above. If the decode was partial,
* this field is not valid.
*
* Valid if ((type == 1RTT || (version && type != RETRY)) && !partial).
*/
unsigned char pn[4];
/*
* [i] Token field in Initial packet. Points to memory inside the decoded
* PACKET, and therefore is valid for as long as the PACKET's buffer is
* valid. token_len is the length of the token in bytes.
*
* Valid if (type == INITIAL).
*/
const unsigned char *token;
size_t token_len;
/*
* [ALL] Payload length in bytes.
*
* Though 1-RTT, Retry and Version Negotiation packets do not contain an
* explicit length field, this field is always valid and is used by the
* packet header encoding and decoding routines to describe the payload
* length, regardless of whether the packet type encoded or decoded uses an
* explicit length indication.
*/
size_t len;
/*
* Pointer to start of payload data in the packet. Points to memory inside
* the decoded PACKET, and therefore is valid for as long as the PACKET'S
* buffer is valid. The length of the buffer in bytes is in len above.
*
* For Version Negotiation packets, points to the array of supported
* versions.
*
* For Retry packets, points to the Retry packet payload, which comprises
* the Retry Token followed by a 16-byte Retry Integrity Tag.
*
* Regardless of whether a packet is a Version Negotiation packet (where the
* payload contains a list of supported versions), a Retry packet (where the
* payload contains a Retry Token and Retry Integrity Tag), or any other
* packet type (where the payload contains frames), the payload is not
* validated and the user must parse the payload bearing this in mind.
*
* If the decode was partial (partial is set), this points to the start of
* the packet number field, rather than the protected payload, as the length
* of the packet number field is unknown. The len field reflects this in
* this case (i.e., the len field is the number of payload bytes plus the
* number of bytes comprising the PN).
*/
const unsigned char *data;
} QUIC_PKT_HDR;
/*
* Extra information which can be output by the packet header decode functions
* for the assistance of the header protector. This avoids the header protector
* needing to partially re-decode the packet header.
*/
struct quic_pkt_hdr_ptrs_st {
unsigned char *raw_start; /* start of packet */
unsigned char *raw_sample; /* start of sampling range */
size_t raw_sample_len; /* maximum length of sampling range */
/*
* Start of PN field. Guaranteed to be NULL unless at least four bytes are
* available via this pointer.
*/
unsigned char *raw_pn;
};
/*
* If partial is 1, reads the unprotected parts of a protected packet header
* from a PACKET, performing a partial decode.
*
* If partial is 0, the input is assumed to have already had header protection
* removed, and all header fields are decoded.
*
* If nodata is 1, the input is assumed to have no payload data in it. Otherwise
* payload data must be present.
*
* On success, the logical decode of the packet header is written to *hdr.
* hdr->partial is set or cleared according to whether a partial decode was
* performed. *ptrs is filled with pointers to various parts of the packet
* buffer.
*
* In order to decode short packets, the connection ID length being used must be
* known contextually, and should be passed as short_conn_id_len. If
* short_conn_id_len is set to an invalid value (a value greater than
* QUIC_MAX_CONN_ID_LEN), this function fails when trying to decode a short
* packet, but succeeds for long packets.
*
* Returns 1 on success and 0 on failure.
*/
int ossl_quic_wire_decode_pkt_hdr(PACKET *pkt,
size_t short_conn_id_len,
int partial,
int nodata,
QUIC_PKT_HDR *hdr,
QUIC_PKT_HDR_PTRS *ptrs);
/*
* Encodes a packet header. The packet is written to pkt.
*
* The length of the (encrypted) packet payload should be written to hdr->len
* and will be placed in the serialized packet header. The payload data itself
* is not copied; the caller should write hdr->len bytes of encrypted payload to
* the WPACKET immediately after the call to this function. However,
* WPACKET_reserve_bytes is called for the payload size.
*
* This function does not apply header protection. You must apply header
* protection yourself after calling this function. *ptrs is filled with
* pointers which can be passed to a header protector, but this must be
* performed after the encrypted payload is written.
*
* The pointers in *ptrs are direct pointers into the WPACKET buffer. If more
* data is written to the WPACKET buffer, WPACKET buffer reallocations may
* occur, causing these pointers to become invalid. Therefore, you must not call
* any write WPACKET function between this call and the call to
* ossl_quic_hdr_protector_encrypt. This function calls WPACKET_reserve_bytes
* for the payload length, so you may assume hdr->len bytes are already free to
* write at the WPACKET cursor location once this function returns successfully.
* It is recommended that you call this function, write the encrypted payload,
* call ossl_quic_hdr_protector_encrypt, and then call
* WPACKET_allocate_bytes(hdr->len).
*
* Version Negotiation and Retry packets do not use header protection; for these
* header types, the fields in *ptrs are all written as zero. Version
* Negotiation, Retry and 1-RTT packets do not contain a Length field, but
* hdr->len bytes of data are still reserved in the WPACKET.
*
* If serializing a short packet and short_conn_id_len does not match the DCID
* specified in hdr, the function fails.
*
* Returns 1 on success and 0 on failure.
*/
int ossl_quic_wire_encode_pkt_hdr(WPACKET *pkt,
size_t short_conn_id_len,
const QUIC_PKT_HDR *hdr,
QUIC_PKT_HDR_PTRS *ptrs);
/*
* Retrieves only the DCID from a packet header. This is intended for demuxer
* use. It avoids the need to parse the rest of the packet header twice.
*
* Information on packet length is not decoded, as this only needs to be used on
* the first packet in a datagram, therefore this takes a buffer and not a
* PACKET.
*
* Returns 1 on success and 0 on failure.
*/
int ossl_quic_wire_get_pkt_hdr_dst_conn_id(const unsigned char *buf,
size_t buf_len,
size_t short_conn_id_len,
QUIC_CONN_ID *dst_conn_id);
/*
* Precisely predicts the encoded length of a packet header structure.
*
* May return 0 if the packet header is not valid, but the fact that this
* function returns non-zero does not guarantee that
* ossl_quic_wire_encode_pkt_hdr() will succeed.
*/
int ossl_quic_wire_get_encoded_pkt_hdr_len(size_t short_conn_id_len,
const QUIC_PKT_HDR *hdr);
/*
* Packet Number Encoding
* ======================
*/
/*
* Decode an encoded packet header QUIC PN.
*
* enc_pn is the raw encoded PN to decode. enc_pn_len is its length in bytes as
* indicated by packet headers. largest_pn is the largest PN successfully
* processed in the relevant PN space.
*
* The resulting PN is written to *res_pn.
*
* Returns 1 on success or 0 on failure.
*/
int ossl_quic_wire_decode_pkt_hdr_pn(const unsigned char *enc_pn,
size_t enc_pn_len,
QUIC_PN largest_pn,
QUIC_PN *res_pn);
/*
* Determine how many bytes should be used to encode a PN. Returns the number of
* bytes (which will be in range [1, 4]).
*/
int ossl_quic_wire_determine_pn_len(QUIC_PN pn, QUIC_PN largest_acked);
/*
* Encode a PN for a packet header using the specified number of bytes, which
* should have been determined by calling ossl_quic_wire_determine_pn_len. The
* PN encoding process is done in two parts to allow the caller to override PN
* encoding length if it wishes.
*
* Returns 1 on success and 0 on failure.
*/
int ossl_quic_wire_encode_pkt_hdr_pn(QUIC_PN pn,
unsigned char *enc_pn,
size_t enc_pn_len);
/*
* Retry Integrity Tags
* ====================
*/
# define QUIC_RETRY_INTEGRITY_TAG_LEN 16
/*
* Validate a retry integrity tag. Returns 1 if the tag is valid.
*
* Must be called on a hdr with a type of QUIC_PKT_TYPE_RETRY with a valid data
* pointer.
*
* client_initial_dcid must be the original DCID used by the client in its first
* Initial packet, as this is used to calculate the Retry Integrity Tag.
*
* Returns 0 if the tag is invalid, if called on any other type of packet or if
* the body is too short.
*/
int ossl_quic_validate_retry_integrity_tag(OSSL_LIB_CTX *libctx,
const char *propq,
const QUIC_PKT_HDR *hdr,
const QUIC_CONN_ID *client_initial_dcid);
/*
* Calculates a retry integrity tag. Returns 0 on error, for example if hdr does
* not have a type of QUIC_PKT_TYPE_RETRY.
*
* client_initial_dcid must be the original DCID used by the client in its first
* Initial packet, as this is used to calculate the Retry Integrity Tag.
*
* tag must point to a buffer of QUIC_RETRY_INTEGRITY_TAG_LEN bytes in size.
*
* Note that hdr->data must point to the Retry packet body, and hdr->len must
* include the space for the Retry Integrity Tag. (This means that you can
* easily fill in a tag in a Retry packet you are generating by calling this
* function and passing (hdr->data + hdr->len - QUIC_RETRY_INTEGRITY_TAG_LEN) as
* the tag argument.) This function fails if hdr->len is too short to contain a
* Retry Integrity Tag.
*/
int ossl_quic_calculate_retry_integrity_tag(OSSL_LIB_CTX *libctx,
const char *propq,
const QUIC_PKT_HDR *hdr,
const QUIC_CONN_ID *client_initial_dcid,
unsigned char *tag);
# endif
#endif

View File

@ -0,0 +1,339 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_INTERNAL_RECORDMETHOD_H
# define OSSL_INTERNAL_RECORDMETHOD_H
# pragma once
# include <openssl/ssl.h>
/*
* We use the term "record" here to refer to a packet of data. Records are
* typically protected via a cipher and MAC, or an AEAD cipher (although not
* always). This usage of the term record is consistent with the TLS concept.
* In QUIC the term "record" is not used but it is analogous to the QUIC term
* "packet". The interface in this file applies to all protocols that protect
* records/packets of data, i.e. (D)TLS and QUIC. The term record is used to
* refer to both contexts.
*/
/*
* An OSSL_RECORD_METHOD is a protocol specific method which provides the
* functions for reading and writing records for that protocol. Which
* OSSL_RECORD_METHOD to use for a given protocol is defined by the SSL_METHOD.
*/
typedef struct ossl_record_method_st OSSL_RECORD_METHOD;
/*
* An OSSL_RECORD_LAYER is just an externally defined opaque pointer created by
* the method
*/
typedef struct ossl_record_layer_st OSSL_RECORD_LAYER;
# define OSSL_RECORD_ROLE_CLIENT 0
# define OSSL_RECORD_ROLE_SERVER 1
# define OSSL_RECORD_DIRECTION_READ 0
# define OSSL_RECORD_DIRECTION_WRITE 1
/*
* Protection level. For <= TLSv1.2 only "NONE" and "APPLICATION" are used.
*/
# define OSSL_RECORD_PROTECTION_LEVEL_NONE 0
# define OSSL_RECORD_PROTECTION_LEVEL_EARLY 1
# define OSSL_RECORD_PROTECTION_LEVEL_HANDSHAKE 2
# define OSSL_RECORD_PROTECTION_LEVEL_APPLICATION 3
# define OSSL_RECORD_RETURN_SUCCESS 1
# define OSSL_RECORD_RETURN_RETRY 0
# define OSSL_RECORD_RETURN_NON_FATAL_ERR -1
# define OSSL_RECORD_RETURN_FATAL -2
# define OSSL_RECORD_RETURN_EOF -3
/*
* Template for creating a record. A record consists of the |type| of data it
* will contain (e.g. alert, handshake, application data, etc) along with a
* buffer of payload data in |buf| of length |buflen|.
*/
struct ossl_record_template_st {
unsigned char type;
unsigned int version;
const unsigned char *buf;
size_t buflen;
};
typedef struct ossl_record_template_st OSSL_RECORD_TEMPLATE;
/*
* Rather than a "method" approach, we could make this fetchable - Should we?
* There could be some complexity in finding suitable record layer implementations
* e.g. we need to find one that matches the negotiated protocol, cipher,
* extensions, etc. The selection_cb approach given above doesn't work so well
* if unknown third party providers with OSSL_RECORD_METHOD implementations are
* loaded.
*/
/*
* If this becomes public API then we will need functions to create and
* free an OSSL_RECORD_METHOD, as well as functions to get/set the various
* function pointers....unless we make it fetchable.
*/
struct ossl_record_method_st {
/*
* Create a new OSSL_RECORD_LAYER object for handling the protocol version
* set by |vers|. |role| is 0 for client and 1 for server. |direction|
* indicates either read or write. |level| is the protection level as
* described above. |settings| are mandatory settings that will cause the
* new() call to fail if they are not understood (for example to require
* Encrypt-Then-Mac support). |options| are optional settings that will not
* cause the new() call to fail if they are not understood (for example
* whether to use "read ahead" or not).
*
* The BIO in |transport| is the BIO for the underlying transport layer.
* Where the direction is "read", then this BIO will only ever be used for
* reading data. Where the direction is "write", then this BIO will only
* every be used for writing data.
*
* An SSL object will always have at least 2 OSSL_RECORD_LAYER objects in
* force at any one time (one for reading and one for writing). In some
* protocols more than 2 might be used (e.g. in DTLS for retransmitting
* messages from an earlier epoch).
*
* The created OSSL_RECORD_LAYER object is stored in *ret on success (or
* NULL otherwise). The return value will be one of
* OSSL_RECORD_RETURN_SUCCESS, OSSL_RECORD_RETURN_FATAL or
* OSSL_RECORD_RETURN_NON_FATAL. A non-fatal return means that creation of
* the record layer has failed because it is unsuitable, but an alternative
* record layer can be tried instead.
*/
/*
* If we eventually make this fetchable then we will need to use something
* other than EVP_CIPHER. Also mactype would not be a NID, but a string. For
* now though, this works.
*/
int (*new_record_layer)(OSSL_LIB_CTX *libctx,
const char *propq, int vers,
int role, int direction,
int level,
uint16_t epoch,
unsigned char *secret,
size_t secretlen,
unsigned char *key,
size_t keylen,
unsigned char *iv,
size_t ivlen,
unsigned char *mackey,
size_t mackeylen,
const EVP_CIPHER *ciph,
size_t taglen,
int mactype,
const EVP_MD *md,
COMP_METHOD *comp,
const EVP_MD *kdfdigest,
BIO *prev,
BIO *transport,
BIO *next,
BIO_ADDR *local,
BIO_ADDR *peer,
const OSSL_PARAM *settings,
const OSSL_PARAM *options,
const OSSL_DISPATCH *fns,
void *cbarg,
void *rlarg,
OSSL_RECORD_LAYER **ret);
int (*free)(OSSL_RECORD_LAYER *rl);
/* Returns 1 if we have unprocessed data buffered or 0 otherwise */
int (*unprocessed_read_pending)(OSSL_RECORD_LAYER *rl);
/*
* Returns 1 if we have processed data buffered that can be read or 0 otherwise
* - not necessarily app data
*/
int (*processed_read_pending)(OSSL_RECORD_LAYER *rl);
/*
* The amount of processed app data that is internally buffered and
* available to read
*/
size_t (*app_data_pending)(OSSL_RECORD_LAYER *rl);
/*
* Find out the maximum number of records that the record layer is prepared
* to process in a single call to write_records. It is the caller's
* responsibility to ensure that no call to write_records exceeds this
* number of records. |type| is the type of the records that the caller
* wants to write, and |len| is the total amount of data that it wants
* to send. |maxfrag| is the maximum allowed fragment size based on user
* configuration, or TLS parameter negotiation. |*preffrag| contains on
* entry the default fragment size that will actually be used based on user
* configuration. This will always be less than or equal to |maxfrag|. On
* exit the record layer may update this to an alternative fragment size to
* be used. This must always be less than or equal to |maxfrag|.
*/
size_t (*get_max_records)(OSSL_RECORD_LAYER *rl, uint8_t type, size_t len,
size_t maxfrag, size_t *preffrag);
/*
* Write |numtempl| records from the array of record templates pointed to
* by |templates|. Each record should be no longer than the value returned
* by get_max_record_len(), and there should be no more records than the
* value returned by get_max_records().
* Where possible the caller will attempt to ensure that all records are the
* same length, except the last record. This may not always be possible so
* the record method implementation should not rely on this being the case.
* In the event of a retry the caller should call retry_write_records()
* to try again. No more calls to write_records() should be attempted until
* retry_write_records() returns success.
* Buffers allocated for the record templates can be freed immediately after
* write_records() returns - even in the case a retry.
* The record templates represent the plaintext payload. The encrypted
* output is written to the |transport| BIO.
* Returns:
* 1 on success
* 0 on retry
* -1 on failure
*/
int (*write_records)(OSSL_RECORD_LAYER *rl, OSSL_RECORD_TEMPLATE *templates,
size_t numtempl);
/*
* Retry a previous call to write_records. The caller should continue to
* call this until the function returns with success or failure. After
* each retry more of the data may have been incrementally sent.
* Returns:
* 1 on success
* 0 on retry
* -1 on failure
*/
int (*retry_write_records)(OSSL_RECORD_LAYER *rl);
/*
* Read a record and return the record layer version and record type in
* the |rversion| and |type| parameters. |*data| is set to point to a
* record layer buffer containing the record payload data and |*datalen|
* is filled in with the length of that data. The |epoch| and |seq_num|
* values are only used if DTLS has been negotiated. In that case they are
* filled in with the epoch and sequence number from the record.
* An opaque record layer handle for the record is returned in |*rechandle|
* which is used in a subsequent call to |release_record|. The buffer must
* remain available until all the bytes from record are released via one or
* more release_record calls.
*
* Internally the OSSL_RECORD_METHOD implementation may read/process
* multiple records in one go and buffer them.
*/
int (*read_record)(OSSL_RECORD_LAYER *rl, void **rechandle, int *rversion,
uint8_t *type, const unsigned char **data, size_t *datalen,
uint16_t *epoch, unsigned char *seq_num);
/*
* Release length bytes from a buffer associated with a record previously
* read with read_record. Once all the bytes from a record are released, the
* whole record and its associated buffer is released. Records are
* guaranteed to be released in the order that they are read.
*/
int (*release_record)(OSSL_RECORD_LAYER *rl, void *rechandle, size_t length);
/*
* In the event that a fatal error is returned from the functions above then
* get_alert_code() can be called to obtain a more details identifier for
* the error. In (D)TLS this is the alert description code.
*/
int (*get_alert_code)(OSSL_RECORD_LAYER *rl);
/*
* Update the transport BIO from the one originally set in the
* new_record_layer call
*/
int (*set1_bio)(OSSL_RECORD_LAYER *rl, BIO *bio);
/* Called when protocol negotiation selects a protocol version to use */
int (*set_protocol_version)(OSSL_RECORD_LAYER *rl, int version);
/*
* Whether we are allowed to receive unencrypted alerts, even if we might
* otherwise expect encrypted records. Ignored by protocol versions where
* this isn't relevant
*/
void (*set_plain_alerts)(OSSL_RECORD_LAYER *rl, int allow);
/*
* Called immediately after creation of the record layer if we are in a
* first handshake. Also called at the end of the first handshake
*/
void (*set_first_handshake)(OSSL_RECORD_LAYER *rl, int first);
/*
* Set the maximum number of pipelines that the record layer should process.
* The default is 1.
*/
void (*set_max_pipelines)(OSSL_RECORD_LAYER *rl, size_t max_pipelines);
/*
* Called to tell the record layer whether we are currently "in init" or
* not. Default at creation of the record layer is "yes".
*/
void (*set_in_init)(OSSL_RECORD_LAYER *rl, int in_init);
/*
* Get a short or long human readable description of the record layer state
*/
void (*get_state)(OSSL_RECORD_LAYER *rl, const char **shortstr,
const char **longstr);
/*
* Set new options or modify ones that were originally specified in the
* new_record_layer call.
*/
int (*set_options)(OSSL_RECORD_LAYER *rl, const OSSL_PARAM *options);
const COMP_METHOD *(*get_compression)(OSSL_RECORD_LAYER *rl);
/*
* Set the maximum fragment length to be used for the record layer. This
* will override any previous value supplied for the "max_frag_len"
* setting during construction of the record layer.
*/
void (*set_max_frag_len)(OSSL_RECORD_LAYER *rl, size_t max_frag_len);
/*
* The maximum expansion in bytes that the record layer might add while
* writing a record
*/
size_t (*get_max_record_overhead)(OSSL_RECORD_LAYER *rl);
/*
* Increment the record sequence number
*/
int (*increment_sequence_ctr)(OSSL_RECORD_LAYER *rl);
/*
* Allocate read or write buffers. Does nothing if already allocated.
* Assumes default buffer length and 1 pipeline.
*/
int (*alloc_buffers)(OSSL_RECORD_LAYER *rl);
/*
* Free read or write buffers. Fails if there is pending read or write
* data. Buffers are automatically reallocated on next read/write.
*/
int (*free_buffers)(OSSL_RECORD_LAYER *rl);
};
/* Standard built-in record methods */
extern const OSSL_RECORD_METHOD ossl_tls_record_method;
# ifndef OPENSSL_NO_KTLS
extern const OSSL_RECORD_METHOD ossl_ktls_record_method;
# endif
extern const OSSL_RECORD_METHOD ossl_dtls_record_method;
#endif /* !defined(OSSL_INTERNAL_RECORDMETHOD_H) */

View File

@ -12,6 +12,7 @@
# include <openssl/e_os2.h>
# include <openssl/trace.h>
# include <openssl/err.h>
# if defined(OPENSSL_THREADS) && !defined(OPENSSL_DEV_NO_ATOMICS)
# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \
@ -25,12 +26,13 @@
# define HAVE_ATOMICS 1
typedef _Atomic int CRYPTO_REF_COUNT;
typedef struct {
_Atomic int val;
} CRYPTO_REF_COUNT;
static inline int CRYPTO_UP_REF(_Atomic int *val, int *ret,
ossl_unused void *lock)
static inline int CRYPTO_UP_REF(CRYPTO_REF_COUNT *refcnt, int *ret)
{
*ret = atomic_fetch_add_explicit(val, 1, memory_order_relaxed) + 1;
*ret = atomic_fetch_add_explicit(&refcnt->val, 1, memory_order_relaxed) + 1;
return 1;
}
@ -44,50 +46,70 @@ static inline int CRYPTO_UP_REF(_Atomic int *val, int *ret,
* to mutable members doesn't have to be serialized anymore, which would
* otherwise imply an acquire fence. Hence conditional acquire fence...
*/
static inline int CRYPTO_DOWN_REF(_Atomic int *val, int *ret,
ossl_unused void *lock)
static inline int CRYPTO_DOWN_REF(CRYPTO_REF_COUNT *refcnt, int *ret)
{
*ret = atomic_fetch_sub_explicit(val, 1, memory_order_relaxed) - 1;
*ret = atomic_fetch_sub_explicit(&refcnt->val, 1, memory_order_relaxed) - 1;
if (*ret == 0)
atomic_thread_fence(memory_order_acquire);
return 1;
}
static inline int CRYPTO_GET_REF(CRYPTO_REF_COUNT *refcnt, int *ret)
{
*ret = atomic_load_explicit(&refcnt->val, memory_order_relaxed);
return 1;
}
# elif defined(__GNUC__) && defined(__ATOMIC_RELAXED) && __GCC_ATOMIC_INT_LOCK_FREE > 0
# define HAVE_ATOMICS 1
typedef int CRYPTO_REF_COUNT;
typedef struct {
int val;
} CRYPTO_REF_COUNT;
static __inline__ int CRYPTO_UP_REF(int *val, int *ret, ossl_unused void *lock)
static __inline__ int CRYPTO_UP_REF(CRYPTO_REF_COUNT *refcnt, int *ret)
{
*ret = __atomic_fetch_add(val, 1, __ATOMIC_RELAXED) + 1;
*ret = __atomic_fetch_add(&refcnt->val, 1, __ATOMIC_RELAXED) + 1;
return 1;
}
static __inline__ int CRYPTO_DOWN_REF(int *val, int *ret,
ossl_unused void *lock)
static __inline__ int CRYPTO_DOWN_REF(CRYPTO_REF_COUNT *refcnt, int *ret)
{
*ret = __atomic_fetch_sub(val, 1, __ATOMIC_RELAXED) - 1;
*ret = __atomic_fetch_sub(&refcnt->val, 1, __ATOMIC_RELAXED) - 1;
if (*ret == 0)
__atomic_thread_fence(__ATOMIC_ACQUIRE);
return 1;
}
# elif defined(__ICL) && defined(_WIN32)
# define HAVE_ATOMICS 1
typedef volatile int CRYPTO_REF_COUNT;
static __inline int CRYPTO_UP_REF(volatile int *val, int *ret,
ossl_unused void *lock)
static __inline__ int CRYPTO_GET_REF(CRYPTO_REF_COUNT *refcnt, int *ret)
{
*ret = _InterlockedExchangeAdd((void *)val, 1) + 1;
*ret = __atomic_load_n(&refcnt->val, __ATOMIC_RELAXED);
return 1;
}
static __inline int CRYPTO_DOWN_REF(volatile int *val, int *ret,
ossl_unused void *lock)
# elif defined(__ICL) && defined(_WIN32)
# define HAVE_ATOMICS 1
typedef struct {
volatile int val;
} CRYPTO_REF_COUNT;
static __inline int CRYPTO_UP_REF(CRYPTO_REF_COUNT *refcnt, int *ret)
{
*ret = _InterlockedExchangeAdd((void *)val, -1) - 1;
*ret = _InterlockedExchangeAdd((void *)&refcnt->val, 1) + 1;
return 1;
}
static __inline int CRYPTO_DOWN_REF(CRYPTO_REF_COUNT *val, int *refcnt)
{
*ret = _InterlockedExchangeAdd((void *)&refcnt->val, -1) - 1;
return 1;
}
static __inline int CRYPTO_GET_REF(CRYPTO_REF_COUNT *refcnt, int *ret)
{
*ret = _InterlockedOr((void *)&refcnt->val, 0);
return 1;
}
@ -95,7 +117,9 @@ static __inline int CRYPTO_DOWN_REF(volatile int *val, int *ret,
# define HAVE_ATOMICS 1
typedef volatile int CRYPTO_REF_COUNT;
typedef struct {
volatile int val;
} CRYPTO_REF_COUNT;
# if (defined(_M_ARM) && _M_ARM>=7 && !defined(_WIN32_WCE)) || defined(_M_ARM64)
# include <intrin.h>
@ -103,21 +127,26 @@ typedef volatile int CRYPTO_REF_COUNT;
# define _ARM_BARRIER_ISH _ARM64_BARRIER_ISH
# endif
static __inline int CRYPTO_UP_REF(volatile int *val, int *ret,
ossl_unused void *lock)
static __inline int CRYPTO_UP_REF(CRYPTO_REF_COUNT *refcnt, int *ret)
{
*ret = _InterlockedExchangeAdd_nf(val, 1) + 1;
*ret = _InterlockedExchangeAdd_nf(&refcnt->val, 1) + 1;
return 1;
}
static __inline int CRYPTO_DOWN_REF(volatile int *val, int *ret,
ossl_unused void *lock)
static __inline int CRYPTO_DOWN_REF(CRYPTO_REF_COUNT *refcnt, int *ret)
{
*ret = _InterlockedExchangeAdd_nf(val, -1) - 1;
*ret = _InterlockedExchangeAdd_nf(&refcnt->val, -1) - 1;
if (*ret == 0)
__dmb(_ARM_BARRIER_ISH);
return 1;
}
static __inline int CRYPTO_GET_REF(CRYPTO_REF_COUNT *refcnt, int *ret)
{
*ret = _InterlockedOr_nf((void *)&refcnt->val, 0);
return 1;
}
# else
# if !defined(_WIN32_WCE)
# pragma intrinsic(_InterlockedExchangeAdd)
@ -131,19 +160,24 @@ static __inline int CRYPTO_DOWN_REF(volatile int *val, int *ret,
# endif
# endif
static __inline int CRYPTO_UP_REF(volatile int *val, int *ret,
ossl_unused void *lock)
static __inline int CRYPTO_UP_REF(CRYPTO_REF_COUNT *refcnt, int *ret)
{
*ret = _InterlockedExchangeAdd(val, 1) + 1;
*ret = _InterlockedExchangeAdd(&refcnt->val, 1) + 1;
return 1;
}
static __inline int CRYPTO_DOWN_REF(volatile int *val, int *ret,
ossl_unused void *lock)
static __inline int CRYPTO_DOWN_REF(CRYPTO_REF_COUNT *refcnt, int *ret)
{
*ret = _InterlockedExchangeAdd(val, -1) - 1;
*ret = _InterlockedExchangeAdd(&refcnt->val, -1) - 1;
return 1;
}
static __inline int CRYPTO_GET_REF(CRYPTO_REF_COUNT *refcnt, int *ret)
{
*ret = _InterlockedExchangeAdd(&refcnt->val, 0);
return 1;
}
# endif
# endif
@ -156,12 +190,91 @@ static __inline int CRYPTO_DOWN_REF(volatile int *val, int *ret,
*/
# ifndef HAVE_ATOMICS
typedef int CRYPTO_REF_COUNT;
# define CRYPTO_UP_REF(val, ret, lock) CRYPTO_atomic_add(val, 1, ret, lock)
# define CRYPTO_DOWN_REF(val, ret, lock) CRYPTO_atomic_add(val, -1, ret, lock)
typedef struct {
int val;
# ifdef OPENSSL_THREADS
CRYPTO_RWLOCK *lock;
# endif
} CRYPTO_REF_COUNT;
# ifdef OPENSSL_THREADS
static ossl_unused ossl_inline int CRYPTO_UP_REF(CRYPTO_REF_COUNT *refcnt,
int *ret)
{
return CRYPTO_atomic_add(&refcnt->val, 1, ret, refcnt->lock);
}
static ossl_unused ossl_inline int CRYPTO_DOWN_REF(CRYPTO_REF_COUNT *refcnt,
int *ret)
{
return CRYPTO_atomic_add(&refcnt->val, -1, ret, refcnt->lock);
}
static ossl_unused ossl_inline int CRYPTO_GET_REF(CRYPTO_REF_COUNT *refcnt,
int *ret)
{
return CRYPTO_atomic_load_int(&refcnt->val, ret, refcnt->lock);
}
# define CRYPTO_NEW_FREE_DEFINED 1
static ossl_unused ossl_inline int CRYPTO_NEW_REF(CRYPTO_REF_COUNT *refcnt, int n)
{
refcnt->val = n;
refcnt->lock = CRYPTO_THREAD_lock_new();
if (refcnt->lock == NULL) {
ERR_raise(ERR_LIB_CRYPTO, ERR_R_CRYPTO_LIB);
return 0;
}
return 1;
}
static ossl_unused ossl_inline void CRYPTO_FREE_REF(CRYPTO_REF_COUNT *refcnt) \
{
if (refcnt != NULL)
CRYPTO_THREAD_lock_free(refcnt->lock);
}
# else /* OPENSSL_THREADS */
static ossl_unused ossl_inline int CRYPTO_UP_REF(CRYPTO_REF_COUNT *refcnt,
int *ret)
{
refcnt->val++;
*ret = refcnt->val;
return 1;
}
static ossl_unused ossl_inline int CRYPTO_DOWN_REF(CRYPTO_REF_COUNT *refcnt,
int *ret)
{
refcnt->val--;
*ret = refcnt->val;
return 1;
}
static ossl_unused ossl_inline int CRYPTO_GET_REF(CRYPTO_REF_COUNT *refcnt,
int *ret)
{
*ret = refcnt->val;
return 1;
}
# endif /* OPENSSL_THREADS */
# endif
# ifndef CRYPTO_NEW_FREE_DEFINED
static ossl_unused ossl_inline int CRYPTO_NEW_REF(CRYPTO_REF_COUNT *refcnt, int n)
{
refcnt->val = n;
return 1;
}
static ossl_unused ossl_inline void CRYPTO_FREE_REF(CRYPTO_REF_COUNT *refcnt) \
{
}
# endif /* CRYPTO_NEW_FREE_DEFINED */
#undef CRYPTO_NEW_FREE_DEFINED
# if !defined(NDEBUG) && !defined(OPENSSL_NO_STDIO)
# define REF_ASSERT_ISNT(test) \
@ -173,6 +286,6 @@ typedef int CRYPTO_REF_COUNT;
# define REF_PRINT_EX(text, count, object) \
OSSL_TRACE3(REF_COUNT, "%p:%4d:%s\n", (object), (count), (text));
# define REF_PRINT_COUNT(text, object) \
REF_PRINT_EX(text, object->references, (void *)object)
REF_PRINT_EX(text, object->references.val, (void *)object)
#endif

View File

@ -0,0 +1,277 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_INTERNAL_RING_BUF_H
# define OSSL_INTERNAL_RING_BUF_H
# pragma once
# include <openssl/e_os2.h> /* For 'ossl_inline' */
# include "internal/safe_math.h"
/*
* ==================================================================
* Byte-wise ring buffer which supports pushing and popping blocks of multiple
* bytes at a time. The logical offset of each byte for the purposes of a QUIC
* stream is tracked. Bytes can be popped from the ring buffer in two stages;
* first they are popped, and then they are culled. Bytes which have been popped
* but not yet culled will not be overwritten, and can be restored.
*/
struct ring_buf {
void *start;
size_t alloc; /* size of buffer allocation in bytes */
/*
* Logical offset of the head (where we append to). This is the current size
* of the QUIC stream. This increases monotonically.
*/
uint64_t head_offset;
/*
* Logical offset of the cull tail. Data is no longer needed and is
* deallocated as the cull tail advances, which occurs as data is
* acknowledged. This increases monotonically.
*/
uint64_t ctail_offset;
};
OSSL_SAFE_MATH_UNSIGNED(u64, uint64_t)
#define MAX_OFFSET (((uint64_t)1) << 62) /* QUIC-imposed limit */
static ossl_inline int ring_buf_init(struct ring_buf *r)
{
r->start = NULL;
r->alloc = 0;
r->head_offset = r->ctail_offset = 0;
return 1;
}
static ossl_inline void ring_buf_destroy(struct ring_buf *r, int cleanse)
{
if (cleanse)
OPENSSL_clear_free(r->start, r->alloc);
else
OPENSSL_free(r->start);
r->start = NULL;
r->alloc = 0;
}
static ossl_inline size_t ring_buf_used(struct ring_buf *r)
{
return (size_t)(r->head_offset - r->ctail_offset);
}
static ossl_inline size_t ring_buf_avail(struct ring_buf *r)
{
return r->alloc - ring_buf_used(r);
}
static ossl_inline int ring_buf_write_at(struct ring_buf *r,
uint64_t logical_offset,
const unsigned char *buf,
size_t buf_len)
{
size_t avail, idx, l;
unsigned char *start = r->start;
int i, err = 0;
avail = ring_buf_avail(r);
if (logical_offset < r->ctail_offset
|| safe_add_u64(logical_offset, buf_len, &err)
> safe_add_u64(r->head_offset, avail, &err)
|| safe_add_u64(r->head_offset, buf_len, &err)
> MAX_OFFSET
|| err)
return 0;
for (i = 0; buf_len > 0 && i < 2; ++i) {
idx = logical_offset % r->alloc;
l = r->alloc - idx;
if (buf_len < l)
l = buf_len;
memcpy(start + idx, buf, l);
if (r->head_offset < logical_offset + l)
r->head_offset = logical_offset + l;
logical_offset += l;
buf += l;
buf_len -= l;
}
assert(buf_len == 0);
return 1;
}
static ossl_inline size_t ring_buf_push(struct ring_buf *r,
const unsigned char *buf,
size_t buf_len)
{
size_t pushed = 0, avail, idx, l;
unsigned char *start = r->start;
for (;;) {
avail = ring_buf_avail(r);
if (buf_len > avail)
buf_len = avail;
if (buf_len > MAX_OFFSET - r->head_offset)
buf_len = (size_t)(MAX_OFFSET - r->head_offset);
if (buf_len == 0)
break;
idx = r->head_offset % r->alloc;
l = r->alloc - idx;
if (buf_len < l)
l = buf_len;
memcpy(start + idx, buf, l);
r->head_offset += l;
buf += l;
buf_len -= l;
pushed += l;
}
return pushed;
}
static ossl_inline const unsigned char *ring_buf_get_ptr(const struct ring_buf *r,
uint64_t logical_offset,
size_t *max_len)
{
unsigned char *start = r->start;
size_t idx;
if (logical_offset >= r->head_offset || logical_offset < r->ctail_offset)
return NULL;
idx = logical_offset % r->alloc;
*max_len = r->alloc - idx;
return start + idx;
}
/*
* Retrieves data out of the read side of the ring buffer starting at the given
* logical offset. *buf is set to point to a contiguous span of bytes and
* *buf_len is set to the number of contiguous bytes. After this function
* returns, there may or may not be more bytes available at the logical offset
* of (logical_offset + *buf_len) by calling this function again. If the logical
* offset is out of the range retained by the ring buffer, returns 0, else
* returns 1. A logical offset at the end of the range retained by the ring
* buffer is not considered an error and is returned with a *buf_len of 0.
*
* The ring buffer state is not changed.
*/
static ossl_inline int ring_buf_get_buf_at(const struct ring_buf *r,
uint64_t logical_offset,
const unsigned char **buf,
size_t *buf_len)
{
const unsigned char *start = r->start;
size_t idx, l;
if (logical_offset > r->head_offset || logical_offset < r->ctail_offset)
return 0;
if (r->alloc == 0) {
*buf = NULL;
*buf_len = 0;
return 1;
}
idx = logical_offset % r->alloc;
l = (size_t)(r->head_offset - logical_offset);
if (l > r->alloc - idx)
l = r->alloc - idx;
*buf = start + idx;
*buf_len = l;
return 1;
}
static ossl_inline void ring_buf_cpop_range(struct ring_buf *r,
uint64_t start, uint64_t end,
int cleanse)
{
assert(end >= start);
if (start > r->ctail_offset || end >= MAX_OFFSET)
return;
if (cleanse && r->alloc > 0 && end > r->ctail_offset) {
size_t idx = r->ctail_offset % r->alloc;
uint64_t cleanse_end = end + 1;
size_t l;
if (cleanse_end > r->head_offset)
cleanse_end = r->head_offset;
l = (size_t)(cleanse_end - r->ctail_offset);
if (l > r->alloc - idx) {
OPENSSL_cleanse((unsigned char *)r->start + idx, r->alloc - idx);
l -= r->alloc - idx;
idx = 0;
}
if (l > 0)
OPENSSL_cleanse((unsigned char *)r->start + idx, l);
}
r->ctail_offset = end + 1;
/* Allow culling unpushed data */
if (r->head_offset < r->ctail_offset)
r->head_offset = r->ctail_offset;
}
static ossl_inline int ring_buf_resize(struct ring_buf *r, size_t num_bytes,
int cleanse)
{
struct ring_buf rnew = {0};
const unsigned char *src = NULL;
size_t src_len = 0, copied = 0;
if (num_bytes == r->alloc)
return 1;
if (num_bytes < ring_buf_used(r))
return 0;
rnew.start = OPENSSL_malloc(num_bytes);
if (rnew.start == NULL)
return 0;
rnew.alloc = num_bytes;
rnew.head_offset = r->head_offset - ring_buf_used(r);
rnew.ctail_offset = rnew.head_offset;
for (;;) {
if (!ring_buf_get_buf_at(r, r->ctail_offset + copied, &src, &src_len)) {
OPENSSL_free(rnew.start);
return 0;
}
if (src_len == 0)
break;
if (ring_buf_push(&rnew, src, src_len) != src_len) {
OPENSSL_free(rnew.start);
return 0;
}
copied += src_len;
}
assert(rnew.head_offset == r->head_offset);
rnew.ctail_offset = r->ctail_offset;
ring_buf_destroy(r, cleanse);
memcpy(r, &rnew, sizeof(*r));
return 1;
}
#endif /* OSSL_INTERNAL_RING_BUF_H */

View File

@ -0,0 +1,443 @@
/*
* Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_INTERNAL_SAFE_MATH_H
# define OSSL_INTERNAL_SAFE_MATH_H
# pragma once
# include <openssl/e_os2.h> /* For 'ossl_inline' */
# ifndef OPENSSL_NO_BUILTIN_OVERFLOW_CHECKING
# ifdef __has_builtin
# define has(func) __has_builtin(func)
# elif __GNUC__ > 5
# define has(func) 1
# endif
# endif /* OPENSSL_NO_BUILTIN_OVERFLOW_CHECKING */
# ifndef has
# define has(func) 0
# endif
/*
* Safe addition helpers
*/
# if has(__builtin_add_overflow)
# define OSSL_SAFE_MATH_ADDS(type_name, type, min, max) \
static ossl_inline ossl_unused type safe_add_ ## type_name(type a, \
type b, \
int *err) \
{ \
type r; \
\
if (!__builtin_add_overflow(a, b, &r)) \
return r; \
*err |= 1; \
return a < 0 ? min : max; \
}
# define OSSL_SAFE_MATH_ADDU(type_name, type, max) \
static ossl_inline ossl_unused type safe_add_ ## type_name(type a, \
type b, \
int *err) \
{ \
type r; \
\
if (!__builtin_add_overflow(a, b, &r)) \
return r; \
*err |= 1; \
return a + b; \
}
# else /* has(__builtin_add_overflow) */
# define OSSL_SAFE_MATH_ADDS(type_name, type, min, max) \
static ossl_inline ossl_unused type safe_add_ ## type_name(type a, \
type b, \
int *err) \
{ \
if ((a < 0) ^ (b < 0) \
|| (a > 0 && b <= max - a) \
|| (a < 0 && b >= min - a) \
|| a == 0) \
return a + b; \
*err |= 1; \
return a < 0 ? min : max; \
}
# define OSSL_SAFE_MATH_ADDU(type_name, type, max) \
static ossl_inline ossl_unused type safe_add_ ## type_name(type a, \
type b, \
int *err) \
{ \
if (b > max - a) \
*err |= 1; \
return a + b; \
}
# endif /* has(__builtin_add_overflow) */
/*
* Safe subtraction helpers
*/
# if has(__builtin_sub_overflow)
# define OSSL_SAFE_MATH_SUBS(type_name, type, min, max) \
static ossl_inline ossl_unused type safe_sub_ ## type_name(type a, \
type b, \
int *err) \
{ \
type r; \
\
if (!__builtin_sub_overflow(a, b, &r)) \
return r; \
*err |= 1; \
return a < 0 ? min : max; \
}
# else /* has(__builtin_sub_overflow) */
# define OSSL_SAFE_MATH_SUBS(type_name, type, min, max) \
static ossl_inline ossl_unused type safe_sub_ ## type_name(type a, \
type b, \
int *err) \
{ \
if (!((a < 0) ^ (b < 0)) \
|| (b > 0 && a >= min + b) \
|| (b < 0 && a <= max + b) \
|| b == 0) \
return a - b; \
*err |= 1; \
return a < 0 ? min : max; \
}
# endif /* has(__builtin_sub_overflow) */
# define OSSL_SAFE_MATH_SUBU(type_name, type) \
static ossl_inline ossl_unused type safe_sub_ ## type_name(type a, \
type b, \
int *err) \
{ \
if (b > a) \
*err |= 1; \
return a - b; \
}
/*
* Safe multiplication helpers
*/
# if has(__builtin_mul_overflow)
# define OSSL_SAFE_MATH_MULS(type_name, type, min, max) \
static ossl_inline ossl_unused type safe_mul_ ## type_name(type a, \
type b, \
int *err) \
{ \
type r; \
\
if (!__builtin_mul_overflow(a, b, &r)) \
return r; \
*err |= 1; \
return (a < 0) ^ (b < 0) ? min : max; \
}
# define OSSL_SAFE_MATH_MULU(type_name, type, max) \
static ossl_inline ossl_unused type safe_mul_ ## type_name(type a, \
type b, \
int *err) \
{ \
type r; \
\
if (!__builtin_mul_overflow(a, b, &r)) \
return r; \
*err |= 1; \
return a * b; \
}
# else /* has(__builtin_mul_overflow) */
# define OSSL_SAFE_MATH_MULS(type_name, type, min, max) \
static ossl_inline ossl_unused type safe_mul_ ## type_name(type a, \
type b, \
int *err) \
{ \
if (a == 0 || b == 0) \
return 0; \
if (a == 1) \
return b; \
if (b == 1) \
return a; \
if (a != min && b != min) { \
const type x = a < 0 ? -a : a; \
const type y = b < 0 ? -b : b; \
\
if (x <= max / y) \
return a * b; \
} \
*err |= 1; \
return (a < 0) ^ (b < 0) ? min : max; \
}
# define OSSL_SAFE_MATH_MULU(type_name, type, max) \
static ossl_inline ossl_unused type safe_mul_ ## type_name(type a, \
type b, \
int *err) \
{ \
if (b != 0 && a > max / b) \
*err |= 1; \
return a * b; \
}
# endif /* has(__builtin_mul_overflow) */
/*
* Safe division helpers
*/
# define OSSL_SAFE_MATH_DIVS(type_name, type, min, max) \
static ossl_inline ossl_unused type safe_div_ ## type_name(type a, \
type b, \
int *err) \
{ \
if (b == 0) { \
*err |= 1; \
return a < 0 ? min : max; \
} \
if (b == -1 && a == min) { \
*err |= 1; \
return max; \
} \
return a / b; \
}
# define OSSL_SAFE_MATH_DIVU(type_name, type, max) \
static ossl_inline ossl_unused type safe_div_ ## type_name(type a, \
type b, \
int *err) \
{ \
if (b != 0) \
return a / b; \
*err |= 1; \
return max; \
}
/*
* Safe modulus helpers
*/
# define OSSL_SAFE_MATH_MODS(type_name, type, min, max) \
static ossl_inline ossl_unused type safe_mod_ ## type_name(type a, \
type b, \
int *err) \
{ \
if (b == 0) { \
*err |= 1; \
return 0; \
} \
if (b == -1 && a == min) { \
*err |= 1; \
return max; \
} \
return a % b; \
}
# define OSSL_SAFE_MATH_MODU(type_name, type) \
static ossl_inline ossl_unused type safe_mod_ ## type_name(type a, \
type b, \
int *err) \
{ \
if (b != 0) \
return a % b; \
*err |= 1; \
return 0; \
}
/*
* Safe negation helpers
*/
# define OSSL_SAFE_MATH_NEGS(type_name, type, min) \
static ossl_inline ossl_unused type safe_neg_ ## type_name(type a, \
int *err) \
{ \
if (a != min) \
return -a; \
*err |= 1; \
return min; \
}
# define OSSL_SAFE_MATH_NEGU(type_name, type) \
static ossl_inline ossl_unused type safe_neg_ ## type_name(type a, \
int *err) \
{ \
if (a == 0) \
return a; \
*err |= 1; \
return 1 + ~a; \
}
/*
* Safe absolute value helpers
*/
# define OSSL_SAFE_MATH_ABSS(type_name, type, min) \
static ossl_inline ossl_unused type safe_abs_ ## type_name(type a, \
int *err) \
{ \
if (a != min) \
return a < 0 ? -a : a; \
*err |= 1; \
return min; \
}
# define OSSL_SAFE_MATH_ABSU(type_name, type) \
static ossl_inline ossl_unused type safe_abs_ ## type_name(type a, \
int *err) \
{ \
return a; \
}
/*
* Safe fused multiply divide helpers
*
* These are a bit obscure:
* . They begin by checking the denominator for zero and getting rid of this
* corner case.
*
* . Second is an attempt to do the multiplication directly, if it doesn't
* overflow, the quotient is returned (for signed values there is a
* potential problem here which isn't present for unsigned).
*
* . Finally, the multiplication/division is transformed so that the larger
* of the numerators is divided first. This requires a remainder
* correction:
*
* a b / c = (a / c) b + (a mod c) b / c, where a > b
*
* The individual operations need to be overflow checked (again signed
* being more problematic).
*
* The algorithm used is not perfect but it should be "good enough".
*/
# define OSSL_SAFE_MATH_MULDIVS(type_name, type, max) \
static ossl_inline ossl_unused type safe_muldiv_ ## type_name(type a, \
type b, \
type c, \
int *err) \
{ \
int e2 = 0; \
type q, r, x, y; \
\
if (c == 0) { \
*err |= 1; \
return a == 0 || b == 0 ? 0 : max; \
} \
x = safe_mul_ ## type_name(a, b, &e2); \
if (!e2) \
return safe_div_ ## type_name(x, c, err); \
if (b > a) { \
x = b; \
b = a; \
a = x; \
} \
q = safe_div_ ## type_name(a, c, err); \
r = safe_mod_ ## type_name(a, c, err); \
x = safe_mul_ ## type_name(r, b, err); \
y = safe_mul_ ## type_name(q, b, err); \
q = safe_div_ ## type_name(x, c, err); \
return safe_add_ ## type_name(y, q, err); \
}
# define OSSL_SAFE_MATH_MULDIVU(type_name, type, max) \
static ossl_inline ossl_unused type safe_muldiv_ ## type_name(type a, \
type b, \
type c, \
int *err) \
{ \
int e2 = 0; \
type x, y; \
\
if (c == 0) { \
*err |= 1; \
return a == 0 || b == 0 ? 0 : max; \
} \
x = safe_mul_ ## type_name(a, b, &e2); \
if (!e2) \
return x / c; \
if (b > a) { \
x = b; \
b = a; \
a = x; \
} \
x = safe_mul_ ## type_name(a % c, b, err); \
y = safe_mul_ ## type_name(a / c, b, err); \
return safe_add_ ## type_name(y, x / c, err); \
}
/*
* Calculate a / b rounding up:
* i.e. a / b + (a % b != 0)
* Which is usually (less safely) converted to (a + b - 1) / b
* If you *know* that b != 0, then it's safe to ignore err.
*/
#define OSSL_SAFE_MATH_DIV_ROUND_UP(type_name, type, max) \
static ossl_inline ossl_unused type safe_div_round_up_ ## type_name \
(type a, type b, int *errp) \
{ \
type x; \
int *err, err_local = 0; \
\
/* Allow errors to be ignored by callers */ \
err = errp != NULL ? errp : &err_local; \
/* Fast path, both positive */ \
if (b > 0 && a > 0) { \
/* Faster path: no overflow concerns */ \
if (a < max - b) \
return (a + b - 1) / b; \
return a / b + (a % b != 0); \
} \
if (b == 0) { \
*err |= 1; \
return a == 0 ? 0 : max; \
} \
if (a == 0) \
return 0; \
/* Rather slow path because there are negatives involved */ \
x = safe_mod_ ## type_name(a, b, err); \
return safe_add_ ## type_name(safe_div_ ## type_name(a, b, err), \
x != 0, err); \
}
/* Calculate ranges of types */
# define OSSL_SAFE_MATH_MINS(type) ((type)1 << (sizeof(type) * 8 - 1))
# define OSSL_SAFE_MATH_MAXS(type) (~OSSL_SAFE_MATH_MINS(type))
# define OSSL_SAFE_MATH_MAXU(type) (~(type)0)
/*
* Wrapper macros to create all the functions of a given type
*/
# define OSSL_SAFE_MATH_SIGNED(type_name, type) \
OSSL_SAFE_MATH_ADDS(type_name, type, OSSL_SAFE_MATH_MINS(type), \
OSSL_SAFE_MATH_MAXS(type)) \
OSSL_SAFE_MATH_SUBS(type_name, type, OSSL_SAFE_MATH_MINS(type), \
OSSL_SAFE_MATH_MAXS(type)) \
OSSL_SAFE_MATH_MULS(type_name, type, OSSL_SAFE_MATH_MINS(type), \
OSSL_SAFE_MATH_MAXS(type)) \
OSSL_SAFE_MATH_DIVS(type_name, type, OSSL_SAFE_MATH_MINS(type), \
OSSL_SAFE_MATH_MAXS(type)) \
OSSL_SAFE_MATH_MODS(type_name, type, OSSL_SAFE_MATH_MINS(type), \
OSSL_SAFE_MATH_MAXS(type)) \
OSSL_SAFE_MATH_DIV_ROUND_UP(type_name, type, \
OSSL_SAFE_MATH_MAXS(type)) \
OSSL_SAFE_MATH_MULDIVS(type_name, type, OSSL_SAFE_MATH_MAXS(type)) \
OSSL_SAFE_MATH_NEGS(type_name, type, OSSL_SAFE_MATH_MINS(type)) \
OSSL_SAFE_MATH_ABSS(type_name, type, OSSL_SAFE_MATH_MINS(type))
# define OSSL_SAFE_MATH_UNSIGNED(type_name, type) \
OSSL_SAFE_MATH_ADDU(type_name, type, OSSL_SAFE_MATH_MAXU(type)) \
OSSL_SAFE_MATH_SUBU(type_name, type) \
OSSL_SAFE_MATH_MULU(type_name, type, OSSL_SAFE_MATH_MAXU(type)) \
OSSL_SAFE_MATH_DIVU(type_name, type, OSSL_SAFE_MATH_MAXU(type)) \
OSSL_SAFE_MATH_MODU(type_name, type) \
OSSL_SAFE_MATH_DIV_ROUND_UP(type_name, type, \
OSSL_SAFE_MATH_MAXU(type)) \
OSSL_SAFE_MATH_MULDIVU(type_name, type, OSSL_SAFE_MATH_MAXU(type)) \
OSSL_SAFE_MATH_NEGU(type_name, type) \
OSSL_SAFE_MATH_ABSU(type_name, type)
#endif /* OSSL_INTERNAL_SAFE_MATH_H */

View File

@ -1,5 +1,5 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -61,7 +61,25 @@ struct servent *PASCAL getservbyname(const char *, const char *);
# define accept(s,f,l) ((int)accept(s,f,l))
# endif
/* Windows have other names for shutdown() reasons */
# ifndef SHUT_RD
# define SHUT_RD SD_RECEIVE
# endif
# ifndef SHUT_WR
# define SHUT_WR SD_SEND
# endif
# ifndef SHUT_RDWR
# define SHUT_RDWR SD_BOTH
# endif
# else
# if defined(__APPLE__)
/*
* This must be defined before including <netinet/in6.h> to get
* IPV6_RECVPKTINFO
*/
# define __APPLE_USE_RFC_3542
# endif
# ifndef NO_SYS_PARAM_H
# include <sys/param.h>
@ -71,6 +89,9 @@ struct servent *PASCAL getservbyname(const char *, const char *);
# endif
# include <netdb.h>
# if defined(OPENSSL_SYS_VMS)
typedef size_t socklen_t; /* Currently appears to be missing on VMS */
# endif
# if defined(OPENSSL_SYS_VMS_NODECC)
# include <socket.h>
# include <in.h>
@ -95,6 +116,13 @@ struct servent *PASCAL getservbyname(const char *, const char *);
# include <sys/select.h>
# endif
# ifdef OPENSSL_SYS_UNIX
# ifndef OPENSSL_SYS_TANDEM
# include <poll.h>
# endif
# include <errno.h>
# endif
# ifndef VMS
# include <sys/ioctl.h>
# else
@ -136,12 +164,15 @@ struct servent *PASCAL getservbyname(const char *, const char *);
# define get_last_socket_error() errno
# define clear_socket_error() errno=0
# define get_last_socket_error_is_eintr() (get_last_socket_error() == EINTR)
# if defined(OPENSSL_SYS_WINDOWS)
# undef get_last_socket_error
# undef clear_socket_error
# undef get_last_socket_error_is_eintr
# define get_last_socket_error() WSAGetLastError()
# define clear_socket_error() WSASetLastError(0)
# define get_last_socket_error_is_eintr() (get_last_socket_error() == WSAEINTR)
# define readsocket(s,b,n) recv((s),(b),(n),0)
# define writesocket(s,b,n) send((s),(b),(n),0)
# elif defined(__DJGPP__)

View File

@ -0,0 +1,24 @@
/*
* Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/ssl.h>
#ifndef OSSL_INTERNAL_SSL_H
# define OSSL_INTERNAL_SSL_H
# pragma once
typedef void (*ossl_msg_cb)(int write_p, int version, int content_type,
const void *buf, size_t len, SSL *ssl, void *arg);
int ossl_ssl_get_error(const SSL *s, int i, int check_err);
/* Set if this is the QUIC handshake layer */
# define TLS1_FLAGS_QUIC 0x2000
#endif

View File

@ -0,0 +1,40 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/evp.h>
/* tls_pad.c */
int ssl3_cbc_remove_padding_and_mac(size_t *reclen,
size_t origreclen,
unsigned char *recdata,
unsigned char **mac,
int *alloced,
size_t block_size, size_t mac_size,
OSSL_LIB_CTX *libctx);
int tls1_cbc_remove_padding_and_mac(size_t *reclen,
size_t origreclen,
unsigned char *recdata,
unsigned char **mac,
int *alloced,
size_t block_size, size_t mac_size,
int aead,
OSSL_LIB_CTX *libctx);
/* ssl3_cbc.c */
__owur char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx);
__owur int ssl3_cbc_digest_record(const EVP_MD *md,
unsigned char *md_out,
size_t *md_out_size,
const unsigned char *header,
const unsigned char *data,
size_t data_size,
size_t data_plus_mac_plus_padding_size,
const unsigned char *mac_secret,
size_t mac_secret_length, char is_sslv3);

View File

@ -0,0 +1,171 @@
/*
* Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_INTERNAL_STATEM_H
# define OSSL_INTERNAL_STATEM_H
/*****************************************************************************
* *
* These enums should be considered PRIVATE to the state machine. No *
* non-state machine code should need to use these *
* *
*****************************************************************************/
/*
* Valid return codes used for functions performing work prior to or after
* sending or receiving a message
*/
typedef enum {
/* Something went wrong */
WORK_ERROR,
/* We're done working and there shouldn't be anything else to do after */
WORK_FINISHED_STOP,
/* We're done working move onto the next thing */
WORK_FINISHED_CONTINUE,
/* We're working on phase A */
WORK_MORE_A,
/* We're working on phase B */
WORK_MORE_B,
/* We're working on phase C */
WORK_MORE_C
} WORK_STATE;
/* Write transition return codes */
typedef enum {
/* Something went wrong */
WRITE_TRAN_ERROR,
/* A transition was successfully completed and we should continue */
WRITE_TRAN_CONTINUE,
/* There is no more write work to be done */
WRITE_TRAN_FINISHED
} WRITE_TRAN;
/* Message flow states */
typedef enum {
/* No handshake in progress */
MSG_FLOW_UNINITED,
/* A permanent error with this connection */
MSG_FLOW_ERROR,
/* We are reading messages */
MSG_FLOW_READING,
/* We are writing messages */
MSG_FLOW_WRITING,
/* Handshake has finished */
MSG_FLOW_FINISHED
} MSG_FLOW_STATE;
/* Read states */
typedef enum {
READ_STATE_HEADER,
READ_STATE_BODY,
READ_STATE_POST_PROCESS
} READ_STATE;
/* Write states */
typedef enum {
WRITE_STATE_TRANSITION,
WRITE_STATE_PRE_WORK,
WRITE_STATE_SEND,
WRITE_STATE_POST_WORK
} WRITE_STATE;
typedef enum {
CON_FUNC_ERROR = 0,
CON_FUNC_SUCCESS,
CON_FUNC_DONT_SEND
} CON_FUNC_RETURN;
typedef int (*ossl_statem_mutate_handshake_cb)(const unsigned char *msgin,
size_t inlen,
unsigned char **msgout,
size_t *outlen,
void *arg);
typedef void (*ossl_statem_finish_mutate_handshake_cb)(void *arg);
/*****************************************************************************
* *
* This structure should be considered "opaque" to anything outside of the *
* state machine. No non-state machine code should be accessing the members *
* of this structure. *
* *
*****************************************************************************/
struct ossl_statem_st {
MSG_FLOW_STATE state;
WRITE_STATE write_state;
WORK_STATE write_state_work;
READ_STATE read_state;
WORK_STATE read_state_work;
OSSL_HANDSHAKE_STATE hand_state;
/* The handshake state requested by an API call (e.g. HelloRequest) */
OSSL_HANDSHAKE_STATE request_state;
int in_init;
int read_state_first_init;
/* true when we are actually in SSL_accept() or SSL_connect() */
int in_handshake;
/*
* True when are processing a "real" handshake that needs cleaning up (not
* just a HelloRequest or similar).
*/
int cleanuphand;
/* Should we skip the CertificateVerify message? */
unsigned int no_cert_verify;
int use_timer;
/* Test harness message mutator callbacks */
ossl_statem_mutate_handshake_cb mutate_handshake_cb;
ossl_statem_finish_mutate_handshake_cb finish_mutate_handshake_cb;
void *mutatearg;
unsigned int write_in_progress : 1;
};
typedef struct ossl_statem_st OSSL_STATEM;
/*****************************************************************************
* *
* The following macros/functions represent the libssl internal API to the *
* state machine. Any libssl code may call these functions/macros *
* *
*****************************************************************************/
typedef struct ssl_connection_st SSL_CONNECTION;
__owur int ossl_statem_accept(SSL *s);
__owur int ossl_statem_connect(SSL *s);
OSSL_HANDSHAKE_STATE ossl_statem_get_state(SSL_CONNECTION *s);
void ossl_statem_clear(SSL_CONNECTION *s);
void ossl_statem_set_renegotiate(SSL_CONNECTION *s);
void ossl_statem_send_fatal(SSL_CONNECTION *s, int al);
void ossl_statem_fatal(SSL_CONNECTION *s, int al, int reason,
const char *fmt, ...);
# define SSLfatal_alert(s, al) ossl_statem_send_fatal((s), (al))
# define SSLfatal(s, al, r) SSLfatal_data((s), (al), (r), NULL)
# define SSLfatal_data \
(ERR_new(), \
ERR_set_debug(OPENSSL_FILE, OPENSSL_LINE, OPENSSL_FUNC), \
ossl_statem_fatal)
int ossl_statem_in_error(const SSL_CONNECTION *s);
void ossl_statem_set_in_init(SSL_CONNECTION *s, int init);
int ossl_statem_get_in_handshake(SSL_CONNECTION *s);
void ossl_statem_set_in_handshake(SSL_CONNECTION *s, int inhand);
__owur int ossl_statem_skip_early_data(SSL_CONNECTION *s);
void ossl_statem_check_finish_init(SSL_CONNECTION *s, int send);
void ossl_statem_set_hello_verify_done(SSL_CONNECTION *s);
__owur int ossl_statem_app_data_allowed(SSL_CONNECTION *s);
__owur int ossl_statem_export_allowed(SSL_CONNECTION *s);
__owur int ossl_statem_export_early_allowed(SSL_CONNECTION *s);
/* Flush the write BIO */
int statem_flush(SSL_CONNECTION *s);
int ossl_statem_set_mutator(SSL *s,
ossl_statem_mutate_handshake_cb mutate_handshake_cb,
ossl_statem_finish_mutate_handshake_cb finish_mutate_handshake_cb,
void *mutatearg);
#endif

View File

@ -0,0 +1,39 @@
/*
* Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OPENSSL_INTERNAL_THREAD_H
# define OPENSSL_INTERNAL_THREAD_H
# include <openssl/configuration.h>
# include <internal/thread_arch.h>
# include <openssl/e_os2.h>
# include <openssl/types.h>
# include <internal/cryptlib.h>
# include "crypto/context.h"
void *ossl_crypto_thread_start(OSSL_LIB_CTX *ctx, CRYPTO_THREAD_ROUTINE start,
void *data);
int ossl_crypto_thread_join(void *task, CRYPTO_THREAD_RETVAL *retval);
int ossl_crypto_thread_clean(void *vhandle);
uint64_t ossl_get_avail_threads(OSSL_LIB_CTX *ctx);
# if defined(OPENSSL_THREADS)
# define OSSL_LIB_CTX_GET_THREADS(CTX) \
ossl_lib_ctx_get_data(CTX, OSSL_LIB_CTX_THREAD_INDEX);
typedef struct openssl_threads_st {
uint64_t max_threads;
uint64_t active_threads;
CRYPTO_MUTEX *lock;
CRYPTO_CONDVAR *cond_finished;
} OSSL_LIB_CTX_THREADS;
# endif /* defined(OPENSSL_THREADS) */
#endif /* OPENSSL_INTERNAL_THREAD_H */

View File

@ -0,0 +1,127 @@
/*
* Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_INTERNAL_THREAD_ARCH_H
# define OSSL_INTERNAL_THREAD_ARCH_H
# include <openssl/configuration.h>
# include <openssl/e_os2.h>
# include "internal/time.h"
# if defined(_WIN32)
# include <windows.h>
# endif
# if defined(OPENSSL_THREADS) && defined(OPENSSL_SYS_UNIX)
# define OPENSSL_THREADS_POSIX
# elif defined(OPENSSL_THREADS) && defined(OPENSSL_SYS_VMS)
# define OPENSSL_THREADS_POSIX
# elif defined(OPENSSL_THREADS) && defined(OPENSSL_SYS_WINDOWS) && \
defined(_WIN32_WINNT)
# if _WIN32_WINNT >= 0x0600
# define OPENSSL_THREADS_WINNT
# elif _WIN32_WINNT >= 0x0501
# define OPENSSL_THREADS_WINNT
# define OPENSSL_THREADS_WINNT_LEGACY
# else
# define OPENSSL_THREADS_NONE
# endif
# else
# define OPENSSL_THREADS_NONE
# endif
# include <openssl/crypto.h>
typedef void CRYPTO_MUTEX;
typedef void CRYPTO_CONDVAR;
CRYPTO_MUTEX *ossl_crypto_mutex_new(void);
void ossl_crypto_mutex_lock(CRYPTO_MUTEX *mutex);
int ossl_crypto_mutex_try_lock(CRYPTO_MUTEX *mutex);
void ossl_crypto_mutex_unlock(CRYPTO_MUTEX *mutex);
void ossl_crypto_mutex_free(CRYPTO_MUTEX **mutex);
CRYPTO_CONDVAR *ossl_crypto_condvar_new(void);
void ossl_crypto_condvar_wait(CRYPTO_CONDVAR *cv, CRYPTO_MUTEX *mutex);
void ossl_crypto_condvar_wait_timeout(CRYPTO_CONDVAR *cv, CRYPTO_MUTEX *mutex,
OSSL_TIME deadline);
void ossl_crypto_condvar_broadcast(CRYPTO_CONDVAR *cv);
void ossl_crypto_condvar_signal(CRYPTO_CONDVAR *cv);
void ossl_crypto_condvar_free(CRYPTO_CONDVAR **cv);
typedef uint32_t CRYPTO_THREAD_RETVAL;
typedef CRYPTO_THREAD_RETVAL (*CRYPTO_THREAD_ROUTINE)(void *);
typedef CRYPTO_THREAD_RETVAL (*CRYPTO_THREAD_ROUTINE_CB)(void *,
void (**)(void *),
void **);
# define CRYPTO_THREAD_NO_STATE 0UL
# define CRYPTO_THREAD_FINISHED (1UL << 0)
# define CRYPTO_THREAD_JOIN_AWAIT (1UL << 1)
# define CRYPTO_THREAD_JOINED (1UL << 2)
# define CRYPTO_THREAD_GET_STATE(THREAD, FLAG) ((THREAD)->state & (FLAG))
# define CRYPTO_THREAD_GET_ERROR(THREAD, FLAG) (((THREAD)->state >> 16) & (FLAG))
typedef struct crypto_thread_st {
uint32_t state;
void *data;
CRYPTO_THREAD_ROUTINE routine;
CRYPTO_THREAD_RETVAL retval;
void *handle;
CRYPTO_MUTEX *lock;
CRYPTO_MUTEX *statelock;
CRYPTO_CONDVAR *condvar;
unsigned long thread_id;
int joinable;
OSSL_LIB_CTX *ctx;
} CRYPTO_THREAD;
# if defined(OPENSSL_THREADS)
# define CRYPTO_THREAD_UNSET_STATE(THREAD, FLAG) \
do { \
(THREAD)->state &= ~(FLAG); \
} while ((void)0, 0)
# define CRYPTO_THREAD_SET_STATE(THREAD, FLAG) \
do { \
(THREAD)->state |= (FLAG); \
} while ((void)0, 0)
# define CRYPTO_THREAD_SET_ERROR(THREAD, FLAG) \
do { \
(THREAD)->state |= ((FLAG) << 16); \
} while ((void)0, 0)
# define CRYPTO_THREAD_UNSET_ERROR(THREAD, FLAG) \
do { \
(THREAD)->state &= ~((FLAG) << 16); \
} while ((void)0, 0)
# else
# define CRYPTO_THREAD_UNSET_STATE(THREAD, FLAG)
# define CRYPTO_THREAD_SET_STATE(THREAD, FLAG)
# define CRYPTO_THREAD_SET_ERROR(THREAD, FLAG)
# define CRYPTO_THREAD_UNSET_ERROR(THREAD, FLAG)
# endif /* defined(OPENSSL_THREADS) */
CRYPTO_THREAD * ossl_crypto_thread_native_start(CRYPTO_THREAD_ROUTINE routine,
void *data, int joinable);
int ossl_crypto_thread_native_spawn(CRYPTO_THREAD *thread);
int ossl_crypto_thread_native_join(CRYPTO_THREAD *thread,
CRYPTO_THREAD_RETVAL *retval);
int ossl_crypto_thread_native_perform_join(CRYPTO_THREAD *thread,
CRYPTO_THREAD_RETVAL *retval);
int ossl_crypto_thread_native_exit(void);
int ossl_crypto_thread_native_is_self(CRYPTO_THREAD *thread);
int ossl_crypto_thread_native_clean(CRYPTO_THREAD *thread);
#endif /* OSSL_INTERNAL_THREAD_ARCH_H */

View File

@ -0,0 +1,242 @@
/*
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_INTERNAL_TIME_H
# define OSSL_INTERNAL_TIME_H
# pragma once
# include <openssl/e_os2.h> /* uint64_t */
# include "internal/e_os.h" /* for struct timeval */
# include "internal/safe_math.h"
/*
* Internal type defining a time.
* This should be treated as an opaque structure.
*
* The time datum is Unix's 1970 and at nanosecond precision, this gives
* a range of 584 years roughly.
*/
typedef struct {
uint64_t t; /* Ticks since the epoch */
} OSSL_TIME;
/* The precision of times allows this many values per second */
# define OSSL_TIME_SECOND ((uint64_t)1000000000)
/* One millisecond. */
# define OSSL_TIME_MS (OSSL_TIME_SECOND / 1000)
/* One microsecond. */
# define OSSL_TIME_US (OSSL_TIME_MS / 1000)
/* One nanosecond. */
# define OSSL_TIME_NS (OSSL_TIME_US / 1000)
#define ossl_seconds2time(s) ossl_ticks2time((s) * OSSL_TIME_SECOND)
#define ossl_time2seconds(t) (ossl_time2ticks(t) / OSSL_TIME_SECOND)
#define ossl_ms2time(ms) ossl_ticks2time((ms) * OSSL_TIME_MS)
#define ossl_time2ms(t) (ossl_time2ticks(t) / OSSL_TIME_MS)
#define ossl_us2time(us) ossl_ticks2time((us) * OSSL_TIME_US)
#define ossl_time2us(t) (ossl_time2ticks(t) / OSSL_TIME_US)
/*
* Arithmetic operations on times.
* These operations are saturating, in that an overflow or underflow returns
* the largest or smallest value respectively.
*/
OSSL_SAFE_MATH_UNSIGNED(time, uint64_t)
/* Convert a tick count into a time */
static ossl_unused ossl_inline
OSSL_TIME ossl_ticks2time(uint64_t ticks)
{
OSSL_TIME r;
r.t = ticks;
return r;
}
/* Convert a time to a tick count */
static ossl_unused ossl_inline
uint64_t ossl_time2ticks(OSSL_TIME t)
{
return t.t;
}
/* Get current time */
OSSL_TIME ossl_time_now(void);
/* The beginning and end of the time range */
static ossl_unused ossl_inline
OSSL_TIME ossl_time_zero(void)
{
return ossl_ticks2time(0);
}
static ossl_unused ossl_inline
OSSL_TIME ossl_time_infinite(void)
{
return ossl_ticks2time(~(uint64_t)0);
}
/* Convert time to timeval */
static ossl_unused ossl_inline
struct timeval ossl_time_to_timeval(OSSL_TIME t)
{
struct timeval tv;
int err = 0;
/*
* Round up any nano secs which struct timeval doesn't support. Ensures that
* we never return a zero time if the input time is non zero
*/
t.t = safe_add_time(t.t, OSSL_TIME_US - 1, &err);
if (err)
t = ossl_time_infinite();
#ifdef _WIN32
tv.tv_sec = (long int)(t.t / OSSL_TIME_SECOND);
#else
tv.tv_sec = (time_t)(t.t / OSSL_TIME_SECOND);
#endif
tv.tv_usec = (t.t % OSSL_TIME_SECOND) / OSSL_TIME_US;
return tv;
}
/* Convert timeval to time */
static ossl_unused ossl_inline
OSSL_TIME ossl_time_from_timeval(struct timeval tv)
{
OSSL_TIME t;
#ifndef __DJGPP__ /* tv_sec is unsigned on djgpp. */
if (tv.tv_sec < 0)
return ossl_time_zero();
#endif
t.t = tv.tv_sec * OSSL_TIME_SECOND + tv.tv_usec * OSSL_TIME_US;
return t;
}
/* Convert OSSL_TIME to time_t */
static ossl_unused ossl_inline
time_t ossl_time_to_time_t(OSSL_TIME t)
{
return (time_t)(t.t / OSSL_TIME_SECOND);
}
/* Convert time_t to OSSL_TIME */
static ossl_unused ossl_inline
OSSL_TIME ossl_time_from_time_t(time_t t)
{
OSSL_TIME ot;
ot.t = t;
ot.t *= OSSL_TIME_SECOND;
return ot;
}
/* Compare two time values, return -1 if less, 1 if greater and 0 if equal */
static ossl_unused ossl_inline
int ossl_time_compare(OSSL_TIME a, OSSL_TIME b)
{
if (a.t > b.t)
return 1;
if (a.t < b.t)
return -1;
return 0;
}
/* Returns true if an OSSL_TIME is ossl_time_zero(). */
static ossl_unused ossl_inline
int ossl_time_is_zero(OSSL_TIME t)
{
return ossl_time_compare(t, ossl_time_zero()) == 0;
}
/* Returns true if an OSSL_TIME is ossl_time_infinite(). */
static ossl_unused ossl_inline
int ossl_time_is_infinite(OSSL_TIME t)
{
return ossl_time_compare(t, ossl_time_infinite()) == 0;
}
static ossl_unused ossl_inline
OSSL_TIME ossl_time_add(OSSL_TIME a, OSSL_TIME b)
{
OSSL_TIME r;
int err = 0;
r.t = safe_add_time(a.t, b.t, &err);
return err ? ossl_time_infinite() : r;
}
static ossl_unused ossl_inline
OSSL_TIME ossl_time_subtract(OSSL_TIME a, OSSL_TIME b)
{
OSSL_TIME r;
int err = 0;
r.t = safe_sub_time(a.t, b.t, &err);
return err ? ossl_time_zero() : r;
}
/* Returns |a - b|. */
static ossl_unused ossl_inline
OSSL_TIME ossl_time_abs_difference(OSSL_TIME a, OSSL_TIME b)
{
return a.t > b.t ? ossl_time_subtract(a, b)
: ossl_time_subtract(b, a);
}
static ossl_unused ossl_inline
OSSL_TIME ossl_time_multiply(OSSL_TIME a, uint64_t b)
{
OSSL_TIME r;
int err = 0;
r.t = safe_mul_time(a.t, b, &err);
return err ? ossl_time_infinite() : r;
}
static ossl_unused ossl_inline
OSSL_TIME ossl_time_divide(OSSL_TIME a, uint64_t b)
{
OSSL_TIME r;
int err = 0;
r.t = safe_div_time(a.t, b, &err);
return err ? ossl_time_zero() : r;
}
static ossl_unused ossl_inline
OSSL_TIME ossl_time_muldiv(OSSL_TIME a, uint64_t b, uint64_t c)
{
OSSL_TIME r;
int err = 0;
r.t = safe_muldiv_time(a.t, b, c, &err);
return err ? ossl_time_zero() : r;
}
/* Return higher of the two given time values. */
static ossl_unused ossl_inline
OSSL_TIME ossl_time_max(OSSL_TIME a, OSSL_TIME b)
{
return a.t > b.t ? a : b;
}
/* Return the lower of the two given time values. */
static ossl_unused ossl_inline
OSSL_TIME ossl_time_min(OSSL_TIME a, OSSL_TIME b)
{
return a.t < b.t ? a : b;
}
#endif

View File

@ -41,6 +41,16 @@
# define OSSL_TLS_GROUP_ID_brainpoolP512r1 0x001C
# define OSSL_TLS_GROUP_ID_x25519 0x001D
# define OSSL_TLS_GROUP_ID_x448 0x001E
# define OSSL_TLS_GROUP_ID_brainpoolP256r1_tls13 0x001F
# define OSSL_TLS_GROUP_ID_brainpoolP384r1_tls13 0x0020
# define OSSL_TLS_GROUP_ID_brainpoolP512r1_tls13 0x0021
# define OSSL_TLS_GROUP_ID_gc256A 0x0022
# define OSSL_TLS_GROUP_ID_gc256B 0x0023
# define OSSL_TLS_GROUP_ID_gc256C 0x0024
# define OSSL_TLS_GROUP_ID_gc256D 0x0025
# define OSSL_TLS_GROUP_ID_gc512A 0x0026
# define OSSL_TLS_GROUP_ID_gc512B 0x0027
# define OSSL_TLS_GROUP_ID_gc512C 0x0028
# define OSSL_TLS_GROUP_ID_ffdhe2048 0x0100
# define OSSL_TLS_GROUP_ID_ffdhe3072 0x0101
# define OSSL_TLS_GROUP_ID_ffdhe4096 0x0102

View File

@ -47,6 +47,10 @@
* can use TSAN_QUALIFIER in cast specifically when it has to count.
*/
#ifndef OSSL_INTERNAL_TSAN_ASSIST_H
# define OSSL_INTERNAL_TSAN_ASSIST_H
# pragma once
# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \
&& !defined(__STDC_NO_ATOMICS__)
# include <stdatomic.h>
@ -146,3 +150,4 @@
# define tsan_counter(ptr) tsan_add((ptr), 1)
# define tsan_decr(ptr) tsan_add((ptr), -1)
#endif

View File

@ -0,0 +1,63 @@
/*
* Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_UINT_SET_H
# define OSSL_UINT_SET_H
#include "openssl/params.h"
#include "internal/list.h"
/*
* uint64_t Integer Sets
* =====================
*
* Utilities for managing a logical set of unsigned 64-bit integers. The
* structure tracks each contiguous range of integers using one allocation and
* is thus optimised for cases where integers tend to appear consecutively.
* Queries are optimised under the assumption that they will generally be made
* on integers near the end of the set.
*
* Discussion of implementation details can be found in uint_set.c.
*/
typedef struct uint_range_st {
uint64_t start, end;
} UINT_RANGE;
typedef struct uint_set_item_st UINT_SET_ITEM;
struct uint_set_item_st {
OSSL_LIST_MEMBER(uint_set, UINT_SET_ITEM);
UINT_RANGE range;
};
DEFINE_LIST_OF(uint_set, UINT_SET_ITEM);
typedef OSSL_LIST(uint_set) UINT_SET;
void ossl_uint_set_init(UINT_SET *s);
void ossl_uint_set_destroy(UINT_SET *s);
/*
* Insert a range into a integer set. Returns 0 on allocation failure, in which
* case the integer set is in a valid but undefined state. Otherwise, returns 1.
* Ranges can overlap existing ranges without limitation. If a range is a subset
* of an existing range in the set, this is a no-op and returns 1.
*/
int ossl_uint_set_insert(UINT_SET *s, const UINT_RANGE *range);
/*
* Remove a range from the set. Returns 0 on allocation failure, in which case
* the integer set is unchanged. Otherwise, returns 1. Ranges which are not
* already in the set can be removed without issue. If a passed range is not in
* the integer set at all, this is a no-op and returns 1.
*/
int ossl_uint_set_remove(UINT_SET *s, const UINT_RANGE *range);
/* Returns 1 iff the given integer is in the integer set. */
int ossl_uint_set_query(const UINT_SET *s, uint64_t v);
#endif

View File

@ -2,7 +2,7 @@
* WARNING: do not edit!
* Generated by Makefile from include/openssl/asn1.h.in
*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -999,6 +999,8 @@ int ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *a, long *num,
unsigned char *data, int max_len);
void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it);
void *ASN1_item_unpack_ex(const ASN1_STRING *oct, const ASN1_ITEM *it,
OSSL_LIB_CTX *libctx, const char *propq);
ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it,
ASN1_OCTET_STRING **oct);

View File

@ -1,7 +1,7 @@
/*
* {- join("\n * ", @autowarntext) -}
*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -832,6 +832,8 @@ int ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *a, long *num,
unsigned char *data, int max_len);
void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it);
void *ASN1_item_unpack_ex(const ASN1_STRING *oct, const ASN1_ITEM *it,
OSSL_LIB_CTX *libctx, const char *propq);
ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it,
ASN1_OCTET_STRING **oct);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -80,6 +80,14 @@ int ASYNC_WAIT_CTX_clear_fd(ASYNC_WAIT_CTX *ctx, const void *key);
int ASYNC_is_capable(void);
typedef void *(*ASYNC_stack_alloc_fn)(size_t *num);
typedef void (*ASYNC_stack_free_fn)(void *addr);
int ASYNC_set_mem_functions(ASYNC_stack_alloc_fn alloc_fn,
ASYNC_stack_free_fn free_fn);
void ASYNC_get_mem_functions(ASYNC_stack_alloc_fn *alloc_fn,
ASYNC_stack_free_fn *free_fn);
int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *ctx, int *ret,
int (*func)(void *), void *args, size_t size);
int ASYNC_pause_job(void);

View File

@ -2,7 +2,7 @@
* WARNING: do not edit!
* Generated by Makefile from include/openssl/bio.h.in
*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -67,6 +67,8 @@ extern "C" {
# define BIO_TYPE_DGRAM_SCTP (24|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR)
# endif
# define BIO_TYPE_CORE_TO_PROV (25|BIO_TYPE_SOURCE_SINK)
# define BIO_TYPE_DGRAM_PAIR (26|BIO_TYPE_SOURCE_SINK)
# define BIO_TYPE_DGRAM_MEM (27|BIO_TYPE_SOURCE_SINK)
#define BIO_TYPE_START 128
@ -171,6 +173,30 @@ extern "C" {
# define BIO_CTRL_SET_INDENT 80
# define BIO_CTRL_GET_INDENT 81
# define BIO_CTRL_DGRAM_GET_LOCAL_ADDR_CAP 82
# define BIO_CTRL_DGRAM_GET_LOCAL_ADDR_ENABLE 83
# define BIO_CTRL_DGRAM_SET_LOCAL_ADDR_ENABLE 84
# define BIO_CTRL_DGRAM_GET_EFFECTIVE_CAPS 85
# define BIO_CTRL_DGRAM_GET_CAPS 86
# define BIO_CTRL_DGRAM_SET_CAPS 87
# define BIO_CTRL_DGRAM_GET_NO_TRUNC 88
# define BIO_CTRL_DGRAM_SET_NO_TRUNC 89
/*
* internal BIO:
* # define BIO_CTRL_SET_KTLS_TX_ZEROCOPY_SENDFILE 90
*/
# define BIO_CTRL_GET_RPOLL_DESCRIPTOR 91
# define BIO_CTRL_GET_WPOLL_DESCRIPTOR 92
# define BIO_CTRL_DGRAM_DETECT_PEER_ADDR 93
# define BIO_DGRAM_CAP_NONE 0U
# define BIO_DGRAM_CAP_HANDLES_SRC_ADDR (1U << 0)
# define BIO_DGRAM_CAP_HANDLES_DST_ADDR (1U << 1)
# define BIO_DGRAM_CAP_PROVIDES_SRC_ADDR (1U << 2)
# define BIO_DGRAM_CAP_PROVIDES_DST_ADDR (1U << 3)
# ifndef OPENSSL_NO_KTLS
# define BIO_get_ktls_send(b) \
(BIO_ctrl(b, BIO_CTRL_GET_KTLS_SEND, 0, NULL) > 0)
@ -208,7 +234,7 @@ extern "C" {
# define BIO_FLAGS_NONCLEAR_RST 0x400
# define BIO_FLAGS_IN_EOF 0x800
/* the BIO FLAGS values 0x1000 to 0x4000 are reserved for internal KTLS flags */
/* the BIO FLAGS values 0x1000 to 0x8000 are reserved for internal KTLS flags */
typedef union bio_addr_st BIO_ADDR;
typedef struct bio_addrinfo_st BIO_ADDRINFO;
@ -262,6 +288,8 @@ void BIO_clear_flags(BIO *b, int flags);
# define BIO_CB_PUTS 0x04
# define BIO_CB_GETS 0x05
# define BIO_CB_CTRL 0x06
# define BIO_CB_RECVMMSG 0x07
# define BIO_CB_SENDMMSG 0x08
/*
* The callback is called before and after the underling operation, The
@ -362,6 +390,34 @@ struct bio_dgram_sctp_prinfo {
};
# endif
/* BIO_sendmmsg/BIO_recvmmsg-related definitions */
typedef struct bio_msg_st {
void *data;
size_t data_len;
BIO_ADDR *peer, *local;
uint64_t flags;
} BIO_MSG;
typedef struct bio_mmsg_cb_args_st {
BIO_MSG *msg;
size_t stride, num_msg;
uint64_t flags;
size_t *msgs_processed;
} BIO_MMSG_CB_ARGS;
#define BIO_POLL_DESCRIPTOR_TYPE_NONE 0
#define BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD 1
#define BIO_POLL_DESCRIPTOR_CUSTOM_START 8192
typedef struct bio_poll_descriptor_st {
uint32_t type;
union {
int fd;
void *custom;
uintptr_t custom_ui;
} value;
} BIO_POLL_DESCRIPTOR;
/*
* #define BIO_CONN_get_param_hostname BIO_ctrl
*/
@ -428,10 +484,17 @@ struct bio_dgram_sctp_prinfo {
# define BIO_C_SET_CONNECT_MODE 155
# define BIO_C_SET_TFO 156 /* like BIO_C_SET_NBIO */
# define BIO_C_SET_SOCK_TYPE 157
# define BIO_C_GET_SOCK_TYPE 158
# define BIO_C_GET_DGRAM_BIO 159
# define BIO_set_app_data(s,arg) BIO_set_ex_data(s,0,arg)
# define BIO_get_app_data(s) BIO_get_ex_data(s,0)
# define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL)
# define BIO_set_tfo(b,n) BIO_ctrl(b,BIO_C_SET_TFO,(n),NULL)
# ifndef OPENSSL_NO_SOCK
/* IP families we support, for BIO_s_connect() and BIO_s_accept() */
@ -452,7 +515,11 @@ struct bio_dgram_sctp_prinfo {
# define BIO_get_conn_port(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,1))
# define BIO_get_conn_address(b) ((const BIO_ADDR *)BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,2))
# define BIO_get_conn_ip_family(b) BIO_ctrl(b,BIO_C_GET_CONNECT,3,NULL)
# define BIO_get_conn_mode(b) BIO_ctrl(b,BIO_C_GET_CONNECT,4,NULL)
# define BIO_set_conn_mode(b,n) BIO_ctrl(b,BIO_C_SET_CONNECT_MODE,(n),NULL)
# define BIO_set_sock_type(b,t) BIO_ctrl(b,BIO_C_SET_SOCK_TYPE,(t),NULL)
# define BIO_get_sock_type(b) BIO_ctrl(b,BIO_C_GET_SOCK_TYPE,0,NULL)
# define BIO_get0_dgram_bio(b, p) BIO_ctrl(b,BIO_C_GET_DGRAM_BIO,0,(void *)(BIO **)(p))
/* BIO_s_accept() */
# define BIO_set_accept_name(b,name) BIO_ctrl(b,BIO_C_SET_ACCEPT,0, \
@ -469,6 +536,7 @@ struct bio_dgram_sctp_prinfo {
(char *)(bio))
# define BIO_set_accept_ip_family(b,f) BIO_int_ctrl(b,BIO_C_SET_ACCEPT,4,f)
# define BIO_get_accept_ip_family(b) BIO_ctrl(b,BIO_C_GET_ACCEPT,4,NULL)
# define BIO_set_tfo_accept(b,n) BIO_ctrl(b,BIO_C_SET_ACCEPT,5,(n)?(void *)"a":NULL)
/* Aliases kept for backward compatibility */
# define BIO_BIND_NORMAL 0
@ -596,8 +664,30 @@ int BIO_ctrl_reset_read_request(BIO *b);
(int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_PEER, 0, (char *)(peer))
# define BIO_dgram_set_peer(b,peer) \
(int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, (char *)(peer))
# define BIO_dgram_detect_peer_addr(b,peer) \
(int)BIO_ctrl(b, BIO_CTRL_DGRAM_DETECT_PEER_ADDR, 0, (char *)(peer))
# define BIO_dgram_get_mtu_overhead(b) \
(unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_MTU_OVERHEAD, 0, NULL)
# define BIO_dgram_get_local_addr_cap(b) \
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_LOCAL_ADDR_CAP, 0, NULL)
# define BIO_dgram_get_local_addr_enable(b, penable) \
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_LOCAL_ADDR_ENABLE, 0, (char *)(penable))
# define BIO_dgram_set_local_addr_enable(b, enable) \
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_SET_LOCAL_ADDR_ENABLE, (enable), NULL)
# define BIO_dgram_get_effective_caps(b) \
(uint32_t)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_EFFECTIVE_CAPS, 0, NULL)
# define BIO_dgram_get_caps(b) \
(uint32_t)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_CAPS, 0, NULL)
# define BIO_dgram_set_caps(b, caps) \
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_SET_CAPS, (long)(caps), NULL)
# define BIO_dgram_get_no_trunc(b) \
(unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_NO_TRUNC, 0, NULL)
# define BIO_dgram_set_no_trunc(b, enable) \
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_SET_NO_TRUNC, (enable), NULL)
# define BIO_dgram_get_mtu(b) \
(unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_MTU, 0, NULL)
# define BIO_dgram_set_mtu(b, mtu) \
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_SET_MTU, (mtu), NULL)
/* ctrl macros for BIO_f_prefix */
# define BIO_set_prefix(b,p) BIO_ctrl((b), BIO_CTRL_SET_PREFIX, 0, (void *)(p))
@ -640,10 +730,18 @@ void BIO_vfree(BIO *a);
int BIO_up_ref(BIO *a);
int BIO_read(BIO *b, void *data, int dlen);
int BIO_read_ex(BIO *b, void *data, size_t dlen, size_t *readbytes);
__owur int BIO_recvmmsg(BIO *b, BIO_MSG *msg,
size_t stride, size_t num_msg, uint64_t flags,
size_t *msgs_processed);
int BIO_gets(BIO *bp, char *buf, int size);
int BIO_get_line(BIO *bio, char *buf, int size);
int BIO_write(BIO *b, const void *data, int dlen);
int BIO_write_ex(BIO *b, const void *data, size_t dlen, size_t *written);
__owur int BIO_sendmmsg(BIO *b, BIO_MSG *msg,
size_t stride, size_t num_msg, uint64_t flags,
size_t *msgs_processed);
__owur int BIO_get_rpoll_descriptor(BIO *b, BIO_POLL_DESCRIPTOR *desc);
__owur int BIO_get_wpoll_descriptor(BIO *b, BIO_POLL_DESCRIPTOR *desc);
int BIO_puts(BIO *bp, const char *buf);
int BIO_indent(BIO *b, int indent, int max);
long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg);
@ -667,6 +765,9 @@ int BIO_nwrite0(BIO *bio, char **buf);
int BIO_nwrite(BIO *bio, char **buf, int num);
const BIO_METHOD *BIO_s_mem(void);
# ifndef OPENSSL_NO_DGRAM
const BIO_METHOD *BIO_s_dgram_mem(void);
# endif
const BIO_METHOD *BIO_s_secmem(void);
BIO *BIO_new_mem_buf(const void *buf, int len);
# ifndef OPENSSL_NO_SOCK
@ -686,6 +787,7 @@ const BIO_METHOD *BIO_f_nbio_test(void);
const BIO_METHOD *BIO_f_prefix(void);
const BIO_METHOD *BIO_s_core(void);
# ifndef OPENSSL_NO_DGRAM
const BIO_METHOD *BIO_s_dgram_pair(void);
const BIO_METHOD *BIO_s_datagram(void);
int BIO_dgram_non_fatal_error(int error);
BIO *BIO_new_dgram(int fd, int close_flag);
@ -704,6 +806,7 @@ int BIO_dgram_sctp_msg_waiting(BIO *b);
# ifndef OPENSSL_NO_SOCK
int BIO_sock_should_retry(int i);
int BIO_sock_non_fatal_error(int error);
int BIO_err_is_non_fatal(unsigned int errcode);
int BIO_socket_wait(int fd, int for_read, time_t max_time);
# endif
int BIO_wait(BIO *bio, time_t max_time, unsigned int nap_milliseconds);
@ -726,6 +829,8 @@ int BIO_hex_string(BIO *out, int indent, int width, const void *data,
# ifndef OPENSSL_NO_SOCK
BIO_ADDR *BIO_ADDR_new(void);
int BIO_ADDR_copy(BIO_ADDR *dst, const BIO_ADDR *src);
BIO_ADDR *BIO_ADDR_dup(const BIO_ADDR *ap);
int BIO_ADDR_rawmake(BIO_ADDR *ap, int family,
const void *where, size_t wherelen, unsigned short port);
void BIO_ADDR_free(BIO_ADDR *);
@ -788,6 +893,7 @@ int BIO_sock_info(int sock,
# define BIO_SOCK_KEEPALIVE 0x04
# define BIO_SOCK_NONBLOCK 0x08
# define BIO_SOCK_NODELAY 0x10
# define BIO_SOCK_TFO 0x20
int BIO_socket(int domain, int socktype, int protocol, int options);
int BIO_connect(int sock, const BIO_ADDR *addr, int options);
@ -805,6 +911,11 @@ BIO *BIO_new_fd(int fd, int close_flag);
int BIO_new_bio_pair(BIO **bio1, size_t writebuf1,
BIO **bio2, size_t writebuf2);
# ifndef OPENSSL_NO_DGRAM
int BIO_new_bio_dgram_pair(BIO **bio1, size_t writebuf1,
BIO **bio2, size_t writebuf2);
# endif
/*
* If successful, returns 1 and in *bio1, *bio2 two BIO pair endpoints.
* Otherwise returns 0 and sets *bio1 and *bio2 to NULL. Size 0 uses default
@ -856,18 +967,30 @@ int BIO_meth_set_write(BIO_METHOD *biom,
int (*write) (BIO *, const char *, int));
int BIO_meth_set_write_ex(BIO_METHOD *biom,
int (*bwrite) (BIO *, const char *, size_t, size_t *));
int BIO_meth_set_sendmmsg(BIO_METHOD *biom,
int (*f) (BIO *, BIO_MSG *, size_t, size_t,
uint64_t, size_t *));
int (*BIO_meth_get_sendmmsg(const BIO_METHOD *biom))(BIO *, BIO_MSG *,
size_t, size_t,
uint64_t, size_t *);
int (*BIO_meth_get_read(const BIO_METHOD *biom)) (BIO *, char *, int);
int (*BIO_meth_get_read_ex(const BIO_METHOD *biom)) (BIO *, char *, size_t, size_t *);
int BIO_meth_set_read(BIO_METHOD *biom,
int (*read) (BIO *, char *, int));
int BIO_meth_set_read_ex(BIO_METHOD *biom,
int (*bread) (BIO *, char *, size_t, size_t *));
int BIO_meth_set_recvmmsg(BIO_METHOD *biom,
int (*f) (BIO *, BIO_MSG *, size_t, size_t,
uint64_t, size_t *));
int (*BIO_meth_get_recvmmsg(const BIO_METHOD *biom))(BIO *, BIO_MSG *,
size_t, size_t,
uint64_t, size_t *);
int (*BIO_meth_get_puts(const BIO_METHOD *biom)) (BIO *, const char *);
int BIO_meth_set_puts(BIO_METHOD *biom,
int (*puts) (BIO *, const char *));
int (*BIO_meth_get_gets(const BIO_METHOD *biom)) (BIO *, char *, int);
int BIO_meth_set_gets(BIO_METHOD *biom,
int (*gets) (BIO *, char *, int));
int (*ossl_gets) (BIO *, char *, int));
long (*BIO_meth_get_ctrl(const BIO_METHOD *biom)) (BIO *, int, long, void *);
int BIO_meth_set_ctrl(BIO_METHOD *biom,
long (*ctrl) (BIO *, int, long, void *));

View File

@ -1,7 +1,7 @@
/*
* {- join("\n * ", @autowarntext) -}
*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -68,6 +68,8 @@ extern "C" {
# define BIO_TYPE_DGRAM_SCTP (24|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR)
# endif
# define BIO_TYPE_CORE_TO_PROV (25|BIO_TYPE_SOURCE_SINK)
# define BIO_TYPE_DGRAM_PAIR (26|BIO_TYPE_SOURCE_SINK)
# define BIO_TYPE_DGRAM_MEM (27|BIO_TYPE_SOURCE_SINK)
#define BIO_TYPE_START 128
@ -172,6 +174,30 @@ extern "C" {
# define BIO_CTRL_SET_INDENT 80
# define BIO_CTRL_GET_INDENT 81
# define BIO_CTRL_DGRAM_GET_LOCAL_ADDR_CAP 82
# define BIO_CTRL_DGRAM_GET_LOCAL_ADDR_ENABLE 83
# define BIO_CTRL_DGRAM_SET_LOCAL_ADDR_ENABLE 84
# define BIO_CTRL_DGRAM_GET_EFFECTIVE_CAPS 85
# define BIO_CTRL_DGRAM_GET_CAPS 86
# define BIO_CTRL_DGRAM_SET_CAPS 87
# define BIO_CTRL_DGRAM_GET_NO_TRUNC 88
# define BIO_CTRL_DGRAM_SET_NO_TRUNC 89
/*
* internal BIO:
* # define BIO_CTRL_SET_KTLS_TX_ZEROCOPY_SENDFILE 90
*/
# define BIO_CTRL_GET_RPOLL_DESCRIPTOR 91
# define BIO_CTRL_GET_WPOLL_DESCRIPTOR 92
# define BIO_CTRL_DGRAM_DETECT_PEER_ADDR 93
# define BIO_DGRAM_CAP_NONE 0U
# define BIO_DGRAM_CAP_HANDLES_SRC_ADDR (1U << 0)
# define BIO_DGRAM_CAP_HANDLES_DST_ADDR (1U << 1)
# define BIO_DGRAM_CAP_PROVIDES_SRC_ADDR (1U << 2)
# define BIO_DGRAM_CAP_PROVIDES_DST_ADDR (1U << 3)
# ifndef OPENSSL_NO_KTLS
# define BIO_get_ktls_send(b) \
(BIO_ctrl(b, BIO_CTRL_GET_KTLS_SEND, 0, NULL) > 0)
@ -209,7 +235,7 @@ extern "C" {
# define BIO_FLAGS_NONCLEAR_RST 0x400
# define BIO_FLAGS_IN_EOF 0x800
/* the BIO FLAGS values 0x1000 to 0x4000 are reserved for internal KTLS flags */
/* the BIO FLAGS values 0x1000 to 0x8000 are reserved for internal KTLS flags */
typedef union bio_addr_st BIO_ADDR;
typedef struct bio_addrinfo_st BIO_ADDRINFO;
@ -263,6 +289,8 @@ void BIO_clear_flags(BIO *b, int flags);
# define BIO_CB_PUTS 0x04
# define BIO_CB_GETS 0x05
# define BIO_CB_CTRL 0x06
# define BIO_CB_RECVMMSG 0x07
# define BIO_CB_SENDMMSG 0x08
/*
* The callback is called before and after the underling operation, The
@ -339,6 +367,34 @@ struct bio_dgram_sctp_prinfo {
};
# endif
/* BIO_sendmmsg/BIO_recvmmsg-related definitions */
typedef struct bio_msg_st {
void *data;
size_t data_len;
BIO_ADDR *peer, *local;
uint64_t flags;
} BIO_MSG;
typedef struct bio_mmsg_cb_args_st {
BIO_MSG *msg;
size_t stride, num_msg;
uint64_t flags;
size_t *msgs_processed;
} BIO_MMSG_CB_ARGS;
#define BIO_POLL_DESCRIPTOR_TYPE_NONE 0
#define BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD 1
#define BIO_POLL_DESCRIPTOR_CUSTOM_START 8192
typedef struct bio_poll_descriptor_st {
uint32_t type;
union {
int fd;
void *custom;
uintptr_t custom_ui;
} value;
} BIO_POLL_DESCRIPTOR;
/*
* #define BIO_CONN_get_param_hostname BIO_ctrl
*/
@ -405,10 +461,17 @@ struct bio_dgram_sctp_prinfo {
# define BIO_C_SET_CONNECT_MODE 155
# define BIO_C_SET_TFO 156 /* like BIO_C_SET_NBIO */
# define BIO_C_SET_SOCK_TYPE 157
# define BIO_C_GET_SOCK_TYPE 158
# define BIO_C_GET_DGRAM_BIO 159
# define BIO_set_app_data(s,arg) BIO_set_ex_data(s,0,arg)
# define BIO_get_app_data(s) BIO_get_ex_data(s,0)
# define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL)
# define BIO_set_tfo(b,n) BIO_ctrl(b,BIO_C_SET_TFO,(n),NULL)
# ifndef OPENSSL_NO_SOCK
/* IP families we support, for BIO_s_connect() and BIO_s_accept() */
@ -429,7 +492,11 @@ struct bio_dgram_sctp_prinfo {
# define BIO_get_conn_port(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,1))
# define BIO_get_conn_address(b) ((const BIO_ADDR *)BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,2))
# define BIO_get_conn_ip_family(b) BIO_ctrl(b,BIO_C_GET_CONNECT,3,NULL)
# define BIO_get_conn_mode(b) BIO_ctrl(b,BIO_C_GET_CONNECT,4,NULL)
# define BIO_set_conn_mode(b,n) BIO_ctrl(b,BIO_C_SET_CONNECT_MODE,(n),NULL)
# define BIO_set_sock_type(b,t) BIO_ctrl(b,BIO_C_SET_SOCK_TYPE,(t),NULL)
# define BIO_get_sock_type(b) BIO_ctrl(b,BIO_C_GET_SOCK_TYPE,0,NULL)
# define BIO_get0_dgram_bio(b, p) BIO_ctrl(b,BIO_C_GET_DGRAM_BIO,0,(void *)(BIO **)(p))
/* BIO_s_accept() */
# define BIO_set_accept_name(b,name) BIO_ctrl(b,BIO_C_SET_ACCEPT,0, \
@ -446,6 +513,7 @@ struct bio_dgram_sctp_prinfo {
(char *)(bio))
# define BIO_set_accept_ip_family(b,f) BIO_int_ctrl(b,BIO_C_SET_ACCEPT,4,f)
# define BIO_get_accept_ip_family(b) BIO_ctrl(b,BIO_C_GET_ACCEPT,4,NULL)
# define BIO_set_tfo_accept(b,n) BIO_ctrl(b,BIO_C_SET_ACCEPT,5,(n)?(void *)"a":NULL)
/* Aliases kept for backward compatibility */
# define BIO_BIND_NORMAL 0
@ -573,8 +641,30 @@ int BIO_ctrl_reset_read_request(BIO *b);
(int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_PEER, 0, (char *)(peer))
# define BIO_dgram_set_peer(b,peer) \
(int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, (char *)(peer))
# define BIO_dgram_detect_peer_addr(b,peer) \
(int)BIO_ctrl(b, BIO_CTRL_DGRAM_DETECT_PEER_ADDR, 0, (char *)(peer))
# define BIO_dgram_get_mtu_overhead(b) \
(unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_MTU_OVERHEAD, 0, NULL)
# define BIO_dgram_get_local_addr_cap(b) \
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_LOCAL_ADDR_CAP, 0, NULL)
# define BIO_dgram_get_local_addr_enable(b, penable) \
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_LOCAL_ADDR_ENABLE, 0, (char *)(penable))
# define BIO_dgram_set_local_addr_enable(b, enable) \
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_SET_LOCAL_ADDR_ENABLE, (enable), NULL)
# define BIO_dgram_get_effective_caps(b) \
(uint32_t)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_EFFECTIVE_CAPS, 0, NULL)
# define BIO_dgram_get_caps(b) \
(uint32_t)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_CAPS, 0, NULL)
# define BIO_dgram_set_caps(b, caps) \
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_SET_CAPS, (long)(caps), NULL)
# define BIO_dgram_get_no_trunc(b) \
(unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_NO_TRUNC, 0, NULL)
# define BIO_dgram_set_no_trunc(b, enable) \
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_SET_NO_TRUNC, (enable), NULL)
# define BIO_dgram_get_mtu(b) \
(unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_MTU, 0, NULL)
# define BIO_dgram_set_mtu(b, mtu) \
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_SET_MTU, (mtu), NULL)
/* ctrl macros for BIO_f_prefix */
# define BIO_set_prefix(b,p) BIO_ctrl((b), BIO_CTRL_SET_PREFIX, 0, (void *)(p))
@ -617,10 +707,18 @@ void BIO_vfree(BIO *a);
int BIO_up_ref(BIO *a);
int BIO_read(BIO *b, void *data, int dlen);
int BIO_read_ex(BIO *b, void *data, size_t dlen, size_t *readbytes);
__owur int BIO_recvmmsg(BIO *b, BIO_MSG *msg,
size_t stride, size_t num_msg, uint64_t flags,
size_t *msgs_processed);
int BIO_gets(BIO *bp, char *buf, int size);
int BIO_get_line(BIO *bio, char *buf, int size);
int BIO_write(BIO *b, const void *data, int dlen);
int BIO_write_ex(BIO *b, const void *data, size_t dlen, size_t *written);
__owur int BIO_sendmmsg(BIO *b, BIO_MSG *msg,
size_t stride, size_t num_msg, uint64_t flags,
size_t *msgs_processed);
__owur int BIO_get_rpoll_descriptor(BIO *b, BIO_POLL_DESCRIPTOR *desc);
__owur int BIO_get_wpoll_descriptor(BIO *b, BIO_POLL_DESCRIPTOR *desc);
int BIO_puts(BIO *bp, const char *buf);
int BIO_indent(BIO *b, int indent, int max);
long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg);
@ -644,6 +742,9 @@ int BIO_nwrite0(BIO *bio, char **buf);
int BIO_nwrite(BIO *bio, char **buf, int num);
const BIO_METHOD *BIO_s_mem(void);
# ifndef OPENSSL_NO_DGRAM
const BIO_METHOD *BIO_s_dgram_mem(void);
# endif
const BIO_METHOD *BIO_s_secmem(void);
BIO *BIO_new_mem_buf(const void *buf, int len);
# ifndef OPENSSL_NO_SOCK
@ -663,6 +764,7 @@ const BIO_METHOD *BIO_f_nbio_test(void);
const BIO_METHOD *BIO_f_prefix(void);
const BIO_METHOD *BIO_s_core(void);
# ifndef OPENSSL_NO_DGRAM
const BIO_METHOD *BIO_s_dgram_pair(void);
const BIO_METHOD *BIO_s_datagram(void);
int BIO_dgram_non_fatal_error(int error);
BIO *BIO_new_dgram(int fd, int close_flag);
@ -681,6 +783,7 @@ int BIO_dgram_sctp_msg_waiting(BIO *b);
# ifndef OPENSSL_NO_SOCK
int BIO_sock_should_retry(int i);
int BIO_sock_non_fatal_error(int error);
int BIO_err_is_non_fatal(unsigned int errcode);
int BIO_socket_wait(int fd, int for_read, time_t max_time);
# endif
int BIO_wait(BIO *bio, time_t max_time, unsigned int nap_milliseconds);
@ -703,6 +806,8 @@ int BIO_hex_string(BIO *out, int indent, int width, const void *data,
# ifndef OPENSSL_NO_SOCK
BIO_ADDR *BIO_ADDR_new(void);
int BIO_ADDR_copy(BIO_ADDR *dst, const BIO_ADDR *src);
BIO_ADDR *BIO_ADDR_dup(const BIO_ADDR *ap);
int BIO_ADDR_rawmake(BIO_ADDR *ap, int family,
const void *where, size_t wherelen, unsigned short port);
void BIO_ADDR_free(BIO_ADDR *);
@ -765,6 +870,7 @@ int BIO_sock_info(int sock,
# define BIO_SOCK_KEEPALIVE 0x04
# define BIO_SOCK_NONBLOCK 0x08
# define BIO_SOCK_NODELAY 0x10
# define BIO_SOCK_TFO 0x20
int BIO_socket(int domain, int socktype, int protocol, int options);
int BIO_connect(int sock, const BIO_ADDR *addr, int options);
@ -782,6 +888,11 @@ BIO *BIO_new_fd(int fd, int close_flag);
int BIO_new_bio_pair(BIO **bio1, size_t writebuf1,
BIO **bio2, size_t writebuf2);
# ifndef OPENSSL_NO_DGRAM
int BIO_new_bio_dgram_pair(BIO **bio1, size_t writebuf1,
BIO **bio2, size_t writebuf2);
# endif
/*
* If successful, returns 1 and in *bio1, *bio2 two BIO pair endpoints.
* Otherwise returns 0 and sets *bio1 and *bio2 to NULL. Size 0 uses default
@ -833,18 +944,30 @@ int BIO_meth_set_write(BIO_METHOD *biom,
int (*write) (BIO *, const char *, int));
int BIO_meth_set_write_ex(BIO_METHOD *biom,
int (*bwrite) (BIO *, const char *, size_t, size_t *));
int BIO_meth_set_sendmmsg(BIO_METHOD *biom,
int (*f) (BIO *, BIO_MSG *, size_t, size_t,
uint64_t, size_t *));
int (*BIO_meth_get_sendmmsg(const BIO_METHOD *biom))(BIO *, BIO_MSG *,
size_t, size_t,
uint64_t, size_t *);
int (*BIO_meth_get_read(const BIO_METHOD *biom)) (BIO *, char *, int);
int (*BIO_meth_get_read_ex(const BIO_METHOD *biom)) (BIO *, char *, size_t, size_t *);
int BIO_meth_set_read(BIO_METHOD *biom,
int (*read) (BIO *, char *, int));
int BIO_meth_set_read_ex(BIO_METHOD *biom,
int (*bread) (BIO *, char *, size_t, size_t *));
int BIO_meth_set_recvmmsg(BIO_METHOD *biom,
int (*f) (BIO *, BIO_MSG *, size_t, size_t,
uint64_t, size_t *));
int (*BIO_meth_get_recvmmsg(const BIO_METHOD *biom))(BIO *, BIO_MSG *,
size_t, size_t,
uint64_t, size_t *);
int (*BIO_meth_get_puts(const BIO_METHOD *biom)) (BIO *, const char *);
int BIO_meth_set_puts(BIO_METHOD *biom,
int (*puts) (BIO *, const char *));
int (*BIO_meth_get_gets(const BIO_METHOD *biom)) (BIO *, char *, int);
int BIO_meth_set_gets(BIO_METHOD *biom,
int (*gets) (BIO *, char *, int));
int (*ossl_gets) (BIO *, char *, int));
long (*BIO_meth_get_ctrl(const BIO_METHOD *biom)) (BIO *, int, long, void *);
int BIO_meth_set_ctrl(BIO_METHOD *biom,
long (*ctrl) (BIO *, int, long, void *));

View File

@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -37,14 +37,18 @@
# define BIO_R_IN_USE 123
# define BIO_R_LENGTH_TOO_LONG 102
# define BIO_R_LISTEN_V6_ONLY 136
# define BIO_R_LOCAL_ADDR_NOT_AVAILABLE 111
# define BIO_R_LOOKUP_RETURNED_NOTHING 142
# define BIO_R_MALFORMED_HOST_OR_SERVICE 130
# define BIO_R_NBIO_CONNECT_ERROR 110
# define BIO_R_NON_FATAL 112
# define BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED 143
# define BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED 144
# define BIO_R_NO_PORT_DEFINED 113
# define BIO_R_NO_SUCH_FILE 128
# define BIO_R_NULL_PARAMETER 115 /* unused */
# define BIO_R_TFO_DISABLED 106
# define BIO_R_TFO_NO_KERNEL_SUPPORT 108
# define BIO_R_TRANSFER_ERROR 104
# define BIO_R_TRANSFER_TIMEOUT 105
# define BIO_R_UNABLE_TO_BIND_SOCKET 117
@ -53,6 +57,7 @@
# define BIO_R_UNABLE_TO_LISTEN_SOCKET 119
# define BIO_R_UNABLE_TO_NODELAY 138
# define BIO_R_UNABLE_TO_REUSEADDR 139
# define BIO_R_UNABLE_TO_TFO 109
# define BIO_R_UNAVAILABLE_IP_FAMILY 145
# define BIO_R_UNINITIALIZED 120
# define BIO_R_UNKNOWN_INFO_TYPE 140
@ -61,5 +66,7 @@
# define BIO_R_UNSUPPORTED_PROTOCOL_FAMILY 131
# define BIO_R_WRITE_TO_READ_ONLY_BIO 126
# define BIO_R_WSASTARTUP 122
# define BIO_R_PORT_MISMATCH 150
# define BIO_R_PEER_ADDR_NOT_AVAILABLE 151
#endif

Some files were not shown because too many files have changed in this diff Show More