Don't crash if QuicServerConfigProtobuf is invalid. Return an error indication (false) if no keys are passed to CryptoSecretBoxer::SetKeys, rather than corrupting the state of the boxer, which would later result in a crash. PiperOrigin-RevId: 416130497
diff --git a/quic/core/crypto/crypto_secret_boxer.cc b/quic/core/crypto/crypto_secret_boxer.cc index 1826212..a4a7a2a 100644 --- a/quic/core/crypto/crypto_secret_boxer.cc +++ b/quic/core/crypto/crypto_secret_boxer.cc
@@ -44,8 +44,11 @@ // kAEAD is the AEAD used for boxing: AES-256-GCM-SIV. static const EVP_AEAD* (*const kAEAD)() = EVP_aead_aes_256_gcm_siv; -void CryptoSecretBoxer::SetKeys(const std::vector<std::string>& keys) { - QUICHE_DCHECK(!keys.empty()); +bool CryptoSecretBoxer::SetKeys(const std::vector<std::string>& keys) { + if (keys.empty()) { + QUIC_LOG(DFATAL) << "No keys supplied!"; + return false; + } const EVP_AEAD* const aead = kAEAD(); std::unique_ptr<State> new_state(new State); @@ -57,7 +60,7 @@ if (!ctx) { ERR_clear_error(); QUIC_LOG(DFATAL) << "EVP_AEAD_CTX_init failed"; - return; + return false; } new_state->ctxs.push_back(std::move(ctx)); @@ -65,6 +68,7 @@ QuicWriterMutexLock l(&lock_); state_ = std::move(new_state); + return true; } std::string CryptoSecretBoxer::Box(QuicRandom* rand,
diff --git a/quic/core/crypto/crypto_secret_boxer.h b/quic/core/crypto/crypto_secret_boxer.h index 5dd5cb2..e2cd037 100644 --- a/quic/core/crypto/crypto_secret_boxer.h +++ b/quic/core/crypto/crypto_secret_boxer.h
@@ -34,13 +34,15 @@ // SetKeys sets a list of encryption keys. The first key in the list will be // used by |Box|, but all supplied keys will be tried by |Unbox|, to handle // key skew across the fleet. This must be called before |Box| or |Unbox|. - // Keys must be |GetKeySize()| bytes long. - void SetKeys(const std::vector<std::string>& keys); + // Keys must be |GetKeySize()| bytes long. No change is made if any key is + // invalid, or if there are no keys supplied. + bool SetKeys(const std::vector<std::string>& keys); // Box encrypts |plaintext| using a random nonce generated from |rand| and // returns the resulting ciphertext. Since an authenticator and nonce are // included, the result will be slightly larger than |plaintext|. The first - // key in the vector supplied to |SetKeys| will be used. + // key in the vector supplied to |SetKeys| will be used. |SetKeys| must be + // called before calling this method. std::string Box(QuicRandom* rand, absl::string_view plaintext) const; // Unbox takes the result of a previous call to |Box| in |ciphertext| and
diff --git a/quic/core/crypto/crypto_secret_boxer_test.cc b/quic/core/crypto/crypto_secret_boxer_test.cc index 225bfc8..7b07d96 100644 --- a/quic/core/crypto/crypto_secret_boxer_test.cc +++ b/quic/core/crypto/crypto_secret_boxer_test.cc
@@ -56,9 +56,9 @@ std::string key_12(CryptoSecretBoxer::GetKeySize(), 0x12); CryptoSecretBoxer boxer_11, boxer_12, boxer; - boxer_11.SetKeys({key_11}); - boxer_12.SetKeys({key_12}); - boxer.SetKeys({key_12, key_11}); + EXPECT_TRUE(boxer_11.SetKeys({key_11})); + EXPECT_TRUE(boxer_12.SetKeys({key_12})); + EXPECT_TRUE(boxer.SetKeys({key_12, key_11})); // Neither single-key boxer can decode the other's tokens. EXPECT_FALSE(CanDecode(boxer_11, boxer_12)); @@ -74,7 +74,7 @@ // After we flush key_11 from |boxer|, it can no longer decode tokens from // |boxer_11|. - boxer.SetKeys({key_12}); + EXPECT_TRUE(boxer.SetKeys({key_12})); EXPECT_FALSE(CanDecode(boxer, boxer_11)); }
diff --git a/quic/core/crypto/quic_crypto_server_config.cc b/quic/core/crypto/quic_crypto_server_config.cc index d6eebbb..e8ac18e 100644 --- a/quic/core/crypto/quic_crypto_server_config.cc +++ b/quic/core/crypto/quic_crypto_server_config.cc
@@ -512,6 +512,7 @@ void QuicCryptoServerConfig::SetSourceAddressTokenKeys( const std::vector<std::string>& keys) { + // TODO(b/208866709) source_address_token_boxer_.SetKeys(keys); } @@ -1576,9 +1577,14 @@ std::unique_ptr<CryptoHandshakeMessage> msg = CryptoFramer::ParseMessage(protobuf.config()); + if (!msg) { + QUIC_LOG(WARNING) << "Failed to parse server config message"; + return nullptr; + } + if (msg->tag() != kSCFG) { QUIC_LOG(WARNING) << "Server config message has tag " << msg->tag() - << " expected " << kSCFG; + << ", but expected " << kSCFG; return nullptr; }