diff options
author | Jordan Bayles <jophba@chromium.org> | 2020-09-25 18:09:11 -0700 |
---|---|---|
committer | Jordan Bayles <jophba@chromium.org> | 2020-09-26 01:40:32 +0000 |
commit | bdf73b44be2e06106b3ac8c2b7f71a89b055d351 (patch) | |
tree | 9286629f4b0220950984373c557fec94edd0f6c6 /cast/sender | |
parent | ce233ef0eb7fe3ffb1a0160308daab8380526552 (diff) | |
download | openscreen-bdf73b44be2e06106b3ac8c2b7f71a89b055d351.tar.gz |
Fixup standalone_{receiver, sender}
Currently the cast sender and receiver cannot connect because the
receiver cannot present a CA-signed certificate due to not being able to
set the private key or use a self signed certificate.
This patch adds support for setting these arguments on both the cast
sender and receiver, as well as some fixes found through manual testing.
Total changelist:
1. Refactored testing code for reading certificates and private keys to share
with the standalone sender, receiver.
2. Refactored TrustStore and CastTrustStore to allow self signed certificates and
usage by the Cast Sender.
3. Updated the UDP socket POSIX implementation to allow reading--the previous
implementation cannot read packets.
4. Updated certificate validation to work with the self signed certificates
in the trust store.
5. Updated documentation.
Example usage:
$ ./out/Default/cast_sender -s cast_streaming.crt -v ~/video-1080-mp4.mp4
$ ./out/Default/cast_receiver lo0 -v -x -p cast_streaming_rsa -s cast_streaming.crt
Bug: b/156995806
Change-Id: I6e31e66beff33c260e467290f454ec1dcc758660
Reviewed-on: https://chromium-review.googlesource.com/c/openscreen/+/2426996
Commit-Queue: Jordan Bayles <jophba@chromium.org>
Reviewed-by: Yuri Wiitala <miu@chromium.org>
Diffstat (limited to 'cast/sender')
-rw-r--r-- | cast/sender/channel/cast_auth_util.cc | 10 | ||||
-rw-r--r-- | cast/sender/channel/cast_auth_util_unittest.cc | 45 |
2 files changed, 30 insertions, 25 deletions
diff --git a/cast/sender/channel/cast_auth_util.cc b/cast/sender/channel/cast_auth_util.cc index 10cbdc45..cb1ced69 100644 --- a/cast/sender/channel/cast_auth_util.cc +++ b/cast/sender/channel/cast_auth_util.cc @@ -7,6 +7,7 @@ #include <openssl/rand.h> #include <algorithm> +#include <memory> #include "cast/common/certificate/cast_cert_validator.h" #include "cast/common/certificate/cast_cert_validator_internal.h" @@ -29,13 +30,13 @@ namespace { #define PARSE_ERROR_PREFIX "Failed to parse auth message: " // The maximum number of days a cert can live for. -const int kMaxSelfSignedCertLifetimeInDays = 4; +constexpr int kMaxSelfSignedCertLifetimeInDays = 4; // The size of the nonce challenge in bytes. -const int kNonceSizeInBytes = 16; +constexpr int kNonceSizeInBytes = 16; // The number of hours after which a nonce is regenerated. -long kNonceExpirationTimeInHours = 24; +constexpr int kNonceExpirationTimeInHours = 24; // Extracts an embedded DeviceAuthMessage payload from an auth challenge reply // message. @@ -122,6 +123,9 @@ Error MapToOpenscreenError(Error::Code error, bool crl_required) { case Error::Code::kErrCertsRestrictions: return Error(Error::Code::kCastV2CertNotSignedByTrustedCa, "Failed certificate restrictions."); + case Error::Code::kErrCertsVerifyUntrustedCert: + return Error(Error::Code::kCastV2CertNotSignedByTrustedCa, + "Failed with untrusted certificate."); case Error::Code::kErrCrlInvalid: // This error is only encountered if |crl_required| is true. OSP_DCHECK(crl_required); diff --git a/cast/sender/channel/cast_auth_util_unittest.cc b/cast/sender/channel/cast_auth_util_unittest.cc index 03655419..acdb07a2 100644 --- a/cast/sender/channel/cast_auth_util_unittest.cc +++ b/cast/sender/channel/cast_auth_util_unittest.cc @@ -15,6 +15,7 @@ #include "platform/api/time.h" #include "platform/test/paths.h" #include "testing/util/read_file.h" +#include "util/crypto/pem_helpers.h" #include "util/osp_logging.h" namespace openscreen { @@ -124,7 +125,7 @@ class CastAuthUtilTest : public ::testing::Test { static AuthResponse CreateAuthResponse( std::vector<uint8_t>* signed_data, ::cast::channel::HashAlgorithm digest_algorithm) { - std::vector<std::string> chain = testing::ReadCertificatesFromPemFile( + std::vector<std::string> chain = ReadCertificatesFromPemFile( GetSpecificTestDataPath() + "certificates/chromecast_gen1.pem"); OSP_CHECK(!chain.empty()); @@ -292,7 +293,7 @@ TEST_F(CastAuthUtilTest, VerifySenderNonceMissing) { } TEST_F(CastAuthUtilTest, VerifyTLSCertificateSuccess) { - std::vector<std::string> tls_cert_der = testing::ReadCertificatesFromPemFile( + std::vector<std::string> tls_cert_der = ReadCertificatesFromPemFile( data_path_ + "certificates/test_tls_cert.pem"); std::string& der_cert = tls_cert_der[0]; const uint8_t* data = (const uint8_t*)der_cert.data(); @@ -310,7 +311,7 @@ TEST_F(CastAuthUtilTest, VerifyTLSCertificateSuccess) { } TEST_F(CastAuthUtilTest, VerifyTLSCertificateTooEarly) { - std::vector<std::string> tls_cert_der = testing::ReadCertificatesFromPemFile( + std::vector<std::string> tls_cert_der = ReadCertificatesFromPemFile( data_path_ + "certificates/test_tls_cert.pem"); std::string& der_cert = tls_cert_der[0]; const uint8_t* data = (const uint8_t*)der_cert.data(); @@ -331,7 +332,7 @@ TEST_F(CastAuthUtilTest, VerifyTLSCertificateTooEarly) { } TEST_F(CastAuthUtilTest, VerifyTLSCertificateTooLate) { - std::vector<std::string> tls_cert_der = testing::ReadCertificatesFromPemFile( + std::vector<std::string> tls_cert_der = ReadCertificatesFromPemFile( data_path_ + "certificates/test_tls_cert.pem"); std::string& der_cert = tls_cert_der[0]; const uint8_t* data = (const uint8_t*)der_cert.data(); @@ -392,16 +393,16 @@ ErrorOr<CastDeviceCertPolicy> TestVerifyRevocation( // Runs a single test case. bool RunTest(const DeviceCertTest& test_case) { - std::unique_ptr<TrustStore> crl_trust_store; - std::unique_ptr<TrustStore> cast_trust_store; + TrustStore crl_trust_store; + TrustStore cast_trust_store; if (test_case.use_test_trust_anchors()) { - crl_trust_store = testing::CreateTrustStoreFromPemFile( + crl_trust_store = TrustStore::CreateInstanceFromPemFile( GetSpecificTestDataPath() + "certificates/cast_crl_test_root_ca.pem"); - cast_trust_store = testing::CreateTrustStoreFromPemFile( + cast_trust_store = TrustStore::CreateInstanceFromPemFile( GetSpecificTestDataPath() + "certificates/cast_test_root_ca.pem"); - EXPECT_FALSE(crl_trust_store->certs.empty()); - EXPECT_FALSE(cast_trust_store->certs.empty()); + EXPECT_FALSE(crl_trust_store.certs.empty()); + EXPECT_FALSE(cast_trust_store.certs.empty()); } std::vector<std::string> certificate_chain; @@ -421,9 +422,9 @@ bool RunTest(const DeviceCertTest& test_case) { ErrorOr<CastDeviceCertPolicy> result(CastDeviceCertPolicy::kUnrestricted); switch (test_case.expected_result()) { case ::cast::certificate::PATH_VERIFICATION_FAILED: - result = TestVerifyRevocation( - certificate_chain, crl_bundle, verification_time, false, - cast_trust_store.get(), crl_trust_store.get()); + result = + TestVerifyRevocation(certificate_chain, crl_bundle, verification_time, + false, &cast_trust_store, &cast_trust_store); EXPECT_EQ(result.error().code(), Error::Code::kCastV2CertNotSignedByTrustedCa); return result.error().code() == @@ -431,9 +432,9 @@ bool RunTest(const DeviceCertTest& test_case) { case ::cast::certificate::CRL_VERIFICATION_FAILED: // Fall-through intended. case ::cast::certificate::REVOCATION_CHECK_FAILED_WITHOUT_CRL: - result = TestVerifyRevocation( - certificate_chain, crl_bundle, verification_time, true, - cast_trust_store.get(), crl_trust_store.get()); + result = + TestVerifyRevocation(certificate_chain, crl_bundle, verification_time, + true, &cast_trust_store, &cast_trust_store); EXPECT_EQ(result.error().code(), Error::Code::kErrCrlInvalid); return result.error().code() == Error::Code::kErrCrlInvalid; case ::cast::certificate::CRL_EXPIRED_AFTER_INITIAL_VERIFICATION: @@ -441,15 +442,15 @@ bool RunTest(const DeviceCertTest& test_case) { // certificate is verified. return true; case ::cast::certificate::REVOCATION_CHECK_FAILED: - result = TestVerifyRevocation( - certificate_chain, crl_bundle, verification_time, true, - cast_trust_store.get(), crl_trust_store.get()); + result = + TestVerifyRevocation(certificate_chain, crl_bundle, verification_time, + true, &cast_trust_store, &cast_trust_store); EXPECT_EQ(result.error().code(), Error::Code::kErrCertsRevoked); return result.error().code() == Error::Code::kErrCertsRevoked; case ::cast::certificate::SUCCESS: - result = TestVerifyRevocation( - certificate_chain, crl_bundle, verification_time, false, - cast_trust_store.get(), crl_trust_store.get()); + result = + TestVerifyRevocation(certificate_chain, crl_bundle, verification_time, + false, &cast_trust_store, &cast_trust_store); EXPECT_EQ(result.error().code(), Error::Code::kCastV2SignedBlobsMismatch); return result.error().code() == Error::Code::kCastV2SignedBlobsMismatch; case ::cast::certificate::UNSPECIFIED: |