ssl: Allow inspection of SSL_CREDENTIAL completion status Before adding the credential to the connection or context, it would be nice if a builder pattern could inspect if the state of the credential is operationally ready. Signed-off-by: Xiangfei Ding <xfding@google.com> Change-Id: I1a10e0a01d1f2a851d31318730f545006a6a6964 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/90087 Reviewed-by: Adam Langley <agl@google.com> Reviewed-by: David Benjamin <davidben@google.com> Reviewed-by: Lily Chen <chlily@google.com>
diff --git a/include/openssl/prefix_symbols.h b/include/openssl/prefix_symbols.h index 95bf738..8a14395 100644 --- a/include/openssl/prefix_symbols.h +++ b/include/openssl/prefix_symbols.h
@@ -1836,6 +1836,7 @@ #pragma redefine_extname SSL_CREDENTIAL_free BORINGSSL_SYMBOL(BORINGSSL_ADD_PREFIX(SSL_CREDENTIAL_free)) #pragma redefine_extname SSL_CREDENTIAL_get_ex_data BORINGSSL_SYMBOL(BORINGSSL_ADD_PREFIX(SSL_CREDENTIAL_get_ex_data)) #pragma redefine_extname SSL_CREDENTIAL_get_ex_new_index BORINGSSL_SYMBOL(BORINGSSL_ADD_PREFIX(SSL_CREDENTIAL_get_ex_new_index)) +#pragma redefine_extname SSL_CREDENTIAL_is_complete BORINGSSL_SYMBOL(BORINGSSL_ADD_PREFIX(SSL_CREDENTIAL_is_complete)) #pragma redefine_extname SSL_CREDENTIAL_new_delegated BORINGSSL_SYMBOL(BORINGSSL_ADD_PREFIX(SSL_CREDENTIAL_new_delegated)) #pragma redefine_extname SSL_CREDENTIAL_new_spake2plusv1_client BORINGSSL_SYMBOL(BORINGSSL_ADD_PREFIX(SSL_CREDENTIAL_new_spake2plusv1_client)) #pragma redefine_extname SSL_CREDENTIAL_new_spake2plusv1_server BORINGSSL_SYMBOL(BORINGSSL_ADD_PREFIX(SSL_CREDENTIAL_new_spake2plusv1_server)) @@ -4897,6 +4898,7 @@ #define SSL_CREDENTIAL_free BORINGSSL_ADD_PREFIX(SSL_CREDENTIAL_free) #define SSL_CREDENTIAL_get_ex_data BORINGSSL_ADD_PREFIX(SSL_CREDENTIAL_get_ex_data) #define SSL_CREDENTIAL_get_ex_new_index BORINGSSL_ADD_PREFIX(SSL_CREDENTIAL_get_ex_new_index) +#define SSL_CREDENTIAL_is_complete BORINGSSL_ADD_PREFIX(SSL_CREDENTIAL_is_complete) #define SSL_CREDENTIAL_new_delegated BORINGSSL_ADD_PREFIX(SSL_CREDENTIAL_new_delegated) #define SSL_CREDENTIAL_new_spake2plusv1_client BORINGSSL_ADD_PREFIX(SSL_CREDENTIAL_new_spake2plusv1_client) #define SSL_CREDENTIAL_new_spake2plusv1_server BORINGSSL_ADD_PREFIX(SSL_CREDENTIAL_new_spake2plusv1_server)
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index 36c3e3a..430273e 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h
@@ -17,7 +17,7 @@ #ifndef OPENSSL_HEADER_SSL_H #define OPENSSL_HEADER_SSL_H -#include <openssl/base.h> // IWYU pragma: export +#include <openssl/base.h> // IWYU pragma: export #include <openssl/bio.h> #include <openssl/buf.h> @@ -802,6 +802,14 @@ // zero, all data referenced by |cred| and |cred| itself are released. OPENSSL_EXPORT void SSL_CREDENTIAL_free(SSL_CREDENTIAL *cred); +// SSL_CREDENTIAL_is_complete returns one if the returns one if |cred| has all +// required properties configured, and zero otherwise. +// +// This includes checks on whether the public key is present in a X.509 +// credential and whether a private key or private key method has been set up +// for such. +OPENSSL_EXPORT int SSL_CREDENTIAL_is_complete(const SSL_CREDENTIAL *cred); + // SSL_CREDENTIAL_set1_private_key sets |cred|'s private key to |cred|. It // returns one on success and zero on failure. OPENSSL_EXPORT int SSL_CREDENTIAL_set1_private_key(SSL_CREDENTIAL *cred,
diff --git a/ssl/ssl_credential.cc b/ssl/ssl_credential.cc index 5206fde..67fa8c3 100644 --- a/ssl/ssl_credential.cc +++ b/ssl/ssl_credential.cc
@@ -342,6 +342,10 @@ } } +int SSL_CREDENTIAL_is_complete(const SSL_CREDENTIAL *cred) { + return cred->IsComplete(); +} + int SSL_CREDENTIAL_set1_private_key(SSL_CREDENTIAL *cred, EVP_PKEY *key) { if (!cred->UsesPrivateKey()) { OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc index 2c8b000..008fd86 100644 --- a/ssl/ssl_test.cc +++ b/ssl/ssl_test.cc
@@ -5546,6 +5546,8 @@ ASSERT_TRUE(cred); bssl::UniquePtr<SSL_CREDENTIAL> cred2(SSL_CREDENTIAL_new_x509()); ASSERT_TRUE(cred2); + ASSERT_FALSE(SSL_CREDENTIAL_is_complete(cred.get())); + ASSERT_FALSE(SSL_CREDENTIAL_is_complete(cred2.get())); SSL_CTX_set_custom_verify(client_ctx.get(), SSL_VERIFY_PEER, AcceptAnyCertificate); @@ -5579,11 +5581,15 @@ ASSERT_TRUE(SSL_CREDENTIAL_set1_cert_chain(cred2.get(), test_chain.data(), test_chain.size())); + ASSERT_FALSE(SSL_CREDENTIAL_is_complete(cred.get())); + ASSERT_FALSE(SSL_CREDENTIAL_is_complete(cred2.get())); ASSERT_TRUE(SSL_CREDENTIAL_set1_private_key(cred.get(), key.get())); ASSERT_TRUE(SSL_CREDENTIAL_set1_private_key(cred2.get(), testkey.get())); SSL_CREDENTIAL_set_must_match_issuer(cred.get(), 1); SSL_CREDENTIAL_set_must_match_issuer(cred2.get(), 1); + ASSERT_TRUE(SSL_CREDENTIAL_is_complete(cred.get())); + ASSERT_TRUE(SSL_CREDENTIAL_is_complete(cred2.get())); ASSERT_TRUE(SSL_CTX_add1_credential(server_ctx.get(), cred.get())); ASSERT_TRUE(SSL_CTX_add1_credential(server_ctx.get(), cred2.get())); @@ -5646,6 +5652,7 @@ // Add cred3 to the CTX so we have an ubiquitous credential bssl::UniquePtr<SSL_CREDENTIAL> cred3(SSL_CREDENTIAL_new_x509()); ASSERT_TRUE(cred3); + ASSERT_FALSE(SSL_CREDENTIAL_is_complete(cred3.get())); ASSERT_TRUE( SSL_CREDENTIAL_set1_cert_chain(cred3.get(), chain.data(), chain.size())); ASSERT_TRUE(SSL_CREDENTIAL_set1_private_key(cred3.get(), key.get())); @@ -5664,6 +5671,7 @@ // unknown property 0xbb with 0 bytes of data. bssl::UniquePtr<SSL_CREDENTIAL> cred(SSL_CREDENTIAL_new_x509()); ASSERT_TRUE(cred); + ASSERT_FALSE(SSL_CREDENTIAL_is_complete(cred.get())); static const uint8_t kTestProperties1[] = {0x00, 0x0b, 0x00, 0x00, 0x00, 0x03, 0xba, 0xdb, 0x0b, 0x00, 0xbb, 0x00, 0x00};