Support CAST V2 authentication - OEMCrypto Interface - DO NOT MERGE
Squashed commit of these CLs from the widevine cdm repo: Allow Version 8 OEMCrypto to be linked with CDM (KLP Modular Branch) https://widevine-internal-review.googlesource.com/#/c/9434/ Allow OEMCrypto v8 or v9 (KLP Modular Branch) https://widevine-internal-review.googlesource.com/#/c/9172/ Add alternate RSA signing (KLP Modular Branch) https://widevine-internal-review.googlesource.com/#/c/9171/ bug: 12702350 Change-Id: Ifd0c88c566bb10efe2411af49bc83265ed56cb23
This commit is contained in:
@@ -34,6 +34,7 @@ OEMCryptoResult OEMCrypto_InstallKeybox(const uint8_t* keybox,
|
||||
SecurityLevel level);
|
||||
uint32_t OEMCrypto_APIVersion(SecurityLevel level);
|
||||
const char* OEMCrypto_SecurityLevel(SecurityLevel level);
|
||||
bool OEMCrypto_SupportsUsageTable(SecurityLevel level);
|
||||
} // namespace wvcdm
|
||||
|
||||
#endif // OEMCRYPTO_ADAPTER_H_
|
||||
|
||||
@@ -50,6 +50,11 @@ typedef OEMCryptoResult (*L1_LoadKeys_t)(
|
||||
const uint8_t* enc_mac_key_iv, const uint8_t* enc_mac_key, size_t num_keys,
|
||||
const OEMCrypto_KeyObject* key_array,
|
||||
const uint8_t* pst, size_t pst_length);
|
||||
typedef OEMCryptoResult (*L1_LoadKeys_V8_t)(
|
||||
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
||||
const uint8_t* signature, size_t signature_length,
|
||||
const uint8_t* enc_mac_key_iv, const uint8_t* enc_mac_key, size_t num_keys,
|
||||
const OEMCrypto_KeyObject* key_array);
|
||||
typedef OEMCryptoResult (*L1_RefreshKeys_t)(
|
||||
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
||||
const uint8_t* signature, size_t signature_length, size_t num_keys,
|
||||
@@ -90,7 +95,12 @@ typedef OEMCryptoResult (*L1_GenerateRSASignature_t)(OEMCrypto_SESSION session,
|
||||
size_t message_length,
|
||||
uint8_t* signature,
|
||||
size_t* signature_length,
|
||||
RSA_Padding_Scheme algorithm);
|
||||
RSA_Padding_Scheme padding_scheme);
|
||||
typedef OEMCryptoResult (*L1_GenerateRSASignature_V8_t)(OEMCrypto_SESSION session,
|
||||
const uint8_t* message,
|
||||
size_t message_length,
|
||||
uint8_t* signature,
|
||||
size_t* signature_length);
|
||||
typedef OEMCryptoResult (*L1_DeriveKeysFromSessionKey_t)(
|
||||
OEMCrypto_SESSION session, const uint8_t* enc_session_key,
|
||||
size_t enc_session_key_length, const uint8_t* mac_key_context,
|
||||
@@ -118,8 +128,28 @@ typedef OEMCryptoResult (*L1_Generic_Verify_t)(OEMCrypto_SESSION session,
|
||||
size_t signature_length);
|
||||
typedef uint32_t (*L1_APIVersion_t)();
|
||||
typedef const char* (*L1_SecurityLevel_t)();
|
||||
typedef OEMCryptoResult (*L1_GetHDCPCapability_t)(OEMCrypto_HDCP_Capability *current,
|
||||
OEMCrypto_HDCP_Capability *maximum);
|
||||
typedef bool (*L1_SupportsUsageTable_t)();
|
||||
typedef OEMCryptoResult (*L1_UpdateUsageTable_t)();
|
||||
typedef OEMCryptoResult (*L1_DeactivateUsageEntry_t)(const uint8_t *pst,
|
||||
size_t pst_length);
|
||||
typedef OEMCryptoResult (*L1_ReportUsage_t)(OEMCrypto_SESSION session,
|
||||
const uint8_t *pst,
|
||||
size_t pst_length,
|
||||
OEMCrypto_PST_Report *buffer,
|
||||
size_t *buffer_length);
|
||||
typedef OEMCryptoResult (*L1_DeleteUsageEntry_t)(OEMCrypto_SESSION session,
|
||||
const uint8_t* pst,
|
||||
size_t pst_length,
|
||||
const uint8_t *message,
|
||||
size_t message_length,
|
||||
const uint8_t *signature,
|
||||
size_t signature_length);
|
||||
typedef OEMCryptoResult (*L1_DeleteUsageTable_t)();
|
||||
|
||||
struct FunctionPointers {
|
||||
uint32_t version;
|
||||
L1_Initialize_t Initialize;
|
||||
L1_Terminate_t Terminate;
|
||||
L1_OpenSession_t OpenSession;
|
||||
@@ -147,6 +177,16 @@ struct FunctionPointers {
|
||||
L1_Generic_Decrypt_t Generic_Decrypt;
|
||||
L1_Generic_Sign_t Generic_Sign;
|
||||
L1_Generic_Verify_t Generic_Verify;
|
||||
L1_GetHDCPCapability_t GetHDCPCapability;
|
||||
L1_SupportsUsageTable_t SupportsUsageTable;
|
||||
L1_UpdateUsageTable_t UpdateUsageTable;
|
||||
L1_DeactivateUsageEntry_t DeactivateUsageEntry;
|
||||
L1_ReportUsage_t ReportUsage;
|
||||
L1_DeleteUsageEntry_t DeleteUsageEntry;
|
||||
L1_DeleteUsageTable_t DeleteUsageTable;
|
||||
|
||||
L1_LoadKeys_V8_t LoadKeys_V8;
|
||||
L1_GenerateRSASignature_V8_t GenerateRSASignature_V8;
|
||||
};
|
||||
|
||||
struct LevelSession {
|
||||
@@ -212,7 +252,6 @@ class Adapter {
|
||||
LOOKUP(GenerateDerivedKeys, OEMCrypto_GenerateDerivedKeys);
|
||||
LOOKUP(GenerateNonce, OEMCrypto_GenerateNonce);
|
||||
LOOKUP(GenerateSignature, OEMCrypto_GenerateSignature);
|
||||
LOOKUP(LoadKeys, OEMCrypto_LoadKeys);
|
||||
LOOKUP(RefreshKeys, OEMCrypto_RefreshKeys);
|
||||
LOOKUP(SelectKey, OEMCrypto_SelectKey);
|
||||
LOOKUP(DecryptCTR, OEMCrypto_DecryptCTR);
|
||||
@@ -224,7 +263,6 @@ class Adapter {
|
||||
LOOKUP(WrapKeybox, OEMCrypto_WrapKeybox);
|
||||
LOOKUP(RewrapDeviceRSAKey, OEMCrypto_RewrapDeviceRSAKey);
|
||||
LOOKUP(LoadDeviceRSAKey, OEMCrypto_LoadDeviceRSAKey);
|
||||
LOOKUP(GenerateRSASignature, OEMCrypto_GenerateRSASignature);
|
||||
LOOKUP(DeriveKeysFromSessionKey, OEMCrypto_DeriveKeysFromSessionKey);
|
||||
LOOKUP(APIVersion, OEMCrypto_APIVersion);
|
||||
LOOKUP(SecurityLevel, OEMCrypto_SecurityLevel);
|
||||
@@ -240,13 +278,27 @@ class Adapter {
|
||||
LOGW("Could not initialize L1. Falling Back to L3.");
|
||||
return false;
|
||||
}
|
||||
uint32_t level1_version = level1_.APIVersion();
|
||||
level1_.version = level1_.APIVersion();
|
||||
uint32_t minimum_version = 8; // TODO(fredgc): allow version 8 and 9?
|
||||
if (level1_version < minimum_version) {
|
||||
if (level1_.version < minimum_version) {
|
||||
LOGW("liboemcrypto.so is version %d, not %d. Falling Back to L3.",
|
||||
level1_version, minimum_version);
|
||||
level1_.version, minimum_version);
|
||||
return false;
|
||||
}
|
||||
if( level1_.version == 8 ) {
|
||||
LOOKUP(LoadKeys_V8, OEMCrypto_LoadKeys_V8);
|
||||
LOOKUP(GenerateRSASignature_V8, OEMCrypto_GenerateRSASignature_V8);
|
||||
} else {
|
||||
LOOKUP(LoadKeys, OEMCrypto_LoadKeys);
|
||||
LOOKUP(GenerateRSASignature, OEMCrypto_GenerateRSASignature);
|
||||
LOOKUP(GetHDCPCapability, OEMCrypto_GetHDCPCapability);
|
||||
LOOKUP(SupportsUsageTable, OEMCrypto_SupportsUsageTable);
|
||||
LOOKUP(UpdateUsageTable, OEMCrypto_UpdateUsageTable);
|
||||
LOOKUP(DeactivateUsageEntry, OEMCrypto_DeactivateUsageEntry);
|
||||
LOOKUP(ReportUsage, OEMCrypto_ReportUsage);
|
||||
LOOKUP(DeleteUsageEntry, OEMCrypto_DeleteUsageEntry);
|
||||
LOOKUP(DeleteUsageTable, OEMCrypto_DeleteUsageTable);
|
||||
}
|
||||
if (OEMCrypto_SUCCESS == level1_.IsKeyboxValid()) {
|
||||
return true;
|
||||
}
|
||||
@@ -300,6 +352,14 @@ class Adapter {
|
||||
level3_.Generic_Encrypt = Level3_Generic_Encrypt;
|
||||
level3_.Generic_Sign = Level3_Generic_Sign;
|
||||
level3_.Generic_Verify = Level3_Generic_Verify;
|
||||
level3_.GetHDCPCapability = Level3_GetHDCPCapability;
|
||||
level3_.SupportsUsageTable = Level3_SupportsUsageTable;
|
||||
level3_.UpdateUsageTable = Level3_UpdateUsageTable;
|
||||
level3_.DeactivateUsageEntry = Level3_DeactivateUsageEntry;
|
||||
level3_.ReportUsage = Level3_ReportUsage;
|
||||
level3_.DeleteUsageEntry = Level3_DeleteUsageEntry;
|
||||
level3_.DeleteUsageTable = Level3_DeleteUsageTable;
|
||||
level3_.version = Level3_APIVersion();
|
||||
}
|
||||
|
||||
OEMCryptoResult Terminate() {
|
||||
@@ -318,7 +378,7 @@ class Adapter {
|
||||
}
|
||||
|
||||
LevelSession get(OEMCrypto_SESSION session) {
|
||||
AutoLock auto_lock(lookup_lock_);
|
||||
AutoLock auto_lock(session_map_lock_);
|
||||
map_iterator pair = session_map_.find(session);
|
||||
if (pair == session_map_.end()) {
|
||||
return LevelSession();
|
||||
@@ -327,7 +387,6 @@ class Adapter {
|
||||
}
|
||||
|
||||
OEMCryptoResult OpenSession(OEMCrypto_SESSION* session, SecurityLevel level) {
|
||||
AutoLock auto_lock(lookup_lock_);
|
||||
LevelSession new_session;
|
||||
OEMCryptoResult result;
|
||||
if (level == kLevelDefault && level1_valid_) {
|
||||
@@ -340,6 +399,7 @@ class Adapter {
|
||||
*session = new_session.session + kLevel3Offset;
|
||||
}
|
||||
if (result == OEMCrypto_SUCCESS) {
|
||||
AutoLock auto_lock(session_map_lock_);
|
||||
// Make sure session is not already in my list of sessions.
|
||||
while (session_map_.find(*session) != session_map_.end()) {
|
||||
(*session)++;
|
||||
@@ -350,7 +410,7 @@ class Adapter {
|
||||
}
|
||||
|
||||
OEMCryptoResult CloseSession(OEMCrypto_SESSION session) {
|
||||
AutoLock auto_lock(lookup_lock_);
|
||||
AutoLock auto_lock(session_map_lock_);
|
||||
map_iterator pair = session_map_.find(session);
|
||||
if (pair == session_map_.end()) {
|
||||
return OEMCrypto_ERROR_INVALID_SESSION;
|
||||
@@ -367,7 +427,7 @@ class Adapter {
|
||||
struct FunctionPointers level1_;
|
||||
struct FunctionPointers level3_;
|
||||
std::map<OEMCrypto_SESSION, LevelSession> session_map_;
|
||||
Lock lookup_lock_;
|
||||
Lock session_map_lock_;
|
||||
// This is just for debugging the map between session ids.
|
||||
// If we add this to the level 3 session id, then the external session
|
||||
// id will match the internal session id in the last two digits.
|
||||
@@ -447,9 +507,15 @@ extern "C" OEMCryptoResult OEMCrypto_LoadKeys(
|
||||
if (!kAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
LevelSession pair = kAdapter->get(session);
|
||||
if (!pair.fcn) return OEMCrypto_ERROR_INVALID_SESSION;
|
||||
return pair.fcn->LoadKeys(pair.session, message, message_length, signature,
|
||||
signature_length, enc_mac_key_iv, enc_mac_key,
|
||||
num_keys, key_array, pst, pst_length);
|
||||
if (pair.fcn->version == 8) {
|
||||
return pair.fcn->LoadKeys_V8(pair.session, message, message_length, signature,
|
||||
signature_length, enc_mac_key_iv, enc_mac_key,
|
||||
num_keys, key_array);
|
||||
} else {
|
||||
return pair.fcn->LoadKeys(pair.session, message, message_length, signature,
|
||||
signature_length, enc_mac_key_iv, enc_mac_key,
|
||||
num_keys, key_array, pst, pst_length);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" OEMCryptoResult OEMCrypto_RefreshKeys(
|
||||
@@ -583,12 +649,18 @@ extern "C" OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(
|
||||
|
||||
extern "C" OEMCryptoResult OEMCrypto_GenerateRSASignature(
|
||||
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
||||
uint8_t* signature, size_t* signature_length, RSA_Padding_Scheme algorithm) {
|
||||
uint8_t* signature, size_t* signature_length, RSA_Padding_Scheme padding_scheme) {
|
||||
if (!kAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
LevelSession pair = kAdapter->get(session);
|
||||
if (!pair.fcn) return OEMCrypto_ERROR_INVALID_SESSION;
|
||||
return pair.fcn->GenerateRSASignature(pair.session, message, message_length,
|
||||
signature, signature_length, algorithm);
|
||||
if (pair.fcn->version == 8) {
|
||||
return pair.fcn->GenerateRSASignature_V8(pair.session, message, message_length,
|
||||
signature, signature_length);
|
||||
} else {
|
||||
return pair.fcn->GenerateRSASignature(pair.session, message, message_length,
|
||||
signature, signature_length,
|
||||
padding_scheme);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey(
|
||||
@@ -671,4 +743,96 @@ extern "C" OEMCryptoResult OEMCrypto_Generic_Verify(
|
||||
algorithm, signature, signature_length);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
OEMCryptoResult OEMCrypto_GetHDCPCapability(OEMCrypto_HDCP_Capability *current,
|
||||
OEMCrypto_HDCP_Capability *maximum) {
|
||||
if (!kAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
const FunctionPointers* fcn = kAdapter->get(kLevelDefault);
|
||||
if (!fcn) return OEMCrypto_ERROR_INVALID_SESSION;
|
||||
if( fcn->version == 8 ) return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
return fcn->GetHDCPCapability(current, maximum);
|
||||
}
|
||||
|
||||
extern "C" bool OEMCrypto_SupportsUsageTable() {
|
||||
return OEMCrypto_SupportsUsageTable(kLevelDefault);
|
||||
}
|
||||
|
||||
bool OEMCrypto_SupportsUsageTable(SecurityLevel level) {
|
||||
if (!kAdapter) return false;
|
||||
const FunctionPointers* fcn = kAdapter->get(level);
|
||||
if (!fcn) return false;
|
||||
if( fcn->version == 8 ) return false;
|
||||
return fcn->SupportsUsageTable();
|
||||
}
|
||||
|
||||
extern "C" OEMCryptoResult OEMCrypto_UpdateUsageTable() {
|
||||
if (!kAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
const FunctionPointers* fcn1 = kAdapter->get(kLevelDefault);
|
||||
const FunctionPointers* fcn3 = kAdapter->get(kLevel3);
|
||||
OEMCryptoResult sts = OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
if (fcn3 && fcn3->version > 8) sts = fcn3->UpdateUsageTable();
|
||||
if (fcn1 && fcn1 != fcn3 && fcn1->version > 8) sts = fcn1->UpdateUsageTable();
|
||||
return sts;
|
||||
}
|
||||
|
||||
extern "C" OEMCryptoResult OEMCrypto_DeactivateUsageEntry(const uint8_t *pst,
|
||||
size_t pst_length) {
|
||||
if (!kAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
const FunctionPointers* fcn1 = kAdapter->get(kLevelDefault);
|
||||
const FunctionPointers* fcn3 = kAdapter->get(kLevel3);
|
||||
OEMCryptoResult sts = OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
if (fcn3 && fcn3->version > 8) {
|
||||
sts = fcn3->DeactivateUsageEntry(pst, pst_length);
|
||||
}
|
||||
if (fcn1 && fcn1 != fcn3 && fcn1->version > 8) {
|
||||
sts = fcn1->DeactivateUsageEntry(pst, pst_length);
|
||||
}
|
||||
return sts;
|
||||
}
|
||||
|
||||
extern "C" OEMCryptoResult OEMCrypto_ReportUsage(OEMCrypto_SESSION session,
|
||||
const uint8_t *pst,
|
||||
size_t pst_length,
|
||||
OEMCrypto_PST_Report *buffer,
|
||||
size_t *buffer_length) {
|
||||
if (!kAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
LevelSession pair = kAdapter->get(session);
|
||||
if (!pair.fcn) return OEMCrypto_ERROR_INVALID_SESSION;
|
||||
if( pair.fcn->version > 8 ) {
|
||||
return pair.fcn->ReportUsage(pair.session, pst, pst_length,buffer,
|
||||
buffer_length);
|
||||
} else {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" OEMCryptoResult OEMCrypto_DeleteUsageEntry(OEMCrypto_SESSION session,
|
||||
const uint8_t* pst,
|
||||
size_t pst_length,
|
||||
const uint8_t *message,
|
||||
size_t message_length,
|
||||
const uint8_t *signature,
|
||||
size_t signature_length) {
|
||||
if (!kAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
LevelSession pair = kAdapter->get(session);
|
||||
if (!pair.fcn) return OEMCrypto_ERROR_INVALID_SESSION;
|
||||
if( pair.fcn->version > 8 ) {
|
||||
return pair.fcn->DeleteUsageEntry(session, pst, pst_length, message,
|
||||
message_length, signature,
|
||||
signature_length);
|
||||
} else {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" OEMCryptoResult OEMCrypto_DeleteUsageTable() {
|
||||
if (!kAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
const FunctionPointers* fcn1 = kAdapter->get(kLevelDefault);
|
||||
const FunctionPointers* fcn3 = kAdapter->get(kLevel3);
|
||||
OEMCryptoResult sts = OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
if (fcn3 && fcn3->version > 8) sts = fcn3->DeleteUsageTable();
|
||||
if (fcn1 && fcn1 != fcn3 && fcn1->version > 8) sts = fcn1->DeleteUsageTable();
|
||||
return sts;
|
||||
}
|
||||
|
||||
}; // namespace wvcdm
|
||||
|
||||
127
libwvdrmengine/cdm/core/src/oemcrypto_adapter_static_v8.cpp
Normal file
127
libwvdrmengine/cdm/core/src/oemcrypto_adapter_static_v8.cpp
Normal file
@@ -0,0 +1,127 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Copyright 2013 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Wrapper of OEMCrypto APIs for platforms that support Level 1 only.
|
||||
* This should be used when liboemcrypto.so is linked with the CDM code at
|
||||
* compile time.
|
||||
* An implementation should compile either oemcrypto_adapter_dynamic.cpp or
|
||||
* oemcrypto_adapter_static.cpp, but not both.
|
||||
* This version contains shim code to allow an older, version 8 API, oemcrypto,
|
||||
* to be linked with CDM.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "oemcrypto_adapter.h"
|
||||
|
||||
extern "C"
|
||||
OEMCryptoResult OEMCrypto_LoadKeys_V8(OEMCrypto_SESSION session,
|
||||
const uint8_t* message,
|
||||
size_t message_length,
|
||||
const uint8_t* signature,
|
||||
size_t signature_length,
|
||||
const uint8_t* enc_mac_keys_iv,
|
||||
const uint8_t* enc_mac_keys,
|
||||
size_t num_keys,
|
||||
const OEMCrypto_KeyObject* key_array);
|
||||
|
||||
extern "C"
|
||||
OEMCryptoResult OEMCrypto_GenerateRSASignature_V8(OEMCrypto_SESSION session,
|
||||
const uint8_t* message,
|
||||
size_t message_length,
|
||||
uint8_t* signature,
|
||||
size_t *signature_length);
|
||||
|
||||
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
OEMCryptoResult OEMCrypto_OpenSession(OEMCrypto_SESSION* session,
|
||||
SecurityLevel level) {
|
||||
return ::OEMCrypto_OpenSession(session);
|
||||
}
|
||||
|
||||
OEMCryptoResult OEMCrypto_IsKeyboxValid(SecurityLevel level) {
|
||||
return ::OEMCrypto_IsKeyboxValid();
|
||||
}
|
||||
|
||||
OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID, size_t* idLength,
|
||||
SecurityLevel level) {
|
||||
return ::OEMCrypto_GetDeviceID(deviceID, idLength);
|
||||
}
|
||||
|
||||
OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData, size_t* keyDataLength,
|
||||
SecurityLevel level) {
|
||||
return ::OEMCrypto_GetKeyData(keyData, keyDataLength);
|
||||
}
|
||||
|
||||
OEMCryptoResult OEMCrypto_InstallKeybox(const uint8_t* keybox,
|
||||
size_t keyBoxLength,
|
||||
SecurityLevel level) {
|
||||
return ::OEMCrypto_InstallKeybox(keybox, keyBoxLength);
|
||||
}
|
||||
|
||||
uint32_t OEMCrypto_APIVersion(SecurityLevel level) {
|
||||
return ::OEMCrypto_APIVersion();
|
||||
}
|
||||
|
||||
const char* OEMCrypto_SecurityLevel(SecurityLevel level) {
|
||||
return ::OEMCrypto_SecurityLevel();
|
||||
}
|
||||
|
||||
extern "C" OEMCryptoResult OEMCrypto_LoadKeys(
|
||||
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
||||
const uint8_t* signature, size_t signature_length,
|
||||
const uint8_t* enc_mac_key_iv, const uint8_t* enc_mac_key, size_t num_keys,
|
||||
const OEMCrypto_KeyObject* key_array,
|
||||
const uint8_t* pst, size_t pst_length) {
|
||||
return LoadKeys_V8(pair.session, message, message_length, signature,
|
||||
signature_length, enc_mac_key_iv, enc_mac_key,
|
||||
num_keys, key_array);
|
||||
}
|
||||
|
||||
extern "C" OEMCryptoResult OEMCrypto_GenerateRSASignature(
|
||||
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
||||
uint8_t* signature, size_t* signature_length, RSA_Padding_Scheme padding_scheme) {
|
||||
return GenerateRSASignature_V8(pair.session, message, message_length,
|
||||
signature, signature_length);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
OEMCryptoResult OEMCrypto_GetHDCPCapability(OEMCrypto_HDCP_Capability *current,
|
||||
OEMCrypto_HDCP_Capability *maximum) {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
extern "C" bool OEMCrypto_SupportsUsageTable() {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
extern "C" OEMCryptoResult OEMCrypto_UpdateUsageTable() {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
extern "C" OEMCryptoResult OEMCrypto_DeactivateUsageEntry(const uint8_t *pst,
|
||||
size_t pst_length) {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
extern "C" OEMCryptoResult OEMCrypto_ReportUsage(OEMCrypto_SESSION session,
|
||||
const uint8_t *pst,
|
||||
size_t pst_length,
|
||||
OEMCrypto_PST_Report *buffer,
|
||||
size_t *buffer_length) {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
extern "C" OEMCryptoResult OEMCrypto_DeleteUsageEntry(OEMCrypto_SESSION session,
|
||||
const uint8_t* pst,
|
||||
size_t pst_length,
|
||||
const uint8_t *message,
|
||||
size_t message_length,
|
||||
const uint8_t *signature,
|
||||
size_t signature_length) {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
}; // namespace wvcdm
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -192,7 +192,8 @@ typedef enum OEMCrypto_Algorithm {
|
||||
#define OEMCrypto_FirstSubsample 1
|
||||
#define OEMCrypto_LastSubsample 2
|
||||
|
||||
/* OEMCrypto_Usage_Entry_Status.
|
||||
/*
|
||||
* OEMCrypto_Usage_Entry_Status.
|
||||
* Valid values for status in the usage table.
|
||||
*/
|
||||
typedef enum OEMCrypto_Usage_Entry_Status {
|
||||
@@ -215,7 +216,8 @@ typedef struct {
|
||||
uint8_t pst[];
|
||||
} OEMCrypto_PST_Report;
|
||||
|
||||
/* OEMCrypto_Clock_Security_Level.
|
||||
/*
|
||||
* OEMCrypto_Clock_Security_Level.
|
||||
* Valid values for clock_security_level in OEMCrypto_PST_Report.
|
||||
*/
|
||||
typedef enum OEMCrypto_Clock_Security_Level {
|
||||
@@ -231,7 +233,9 @@ typedef enum RSA_Padding_Scheme {
|
||||
} RSA_Padding_Scheme;
|
||||
|
||||
|
||||
/* Obfuscation Renames. */
|
||||
/*
|
||||
* Obfuscation Renames.
|
||||
*/
|
||||
#define OEMCrypto_Initialize _oecc01
|
||||
#define OEMCrypto_Terminate _oecc02
|
||||
#define OEMCrypto_InstallKeybox _oecc03
|
||||
@@ -246,12 +250,12 @@ typedef enum RSA_Padding_Scheme {
|
||||
#define OEMCrypto_GenerateDerivedKeys _oecc12
|
||||
#define OEMCrypto_GenerateSignature _oecc13
|
||||
#define OEMCrypto_GenerateNonce _oecc14
|
||||
#define OEMCrypto_LoadKeys _oecc15
|
||||
#define OEMCrypto_LoadKeys_V8 _oecc15
|
||||
#define OEMCrypto_RefreshKeys _oecc16
|
||||
#define OEMCrypto_SelectKey _oecc17
|
||||
#define OEMCrypto_RewrapDeviceRSAKey _oecc18
|
||||
#define OEMCrypto_LoadDeviceRSAKey _oecc19
|
||||
#define OEMCrypto_GenerateRSASignature _oecc20
|
||||
#define OEMCrypto_GenerateRSASignature_V8 _oecc20
|
||||
#define OEMCrypto_DeriveKeysFromSessionKey _oecc21
|
||||
#define OEMCrypto_APIVersion _oecc22
|
||||
#define OEMCrypto_SecurityLevel _oecc23
|
||||
@@ -266,27 +270,28 @@ typedef enum RSA_Padding_Scheme {
|
||||
#define OEMCrypto_ReportUsage _oecc32
|
||||
#define OEMCrypto_DeleteUsageEntry _oecc33
|
||||
#define OEMCrypto_DeleteUsageTable _oecc34
|
||||
#define OEMCrypto_LoadKeys _oecc35
|
||||
#define OEMCrypto_GenerateRSASignature _oecc36
|
||||
|
||||
/*
|
||||
* OEMCrypto_Initialize
|
||||
*
|
||||
|
||||
Initializes the crypto hardware.
|
||||
|
||||
Parameters:
|
||||
None
|
||||
|
||||
Returns:
|
||||
OEMCrypto_SUCCESS success
|
||||
OEMCrypto_ERROR_INIT_FAILED failed to initialize crypto hardware
|
||||
|
||||
Threading:
|
||||
No other function calls will be made while this function is running. This
|
||||
function will not be called again before OEMCrypto_Terminate().
|
||||
|
||||
Version:
|
||||
This method is supported by all API versions.
|
||||
|
||||
* Description:
|
||||
* Initialize the crypto firmware/hardware.
|
||||
*
|
||||
* Parameters:
|
||||
* N/A
|
||||
*
|
||||
* Threading:
|
||||
* No other function calls will be made while this function is running. This
|
||||
* function will not be called again before OEMCrypto_Terminate.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS success
|
||||
* OEMCrypto_ERROR_INIT_FAILED failed to initialize crypto hardware
|
||||
*
|
||||
* Version:
|
||||
* This method is supported by all API versions.
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_Initialize(void);
|
||||
|
||||
@@ -428,8 +433,12 @@ OEMCryptoResult OEMCrypto_GenerateDerivedKeys(
|
||||
*
|
||||
* Because the nonce will be used to prevent replay attacks, it is desirable
|
||||
* that a rogue application cannot rapidly call this function until a
|
||||
* repeated nonce is created randomly. With this in mind, we require that
|
||||
* creation of more than 20 nonces will take at least one full second.
|
||||
* repeated nonce is created randomly. With this in mind, if more than 20
|
||||
* nonces are requested within one second, OEMCrypto will return an error
|
||||
* after the 20th and not generate any more nonces for the rest of the
|
||||
* second. After an error, if the application waits at least one second
|
||||
* before requesting more nonces, then OEMCrypto will reset the error
|
||||
* condition and generate valid nonces again.
|
||||
*
|
||||
* Parameters:
|
||||
* session (in) - crypto session identifier.
|
||||
@@ -1028,52 +1037,52 @@ OEMCryptoResult OEMCrypto_InstallKeybox(const uint8_t *keybox,
|
||||
/*
|
||||
* OEMCrypto_IsKeyboxValid
|
||||
*
|
||||
Validates the Widevine Keybox loaded into the security processor device. This
|
||||
method verifies two fields in the keybox:
|
||||
|
||||
Verify the MAGIC field contains a valid signature (such as, ‘k’’b’’o’’x’).
|
||||
|
||||
Compute the CRC using CRC-32-POSIX-1003.2 standard and compare the checksum
|
||||
to the CRC stored in the Keybox. The CRC is computed over the entire Keybox
|
||||
excluding the 4 bytes of the CRC (for example, Keybox[0..123]). For a
|
||||
description of the fields stored in the keybox, see Keybox Definition.
|
||||
|
||||
Parameters:
|
||||
none
|
||||
|
||||
Returns:
|
||||
OEMCrypto_SUCCESS
|
||||
OEMCrypto_ERROR_BAD_MAGIC
|
||||
OEMCrypto_ERROR_BAD_CRC
|
||||
|
||||
Threading:
|
||||
This function may be called simultaneously with any session functions.
|
||||
|
||||
Version:
|
||||
This method is supported in all API versions.
|
||||
* Description:
|
||||
* Validate the Widevine Keybox stored on the device.
|
||||
*
|
||||
* The API performs two verification steps on the Keybox. It first verifies
|
||||
* the MAGIC field contains a valid signature (must be 'kbox'). The API then
|
||||
* computes the CRC using CRC-32 (Posix 1003.2 standard) and compares the
|
||||
* checksum to the CRC stored in the Keybox. The CRC is computed over the
|
||||
* entire Keybox excluding the 4 CRC bytes (i.e. Keybox[0..123]).
|
||||
*
|
||||
* Parameters:
|
||||
* none
|
||||
*
|
||||
* Threading:
|
||||
* This function may be called simultaneously with any session functions.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS
|
||||
* OEMCrypto_ERROR_BAD_MAGIC
|
||||
* OEMCrypto_ERROR_BAD_CRC
|
||||
*
|
||||
* Version:
|
||||
* This method is supported by all API versions.
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_IsKeyboxValid(void);
|
||||
|
||||
/*
|
||||
* OEMCrypto_GetDeviceID
|
||||
*
|
||||
Retrieve DeviceID from the Keybox.
|
||||
|
||||
Parameters:
|
||||
[out] deviceId - pointer to the buffer that receives the Device ID
|
||||
[in/out] idLength – on input, size of the caller’s device ID buffer. On
|
||||
output, the number of bytes written into the buffer.
|
||||
|
||||
Returns:
|
||||
OEMCrypto_SUCCESS success
|
||||
OEMCrypto_ERROR_SHORT_BUFFER if the buffer is too small to return device ID
|
||||
OEMCrypto_ERROR_NO_DEVICEID failed to return Device Id
|
||||
|
||||
Threading:
|
||||
This function may be called simultaneously with any session functions.
|
||||
|
||||
Version:
|
||||
This method is supported in all API versions.
|
||||
* Description:
|
||||
* Retrieve the device's unique identifier from the Keybox.
|
||||
*
|
||||
* Parameters:
|
||||
* deviceId (out) - pointer to the buffer that receives the Device ID
|
||||
* idLength (in/out) - on input, size of the caller's device ID buffer.
|
||||
* On output, the number of bytes written into the buffer.
|
||||
*
|
||||
* Threading:
|
||||
* This function may be called simultaneously with any session functions.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS success
|
||||
* OEMCrypto_ERROR_SHORT_BUFFER buffer is too small to return the device ID
|
||||
* OEMCrypto_ERROR_NO_DEVICEID failed to return Device Id
|
||||
*
|
||||
* Version:
|
||||
* This method is supported by all API versions.
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID,
|
||||
size_t *idLength);
|
||||
@@ -1081,24 +1090,31 @@ OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID,
|
||||
/*
|
||||
* OEMCrypto_GetKeyData
|
||||
*
|
||||
Return the Key Data field from the Keybox.
|
||||
|
||||
Parameters:
|
||||
[out] keyData - pointer to the buffer to hold the Key Data field from the
|
||||
Keybox
|
||||
[in/out] keyDataLength – on input, the allocated buffer size. On output, the
|
||||
number of bytes in Key Data
|
||||
|
||||
Returns:
|
||||
OEMCrypto_SUCCESS success
|
||||
OEMCrypto_ERROR_SHORT_BUFFER if the buffer is too small to return KeyData
|
||||
OEMCrypto_ERROR_NO_KEYDATA
|
||||
|
||||
Threading:
|
||||
This function may be called simultaneously with any session functions.
|
||||
|
||||
Version:
|
||||
This method is supported in all API versions.
|
||||
* Description:
|
||||
* Returns the Key Data field from the Keybox. The Key Data field does not
|
||||
* need to be encrypted by an OEM root key, but may be if desired.
|
||||
*
|
||||
* If the Key Data field was encrypted with an OEM root key when the Keybox
|
||||
* was stored on the device, then this function should decrypt it and return
|
||||
* the clear Key Data. If the Key Data was not encrypted, then this function
|
||||
* should just access and return the clear Key data.
|
||||
*
|
||||
* Parameters:
|
||||
* keyData (out) - pointer to a caller-managed buffer to hold the Key Data
|
||||
* field from the Keybox
|
||||
* dataLength (in/out) - on input, the allocated buffer size. On output,
|
||||
* the number of bytes in KeyData.
|
||||
*
|
||||
* Threading:
|
||||
* This function may be called simultaneously with any session functions.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS success
|
||||
* OEMCrypto_ERROR_SHORT_BUFFER the buffer is too small to return the KeyData
|
||||
* OEMCrypto_ERROR_NO_KEYDATA failed to return KeyData
|
||||
*
|
||||
* Version:
|
||||
* This method is supported by all API versions.
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData,
|
||||
size_t *keyDataLength);
|
||||
@@ -1106,23 +1122,25 @@ OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData,
|
||||
/*
|
||||
* OEMCrypto_GetRandom
|
||||
*
|
||||
Returns a buffer filled with hardware-generated random bytes, if supported by
|
||||
the hardware.
|
||||
|
||||
Parameters:
|
||||
[out] randomData - pointer to the buffer that receives random data
|
||||
[in] dataLength - length of the random data buffer in bytes
|
||||
|
||||
Returns:
|
||||
OEMCrypto_SUCCESS success
|
||||
OEMCrypto_ERROR_RNG_FAILED failed to generate random number
|
||||
OEMCrypto_ERROR_RNG_NOT_SUPPORTED function not supported
|
||||
|
||||
Threading:
|
||||
This function may be called simultaneously with any session functions.
|
||||
|
||||
Version:
|
||||
This method is supported in all API versions.
|
||||
* Description:
|
||||
* Return a buffer filled with hardware-generated random bytes. If the
|
||||
* hardware feature does not exist, return OEMCrypto_ERROR_RNG_NOT_SUPPORTED.
|
||||
*
|
||||
* Parameters:
|
||||
* randomData (out) - Pointer to caller-manager buffer that will receive the
|
||||
* random data.
|
||||
* dataLength (in) - Length of the random data buffer in bytes.
|
||||
*
|
||||
* Threading:
|
||||
* This function may be called simultaneously with any session functions.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS success
|
||||
* OEMCrypto_ERROR_RNG_FAILED failed to generate random number
|
||||
* OEMCrypto_ERROR_RNG_NOT_SUPPORTED function not supported
|
||||
*
|
||||
* Version:
|
||||
* This method is supported by all API versions.
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_GetRandom(uint8_t* randomData,
|
||||
size_t dataLength);
|
||||
@@ -1263,8 +1281,6 @@ OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(OEMCrypto_SESSION session,
|
||||
* - padding. This is the wrapped key generated
|
||||
* - by OEMCrypto_RewrapDeviceRSAKey.
|
||||
* wrapped_rsa_key_length (in) - length of the wrapped key buffer, in bytes.
|
||||
* wrapped_rsa_key_iv (in) - The initialization vector used to encrypt
|
||||
* - wrapped_rsa_key.
|
||||
*
|
||||
* Threading:
|
||||
* This function may be called simultaneously with functions on other sessions,
|
||||
@@ -1546,41 +1562,25 @@ bool OEMCrypto_SupportsUsageTable();
|
||||
* that entry is “inactive”, then return OEMCrypto_ERROR_INVALID_SESSION.
|
||||
*
|
||||
* Parameters:
|
||||
* current (out) - this is the current HDCP version, based on the device itself,
|
||||
* and the display to which it is connected.
|
||||
* maximum (out) - this is the maximum supported HDCP version for the device,
|
||||
* ignoring any attached device.
|
||||
*
|
||||
* Threading:
|
||||
* This function may be called simultaneously with any other functions.
|
||||
* [in] session: crypto session identifier.
|
||||
* [in] in_buffer: pointer to memory containing data to be encrypted.
|
||||
* [in] buffer_length: length of the buffer, in bytes.
|
||||
* [in] iv: IV for encrypting data. Size is specified by the algorithm.
|
||||
* [in] algorithm: Specifies which encryption algorithm to use. See
|
||||
* OEMCrypto_Algorithm for valid values.
|
||||
* [out] out_buffer: pointer to buffer in which encrypted data should be stored.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS
|
||||
* OEMCrypto_ERROR_UNKNOWN_FAILURE
|
||||
*
|
||||
* Version:
|
||||
* This method changed in API version 9.
|
||||
*/
|
||||
typedef uint8_t OEMCrypto_HDCP_Capability;
|
||||
OEMCryptoResult OEMCrypto_GetHDCPCapability(OEMCrypto_HDCP_Capability *current,
|
||||
OEMCrypto_HDCP_Capability *maximum);
|
||||
|
||||
/*
|
||||
* OEMCrypto_SupportsUsageTable()
|
||||
*
|
||||
* Description:
|
||||
* This is used to determine if the device can support a usage table. Since this
|
||||
* function is spoofable, it is not relied on for security purposes. It is for
|
||||
* information only. The usage table is described in the section above.
|
||||
*
|
||||
* Parameters:
|
||||
* none
|
||||
* OEMCrypto_SUCCESS success
|
||||
* OEMCrypto_ERROR_KEY_EXPIRED
|
||||
* OEMCrypto_ERROR_NO_DEVICE_KEY
|
||||
* OEMCrypto_ERROR_INVALID_SESSION
|
||||
* OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
|
||||
* OEMCrypto_ERROR_UNKNOWN_FAILURE
|
||||
*
|
||||
* Threading:
|
||||
* This function may be called simultaneously with any other functions.
|
||||
*
|
||||
* Returns:
|
||||
* Returns true if the device can maintain a usage table. Returns false otherwise.
|
||||
* This function may be called simultaneously with functions on other sessions,
|
||||
* but not with other functions on this session.
|
||||
*
|
||||
* Version:
|
||||
* This method changed in API version 9.
|
||||
|
||||
@@ -43,6 +43,13 @@ namespace wvoec3 {
|
||||
#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_DeleteUsageTable _lcc34
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -125,7 +132,7 @@ OEMCryptoResult Level3_GenerateRSASignature(OEMCrypto_SESSION session,
|
||||
size_t message_length,
|
||||
uint8_t* signature,
|
||||
size_t *signature_length,
|
||||
RSA_Padding_Scheme algorithm);
|
||||
RSA_Padding_Scheme padding_scheme);
|
||||
OEMCryptoResult Level3_DeriveKeysFromSessionKey(OEMCrypto_SESSION session,
|
||||
const uint8_t* enc_session_key,
|
||||
size_t enc_session_key_length,
|
||||
@@ -159,6 +166,26 @@ OEMCryptoResult Level3_Generic_Verify(OEMCrypto_SESSION session,
|
||||
OEMCrypto_Algorithm algorithm,
|
||||
const uint8_t* signature,
|
||||
size_t signature_length);
|
||||
OEMCryptoResult Level3_GetHDCPCapability(OEMCrypto_HDCP_Capability *current,
|
||||
OEMCrypto_HDCP_Capability *maximum);
|
||||
bool Level3_SupportsUsageTable();
|
||||
OEMCryptoResult Level3_UpdateUsageTable();
|
||||
OEMCryptoResult Level3_DeactivateUsageEntry(const uint8_t *pst,
|
||||
size_t pst_length);
|
||||
OEMCryptoResult Level3_ReportUsage(OEMCrypto_SESSION session,
|
||||
const uint8_t *pst,
|
||||
size_t pst_length,
|
||||
OEMCrypto_PST_Report *buffer,
|
||||
size_t *buffer_length);
|
||||
OEMCryptoResult Level3_DeleteUsageEntry(OEMCrypto_SESSION session,
|
||||
const uint8_t* pst,
|
||||
size_t pst_length,
|
||||
const uint8_t *message,
|
||||
size_t message_length,
|
||||
const uint8_t *signature,
|
||||
size_t signature_length);
|
||||
OEMCryptoResult Level3_DeleteUsageTable();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "oemcrypto_engine_mock.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string.h>
|
||||
@@ -31,8 +32,9 @@
|
||||
static const int kPssSaltLength = 20;
|
||||
|
||||
namespace {
|
||||
// Increment counter for AES-CTR
|
||||
void ctr128_inc(uint8_t* counter) {
|
||||
// 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.
|
||||
void ctr128_inc64(uint8_t* counter) {
|
||||
uint32_t n = 16;
|
||||
do {
|
||||
if (++counter[--n] != 0) return;
|
||||
@@ -252,7 +254,8 @@ size_t SessionContext::RSASignatureSize() {
|
||||
bool SessionContext::GenerateRSASignature(const uint8_t* message,
|
||||
size_t message_length,
|
||||
uint8_t* signature,
|
||||
size_t* signature_length) {
|
||||
size_t* signature_length,
|
||||
RSA_Padding_Scheme padding_scheme) {
|
||||
if (message == NULL || message_length == 0 ||
|
||||
signature == NULL || signature_length == 0) {
|
||||
LOGE("[GenerateRSASignature(): OEMCrypto_ERROR_INVALID_CONTEXT]");
|
||||
@@ -266,33 +269,55 @@ bool SessionContext::GenerateRSASignature(const uint8_t* message,
|
||||
*signature_length = RSA_size(rsa_key_);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Hash the message using SHA1.
|
||||
uint8_t hash[SHA_DIGEST_LENGTH];
|
||||
if (!SHA1(message, message_length, hash)) {
|
||||
LOGE("[GeneratRSASignature(): error creating signature hash.]");
|
||||
dump_openssl_error();
|
||||
if ((padding_scheme & allowed_schemes_) != padding_scheme) {
|
||||
LOGE("[GenerateRSASignature(): padding_scheme not allowed]");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add PSS padding.
|
||||
std::vector<uint8_t> padded_digest(*signature_length);
|
||||
int status = RSA_padding_add_PKCS1_PSS(rsa_key_, &padded_digest[0], hash,
|
||||
EVP_sha1(), kPssSaltLength);
|
||||
if (status == -1) {
|
||||
LOGE("[GeneratRSASignature(): error padding hash.]");
|
||||
dump_openssl_error();
|
||||
if (padding_scheme == kSign_RSASSA_PSS) {
|
||||
// Hash the message using SHA1.
|
||||
uint8_t hash[SHA_DIGEST_LENGTH];
|
||||
if (!SHA1(message, message_length, hash)) {
|
||||
LOGE("[GeneratRSASignature(): error creating signature hash.]");
|
||||
dump_openssl_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add PSS padding.
|
||||
std::vector<uint8_t> padded_digest(*signature_length);
|
||||
int status = RSA_padding_add_PKCS1_PSS(rsa_key_, &padded_digest[0], hash,
|
||||
EVP_sha1(), kPssSaltLength);
|
||||
if (status == -1) {
|
||||
LOGE("[GeneratRSASignature(): error padding hash.]");
|
||||
dump_openssl_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Encrypt PSS padded digest.
|
||||
status = RSA_private_encrypt(*signature_length, &padded_digest[0], signature,
|
||||
rsa_key_, RSA_NO_PADDING);
|
||||
if (status == -1) {
|
||||
LOGE("[GeneratRSASignature(): error in private encrypt.]");
|
||||
dump_openssl_error();
|
||||
return false;
|
||||
}
|
||||
} else if (padding_scheme == kSign_PKCS1_Block1) {
|
||||
if (message_length > 83) {
|
||||
LOGE("[GeneratRSASignature(): RSA digest too large.]");
|
||||
return false;
|
||||
}
|
||||
// Pad the message with PKCS1 padding, and then encrypt.
|
||||
int status = RSA_private_encrypt(message_length, message, signature,
|
||||
rsa_key_, RSA_PKCS1_PADDING);
|
||||
if (status != *signature_length) {
|
||||
LOGE("[GeneratRSASignature(): error in RSA private encrypt. status=%d]", status);
|
||||
dump_openssl_error();
|
||||
return false;
|
||||
}
|
||||
} else { // Bad RSA_Padding_Scheme
|
||||
return false;
|
||||
}
|
||||
|
||||
// Encrypt PSS padded digest.
|
||||
status = RSA_private_encrypt(*signature_length, &padded_digest[0], signature,
|
||||
rsa_key_, RSA_NO_PADDING);
|
||||
if (status == -1) {
|
||||
LOGE("[GeneratRSASignature(): error in private encrypt.]");
|
||||
dump_openssl_error();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -485,6 +510,16 @@ bool SessionContext::LoadRSAKey(uint8_t* pkcs8_rsa_key,
|
||||
RSA_free(rsa_key_);
|
||||
rsa_key_ = NULL;
|
||||
}
|
||||
if (rsa_key_length < 8) {
|
||||
LOGE("[LoadRSAKey(): Very Short Buffer]");
|
||||
return false;
|
||||
}
|
||||
if( (memcmp(pkcs8_rsa_key, "SIGN", 4) == 0) ) {
|
||||
uint32_t *schemes_n = (uint32_t *)(pkcs8_rsa_key + 4);
|
||||
allowed_schemes_ = htonl(*schemes_n);
|
||||
pkcs8_rsa_key += 8;
|
||||
rsa_key_length -= 8;
|
||||
}
|
||||
BIO *bio = BIO_new_mem_buf(pkcs8_rsa_key, rsa_key_length);
|
||||
if( bio == NULL ) {
|
||||
LOGE("[LoadRSAKey(): Could not allocate bio buffer]");
|
||||
@@ -899,11 +934,11 @@ bool CryptoEngine::DecryptCTR(SessionContext* session,
|
||||
const uint8_t* cipher_data,
|
||||
size_t cipher_data_length,
|
||||
bool is_encrypted,
|
||||
void* clear_data,
|
||||
uint8_t* clear_data,
|
||||
BufferType buffer_type) {
|
||||
|
||||
// If the data is clear, we do not need a current key selected.
|
||||
if (!is_encrypted) {
|
||||
if (!is_encrypted && buffer_type != kBufferTypeDirect) {
|
||||
memcpy(reinterpret_cast<uint8_t*>(clear_data),
|
||||
cipher_data, cipher_data_length);
|
||||
return true;
|
||||
@@ -961,20 +996,20 @@ bool CryptoEngine::DecryptCTR(SessionContext* session,
|
||||
|
||||
// Encrypt the IV.
|
||||
uint8_t ecount_buf[AES_BLOCK_SIZE];
|
||||
if (block_offset != 0) {
|
||||
// The context is needed only when not starting a new block.
|
||||
AES_encrypt(aes_iv, ecount_buf, &aes_key);
|
||||
ctr128_inc(aes_iv);
|
||||
}
|
||||
|
||||
// Decryption.
|
||||
unsigned int block_offset_cur = block_offset;
|
||||
AES_ctr128_encrypt(
|
||||
cipher_data, reinterpret_cast<uint8_t*>(clear_data), cipher_data_length,
|
||||
&aes_key, aes_iv, ecount_buf, &block_offset_cur);
|
||||
if (block_offset_cur != ((block_offset + cipher_data_length) % AES_BLOCK_SIZE)) {
|
||||
LOGE("[DecryptCTR(): FAILURE: byte offset wrong.]");
|
||||
return false;
|
||||
// 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, which increments the entire 128 bit iv. That is
|
||||
// why we implement the CTR loop ourselves.
|
||||
size_t l = 0;
|
||||
while (l < cipher_data_length) {
|
||||
AES_encrypt(aes_iv, ecount_buf, &aes_key);
|
||||
for (int n = block_offset; n < AES_BLOCK_SIZE && l < cipher_data_length;
|
||||
++n, ++l) {
|
||||
clear_data[l] = cipher_data[l] ^ ecount_buf[n];
|
||||
}
|
||||
ctr128_inc64(aes_iv);
|
||||
block_offset = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ class SessionContext {
|
||||
public:
|
||||
explicit SessionContext(CryptoEngine* ce, SessionId sid)
|
||||
: valid_(true), ce_(ce), id_(sid), current_content_key_(NULL),
|
||||
rsa_key_(NULL) {}
|
||||
rsa_key_(NULL), allowed_schemes_(kSign_RSASSA_PSS) {}
|
||||
~SessionContext() {}
|
||||
|
||||
void Open();
|
||||
@@ -110,7 +110,8 @@ class SessionContext {
|
||||
bool GenerateRSASignature(const uint8_t* message,
|
||||
size_t message_length,
|
||||
uint8_t* signature,
|
||||
size_t* signature_length);
|
||||
size_t* signature_length,
|
||||
RSA_Padding_Scheme padding_scheme);
|
||||
bool ValidateMessage(const uint8_t* message,
|
||||
size_t message_length,
|
||||
const uint8_t* signature,
|
||||
@@ -177,6 +178,7 @@ class SessionContext {
|
||||
encryption_key_ = enc_key;
|
||||
}
|
||||
const std::vector<uint8_t>& encryption_key() { return encryption_key_; }
|
||||
const uint32_t allowed_schemes() { return allowed_schemes_; }
|
||||
|
||||
void AddNonce(uint32_t nonce);
|
||||
bool CheckNonce(uint32_t nonce);
|
||||
@@ -198,6 +200,7 @@ class SessionContext {
|
||||
SessionKeyTable session_keys_;
|
||||
NonceTable nonce_table_;
|
||||
RSA* rsa_key_;
|
||||
uint32_t allowed_schemes_; // for RSA signatures.
|
||||
time_t timer_start_;
|
||||
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(SessionContext);
|
||||
@@ -251,7 +254,7 @@ class CryptoEngine {
|
||||
const uint8_t* cipher_data,
|
||||
size_t cipher_data_length,
|
||||
bool is_encrypted,
|
||||
void* clear_data,
|
||||
uint8_t* clear_data,
|
||||
BufferType buffer_type);
|
||||
|
||||
private:
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
namespace wvoec_mock {
|
||||
|
||||
const WidevineKeybox kDefaultKeybox = {
|
||||
|
||||
// change to #if 0 for test provisioning server with mock library
|
||||
#if 1
|
||||
// Sample keybox used for test vectors
|
||||
{
|
||||
// deviceID
|
||||
@@ -47,6 +50,38 @@ const WidevineKeybox kDefaultKeybox = {
|
||||
// Crc
|
||||
0x0a, 0x7a, 0x2c, 0x35,
|
||||
}
|
||||
#else
|
||||
// Test keybox for temporary CAST provisioning server
|
||||
{
|
||||
// deviceID
|
||||
0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // a1
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||
}, {
|
||||
// key
|
||||
0x92, 0x13, 0xa7, 0xb0, 0x0e, 0xd9, 0x2c, 0xb0,
|
||||
0xba, 0x61, 0xc1, 0x89, 0x1f, 0x45, 0x34, 0x4a,
|
||||
}, {
|
||||
// data
|
||||
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x04,
|
||||
0x20, 0x8b, 0xf0, 0xba, 0x89, 0x39, 0x73, 0xb6,
|
||||
0x59, 0x82, 0x62, 0xa4, 0x72, 0x0c, 0xfe, 0xf4,
|
||||
0x70, 0xa7, 0x0a, 0xc6, 0xe5, 0x7c, 0x5e, 0x04,
|
||||
0x43, 0x8f, 0xa2, 0x87, 0x2b, 0xe1, 0x01, 0x67,
|
||||
0xba, 0x04, 0x99, 0x73, 0xe1, 0x92, 0x6e, 0x6e,
|
||||
0x9a, 0xf7, 0x67, 0x4e, 0xcd, 0xff, 0xb8, 0x43,
|
||||
0xc0, 0xb7, 0xa5, 0x5e, 0xc4, 0xd7, 0x3f, 0x35,
|
||||
0xf3, 0xc1, 0x84, 0x22, 0xe6, 0xf8, 0x2e, 0xfc,
|
||||
}, {
|
||||
// magic
|
||||
0x6b, 0x62, 0x6f, 0x78,
|
||||
}, {
|
||||
// Crc
|
||||
0x74, 0x57, 0x35, 0x2f,
|
||||
}
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
WvKeybox::WvKeybox() : valid_(false) {
|
||||
|
||||
@@ -895,7 +895,7 @@ OEMCryptoResult OEMCrypto_GenerateRSASignature(OEMCrypto_SESSION session,
|
||||
size_t message_length,
|
||||
uint8_t* signature,
|
||||
size_t* signature_length,
|
||||
RSA_Padding_Scheme algorithm) {
|
||||
RSA_Padding_Scheme padding_scheme) {
|
||||
if (trace_all_calls) {
|
||||
printf("-- OEMCryptoResult OEMCrypto_GenerateRSASignature()\n");
|
||||
dump_hex("message", message, message_length);
|
||||
@@ -928,15 +928,11 @@ OEMCryptoResult OEMCrypto_GenerateRSASignature(OEMCrypto_SESSION session,
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
|
||||
if (algorithm != kSign_RSASSA_PSS) {
|
||||
LOGE("[OEMCrypto_GenerateRSASignature(): OEMCrypto_ERROR_NOT_IMPLEMENTED]");
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
if (session_ctx->GenerateRSASignature(message,
|
||||
message_length,
|
||||
signature,
|
||||
signature_length)) {
|
||||
signature_length,
|
||||
padding_scheme)) {
|
||||
if (trace_all_calls) {
|
||||
dump_hex("signature", signature, *signature_length);
|
||||
}
|
||||
@@ -971,6 +967,11 @@ OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey(
|
||||
return OEMCrypto_ERROR_INVALID_SESSION;
|
||||
}
|
||||
|
||||
if (session_ctx->allowed_schemes() != kSign_RSASSA_PSS) {
|
||||
LOGE("[OEMCrypto_GenerateDerivedKeys(): x509 key used to derive keys]");
|
||||
return OEMCrypto_ERROR_INVALID_RSA_KEY;
|
||||
}
|
||||
|
||||
const std::vector<uint8_t> ssn_key_str(enc_session_key,
|
||||
enc_session_key + enc_session_key_length);
|
||||
const std::vector<uint8_t> mac_ctx_str(mac_key_context,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user