aboutsummaryrefslogtreecommitdiff
path: root/cast/sender
diff options
context:
space:
mode:
authorJordan Bayles <jophba@chromium.org>2020-09-25 18:09:11 -0700
committerJordan Bayles <jophba@chromium.org>2020-09-26 01:40:32 +0000
commitbdf73b44be2e06106b3ac8c2b7f71a89b055d351 (patch)
tree9286629f4b0220950984373c557fec94edd0f6c6 /cast/sender
parentce233ef0eb7fe3ffb1a0160308daab8380526552 (diff)
downloadopenscreen-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.cc10
-rw-r--r--cast/sender/channel/cast_auth_util_unittest.cc45
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: