Merges to android Pi release (part 12)

These are a set of CLs merged from the wv cdm repo to the android repo.

* Correct error logging

  Author: Rahul Frias <rfrias@google.com>

  [ Merge of http://go/wvgerrit/40000 ]

  In tests, we set the cipher list to avoid using insecure
  ciphers when connecting to the provisioning/license service.
  The result of setting the cipher list was being incorrectly
  validated.

  Bug: 64847919

* Move mips cache headers to clear_cache_function.h

  Author: Srujan Gaddam <srujzs@google.com>

  [ Merge of http://go/wvgerrit/39700 ]

  Since the clear_cache function has been moved away from the dynamic
  adapter, we need these conditional includes to be migrated as well for
  MIPS.

* Comment out Level 3 debug call until merge

  Author: Srujan Gaddam <srujzs@google.com>

  [ Merge of http://go/wvgerrit/39761 ]

  This call was introduced in go/wvgerrit/34260/. Since the haystack tool
  in google3 still needs this merge, this should be commented out so the
  tool can still build until the merge has finished.

* Add logging for MAC keys to mock

  Author: Srujan Gaddam <srujzs@google.com>

  [ Merge of http://go/wvgerrit/39740 ]

  Bug: 70637842

* Move external interfaces into level3.h + refactor

  Author: Srujan Gaddam <srujzs@google.com>

  [ Merge of http://go/wvgerrit/39673 ]

  As part of b/70523618, this CL moves interfaces that partners are
  responsible for in Level 3 to level3.h so they can be visible as
  part of the CDM release process. It also cleans up some of the
  names of the files and adds documentation.

* Corrected close session logging level

  Author: Rahul Frias <rfrias@google.com>

  [ Merge of http://go/wvgerrit/39676 ]

  Bug: 69460963

* Remove Security Level Path Backward Compatibility Support

  Author: Rahul Frias <rfrias@google.com>

  [ Merge of http://go/wvgerrit/39505 ]

  From the android K release onwards certificates were stored in
  security level specific directories. If upgrading from
  previous releases persistent information needed to be moved
  to those directories.

  Since no device is likely to upgrade from J to Pi, comptibility
  support can be removed.

  Bug: 70160032

* Rename privacy_crypto_openssl To privacy_crypto_boringssl

  Author: John W. Bruce <juce@google.com>

  [ Merge of http://go/wvgerrit/37122 ]

  Now that we no longer support OpenSSL in the Shared Source CDM, the name
  of this file can be updated.

  Bug: 67907873
  Test: build.py x86-64
  Test: wv_ce_cdm_unittest
  Test: jenkins/linux_unit_tests

* Remove Conditional Compilation from OpenSSL/BoringSSL

  Author: John W. Bruce <juce@google.com>

  [ Merge of http://go/wvgerrit/39460 ]

  This change removes the usages of conditional compilation to support
  both BoringSSL and OpenSSL, as well as to support multiple versions of
  the OpenSSL API. All code is now compiled against one of the two
  versions of BoringSSL in third_party/.

  Note that in some cases, the kit/ and legacy_kit/ versions of BoringSSL
  had different APIs, so when removing the OpenSSL version compatibility
  conditional compilation, sometimes the older branch was kept and
  sometimes the newer branch was kept.

  Bug: 67907873
  Test: build.py x86-64
  Test: wv_ce_cdm_unittest
  Test: jenkins/linux_unit_tests

* Build CE & Jenkins CDMs With BoringSSL from third_party/

  Author: John W. Bruce <juce@google.com>

  [ Merge of http://go/wvgerrit/37120 ]

  Up until now, integrators have been responsible for providing a
  compatible crypto library for use by the CE CDM. (either OpenSSL or
  BoringSSL) After this change, this decision will no longer be in their
  hands. The CE CDM build will always use the copy of BoringSSL in
  third_party/, which will be statically linked with our library with
  hidden visibility. This allows us to better control what crypto library
  we use and will prevent continuing problems with trying to support both
  OpenSSL and BoringSSL.

  Unfortunately, BoringSSL began using C++11 in mid-2017, and we can't
  support C++11 right now. Until we can, we need to use a C++11-free
  version of BoringSSL for libssl. The CDM itself will continue to use a
  recent BoringSSL, as it only needs libcrypto. But the unit tests that
  need libssl have to use the legacy version.

  Bug: 67907873
  Test: build.py x86-64
  Test: wv_ce_cdm_unittest
  Test: jenkins/linux_unit_tests

* Modified RNG for Level3 to use more entropy

  Author: Srujan Gaddam <srujzs@google.com>

  [ Merge of http://go/wvgerrit/39220 ]

  Bug: 65165076

  Modified seed generation to use an xor of clock_gettime and
  client-implemented code to supply random seeds to the RNG. Modified the RNG
  as well to use xoroshiro128+ instead of xorshift, since it uses more
  than one seed/state (which are 64-bit) and has higher "statistical quality".
  The default implementations for the seed generation use /dev/urandom.

* Configure base path for Level3FileSystem

  Author: Srujan Gaddam <srujzs@google.com>

  [ Merge of http://go/wvgerrit/39506 ]

  This is in response to b/70354006. This change makes the
  Android Level3FileSystem use the existing properties method
  GetDevicesFilesBasePath for binderization. The same is done for the
  Linux implementation.

* Add legacy_kit/ to BoringSSL Directory

  Author: John W. Bruce <juce@google.com>

  [ Merge of http://go/wvgerrit/38861 ]

  This adds a second copy of BoringSSL to the third_party/boringssl/
  directory. This second copy is pinned to the last revision of BoringSSL
  not to require C++11 and is not updated by the UPDATE_BORINGSSL.sh
  script. This second copy will be used to provide libssl to the tests on
  devices that do not support C++11.

  Once we support C++11 in the CDM again, this weight should be removed
  and all targets should use the copy of BoringSSL in the kit/ directory.

  Bug: 67907873

* Use Shared Libraries for Unit Tests

  Author: John W. Bruce <juce@google.com>

  [ Merge of http://go/wvgerrit/38860 ]

  Some unit tests were using a statically-linked CDM instead of a
  dynamically-linked one. (Or, in one case, trying to link both ways into
  the same binary.) For now, we need to only link dynamically, so that the
  unit tests and the CDM can use different versions of BoringSSL.

  Long-term, we would like to test both kinds of linkage. (See b/69548115
  for that.)

  Some unit tests were also using a dynamicaly-linked CDM that was named
  such that it appeared to be statically-linked. This patch renames some
  targets to make the linkage clearer.

  Bug: 67907873

* Change CDM_Backwards_Compatiblity_Tests to dedicated brances

  Author: Fred Gylys-Colwell <fredgc@google.com>

  [ Merge of http://go/wvgerrit/39003 ]

  The build scripts used by CDM_Backwards_Compatiblity_Tests now pull
  old versions of oemcrypto from the dedicated branches oemcrypto-v*,
  which [will eventually] contain old oemcrypto versions, that build
  with the current build system with a current boringssl version.

  bug: 67907873

* Fix spacing on level3 header

  Author: Srujan Gaddam <srujzs@google.com>

  [ Merge of http://go/wvgerrit/38760 ]

* Correct Query status calls

  Author: Rahul Frias <rfrias@google.com>

  [ Merge of http://go/wvgerrit/38640 ]

  Bug: 70160032

* Refactoring to allow encryption of client ID

  Author: Rahul Frias <rfrias@google.com>

  [ Merge of http://go/wvgerrit/37460 ]

  The code has been restructured to allow encryption of client
  identification in provisioning requests. This will be enabled
  when server side changes have been made (b/69427217).

  * Additional information is included in the Client Identification
    portion of the provisioning request.
  * Client identification will be encrypted with a service
    certificate provided by the app/client. Platform changes
    to enable passing this to core are needed. If a service certificate
    is not provided, a default one associated with the production Keysmith
    will be used.
  * Switched APIs in CdmEngine to take a service certificate for
    provisioning rather than licensing. Service certificates for
    licensing are session based and passed as properties from platform
    code.

  Bug: 30737060

* Allow some CDM errors to be reported from multiple locations

  Author: Rahul Frias <rfrias@google.com>

  [ Merge of http://go/wvgerrit/38360 ]

  This creates some CdmResponseType errors which may be reused
  PARAMETER_NULL, NOT_INITIALIZED_ERROR, REINIT_ERROR.

  I have made changes to a few classes to report these errors.
  Will work on additional classes in a separate CL.

  Bug: 69864404

BUG: 71650075
Test: WV Unit/integration tests
Change-Id: Icc048770d424ac537d11ff327cda2cb142da802d
This commit is contained in:
Rahul Frias
2018-01-10 23:54:59 -08:00
parent 5d690be108
commit aac1439dea
79 changed files with 582991 additions and 3305 deletions

View File

@@ -12,57 +12,58 @@
#include <stddef.h>
#include <stdint.h>
#include "level3_file_system.h"
#include "OEMCryptoCENC.h"
namespace wvoec3 {
#ifdef DYNAMIC_ADAPTER
#define Level3_IsInApp _lcc00
#define Level3_Initialize _lcc01
#define Level3_Terminate _lcc02
#define Level3_InstallKeybox _lcc03
#define Level3_GetKeyData _lcc04
#define Level3_IsKeyboxValid _lcc05
#define Level3_GetRandom _lcc06
#define Level3_GetDeviceID _lcc07
#define Level3_WrapKeybox _lcc08
#define Level3_OpenSession _lcc09
#define Level3_CloseSession _lcc10
#define Level3_DecryptCENC _lcc11
#define Level3_GenerateDerivedKeys _lcc12
#define Level3_GenerateSignature _lcc13
#define Level3_GenerateNonce _lcc14
#define Level3_RefreshKeys _lcc16
#define Level3_SelectKey _lcc17
#define Level3_RewrapDeviceRSAKey _lcc18
#define Level3_LoadDeviceRSAKey _lcc19
#define Level3_GenerateRSASignature _lcc20
#define Level3_DeriveKeysFromSessionKey _lcc21
#define Level3_APIVersion _lcc22
#define Level3_SecurityLevel _lcc23
#define Level3_Generic_Encrypt _lcc24
#define Level3_Generic_Decrypt _lcc25
#define Level3_Generic_Sign _lcc26
#define Level3_Generic_Verify _lcc27
#define Level3_GetHDCPCapability _lcc28
#define Level3_SupportsUsageTable _lcc29
#define Level3_UpdateUsageTable _lcc30
#define Level3_DeactivateUsageEntry _lcc31
#define Level3_ReportUsage _lcc32
#define Level3_DeleteUsageEntry _lcc33
#define Level3_DeleteOldUsageTable _lcc34
#define Level3_GetMaxNumberOfSessions _lcc37
#define Level3_GetNumberOfOpenSessions _lcc38
#define Level3_IsAntiRollbackHwPresent _lcc39
#define Level3_CopyBuffer _lcc40
#define Level3_QueryKeyControl _lcc41
#define Level3_LoadTestKeybox _lcc42
#define Level3_ForceDeleteUsageEntry _lcc43
#define Level3_LoadTestRSAKey _lcc45
#define Level3_SecurityPatchLevel _lcc46
#define Level3_GetProvisioningMethod _lcc49
#define Level3_GetOEMPublicCertificate _lcc50
#define Level3_RewrapDeviceRSAKey30 _lcc51
#define Level3_IsInApp _lcc00
#define Level3_Initialize _lcc01
#define Level3_Terminate _lcc02
#define Level3_InstallKeybox _lcc03
#define Level3_GetKeyData _lcc04
#define Level3_IsKeyboxValid _lcc05
#define Level3_GetRandom _lcc06
#define Level3_GetDeviceID _lcc07
#define Level3_WrapKeybox _lcc08
#define Level3_OpenSession _lcc09
#define Level3_CloseSession _lcc10
#define Level3_DecryptCENC _lcc11
#define Level3_GenerateDerivedKeys _lcc12
#define Level3_GenerateSignature _lcc13
#define Level3_GenerateNonce _lcc14
#define Level3_RefreshKeys _lcc16
#define Level3_SelectKey _lcc17
#define Level3_RewrapDeviceRSAKey _lcc18
#define Level3_LoadDeviceRSAKey _lcc19
#define Level3_GenerateRSASignature _lcc20
#define Level3_DeriveKeysFromSessionKey _lcc21
#define Level3_APIVersion _lcc22
#define Level3_SecurityLevel _lcc23
#define Level3_Generic_Encrypt _lcc24
#define Level3_Generic_Decrypt _lcc25
#define Level3_Generic_Sign _lcc26
#define Level3_Generic_Verify _lcc27
#define Level3_GetHDCPCapability _lcc28
#define Level3_SupportsUsageTable _lcc29
#define Level3_UpdateUsageTable _lcc30
#define Level3_DeactivateUsageEntry _lcc31
#define Level3_ReportUsage _lcc32
#define Level3_DeleteUsageEntry _lcc33
#define Level3_DeleteOldUsageTable _lcc34
#define Level3_GetMaxNumberOfSessions _lcc37
#define Level3_GetNumberOfOpenSessions _lcc38
#define Level3_IsAntiRollbackHwPresent _lcc39
#define Level3_CopyBuffer _lcc40
#define Level3_QueryKeyControl _lcc41
#define Level3_LoadTestKeybox _lcc42
#define Level3_ForceDeleteUsageEntry _lcc43
#define Level3_LoadTestRSAKey _lcc45
#define Level3_SecurityPatchLevel _lcc46
#define Level3_GetProvisioningMethod _lcc49
#define Level3_GetOEMPublicCertificate _lcc50
#define Level3_RewrapDeviceRSAKey30 _lcc51
#define Level3_SupportedCertificates _lcc52
#define Level3_IsSRMUpdateSupported _lcc53
#define Level3_GetCurrentSRMVersion _lcc54
@@ -79,50 +80,50 @@ namespace wvoec3 {
#define Level3_CopyOldUsageEntry _lcc69
#define Level3_CreateOldUsageEntry _lcc70
#else
#define Level3_Initialize _oecc01
#define Level3_Terminate _oecc02
#define Level3_InstallKeybox _oecc03
#define Level3_GetKeyData _oecc04
#define Level3_IsKeyboxValid _oecc05
#define Level3_GetRandom _oecc06
#define Level3_GetDeviceID _oecc07
#define Level3_WrapKeybox _oecc08
#define Level3_OpenSession _oecc09
#define Level3_CloseSession _oecc10
#define Level3_GenerateDerivedKeys _oecc12
#define Level3_GenerateSignature _oecc13
#define Level3_GenerateNonce _oecc14
#define Level3_RefreshKeys _oecc16
#define Level3_SelectKey _oecc17
#define Level3_RewrapDeviceRSAKey _oecc18
#define Level3_LoadDeviceRSAKey _oecc19
#define Level3_DeriveKeysFromSessionKey _oecc21
#define Level3_APIVersion _oecc22
#define Level3_SecurityLevel _oecc23
#define Level3_Generic_Encrypt _oecc24
#define Level3_Generic_Decrypt _oecc25
#define Level3_Generic_Sign _oecc26
#define Level3_Generic_Verify _oecc27
#define Level3_SupportsUsageTable _oecc29
#define Level3_UpdateUsageTable _oecc30
#define Level3_ReportUsage _oecc32
#define Level3_DeleteUsageEntry _oecc33
#define Level3_DeleteOldUsageTable _oecc34
#define Level3_GenerateRSASignature _oecc36
#define Level3_GetMaxNumberOfSessions _oecc37
#define Level3_GetNumberOfOpenSessions _oecc38
#define Level3_IsAntiRollbackHwPresent _oecc39
#define Level3_CopyBuffer _oecc40
#define Level3_QueryKeyControl _oecc41
#define Level3_LoadTestKeybox _oecc42
#define Level3_ForceDeleteUsageEntry _oecc43
#define Level3_GetHDCPCapability _oecc44
#define Level3_LoadTestRSAKey _oecc45
#define Level3_SecurityPatchLevel _oecc46
#define Level3_DecryptCENC _oecc48
#define Level3_GetProvisioningMethod _oecc49
#define Level3_GetOEMPublicCertificate _oecc50
#define Level3_RewrapDeviceRSAKey30 _oecc51
#define Level3_Initialize _oecc01
#define Level3_Terminate _oecc02
#define Level3_InstallKeybox _oecc03
#define Level3_GetKeyData _oecc04
#define Level3_IsKeyboxValid _oecc05
#define Level3_GetRandom _oecc06
#define Level3_GetDeviceID _oecc07
#define Level3_WrapKeybox _oecc08
#define Level3_OpenSession _oecc09
#define Level3_CloseSession _oecc10
#define Level3_GenerateDerivedKeys _oecc12
#define Level3_GenerateSignature _oecc13
#define Level3_GenerateNonce _oecc14
#define Level3_RefreshKeys _oecc16
#define Level3_SelectKey _oecc17
#define Level3_RewrapDeviceRSAKey _oecc18
#define Level3_LoadDeviceRSAKey _oecc19
#define Level3_DeriveKeysFromSessionKey _oecc21
#define Level3_APIVersion _oecc22
#define Level3_SecurityLevel _oecc23
#define Level3_Generic_Encrypt _oecc24
#define Level3_Generic_Decrypt _oecc25
#define Level3_Generic_Sign _oecc26
#define Level3_Generic_Verify _oecc27
#define Level3_SupportsUsageTable _oecc29
#define Level3_UpdateUsageTable _oecc30
#define Level3_ReportUsage _oecc32
#define Level3_DeleteUsageEntry _oecc33
#define Level3_DeleteOldUsageTable _oecc34
#define Level3_GenerateRSASignature _oecc36
#define Level3_GetMaxNumberOfSessions _oecc37
#define Level3_GetNumberOfOpenSessions _oecc38
#define Level3_IsAntiRollbackHwPresent _oecc39
#define Level3_CopyBuffer _oecc40
#define Level3_QueryKeyControl _oecc41
#define Level3_LoadTestKeybox _oecc42
#define Level3_ForceDeleteUsageEntry _oecc43
#define Level3_GetHDCPCapability _oecc44
#define Level3_LoadTestRSAKey _oecc45
#define Level3_SecurityPatchLevel _oecc46
#define Level3_DecryptCENC _oecc48
#define Level3_GetProvisioningMethod _oecc49
#define Level3_GetOEMPublicCertificate _oecc50
#define Level3_RewrapDeviceRSAKey30 _oecc51
#define Level3_SupportedCertificates _oecc52
#define Level3_IsSRMUpdateSupported _oecc53
#define Level3_GetCurrentSRMVersion _oecc54
@@ -348,6 +349,28 @@ OEMCryptoResult Level3_CreateOldUsageEntry(uint64_t time_since_license_received,
size_t pst_length);
} // extern "C"
// The following are interfaces needed for Level3 OEMCrypto specifically, which
// partners are expected to implement.
// Returns a stable, unique identifier for the device. This could be a
// serial number or any other character sequence representing that device.
// The parameter |len| needs to be changed to reflect the length of the
// unique identifier.
const char *getUniqueID(size_t *len);
// Returns a 64-bit unsigned integer to be used as a random seed for RNG.
// If the operation is unsuccessful, this function returns 0.
// We provide a sample implementation under the name generate_entropy_linux.cpp
// which partners should use if they can.
uint64_t generate_entropy();
// Creates and returns an OEMCrypto_Level3FileSystem implementation.
OEMCrypto_Level3FileSystem* createLevel3FileSystem();
// Deletes the pointer retrieved by the function above.
void deleteLevel3FileSystem(OEMCrypto_Level3FileSystem* file_system);
} // namespace wvoec3
#endif // LEVEL3_OEMCRYPTO_H_

View File

@@ -0,0 +1,29 @@
// Copyright 2017 Google Inc. All Rights Reserved
/*********************************************************************
* level3_file_system.h
*
* File system for OEMCrypto Level3 file operations.
*********************************************************************/
#ifndef LEVEL3_FILE_SYSTEM_H_
#define LEVEL3_FILE_SYSTEM_H_
#include <stdlib.h>
namespace wvoec3 {
class OEMCrypto_Level3FileSystem {
public:
virtual ~OEMCrypto_Level3FileSystem() {}
virtual ssize_t Read(const char *filename, void *buffer, size_t size) = 0;
virtual ssize_t Write(const char *filename, const void *buffer,
size_t size) = 0;
virtual bool Exists(const char *filename) = 0;
virtual ssize_t FileSize(const char *filename) = 0;
virtual bool Remove(const char *filename) = 0;
};
} // namespace wvoec3
#endif

View File

@@ -946,6 +946,10 @@ extern "C" OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey30(
// The wrapped keybox must be signed with the same key we verify with. I'll
// pick the server key, so I don't have to modify LoadRSAKey.
unsigned int sig_length = sizeof(wrapped->signature);
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
LOGI(("message verified with HMAC and mac_key_server, key = " +
wvcdm::b2a_hex(session_ctx->mac_key_server())).c_str());
}
if (!HMAC(EVP_sha256(), &session_ctx->mac_key_server()[0],
session_ctx->mac_key_server().size(), wrapped->context,
buffer_size - sizeof(wrapped->signature), wrapped->signature,
@@ -1091,6 +1095,10 @@ extern "C" OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(
// The wrapped keybox must be signed with the same key we verify with. I'll
// pick the server key, so I don't have to modify LoadRSAKey.
unsigned int sig_length = sizeof(wrapped->signature);
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
LOGI(("message verified with HMAC and mac_key_server, key = " +
wvcdm::b2a_hex(session_ctx->mac_key_server())).c_str());
}
if (!HMAC(EVP_sha256(), &session_ctx->mac_key_server()[0],
session_ctx->mac_key_server().size(), wrapped->context,
buffer_size - sizeof(wrapped->signature), wrapped->signature,

View File

@@ -201,12 +201,14 @@ bool SessionContext::GenerateSignature(const uint8_t* message,
}
const uint8_t *mac_key = NULL;
bool using_usage_mac_key_client = false;
if (mac_key_client_.size() == wvcdm::MAC_KEY_SIZE) {
// If we have a mac key, use it.
mac_key = &mac_key_client_[0];
} else if (usage_entry_status_ == kUsageEntryLoaded) {
// If not, but we have a usage entry, use its key.
mac_key = usage_entry_->mac_key_client();
using_usage_mac_key_client = true;
} else {
return false;
}
@@ -216,6 +218,19 @@ bool SessionContext::GenerateSignature(const uint8_t* message,
return false;
}
if (using_usage_mac_key_client &&
LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
std::vector<uint8_t> usage_entry_mac_key_client(
usage_entry_->mac_key_client(),
usage_entry_->mac_key_client() + wvcdm::MAC_KEY_SIZE * sizeof(uint8_t));
LOGI(("message signed with HMAC and usage_entry_'s mac_key_client, "
"mac_key_client = " +
wvcdm::b2a_hex(usage_entry_mac_key_client)).c_str());
} else if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
LOGI(("message signed with HMAC and mac_key_client_, mac_key_client_ = " +
wvcdm::b2a_hex(mac_key_client_)).c_str());
}
unsigned int md_len = *signature_length;
if (HMAC(EVP_sha256(), mac_key, wvcdm::MAC_KEY_SIZE, message,
message_length, signature, &md_len)) {
@@ -313,6 +328,10 @@ bool SessionContext::ValidateMessage(const uint8_t* given_message,
uint8_t computed_signature[SHA256_DIGEST_LENGTH];
memset(computed_signature, 0, SHA256_DIGEST_LENGTH);
unsigned int md_len = SHA256_DIGEST_LENGTH;
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
LOGI(("message verified with HMAC and mac_key_server, key = " +
wvcdm::b2a_hex(mac_key_server_)).c_str());
}
if (!HMAC(EVP_sha256(), &mac_key_server_[0], mac_key_server_.size(),
given_message, message_length, computed_signature, &md_len)) {
LOGE("ValidateMessage: Could not compute signature.");
@@ -510,6 +529,10 @@ OEMCryptoResult SessionContext::LoadKeys(
LOGE("LoadKeys: Usage table can't set keys.\n");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
LOGI(("usage_entry_'s mac_key_client_ has changed to = " +
wvcdm::b2a_hex(mac_key_client_)).c_str());
}
break;
case kUsageEntryLoaded:
if (!usage_entry_->VerifyPST(pst, pst_length)) {
@@ -982,6 +1005,10 @@ bool SessionContext::UpdateMacKeys(const std::vector<uint8_t>& enc_mac_keys,
mac_keys.begin(), mac_keys.begin() + wvcdm::MAC_KEY_SIZE);
mac_key_client_ = std::vector<uint8_t>(mac_keys.begin() + wvcdm::MAC_KEY_SIZE,
mac_keys.end());
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
LOGI(("mac_key_client_ has been updated to = " +
wvcdm::b2a_hex(mac_key_client_)).c_str());
}
return true;
}

View File

@@ -158,6 +158,14 @@ OEMCryptoResult UsageTableEntry::ReportUsage(const std::vector<uint8_t>& pst,
pst_report.set_pst_length(data_.pst_length);
memcpy(pst_report.pst(), data_.pst, data_.pst_length);
unsigned int md_len = SHA_DIGEST_LENGTH;
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
std::vector<uint8_t> mac_key_client(
data_.mac_key_client,
data_.mac_key_client + wvcdm::MAC_KEY_SIZE * sizeof(uint8_t));
LOGI(("message signed with HMAC and data_.mac_key_client, "
"mac_key_client = " +
wvcdm::b2a_hex(mac_key_client)).c_str());
}
if (!HMAC(EVP_sha1(), data_.mac_key_client, wvcdm::MAC_KEY_SIZE,
buffer + SHA_DIGEST_LENGTH, length_needed - SHA_DIGEST_LENGTH,
pst_report.signature(), &md_len)) {
@@ -307,6 +315,13 @@ OEMCryptoResult UsageTableEntry::CopyOldUsageEntry(
} else {
memcpy(data_.mac_key_client, &(old_entry->mac_key_client_[0]),
wvcdm::MAC_KEY_SIZE);
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
std::vector<uint8_t> mac_key_client(
data_.mac_key_client,
data_.mac_key_client + wvcdm::MAC_KEY_SIZE * sizeof(uint8_t));
LOGI(("data_.mac_key_client has changed to = " +
wvcdm::b2a_hex(mac_key_client)).c_str());
}
}
if (pst.size() > kMaxPSTLength) {
LOGE("CopyOldEntry: PST Length was too large. Truncating.");

View File

@@ -17,6 +17,7 @@
#include <gtest/gtest.h>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
@@ -43,29 +44,20 @@ void PrintTo(const vector<uint8_t>& value, ostream* os) {
namespace {
int GetRandBytes(unsigned char* buf, int num) {
// returns 1 on success, -1 if not supported, or 0 if other failure.
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
return RAND_pseudo_bytes(buf, num);
#else
return RAND_bytes(buf, num);
#endif
}
#ifdef OPENSSL_IS_BORINGSSL
void DeleteX509Stack(STACK_OF(X509)* stack) {
sk_X509_pop_free(stack, X509_free);
}
typedef size_t X509Count;
#else
typedef int X509Count;
#endif
} // namespace
namespace wvoec {
// Increment counter for AES-CTR. The CENC spec specifies we increment only
// the low 64 bits of the IV counter, and leave the high 64 bits alone. This
// is different from the OpenSSL implementation, so we implement the CTR loop
// is different from the BoringSSL implementation, so we implement the CTR loop
// ourselves.
void ctr128_inc64(int64_t increaseBy, uint8_t* iv) {
ASSERT_NE(static_cast<void*>(NULL), iv);
@@ -77,19 +69,19 @@ void ctr128_inc64(int64_t increaseBy, uint8_t* iv) {
// Some compilers don't like the macro htonl within an ASSERT_EQ.
uint32_t htonl_fnc(uint32_t x) { return htonl(x); }
void dump_openssl_error() {
void dump_boringssl_error() {
while (unsigned long err = ERR_get_error()) {
char buffer[120];
ERR_error_string_n(err, buffer, sizeof(buffer));
cout << "openssl error -- " << buffer << "\n";
cout << "BoringSSL Error -- " << buffer << "\n";
}
}
template <typename T, void (*func)(T*)>
class openssl_ptr {
class boringssl_ptr {
public:
explicit openssl_ptr(T* p = NULL) : ptr_(p) {}
~openssl_ptr() {
explicit boringssl_ptr(T* p = NULL) : ptr_(p) {}
~boringssl_ptr() {
if (ptr_) func(ptr_);
}
T& operator*() const { return *ptr_; }
@@ -99,7 +91,7 @@ class openssl_ptr {
private:
T* ptr_;
CORE_DISALLOW_COPY_AND_ASSIGN(openssl_ptr);
CORE_DISALLOW_COPY_AND_ASSIGN(boringssl_ptr);
};
Session::Session()
@@ -608,43 +600,30 @@ void Session::LoadOEMCert(bool verify_cert) {
OEMCrypto_GetOEMPublicCertificate(session_id(), &public_cert[0],
&public_cert_length));
// Load the certificate chain into an OpenSSL X509 Stack
#ifdef OPENSSL_IS_BORINGSSL
const openssl_ptr<STACK_OF(X509), DeleteX509Stack> x509_stack(
// Load the certificate chain into a BoringSSL X509 Stack
const boringssl_ptr<STACK_OF(X509), DeleteX509Stack> x509_stack(
sk_X509_new_null());
ASSERT_TRUE(x509_stack.NotNull()) << "Unable to allocate X509 stack.";
CBS pkcs7;
CBS_init(&pkcs7, public_cert.data(), public_cert.size());
if (!PKCS7_get_certificates(x509_stack.get(), &pkcs7)) {
dump_openssl_error();
dump_boringssl_error();
FAIL() << "Unable to deserialize certificate chain.";
}
STACK_OF(X509)* certs = x509_stack.get();
#else
// load the cert into rsa_key_.
openssl_ptr<BIO, BIO_vfree> bio(
BIO_new_mem_buf(&public_cert[0], public_cert_length));
ASSERT_TRUE(bio.NotNull());
openssl_ptr<PKCS7, PKCS7_free> cert(
d2i_PKCS7_bio(bio.get(), NULL));
ASSERT_TRUE(cert.NotNull());
EXPECT_EQ(OBJ_obj2nid(cert->type), NID_pkcs7_signed);
STACK_OF(X509)* certs = cert->d.sign->cert;
#endif
// Load the public cert's key into public_rsa_ and verify, if requested
for (X509Count i = 0; certs && i < sk_X509_num(certs); i++) {
for (size_t i = 0; certs && i < sk_X509_num(certs); i++) {
X509* x509_cert = sk_X509_value(certs, i);
openssl_ptr<EVP_PKEY, EVP_PKEY_free> pubkey(X509_get_pubkey(x509_cert));
boringssl_ptr<EVP_PKEY, EVP_PKEY_free> pubkey(X509_get_pubkey(x509_cert));
ASSERT_TRUE(pubkey.NotNull());
if (i == 0) {
public_rsa_ = EVP_PKEY_get1_RSA(pubkey.get());
if (!public_rsa_) {
cout << "d2i_RSAPrivateKey failed.\n";
dump_openssl_error();
dump_boringssl_error();
ASSERT_TRUE(NULL != public_rsa_);
}
}
@@ -654,9 +633,9 @@ void Session::LoadOEMCert(bool verify_cert) {
X509_NAME* name = X509_get_subject_name(x509_cert);
printf(" OEM Certificate Name: %s\n",
X509_NAME_oneline(name, &buffer[0], buffer.size()));
openssl_ptr<X509_STORE, X509_STORE_free> store(X509_STORE_new());
boringssl_ptr<X509_STORE, X509_STORE_free> store(X509_STORE_new());
ASSERT_TRUE(store.NotNull());
openssl_ptr<X509_STORE_CTX, X509_STORE_CTX_free> store_ctx(
boringssl_ptr<X509_STORE_CTX, X509_STORE_CTX_free> store_ctx(
X509_STORE_CTX_new());
ASSERT_TRUE(store_ctx.NotNull());
@@ -665,23 +644,13 @@ void Session::LoadOEMCert(bool verify_cert) {
// TODO(fredgc): Verify cert is signed by Google.
int result = X509_verify_cert(store_ctx.get());
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
ASSERT_GE(0, result) << " OEM Cert not valid. " <<
X509_verify_cert_error_string(store_ctx->error);
#else
ASSERT_GE(0, result) << " OEM Cert not valid. " <<
X509_verify_cert_error_string(
X509_STORE_CTX_get_error(store_ctx.get()));
#endif
if (result == 0) {
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
printf("Cert not verified: %s.\n",
X509_verify_cert_error_string(store_ctx->error));
#else
printf("Cert not verified: %s.\n",
X509_verify_cert_error_string(
X509_STORE_CTX_get_error(store_ctx.get())));
#endif
}
}
}
@@ -769,28 +738,28 @@ void Session::PreparePublicKey(const uint8_t* rsa_key, size_t rsa_key_length) {
rsa_key_length = sizeof(kTestRSAPKCS8PrivateKeyInfo2_2048);
}
uint8_t* p = const_cast<uint8_t*>(rsa_key);
openssl_ptr<BIO, BIO_vfree> bio(BIO_new_mem_buf(p, rsa_key_length));
boringssl_ptr<BIO, BIO_vfree> bio(BIO_new_mem_buf(p, rsa_key_length));
ASSERT_TRUE(bio.NotNull());
openssl_ptr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free> pkcs8_pki(
boringssl_ptr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free> pkcs8_pki(
d2i_PKCS8_PRIV_KEY_INFO_bio(bio.get(), NULL));
ASSERT_TRUE(pkcs8_pki.NotNull());
openssl_ptr<EVP_PKEY, EVP_PKEY_free> evp(EVP_PKCS82PKEY(pkcs8_pki.get()));
boringssl_ptr<EVP_PKEY, EVP_PKEY_free> evp(EVP_PKCS82PKEY(pkcs8_pki.get()));
ASSERT_TRUE(evp.NotNull());
if (public_rsa_) RSA_free(public_rsa_);
public_rsa_ = EVP_PKEY_get1_RSA(evp.get());
if (!public_rsa_) {
cout << "d2i_RSAPrivateKey failed. ";
dump_openssl_error();
dump_boringssl_error();
FAIL() << "Could not parse public RSA key.";
}
switch (RSA_check_key(public_rsa_)) {
case 1: // valid.
return;
case 0: // not valid.
dump_openssl_error();
dump_boringssl_error();
FAIL() << "[rsa key not valid] ";
default: // -1 == check failed.
dump_openssl_error();
dump_boringssl_error();
FAIL() << "[error checking rsa key] ";
}
}
@@ -799,13 +768,9 @@ bool Session::VerifyPSSSignature(EVP_PKEY* pkey, const uint8_t* message,
size_t message_length,
const uint8_t* signature,
size_t signature_length) {
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
EVP_MD_CTX md_ctx_struct;
EVP_MD_CTX* md_ctx = &md_ctx_struct;
EVP_MD_CTX_init(md_ctx);
#else
EVP_MD_CTX* md_ctx = EVP_MD_CTX_new();
#endif
EVP_PKEY_CTX* pkey_ctx = NULL;
if (EVP_DigestVerifyInit(md_ctx, &pkey_ctx, EVP_sha1(), NULL /* no ENGINE */,
@@ -843,20 +808,12 @@ bool Session::VerifyPSSSignature(EVP_PKEY* pkey, const uint8_t* message,
goto err;
}
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
EVP_MD_CTX_cleanup(md_ctx);
#else
EVP_MD_CTX_free(md_ctx);
#endif
return true;
err:
dump_openssl_error();
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
dump_boringssl_error();
EVP_MD_CTX_cleanup(md_ctx);
#else
EVP_MD_CTX_free(md_ctx);
#endif
return false;
}
@@ -872,7 +829,7 @@ void Session::VerifyRSASignature(const vector<uint8_t>& message,
<< RSA_size(public_rsa_) << "\n";
if (padding_scheme == kSign_RSASSA_PSS) {
openssl_ptr<EVP_PKEY, EVP_PKEY_free> pkey(EVP_PKEY_new());
boringssl_ptr<EVP_PKEY, EVP_PKEY_free> pkey(EVP_PKEY_new());
ASSERT_EQ(1, EVP_PKEY_set1_RSA(pkey.get(), public_rsa_));
const bool ok = VerifyPSSSignature(pkey.get(), &message[0], message.size(),
@@ -907,7 +864,7 @@ bool Session::GenerateRSASessionKey(vector<uint8_t>* session_key,
int size = static_cast<int>(RSA_size(public_rsa_));
if (status != size) {
cout << "GenerateRSASessionKey error encrypting session key.\n";
dump_openssl_error();
dump_boringssl_error();
return false;
}
return true;
@@ -1039,7 +996,7 @@ void Session::VerifyPST(const Test_PST_Report& expected) {
pst_report_buffer_.size() - SHA_DIGEST_LENGTH,
&signature[0], &md_len)) {
cout << "Error computing HMAC.\n";
dump_openssl_error();
dump_boringssl_error();
}
EXPECT_EQ(0, memcmp(computed.signature(), &signature[0],
SHA_DIGEST_LENGTH));

View File

@@ -112,8 +112,8 @@ void ctr128_inc64(int64_t increaseBy, uint8_t* iv);
// Some compilers don't like the macro htonl within an ASSERT_EQ.
uint32_t htonl_fnc(uint32_t x);
// Prints error string from openSSL
void dump_openssl_error();
// Prints error string from BoringSSL
void dump_boringssl_error();
class Session {
public:

View File

@@ -0,0 +1,147 @@
#include "oemcrypto_session_tests_helper.h"
#include <gtest/gtest.h>
#include "oec_test_data.h"
using namespace std;
using namespace wvoec;
namespace wvoec {
// Make this function available when in Fuzz mode because we are not inheriting
// from OEMCryptoClientTest.
const uint8_t* find(const vector<uint8_t>& message,
const vector<uint8_t>& substring) {
vector<uint8_t>::const_iterator pos = search(
message.begin(), message.end(), substring.begin(), substring.end());
if (pos == message.end()) {
return NULL;
}
return &(*pos);
}
// If force is true, we assert that the key loads successfully.
void SessionUtil::CreateWrappedRSAKeyFromKeybox(uint32_t allowed_schemes,
bool force) {
Session s;
ASSERT_NO_FATAL_FAILURE(s.open());
ASSERT_NO_FATAL_FAILURE(s.GenerateDerivedKeysFromKeybox());
// Provisioning request would be signed by the client and verified by the
// server.
ASSERT_NO_FATAL_FAILURE(s.VerifyClientSignature());
struct RSAPrivateKeyMessage encrypted;
std::vector<uint8_t> signature;
ASSERT_NO_FATAL_FAILURE(
s.MakeRSACertificate(&encrypted, sizeof(encrypted),
&signature, allowed_schemes,
encoded_rsa_key_));
ASSERT_NO_FATAL_FAILURE(s.RewrapRSAKey(
encrypted, sizeof(encrypted), signature, &wrapped_rsa_key_, force));
// Verify that the clear key is not contained in the wrapped key.
// It should be encrypted.
ASSERT_EQ(NULL, find(wrapped_rsa_key_, encoded_rsa_key_));
}
// If force is true, we assert that the key loads successfully.
void SessionUtil::CreateWrappedRSAKeyFromOEMCert(
uint32_t allowed_schemes, bool force) {
Session s;
ASSERT_NO_FATAL_FAILURE(s.open());
ASSERT_NO_FATAL_FAILURE(s.LoadOEMCert());
s.GenerateNonce();
struct RSAPrivateKeyMessage encrypted;
std::vector<uint8_t> signature;
std::vector<uint8_t> message_key;
std::vector<uint8_t> encrypted_message_key;
s.GenerateRSASessionKey(&message_key, &encrypted_message_key);
ASSERT_NO_FATAL_FAILURE(
s.MakeRSACertificate(&encrypted, sizeof(encrypted), &signature,
allowed_schemes, encoded_rsa_key_, &message_key));
ASSERT_NO_FATAL_FAILURE(
s.RewrapRSAKey30(encrypted, encrypted_message_key,
&wrapped_rsa_key_, force));
// Verify that the clear key is not contained in the wrapped key.
// It should be encrypted.
ASSERT_EQ(NULL, find(wrapped_rsa_key_, encoded_rsa_key_));
}
// If force is true, we assert that the key loads successfully.
void SessionUtil::CreateWrappedRSAKey(uint32_t allowed_schemes,
bool force) {
switch (global_features.provisioning_method) {
case OEMCrypto_OEMCertificate:
CreateWrappedRSAKeyFromOEMCert(allowed_schemes, force);
break;
case OEMCrypto_Keybox:
CreateWrappedRSAKeyFromKeybox(allowed_schemes, force);
break;
default:
FAIL() << "Cannot generate wrapped RSA key if provision method = "
<< wvoec::ProvisioningMethodName(
global_features.provisioning_method);
}
}
void SessionUtil::InstallKeybox(const wvoec_mock::WidevineKeybox& keybox,
bool good) {
uint8_t wrapped[sizeof(wvoec_mock::WidevineKeybox)];
size_t length = sizeof(wvoec_mock::WidevineKeybox);
ASSERT_EQ(
OEMCrypto_SUCCESS,
OEMCrypto_WrapKeybox(reinterpret_cast<const uint8_t*>(&keybox),
sizeof(keybox), wrapped, &length, NULL, 0));
OEMCryptoResult sts = OEMCrypto_InstallKeybox(wrapped, sizeof(keybox));
if (good) {
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
} else {
// Can return error now, or return error on IsKeyboxValid.
}
}
void SessionUtil::EnsureTestKeys() {
switch (global_features.derive_key_method) {
case DeviceFeatures::LOAD_TEST_KEYBOX:
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadTestKeybox());
break;
case DeviceFeatures::LOAD_TEST_RSA_KEY:
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadTestRSAKey());
break;
case DeviceFeatures::EXISTING_TEST_KEYBOX:
// already has test keybox.
break;
case DeviceFeatures::FORCE_TEST_KEYBOX:
InstallKeybox(kTestKeybox, true);
break;
case DeviceFeatures::TEST_PROVISION_30:
// Can use oem certificate to install test rsa key.
break;
default:
FAIL() << "Cannot run test without test keybox or RSA key installed.";
}
}
// This makes sure that the derived keys (encryption key and two mac keys)
// are installed in OEMCrypto and in the test session.
void SessionUtil::InstallTestSessionKeys(Session* s) {
if (global_features.uses_certificate) {
if (global_features.loads_certificate) {
if (wrapped_rsa_key_.size() == 0) {
// If we don't have a wrapped key yet, create one.
// This wrapped key will be shared by all sessions in the test.
ASSERT_NO_FATAL_FAILURE(
CreateWrappedRSAKey(kSign_RSASSA_PSS, true));
}
// Load the wrapped rsa test key.
ASSERT_NO_FATAL_FAILURE(
s->InstallRSASessionTestKey(wrapped_rsa_key_));
}
// Test RSA key should be loaded.
ASSERT_NO_FATAL_FAILURE(
s->GenerateDerivedKeysFromSessionKey());
} else { // Just uses keybox. Test keybox should already be installed.
ASSERT_NO_FATAL_FAILURE(
s->GenerateDerivedKeysFromKeybox());
}
}
}

View File

@@ -0,0 +1,39 @@
#include <assert.h>
#include <algorithm>
#include <iostream>
#include <openssl/aes.h>
#include <openssl/rand.h>
#include "oec_session_util.h"
#include "oec_test_data.h"
#include "OEMCryptoCENC.h"
namespace wvoec {
class SessionUtil {
public:
SessionUtil()
: encoded_rsa_key_(kTestRSAPKCS8PrivateKeyInfo2_2048,
kTestRSAPKCS8PrivateKeyInfo2_2048 +
sizeof(kTestRSAPKCS8PrivateKeyInfo2_2048)) {}
// If force is true, we assert that the key loads successfully.
void CreateWrappedRSAKeyFromKeybox(uint32_t allowed_schemes, bool force);
// If force is true, we assert that the key loads successfully.
void CreateWrappedRSAKeyFromOEMCert(uint32_t allowed_schemes, bool force);
// If force is true, we assert that the key loads successfully.
void CreateWrappedRSAKey(uint32_t allowed_schemes, bool force);
void InstallKeybox(const wvoec_mock::WidevineKeybox& keybox, bool good);
void EnsureTestKeys();
void InstallTestSessionKeys(Session* s);
std::vector<uint8_t> encoded_rsa_key_;
std::vector<uint8_t> wrapped_rsa_key_;
};
} // namespace wvoec

View File

@@ -2959,7 +2959,7 @@ class OEMCryptoCastReceiverTest : public OEMCryptoLoadsCertificateAlternates {
// test must do that also.
uint8_t hash[SHA_DIGEST_LENGTH];
if (!SHA1(&message[0], message.size(), hash)) {
dump_openssl_error();
dump_boringssl_error();
FAIL() << "openssl error creating SHA1 hash.";
}