#include <grpc/support/port_platform.h>
#include "src/core/tsi/ssl_transport_security.h"
#include <limits.h>
#include <string.h>
#ifdef GPR_WINDOWS
#include <ws2tcpip.h>
#else
#include <arpa/inet.h>
#include <sys/socket.h>
#endif
#include <string>
#include <openssl/bio.h>
#include <openssl/crypto.h>
#include <openssl/engine.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/tls1.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include <grpc/grpc_security.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
#include <grpc/support/thd_id.h>
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/gprpp/crash.h"
#include "src/core/tsi/ssl/key_logging/ssl_key_logging.h"
#include "src/core/tsi/ssl/session_cache/ssl_session_cache.h"
#include "src/core/tsi/ssl_transport_security_utils.h"
#include "src/core/tsi/ssl_types.h"
#include "src/core/tsi/transport_security.h"
#define TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND …
#define TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND …
#define TSI_SSL_HANDSHAKER_OUTGOING_BUFFER_INITIAL_SIZE …
#ifndef TSI_OPENSSL_ALPN_SUPPORT
#define TSI_OPENSSL_ALPN_SUPPORT …
#endif
#define TSI_SSL_MAX_PROTECTION_OVERHEAD …
TlsSessionKeyLogger;
struct tsi_ssl_root_certs_store { … };
struct tsi_ssl_handshaker_factory { … };
struct tsi_ssl_client_handshaker_factory { … };
struct tsi_ssl_server_handshaker_factory { … };
struct tsi_ssl_handshaker { … };
struct tsi_ssl_handshaker_result { … };
struct tsi_ssl_frame_protector { … };
static gpr_once g_init_openssl_once = …;
static int g_ssl_ctx_ex_factory_index = …;
static const unsigned char kSslSessionIdContext[] = …;
static int g_ssl_ex_verified_root_cert_index = …;
#if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_NO_ENGINE)
static const char kSslEnginePrefix[] = "engine:";
#endif
#if OPENSSL_VERSION_NUMBER < 0x10100000
static gpr_mu* g_openssl_mutexes = nullptr;
static void openssl_locking_cb(int mode, int type, const char* file,
int line) GRPC_UNUSED;
static unsigned long openssl_thread_id_cb(void) GRPC_UNUSED;
static void openssl_locking_cb(int mode, int type, const char* file, int line) {
if (mode & CRYPTO_LOCK) {
gpr_mu_lock(&g_openssl_mutexes[type]);
} else {
gpr_mu_unlock(&g_openssl_mutexes[type]);
}
}
static unsigned long openssl_thread_id_cb(void) {
return static_cast<unsigned long>(gpr_thd_currentid());
}
#endif
static void init_openssl(void) { … }
static void ssl_log_where_info(const SSL* ssl, int where, int flag,
const char* msg) { … }
static void ssl_info_callback(const SSL* ssl, int where, int ret) { … }
static int looks_like_ip_address(absl::string_view name) { … }
static tsi_result ssl_get_x509_common_name(X509* cert, unsigned char** utf8,
size_t* utf8_size) { … }
static tsi_result peer_property_from_x509_common_name(
X509* cert, tsi_peer_property* property) { … }
static tsi_result peer_property_from_x509_subject(X509* cert,
tsi_peer_property* property,
bool is_verified_root_cert) { … }
static tsi_result add_pem_certificate(X509* cert, tsi_peer_property* property) { … }
static tsi_result add_subject_alt_names_properties_to_peer(
tsi_peer* peer, GENERAL_NAMES* subject_alt_names,
size_t subject_alt_name_count, int* current_insert_index) { … }
static tsi_result peer_from_x509(X509* cert, int include_certificate_type,
tsi_peer* peer) { … }
static tsi_result ssl_ctx_use_certificate_chain(SSL_CTX* context,
const char* pem_cert_chain,
size_t pem_cert_chain_size) { … }
#if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_NO_ENGINE)
static tsi_result ssl_ctx_use_engine_private_key(SSL_CTX* context,
const char* pem_key,
size_t pem_key_size) {
tsi_result result = TSI_OK;
EVP_PKEY* private_key = nullptr;
ENGINE* engine = nullptr;
char* engine_name = nullptr;
do {
char* engine_start = (char*)pem_key + strlen(kSslEnginePrefix);
char* engine_end = (char*)strchr(engine_start, ':');
if (engine_end == nullptr) {
result = TSI_INVALID_ARGUMENT;
break;
}
char* key_id = engine_end + 1;
int engine_name_length = engine_end - engine_start;
if (engine_name_length == 0) {
result = TSI_INVALID_ARGUMENT;
break;
}
engine_name = static_cast<char*>(gpr_zalloc(engine_name_length + 1));
memcpy(engine_name, engine_start, engine_name_length);
gpr_log(GPR_DEBUG, "ENGINE key: %s", engine_name);
ENGINE_load_dynamic();
engine = ENGINE_by_id(engine_name);
if (engine == nullptr) {
engine = ENGINE_by_id("dynamic");
if (engine == nullptr) {
gpr_log(GPR_ERROR, "Cannot load dynamic engine");
result = TSI_INVALID_ARGUMENT;
break;
}
if (!ENGINE_ctrl_cmd_string(engine, "ID", engine_name, 0) ||
!ENGINE_ctrl_cmd_string(engine, "DIR_LOAD", "2", 0) ||
!ENGINE_ctrl_cmd_string(engine, "DIR_ADD", ".", 0) ||
!ENGINE_ctrl_cmd_string(engine, "LIST_ADD", "1", 0) ||
!ENGINE_ctrl_cmd_string(engine, "LOAD", NULL, 0)) {
gpr_log(GPR_ERROR, "Cannot find engine");
result = TSI_INVALID_ARGUMENT;
break;
}
}
if (!ENGINE_set_default(engine, ENGINE_METHOD_ALL)) {
gpr_log(GPR_ERROR, "ENGINE_set_default with ENGINE_METHOD_ALL failed");
result = TSI_INVALID_ARGUMENT;
break;
}
if (!ENGINE_init(engine)) {
gpr_log(GPR_ERROR, "ENGINE_init failed");
result = TSI_INVALID_ARGUMENT;
break;
}
private_key = ENGINE_load_private_key(engine, key_id, 0, 0);
if (private_key == nullptr) {
gpr_log(GPR_ERROR, "ENGINE_load_private_key failed");
result = TSI_INVALID_ARGUMENT;
break;
}
if (!SSL_CTX_use_PrivateKey(context, private_key)) {
gpr_log(GPR_ERROR, "SSL_CTX_use_PrivateKey failed");
result = TSI_INVALID_ARGUMENT;
break;
}
} while (0);
if (engine != nullptr) ENGINE_free(engine);
if (private_key != nullptr) EVP_PKEY_free(private_key);
if (engine_name != nullptr) gpr_free(engine_name);
return result;
}
#endif
static tsi_result ssl_ctx_use_pem_private_key(SSL_CTX* context,
const char* pem_key,
size_t pem_key_size) { … }
static tsi_result ssl_ctx_use_private_key(SSL_CTX* context, const char* pem_key,
size_t pem_key_size) { … }
static tsi_result x509_store_load_certs(X509_STORE* cert_store,
const char* pem_roots,
size_t pem_roots_size,
STACK_OF(X509_NAME) * *root_names) { … }
static tsi_result ssl_ctx_load_verification_certs(SSL_CTX* context,
const char* pem_roots,
size_t pem_roots_size,
STACK_OF(X509_NAME) *
*root_name) { … }
static tsi_result populate_ssl_context(
SSL_CTX* context, const tsi_ssl_pem_key_cert_pair* key_cert_pair,
const char* cipher_list) { … }
tsi_result tsi_ssl_extract_x509_subject_names_from_pem_cert(
const char* pem_cert, tsi_peer* peer) { … }
static tsi_result build_alpn_protocol_name_list(
const char** alpn_protocols, uint16_t num_alpn_protocols,
unsigned char** protocol_name_list, size_t* protocol_name_list_length) { … }
static int verify_cb(int ok, X509_STORE_CTX* ctx) { … }
static int NullVerifyCallback(int , X509_STORE_CTX* ) { … }
static int RootCertExtractCallback(int preverify_ok, X509_STORE_CTX* ctx) { … }
static tsi_result tsi_set_min_and_max_tls_versions(
SSL_CTX* ssl_context, tsi_tls_version min_tls_version,
tsi_tls_version max_tls_version) { … }
tsi_ssl_root_certs_store* tsi_ssl_root_certs_store_create(
const char* pem_roots) { … }
void tsi_ssl_root_certs_store_destroy(tsi_ssl_root_certs_store* self) { … }
tsi_ssl_session_cache* tsi_ssl_session_cache_create_lru(size_t capacity) { … }
void tsi_ssl_session_cache_ref(tsi_ssl_session_cache* cache) { … }
void tsi_ssl_session_cache_unref(tsi_ssl_session_cache* cache) { … }
static tsi_result ssl_protector_protect(tsi_frame_protector* self,
const unsigned char* unprotected_bytes,
size_t* unprotected_bytes_size,
unsigned char* protected_output_frames,
size_t* protected_output_frames_size) { … }
static tsi_result ssl_protector_protect_flush(
tsi_frame_protector* self, unsigned char* protected_output_frames,
size_t* protected_output_frames_size, size_t* still_pending_size) { … }
static tsi_result ssl_protector_unprotect(
tsi_frame_protector* self, const unsigned char* protected_frames_bytes,
size_t* protected_frames_bytes_size, unsigned char* unprotected_bytes,
size_t* unprotected_bytes_size) { … }
static void ssl_protector_destroy(tsi_frame_protector* self) { … }
static const tsi_frame_protector_vtable frame_protector_vtable = …;
static void tsi_ssl_handshaker_factory_destroy(
tsi_ssl_handshaker_factory* factory) { … }
static tsi_ssl_handshaker_factory* tsi_ssl_handshaker_factory_ref(
tsi_ssl_handshaker_factory* factory) { … }
static void tsi_ssl_handshaker_factory_unref(
tsi_ssl_handshaker_factory* factory) { … }
static tsi_ssl_handshaker_factory_vtable handshaker_factory_vtable = …;
static void tsi_ssl_handshaker_factory_init(
tsi_ssl_handshaker_factory* factory) { … }
tsi_result tsi_ssl_get_cert_chain_contents(STACK_OF(X509) * peer_chain,
tsi_peer_property* property) { … }
static tsi_result ssl_handshaker_result_extract_peer(
const tsi_handshaker_result* self, tsi_peer* peer) { … }
static tsi_result ssl_handshaker_result_get_frame_protector_type(
const tsi_handshaker_result* ,
tsi_frame_protector_type* frame_protector_type) { … }
static tsi_result ssl_handshaker_result_create_frame_protector(
const tsi_handshaker_result* self, size_t* max_output_protected_frame_size,
tsi_frame_protector** protector) { … }
static tsi_result ssl_handshaker_result_get_unused_bytes(
const tsi_handshaker_result* self, const unsigned char** bytes,
size_t* bytes_size) { … }
static void ssl_handshaker_result_destroy(tsi_handshaker_result* self) { … }
static const tsi_handshaker_result_vtable handshaker_result_vtable = …;
static tsi_result ssl_handshaker_result_create(
tsi_ssl_handshaker* handshaker, unsigned char* unused_bytes,
size_t unused_bytes_size, tsi_handshaker_result** handshaker_result,
std::string* error) { … }
static tsi_result ssl_handshaker_get_bytes_to_send_to_peer(
tsi_ssl_handshaker* impl, unsigned char* bytes, size_t* bytes_size,
std::string* error) { … }
static tsi_result ssl_handshaker_get_result(tsi_ssl_handshaker* impl) { … }
static tsi_result ssl_handshaker_do_handshake(tsi_ssl_handshaker* impl,
std::string* error) { … }
static tsi_result ssl_handshaker_process_bytes_from_peer(
tsi_ssl_handshaker* impl, const unsigned char* bytes, size_t* bytes_size,
std::string* error) { … }
static void ssl_handshaker_destroy(tsi_handshaker* self) { … }
static tsi_result ssl_bytes_remaining(tsi_ssl_handshaker* impl,
unsigned char** bytes_remaining,
size_t* bytes_remaining_size,
std::string* error) { … }
static tsi_result ssl_handshaker_write_output_buffer(tsi_handshaker* self,
size_t* bytes_written,
std::string* error) { … }
static tsi_result ssl_handshaker_next(tsi_handshaker* self,
const unsigned char* received_bytes,
size_t received_bytes_size,
const unsigned char** bytes_to_send,
size_t* bytes_to_send_size,
tsi_handshaker_result** handshaker_result,
tsi_handshaker_on_next_done_cb ,
void* , std::string* error) { … }
static const tsi_handshaker_vtable handshaker_vtable = …;
static void tsi_ssl_handshaker_resume_session(
SSL* ssl, tsi::SslSessionLRUCache* session_cache) { … }
static tsi_result create_tsi_ssl_handshaker(SSL_CTX* ctx, int is_client,
const char* server_name_indication,
size_t network_bio_buf_size,
size_t ssl_bio_buf_size,
tsi_ssl_handshaker_factory* factory,
tsi_handshaker** handshaker) { … }
static int select_protocol_list(const unsigned char** out,
unsigned char* outlen,
const unsigned char* client_list,
size_t client_list_len,
const unsigned char* server_list,
size_t server_list_len) { … }
tsi_result tsi_ssl_client_handshaker_factory_create_handshaker(
tsi_ssl_client_handshaker_factory* factory,
const char* server_name_indication, size_t network_bio_buf_size,
size_t ssl_bio_buf_size, tsi_handshaker** handshaker) { … }
void tsi_ssl_client_handshaker_factory_unref(
tsi_ssl_client_handshaker_factory* factory) { … }
static void tsi_ssl_client_handshaker_factory_destroy(
tsi_ssl_handshaker_factory* factory) { … }
static int client_handshaker_factory_npn_callback(
SSL* , unsigned char** out, unsigned char* outlen,
const unsigned char* in, unsigned int inlen, void* arg) { … }
tsi_result tsi_ssl_server_handshaker_factory_create_handshaker(
tsi_ssl_server_handshaker_factory* factory, size_t network_bio_buf_size,
size_t ssl_bio_buf_size, tsi_handshaker** handshaker) { … }
void tsi_ssl_server_handshaker_factory_unref(
tsi_ssl_server_handshaker_factory* factory) { … }
static void tsi_ssl_server_handshaker_factory_destroy(
tsi_ssl_handshaker_factory* factory) { … }
static int does_entry_match_name(absl::string_view entry,
absl::string_view name) { … }
static int ssl_server_handshaker_factory_servername_callback(SSL* ssl,
int* ,
void* arg) { … }
#if TSI_OPENSSL_ALPN_SUPPORT
static int server_handshaker_factory_alpn_callback(
SSL* , const unsigned char** out, unsigned char* outlen,
const unsigned char* in, unsigned int inlen, void* arg) { … }
#endif
static int server_handshaker_factory_npn_advertised_callback(
SSL* , const unsigned char** out, unsigned int* outlen, void* arg) { … }
static int server_handshaker_factory_new_session_callback(
SSL* ssl, SSL_SESSION* session) { … }
template <typename T>
static void ssl_keylogging_callback(const SSL* ssl, const char* info) { … }
static tsi_ssl_handshaker_factory_vtable client_handshaker_factory_vtable = …;
tsi_result tsi_create_ssl_client_handshaker_factory(
const tsi_ssl_pem_key_cert_pair* pem_key_cert_pair,
const char* pem_root_certs, const char* cipher_suites,
const char** alpn_protocols, uint16_t num_alpn_protocols,
tsi_ssl_client_handshaker_factory** factory) { … }
tsi_result tsi_create_ssl_client_handshaker_factory_with_options(
const tsi_ssl_client_handshaker_options* options,
tsi_ssl_client_handshaker_factory** factory) { … }
static tsi_ssl_handshaker_factory_vtable server_handshaker_factory_vtable = …;
tsi_result tsi_create_ssl_server_handshaker_factory(
const tsi_ssl_pem_key_cert_pair* pem_key_cert_pairs,
size_t num_key_cert_pairs, const char* pem_client_root_certs,
int force_client_auth, const char* cipher_suites,
const char** alpn_protocols, uint16_t num_alpn_protocols,
tsi_ssl_server_handshaker_factory** factory) { … }
tsi_result tsi_create_ssl_server_handshaker_factory_ex(
const tsi_ssl_pem_key_cert_pair* pem_key_cert_pairs,
size_t num_key_cert_pairs, const char* pem_client_root_certs,
tsi_client_certificate_request_type client_certificate_request,
const char* cipher_suites, const char** alpn_protocols,
uint16_t num_alpn_protocols, tsi_ssl_server_handshaker_factory** factory) { … }
tsi_result tsi_create_ssl_server_handshaker_factory_with_options(
const tsi_ssl_server_handshaker_options* options,
tsi_ssl_server_handshaker_factory** factory) { … }
int tsi_ssl_peer_matches_name(const tsi_peer* peer, absl::string_view name) { … }
const tsi_ssl_handshaker_factory_vtable* tsi_ssl_handshaker_factory_swap_vtable(
tsi_ssl_handshaker_factory* factory,
tsi_ssl_handshaker_factory_vtable* new_vtable) { … }