From 9a350eddbda4719a3502745314a42d241b68155e Mon Sep 17 00:00:00 2001 From: Rahul Frias Date: Sat, 13 Mar 2021 02:18:56 -0800 Subject: [PATCH] Extract creation and expiration times from DRM cert [ Merge of http://go/wvgerrit/119843 ] Creation and expiration times are extracted from the device DRM certificate. They are reported as * -1 if not set in the proto * 0 if unlimited * positive number otherwise Bug: 169740403 Test: WV unit, integraiton tests Change-Id: I9463954dfeb82b6a88ff5d608ed74d20f2424e83 --- .../core/include/certificate_provisioning.h | 8 +- .../cdm/core/include/wv_cdm_constants.h | 1 + .../cdm/core/src/certificate_provisioning.cpp | 13 ++- libwvdrmengine/cdm/core/src/device_files.cpp | 3 +- .../certificate_provisioning_unittest.cpp | 104 +++++++++++++++--- .../cdm/test/request_license_test.cpp | 3 +- 6 files changed, 113 insertions(+), 19 deletions(-) diff --git a/libwvdrmengine/cdm/core/include/certificate_provisioning.h b/libwvdrmengine/cdm/core/include/certificate_provisioning.h index 8766de81..afdc4770 100644 --- a/libwvdrmengine/cdm/core/include/certificate_provisioning.h +++ b/libwvdrmengine/cdm/core/include/certificate_provisioning.h @@ -54,9 +54,13 @@ class CertificateProvisioning { // Extract serial number and system ID from a DRM Device certificate. // Either |serial_number| or |system_id| may be null, but not both. + // Both |creation_time_seconds| and |expiration_time_seconds| may be null. + // |creation_time_seconds| and |expiration_time_seconds| will be set to -1 + // if not present, 0 if unlimited and a valid time otherwise static bool ExtractDeviceInfo(const std::string& device_certificate, - std::string* serial_number, - uint32_t* system_id); + std::string* serial_number, uint32_t* system_id, + int64_t* creation_time_seconds, + int64_t* expiration_time_seconds); // Removes json wrapping if applicable to extract the // SignedProvisioningMessage diff --git a/libwvdrmengine/cdm/core/include/wv_cdm_constants.h b/libwvdrmengine/cdm/core/include/wv_cdm_constants.h index bf22fd80..22c70283 100644 --- a/libwvdrmengine/cdm/core/include/wv_cdm_constants.h +++ b/libwvdrmengine/cdm/core/include/wv_cdm_constants.h @@ -26,6 +26,7 @@ static const size_t CERTIFICATE_DATA_SIZE = 4 * 1024; // (NaN in JS translates to 0 in unix timestamp). static const int64_t NEVER_EXPIRES = 0; static const int64_t UNLIMITED_DURATION = 0; +static const int64_t INVALID_TIME = -1; // This is the lower limit. For OEMCrypto v16+ one can query and find how many // are supported diff --git a/libwvdrmengine/cdm/core/src/certificate_provisioning.cpp b/libwvdrmengine/cdm/core/src/certificate_provisioning.cpp index 8357232a..27e01b9f 100644 --- a/libwvdrmengine/cdm/core/src/certificate_provisioning.cpp +++ b/libwvdrmengine/cdm/core/src/certificate_provisioning.cpp @@ -500,7 +500,8 @@ bool CertificateProvisioning::ExtractAndDecodeSignedMessageForTesting( bool CertificateProvisioning::ExtractDeviceInfo( const std::string& device_certificate, std::string* serial_number, - uint32_t* system_id) { + uint32_t* system_id, int64_t* creation_time_seconds, + int64_t* expiration_time_seconds) { LOGV("Extracting device info"); if (serial_number == nullptr && system_id == nullptr) { LOGE("Output parameters |serial_number| and |system_id| not provided"); @@ -527,6 +528,16 @@ bool CertificateProvisioning::ExtractDeviceInfo( if (system_id != nullptr) { *system_id = drm_certificate.system_id(); } + if (creation_time_seconds != nullptr) { + *creation_time_seconds = drm_certificate.has_creation_time_seconds() + ? drm_certificate.creation_time_seconds() + : INVALID_TIME; + } + if (expiration_time_seconds != nullptr) { + *expiration_time_seconds = drm_certificate.has_expiration_time_seconds() + ? drm_certificate.expiration_time_seconds() + : INVALID_TIME; + } return true; } diff --git a/libwvdrmengine/cdm/core/src/device_files.cpp b/libwvdrmengine/cdm/core/src/device_files.cpp index 807681fb..8fcea5e8 100644 --- a/libwvdrmengine/cdm/core/src/device_files.cpp +++ b/libwvdrmengine/cdm/core/src/device_files.cpp @@ -214,7 +214,8 @@ bool DeviceFiles::RetrieveCertificate(bool atsc_mode_enabled, } return CertificateProvisioning::ExtractDeviceInfo( - device_certificate.certificate(), serial_number, system_id); + device_certificate.certificate(), serial_number, system_id, nullptr, + nullptr); } bool DeviceFiles::HasCertificate(bool atsc_mode_enabled) { diff --git a/libwvdrmengine/cdm/core/test/certificate_provisioning_unittest.cpp b/libwvdrmengine/cdm/core/test/certificate_provisioning_unittest.cpp index aaf00974..4ba4c3e1 100644 --- a/libwvdrmengine/cdm/core/test/certificate_provisioning_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/certificate_provisioning_unittest.cpp @@ -17,17 +17,37 @@ namespace { const std::string kSignedDeviceCertificate = wvcdm::a2bs_hex( - "0A350802121B7769646576696E655F746573745F73657269616C5F6E756D62657228D2093A" - "11746573742E7769646576696E652E636F6D12097369676E6174757265"); + "0A3D0802121B7769646576696E655F746573745F73657269616C5F6E756D62657218C09A0C" + "28D2093A11746573742E7769646576696E652E636F6D6080B51812097369676E617475726" + "5"); +const std::string kSignedDeviceCertificateCreationTimeUnlimited = + wvcdm::a2bs_hex( + "0A370802121B7769646576696E655F746573745F73657269616C5F6E756D6265721800" + "28D2093A11746573742E7769646576696E652E636F6D12097369676E6174757265"); +const std::string kSignedDeviceCertificateExpirationTimeInvalid = + wvcdm::a2bs_hex( + "0A390802121B7769646576696E655F746573745F73657269616C5F6E756D62657218C0" + "9A0C28D2093A11746573742E7769646576696E652E636F6D12097369676E617475726" + "5"); +const std::string kSignedDeviceCertificateExpirationTimeUnlimited = + wvcdm::a2bs_hex( + "0A3B0802121B7769646576696E655F746573745F73657269616C5F6E756D62657218C0" + "9A0C28D2093A11746573742E7769646576696E652E636F6D600012097369676E617475" + "7265"); const std::string kSignedDeviceCertificateInvalid = wvcdm::a2bs_hex( "76340802121B7769646576696E655F746573745F73657269616C5F6E756D62657228D2093A" "11746573742E7769646576696E652E636F6D12097369676E6174757265"); -const std::string kSignedDeviceCertificateNoDrmCertificate = - wvcdm::a2bs_hex("12097369676E6174757265"); const std::string kSignedDeviceCertificateInvalidCertificateType = wvcdm::a2bs_hex( "0A350801121B7769646576696E655F746573745F73657269616C5F6E756D62657228D2" "093A11746573742E7769646576696E652E636F6D12097369676E6174757265"); +const std::string kSignedDeviceCertificateNoDrmCertificate = + wvcdm::a2bs_hex("12097369676E6174757265"); +const std::string kSignedDeviceCertificateTimesInvalid = wvcdm::a2bs_hex( + "0A350802121B7769646576696E655F746573745F73657269616C5F6E756D62657228D2093A" + "11746573742E7769646576696E652E636F6D12097369676E6174757265"); +const int64_t kCreationTime = 200000; +const int64_t kExpirationTime = 400000; const std::string kSerialNumber = "widevine_test_serial_number"; const uint32_t kSystemId = 1234; @@ -91,17 +111,20 @@ TEST_F(CertificateProvisioningTest, ExtractDeviceInfo_InvalidInput) { uint32_t system_id; EXPECT_FALSE(certificate_provisioning_->ExtractDeviceInfo( - kSignedDeviceCertificate, nullptr, nullptr)); + kSignedDeviceCertificate, nullptr, nullptr, nullptr, nullptr)); + + int64_t creation_time_seconds, expiration_time_seconds; + EXPECT_FALSE(certificate_provisioning_->ExtractDeviceInfo( + kSignedDeviceCertificateInvalid, &serial_number, &system_id, + &creation_time_seconds, &expiration_time_seconds)); EXPECT_FALSE(certificate_provisioning_->ExtractDeviceInfo( - kSignedDeviceCertificateInvalid, &serial_number, &system_id)); - - EXPECT_FALSE(certificate_provisioning_->ExtractDeviceInfo( - kSignedDeviceCertificateNoDrmCertificate, &serial_number, &system_id)); + kSignedDeviceCertificateNoDrmCertificate, &serial_number, &system_id, + &creation_time_seconds, &expiration_time_seconds)); EXPECT_FALSE(certificate_provisioning_->ExtractDeviceInfo( kSignedDeviceCertificateInvalidCertificateType, &serial_number, - &system_id)); + &system_id, &creation_time_seconds, &expiration_time_seconds)); } // Tests ExtractDeviceInfo success scenarios @@ -111,19 +134,72 @@ TEST_F(CertificateProvisioningTest, ExtractDeviceInfo_InvalidInput) { TEST_F(CertificateProvisioningTest, ExtractDeviceInfo) { std::string serial_number; uint32_t system_id; + int64_t creation_time_seconds, expiration_time_seconds; EXPECT_TRUE(certificate_provisioning_->ExtractDeviceInfo( - kSignedDeviceCertificate, &serial_number, &system_id)); + kSignedDeviceCertificateTimesInvalid, &serial_number, &system_id, + &creation_time_seconds, &expiration_time_seconds)); EXPECT_EQ(kSerialNumber, serial_number); EXPECT_EQ(kSystemId, system_id); + EXPECT_EQ(INVALID_TIME, creation_time_seconds); + EXPECT_EQ(INVALID_TIME, expiration_time_seconds); + + EXPECT_TRUE(certificate_provisioning_->ExtractDeviceInfo( + kSignedDeviceCertificateTimesInvalid, nullptr, &system_id, nullptr, + nullptr)); + EXPECT_EQ(kSystemId, system_id); EXPECT_TRUE(certificate_provisioning_->ExtractDeviceInfo( - kSignedDeviceCertificate, nullptr, &system_id)); - EXPECT_EQ(kSystemId, system_id); + kSignedDeviceCertificateTimesInvalid, &serial_number, nullptr, nullptr, + nullptr)); + EXPECT_EQ(kSerialNumber, serial_number); EXPECT_TRUE(certificate_provisioning_->ExtractDeviceInfo( - kSignedDeviceCertificate, &serial_number, nullptr)); + kSignedDeviceCertificateCreationTimeUnlimited, &serial_number, &system_id, + &creation_time_seconds, &expiration_time_seconds)); EXPECT_EQ(kSerialNumber, serial_number); + EXPECT_EQ(kSystemId, system_id); + EXPECT_EQ(UNLIMITED_DURATION, creation_time_seconds); + EXPECT_EQ(INVALID_TIME, expiration_time_seconds); + + EXPECT_TRUE(certificate_provisioning_->ExtractDeviceInfo( + kSignedDeviceCertificateExpirationTimeInvalid, &serial_number, &system_id, + &creation_time_seconds, &expiration_time_seconds)); + EXPECT_EQ(kSerialNumber, serial_number); + EXPECT_EQ(kSystemId, system_id); + EXPECT_EQ(kCreationTime, creation_time_seconds); + EXPECT_EQ(INVALID_TIME, expiration_time_seconds); + + EXPECT_TRUE(certificate_provisioning_->ExtractDeviceInfo( + kSignedDeviceCertificateExpirationTimeUnlimited, &serial_number, + &system_id, &creation_time_seconds, &expiration_time_seconds)); + EXPECT_EQ(kSerialNumber, serial_number); + EXPECT_EQ(kSystemId, system_id); + EXPECT_EQ(kCreationTime, creation_time_seconds); + EXPECT_EQ(UNLIMITED_DURATION, expiration_time_seconds); + + EXPECT_TRUE(certificate_provisioning_->ExtractDeviceInfo( + kSignedDeviceCertificate, &serial_number, &system_id, + &creation_time_seconds, &expiration_time_seconds)); + EXPECT_EQ(kSerialNumber, serial_number); + EXPECT_EQ(kSystemId, system_id); + EXPECT_EQ(kCreationTime, creation_time_seconds); + EXPECT_EQ(kExpirationTime, expiration_time_seconds); + + EXPECT_TRUE(certificate_provisioning_->ExtractDeviceInfo( + kSignedDeviceCertificate, &serial_number, &system_id, nullptr, + &expiration_time_seconds)); + EXPECT_EQ(kSerialNumber, serial_number); + EXPECT_EQ(kSystemId, system_id); + EXPECT_EQ(kExpirationTime, expiration_time_seconds); + + EXPECT_TRUE(certificate_provisioning_->ExtractDeviceInfo( + kSignedDeviceCertificateExpirationTimeUnlimited, &serial_number, + &system_id, &creation_time_seconds, nullptr)); + EXPECT_EQ(kSerialNumber, serial_number); + EXPECT_EQ(kSystemId, system_id); + EXPECT_EQ(kCreationTime, creation_time_seconds); + EXPECT_EQ(kExpirationTime, expiration_time_seconds); } } // namespace wvcdm diff --git a/libwvdrmengine/cdm/test/request_license_test.cpp b/libwvdrmengine/cdm/test/request_license_test.cpp index e0598ea9..83586654 100644 --- a/libwvdrmengine/cdm/test/request_license_test.cpp +++ b/libwvdrmengine/cdm/test/request_license_test.cpp @@ -2151,7 +2151,8 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase { } if (!CertificateProvisioning::ExtractDeviceInfo( - prov_response.device_certificate(), serial_number, nullptr)) { + prov_response.device_certificate(), serial_number, nullptr, nullptr, + nullptr)) { EXPECT_TRUE(false); return false; }