diff --git a/cpp2rust/converter/converter_lib.cpp b/cpp2rust/converter/converter_lib.cpp index 227a7d2a..475001ba 100644 --- a/cpp2rust/converter/converter_lib.cpp +++ b/cpp2rust/converter/converter_lib.cpp @@ -753,6 +753,17 @@ bool IsBuiltinVaStart(const clang::CallExpr *expr) { return false; } +std::string GetNameOfScalarTypedef(clang::QualType qual_type) { + qual_type = qual_type.getNonReferenceType(); + const auto *typedef_type = + llvm::dyn_cast(qual_type.getTypePtr()); + if (!typedef_type || !qual_type.getCanonicalType()->isBuiltinType()) { + return {}; + } + std::string name = typedef_type->getDecl()->getNameAsString(); + return qual_type.isConstQualified() ? "const " + name : name; +} + bool IsBuiltinVaEnd(const clang::CallExpr *expr) { if (auto *fn = expr->getDirectCallee()) { return fn->getBuiltinID() == clang::Builtin::BI__builtin_va_end; diff --git a/cpp2rust/converter/converter_lib.h b/cpp2rust/converter/converter_lib.h index e606a2e3..c619632c 100644 --- a/cpp2rust/converter/converter_lib.h +++ b/cpp2rust/converter/converter_lib.h @@ -159,6 +159,8 @@ std::string GetClassName(clang::QualType type); bool IsVaListType(clang::QualType type); +std::string GetNameOfScalarTypedef(clang::QualType qual_type); + bool IsBuiltinVaStart(const clang::CallExpr *expr); bool IsBuiltinVaEnd(const clang::CallExpr *expr); diff --git a/cpp2rust/converter/mapper.cpp b/cpp2rust/converter/mapper.cpp index 3b1f7bc9..b6a17bd4 100644 --- a/cpp2rust/converter/mapper.cpp +++ b/cpp2rust/converter/mapper.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -400,12 +401,22 @@ TranslationRule::ExprRule *search(const clang::Expr *expr) { return rule; } -TranslationRule::TypeRule *search(clang::QualType qual_type) { +std::pair>> +search(clang::QualType qual_type) { + if (auto name = GetNameOfScalarTypedef(qual_type); !name.empty()) { + auto res = search(types_, name, GetTypeMapKey(name)); + if (res.first) { + log() << "search type " << name + << ", result: " << res.first->type_info.type << '\n'; + return res; + } + } auto type = ToString(qual_type); - auto [rule, subs] = search(types_, type, GetTypeMapKey(type)); + auto res = search(types_, type, GetTypeMapKey(type)); log() << "search type " << type - << ", result: " << (rule ? rule->type_info.type : "None") << '\n'; - return rule; + << ", result: " << (res.first ? res.first->type_info.type : "None") + << '\n'; + return res; } void addRulesFromDirectory(const std::filesystem::path &dir, Model model) { @@ -424,7 +435,18 @@ void addRulesFromDirectory(const std::filesystem::path &dir, Model model) { exprs_.emplace(GetExprMapKey(rule.src), std::move(rule)); } for (auto &[_, rule] : type_rules) { - types_.emplace(GetTypeMapKey(rule.src), std::move(rule)); + auto key = GetTypeMapKey(rule.src); + auto [begin, end] = types_.equal_range(key); + for (auto it = begin; it != end; ++it) { + if (it->second.src == rule.src) { + llvm::errs() << "ERROR: duplicate type rule for C++ type '" + << rule.src << "': maps to both '" + << it->second.type_info.type << "' and '" + << rule.type_info.type << "'\n"; + std::exit(EXIT_FAILURE); + } + } + types_.emplace(std::move(key), std::move(rule)); } } } @@ -579,7 +601,7 @@ PushASTContext::PushASTContext(clang::ASTContext &ctx) : prev_(ctx_) { PushASTContext::~PushASTContext() { ctx_ = prev_; } bool Contains(clang::QualType qual_type) { - return search(qual_type) != nullptr; + return search(qual_type).first != nullptr; } bool Contains(const clang::Expr *expr) { return search(expr) != nullptr; } @@ -614,8 +636,7 @@ std::string InstantiateTemplate(const clang::Expr *expr, unsigned n) { } std::string Map(clang::QualType qual_type) { - auto type_str = ToString(qual_type); - auto [rule, subs] = search(types_, type_str, GetTypeMapKey(type_str)); + auto [rule, subs] = search(qual_type); if (rule) { for (auto &ty : subs) { if (ty) { @@ -628,8 +649,7 @@ std::string Map(clang::QualType qual_type) { } std::string MapInitializer(clang::QualType qual_type) { - auto type_str = ToString(qual_type); - auto [rule, subs] = search(types_, type_str, GetTypeMapKey(type_str)); + auto [rule, subs] = search(qual_type); if (rule && !rule->initializer.empty()) { for (auto &ty : subs) { if (ty) { @@ -642,12 +662,12 @@ std::string MapInitializer(clang::QualType qual_type) { } bool MapsToPointer(clang::QualType qual_type) { - auto rule = search(qual_type); + auto rule = search(qual_type).first; return rule && rule->type_info.is_pointer(); } bool MapsToRefcountPointer(clang::QualType qual_type) { - auto rule = search(qual_type); + auto rule = search(qual_type).first; return rule && rule->type_info.is_refcount_pointer; } @@ -921,8 +941,8 @@ void LoadTranslationRules(Model model, clang::ASTContext &ctx, } translation_rules_loaded_ = true; - addRulesFromDirectory(rules_dir, model); addBuiltinTypes(model); + addRulesFromDirectory(rules_dir, model); #if 0 for (auto &[src, rule] : exprs_) { diff --git a/cpp2rust/cpp_rule_preprocessor.cpp b/cpp2rust/cpp_rule_preprocessor.cpp index e7d1ae2f..8e2c3444 100644 --- a/cpp2rust/cpp_rule_preprocessor.cpp +++ b/cpp2rust/cpp_rule_preprocessor.cpp @@ -26,6 +26,7 @@ #include #include "compat/platform_flags.h" +#include "converter/converter_lib.h" #include "converter/mapper.h" namespace fs = std::filesystem; @@ -113,7 +114,11 @@ class Callback : public clang::ast_matchers::MatchFinder::MatchCallback { } else { type = var->getUnderlyingType(); } - out_.try_emplace(var->getQualifiedNameAsString(), Mapper::ToString(type)); + auto src = GetNameOfScalarTypedef(type); + if (src.empty()) { + src = Mapper::ToString(type); + } + out_.try_emplace(var->getQualifiedNameAsString(), std::move(src)); return; } diff --git a/rule-preprocessor/src/semantic.rs b/rule-preprocessor/src/semantic.rs index 6dbef216..5f2dabb4 100644 --- a/rule-preprocessor/src/semantic.rs +++ b/rule-preprocessor/src/semantic.rs @@ -46,7 +46,7 @@ fn build_rustc_args(crate_root: &Path) -> Vec { args.push("-L".to_string()); args.push(format!("dependency={}", deps.display())); - for dep in &["libcc2rs", "libc", "brotli_sys"] { + for dep in &["libcc2rs", "libc", "brotli_sys", "rustls_ffi"] { if let Some(rlib) = find_rlib(deps.as_path(), dep) { args.push("--extern".to_string()); args.push(format!("{}={}", dep, rlib.display())); diff --git a/rules/Cargo.toml b/rules/Cargo.toml index 6c8855d0..c36f8bf0 100644 --- a/rules/Cargo.toml +++ b/rules/Cargo.toml @@ -12,3 +12,4 @@ path = "src/lib.rs" libc = "0.2.148" libcc2rs = { version = "0.1.0", path = "../libcc2rs" } brotli-sys = "0.3" +rustls-ffi = { version = "0.15.3", default-features = false } diff --git a/rules/cstdlib/src.cpp b/rules/cstdlib/src.cpp index b800f02f..cc8f4433 100644 --- a/rules/cstdlib/src.cpp +++ b/rules/cstdlib/src.cpp @@ -28,3 +28,7 @@ void f9(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) { return qsort(base, nmemb, size, compar); } + +char *f10(const char *path, char *resolved_path) { + return realpath(path, resolved_path); +} diff --git a/rules/cstdlib/tgt_unsafe.rs b/rules/cstdlib/tgt_unsafe.rs index aedeb411..36017306 100644 --- a/rules/cstdlib/tgt_unsafe.rs +++ b/rules/cstdlib/tgt_unsafe.rs @@ -64,3 +64,7 @@ unsafe fn f9( >(a3 as *const ())), ) } + +unsafe fn f10(a0: *const u8, a1: *mut u8) -> *mut u8 { + libc::realpath(a0 as *const i8, a1 as *mut i8) as *mut u8 +} diff --git a/rules/rustls/rustls.h b/rules/rustls/rustls.h new file mode 100644 index 00000000..3c91f15d --- /dev/null +++ b/rules/rustls/rustls.h @@ -0,0 +1,2869 @@ +#ifndef RUSTLS_H +#define RUSTLS_H + +#include +#include +#include +#include +#include + +#define RUSTLS_VERSION_MAJOR 0 +#define RUSTLS_VERSION_MINOR 15 +#define RUSTLS_VERSION_PATCH 3 + +/** + * This gives each version part 8 bits, and leaves the 8 least significant bits + * empty for future additions, for example pre-release versions. + */ +#define RUSTLS_VERSION_NUMBER ((RUSTLS_VERSION_MAJOR << 24) \ + |(RUSTLS_VERSION_MINOR << 16) \ + |(RUSTLS_VERSION_MINOR << 8)) + +#if defined(__clang__) || defined(__GNUC__) +# define DEPRECATED_FUNC(why) __attribute__((deprecated(why))) +#elif defined(_MSC_VER) +# define DEPRECATED_FUNC(why) __declspec(deprecated(why)) +#else +# define DEPRECATED_FUNC(why) +#endif + + +/** + * Describes which sort of handshake happened. + */ +typedef enum rustls_handshake_kind { + /** + * The type of handshake could not be determined. + * + * This variant should not be used. + */ + RUSTLS_HANDSHAKE_KIND_UNKNOWN = 0, + /** + * A full TLS handshake. + * + * This is the typical TLS connection initiation process when resumption is + * not yet unavailable, and the initial client hello was accepted by the server. + */ + RUSTLS_HANDSHAKE_KIND_FULL = 1, + /** + * A full TLS handshake, with an extra round-trip for a hello retry request. + * + * The server can respond with a hello retry request (HRR) if the initial client + * hello is unacceptable for several reasons, the most likely if no supported key + * shares were offered by the client. + */ + RUSTLS_HANDSHAKE_KIND_FULL_WITH_HELLO_RETRY_REQUEST = 2, + /** + * A resumed TLS handshake. + * + * Resumed handshakes involve fewer round trips and less cryptography than + * full ones, but can only happen when the peers have previously done a full + * handshake together, and then remember data about it. + */ + RUSTLS_HANDSHAKE_KIND_RESUMED = 3, +} rustls_handshake_kind; + +/** + * Numeric error codes returned from rustls-ffi API functions. + */ +enum rustls_result_t { + RUSTLS_RESULT_OK = 7000, + RUSTLS_RESULT_IO = 7001, + RUSTLS_RESULT_NULL_PARAMETER = 7002, + RUSTLS_RESULT_INVALID_DNS_NAME_ERROR = 7003, + RUSTLS_RESULT_PANIC = 7004, + RUSTLS_RESULT_CERTIFICATE_PARSE_ERROR = 7005, + RUSTLS_RESULT_PRIVATE_KEY_PARSE_ERROR = 7006, + RUSTLS_RESULT_INSUFFICIENT_SIZE = 7007, + RUSTLS_RESULT_NOT_FOUND = 7008, + RUSTLS_RESULT_INVALID_PARAMETER = 7009, + RUSTLS_RESULT_UNEXPECTED_EOF = 7010, + RUSTLS_RESULT_PLAINTEXT_EMPTY = 7011, + RUSTLS_RESULT_ACCEPTOR_NOT_READY = 7012, + RUSTLS_RESULT_ALREADY_USED = 7013, + RUSTLS_RESULT_CERTIFICATE_REVOCATION_LIST_PARSE_ERROR = 7014, + RUSTLS_RESULT_NO_SERVER_CERT_VERIFIER = 7015, + RUSTLS_RESULT_NO_DEFAULT_CRYPTO_PROVIDER = 7016, + RUSTLS_RESULT_GET_RANDOM_FAILED = 7017, + RUSTLS_RESULT_NO_CERT_RESOLVER = 7018, + RUSTLS_RESULT_HPKE_ERROR = 7019, + RUSTLS_RESULT_BUILDER_INCOMPATIBLE_TLS_VERSIONS = 7020, + RUSTLS_RESULT_NO_CERTIFICATES_PRESENTED = 7101, + RUSTLS_RESULT_DECRYPT_ERROR = 7102, + RUSTLS_RESULT_FAILED_TO_GET_CURRENT_TIME = 7103, + RUSTLS_RESULT_FAILED_TO_GET_RANDOM_BYTES = 7113, + RUSTLS_RESULT_HANDSHAKE_NOT_COMPLETE = 7104, + RUSTLS_RESULT_PEER_SENT_OVERSIZED_RECORD = 7105, + RUSTLS_RESULT_NO_APPLICATION_PROTOCOL = 7106, + RUSTLS_RESULT_BAD_MAX_FRAGMENT_SIZE = 7114, + RUSTLS_RESULT_UNSUPPORTED_NAME_TYPE = 7115, + RUSTLS_RESULT_ENCRYPT_ERROR = 7116, + RUSTLS_RESULT_CERT_ENCODING_BAD = 7121, + RUSTLS_RESULT_CERT_EXPIRED = 7122, + RUSTLS_RESULT_CERT_NOT_YET_VALID = 7123, + RUSTLS_RESULT_CERT_REVOKED = 7124, + RUSTLS_RESULT_CERT_UNHANDLED_CRITICAL_EXTENSION = 7125, + RUSTLS_RESULT_CERT_UNKNOWN_ISSUER = 7126, + RUSTLS_RESULT_CERT_BAD_SIGNATURE = 7127, + RUSTLS_RESULT_CERT_NOT_VALID_FOR_NAME = 7128, + RUSTLS_RESULT_CERT_INVALID_PURPOSE = 7129, + RUSTLS_RESULT_CERT_APPLICATION_VERIFICATION_FAILURE = 7130, + RUSTLS_RESULT_CERT_OTHER_ERROR = 7131, + RUSTLS_RESULT_CERT_UNKNOWN_REVOCATION_STATUS = 7154, + RUSTLS_RESULT_CERT_EXPIRED_REVOCATION_LIST = 7156, + RUSTLS_RESULT_CERT_UNSUPPORTED_SIGNATURE_ALGORITHM = 7157, + RUSTLS_RESULT_MESSAGE_HANDSHAKE_PAYLOAD_TOO_LARGE = 7133, + RUSTLS_RESULT_MESSAGE_INVALID_CCS = 7134, + RUSTLS_RESULT_MESSAGE_INVALID_CONTENT_TYPE = 7135, + RUSTLS_RESULT_MESSAGE_INVALID_CERT_STATUS_TYPE = 7136, + RUSTLS_RESULT_MESSAGE_INVALID_CERT_REQUEST = 7137, + RUSTLS_RESULT_MESSAGE_INVALID_DH_PARAMS = 7138, + RUSTLS_RESULT_MESSAGE_INVALID_EMPTY_PAYLOAD = 7139, + RUSTLS_RESULT_MESSAGE_INVALID_KEY_UPDATE = 7140, + RUSTLS_RESULT_MESSAGE_INVALID_SERVER_NAME = 7141, + RUSTLS_RESULT_MESSAGE_TOO_LARGE = 7142, + RUSTLS_RESULT_MESSAGE_TOO_SHORT = 7143, + RUSTLS_RESULT_MESSAGE_MISSING_DATA = 7144, + RUSTLS_RESULT_MESSAGE_MISSING_KEY_EXCHANGE = 7145, + RUSTLS_RESULT_MESSAGE_NO_SIGNATURE_SCHEMES = 7146, + RUSTLS_RESULT_MESSAGE_TRAILING_DATA = 7147, + RUSTLS_RESULT_MESSAGE_UNEXPECTED_MESSAGE = 7148, + RUSTLS_RESULT_MESSAGE_UNKNOWN_PROTOCOL_VERSION = 7149, + RUSTLS_RESULT_MESSAGE_UNSUPPORTED_COMPRESSION = 7150, + RUSTLS_RESULT_MESSAGE_UNSUPPORTED_CURVE_TYPE = 7151, + RUSTLS_RESULT_MESSAGE_UNSUPPORTED_KEY_EXCHANGE_ALGORITHM = 7152, + RUSTLS_RESULT_MESSAGE_INVALID_OTHER = 7153, + RUSTLS_RESULT_MESSAGE_CERTIFICATE_PAYLOAD_TOO_LARGE = 7155, + RUSTLS_RESULT_PEER_INCOMPATIBLE_ERROR = 7107, + RUSTLS_RESULT_PEER_MISBEHAVED_ERROR = 7108, + RUSTLS_RESULT_INAPPROPRIATE_MESSAGE = 7109, + RUSTLS_RESULT_INAPPROPRIATE_HANDSHAKE_MESSAGE = 7110, + RUSTLS_RESULT_GENERAL = 7112, + RUSTLS_RESULT_ALERT_CLOSE_NOTIFY = 7200, + RUSTLS_RESULT_ALERT_UNEXPECTED_MESSAGE = 7201, + RUSTLS_RESULT_ALERT_BAD_RECORD_MAC = 7202, + RUSTLS_RESULT_ALERT_DECRYPTION_FAILED = 7203, + RUSTLS_RESULT_ALERT_RECORD_OVERFLOW = 7204, + RUSTLS_RESULT_ALERT_DECOMPRESSION_FAILURE = 7205, + RUSTLS_RESULT_ALERT_HANDSHAKE_FAILURE = 7206, + RUSTLS_RESULT_ALERT_NO_CERTIFICATE = 7207, + RUSTLS_RESULT_ALERT_BAD_CERTIFICATE = 7208, + RUSTLS_RESULT_ALERT_UNSUPPORTED_CERTIFICATE = 7209, + RUSTLS_RESULT_ALERT_CERTIFICATE_REVOKED = 7210, + RUSTLS_RESULT_ALERT_CERTIFICATE_EXPIRED = 7211, + RUSTLS_RESULT_ALERT_CERTIFICATE_UNKNOWN = 7212, + RUSTLS_RESULT_ALERT_ILLEGAL_PARAMETER = 7213, + RUSTLS_RESULT_ALERT_UNKNOWN_CA = 7214, + RUSTLS_RESULT_ALERT_ACCESS_DENIED = 7215, + RUSTLS_RESULT_ALERT_DECODE_ERROR = 7216, + RUSTLS_RESULT_ALERT_DECRYPT_ERROR = 7217, + RUSTLS_RESULT_ALERT_EXPORT_RESTRICTION = 7218, + RUSTLS_RESULT_ALERT_PROTOCOL_VERSION = 7219, + RUSTLS_RESULT_ALERT_INSUFFICIENT_SECURITY = 7220, + RUSTLS_RESULT_ALERT_INTERNAL_ERROR = 7221, + RUSTLS_RESULT_ALERT_INAPPROPRIATE_FALLBACK = 7222, + RUSTLS_RESULT_ALERT_USER_CANCELED = 7223, + RUSTLS_RESULT_ALERT_NO_RENEGOTIATION = 7224, + RUSTLS_RESULT_ALERT_MISSING_EXTENSION = 7225, + RUSTLS_RESULT_ALERT_UNSUPPORTED_EXTENSION = 7226, + RUSTLS_RESULT_ALERT_CERTIFICATE_UNOBTAINABLE = 7227, + RUSTLS_RESULT_ALERT_UNRECOGNISED_NAME = 7228, + RUSTLS_RESULT_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE = 7229, + RUSTLS_RESULT_ALERT_BAD_CERTIFICATE_HASH_VALUE = 7230, + RUSTLS_RESULT_ALERT_UNKNOWN_PSK_IDENTITY = 7231, + RUSTLS_RESULT_ALERT_CERTIFICATE_REQUIRED = 7232, + RUSTLS_RESULT_ALERT_NO_APPLICATION_PROTOCOL = 7233, + RUSTLS_RESULT_ALERT_UNKNOWN = 7234, + RUSTLS_RESULT_CERT_REVOCATION_LIST_BAD_SIGNATURE = 7400, + RUSTLS_RESULT_CERT_REVOCATION_LIST_INVALID_CRL_NUMBER = 7401, + RUSTLS_RESULT_CERT_REVOCATION_LIST_INVALID_REVOKED_CERT_SERIAL_NUMBER = 7402, + RUSTLS_RESULT_CERT_REVOCATION_LIST_ISSUER_INVALID_FOR_CRL = 7403, + RUSTLS_RESULT_CERT_REVOCATION_LIST_OTHER_ERROR = 7404, + RUSTLS_RESULT_CERT_REVOCATION_LIST_PARSE_ERROR = 7405, + RUSTLS_RESULT_CERT_REVOCATION_LIST_UNSUPPORTED_CRL_VERSION = 7406, + RUSTLS_RESULT_CERT_REVOCATION_LIST_UNSUPPORTED_CRITICAL_EXTENSION = 7407, + RUSTLS_RESULT_CERT_REVOCATION_LIST_UNSUPPORTED_DELTA_CRL = 7408, + RUSTLS_RESULT_CERT_REVOCATION_LIST_UNSUPPORTED_INDIRECT_CRL = 7409, + RUSTLS_RESULT_CERT_REVOCATION_LIST_UNSUPPORTED_REVOCATION_REASON = 7410, + RUSTLS_RESULT_CERT_REVOCATION_LIST_UNSUPPORTED_SIGNATURE_ALGORITHM = 7411, + RUSTLS_RESULT_CLIENT_CERT_VERIFIER_BUILDER_NO_ROOT_ANCHORS = 7500, + RUSTLS_RESULT_INCONSISTENT_KEYS_KEYS_MISMATCH = 7600, + RUSTLS_RESULT_INCONSISTENT_KEYS_UNKNOWN = 7601, + RUSTLS_RESULT_INVALID_ENCRYPTED_CLIENT_HELLO_INVALID_CONFIG_LIST = 7700, + RUSTLS_RESULT_INVALID_ENCRYPTED_CLIENT_HELLO_NO_COMPATIBLE_CONFIG = 7701, + RUSTLS_RESULT_INVALID_ENCRYPTED_CLIENT_HELLO_SNI_REQUIRED = 7702, +}; +typedef uint32_t rustls_result; + +/** + * Definitions of known TLS protocol versions. + */ +typedef enum rustls_tls_version { + RUSTLS_TLS_VERSION_UNKNOWN = 0, + RUSTLS_TLS_VERSION_SSLV2 = 512, + RUSTLS_TLS_VERSION_SSLV3 = 768, + RUSTLS_TLS_VERSION_TLSV1_0 = 769, + RUSTLS_TLS_VERSION_TLSV1_1 = 770, + RUSTLS_TLS_VERSION_TLSV1_2 = 771, + RUSTLS_TLS_VERSION_TLSV1_3 = 772, +} rustls_tls_version; + +/** + * A parsed ClientHello produced by a rustls_acceptor. + * + * It is used to check server name indication (SNI), ALPN protocols, + * signature schemes, and cipher suites. It can be combined with a + * `rustls_server_config` to build a `rustls_connection`. + */ +typedef struct rustls_accepted rustls_accepted; + +/** + * Represents a TLS alert resulting from accepting a client. + */ +typedef struct rustls_accepted_alert rustls_accepted_alert; + +/** + * A buffer and parser for ClientHello bytes. + * + * This allows reading ClientHello before choosing a rustls_server_config. + * + * It's useful when the server config will be based on parameters in the + * ClientHello: server name indication (SNI), ALPN protocols, signature + * schemes, and cipher suites. + * + * In particular, if a server wants to do some potentially expensive work + * to load a certificate for a given hostname, rustls_acceptor allows doing + * that asynchronously, as opposed to rustls_server_config_builder_set_hello_callback(), + * which doesn't work well for asynchronous I/O. + * + * The general flow is: + * - rustls_acceptor_new() + * - Loop: + * - Read bytes from the network it with rustls_acceptor_read_tls(). + * - If successful, parse those bytes with rustls_acceptor_accept(). + * - If that returns RUSTLS_RESULT_ACCEPTOR_NOT_READY, continue. + * - Otherwise, break. + * - If rustls_acceptor_accept() returned RUSTLS_RESULT_OK: + * - Examine the resulting rustls_accepted. + * - Create or select a rustls_server_config. + * - Call rustls_accepted_into_connection(). + * - Otherwise, there was a problem with the ClientHello data and the + * connection should be rejected. + */ +typedef struct rustls_acceptor rustls_acceptor; + +/** + * An X.509 certificate, as used in rustls. + * Corresponds to `CertificateDer` in the Rust pki-types API. + * + */ +typedef struct rustls_certificate rustls_certificate; + +/** + * The complete chain of certificates to send during a TLS handshake, + * plus a private key that matches the end-entity (leaf) certificate. + * + * Corresponds to `CertifiedKey` in the Rust API. + * + */ +typedef struct rustls_certified_key rustls_certified_key; + +/** + * A built client certificate verifier that can be provided to a `rustls_server_config_builder` + * with `rustls_server_config_builder_set_client_verifier`. + */ +typedef struct rustls_client_cert_verifier rustls_client_cert_verifier; + +/** + * A client config that is done being constructed and is now read-only. + * + * Under the hood, this object corresponds to an `Arc`. + * + */ +typedef struct rustls_client_config rustls_client_config; + +/** + * A client config being constructed. + * + * A builder can be modified by, e.g. `rustls_client_config_builder_load_roots_from_file`. + * Once you're done configuring settings, call `rustls_client_config_builder_build` + * to turn it into a *rustls_client_config. + * + * Alternatively, if an error occurs or, you don't wish to build a config, + * call `rustls_client_config_builder_free` to free the builder directly. + * + * This object is not safe for concurrent mutation. Under the hood, + * it corresponds to a `Box`. + * + */ +typedef struct rustls_client_config_builder rustls_client_config_builder; + +/** + * A C representation of a Rustls `Connection`. + */ +typedef struct rustls_connection rustls_connection; + +/** + * A C representation of a Rustls [`CryptoProvider`]. + */ +typedef struct rustls_crypto_provider rustls_crypto_provider; + +/** + * A `rustls_crypto_provider` builder. + */ +typedef struct rustls_crypto_provider_builder rustls_crypto_provider_builder; + +/** + * A collection of supported Hybrid Public Key Encryption (HPKE) suites. + * + * `rustls_hpke` can be provided to `rustls_client_config_builder_enable_ech` and + * `rustls_client_config_builder_enable_ech_grease()` to customize a + * `rustls_client_config_builder` to use Encrypted Client Hello (ECH). + */ +typedef struct rustls_hpke rustls_hpke; + +/** + * An alias for `struct iovec` from uio.h (on Unix) or `WSABUF` on Windows. + * + * You should cast `const struct rustls_iovec *` to `const struct iovec *` on + * Unix, or `const *LPWSABUF` on Windows. See [`std::io::IoSlice`] for details + * on interoperability with platform specific vectored IO. + */ +typedef struct rustls_iovec rustls_iovec; + +/** + * A root certificate store. + * + */ +typedef struct rustls_root_cert_store rustls_root_cert_store; + +/** + * A `rustls_root_cert_store` being constructed. + * + * A builder can be modified by adding trust anchor root certificates with + * `rustls_root_cert_store_builder_add_pem`. Once you're done adding root certificates, + * call `rustls_root_cert_store_builder_build` to turn it into a `rustls_root_cert_store`. + * This object is not safe for concurrent mutation. + */ +typedef struct rustls_root_cert_store_builder rustls_root_cert_store_builder; + +/** + * A built server certificate verifier that can be provided to a `rustls_client_config_builder` + * with `rustls_client_config_builder_set_server_verifier`. + */ +typedef struct rustls_server_cert_verifier rustls_server_cert_verifier; + +/** + * A server config that is done being constructed and is now read-only. + * + * Under the hood, this object corresponds to an `Arc`. + * + */ +typedef struct rustls_server_config rustls_server_config; + +/** + * A server config being constructed. + * + * A builder can be modified by, + * e.g. rustls_server_config_builder_load_native_roots. Once you're + * done configuring settings, call rustls_server_config_builder_build + * to turn it into a *const rustls_server_config. + * + * Alternatively, if an error occurs or, you don't wish to build a config, + * call `rustls_server_config_builder_free` to free the builder directly. + * + * This object is not safe for concurrent mutation. + * + */ +typedef struct rustls_server_config_builder rustls_server_config_builder; + +/** + * A signing key that can be used to construct a certified key. + */ +typedef struct rustls_signing_key rustls_signing_key; + +/** + * A read-only view of a slice of Rust byte slices. + * + * This is used to pass data from rustls-ffi to callback functions provided + * by the user of the API. Because Vec and slice are not `#[repr(C)]`, we + * provide access via a pointer to an opaque struct and an accessor method + * that acts on that struct to get entries of type `rustls_slice_bytes`. + * Internally, the pointee is a `&[&[u8]]`. + * + * The memory exposed is available as specified by the function + * using this in its signature. For instance, when this is a parameter to a + * callback, the lifetime will usually be the duration of the callback. + * Functions that receive one of these must not call its methods beyond the + * allowed lifetime. + */ +typedef struct rustls_slice_slice_bytes rustls_slice_slice_bytes; + +/** + * A read-only view of a slice of multiple Rust `&str`'s (that is, multiple + * strings). + * + * Like `rustls_str`, this guarantees that each string contains + * UTF-8 and no NUL bytes. Strings are not NUL-terminated. + * + * This is used to pass data from rustls-ffi to callback functions provided + * by the user of the API. Because Vec and slice are not `#[repr(C)]`, we + * can't provide a straightforward `data` and `len` structure. Instead, we + * provide access via a pointer to an opaque struct and accessor methods. + * Internally, the pointee is a `&[&str]`. + * + * The memory exposed is available as specified by the function + * using this in its signature. For instance, when this is a parameter to a + * callback, the lifetime will usually be the duration of the callback. + * Functions that receive one of these must not call its methods beyond the + * allowed lifetime. + */ +typedef struct rustls_slice_str rustls_slice_str; + +/** + * A cipher suite supported by rustls. + */ +typedef struct rustls_supported_ciphersuite rustls_supported_ciphersuite; + +/** + * A client certificate verifier being constructed. + * + * A builder can be modified by, e.g. `rustls_web_pki_client_cert_verifier_builder_add_crl`. + * + * Once you're done configuring settings, call `rustls_web_pki_client_cert_verifier_builder_build` + * to turn it into a `rustls_client_cert_verifier`. + * + * This object is not safe for concurrent mutation. + * + * See + * for more information. + */ +typedef struct rustls_web_pki_client_cert_verifier_builder rustls_web_pki_client_cert_verifier_builder; + +/** + * A server certificate verifier being constructed. + * + * A builder can be modified by, e.g. `rustls_web_pki_server_cert_verifier_builder_add_crl`. + * + * Once you're done configuring settings, call `rustls_web_pki_server_cert_verifier_builder_build` + * to turn it into a `rustls_server_cert_verifier`. This object is not safe for concurrent mutation. + * + * See + * for more information. + */ +typedef struct rustls_web_pki_server_cert_verifier_builder rustls_web_pki_server_cert_verifier_builder; + +/** + * A return value for a function that may return either success (0) or a + * non-zero value representing an error. + * + * The values should match socket error numbers for your operating system -- + * for example, the integers for `ETIMEDOUT`, `EAGAIN`, or similar. + */ +typedef int rustls_io_result; + +/** + * A callback for `rustls_connection_read_tls`. + * + * An implementation of this callback should attempt to read up to n bytes from the + * network, storing them in `buf`. If any bytes were stored, the implementation should + * set out_n to the number of bytes stored and return 0. + * + * If there was an error, the implementation should return a nonzero rustls_io_result, + * which will be passed through to the caller. + * + * On POSIX systems, returning `errno` is convenient. + * + * On other systems, any appropriate error code works. + * + * It's best to make one read attempt to the network per call. Additional reads will + * be triggered by subsequent calls to one of the `_read_tls` methods. + * + * `userdata` is set to the value provided to `rustls_connection_set_userdata`. + * In most cases that should be a struct that contains, at a minimum, a file descriptor. + * + * The buf and out_n pointers are borrowed and should not be retained across calls. + */ +typedef rustls_io_result (*rustls_read_callback)(void *userdata, + uint8_t *buf, + size_t n, + size_t *out_n); + +/** + * A read-only view on a Rust `&str`. + * + * The contents are guaranteed to be valid UTF-8. + * + * As an additional guarantee on top of Rust's normal UTF-8 guarantee, + * a `rustls_str` is guaranteed not to contain internal NUL bytes, so it is + * safe to interpolate into a C string or compare using strncmp. Keep in mind + * that it is not NUL-terminated. + * + * The memory exposed is available as specified by the function + * using this in its signature. For instance, when this is a parameter to a + * callback, the lifetime will usually be the duration of the callback. + * Functions that receive one of these must not dereference the data pointer + * beyond the allowed lifetime. + */ +typedef struct rustls_str { + const char *data; + size_t len; +} rustls_str; + +/** + * A read-only view on a Rust byte slice. + * + * This is used to pass data from rustls-ffi to callback functions provided + * by the user of the API. + * `len` indicates the number of bytes than can be safely read. + * + * The memory exposed is available as specified by the function + * using this in its signature. For instance, when this is a parameter to a + * callback, the lifetime will usually be the duration of the callback. + * Functions that receive one of these must not dereference the data pointer + * beyond the allowed lifetime. + */ +typedef struct rustls_slice_bytes { + const uint8_t *data; + size_t len; +} rustls_slice_bytes; + +/** + * A callback for `rustls_connection_write_tls` or `rustls_accepted_alert_write_tls`. + * + * An implementation of this callback should attempt to write the `n` bytes in buf + * to the network. + * + * If any bytes were written, the implementation should set `out_n` to the number of + * bytes stored and return 0. + * + * If there was an error, the implementation should return a nonzero `rustls_io_result`, + * which will be passed through to the caller. + * + * On POSIX systems, returning `errno` is convenient. + * + * On other systems, any appropriate error code works. + * + * It's best to make one write attempt to the network per call. Additional writes will + * be triggered by subsequent calls to rustls_connection_write_tls. + * + * `userdata` is set to the value provided to `rustls_connection_set_userdata`. In most + * cases that should be a struct that contains, at a minimum, a file descriptor. + * + * The buf and out_n pointers are borrowed and should not be retained across calls. + */ +typedef rustls_io_result (*rustls_write_callback)(void *userdata, + const uint8_t *buf, + size_t n, + size_t *out_n); + +/** + * User-provided input to a custom certificate verifier callback. + * + * See `rustls_client_config_builder_dangerous_set_certificate_verifier()`. + */ +typedef void *rustls_verify_server_cert_user_data; + +/** + * Input to a custom certificate verifier callback. + * + * See `rustls_client_config_builder_dangerous_set_certificate_verifier()`. + * + * server_name can contain a hostname, an IPv4 address in textual form, or an + * IPv6 address in textual form. + */ +typedef struct rustls_verify_server_cert_params { + struct rustls_slice_bytes end_entity_cert_der; + const struct rustls_slice_slice_bytes *intermediate_certs_der; + struct rustls_str server_name; + struct rustls_slice_bytes ocsp_response; +} rustls_verify_server_cert_params; + +/** + * A callback that is invoked to verify a server certificate. + */ +typedef uint32_t (*rustls_verify_server_cert_callback)(rustls_verify_server_cert_user_data userdata, + const struct rustls_verify_server_cert_params *params); + +/** + * An optional callback for logging key material. + * + * See the documentation on `rustls_client_config_builder_set_key_log` and + * `rustls_server_config_builder_set_key_log` for more information about the + * lifetimes of the parameters. + */ +typedef void (*rustls_keylog_log_callback)(struct rustls_str label, + const uint8_t *client_random, + size_t client_random_len, + const uint8_t *secret, + size_t secret_len); + +/** + * An optional callback for deciding if key material will be logged. + * + * See the documentation on `rustls_client_config_builder_set_key_log` and + * `rustls_server_config_builder_set_key_log` for more information about the + * lifetimes of the parameters. + */ +typedef int (*rustls_keylog_will_log_callback)(struct rustls_str label); + +/** + * Numeric representation of a log level. + * + * Passed as a field of the `rustls_log_params` passed to a log callback. + * Use with `rustls_log_level_str` to convert to a string label. + */ +typedef size_t rustls_log_level; + +/** + * Parameter structure passed to a `rustls_log_callback`. + */ +typedef struct rustls_log_params { + /** + * The log level the message was logged at. + */ + rustls_log_level level; + /** + * The message that was logged. + */ + struct rustls_str message; +} rustls_log_params; + +/** + * A callback that is invoked for messages logged by rustls. + */ +typedef void (*rustls_log_callback)(void *userdata, const struct rustls_log_params *params); + +/** + * A callback for `rustls_connection_write_tls_vectored`. + * + * An implementation of this callback should attempt to write the bytes in + * the given `count` iovecs to the network. + * + * If any bytes were written, the implementation should set out_n to the number of + * bytes written and return 0. + * + * If there was an error, the implementation should return a nonzero rustls_io_result, + * which will be passed through to the caller. + * + * On POSIX systems, returning `errno` is convenient. + * + * On other systems, any appropriate error code works. + * + * It's best to make one write attempt to the network per call. Additional write will + * be triggered by subsequent calls to one of the `_write_tls` methods. + * + * `userdata` is set to the value provided to `rustls_*_session_set_userdata`. In most + * cases that should be a struct that contains, at a minimum, a file descriptor. + * + * The iov and out_n pointers are borrowed and should not be retained across calls. + */ +typedef rustls_io_result (*rustls_write_vectored_callback)(void *userdata, + const struct rustls_iovec *iov, + size_t count, + size_t *out_n); + +/** + * Any context information the callback will receive when invoked. + */ +typedef void *rustls_client_hello_userdata; + +/** + * A read-only view on a Rust slice of 16-bit integers in platform endianness. + * + * This is used to pass data from rustls-ffi to callback functions provided + * by the user of the API. + * `len` indicates the number of bytes than can be safely read. + * + * The memory exposed is available as specified by the function + * using this in its signature. For instance, when this is a parameter to a + * callback, the lifetime will usually be the duration of the callback. + * Functions that receive one of these must not dereference the data pointer + * beyond the allowed lifetime. + */ +typedef struct rustls_slice_u16 { + const uint16_t *data; + size_t len; +} rustls_slice_u16; + +/** + * The TLS Client Hello information provided to a ClientHelloCallback function. + * + * `server_name` is the value of the ServerNameIndication extension provided + * by the client. If the client did not send an SNI, the length of this + * `rustls_string` will be 0. + * + * `signature_schemes` carries the values supplied by the client or, if the + * client did not send this TLS extension, the default schemes in the rustls library. See: + * . + * + * `named_groups` carries the values of the `named_groups` extension sent by the + * client. If the client did not send a `named_groups` extension, the length of + * this `rustls_slice_u16` will be 0. The meaning of this extension differ + * based on TLS version. See the Rustls documentation for more information: + * + * + * `alpn` carries the list of ALPN protocol names that the client proposed to + * the server. Again, the length of this list will be 0 if none were supplied. + * + * All this data, when passed to a callback function, is only accessible during + * the call and may not be modified. Users of this API must copy any values that + * they want to access when the callback returned. + * + * EXPERIMENTAL: this feature of rustls-ffi is likely to change in the future, as + * the rustls library is re-evaluating their current approach to client hello handling. + */ +typedef struct rustls_client_hello { + struct rustls_str server_name; + struct rustls_slice_u16 signature_schemes; + struct rustls_slice_u16 named_groups; + const struct rustls_slice_slice_bytes *alpn; +} rustls_client_hello; + +/** + * Prototype of a callback that can be installed by the application at the + * `rustls_server_config`. + * + * This callback will be invoked by a `rustls_connection` once the TLS client + * hello message has been received. + * + * `userdata` will be set based on rustls_connection_set_userdata. + * + * `hello` gives the value of the available client announcements, as interpreted + * by rustls. See the definition of `rustls_client_hello` for details. + * + * NOTE: + * - the passed in `hello` and all its values are only available during the + * callback invocations. + * - the passed callback function must be safe to call multiple times concurrently + * with the same userdata, unless there is only a single config and connection + * where it is installed. + * + * EXPERIMENTAL: this feature of rustls-ffi is likely to change in the future, as + * the rustls library is re-evaluating their current approach to client hello handling. + */ +typedef const struct rustls_certified_key *(*rustls_client_hello_callback)(rustls_client_hello_userdata userdata, + const struct rustls_client_hello *hello); + +/** + * Any context information the callback will receive when invoked. + */ +typedef void *rustls_session_store_userdata; + +/** + * Prototype of a callback that can be installed by the application at the + * `rustls_server_config` or `rustls_client_config`. + * + * This callback will be invoked by a TLS session when looking up the data + * for a TLS session id. + * + * `userdata` will be supplied based on rustls_{client,server}_session_set_userdata. + * + * The `buf` points to `count` consecutive bytes where the + * callback is expected to copy the result to. The number of copied bytes + * needs to be written to `out_n`. The callback should not read any + * data from `buf`. + * + * If the value to copy is larger than `count`, the callback should never + * do a partial copy but instead remove the value from its store and + * act as if it was never found. + * + * The callback should return RUSTLS_RESULT_OK to indicate that a value was + * retrieved and written in its entirety into `buf`, or RUSTLS_RESULT_NOT_FOUND + * if no session was retrieved. + * + * When `remove_after` is != 0, the returned data needs to be removed + * from the store. + * + * NOTE: the passed in `key` and `buf` are only available during the + * callback invocation. + * NOTE: callbacks used in several sessions via a common config + * must be implemented thread-safe. + */ +typedef uint32_t (*rustls_session_store_get_callback)(rustls_session_store_userdata userdata, + const struct rustls_slice_bytes *key, + int remove_after, + uint8_t *buf, + size_t count, + size_t *out_n); + +/** + * Prototype of a callback that can be installed by the application at the + * `rustls_server_config` or `rustls_client_config`. + * + * This callback will be invoked by a TLS session when a TLS session + * been created and an id for later use is handed to the client/has + * been received from the server. + * + * `userdata` will be supplied based on rustls_{client,server}_session_set_userdata. + * + * The callback should return RUSTLS_RESULT_OK to indicate that a value was + * successfully stored, or RUSTLS_RESULT_IO on failure. + * + * NOTE: the passed in `key` and `val` are only available during the + * callback invocation. + * NOTE: callbacks used in several sessions via a common config + * must be implemented thread-safe. + */ +typedef uint32_t (*rustls_session_store_put_callback)(rustls_session_store_userdata userdata, + const struct rustls_slice_bytes *key, + const struct rustls_slice_bytes *val); + +/** + * Rustls' list of supported protocol versions. The length of the array is + * given by `RUSTLS_ALL_VERSIONS_LEN`. + */ +extern const uint16_t RUSTLS_ALL_VERSIONS[2]; + +/** + * The length of the array `RUSTLS_ALL_VERSIONS`. + */ +extern const size_t RUSTLS_ALL_VERSIONS_LEN; + +/** + * Rustls' default list of protocol versions. The length of the array is + * given by `RUSTLS_DEFAULT_VERSIONS_LEN`. + */ +extern const uint16_t RUSTLS_DEFAULT_VERSIONS[2]; + +/** + * The length of the array `RUSTLS_DEFAULT_VERSIONS`. + */ +extern const size_t RUSTLS_DEFAULT_VERSIONS_LEN; + +/** + * Create and return a new rustls_acceptor. + * + * Caller owns the pointed-to memory and must eventually free it with + * `rustls_acceptor_free()`. + */ +struct rustls_acceptor *rustls_acceptor_new(void); + +/** + * Free a rustls_acceptor. + * + * Parameters: + * + * acceptor: The rustls_acceptor to free. + * + * Calling with NULL is fine. Must not be called twice with the same value. + */ +void rustls_acceptor_free(struct rustls_acceptor *acceptor); + +/** + * Read some TLS bytes from the network into internal buffers. + * + * The actual network I/O is performed by `callback`, which you provide. + * Rustls will invoke your callback with a suitable buffer to store the + * read bytes into. You don't have to fill it up, just fill with as many + * bytes as you get in one syscall. + * + * Parameters: + * + * acceptor: The rustls_acceptor to read bytes into. + * callback: A function that will perform the actual network I/O. + * Must be valid to call with the given userdata parameter until + * this function call returns. + * userdata: An opaque parameter to be passed directly to `callback`. + * Note: this is distinct from the `userdata` parameter set with + * `rustls_connection_set_userdata`. + * out_n: An output parameter. This will be passed through to `callback`, + * which should use it to store the number of bytes written. + * + * Returns: + * + * - 0: Success. You should call `rustls_acceptor_accept()` next. + * - Any non-zero value: error. + * + * This function passes through return values from `callback`. Typically + * `callback` should return an errno value. See `rustls_read_callback()` for + * more details. + */ +rustls_io_result rustls_acceptor_read_tls(struct rustls_acceptor *acceptor, + rustls_read_callback callback, + void *userdata, + size_t *out_n); + +/** + * Parse all TLS bytes read so far. + * + * If those bytes make up a ClientHello, create a rustls_accepted from them. + * + * Parameters: + * + * acceptor: The rustls_acceptor to access. + * out_accepted: An output parameter. The pointed-to pointer will be set + * to a new rustls_accepted only when the function returns + * RUSTLS_RESULT_OK. The memory is owned by the caller and must eventually + * be freed + * out_alert: An output parameter. The pointed-to pointer will be set + * to a new rustls_accepted_alert only when the function returns + * a non-OK result. The memory is owned by the caller and must eventually + * be freed with rustls_accepted_alert_free. The caller should call + * rustls_accepted_alert_write_tls to write the alert bytes to the TLS + * connection before freeing the rustls_accepted_alert. + * + * At most one of out_accepted or out_alert will be set. + * + * Returns: + * + * - RUSTLS_RESULT_OK: a ClientHello has successfully been parsed. + * A pointer to a newly allocated rustls_accepted has been written to + * *out_accepted. + * - RUSTLS_RESULT_ACCEPTOR_NOT_READY: a full ClientHello has not yet been read. + * Read more TLS bytes to continue. + * - Any other rustls_result: the TLS bytes read so far cannot be parsed + * as a ClientHello, and reading additional bytes won't help. + * + * Memory and lifetimes: + * + * After this method returns RUSTLS_RESULT_OK, `acceptor` is + * still allocated and valid. It needs to be freed regardless of success + * or failure of this function. + * + * Calling `rustls_acceptor_accept()` multiple times on the same + * `rustls_acceptor` is acceptable from a memory perspective but pointless + * from a protocol perspective. + */ +rustls_result rustls_acceptor_accept(struct rustls_acceptor *acceptor, + struct rustls_accepted **out_accepted, + struct rustls_accepted_alert **out_alert); + +/** + * Get the server name indication (SNI) from the ClientHello. + * + * Parameters: + * + * accepted: The rustls_accepted to access. + * + * Returns: + * + * A rustls_str containing the SNI field. + * + * The returned value is valid until rustls_accepted_into_connection or + * rustls_accepted_free is called on the same `accepted`. It is not owned + * by the caller and does not need to be freed. + * + * This will be a zero-length rustls_str in these error cases: + * + * - The SNI contains a NUL byte. + * - The `accepted` parameter was NULL. + * - The `accepted` parameter was already transformed into a connection + * with rustls_accepted_into_connection. + */ +struct rustls_str rustls_accepted_server_name(const struct rustls_accepted *accepted); + +/** + * Get the i'th in the list of signature schemes offered in the ClientHello. + * + * This is useful in selecting a server certificate when there are multiple + * available for the same server name, for instance when selecting + * between an RSA and an ECDSA certificate. + * + * Parameters: + * + * accepted: The rustls_accepted to access. + * i: Fetch the signature scheme at this offset. + * + * Returns: + * + * A TLS Signature Scheme from + * + * This will be 0 in these cases: + * - i is greater than the number of available cipher suites. + * - accepted is NULL. + * - rustls_accepted_into_connection has already been called with `accepted`. + */ +uint16_t rustls_accepted_signature_scheme(const struct rustls_accepted *accepted, + size_t i); + +/** + * Get the i'th in the list of cipher suites offered in the ClientHello. + * + * Parameters: + * + * accepted: The rustls_accepted to access. + * i: Fetch the cipher suite at this offset. + * + * Returns: + * + * A cipher suite value from + * + * This will be 0 in these cases: + * - i is greater than the number of available cipher suites. + * - accepted is NULL. + * - rustls_accepted_into_connection has already been called with `accepted`. + * + * Note that 0 is technically a valid cipher suite "TLS_NULL_WITH_NULL_NULL", + * but this library will never support null ciphers. + */ +uint16_t rustls_accepted_cipher_suite(const struct rustls_accepted *accepted, + size_t i); + +/** + * Get the i'th in the list of ALPN protocols requested in the ClientHello. + * + * accepted: The rustls_accepted to access. + * i: Fetch the ALPN value at this offset. + * + * Returns: + * + * A rustls_slice_bytes containing the i'th ALPN protocol. This may + * contain internal NUL bytes and is not guaranteed to contain valid + * UTF-8. + * + * This will be a zero-length rustls_slice bytes in these cases: + * - i is greater than the number of offered ALPN protocols. + * - The client did not offer the ALPN extension. + * - The `accepted` parameter was already transformed into a connection + * with rustls_accepted_into_connection. + * + * The returned value is valid until rustls_accepted_into_connection or + * rustls_accepted_free is called on the same `accepted`. It is not owned + * by the caller and does not need to be freed. + * + * If you are calling this from Rust, note that the `'static` lifetime + * in the return signature is fake and must not be relied upon. + */ +struct rustls_slice_bytes rustls_accepted_alpn(const struct rustls_accepted *accepted, size_t i); + +/** + * Turn a rustls_accepted into a rustls_connection, given the provided + * rustls_server_config. + * + * Parameters: + * + * accepted: The rustls_accepted to transform. + * config: The configuration with which to create this connection. + * out_conn: An output parameter. The pointed-to pointer will be set + * to a new rustls_connection only when the function returns + * RUSTLS_RESULT_OK. + * out_alert: An output parameter. The pointed-to pointer will be set + * to a new rustls_accepted_alert when, and only when, the function returns + * a non-OK result. The memory is owned by the caller and must eventually + * be freed with rustls_accepted_alert_free. The caller should call + * rustls_accepted_alert_write_tls to write the alert bytes to + * the TLS connection before freeing the rustls_accepted_alert. + * + * At most one of out_conn or out_alert will be set. + * + * Returns: + * + * - RUSTLS_RESULT_OK: The `accepted` parameter was successfully + * transformed into a rustls_connection, and *out_conn was written to. + * - RUSTLS_RESULT_ALREADY_USED: This function was called twice on the + * same rustls_connection. + * - RUSTLS_RESULT_NULL_PARAMETER: One of the input parameters was NULL. + * + * Memory and lifetimes: + * + * In both success and failure cases, this consumes the contents of + * `accepted` but does not free its allocated memory. In either case, + * call rustls_accepted_free to avoid a memory leak. + * + * Calling accessor methods on an `accepted` after consuming it will + * return zero or default values. + * + * The rustls_connection emitted by this function in the success case + * is owned by the caller and must eventually be freed. + * + * This function does not take ownership of `config`. It does increment + * `config`'s internal reference count, indicating that the + * rustls_connection may hold a reference to it until it is done. + * See the documentation for rustls_connection for details. + */ +rustls_result rustls_accepted_into_connection(struct rustls_accepted *accepted, + const struct rustls_server_config *config, + struct rustls_connection **out_conn, + struct rustls_accepted_alert **out_alert); + +/** + * Free a rustls_accepted. + * + * Parameters: + * + * accepted: The rustls_accepted to free. + * + * Calling with NULL is fine. Must not be called twice with the same value. + */ +void rustls_accepted_free(struct rustls_accepted *accepted); + +/** + * Write some TLS bytes (an alert) to the network. + * + * The actual network I/O is performed by `callback`, which you provide. + * Rustls will invoke your callback with a suitable buffer containing TLS + * bytes to send. You don't have to write them all, just as many as you can + * in one syscall. + * + * The `userdata` parameter is passed through directly to `callback`. Note that + * this is distinct from the `userdata` parameter set with + * `rustls_connection_set_userdata`. + * + * Returns 0 for success, or an errno value on error. Passes through return values + * from callback. See [`rustls_write_callback`] or [`AcceptedAlert`] for + * more details. + */ +rustls_io_result rustls_accepted_alert_write_tls(struct rustls_accepted_alert *accepted_alert, + rustls_write_callback callback, + void *userdata, + size_t *out_n); + +/** + * Free a rustls_accepted_alert. + * + * Parameters: + * + * accepted_alert: The rustls_accepted_alert to free. + * + * Calling with NULL is fine. Must not be called twice with the same value. + */ +void rustls_accepted_alert_free(struct rustls_accepted_alert *accepted_alert); + +/** + * Get the DER data of the certificate itself. + * The data is owned by the certificate and has the same lifetime. + */ +rustls_result rustls_certificate_get_der(const struct rustls_certificate *cert, + const uint8_t **out_der_data, + size_t *out_der_len); + +/** + * Build a `rustls_certified_key` from a certificate chain and a private key + * and the default process-wide crypto provider. + * + * `cert_chain` must point to a buffer of `cert_chain_len` bytes, containing + * a series of PEM-encoded certificates, with the end-entity (leaf) + * certificate first. + * + * `private_key` must point to a buffer of `private_key_len` bytes, containing + * a PEM-encoded private key in either PKCS#1, PKCS#8 or SEC#1 format when + * using `aws-lc-rs` as the crypto provider. Supported formats may vary by + * provider. + * + * On success, this writes a pointer to the newly created + * `rustls_certified_key` in `certified_key_out`. That pointer must later + * be freed with `rustls_certified_key_free` to avoid memory leaks. Note that + * internally, this is an atomically reference-counted pointer, so even after + * the original caller has called `rustls_certified_key_free`, other objects + * may retain a pointer to the object. The memory will be freed when all + * references are gone. + * + * This function does not take ownership of any of its input pointers. It + * parses the pointed-to data and makes a copy of the result. You may + * free the cert_chain and private_key pointers after calling it. + * + * Typically, you will build a `rustls_certified_key`, use it to create a + * `rustls_server_config` (which increments the reference count), and then + * immediately call `rustls_certified_key_free`. That leaves the + * `rustls_server_config` in possession of the sole reference, so the + * `rustls_certified_key`'s memory will automatically be released when + * the `rustls_server_config` is freed. + */ +rustls_result rustls_certified_key_build(const uint8_t *cert_chain, + size_t cert_chain_len, + const uint8_t *private_key, + size_t private_key_len, + const struct rustls_certified_key **certified_key_out); + +/** + * Build a `rustls_certified_key` from a certificate chain and a + * `rustls_signing_key`. + * + * `cert_chain` must point to a buffer of `cert_chain_len` bytes, containing + * a series of PEM-encoded certificates, with the end-entity (leaf) + * certificate first. + * + * `signing_key` must point to a `rustls_signing_key` loaded using a + * `rustls_crypto_provider` and `rustls_crypto_provider_load_key()`. + * + * On success, this writes a pointer to the newly created + * `rustls_certified_key` in `certified_key_out`. That pointer must later + * be freed with `rustls_certified_key_free` to avoid memory leaks. Note that + * internally, this is an atomically reference-counted pointer, so even after + * the original caller has called `rustls_certified_key_free`, other objects + * may retain a pointer to the object. The memory will be freed when all + * references are gone. + * + * This function does not take ownership of any of its input pointers. It + * parses the pointed-to data and makes a copy of the result. You may + * free the cert_chain and private_key pointers after calling it. + * + * Typically, you will build a `rustls_certified_key`, use it to create a + * `rustls_server_config` (which increments the reference count), and then + * immediately call `rustls_certified_key_free`. That leaves the + * `rustls_server_config` in possession of the sole reference, so the + * `rustls_certified_key`'s memory will automatically be released when + * the `rustls_server_config` is freed. + */ +rustls_result rustls_certified_key_build_with_signing_key(const uint8_t *cert_chain, + size_t cert_chain_len, + struct rustls_signing_key *signing_key, + const struct rustls_certified_key **certified_key_out); + +/** + * Return the i-th rustls_certificate in the rustls_certified_key. + * + * 0 gives the end-entity certificate. 1 and higher give certificates from the chain. + * + * Indexes higher than the last available certificate return NULL. + * + * The returned certificate is valid until the rustls_certified_key is freed. + */ +const struct rustls_certificate *rustls_certified_key_get_certificate(const struct rustls_certified_key *certified_key, + size_t i); + +/** + * Create a copy of the rustls_certified_key with the given OCSP response data + * as DER encoded bytes. + * + * The OCSP response may be given as NULL to clear any possibly present OCSP + * data from the cloned key. + * + * The cloned key is independent from its original and needs to be freed + * by the application. + */ +rustls_result rustls_certified_key_clone_with_ocsp(const struct rustls_certified_key *certified_key, + const struct rustls_slice_bytes *ocsp_response, + const struct rustls_certified_key **cloned_key_out); + +/** + * Verify the consistency of this `rustls_certified_key`'s public and private keys. + * + * This is done by performing a comparison of subject public key information (SPKI) bytes + * between the certificate and private key. + * + * If the private key matches the certificate this function returns `RUSTLS_RESULT_OK`, + * otherwise an error `rustls_result` is returned. + */ +rustls_result rustls_certified_key_keys_match(const struct rustls_certified_key *key); + +/** + * "Free" a certified_key previously returned from `rustls_certified_key_build`. + * + * Since certified_key is actually an atomically reference-counted pointer, + * extant certified_key may still hold an internal reference to the Rust object. + * + * However, C code must consider this pointer unusable after "free"ing it. + * + * Calling with NULL is fine. Must not be called twice with the same value. + */ +void rustls_certified_key_free(const struct rustls_certified_key *key); + +/** + * Create a `rustls_root_cert_store_builder`. + * + * Caller owns the memory and may free it with `rustls_root_cert_store_free`, regardless of + * whether `rustls_root_cert_store_builder_build` was called. + * + * If you wish to abandon the builder without calling `rustls_root_cert_store_builder_build`, + * it must be freed with `rustls_root_cert_store_builder_free`. + */ +struct rustls_root_cert_store_builder *rustls_root_cert_store_builder_new(void); + +/** + * Add one or more certificates to the root cert store builder using PEM + * encoded data. + * + * When `strict` is true an error will return a `CertificateParseError` + * result. So will an attempt to parse data that has zero certificates. + * + * When `strict` is false, unparseable root certificates will be ignored. + * This may be useful on systems that have syntactically invalid root + * certificates. + */ +rustls_result rustls_root_cert_store_builder_add_pem(struct rustls_root_cert_store_builder *builder, + const uint8_t *pem, + size_t pem_len, + bool strict); + +/** + * Add one or more certificates to the root cert store builder using PEM + * encoded data read from the named file. + * + * When `strict` is true an error will return a `CertificateParseError` + * result. So will an attempt to parse data that has zero certificates. + * + * When `strict` is false, unparseable root certificates will be ignored. + * This may be useful on systems that have syntactically invalid root + * certificates. + */ +rustls_result rustls_root_cert_store_builder_load_roots_from_file(struct rustls_root_cert_store_builder *builder, + const char *filename, + bool strict); + +/** + * Create a new `rustls_root_cert_store` from the builder. + * + * The builder is consumed and cannot be used again, but must still be freed. + * + * The root cert store can be used in several `rustls_web_pki_client_cert_verifier_builder_new` + * instances and must be freed by the application when no longer needed. See the documentation of + * `rustls_root_cert_store_free` for details about lifetime. + */ +rustls_result rustls_root_cert_store_builder_build(struct rustls_root_cert_store_builder *builder, + const struct rustls_root_cert_store **root_cert_store_out); + +/** + * Free a `rustls_root_cert_store_builder` previously returned from + * `rustls_root_cert_store_builder_new`. + * + * Calling with NULL is fine. Must not be called twice with the same value. + */ +void rustls_root_cert_store_builder_free(struct rustls_root_cert_store_builder *builder); + +/** + * Free a rustls_root_cert_store previously returned from rustls_root_cert_store_builder_build. + * + * Calling with NULL is fine. Must not be called twice with the same value. + */ +void rustls_root_cert_store_free(const struct rustls_root_cert_store *store); + +/** + * Return a 16-bit unsigned integer corresponding to this cipher suite's assignment from + * . + * + * The bytes from the assignment are interpreted in network order. + */ +uint16_t rustls_supported_ciphersuite_get_suite(const struct rustls_supported_ciphersuite *supported_ciphersuite); + +/** + * Returns the name of the ciphersuite as a `rustls_str`. + * + * If the provided ciphersuite is invalid, the `rustls_str` will contain the + * empty string. The lifetime of the `rustls_str` is the lifetime of the program, + * it does not need to be freed. + */ +struct rustls_str rustls_supported_ciphersuite_get_name(const struct rustls_supported_ciphersuite *supported_ciphersuite); + +/** + * Returns the `rustls_tls_version` of the ciphersuite. + * + * See also `RUSTLS_ALL_VERSIONS`. + */ +enum rustls_tls_version rustls_supported_ciphersuite_protocol_version(const struct rustls_supported_ciphersuite *supported_ciphersuite); + +/** + * Create a rustls_client_config_builder using the process default crypto provider. + * + * Caller owns the memory and must eventually call `rustls_client_config_builder_build`, + * then free the resulting `rustls_client_config`. + * + * Alternatively, if an error occurs or, you don't wish to build a config, + * call `rustls_client_config_builder_free` to free the builder directly. + * + * This uses the process default provider's values for the cipher suites and key + * exchange groups, as well as safe defaults for protocol versions. + * + * This starts out with no trusted roots. Caller must add roots with + * rustls_client_config_builder_load_roots_from_file or provide a custom verifier. + */ +struct rustls_client_config_builder *rustls_client_config_builder_new(void); + +/** + * Create a rustls_client_config_builder using the specified crypto provider. + * + * Caller owns the memory and must eventually call `rustls_client_config_builder_build`, + * then free the resulting `rustls_client_config`. + * + * Alternatively, if an error occurs or, you don't wish to build a config, + * call `rustls_client_config_builder_free` to free the builder directly. + * + * `tls_version` sets the TLS protocol versions to use when negotiating a TLS session. + * `tls_version` is the version of the protocol, as defined in rfc8446, + * ch. 4.2.1 and end of ch. 5.1. Some values are defined in + * `rustls_tls_version` for convenience, and the arrays + * RUSTLS_DEFAULT_VERSIONS or RUSTLS_ALL_VERSIONS can be used directly. + * + * `tls_versions` will only be used during the call and the application retains + * ownership. `tls_versions_len` is the number of consecutive `uint16_t` + * pointed to by `tls_versions`. + * + * Ciphersuites are configured separately via the crypto provider. See + * `rustls_crypto_provider_builder_set_cipher_suites` for more information. + */ +rustls_result rustls_client_config_builder_new_custom(const struct rustls_crypto_provider *provider, + const uint16_t *tls_versions, + size_t tls_versions_len, + struct rustls_client_config_builder **builder_out); + +/** + * Set a custom server certificate verifier using the builder crypto provider. + * Returns rustls_result::NoDefaultCryptoProvider if no process default crypto + * provider has been set, and the builder was not constructed with an explicit + * provider choice. + * + * The callback must not capture any of the pointers in its + * rustls_verify_server_cert_params. + * If `userdata` has been set with rustls_connection_set_userdata, it + * will be passed to the callback. Otherwise the userdata param passed to + * the callback will be NULL. + * + * The callback must be safe to call on any thread at any time, including + * multiple concurrent calls. So, for instance, if the callback mutates + * userdata (or other shared state), it must use synchronization primitives + * to make such mutation safe. + * + * The callback receives certificate chain information as raw bytes. + * Currently this library offers no functions to parse the certificates, + * so you'll need to bring your own certificate parsing library + * if you need to parse them. + * + * If the custom verifier accepts the certificate, it should return + * RUSTLS_RESULT_OK. Otherwise, it may return any other rustls_result error. + * Feel free to use an appropriate error from the RUSTLS_RESULT_CERT_* + * section. + * + * + */ +rustls_result rustls_client_config_builder_dangerous_set_certificate_verifier(struct rustls_client_config_builder *config_builder, + rustls_verify_server_cert_callback callback); + +/** + * Configure the server certificate verifier. + * + * This increases the reference count of `verifier` and does not take ownership. + */ +void rustls_client_config_builder_set_server_verifier(struct rustls_client_config_builder *builder, + const struct rustls_server_cert_verifier *verifier); + +/** + * Set the ALPN protocol list to the given protocols. + * + * `protocols` must point to a buffer of `rustls_slice_bytes` (built by the caller) with `len` + * elements. + * + * Each element of the buffer must be a rustls_slice_bytes whose + * data field points to a single ALPN protocol ID. + * + * Standard ALPN protocol IDs are defined at + * . + * + * This function makes a copy of the data in `protocols` and does not retain + * any pointers, so the caller can free the pointed-to memory after calling. + * + * + */ +rustls_result rustls_client_config_builder_set_alpn_protocols(struct rustls_client_config_builder *builder, + const struct rustls_slice_bytes *protocols, + size_t len); + +/** + * Enable or disable verifying the selected ALPN was offered. + * + * The default is `true`. + * + * + */ +void rustls_client_config_builder_set_check_selected_alpn(struct rustls_client_config_builder *config, + bool enable); + +/** + * Enable or disable SNI. + * + */ +void rustls_client_config_builder_set_enable_sni(struct rustls_client_config_builder *config, + bool enable); + +/** + * Provide the configuration a list of certificates where the connection + * will select the first one that is compatible with the server's signature + * verification capabilities. + * + * Clients that want to support both ECDSA and RSA certificates will want the + * ECSDA to go first in the list. + * + * The built configuration will keep a reference to all certified keys + * provided. The client may `rustls_certified_key_free()` afterwards + * without the configuration losing them. The same certified key may also + * be used in multiple configs. + * + * EXPERIMENTAL: installing a client authentication callback will replace any + * configured certified keys and vice versa. + */ +rustls_result rustls_client_config_builder_set_certified_key(struct rustls_client_config_builder *builder, + const struct rustls_certified_key *const *certified_keys, + size_t certified_keys_len); + +/** + * Log key material to the file specified by the `SSLKEYLOGFILE` environment variable. + * + * The key material will be logged in the NSS key log format, + * and is + * compatible with tools like Wireshark. + * + * Secrets logged in this manner are **extremely sensitive** and can break the security + * of past, present and future sessions. + * + * For more control over which secrets are logged, or to customize the format, prefer + * `rustls_client_config_builder_set_key_log`. + */ +rustls_result rustls_client_config_builder_set_key_log_file(struct rustls_client_config_builder *builder); + +/** + * Provide callbacks to manage logging key material. + * + * The `log_cb` argument is mandatory and must not be `NULL` or a `NullParameter` error is + * returned. The `log_cb` will be invoked with a `client_random` to identify the relevant session, + * a `label` to identify the purpose of the `secret`, and the `secret` itself. See the + * Rustls documentation of the `KeyLog` trait for more information on possible labels: + * + * + * The `will_log_cb` may be `NULL`, in which case all key material will be provided to + * the `log_cb`. By providing a custom `will_log_cb` you may return `0` for labels you don't + * wish to log, and non-zero for labels you _do_ wish to log as a performance optimization. + * + * Both callbacks **must** be thread-safe. Arguments provided to the callback live only for as + * long as the callback is executing and are not valid after the callback returns. The + * callbacks must not retain references to the provided data. + * + * Secrets provided to the `log_cb` are **extremely sensitive** and can break the security + * of past, present and future sessions. + * + * See also `rustls_client_config_builder_set_key_log_file` for a simpler way to log + * to a file specified by the `SSLKEYLOGFILE` environment variable. + */ +rustls_result rustls_client_config_builder_set_key_log(struct rustls_client_config_builder *builder, + rustls_keylog_log_callback log_cb, + rustls_keylog_will_log_callback will_log_cb); + +/** + * Configure the client for Encrypted Client Hello (ECH). + * + * This requires providing a TLS encoded list of ECH configurations that should + * have been retrieved from the DNS HTTPS record for the domain you intend to connect to. + * This should be done using DNS-over-HTTPS to avoid leaking the domain name you are + * connecting to ahead of the TLS handshake. + * + * At least one of the ECH configurations must be compatible with the provided `rustls_hpke` + * instance. See `rustls_supported_hpke()` for more information. + * + * Calling this function will replace any existing ECH configuration set by + * previous calls to `rustls_client_config_builder_enable_ech()` or + * `rustls_client_config_builder_enable_ech_grease()`. + * + * The provided `ech_config_list_bytes` and `rustls_hpke` must not be NULL or an + * error will be returned. The caller maintains ownership of the ECH config list TLS bytes + * and `rustls_hpke` instance. This function does not retain any reference to + * `ech_config_list_bytes`. + * + * A `RUSTLS_RESULT_BUILDER_INCOMPATIBLE_TLS_VERSIONS` error is returned if the builder's + * TLS versions have been customized via `rustls_client_config_builder_new_custom()` + * and the customization isn't "only TLS 1.3". ECH may only be used with TLS 1.3. + */ +rustls_result rustls_client_config_builder_enable_ech(struct rustls_client_config_builder *builder, + const uint8_t *ech_config_list_bytes, + size_t ech_config_list_bytes_size, + const struct rustls_hpke *hpke); + +/** + * Configure the client for GREASE Encrypted Client Hello (ECH). + * + * This is a feature to prevent ossification of the TLS handshake by acting as though + * ECH were configured for an imaginary ECH config generated with one of the + * `rustls_hpke` supported suites, chosen at random. + * + * The provided `rustls_client_config_builder` and `rustls_hpke` must not be NULL or an + * error will be returned. The caller maintains ownership of both the + * `rustls_client_config_builder` and the `rustls_hpke` instance. + * + * Calling this function will replace any existing ECH configuration set by + * previous calls to `rustls_client_config_builder_enable_ech()` or + * `rustls_client_config_builder_enable_ech_grease()`. + * + * A `RUSTLS_RESULT_BUILDER_INCOMPATIBLE_TLS_VERSIONS` error is returned if the builder's + * TLS versions have been customized via `rustls_client_config_builder_new_custom()` + * and the customization isn't "only TLS 1.3". ECH may only be used with TLS 1.3. + */ +rustls_result rustls_client_config_builder_enable_ech_grease(struct rustls_client_config_builder *builder, + const struct rustls_hpke *hpke); + +/** + * Turn a *rustls_client_config_builder (mutable) into a const *rustls_client_config + * (read-only). + */ +rustls_result rustls_client_config_builder_build(struct rustls_client_config_builder *builder, + const struct rustls_client_config **config_out); + +/** + * "Free" a client_config_builder without building it into a rustls_client_config. + * + * Normally builders are built into rustls_client_config via `rustls_client_config_builder_build` + * and may not be free'd or otherwise used afterwards. + * + * Use free only when the building of a config has to be aborted before a config + * was created. + */ +void rustls_client_config_builder_free(struct rustls_client_config_builder *config); + +/** + * Returns true if a `rustls_connection` created from the `rustls_client_config` will + * operate in FIPS mode. + * + * This is different from `rustls_crypto_provider_fips` which is concerned + * only with cryptography, whereas this also covers TLS-level configuration that NIST + * recommends, as well as ECH HPKE suites if applicable. + */ +bool rustls_client_config_fips(const struct rustls_client_config *config); + +/** + * "Free" a `rustls_client_config` previously returned from + * `rustls_client_config_builder_build`. + * + * Since `rustls_client_config` is actually an atomically reference-counted pointer, + * extant client connections may still hold an internal reference to the Rust object. + * + * However, C code must consider this pointer unusable after "free"ing it. + * + * Calling with NULL is fine. Must not be called twice with the same value. + */ +void rustls_client_config_free(const struct rustls_client_config *config); + +/** + * Create a new client `rustls_connection`. + * + * If this returns `RUSTLS_RESULT_OK`, the memory pointed to by `conn_out` is modified to + * point at a valid `rustls_connection`. The caller now owns the `rustls_connection` + * and must call `rustls_connection_free` when done with it. + * + * Uses the `rustls_client_config` to determine ALPN protocol support. Prefer + * `rustls_client_connection_new_alpn` to customize this per-connection. + * + * If this returns an error code, the memory pointed to by `conn_out` remains + * unchanged. + * + * The `server_name` parameter can contain a hostname or an IP address in + * textual form (IPv4 or IPv6). This function will return an error if it + * cannot be parsed as one of those types. + */ +rustls_result rustls_client_connection_new(const struct rustls_client_config *config, + const char *server_name, + struct rustls_connection **conn_out); + +/** + * Create a new client `rustls_connection` with custom ALPN protocols. + * + * Operates the same as `rustls_client_connection_new`, but allows specifying + * custom per-connection ALPN protocols instead of inheriting ALPN protocols + * from the `rustls_clinet_config`. + * + * If this returns `RUSTLS_RESULT_OK`, the memory pointed to by `conn_out` is modified to + * point at a valid `rustls_connection`. The caller now owns the `rustls_connection` + * and must call `rustls_connection_free` when done with it. + * + * If this returns an error code, the memory pointed to by `conn_out` remains + * unchanged. + * + * The `server_name` parameter can contain a hostname or an IP address in + * textual form (IPv4 or IPv6). This function will return an error if it + * cannot be parsed as one of those types. + * + * `alpn_protocols` must point to a buffer of `rustls_slice_bytes` (built by the caller) + * with `alpn_protocols_len` elements. Each element of the buffer must be a `rustls_slice_bytes` + * whose data field points to a single ALPN protocol ID. This function makes a copy of the + * data in `alpn_protocols` and does not retain any pointers, so the caller can free the + * pointed-to memory after calling. + * + * Standard ALPN protocol IDs are defined at + * . + */ +rustls_result rustls_client_connection_new_alpn(const struct rustls_client_config *config, + const char *server_name, + const struct rustls_slice_bytes *alpn_protocols, + size_t alpn_protocols_len, + struct rustls_connection **conn_out); + +/** + * Set the userdata pointer associated with this connection. This will be passed + * to any callbacks invoked by the connection, if you've set up callbacks in the config. + * The pointed-to data must outlive the connection. + */ +void rustls_connection_set_userdata(struct rustls_connection *conn, void *userdata); + +/** + * Set the logging callback for this connection. The log callback will be invoked + * with the userdata parameter previously set by rustls_connection_set_userdata, or + * NULL if no userdata was set. + */ +void rustls_connection_set_log_callback(struct rustls_connection *conn, rustls_log_callback cb); + +/** + * Read some TLS bytes from the network into internal buffers. The actual network + * I/O is performed by `callback`, which you provide. Rustls will invoke your + * callback with a suitable buffer to store the read bytes into. You don't have + * to fill it up, just fill with as many bytes as you get in one syscall. + * The `userdata` parameter is passed through directly to `callback`. Note that + * this is distinct from the `userdata` parameter set with + * `rustls_connection_set_userdata`. + * Returns 0 for success, or an errno value on error. Passes through return values + * from callback. See rustls_read_callback for more details. + * + */ +rustls_io_result rustls_connection_read_tls(struct rustls_connection *conn, + rustls_read_callback callback, + void *userdata, + size_t *out_n); + +/** + * Write some TLS bytes to the network. The actual network I/O is performed by + * `callback`, which you provide. Rustls will invoke your callback with a + * suitable buffer containing TLS bytes to send. You don't have to write them + * all, just as many as you can in one syscall. + * The `userdata` parameter is passed through directly to `callback`. Note that + * this is distinct from the `userdata` parameter set with + * `rustls_connection_set_userdata`. + * Returns 0 for success, or an errno value on error. Passes through return values + * from callback. See rustls_write_callback for more details. + * + */ +rustls_io_result rustls_connection_write_tls(struct rustls_connection *conn, + rustls_write_callback callback, + void *userdata, + size_t *out_n); + +/** + * Write all available TLS bytes to the network. The actual network I/O is performed by + * `callback`, which you provide. Rustls will invoke your callback with an array + * of rustls_slice_bytes, each containing a buffer with TLS bytes to send. + * You don't have to write them all, just as many as you are willing. + * The `userdata` parameter is passed through directly to `callback`. Note that + * this is distinct from the `userdata` parameter set with + * `rustls_connection_set_userdata`. + * Returns 0 for success, or an errno value on error. Passes through return values + * from callback. See rustls_write_callback for more details. + * + */ +rustls_io_result rustls_connection_write_tls_vectored(struct rustls_connection *conn, + rustls_write_vectored_callback callback, + void *userdata, + size_t *out_n); + +/** + * Decrypt any available ciphertext from the internal buffer and put it + * into the internal plaintext buffer, potentially making bytes available + * for rustls_connection_read(). + * + */ +rustls_result rustls_connection_process_new_packets(struct rustls_connection *conn); + +/** + * + */ +bool rustls_connection_wants_read(const struct rustls_connection *conn); + +/** + * + */ +bool rustls_connection_wants_write(const struct rustls_connection *conn); + +/** + * Returns true if the connection is currently performing the TLS handshake. + * + * Note: This may return `false` while there are still handshake packets waiting + * to be extracted and transmitted with `rustls_connection_write_tls()`. + * + * See the rustls documentation for more information. + * + * + */ +bool rustls_connection_is_handshaking(const struct rustls_connection *conn); + +/** + * Returns a `rustls_handshake_kind` describing the `rustls_connection`. + */ +enum rustls_handshake_kind rustls_connection_handshake_kind(const struct rustls_connection *conn); + +/** + * Sets a limit on the internal buffers used to buffer unsent plaintext (prior + * to completing the TLS handshake) and unsent TLS records. By default, there + * is no limit. The limit can be set at any time, even if the current buffer + * use is higher. + * + */ +void rustls_connection_set_buffer_limit(struct rustls_connection *conn, size_t n); + +/** + * Queues a close_notify fatal alert to be sent in the next write_tls call. + * + */ +void rustls_connection_send_close_notify(struct rustls_connection *conn); + +/** + * Queues a TLS1.3 key_update message to refresh a connection’s keys. + * + * Rustls internally manages key updates as required and so this function should + * seldom be used. See the Rustls documentation for important caveats and suggestions + * on occasions that merit its use. + * + * + */ +rustls_result rustls_connection_refresh_traffic_keys(struct rustls_connection *conn); + +/** + * Return the i-th certificate provided by the peer. + * Index 0 is the end entity certificate. Higher indexes are certificates + * in the chain. Requesting an index higher than what is available returns + * NULL. + * The returned pointer is valid until the next mutating function call + * affecting the connection. A mutating function call is one where the + * first argument has type `struct rustls_connection *` (as opposed to + * `const struct rustls_connection *`). + * + */ +const struct rustls_certificate *rustls_connection_get_peer_certificate(const struct rustls_connection *conn, + size_t i); + +/** + * Get the ALPN protocol that was negotiated, if any. Stores a pointer to a + * borrowed buffer of bytes, and that buffer's len, in the output parameters. + * The borrow lives as long as the connection. + * If the connection is still handshaking, or no ALPN protocol was negotiated, + * stores NULL and 0 in the output parameters. + * The provided pointer is valid until the next mutating function call + * affecting the connection. A mutating function call is one where the + * first argument has type `struct rustls_connection *` (as opposed to + * `const struct rustls_connection *`). + * + * + */ +void rustls_connection_get_alpn_protocol(const struct rustls_connection *conn, + const uint8_t **protocol_out, + size_t *protocol_out_len); + +/** + * Return the TLS protocol version that has been negotiated. Before this + * has been decided during the handshake, this will return 0. Otherwise, + * the u16 version number as defined in the relevant RFC is returned. + * + * + */ +uint16_t rustls_connection_get_protocol_version(const struct rustls_connection *conn); + +/** + * Retrieves the [IANA registered cipher suite identifier][IANA] agreed with the peer. + * + * This returns `TLS_NULL_WITH_NULL_NULL` (0x0000) until the ciphersuite is agreed. + * + * [IANA]: + */ +uint16_t rustls_connection_get_negotiated_ciphersuite(const struct rustls_connection *conn); + +/** + * Retrieves the cipher suite name agreed with the peer. + * + * This returns "" until the ciphersuite is agreed. + * + * The lifetime of the `rustls_str` is the lifetime of the program, it does not + * need to be freed. + * + * + */ +struct rustls_str rustls_connection_get_negotiated_ciphersuite_name(const struct rustls_connection *conn); + +/** + * Retrieves the [IANA registered supported group identifier][IANA] agreed with the peer. + * + * This returns Reserved (0x0000) until the key exchange group is agreed. + * + * [IANA]: + */ +uint16_t rustls_connection_get_negotiated_key_exchange_group(const struct rustls_connection *conn); + +/** + * Retrieves the key exchange group name agreed with the peer. + * + * This returns "" until the key exchange group is agreed. + * + * The lifetime of the `rustls_str` is the lifetime of the program, it does not + * need to be freed. + */ +struct rustls_str rustls_connection_get_negotiated_key_exchange_group_name(const struct rustls_connection *conn); + +/** + * Retrieves the number of TLS 1.3 tickets that have been received by a client connection. + * + * This returns 0 if the `conn` is `NULL`, or a server connection. + */ +uint32_t rustls_connection_get_tls13_tickets_received(const struct rustls_connection *conn); + +/** + * Write up to `count` plaintext bytes from `buf` into the `rustls_connection`. + * This will increase the number of output bytes available to + * `rustls_connection_write_tls`. + * On success, store the number of bytes actually written in *out_n + * (this may be less than `count`). + * + */ +rustls_result rustls_connection_write(struct rustls_connection *conn, + const uint8_t *buf, + size_t count, + size_t *out_n); + +/** + * Read up to `count` plaintext bytes from the `rustls_connection` into `buf`. + * On success, store the number of bytes read in *out_n (this may be less + * than `count`). A success with *out_n set to 0 means "all bytes currently + * available have been read, but more bytes may become available after + * subsequent calls to rustls_connection_read_tls and + * rustls_connection_process_new_packets." + * + * Subtle note: Even though this function only writes to `buf` and does not + * read from it, the memory in `buf` must be initialized before the call (for + * Rust-internal reasons). Initializing a buffer once and then using it + * multiple times without zeroizing before each call is fine. + * + */ +rustls_result rustls_connection_read(struct rustls_connection *conn, + uint8_t *buf, + size_t count, + size_t *out_n); + +#if defined(DEFINE_READ_BUF) +/** + * Read up to `count` plaintext bytes from the `rustls_connection` into `buf`. + * On success, store the number of bytes read in *out_n (this may be less + * than `count`). A success with *out_n set to 0 means "all bytes currently + * available have been read, but more bytes may become available after + * subsequent calls to rustls_connection_read_tls and + * rustls_connection_process_new_packets." + * + * This experimental API is only available when using a nightly Rust compiler + * and enabling the `read_buf` Cargo feature. It will be deprecated and later + * removed in future versions. + * + * Unlike with `rustls_connection_read`, this function may be called with `buf` + * pointing to an uninitialized memory buffer. + */ +rustls_result rustls_connection_read_2(struct rustls_connection *conn, + uint8_t *buf, + size_t count, + size_t *out_n); +#endif + +/** + * Returns true if the `rustls_connection` was made with a `rustls_client_config` + * or `rustls_server_config` that is FIPS compatible. + * + * This is different from `rustls_crypto_provider_fips` which is concerned + * only with cryptography, whereas this also covers TLS-level configuration that NIST + * recommends, as well as ECH HPKE suites if applicable. + */ +bool rustls_connection_fips(const struct rustls_connection *conn); + +/** + * Free a rustls_connection. Calling with NULL is fine. + * Must not be called twice with the same value. + */ +void rustls_connection_free(struct rustls_connection *conn); + +/** + * Constructs a new `rustls_crypto_provider_builder` using the process-wide default crypto + * provider as the base crypto provider to be customized. + * + * When this function returns `rustls_result::Ok` a pointer to the `rustls_crypto_provider_builder` + * is written to `builder_out`. It returns `rustls_result::NoDefaultCryptoProvider` if no default + * provider has been registered. + * + * The caller owns the returned `rustls_crypto_provider_builder` and must free it using + * `rustls_crypto_provider_builder_free`. + * + * This function is typically used for customizing the default crypto provider for specific + * connections. For example, a typical workflow might be to: + * + * * Either: + * * Use the default `aws-lc-rs` or `*ring*` provider that rustls-ffi is built with based on + * the `CRYPTO_PROVIDER` build variable. + * * Call `rustls_crypto_provider_builder_new_with_base` with the desired provider, and + * then install it as the process default with + * `rustls_crypto_provider_builder_build_as_default`. + * * Afterward, as required for customization: + * * Use `rustls_crypto_provider_builder_new_from_default` to get a builder backed by the + * default crypto provider. + * * Use `rustls_crypto_provider_builder_set_cipher_suites` to customize the supported + * ciphersuites. + * * Use `rustls_crypto_provider_builder_build` to build a customized provider. + * * Provide that customized provider to client or server configuration builders. + */ +rustls_result rustls_crypto_provider_builder_new_from_default(struct rustls_crypto_provider_builder **builder_out); + +/** + * Constructs a new `rustls_crypto_provider_builder` using the given `rustls_crypto_provider` + * as the base crypto provider to be customized. + * + * The caller owns the returned `rustls_crypto_provider_builder` and must free it using + * `rustls_crypto_provider_builder_free`. + * + * This function can be used for setting the default process wide crypto provider, + * or for constructing a custom crypto provider for a specific connection. A typical + * workflow could be to: + * + * * Call `rustls_crypto_provider_builder_new_with_base` with a custom provider + * * Install the custom provider as the process-wide default with + * `rustls_crypto_provider_builder_build_as_default`. + * + * Or, for per-connection customization: + * + * * Call `rustls_crypto_provider_builder_new_with_base` with a custom provider + * * Use `rustls_crypto_provider_builder_set_cipher_suites` to customize the supported + * ciphersuites. + * * Use `rustls_crypto_provider_builder_build` to build a customized provider. + * * Provide that customized provider to client or server configuration builders. + */ +struct rustls_crypto_provider_builder *rustls_crypto_provider_builder_new_with_base(const struct rustls_crypto_provider *base); + +/** + * Customize the supported ciphersuites of the `rustls_crypto_provider_builder`. + * + * Returns an error if the builder has already been built. Overwrites any previously + * set ciphersuites. + */ +rustls_result rustls_crypto_provider_builder_set_cipher_suites(struct rustls_crypto_provider_builder *builder, + const struct rustls_supported_ciphersuite *const *cipher_suites, + size_t cipher_suites_len); + +/** + * Builds a `rustls_crypto_provider` from the builder and returns it. Returns an error if the + * builder has already been built. + * + * The `rustls_crypto_provider_builder` builder is consumed and should not be used + * for further calls, except to `rustls_crypto_provider_builder_free`. The caller must + * still free the builder after a successful build. + */ +rustls_result rustls_crypto_provider_builder_build(struct rustls_crypto_provider_builder *builder, + const struct rustls_crypto_provider **provider_out); + +/** + * Builds a `rustls_crypto_provider` from the builder and sets it as the + * process-wide default crypto provider. + * + * Afterward, the default provider can be retrieved using `rustls_crypto_provider_default`. + * + * This can only be done once per process, and will return an error if a + * default provider has already been set, or if the builder has already been built. + * + * The `rustls_crypto_provider_builder` builder is consumed and should not be used + * for further calls, except to `rustls_crypto_provider_builder_free`. The caller must + * still free the builder after a successful build. + */ +rustls_result rustls_crypto_provider_builder_build_as_default(struct rustls_crypto_provider_builder *builder); + +/** + * Free the `rustls_crypto_provider_builder`. + * + * Calling with `NULL` is fine. + * Must not be called twice with the same value. + */ +void rustls_crypto_provider_builder_free(struct rustls_crypto_provider_builder *builder); + +#if defined(DEFINE_RING) +/** + * Return the `rustls_crypto_provider` backed by the `*ring*` cryptography library. + * + * The caller owns the returned `rustls_crypto_provider` and must free it using + * `rustls_crypto_provider_free`. + */ +const struct rustls_crypto_provider *rustls_ring_crypto_provider(void); +#endif + +#if defined(DEFINE_AWS_LC_RS) +/** + * Return the `rustls_crypto_provider` backed by the `aws-lc-rs` cryptography library. + * + * The caller owns the returned `rustls_crypto_provider` and must free it using + * `rustls_crypto_provider_free`. + */ +const struct rustls_crypto_provider *rustls_aws_lc_rs_crypto_provider(void); +#endif + +#if defined(DEFINE_FIPS) +/** + * Return a `rustls_crypto_provider` that uses FIPS140-3 approved cryptography. + * + * Using this function expresses in your code that you require FIPS-approved cryptography, + * and will not compile if you make a mistake with cargo features. + * + * See the upstream [rustls FIPS documentation][FIPS] for more information. + * + * The caller owns the returned `rustls_crypto_provider` and must free it using + * `rustls_crypto_provider_free`. + * + * [FIPS]: https://docs.rs/rustls/latest/rustls/manual/_06_fips/index.html + */ +const struct rustls_crypto_provider *rustls_default_fips_provider(void); +#endif + +/** + * Retrieve a pointer to the process default `rustls_crypto_provider`. + * + * This may return `NULL` if no process default provider has been set using + * `rustls_crypto_provider_builder_build_default`. + * + * Caller owns the returned `rustls_crypto_provider` and must free it w/ `rustls_crypto_provider_free`. + */ +const struct rustls_crypto_provider *rustls_crypto_provider_default(void); + +/** + * Returns the number of ciphersuites the `rustls_crypto_provider` supports. + * + * You can use this to know the maximum allowed index for use with + * `rustls_crypto_provider_ciphersuites_get`. + * + * This function will return 0 if the `provider` is NULL. + */ +size_t rustls_crypto_provider_ciphersuites_len(const struct rustls_crypto_provider *provider); + +/** + * Retrieve a pointer to a supported ciphersuite of the `rustls_crypto_provider`. + * + * This function will return NULL if the `provider` is NULL, or if the index is out of bounds + * with respect to `rustls_crypto_provider_ciphersuites_len`. + * + * The lifetime of the returned `rustls_supported_ciphersuite` is equal to the lifetime of the + * `provider` and should not be used after the `provider` is freed. + */ +const struct rustls_supported_ciphersuite *rustls_crypto_provider_ciphersuites_get(const struct rustls_crypto_provider *provider, + size_t index); + +/** + * Load a private key from the provided PEM content using the crypto provider. + * + * `private_key` must point to a buffer of `private_key_len` bytes, containing + * a PEM-encoded private key. The exact formats supported will differ based on + * the crypto provider in use. The default providers support PKCS#1, PKCS#8 or + * SEC1 formats. + * + * When this function returns `rustls_result::Ok` a pointer to a `rustls_signing_key` + * is written to `signing_key_out`. The caller owns the returned `rustls_signing_key` + * and must free it with `rustls_signing_key_free`. + */ +rustls_result rustls_crypto_provider_load_key(const struct rustls_crypto_provider *provider, + const uint8_t *private_key, + size_t private_key_len, + struct rustls_signing_key **signing_key_out); + +/** + * Write `len` bytes of cryptographically secure random data to `buff` using the crypto provider. + * + * `buff` must point to a buffer of at least `len` bytes. The caller maintains ownership + * of the buffer. + * + * Returns `RUSTLS_RESULT_OK` on success, or `RUSTLS_RESULT_GET_RANDOM_FAILED` on failure. + */ +rustls_result rustls_crypto_provider_random(const struct rustls_crypto_provider *provider, + uint8_t *buff, + size_t len); + +/** + * Returns true if the `rustls_crypto_provider` is operating in FIPS mode. + * + * This covers only the cryptographic parts of FIPS approval. There are also + * TLS protocol-level recommendations made by NIST. You should prefer to call + * `rustls_client_config_fips` or `rustls_server_config_fips` which take these + * into account. + */ +bool rustls_crypto_provider_fips(const struct rustls_crypto_provider *provider); + +/** + * Frees the `rustls_crypto_provider`. + * + * Calling with `NULL` is fine. + * Must not be called twice with the same value. + */ +void rustls_crypto_provider_free(const struct rustls_crypto_provider *provider); + +/** + * Returns the number of ciphersuites the default process-wide crypto provider supports. + * + * You can use this to know the maximum allowed index for use with + * `rustls_default_crypto_provider_ciphersuites_get`. + * + * This function will return 0 if no process-wide default `rustls_crypto_provider` is available. + */ +size_t rustls_default_crypto_provider_ciphersuites_len(void); + +/** + * Retrieve a pointer to a supported ciphersuite of the default process-wide crypto provider. + * + * This function will return NULL if the `provider` is NULL, or if the index is out of bounds + * with respect to `rustls_default_crypto_provider_ciphersuites_len`. + * + * The lifetime of the returned `rustls_supported_ciphersuite` is static, as the process-wide + * default provider lives for as long as the process. + */ +const struct rustls_supported_ciphersuite *rustls_default_crypto_provider_ciphersuites_get(size_t index); + +/** + * Write `len` bytes of cryptographically secure random data to `buff` using the process-wide + * default crypto provider. + * + * `buff` must point to a buffer of at least `len` bytes. The caller maintains ownership + * of the buffer. + * + * Returns `RUSTLS_RESULT_OK` on success, and one of `RUSTLS_RESULT_NO_DEFAULT_CRYPTO_PROVIDER` + * or `RUSTLS_RESULT_GET_RANDOM_FAILED` on failure. + */ +rustls_result rustls_default_crypto_provider_random(uint8_t *buff, size_t len); + +/** + * Frees the `rustls_signing_key`. This is safe to call with a `NULL` argument, but + * must not be called twice with the same value. + */ +void rustls_signing_key_free(struct rustls_signing_key *signing_key); + +/** + * Returns a pointer to the supported `rustls_hpke` Hybrid Public Key Encryption (HPKE) + * suites, or `NULL` if HPKE is not supported. + * + * HPKE is only supported with the `aws-lc-rs` cryptography provider. + * + * The returned pointer has a static lifetime equal to that of the program and does not + * need to be freed. + */ +const struct rustls_hpke *rustls_supported_hpke(void); + +/** + * Convert a `rustls_handshake_kind` to a string with a friendly description of the kind + * of handshake. + * + * The returned `rustls_str` has a static lifetime equal to that of the program and does + * not need to be manually freed. + */ +struct rustls_str rustls_handshake_kind_str(enum rustls_handshake_kind kind); + +/** + * After a rustls function returns an error, you may call + * this to get a pointer to a buffer containing a detailed error + * message. + * + * The contents of the error buffer will be out_n bytes long, + * UTF-8 encoded, and not NUL-terminated. + */ +void rustls_error(unsigned int result, char *buf, size_t len, size_t *out_n); + +/** + * Returns true if the `result` is a certificate related error. + */ +bool rustls_result_is_cert_error(unsigned int result); + +/** + * Return a rustls_str containing the stringified version of a log level. + */ +struct rustls_str rustls_log_level_str(rustls_log_level level); + +/** + * Return the length of the outer slice. If the input pointer is NULL, + * returns 0. + */ +size_t rustls_slice_slice_bytes_len(const struct rustls_slice_slice_bytes *input); + +/** + * Retrieve the nth element from the input slice of slices. + * + * If the input pointer is NULL, or n is greater than the length + * of the `rustls_slice_slice_bytes`, returns rustls_slice_bytes{NULL, 0}. + */ +struct rustls_slice_bytes rustls_slice_slice_bytes_get(const struct rustls_slice_slice_bytes *input, + size_t n); + +/** + * Return the length of the outer slice. + * + * If the input pointer is NULL, returns 0. + */ +size_t rustls_slice_str_len(const struct rustls_slice_str *input); + +/** + * Retrieve the nth element from the input slice of `&str`s. + * + * If the input pointer is NULL, or n is greater than the length of the + * rustls_slice_str, returns rustls_str{NULL, 0}. + */ +struct rustls_str rustls_slice_str_get(const struct rustls_slice_str *input, size_t n); + +/** + * Create a rustls_server_config_builder using the process default crypto provider. + * + * Caller owns the memory and must eventually call rustls_server_config_builder_build, + * then free the resulting rustls_server_config. + * + * Alternatively, if an error occurs or, you don't wish to build a config, call + * `rustls_server_config_builder_free` to free the builder directly. + * + * This uses the process default provider's values for the cipher suites and key exchange + * groups, as well as safe defaults for protocol versions. + */ +struct rustls_server_config_builder *rustls_server_config_builder_new(void); + +/** + * Create a rustls_server_config_builder using the specified crypto provider. + * + * Caller owns the memory and must eventually call rustls_server_config_builder_build, + * then free the resulting rustls_server_config. + * + * Alternatively, if an error occurs or, you don't wish to build a config, call + * `rustls_server_config_builder_free` to free the builder directly. + * + * `tls_versions` set the TLS protocol versions to use when negotiating a TLS session. + * + * `tls_versions` is the version of the protocol, as defined in rfc8446, + * ch. 4.2.1 and end of ch. 5.1. Some values are defined in + * `rustls_tls_version` for convenience. + * + * `tls_versions` will only be used during the call and the application retains + * ownership. `tls_versions_len` is the number of consecutive `uint16_t` pointed + * to by `tls_versions`. + * + * Ciphersuites are configured separately via the crypto provider. See + * `rustls_crypto_provider_builder_set_cipher_suites` for more information. + */ +rustls_result rustls_server_config_builder_new_custom(const struct rustls_crypto_provider *provider, + const uint16_t *tls_versions, + size_t tls_versions_len, + struct rustls_server_config_builder **builder_out); + +/** + * Create a rustls_server_config_builder for TLS sessions that may verify client + * certificates. + * + * This increases the refcount of `verifier` and doesn't take ownership. + */ +void rustls_server_config_builder_set_client_verifier(struct rustls_server_config_builder *builder, + const struct rustls_client_cert_verifier *verifier); + +/** + * Log key material to the file specified by the `SSLKEYLOGFILE` environment variable. + * + * The key material will be logged in the NSS key log format, + * and is + * compatible with tools like Wireshark. + * + * Secrets logged in this manner are **extremely sensitive** and can break the security + * of past, present and future sessions. + * + * For more control over which secrets are logged, or to customize the format, prefer + * `rustls_server_config_builder_set_key_log`. + */ +rustls_result rustls_server_config_builder_set_key_log_file(struct rustls_server_config_builder *builder); + +/** + * Provide callbacks to manage logging key material. + * + * The `log_cb` argument is mandatory and must not be `NULL` or a `NullParameter` error is + * returned. The `log_cb` will be invoked with a `client_random` to identify the relevant session, + * a `label` to identify the purpose of the `secret`, and the `secret` itself. See the + * Rustls documentation of the `KeyLog` trait for more information on possible labels: + * + * + * The `will_log_cb` may be `NULL`, in which case all key material will be provided to + * the `log_cb`. By providing a custom `will_log_cb` you may return `0` for labels you don't + * wish to log, and non-zero for labels you _do_ wish to log as a performance optimization. + * + * Both callbacks **must** be thread-safe. Arguments provided to the callback live only for as + * long as the callback is executing and are not valid after the callback returns. The + * callbacks must not retain references to the provided data. + * + * Secrets provided to the `log_cb` are **extremely sensitive** and can break the security + * of past, present and future sessions. + * + * See also `rustls_server_config_builder_set_key_log_file` for a simpler way to log + * to a file specified by the `SSLKEYLOGFILE` environment variable. + */ +rustls_result rustls_server_config_builder_set_key_log(struct rustls_server_config_builder *builder, + rustls_keylog_log_callback log_cb, + rustls_keylog_will_log_callback will_log_cb); + +/** + * "Free" a server_config_builder without building it into a rustls_server_config. + * + * Normally builders are built into rustls_server_configs via `rustls_server_config_builder_build` + * and may not be free'd or otherwise used afterwards. + * + * Use free only when the building of a config has to be aborted before a config + * was created. + */ +void rustls_server_config_builder_free(struct rustls_server_config_builder *config); + +/** + * With `ignore` != 0, the server will ignore the client ordering of cipher + * suites, aka preference, during handshake and respect its own ordering + * as configured. + * + */ +rustls_result rustls_server_config_builder_set_ignore_client_order(struct rustls_server_config_builder *builder, + bool ignore); + +/** + * Set the ALPN protocol list to the given protocols. + * + * `protocols` must point to a buffer of `rustls_slice_bytes` (built by the caller) + * with `len` elements. Each element of the buffer must point to a slice of bytes that + * contains a single ALPN protocol from + * . + * + * This function makes a copy of the data in `protocols` and does not retain + * any pointers, so the caller can free the pointed-to memory after calling. + * + * + */ +rustls_result rustls_server_config_builder_set_alpn_protocols(struct rustls_server_config_builder *builder, + const struct rustls_slice_bytes *protocols, + size_t len); + +/** + * Provide the configuration a list of certificates where the connection + * will select the first one that is compatible with the client's signature + * verification capabilities. + * + * Servers that want to support both ECDSA and RSA certificates will want + * the ECSDA to go first in the list. + * + * The built configuration will keep a reference to all certified keys + * provided. The client may `rustls_certified_key_free()` afterwards + * without the configuration losing them. The same certified key may also + * be used in multiple configs. + * + * EXPERIMENTAL: installing a client_hello callback will replace any + * configured certified keys and vice versa. + */ +rustls_result rustls_server_config_builder_set_certified_keys(struct rustls_server_config_builder *builder, + const struct rustls_certified_key *const *certified_keys, + size_t certified_keys_len); + +/** + * Turn a *rustls_server_config_builder (mutable) into a const *rustls_server_config + * (read-only). The constructed `rustls_server_config` will be written to the `config_out` + * pointer when this function returns `rustls_result::Ok`. + * + * This function may return an error if no process default crypto provider has been set + * and the builder was constructed using `rustls_server_config_builder_new`, or if no + * certificate resolver was set. + */ +rustls_result rustls_server_config_builder_build(struct rustls_server_config_builder *builder, + const struct rustls_server_config **config_out); + +/** + * Returns true if a `rustls_connection` created from the `rustls_server_config` will + * operate in FIPS mode. + * + * This is different from `rustls_crypto_provider_fips` which is concerned + * only with cryptography, whereas this also covers TLS-level configuration that NIST + * recommends, as well as ECH HPKE suites if applicable. + */ +bool rustls_server_config_fips(const struct rustls_server_config *config); + +/** + * "Free" a rustls_server_config previously returned from + * rustls_server_config_builder_build. + * + * Since rustls_server_config is actually an + * atomically reference-counted pointer, extant server connections may still + * hold an internal reference to the Rust object. However, C code must + * consider this pointer unusable after "free"ing it. + * Calling with NULL is fine. Must not be called twice with the same value. + */ +void rustls_server_config_free(const struct rustls_server_config *config); + +/** + * Create a new rustls_connection containing a server connection, and return it. + * + * It is returned in the output parameter `conn_out`. + * + * If this returns an error code, the memory pointed to by `conn_out` remains unchanged. + * + * If this returns a non-error, the memory pointed to by `conn_out` is modified to point + * at a valid rustls_connection + * + * The caller now owns the rustls_connection and must call `rustls_connection_free` when + * done with it. + */ +rustls_result rustls_server_connection_new(const struct rustls_server_config *config, + struct rustls_connection **conn_out); + +/** + * Returns a `rustls_str` reference to the server name sent by the client in a server name + * indication (SNI) extension. + * + * The returned `rustls_str` is valid until the next mutating function call affecting the + * connection. A mutating function call is one where the first argument has type + * `struct rustls_connection *` (as opposed to `const struct rustls_connection *`). The caller + * does not need to free the `rustls_str`. + * + * Returns a zero-length `rustls_str` if: + * + * - the connection is not a server connection. + * - the connection is a server connection but the SNI extension in the client hello has not + * been processed during the handshake yet. Check `rustls_connection_is_handshaking`. + * - the SNI value contains null bytes. + */ +struct rustls_str rustls_server_connection_get_server_name(const struct rustls_connection *conn); + +/** + * Register a callback to be invoked when a connection created from this config + * sees a TLS ClientHello message. If `userdata` has been set with + * rustls_connection_set_userdata, it will be passed to the callback. + * Otherwise the userdata param passed to the callback will be NULL. + * + * Any existing `ResolvesServerCert` implementation currently installed in the + * `rustls_server_config` will be replaced. This also means registering twice + * will overwrite the first registration. It is not permitted to pass a NULL + * value for `callback`. + * + * EXPERIMENTAL: this feature of rustls-ffi is likely to change in the future, as + * the rustls library is re-evaluating their current approach to client hello handling. + * Installing a client_hello callback will replace any configured certified keys + * and vice versa. Same holds true for the set_certified_keys variant. + */ +rustls_result rustls_server_config_builder_set_hello_callback(struct rustls_server_config_builder *builder, + rustls_client_hello_callback callback); + +/** + * Select a `rustls_certified_key` from the list that matches the cryptographic + * parameters of a TLS client hello. + * + * Note that this does not do any SNI matching. The input certificates should + * already have been filtered to ones matching the SNI from the client hello. + * + * This is intended for servers that are configured with several keys for the + * same domain name(s), for example ECDSA and RSA types. The presented keys are + * inspected in the order given and keys first in the list are given preference, + * all else being equal. However rustls is free to choose whichever it considers + * to be the best key with its knowledge about security issues and possible future + * extensions of the protocol. + * + * Return RUSTLS_RESULT_OK if a key was selected and RUSTLS_RESULT_NOT_FOUND + * if none was suitable. + */ +rustls_result rustls_client_hello_select_certified_key(const struct rustls_client_hello *hello, + const struct rustls_certified_key *const *certified_keys, + size_t certified_keys_len, + const struct rustls_certified_key **out_key); + +/** + * Register callbacks for persistence of TLS session IDs and secrets. Both + * keys and values are highly sensitive data, containing enough information + * to break the security of the connections involved. + * + * If `builder`, `get_cb`, or `put_cb` are NULL, this function will return + * immediately without doing anything. + * + * If `userdata` has been set with rustls_connection_set_userdata, it + * will be passed to the callbacks. Otherwise the userdata param passed to + * the callbacks will be NULL. + */ +void rustls_server_config_builder_set_persistence(struct rustls_server_config_builder *builder, + rustls_session_store_get_callback get_cb, + rustls_session_store_put_callback put_cb); + +/** + * Free a `rustls_client_cert_verifier` previously returned from + * `rustls_client_cert_verifier_builder_build`. Calling with NULL is fine. Must not be + * called twice with the same value. + */ +void rustls_client_cert_verifier_free(struct rustls_client_cert_verifier *verifier); + +/** + * Create a `rustls_web_pki_client_cert_verifier_builder` using the process-wide default + * cryptography provider. + * + * Caller owns the memory and may eventually call `rustls_web_pki_client_cert_verifier_builder_free` + * to free it, whether or not `rustls_web_pki_client_cert_verifier_builder_build` was called. + * + * Without further modification the builder will produce a client certificate verifier that + * will require a client present a client certificate that chains to one of the trust anchors + * in the provided `rustls_root_cert_store`. The root cert store must not be empty. + * + * Revocation checking will not be performed unless + * `rustls_web_pki_client_cert_verifier_builder_add_crl` is used to add certificate revocation + * lists (CRLs) to the builder. If CRLs are added, revocation checking will be performed + * for the entire certificate chain unless + * `rustls_web_pki_client_cert_verifier_only_check_end_entity_revocation` is used. Unknown + * revocation status for certificates considered for revocation status will be treated as + * an error unless `rustls_web_pki_client_cert_verifier_allow_unknown_revocation_status` is + * used. + * + * Unauthenticated clients will not be permitted unless + * `rustls_web_pki_client_cert_verifier_builder_allow_unauthenticated` is used. + * + * This copies the contents of the `rustls_root_cert_store`. It does not take + * ownership of the pointed-to data. + */ +struct rustls_web_pki_client_cert_verifier_builder *rustls_web_pki_client_cert_verifier_builder_new(const struct rustls_root_cert_store *store); + +/** + * Create a `rustls_web_pki_client_cert_verifier_builder` using the specified + * cryptography provider. + * + * Caller owns the memory and may eventually call + * `rustls_web_pki_client_cert_verifier_builder_free` to free it, whether or + * not `rustls_web_pki_client_cert_verifier_builder_build` was called. + * + * Without further modification the builder will produce a client certificate verifier that + * will require a client present a client certificate that chains to one of the trust anchors + * in the provided `rustls_root_cert_store`. The root cert store must not be empty. + * + * Revocation checking will not be performed unless + * `rustls_web_pki_client_cert_verifier_builder_add_crl` is used to add certificate revocation + * lists (CRLs) to the builder. If CRLs are added, revocation checking will be performed + * for the entire certificate chain unless + * `rustls_web_pki_client_cert_verifier_only_check_end_entity_revocation` is used. Unknown + * revocation status for certificates considered for revocation status will be treated as + * an error unless `rustls_web_pki_client_cert_verifier_allow_unknown_revocation_status` is + * used. + * + * Unauthenticated clients will not be permitted unless + * `rustls_web_pki_client_cert_verifier_builder_allow_unauthenticated` is used. + * + * This copies the contents of the `rustls_root_cert_store`. It does not take + * ownership of the pointed-to data. + */ +struct rustls_web_pki_client_cert_verifier_builder *rustls_web_pki_client_cert_verifier_builder_new_with_provider(const struct rustls_crypto_provider *provider, + const struct rustls_root_cert_store *store); + +/** + * Add one or more certificate revocation lists (CRLs) to the client certificate verifier + * builder by reading the CRL content from the provided buffer of PEM encoded content. + * + * By default revocation checking will be performed on the entire certificate chain. To only + * check the revocation status of the end entity certificate, use + * `rustls_web_pki_client_cert_verifier_only_check_end_entity_revocation`. + * + * This function returns an error if the provided buffer is not valid PEM encoded content. + */ +rustls_result rustls_web_pki_client_cert_verifier_builder_add_crl(struct rustls_web_pki_client_cert_verifier_builder *builder, + const uint8_t *crl_pem, + size_t crl_pem_len); + +/** + * When CRLs are provided with `rustls_web_pki_client_cert_verifier_builder_add_crl`, only + * check the revocation status of end entity certificates, ignoring any intermediate certificates + * in the chain. + */ +rustls_result rustls_web_pki_client_cert_verifier_only_check_end_entity_revocation(struct rustls_web_pki_client_cert_verifier_builder *builder); + +/** + * When CRLs are provided with `rustls_web_pki_client_cert_verifier_builder_add_crl`, and it + * isn't possible to determine the revocation status of a considered certificate, do not treat + * it as an error condition. + * + * Overrides the default behavior where unknown revocation status is considered an error. + */ +rustls_result rustls_web_pki_client_cert_verifier_allow_unknown_revocation_status(struct rustls_web_pki_client_cert_verifier_builder *builder); + +/** + * Allow unauthenticated anonymous clients in addition to those that present a client + * certificate that chains to one of the verifier's configured trust anchors. + */ +rustls_result rustls_web_pki_client_cert_verifier_builder_allow_unauthenticated(struct rustls_web_pki_client_cert_verifier_builder *builder); + +/** + * Clear the list of trust anchor hint subjects. + * + * By default, the client cert verifier will use the subjects provided by the root cert + * store configured for client authentication. Calling this function will remove these + * hint subjects, indicating the client should make a free choice of which certificate + * to send. + */ +rustls_result rustls_web_pki_client_cert_verifier_clear_root_hint_subjects(struct rustls_web_pki_client_cert_verifier_builder *builder); + +/** + * Add additional distinguished names to the list of trust anchor hint subjects. + * + * By default, the client cert verifier will use the subjects provided by the root cert + * store configured for client authentication. Calling this function will add to these + * existing hint subjects. Calling this function with an empty `store` will have no + * effect, use `rustls_web_pki_client_cert_verifier_clear_root_hint_subjects` to clear + * the subject hints. + */ +rustls_result rustls_web_pki_client_cert_verifier_add_root_hint_subjects(struct rustls_web_pki_client_cert_verifier_builder *builder, + const struct rustls_root_cert_store *store); + +/** + * Create a new client certificate verifier from the builder. + * + * The builder is consumed and cannot be used again, but must still be freed. + * + * The verifier can be used in several `rustls_server_config` instances and must be + * freed by the application when no longer needed. See the documentation of + * `rustls_web_pki_client_cert_verifier_builder_free` for details about lifetime. + */ +rustls_result rustls_web_pki_client_cert_verifier_builder_build(struct rustls_web_pki_client_cert_verifier_builder *builder, + struct rustls_client_cert_verifier **verifier_out); + +/** + * Free a `rustls_client_cert_verifier_builder` previously returned from + * `rustls_client_cert_verifier_builder_new`. + * + * Calling with NULL is fine. Must not be called twice with the same value. + */ +void rustls_web_pki_client_cert_verifier_builder_free(struct rustls_web_pki_client_cert_verifier_builder *builder); + +/** + * Create a `rustls_web_pki_server_cert_verifier_builder` using the process-wide default + * crypto provider. + * + * Caller owns the memory and may free it with `rustls_web_pki_server_cert_verifier_builder_free`, + * regardless of whether `rustls_web_pki_server_cert_verifier_builder_build` was called. + * + * Without further modification the builder will produce a server certificate verifier that + * will require a server present a certificate that chains to one of the trust anchors + * in the provided `rustls_root_cert_store`. The root cert store must not be empty. + * + * Revocation checking will not be performed unless + * `rustls_web_pki_server_cert_verifier_builder_add_crl` is used to add certificate revocation + * lists (CRLs) to the builder. If CRLs are added, revocation checking will be performed + * for the entire certificate chain unless + * `rustls_web_pki_server_cert_verifier_only_check_end_entity_revocation` is used. Unknown + * revocation status for certificates considered for revocation status will be treated as + * an error unless `rustls_web_pki_server_cert_verifier_allow_unknown_revocation_status` is + * used. + * + * This copies the contents of the `rustls_root_cert_store`. It does not take + * ownership of the pointed-to data. + */ +struct rustls_web_pki_server_cert_verifier_builder *rustls_web_pki_server_cert_verifier_builder_new(const struct rustls_root_cert_store *store); + +/** + * Create a `rustls_web_pki_server_cert_verifier_builder` using the specified + * crypto provider. Caller owns the memory and may free it with + * `rustls_web_pki_server_cert_verifier_builder_free`, regardless of whether + * `rustls_web_pki_server_cert_verifier_builder_build` was called. + * + * Without further modification the builder will produce a server certificate verifier that + * will require a server present a certificate that chains to one of the trust anchors + * in the provided `rustls_root_cert_store`. The root cert store must not be empty. + * + * Revocation checking will not be performed unless + * `rustls_web_pki_server_cert_verifier_builder_add_crl` is used to add certificate revocation + * lists (CRLs) to the builder. If CRLs are added, revocation checking will be performed + * for the entire certificate chain unless + * `rustls_web_pki_server_cert_verifier_only_check_end_entity_revocation` is used. Unknown + * revocation status for certificates considered for revocation status will be treated as + * an error unless `rustls_web_pki_server_cert_verifier_allow_unknown_revocation_status` is + * used. Expired CRLs will not be treated as an error unless + * `rustls_web_pki_server_cert_verifier_enforce_revocation_expiry` is used. + * + * This copies the contents of the `rustls_root_cert_store`. It does not take + * ownership of the pointed-to data. + */ +struct rustls_web_pki_server_cert_verifier_builder *rustls_web_pki_server_cert_verifier_builder_new_with_provider(const struct rustls_crypto_provider *provider, + const struct rustls_root_cert_store *store); + +/** + * Add one or more certificate revocation lists (CRLs) to the server certificate verifier + * builder by reading the CRL content from the provided buffer of PEM encoded content. + * + * By default revocation checking will be performed on the entire certificate chain. To only + * check the revocation status of the end entity certificate, use + * `rustls_web_pki_server_cert_verifier_only_check_end_entity_revocation`. + * + * This function returns an error if the provided buffer is not valid PEM encoded content. + */ +rustls_result rustls_web_pki_server_cert_verifier_builder_add_crl(struct rustls_web_pki_server_cert_verifier_builder *builder, + const uint8_t *crl_pem, + size_t crl_pem_len); + +/** + * When CRLs are provided with `rustls_web_pki_server_cert_verifier_builder_add_crl`, only + * check the revocation status of end entity certificates, ignoring any intermediate certificates + * in the chain. + */ +rustls_result rustls_web_pki_server_cert_verifier_only_check_end_entity_revocation(struct rustls_web_pki_server_cert_verifier_builder *builder); + +/** + * When CRLs are provided with `rustls_web_pki_server_cert_verifier_builder_add_crl`, and it + * isn't possible to determine the revocation status of a considered certificate, do not treat + * it as an error condition. + * + * Overrides the default behavior where unknown revocation status is considered an error. + */ +rustls_result rustls_web_pki_server_cert_verifier_allow_unknown_revocation_status(struct rustls_web_pki_server_cert_verifier_builder *builder); + +/** + * When CRLs are provided with `rustls_web_pki_server_cert_verifier_builder_add_crl`, and the + * CRL nextUpdate field is in the past, treat it as an error condition. + * + * Overrides the default behavior where CRL expiration is ignored. + */ +rustls_result rustls_web_pki_server_cert_verifier_enforce_revocation_expiry(struct rustls_web_pki_server_cert_verifier_builder *builder); + +/** + * Create a new server certificate verifier from the builder. + * + * The builder is consumed and cannot be used again, but must still be freed. + * + * The verifier can be used in several `rustls_client_config` instances and must be + * freed by the application when no longer needed. See the documentation of + * `rustls_web_pki_server_cert_verifier_builder_free` for details about lifetime. + */ +rustls_result rustls_web_pki_server_cert_verifier_builder_build(struct rustls_web_pki_server_cert_verifier_builder *builder, + struct rustls_server_cert_verifier **verifier_out); + +/** + * Free a `rustls_server_cert_verifier_builder` previously returned from + * `rustls_server_cert_verifier_builder_new`. + * + * Calling with NULL is fine. Must not be called twice with the same value. + */ +void rustls_web_pki_server_cert_verifier_builder_free(struct rustls_web_pki_server_cert_verifier_builder *builder); + +/** + * Create a verifier that uses the default behavior for the current platform. + * + * This uses [`rustls-platform-verifier`][]. + * + * The verifier can be used in several `rustls_client_config` instances and must be freed by + * the application using `rustls_server_cert_verifier_free` when no longer needed. + * + * [`rustls-platform-verifier`]: https://github.com/rustls/rustls-platform-verifier + */ +rustls_result rustls_platform_server_cert_verifier(struct rustls_server_cert_verifier **verifier_out); + +/** + * Create a verifier that uses the default behavior for the current platform. + * + * This uses [`rustls-platform-verifier`][] and the specified crypto provider. + * + * The verifier can be used in several `rustls_client_config` instances and must be freed by + * the application using `rustls_server_cert_verifier_free` when no longer needed. + * + * If the initialization of `rustls-platform-verifier` fails, this function returns + * `NULL`. + * + * [`rustls-platform-verifier`]: https://github.com/rustls/rustls-platform-verifier + */ +DEPRECATED_FUNC("prefer to use rustls_platform_server_cert_verifier_try_with_provider") +struct rustls_server_cert_verifier *rustls_platform_server_cert_verifier_with_provider(const struct rustls_crypto_provider *provider); + +/** + * Create a verifier that uses the default behavior for the current platform. + * + * This uses [`rustls-platform-verifier`][] and the specified crypto provider. + * + * If the initialization of `rustls-platform-verifier` fails, this function returns + * an error and `NULL` is written to `verifier_out`. Otherwise it fills in `verifier_out` + * (whose ownership is transferred to the caller) and returns `RUSTLS_SUCCESS`. + * + * The verifier can be used in several `rustls_client_config` instances and must be freed by + * the application using `rustls_server_cert_verifier_free` when no longer needed. + * + * [`rustls-platform-verifier`]: https://github.com/rustls/rustls-platform-verifier + */ +rustls_result rustls_platform_server_cert_verifier_try_with_provider(const struct rustls_crypto_provider *provider, + struct rustls_server_cert_verifier **verifier_out); + +/** + * Free a `rustls_server_cert_verifier` previously returned from + * `rustls_server_cert_verifier_builder_build` or `rustls_platform_server_cert_verifier`. + * + * Calling with NULL is fine. Must not be called twice with the same value. + */ +void rustls_server_cert_verifier_free(struct rustls_server_cert_verifier *verifier); + +/** + * Returns a static string containing the rustls-ffi version as well as the + * rustls version. The string is alive for the lifetime of the program and does + * not need to be freed. + */ +struct rustls_str rustls_version(void); + +#endif /* RUSTLS_H */ diff --git a/rules/rustls/src.cpp b/rules/rustls/src.cpp new file mode 100644 index 00000000..8a76721d --- /dev/null +++ b/rules/rustls/src.cpp @@ -0,0 +1,248 @@ +// Copyright (c) 2022-present INESC-ID. +// Distributed under the MIT license that can be found in the LICENSE file. + +#include "rustls.h" + +using t1 = rustls_connection *; +using t2 = const rustls_connection *; +using t3 = const rustls_certificate *; +using t4 = rustls_str; +using t5 = rustls_result; +using t6 = rustls_io_result; +using t7 = rustls_tls_version; + +rustls_result f1() { return RUSTLS_RESULT_OK; } +rustls_result f2() { return RUSTLS_RESULT_NULL_PARAMETER; } +rustls_result f3() { return RUSTLS_RESULT_PLAINTEXT_EMPTY; } +rustls_result f4() { return RUSTLS_RESULT_UNEXPECTED_EOF; } + +rustls_tls_version f5() { return RUSTLS_TLS_VERSION_TLSV1_2; } +rustls_tls_version f6() { return RUSTLS_TLS_VERSION_TLSV1_3; } + +rustls_result f7(rustls_connection *conn, uint8_t *buf, size_t count, + size_t *out_n) { + return rustls_connection_read(conn, buf, count, out_n); +} +rustls_result f8(rustls_connection *conn, const uint8_t *buf, size_t count, + size_t *out_n) { + return rustls_connection_write(conn, buf, count, out_n); +} +rustls_result f9(rustls_connection *conn) { + return rustls_connection_process_new_packets(conn); +} +bool f10(const rustls_connection *conn) { + return rustls_connection_wants_read(conn); +} +bool f11(const rustls_connection *conn) { + return rustls_connection_wants_write(conn); +} +bool f12(const rustls_connection *conn) { + return rustls_connection_is_handshaking(conn); +} +void f13(rustls_connection *conn) { + return rustls_connection_send_close_notify(conn); +} +void f14(rustls_connection *conn, void *userdata) { + return rustls_connection_set_userdata(conn, userdata); +} +void f15(const rustls_connection *conn, const uint8_t **protocol_out, + size_t *protocol_out_len) { + return rustls_connection_get_alpn_protocol(conn, protocol_out, + protocol_out_len); +} +uint16_t f16(const rustls_connection *conn) { + return rustls_connection_get_protocol_version(conn); +} +rustls_str f17(const rustls_connection *conn) { + return rustls_connection_get_negotiated_ciphersuite_name(conn); +} +rustls_str f18(const rustls_connection *conn) { + return rustls_connection_get_negotiated_key_exchange_group_name(conn); +} +const rustls_certificate *f19(const rustls_connection *conn, size_t i) { + return rustls_connection_get_peer_certificate(conn, i); +} +void f20(rustls_connection *conn) { return rustls_connection_free(conn); } + +using t8 = rustls_client_config *; +using t9 = const rustls_client_config *; +using t10 = rustls_client_config_builder *; +using t11 = const rustls_client_config_builder *; +using t12 = rustls_certified_key *; +using t13 = const rustls_certified_key *; +using t14 = rustls_crypto_provider *; +using t15 = const rustls_crypto_provider *; +using t16 = rustls_crypto_provider_builder *; +using t17 = const rustls_crypto_provider_builder *; +using t18 = rustls_root_cert_store *; +using t19 = const rustls_root_cert_store *; +using t20 = rustls_root_cert_store_builder *; +using t21 = const rustls_root_cert_store_builder *; +using t22 = rustls_server_cert_verifier *; +using t23 = const rustls_server_cert_verifier *; +using t24 = rustls_web_pki_server_cert_verifier_builder *; +using t25 = const rustls_web_pki_server_cert_verifier_builder *; +using t26 = rustls_supported_ciphersuite *; +using t27 = const rustls_supported_ciphersuite *; +using t28 = rustls_slice_bytes; +using t29 = rustls_verify_server_cert_params; + +rustls_result f21(rustls_client_config_builder *builder, + const rustls_client_config **config_out) { + return rustls_client_config_builder_build(builder, config_out); +} +void f22(rustls_client_config_builder *config) { + return rustls_client_config_builder_free(config); +} +rustls_result f23(const rustls_crypto_provider *provider, + const uint16_t *tls_versions, size_t tls_versions_len, + rustls_client_config_builder **builder_out) { + return rustls_client_config_builder_new_custom(provider, tls_versions, + tls_versions_len, builder_out); +} +rustls_result f24(rustls_client_config_builder *builder, + const rustls_slice_bytes *protocols, size_t len) { + return rustls_client_config_builder_set_alpn_protocols(builder, protocols, + len); +} +rustls_result f25(rustls_client_config_builder *builder, + const rustls_certified_key *const *certified_keys, + size_t certified_keys_len) { + return rustls_client_config_builder_set_certified_key(builder, certified_keys, + certified_keys_len); +} +void f26(rustls_client_config_builder *builder, + const rustls_server_cert_verifier *verifier) { + return rustls_client_config_builder_set_server_verifier(builder, verifier); +} +void f27(const rustls_client_config *config) { + return rustls_client_config_free(config); +} +rustls_result f28(const rustls_client_config *config, const char *server_name, + rustls_connection **conn_out) { + return rustls_client_connection_new(config, server_name, conn_out); +} + +rustls_result f29(const rustls_certificate *cert, const uint8_t **out_der_data, + size_t *out_der_len) { + return rustls_certificate_get_der(cert, out_der_data, out_der_len); +} +rustls_result f30(const uint8_t *cert_chain, size_t cert_chain_len, + const uint8_t *private_key, size_t private_key_len, + const rustls_certified_key **certified_key_out) { + return rustls_certified_key_build(cert_chain, cert_chain_len, private_key, + private_key_len, certified_key_out); +} +void f31(const rustls_certified_key *key) { + return rustls_certified_key_free(key); +} +rustls_result f32(const rustls_certified_key *key) { + return rustls_certified_key_keys_match(key); +} +rustls_result f33(rustls_root_cert_store_builder *builder, const uint8_t *pem, + size_t pem_len, bool strict) { + return rustls_root_cert_store_builder_add_pem(builder, pem, pem_len, strict); +} +rustls_result f34(rustls_root_cert_store_builder *builder, + const rustls_root_cert_store **root_cert_store_out) { + return rustls_root_cert_store_builder_build(builder, root_cert_store_out); +} +void f35(rustls_root_cert_store_builder *builder) { + return rustls_root_cert_store_builder_free(builder); +} +rustls_result f36(rustls_root_cert_store_builder *builder, const char *filename, + bool strict) { + return rustls_root_cert_store_builder_load_roots_from_file(builder, filename, + strict); +} +rustls_root_cert_store_builder *f37() { + return rustls_root_cert_store_builder_new(); +} +void f38(const rustls_root_cert_store *store) { + return rustls_root_cert_store_free(store); +} + +rustls_result f39(rustls_crypto_provider_builder *builder, + const rustls_crypto_provider **provider_out) { + return rustls_crypto_provider_builder_build(builder, provider_out); +} +void f40(rustls_crypto_provider_builder *builder) { + return rustls_crypto_provider_builder_free(builder); +} +rustls_result f41(rustls_crypto_provider_builder **builder_out) { + return rustls_crypto_provider_builder_new_from_default(builder_out); +} +rustls_result f42(rustls_crypto_provider_builder *builder, + const rustls_supported_ciphersuite *const *cipher_suites, + size_t cipher_suites_len) { + return rustls_crypto_provider_builder_set_cipher_suites(builder, cipher_suites, + cipher_suites_len); +} +void f43(const rustls_crypto_provider *provider) { + return rustls_crypto_provider_free(provider); +} +const rustls_supported_ciphersuite *f44(size_t index) { + return rustls_default_crypto_provider_ciphersuites_get(index); +} +size_t f45() { return rustls_default_crypto_provider_ciphersuites_len(); } +rustls_result f46(uint8_t *buff, size_t len) { + return rustls_default_crypto_provider_random(buff, len); +} + +rustls_result f47(rustls_server_cert_verifier **verifier_out) { + return rustls_platform_server_cert_verifier(verifier_out); +} +void f48(rustls_server_cert_verifier *verifier) { + return rustls_server_cert_verifier_free(verifier); +} +rustls_result f49(rustls_web_pki_server_cert_verifier_builder *builder, + const uint8_t *crl_pem, size_t crl_pem_len) { + return rustls_web_pki_server_cert_verifier_builder_add_crl(builder, crl_pem, + crl_pem_len); +} +rustls_result f50(rustls_web_pki_server_cert_verifier_builder *builder, + rustls_server_cert_verifier **verifier_out) { + return rustls_web_pki_server_cert_verifier_builder_build(builder, + verifier_out); +} +void f51(rustls_web_pki_server_cert_verifier_builder *builder) { + return rustls_web_pki_server_cert_verifier_builder_free(builder); +} +rustls_web_pki_server_cert_verifier_builder * +f52(const rustls_root_cert_store *store) { + return rustls_web_pki_server_cert_verifier_builder_new(store); +} + +uint16_t f53(const rustls_supported_ciphersuite *supported_ciphersuite) { + return rustls_supported_ciphersuite_get_suite(supported_ciphersuite); +} +rustls_tls_version +f54(const rustls_supported_ciphersuite *supported_ciphersuite) { + return rustls_supported_ciphersuite_protocol_version(supported_ciphersuite); +} + +rustls_str f55() { return rustls_version(); } + +void f56(unsigned int result, char *buf, size_t len, size_t *out_n) { + return rustls_error(result, buf, len, out_n); +} +bool f57(unsigned int result) { return rustls_result_is_cert_error(result); } + +rustls_io_result f58(rustls_connection *conn, rustls_read_callback callback, + void *userdata, size_t *out_n) { + return rustls_connection_read_tls(conn, callback, userdata, out_n); +} +rustls_io_result f59(rustls_connection *conn, rustls_write_callback callback, + void *userdata, size_t *out_n) { + return rustls_connection_write_tls(conn, callback, userdata, out_n); +} +rustls_result f60(rustls_client_config_builder *builder, + rustls_keylog_log_callback log_cb, + rustls_keylog_will_log_callback will_log_cb) { + return rustls_client_config_builder_set_key_log(builder, log_cb, will_log_cb); +} +rustls_result f61(rustls_client_config_builder *config_builder, + rustls_verify_server_cert_callback callback) { + return rustls_client_config_builder_dangerous_set_certificate_verifier( + config_builder, callback); +} diff --git a/rules/rustls/tgt_unsafe.rs b/rules/rustls/tgt_unsafe.rs new file mode 100644 index 00000000..31e49d5c --- /dev/null +++ b/rules/rustls/tgt_unsafe.rs @@ -0,0 +1,487 @@ +// Copyright (c) 2022-present INESC-ID. +// Distributed under the MIT license that can be found in the LICENSE file. + +fn t1() -> *mut ::rustls_ffi::connection::rustls_connection { + std::ptr::null_mut() +} +fn t2() -> *const ::rustls_ffi::connection::rustls_connection { + std::ptr::null() +} +fn t3() -> *const ::rustls_ffi::certificate::rustls_certificate<'static> { + std::ptr::null() +} +fn t4() -> ::rustls_ffi::rslice::rustls_str<'static> { + unsafe { std::mem::zeroed() } +} +fn t5() -> ::rustls_ffi::rustls_result { + ::rustls_ffi::rustls_result::Ok +} +fn t6() -> ::rustls_ffi::rustls_io_result { + ::rustls_ffi::rustls_io_result(0) +} +fn t7() -> ::rustls_ffi::enums::rustls_tls_version { + ::rustls_ffi::enums::rustls_tls_version::Unknown +} + +unsafe fn f1() -> ::rustls_ffi::rustls_result { + ::rustls_ffi::rustls_result::Ok +} +unsafe fn f2() -> ::rustls_ffi::rustls_result { + ::rustls_ffi::rustls_result::NullParameter +} +unsafe fn f3() -> ::rustls_ffi::rustls_result { + ::rustls_ffi::rustls_result::PlaintextEmpty +} +unsafe fn f4() -> ::rustls_ffi::rustls_result { + ::rustls_ffi::rustls_result::UnexpectedEof +} + +unsafe fn f5() -> i32 { + ::rustls_ffi::enums::rustls_tls_version::Tlsv1_2 as i32 +} +unsafe fn f6() -> i32 { + ::rustls_ffi::enums::rustls_tls_version::Tlsv1_3 as i32 +} + +unsafe fn f7( + a0: *mut ::rustls_ffi::connection::rustls_connection, + a1: *mut u8, + a2: u64, + a3: *mut u64, +) -> u32 { + ::rustls_ffi::connection::rustls_connection::rustls_connection_read( + a0, + a1, + a2 as usize, + a3 as *mut usize, + ) as u32 +} +unsafe fn f8( + a0: *mut ::rustls_ffi::connection::rustls_connection, + a1: *const u8, + a2: u64, + a3: *mut u64, +) -> u32 { + ::rustls_ffi::connection::rustls_connection::rustls_connection_write( + a0, + a1, + a2 as usize, + a3 as *mut usize, + ) as u32 +} +unsafe fn f9(a0: *mut ::rustls_ffi::connection::rustls_connection) -> u32 { + ::rustls_ffi::connection::rustls_connection::rustls_connection_process_new_packets(a0) as u32 +} +unsafe fn f10(a0: *const ::rustls_ffi::connection::rustls_connection) -> bool { + ::rustls_ffi::connection::rustls_connection::rustls_connection_wants_read(a0) +} +unsafe fn f11(a0: *const ::rustls_ffi::connection::rustls_connection) -> bool { + ::rustls_ffi::connection::rustls_connection::rustls_connection_wants_write(a0) +} +unsafe fn f12(a0: *const ::rustls_ffi::connection::rustls_connection) -> bool { + ::rustls_ffi::connection::rustls_connection::rustls_connection_is_handshaking(a0) +} +unsafe fn f13(a0: *mut ::rustls_ffi::connection::rustls_connection) { + ::rustls_ffi::connection::rustls_connection::rustls_connection_send_close_notify(a0) +} +unsafe fn f14(a0: *mut ::rustls_ffi::connection::rustls_connection, a1: *mut std::ffi::c_void) { + ::rustls_ffi::connection::rustls_connection::rustls_connection_set_userdata(a0, a1) +} +unsafe fn f15( + a0: *const ::rustls_ffi::connection::rustls_connection, + a1: *mut *const u8, + a2: *mut u64, +) { + ::rustls_ffi::connection::rustls_connection::rustls_connection_get_alpn_protocol( + a0, + a1, + a2 as *mut usize, + ) +} +unsafe fn f16(a0: *const ::rustls_ffi::connection::rustls_connection) -> u16 { + ::rustls_ffi::connection::rustls_connection::rustls_connection_get_protocol_version(a0) +} +unsafe fn f17( + a0: *const ::rustls_ffi::connection::rustls_connection, +) -> ::rustls_ffi::rslice::rustls_str<'static> { + ::rustls_ffi::connection::rustls_connection::rustls_connection_get_negotiated_ciphersuite_name( + a0, + ) +} +unsafe fn f18( + a0: *const ::rustls_ffi::connection::rustls_connection, +) -> ::rustls_ffi::rslice::rustls_str<'static> { + ::rustls_ffi::connection::rustls_connection::rustls_connection_get_negotiated_key_exchange_group_name(a0) +} +unsafe fn f19( + a0: *const ::rustls_ffi::connection::rustls_connection, + a1: u64, +) -> *const ::rustls_ffi::certificate::rustls_certificate<'static> { + ::rustls_ffi::connection::rustls_connection::rustls_connection_get_peer_certificate( + a0, + a1 as usize, + ) +} +unsafe fn f20(a0: *mut ::rustls_ffi::connection::rustls_connection) { + ::rustls_ffi::connection::rustls_connection::rustls_connection_free(a0) +} + +fn t8() -> *mut ::rustls_ffi::client::rustls_client_config { + std::ptr::null_mut() +} +fn t9() -> *const ::rustls_ffi::client::rustls_client_config { + std::ptr::null() +} +fn t10() -> *mut ::rustls_ffi::client::rustls_client_config_builder { + std::ptr::null_mut() +} +fn t11() -> *const ::rustls_ffi::client::rustls_client_config_builder { + std::ptr::null() +} +fn t12() -> *mut ::rustls_ffi::certificate::rustls_certified_key { + std::ptr::null_mut() +} +fn t13() -> *const ::rustls_ffi::certificate::rustls_certified_key { + std::ptr::null() +} +fn t14() -> *mut ::rustls_ffi::crypto_provider::rustls_crypto_provider { + std::ptr::null_mut() +} +fn t15() -> *const ::rustls_ffi::crypto_provider::rustls_crypto_provider { + std::ptr::null() +} +fn t16() -> *mut ::rustls_ffi::crypto_provider::rustls_crypto_provider_builder { + std::ptr::null_mut() +} +fn t17() -> *const ::rustls_ffi::crypto_provider::rustls_crypto_provider_builder { + std::ptr::null() +} +fn t18() -> *mut ::rustls_ffi::certificate::rustls_root_cert_store { + std::ptr::null_mut() +} +fn t19() -> *const ::rustls_ffi::certificate::rustls_root_cert_store { + std::ptr::null() +} +fn t20() -> *mut ::rustls_ffi::certificate::rustls_root_cert_store_builder { + std::ptr::null_mut() +} +fn t21() -> *const ::rustls_ffi::certificate::rustls_root_cert_store_builder { + std::ptr::null() +} +fn t22() -> *mut ::rustls_ffi::verifier::rustls_server_cert_verifier { + std::ptr::null_mut() +} +fn t23() -> *const ::rustls_ffi::verifier::rustls_server_cert_verifier { + std::ptr::null() +} +fn t24() -> *mut ::rustls_ffi::verifier::rustls_web_pki_server_cert_verifier_builder { + std::ptr::null_mut() +} +fn t25() -> *const ::rustls_ffi::verifier::rustls_web_pki_server_cert_verifier_builder { + std::ptr::null() +} +fn t26() -> *mut ::rustls_ffi::cipher::rustls_supported_ciphersuite { + std::ptr::null_mut() +} +fn t27() -> *const ::rustls_ffi::cipher::rustls_supported_ciphersuite { + std::ptr::null() +} +fn t28() -> ::rustls_ffi::rslice::rustls_slice_bytes<'static> { + unsafe { std::mem::zeroed() } +} +fn t29() -> ::rustls_ffi::client::rustls_verify_server_cert_params<'static> { + unsafe { std::mem::zeroed() } +} + +unsafe fn f21( + a0: *mut ::rustls_ffi::client::rustls_client_config_builder, + a1: *mut *const ::rustls_ffi::client::rustls_client_config, +) -> u32 { + ::rustls_ffi::client::rustls_client_config_builder::rustls_client_config_builder_build(a0, a1) + as u32 +} +unsafe fn f22(a0: *mut ::rustls_ffi::client::rustls_client_config_builder) { + ::rustls_ffi::client::rustls_client_config_builder::rustls_client_config_builder_free(a0) +} +unsafe fn f23( + a0: *const ::rustls_ffi::crypto_provider::rustls_crypto_provider, + a1: *const u16, + a2: u64, + a3: *mut *mut ::rustls_ffi::client::rustls_client_config_builder, +) -> u32 { + ::rustls_ffi::client::rustls_client_config_builder::rustls_client_config_builder_new_custom( + a0, + a1, + a2 as usize, + a3, + ) as u32 +} +unsafe fn f24( + a0: *mut ::rustls_ffi::client::rustls_client_config_builder, + a1: *const ::rustls_ffi::rslice::rustls_slice_bytes<'static>, + a2: u64, +) -> u32 { + ::rustls_ffi::client::rustls_client_config_builder::rustls_client_config_builder_set_alpn_protocols(a0, a1, a2 as usize) as u32 +} +unsafe fn f25( + a0: *mut ::rustls_ffi::client::rustls_client_config_builder, + a1: *const *const ::rustls_ffi::certificate::rustls_certified_key, + a2: u64, +) -> u32 { + ::rustls_ffi::client::rustls_client_config_builder::rustls_client_config_builder_set_certified_key(a0, a1, a2 as usize) as u32 +} +unsafe fn f26( + a0: *mut ::rustls_ffi::client::rustls_client_config_builder, + a1: *const ::rustls_ffi::verifier::rustls_server_cert_verifier, +) { + ::rustls_ffi::client::rustls_client_config_builder::rustls_client_config_builder_set_server_verifier(a0, a1) +} +unsafe fn f27(a0: *const ::rustls_ffi::client::rustls_client_config) { + ::rustls_ffi::client::rustls_client_config::rustls_client_config_free(a0) +} +unsafe fn f28( + a0: *const ::rustls_ffi::client::rustls_client_config, + a1: *const u8, + a2: *mut *mut ::rustls_ffi::connection::rustls_connection, +) -> u32 { + ::rustls_ffi::client::rustls_client_config::rustls_client_connection_new( + a0, + a1 as *const ::std::ffi::c_char, + a2, + ) as u32 +} + +unsafe fn f29( + a0: *const ::rustls_ffi::certificate::rustls_certificate<'static>, + a1: *mut *const u8, + a2: *mut u64, +) -> u32 { + ::rustls_ffi::certificate::rustls_certificate_get_der(a0, a1, a2 as *mut usize) as u32 +} +unsafe fn f30( + a0: *const u8, + a1: u64, + a2: *const u8, + a3: u64, + a4: *mut *const ::rustls_ffi::certificate::rustls_certified_key, +) -> u32 { + ::rustls_ffi::certificate::rustls_certified_key::rustls_certified_key_build( + a0, + a1 as usize, + a2, + a3 as usize, + a4, + ) as u32 +} +unsafe fn f31(a0: *const ::rustls_ffi::certificate::rustls_certified_key) { + ::rustls_ffi::certificate::rustls_certified_key::rustls_certified_key_free(a0) +} +unsafe fn f32(a0: *const ::rustls_ffi::certificate::rustls_certified_key) -> u32 { + ::rustls_ffi::certificate::rustls_certified_key::rustls_certified_key_keys_match(a0) as u32 +} +unsafe fn f33( + a0: *mut ::rustls_ffi::certificate::rustls_root_cert_store_builder, + a1: *const u8, + a2: u64, + a3: bool, +) -> u32 { + ::rustls_ffi::certificate::rustls_root_cert_store_builder::rustls_root_cert_store_builder_add_pem(a0, a1, a2 as usize, a3) as u32 +} +unsafe fn f34( + a0: *mut ::rustls_ffi::certificate::rustls_root_cert_store_builder, + a1: *mut *const ::rustls_ffi::certificate::rustls_root_cert_store, +) -> u32 { + ::rustls_ffi::certificate::rustls_root_cert_store_builder::rustls_root_cert_store_builder_build( + a0, a1, + ) as u32 +} +unsafe fn f35(a0: *mut ::rustls_ffi::certificate::rustls_root_cert_store_builder) { + ::rustls_ffi::certificate::rustls_root_cert_store_builder::rustls_root_cert_store_builder_free( + a0, + ) +} +unsafe fn f36( + a0: *mut ::rustls_ffi::certificate::rustls_root_cert_store_builder, + a1: *const u8, + a2: bool, +) -> u32 { + ::rustls_ffi::certificate::rustls_root_cert_store_builder::rustls_root_cert_store_builder_load_roots_from_file(a0, a1 as *const ::std::ffi::c_char, a2) as u32 +} +unsafe fn f37() -> *mut ::rustls_ffi::certificate::rustls_root_cert_store_builder { + ::rustls_ffi::certificate::rustls_root_cert_store_builder::rustls_root_cert_store_builder_new() +} +unsafe fn f38(a0: *const ::rustls_ffi::certificate::rustls_root_cert_store) { + ::rustls_ffi::certificate::rustls_root_cert_store::rustls_root_cert_store_free(a0) +} + +unsafe fn f39( + a0: *mut ::rustls_ffi::crypto_provider::rustls_crypto_provider_builder, + a1: *mut *const ::rustls_ffi::crypto_provider::rustls_crypto_provider, +) -> u32 { + ::rustls_ffi::crypto_provider::rustls_crypto_provider_builder_build(a0, a1) as u32 +} +unsafe fn f40(a0: *mut ::rustls_ffi::crypto_provider::rustls_crypto_provider_builder) { + ::rustls_ffi::crypto_provider::rustls_crypto_provider_builder_free(a0) +} +unsafe fn f41(a0: *mut *mut ::rustls_ffi::crypto_provider::rustls_crypto_provider_builder) -> u32 { + ::rustls_ffi::crypto_provider::rustls_crypto_provider_builder_new_from_default(a0) as u32 +} +unsafe fn f42( + a0: *mut ::rustls_ffi::crypto_provider::rustls_crypto_provider_builder, + a1: *const *const ::rustls_ffi::cipher::rustls_supported_ciphersuite, + a2: u64, +) -> u32 { + ::rustls_ffi::crypto_provider::rustls_crypto_provider_builder_set_cipher_suites( + a0, + a1, + a2 as usize, + ) as u32 +} +unsafe fn f43(a0: *const ::rustls_ffi::crypto_provider::rustls_crypto_provider) { + ::rustls_ffi::crypto_provider::rustls_crypto_provider_free(a0) +} +unsafe fn f44(a0: u64) -> *const ::rustls_ffi::cipher::rustls_supported_ciphersuite { + ::rustls_ffi::crypto_provider::rustls_default_crypto_provider_ciphersuites_get(a0 as usize) +} +unsafe fn f45() -> u64 { + ::rustls_ffi::crypto_provider::rustls_default_crypto_provider_ciphersuites_len() as u64 +} +unsafe fn f46(a0: *mut u8, a1: u64) -> u32 { + ::rustls_ffi::crypto_provider::rustls_default_crypto_provider_random(a0, a1 as usize) as u32 +} + +unsafe fn f47(a0: *mut *mut ::rustls_ffi::verifier::rustls_server_cert_verifier) -> u32 { + ::rustls_ffi::verifier::rustls_server_cert_verifier::rustls_platform_server_cert_verifier(a0) + as u32 +} +unsafe fn f48(a0: *mut ::rustls_ffi::verifier::rustls_server_cert_verifier) { + ::rustls_ffi::verifier::rustls_server_cert_verifier::rustls_server_cert_verifier_free(a0) +} +unsafe fn f49( + a0: *mut ::rustls_ffi::verifier::rustls_web_pki_server_cert_verifier_builder, + a1: *const u8, + a2: u64, +) -> u32 { + unsafe extern "C" { + fn rustls_web_pki_server_cert_verifier_builder_add_crl( + builder: *mut ::rustls_ffi::verifier::rustls_web_pki_server_cert_verifier_builder, + crl_pem: *const u8, + crl_pem_len: usize, + ) -> ::rustls_ffi::rustls_result; + } + rustls_web_pki_server_cert_verifier_builder_add_crl(a0, a1, a2 as usize) as u32 +} +unsafe fn f50( + a0: *mut ::rustls_ffi::verifier::rustls_web_pki_server_cert_verifier_builder, + a1: *mut *mut ::rustls_ffi::verifier::rustls_server_cert_verifier, +) -> u32 { + unsafe extern "C" { + fn rustls_web_pki_server_cert_verifier_builder_build( + builder: *mut ::rustls_ffi::verifier::rustls_web_pki_server_cert_verifier_builder, + verifier_out: *mut *mut ::rustls_ffi::verifier::rustls_server_cert_verifier, + ) -> ::rustls_ffi::rustls_result; + } + rustls_web_pki_server_cert_verifier_builder_build(a0, a1) as u32 +} +unsafe fn f51(a0: *mut ::rustls_ffi::verifier::rustls_web_pki_server_cert_verifier_builder) { + unsafe extern "C" { + fn rustls_web_pki_server_cert_verifier_builder_free( + builder: *mut ::rustls_ffi::verifier::rustls_web_pki_server_cert_verifier_builder, + ); + } + rustls_web_pki_server_cert_verifier_builder_free(a0) +} +unsafe fn f52( + a0: *const ::rustls_ffi::certificate::rustls_root_cert_store, +) -> *mut ::rustls_ffi::verifier::rustls_web_pki_server_cert_verifier_builder { + unsafe extern "C" { + fn rustls_web_pki_server_cert_verifier_builder_new( + store: *const ::rustls_ffi::certificate::rustls_root_cert_store, + ) -> *mut ::rustls_ffi::verifier::rustls_web_pki_server_cert_verifier_builder; + } + rustls_web_pki_server_cert_verifier_builder_new(a0) +} + +unsafe fn f53(a0: *const ::rustls_ffi::cipher::rustls_supported_ciphersuite) -> u16 { + ::rustls_ffi::cipher::rustls_supported_ciphersuite::rustls_supported_ciphersuite_get_suite(a0) +} +unsafe fn f54( + a0: *const ::rustls_ffi::cipher::rustls_supported_ciphersuite, +) -> ::rustls_ffi::enums::rustls_tls_version { + ::rustls_ffi::cipher::rustls_supported_ciphersuite_protocol_version(a0) +} + +unsafe fn f55() -> ::rustls_ffi::rslice::rustls_str<'static> { + ::rustls_ffi::version::rustls_version() +} + +unsafe fn f56(a0: u32, a1: *mut u8, a2: u64, a3: *mut u64) { + ::rustls_ffi::rustls_result::rustls_error( + a0, + a1 as *mut ::std::ffi::c_char, + a2 as usize, + a3 as *mut usize, + ) +} +unsafe fn f57(a0: u32) -> bool { + ::rustls_ffi::rustls_result::rustls_result_is_cert_error(a0) +} + +unsafe fn f58( + a0: *mut ::rustls_ffi::connection::rustls_connection, + a1: unsafe fn(*mut ::libc::c_void, *mut u8, u64, *mut u64) -> i32, + a2: *mut ::libc::c_void, + a3: *mut u64, +) -> i32 { + ::rustls_ffi::connection::rustls_connection::rustls_connection_read_tls( + a0, + std::mem::transmute::<*const (), ::rustls_ffi::io::rustls_read_callback>(a1 as *const ()), + a2, + a3 as *mut usize, + ) + .0 +} +unsafe fn f59( + a0: *mut ::rustls_ffi::connection::rustls_connection, + a1: unsafe fn(*mut ::libc::c_void, *const u8, u64, *mut u64) -> i32, + a2: *mut ::libc::c_void, + a3: *mut u64, +) -> i32 { + ::rustls_ffi::connection::rustls_connection::rustls_connection_write_tls( + a0, + std::mem::transmute::<*const (), ::rustls_ffi::io::rustls_write_callback>(a1 as *const ()), + a2, + a3 as *mut usize, + ) + .0 +} +unsafe fn f60( + a0: *mut ::rustls_ffi::client::rustls_client_config_builder, + a1: unsafe fn(::rustls_ffi::rslice::rustls_str<'static>, *const u8, u64, *const u8, u64), + a2: Option) -> i32>, +) -> u32 { + ::rustls_ffi::client::rustls_client_config_builder::rustls_client_config_builder_set_key_log( + a0, + std::mem::transmute::<*const (), ::rustls_ffi::keylog::rustls_keylog_log_callback>( + a1 as *const (), + ), + std::mem::transmute::< + Option) -> i32>, + ::rustls_ffi::keylog::rustls_keylog_will_log_callback, + >(a2), + ) as u32 +} +unsafe fn f61( + a0: *mut ::rustls_ffi::client::rustls_client_config_builder, + a1: unsafe fn( + *mut ::libc::c_void, + *const ::rustls_ffi::client::rustls_verify_server_cert_params<'static>, + ) -> u32, +) -> u32 { + ::rustls_ffi::client::rustls_client_config_builder::rustls_client_config_builder_dangerous_set_certificate_verifier( + a0, + std::mem::transmute::<*const (), ::rustls_ffi::client::rustls_verify_server_cert_callback>( + a1 as *const (), + ), + ) as u32 +} diff --git a/rules/src/modules.rs b/rules/src/modules.rs index efd63874..9a7971c5 100644 --- a/rules/src/modules.rs +++ b/rules/src/modules.rs @@ -80,6 +80,8 @@ pub mod pair_tgt_unsafe; pub mod poll_tgt_unsafe; #[path = r#"../pwd/tgt_unsafe.rs"#] pub mod pwd_tgt_unsafe; +#[path = r#"../rustls/tgt_unsafe.rs"#] +pub mod rustls_tgt_unsafe; #[path = r#"../select/tgt_unsafe.rs"#] pub mod select_tgt_unsafe; #[path = r#"../signal/tgt_unsafe.rs"#] diff --git a/rules/stdio/src.cpp b/rules/stdio/src.cpp index c172b5fd..7ef4882a 100644 --- a/rules/stdio/src.cpp +++ b/rules/stdio/src.cpp @@ -62,3 +62,7 @@ int f22(const char *a0, const char *a1) { } int f23(FILE *stream) { return getc(stream); } + +int f24(FILE *stream, char *buf, int mode, size_t size) { + return setvbuf(stream, buf, mode, size); +} diff --git a/rules/stdio/tgt_unsafe.rs b/rules/stdio/tgt_unsafe.rs index 72aacd08..8ccd5fc8 100644 --- a/rules/stdio/tgt_unsafe.rs +++ b/rules/stdio/tgt_unsafe.rs @@ -92,3 +92,7 @@ unsafe fn f22(a0: *const i8, a1: *const i8) -> i32 { unsafe fn f23(a0: *mut ::libc::FILE) -> i32 { libc::fgetc(a0) } + +unsafe fn f24(a0: *mut ::libc::FILE, a1: *mut u8, a2: i32, a3: u64) -> i32 { + libc::setvbuf(a0, a1 as *mut i8, a2, a3 as ::libc::size_t) +}