OEMCrypto v11 Documentation and Headers
Merge from widevine repo of http://go/wvgerrit/16186 These are the OEMCrypto v11 documents and header files. I have updated just enough code so that existing unit tests pass. New unit tests, the reference implementation, and the level 3 implementation are in future CLs. Change-Id: I9bbf1909e047f63a5877320a2d06740a3c4a3e32
This commit is contained in:
@@ -34,6 +34,7 @@ OEMCryptoResult OEMCrypto_GetNumberOfOpenSessions(SecurityLevel level,
|
||||
size_t* count);
|
||||
OEMCryptoResult OEMCrypto_GetMaxNumberOfSessions(SecurityLevel level,
|
||||
size_t* maximum);
|
||||
uint8_t OEMCrypto_Security_Patch_Level(SecurityLevel level);
|
||||
} // namespace wvcdm
|
||||
|
||||
#endif // WVCDM_CORE_OEMCRYPTO_ADAPTER_H_
|
||||
|
||||
@@ -683,10 +683,11 @@ CdmResponseType CryptoSession::Decrypt(const CdmDecryptionParameters& params) {
|
||||
}
|
||||
}
|
||||
}
|
||||
sts = OEMCrypto_DecryptCTR(
|
||||
// TODO(rfrias): add encrypt pattern parameter.
|
||||
sts = OEMCrypto_DecryptCENC(
|
||||
oec_session_id_, params.encrypt_buffer, params.encrypt_length,
|
||||
params.is_encrypted, &(*params.iv).front(), params.block_offset,
|
||||
&buffer_descriptor, params.subsample_flags);
|
||||
&buffer_descriptor, NULL, params.subsample_flags);
|
||||
}
|
||||
|
||||
switch (sts) {
|
||||
|
||||
@@ -30,6 +30,17 @@ using wvcdm::kLevel3;
|
||||
|
||||
namespace {
|
||||
|
||||
// TODO(fredgc): rename to _V10 after removing from level3.h.
|
||||
typedef struct {
|
||||
const uint8_t* key_id;
|
||||
size_t key_id_length;
|
||||
const uint8_t* key_data_iv;
|
||||
const uint8_t* key_data;
|
||||
size_t key_data_length;
|
||||
const uint8_t* key_control_iv;
|
||||
const uint8_t* key_control;
|
||||
} OEMCrypto_KeyObject_TODO;
|
||||
|
||||
typedef OEMCryptoResult (*L1_Initialize_t)(void);
|
||||
typedef OEMCryptoResult (*L1_Terminate_t)(void);
|
||||
typedef OEMCryptoResult (*L1_OpenSession_t)(OEMCrypto_SESSION* session);
|
||||
@@ -51,6 +62,12 @@ 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_V10_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_V10* 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,
|
||||
@@ -66,10 +83,15 @@ typedef OEMCryptoResult (*L1_QueryKeyControl_t)(
|
||||
typedef OEMCryptoResult (*L1_SelectKey_t)(const OEMCrypto_SESSION session,
|
||||
const uint8_t* key_id,
|
||||
size_t key_id_length);
|
||||
typedef OEMCryptoResult (*L1_DecryptCTR_t)(
|
||||
typedef OEMCryptoResult (*L1_DecryptCTR_V10_t)(
|
||||
OEMCrypto_SESSION session, const uint8_t* data_addr, size_t data_length,
|
||||
bool is_encrypted, const uint8_t* iv, size_t offset,
|
||||
const OEMCrypto_DestBufferDesc* out_buffer, uint8_t subsample_flags);
|
||||
typedef OEMCryptoResult (*L1_DecryptCENC_t)(
|
||||
OEMCrypto_SESSION session, const uint8_t* data_addr, size_t data_length,
|
||||
bool is_encrypted, const uint8_t* iv, size_t offset,
|
||||
const OEMCrypto_DestBufferDesc* out_buffer,
|
||||
const OEMCrypto_PatternDesc* pattern, uint8_t subsample_flags);
|
||||
typedef OEMCryptoResult (*L1_CopyBuffer_t)(const uint8_t* data_addr,
|
||||
size_t data_length,
|
||||
OEMCrypto_DestBufferDesc* out_buffer,
|
||||
@@ -113,6 +135,7 @@ typedef OEMCryptoResult (*L1_DeriveKeysFromSessionKey_t)(
|
||||
size_t mac_key_context_length, const uint8_t* enc_key_context,
|
||||
size_t enc_key_context_length);
|
||||
typedef uint32_t (*L1_APIVersion_t)();
|
||||
typedef uint8_t (*L1_SecurityPatchLevel_t)();
|
||||
typedef const char* (*L1_SecurityLevel_t)();
|
||||
typedef OEMCryptoResult (*L1_GetHDCPCapability_V9_t)(uint8_t* current,
|
||||
uint8_t* maximum);
|
||||
@@ -169,7 +192,8 @@ struct FunctionPointers {
|
||||
L1_RefreshKeys_t RefreshKeys;
|
||||
L1_QueryKeyControl_t QueryKeyControl;
|
||||
L1_SelectKey_t SelectKey;
|
||||
L1_DecryptCTR_t DecryptCTR;
|
||||
L1_DecryptCTR_V10_t DecryptCTR_V10;
|
||||
L1_DecryptCENC_t DecryptCENC;
|
||||
L1_CopyBuffer_t CopyBuffer;
|
||||
L1_WrapKeybox_t WrapKeybox;
|
||||
L1_InstallKeybox_t InstallKeybox;
|
||||
@@ -184,6 +208,7 @@ struct FunctionPointers {
|
||||
L1_GenerateRSASignature_t GenerateRSASignature;
|
||||
L1_DeriveKeysFromSessionKey_t DeriveKeysFromSessionKey;
|
||||
L1_APIVersion_t APIVersion;
|
||||
L1_SecurityPatchLevel_t SecurityPatchLevel;
|
||||
L1_SecurityLevel_t SecurityLevel;
|
||||
L1_GetHDCPCapability_t GetHDCPCapability;
|
||||
L1_SupportsUsageTable_t SupportsUsageTable;
|
||||
@@ -204,6 +229,7 @@ struct FunctionPointers {
|
||||
L1_LoadKeys_V8_t LoadKeys_V8;
|
||||
L1_GenerateRSASignature_V8_t GenerateRSASignature_V8;
|
||||
L1_GetHDCPCapability_V9_t GetHDCPCapability_V9;
|
||||
L1_LoadKeys_V10_t LoadKeys_V10;
|
||||
};
|
||||
|
||||
struct LevelSession {
|
||||
@@ -277,7 +303,6 @@ class Adapter {
|
||||
LOOKUP(GenerateSignature, OEMCrypto_GenerateSignature);
|
||||
LOOKUP(RefreshKeys, OEMCrypto_RefreshKeys);
|
||||
LOOKUP(SelectKey, OEMCrypto_SelectKey);
|
||||
LOOKUP(DecryptCTR, OEMCrypto_DecryptCTR);
|
||||
LOOKUP(InstallKeybox, OEMCrypto_InstallKeybox);
|
||||
LOOKUP(IsKeyboxValid, OEMCrypto_IsKeyboxValid);
|
||||
LOOKUP(GetDeviceID, OEMCrypto_GetDeviceID);
|
||||
@@ -333,6 +358,14 @@ class Adapter {
|
||||
LOOKUP(GetNumberOfOpenSessions, OEMCrypto_GetNumberOfOpenSessions);
|
||||
LOOKUP(GetMaxNumberOfSessions, OEMCrypto_GetMaxNumberOfSessions);
|
||||
LOOKUP(ForceDeleteUsageEntry, OEMCrypto_ForceDeleteUsageEntry);
|
||||
if (level1_.version == 10) {
|
||||
LOOKUP(LoadKeys_V10, OEMCrypto_LoadKeys_V10);
|
||||
LOOKUP(DecryptCTR_V10, OEMCrypto_DecryptCTR_V10);
|
||||
} else {
|
||||
LOOKUP(LoadKeys, OEMCrypto_LoadKeys);
|
||||
LOOKUP(DecryptCENC, OEMCrypto_DecryptCENC);
|
||||
LOOKUP(SecurityPatchLevel, OEMCrypto_Security_Patch_Level);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OEMCrypto_SUCCESS == level1_.IsKeyboxValid()) {
|
||||
@@ -387,11 +420,11 @@ class Adapter {
|
||||
level3_.GenerateDerivedKeys = Level3_GenerateDerivedKeys;
|
||||
level3_.GenerateNonce = Level3_GenerateNonce;
|
||||
level3_.GenerateSignature = Level3_GenerateSignature;
|
||||
level3_.LoadKeys = Level3_LoadKeys;
|
||||
level3_.LoadKeys_V10 = Level3_LoadKeys;
|
||||
level3_.RefreshKeys = Level3_RefreshKeys;
|
||||
level3_.QueryKeyControl = Level3_QueryKeyControl;
|
||||
level3_.SelectKey = Level3_SelectKey;
|
||||
level3_.DecryptCTR = Level3_DecryptCTR;
|
||||
level3_.DecryptCTR_V10 = Level3_DecryptCTR;
|
||||
level3_.CopyBuffer = Level3_CopyBuffer;
|
||||
level3_.WrapKeybox = Level3_WrapKeybox;
|
||||
level3_.InstallKeybox = Level3_InstallKeybox;
|
||||
@@ -572,6 +605,14 @@ uint32_t OEMCrypto_APIVersion(SecurityLevel level) {
|
||||
return fcn->APIVersion();
|
||||
}
|
||||
|
||||
uint8_t OEMCrypto_Security_Patch_Level(SecurityLevel level) {
|
||||
if (!kAdapter) return 0;
|
||||
const FunctionPointers* fcn = kAdapter->get(level);
|
||||
if (!fcn) return 0;
|
||||
if (fcn->version < 10) return 0;
|
||||
return fcn->SecurityPatchLevel();
|
||||
}
|
||||
|
||||
const char* OEMCrypto_SecurityLevel(SecurityLevel level) {
|
||||
if (!kAdapter) return "";
|
||||
const FunctionPointers* fcn = kAdapter->get(level);
|
||||
@@ -705,6 +746,25 @@ extern "C" OEMCryptoResult OEMCrypto_LoadKeys(
|
||||
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 if (pair.fcn->version < 11) {
|
||||
std::vector<OEMCrypto_KeyObject_V10> key_array_v10(num_keys);
|
||||
for(int i=0; i< num_keys; i++) {
|
||||
key_array_v10[i].key_id = key_array[i].key_id;
|
||||
key_array_v10[i].key_id_length = key_array[i].key_id_length;
|
||||
key_array_v10[i].key_data_iv = key_array[i].key_data_iv;
|
||||
key_array_v10[i].key_data = key_array[i].key_data;
|
||||
key_array_v10[i].key_data_length = key_array[i].key_data_length;
|
||||
key_array_v10[i].key_control_iv = key_array[i].key_control_iv;
|
||||
key_array_v10[i].key_control = key_array[i].key_control;
|
||||
if (key_array[i].cipher_mode == OEMCrypto_CipherMode_CBC) {
|
||||
LOGE("CBC Mode not supported.");
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
||||
return pair.fcn->LoadKeys_V10(pair.session, message, message_length,
|
||||
signature,
|
||||
signature_length, enc_mac_key_iv, enc_mac_key,
|
||||
num_keys, &key_array_v10[0], pst, pst_length);
|
||||
} else {
|
||||
return pair.fcn->LoadKeys(pair.session, message, message_length, signature,
|
||||
signature_length, enc_mac_key_iv, enc_mac_key,
|
||||
@@ -743,16 +803,23 @@ extern "C" OEMCryptoResult OEMCrypto_SelectKey(const OEMCrypto_SESSION session,
|
||||
return pair.fcn->SelectKey(pair.session, key_id, key_id_length);
|
||||
}
|
||||
|
||||
extern "C" OEMCryptoResult OEMCrypto_DecryptCTR(
|
||||
extern "C" OEMCryptoResult OEMCrypto_DecryptCENC(
|
||||
OEMCrypto_SESSION session, const uint8_t* data_addr, size_t data_length,
|
||||
bool is_encrypted, const uint8_t* iv, size_t offset,
|
||||
OEMCrypto_DestBufferDesc* out_buffer, uint8_t subsample_flags) {
|
||||
OEMCrypto_DestBufferDesc* out_buffer, const OEMCrypto_PatternDesc* pattern,
|
||||
uint8_t subsample_flags) {
|
||||
if (!kAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
LevelSession pair = kAdapter->get(session);
|
||||
if (!pair.fcn) return OEMCrypto_ERROR_INVALID_SESSION;
|
||||
return pair.fcn->DecryptCTR(pair.session, data_addr, data_length,
|
||||
if (pair.fcn->version < 11) {
|
||||
return pair.fcn->DecryptCTR_V10(pair.session, data_addr, data_length,
|
||||
is_encrypted, iv, offset, out_buffer,
|
||||
subsample_flags);
|
||||
} else {
|
||||
return pair.fcn->DecryptCENC(pair.session, data_addr, data_length,
|
||||
is_encrypted, iv, offset, out_buffer, pattern,
|
||||
subsample_flags);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" OEMCryptoResult OEMCrypto_CopyBuffer(
|
||||
|
||||
Binary file not shown.
Binary file not shown.
BIN
libwvdrmengine/docs/Widevine_Modular_DRM_Version_11_Delta.pdf
Normal file
BIN
libwvdrmengine/docs/Widevine_Modular_DRM_Version_11_Delta.pdf
Normal file
Binary file not shown.
@@ -121,6 +121,14 @@ typedef struct {
|
||||
} buffer;
|
||||
} OEMCrypto_DestBufferDesc;
|
||||
|
||||
/** OEMCryptoCipherMode is used in LoadKeys to prepare a key for either CTR
|
||||
* decryption or CBC decryption.
|
||||
*/
|
||||
typedef enum OEMCryptoCipherMode {
|
||||
OEMCrypto_CipherMode_CTR,
|
||||
OEMCrypto_CipherMode_CBC,
|
||||
} OEMCryptoCipherMode;
|
||||
|
||||
/*
|
||||
* OEMCrypto_KeyObject
|
||||
* Points to the relevant fields for a content key. The fields are extracted
|
||||
@@ -137,6 +145,8 @@ typedef struct {
|
||||
* key_control field.
|
||||
* key_control - the key control block. It is encrypted (AES-128-CBC) with
|
||||
* the content key from the key_data field.
|
||||
* cipher_mode - whether the key should be prepared for CTR mode or CBC mode
|
||||
* when used in later calls to DecryptCENC.
|
||||
*
|
||||
* The memory for the OEMCrypto_KeyObject fields is allocated and freed
|
||||
* by the caller of OEMCrypto_LoadKeys().
|
||||
@@ -149,6 +159,7 @@ typedef struct {
|
||||
size_t key_data_length;
|
||||
const uint8_t* key_control_iv;
|
||||
const uint8_t* key_control;
|
||||
OEMCryptoCipherMode cipher_mode;
|
||||
} OEMCrypto_KeyObject;
|
||||
|
||||
/*
|
||||
@@ -188,11 +199,21 @@ typedef enum OEMCrypto_Algorithm {
|
||||
} OEMCrypto_Algorithm;
|
||||
|
||||
/*
|
||||
* Flags indicating data endpoints in OEMCrypto_DecryptCTR.
|
||||
* Flags indicating data endpoints in OEMCrypto_DecryptCENC.
|
||||
*/
|
||||
#define OEMCrypto_FirstSubsample 1
|
||||
#define OEMCrypto_LastSubsample 2
|
||||
|
||||
/* OEMCrypto_PatternDesc
|
||||
* This is used in OEMCrypto_DecryptCENC to indicate the encrypt/skip pattern
|
||||
* used, as specified in the CENC standard.
|
||||
*/
|
||||
typedef struct {
|
||||
size_t encrypt; // number of 16 byte blocks to decrypt.
|
||||
size_t skip; // number of 16 byte blocks to leave in clear.
|
||||
size_t offset; // offset into the pattern in blocks for this call.
|
||||
} OEMCrypto_PatternDesc;
|
||||
|
||||
/*
|
||||
* OEMCrypto_Usage_Entry_Status.
|
||||
* Valid values for status in the usage table.
|
||||
@@ -284,7 +305,7 @@ typedef enum OEMCrypto_HDCP_Capability {
|
||||
#define OEMCrypto_ReportUsage _oecc32
|
||||
#define OEMCrypto_DeleteUsageEntry _oecc33
|
||||
#define OEMCrypto_DeleteUsageTable _oecc34
|
||||
#define OEMCrypto_LoadKeys _oecc35
|
||||
#define OEMCrypto_LoadKeys_v10 _oecc35
|
||||
#define OEMCrypto_GenerateRSASignature _oecc36
|
||||
#define OEMCrypto_GetMaxNumberOfSessions _oecc37
|
||||
#define OEMCrypto_GetNumberOfOpenSessions _oecc38
|
||||
@@ -295,6 +316,9 @@ typedef enum OEMCrypto_HDCP_Capability {
|
||||
#define OEMCrypto_ForceDeleteUsageEntry _oecc43
|
||||
#define OEMCrypto_GetHDCPCapability _oecc44
|
||||
#define OEMCrypto_LoadTestRSAKey _oecc45
|
||||
#define OEMCrypto_Security_Patch_Level _oecc46
|
||||
#define OEMCrypto_LoadKeys _oecc47
|
||||
#define OEMCrypto_DecryptCENC _oecc48
|
||||
|
||||
|
||||
/*
|
||||
@@ -565,10 +589,12 @@ OEMCryptoResult OEMCrypto_GenerateSignature(
|
||||
* the previous call to OEMCrypto_GenerateNonce().
|
||||
*
|
||||
* This session’s elapsed time clock is started at 0. The clock will be used
|
||||
* in OEMCrypto_DecryptCTR().
|
||||
* in OEMCrypto_DecryptCENC().
|
||||
*
|
||||
* NOTE: OEMCrypto_GenerateDerivedKeys() must be called first to establish the
|
||||
* mac_key and encrypt_key.
|
||||
* NOTE: The calling software must have previously established the mac_keys
|
||||
* and encrypt_key with a call to OEMCrypto_GenerateDerivedKeys(),
|
||||
* OEMCrypto_DeriveKeysFromSessionKey(), or a previous call to
|
||||
* OEMCrypto_LoadKeys().
|
||||
*
|
||||
* Refer to document "Widevine Modular DRM Security Integration Guide for
|
||||
* CENC" for details.
|
||||
@@ -604,9 +630,15 @@ OEMCryptoResult OEMCrypto_GenerateSignature(
|
||||
* the cache. Note that all the key control blocks in a particular call shall
|
||||
* have the same nonce value.
|
||||
*
|
||||
* 6. If the key control block has a nonzero Replay_Control, then the
|
||||
* 6. If any key control block has the Require_AntiRollback_Hardware bit set,
|
||||
* and the device does not protect the usage table from rollback, then do not
|
||||
* load the keys and return OEMCrypto_ERROR_UNKNOWN_FAILURE.
|
||||
*
|
||||
* 7. If the key control block has a nonzero Replay_Control, then the
|
||||
* verification described below is also performed.
|
||||
*
|
||||
* 8. If num_keys == 0, then return OEMCrypto_ERROR_INVALID_CONTEXT.
|
||||
*
|
||||
* Usage Table and Provider Session Token (pst):
|
||||
*
|
||||
* If a key control block has a nonzero value for Replay_Control, then all keys
|
||||
@@ -652,6 +684,10 @@ OEMCryptoResult OEMCrypto_GenerateSignature(
|
||||
* Devices that do not support the Usage Table will return
|
||||
* OEMCrypto_ERROR_INVALID_CONTEXT if the Replay_Control is nonzero.
|
||||
*
|
||||
* Note: If LoadKeys creates a new entry in the usage table, OEMCrypto will
|
||||
* increment the Usage Table’s generation number, and then sign, encrypt, and
|
||||
* save the Usage Table.
|
||||
*
|
||||
* Parameters:
|
||||
* session (in) - crypto session identifier.
|
||||
* message (in) - pointer to memory containing message to be verified.
|
||||
@@ -681,7 +717,7 @@ OEMCryptoResult OEMCrypto_GenerateSignature(
|
||||
* OEMCrypto_ERROR_UNKNOWN_FAILURE
|
||||
*
|
||||
* Version:
|
||||
* This method changed in API version 9.
|
||||
* This method changed in API version 11.
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session,
|
||||
const uint8_t* message,
|
||||
@@ -714,7 +750,7 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session,
|
||||
* first to establish the mac_key[server].
|
||||
*
|
||||
* This session’s elapsed time clock is reset to 0 when this function is called.
|
||||
* The elapsed time clock is used in OEMCrypto_DecryptCTR().
|
||||
* The elapsed time clock is used in OEMCrypto_DecryptCENC().
|
||||
*
|
||||
* This function does not add keys to the key table. It is only used to update a
|
||||
* key control block license duration. Refer to the License Signing and
|
||||
@@ -849,7 +885,7 @@ OEMCrypto_QueryKeyControl(OEMCrypto_SESSION session,
|
||||
*
|
||||
* Description:
|
||||
* Select a content key and install it in the hardware key ladder for
|
||||
* subsequent decryption operations (OEMCrypto_DecryptCTR()) for this session.
|
||||
* subsequent decryption operations (OEMCrypto_DecryptCENC()) for this session.
|
||||
* The specified key must have been previously "installed" via
|
||||
* OEMCrypto_LoadKeys() or OEMCrypto_RefreshKeys().
|
||||
*
|
||||
@@ -864,7 +900,7 @@ OEMCrypto_QueryKeyControl(OEMCrypto_SESSION session,
|
||||
* permission flags and timers based on the key's control block.
|
||||
*
|
||||
* Step 3: use the latched content key to decrypt (AES-128-CTR) buffers passed in
|
||||
* via OEMCrypto_DecryptCTR(). If the key is 256 bits it will be used for
|
||||
* via OEMCrypto_DecryptCENC(). If the key is 256 bits it will be used for
|
||||
* OEMCrypto_Generic_Sign or OEMCrypto_Generic_Verify as specified in the key
|
||||
* control block. Continue to use this key until OEMCrypto_SelectKey() is called
|
||||
* again, or until OEMCrypto_CloseSession() is called.
|
||||
@@ -898,15 +934,17 @@ OEMCryptoResult OEMCrypto_SelectKey(OEMCrypto_SESSION session,
|
||||
size_t key_id_length);
|
||||
|
||||
/*
|
||||
* OEMCrypto_DecryptCTR
|
||||
* OEMCrypto_DecryptCENC
|
||||
*
|
||||
* Description:
|
||||
* Decrypts (AES-128-CTR) or copies the payload in the buffer referenced by the
|
||||
* data_addr parameter into the buffer referenced by the out_buffer parameter,
|
||||
* using the session context indicated by the session parameter. If is_encrypted
|
||||
* is true, the content key associated with the session is latched in the active
|
||||
* hardware key ladder and is used for the decryption operation. If is_encrypted
|
||||
* is false, the data is simply copied.
|
||||
* Decrypts or copies the payload in the buffer referenced by the *data_addr
|
||||
* parameter into the buffer referenced by the out_buffer parameter, using
|
||||
* the session context indicated by the session parameter. Decryption mode
|
||||
* is AES-128-CTR or AES-128-CBC depending on the value of cipher_mode set in
|
||||
* the OEMCrypto_KeyObject passed in to OEMCrypto_LoadKeys. If is_encrypted
|
||||
* is true, the content key associated with the session is latched in the
|
||||
* active hardware key ladder and is used for the decryption operation. If
|
||||
* is_encrypted is false, the data is simply copied.
|
||||
*
|
||||
* After decryption, the data_length bytes are copied to the location described
|
||||
* by out_buffer. This could be one of
|
||||
@@ -921,13 +959,13 @@ OEMCryptoResult OEMCrypto_SelectKey(OEMCrypto_SESSION session,
|
||||
* the decoder and rendered.
|
||||
*
|
||||
* NOTES:
|
||||
* IV points to the counter value to be used for the initial
|
||||
* encrypted block of the input buffer. The IV length is the AES
|
||||
* block size. For subsequent encrypted AES blocks the IV is
|
||||
* calculated by incrementing the lower 64 bits (byte 8-15) of the
|
||||
* IV value used for the previous block. The counter rolls over to
|
||||
* zero when it reaches its maximum value (0xFFFFFFFFFFFFFFFF).
|
||||
* The upper 64 bits (byte 0-7) of the IV do not change.
|
||||
* For CTR mode, IV points to the counter value to be used for the initial
|
||||
* encrypted block of the input buffer. The IV length is the AES block
|
||||
* size. For subsequent encrypted AES blocks the IV is calculated by
|
||||
* incrementing the lower 64 bits (byte 8-15) of the IV value used for the
|
||||
* previous block. The counter rolls over to zero when it reaches its maximum
|
||||
* value (0xFFFFFFFFFFFFFFFF). The upper 64 bits (byte 0-7) of the IV do not
|
||||
* change.
|
||||
*
|
||||
* This method may be called several times before the decrypted data is used.
|
||||
* For this reason, the parameter subsample_flags may be used to optimize
|
||||
@@ -938,7 +976,7 @@ OEMCryptoResult OEMCrypto_SelectKey(OEMCrypto_SESSION session,
|
||||
* OEMCrypto_LastSubsample has been set. If an implementation decrypts data
|
||||
* immediately, it may ignore subsample_flags.
|
||||
*
|
||||
* If the destination buffer is secure, an offset may be specified. DecryptCTR
|
||||
* If the destination buffer is secure, an offset may be specified. DecryptCENC
|
||||
* begins storing data out_buffer->secure.offset bytes after the beginning of the
|
||||
* secure buffer.
|
||||
*
|
||||
@@ -946,6 +984,13 @@ OEMCryptoResult OEMCrypto_SelectKey(OEMCrypto_SESSION session,
|
||||
* time_of_last_decrypt. If the status of the entry is "unused", then change the
|
||||
* status to "active" and set the time_of_first_decrypt.
|
||||
*
|
||||
* The decryption mode, either OEMCrypto_CipherMode_CTR or
|
||||
* OEMCrypto_CipherMode_CBC, was specified in the call to OEMCrypto_LoadKeys.
|
||||
* The encryption pattern is specified in by the parameter pattern. A
|
||||
* description of partial encryption patterns can be found in the document
|
||||
* Draft International Standard ISO/IEC DIS 23001-7. Search for the codes
|
||||
* "cenc", "cbc1", "cens" or "cbcs".
|
||||
*
|
||||
*
|
||||
* Verification:
|
||||
* The following checks should be performed if is_encrypted is true. If any
|
||||
@@ -992,9 +1037,12 @@ OEMCryptoResult OEMCrypto_SelectKey(OEMCrypto_SESSION session,
|
||||
* decryption block start address and data_addr are discarded
|
||||
* after decryption. It does not adjust the beginning of the
|
||||
* source or destination data. This parameter satisfies
|
||||
* 0 <= block_offset < 16.
|
||||
* 0 <= block_offset < 16. This paramater is only used
|
||||
* for CTR mode.
|
||||
* out_buffer (in) - A caller-owned descriptor that specifies the handling of the
|
||||
* decrypted byte stream. See OEMCrypto_DestbufferDesc for details.
|
||||
* pattern (in) - A caller-owned structure indicating the encrypt/skip
|
||||
* pattern as specified in the CENC standard.
|
||||
* subsample_flags (in) - bitwise flags indicating if this is the first, middle,
|
||||
* or last subsample in a chunk of data.
|
||||
* 0 = neither first nor last subsample,
|
||||
@@ -1018,15 +1066,17 @@ OEMCryptoResult OEMCrypto_SelectKey(OEMCrypto_SESSION session,
|
||||
* OEMCrypto_ERROR_UNKNOWN_FAILURE
|
||||
*
|
||||
* Version:
|
||||
* This method changed in API version 9.
|
||||
* This method changed in API version 11.
|
||||
* This method changed its name in API version 11.
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session,
|
||||
OEMCryptoResult OEMCrypto_DecryptCENC(OEMCrypto_SESSION session,
|
||||
const uint8_t *data_addr,
|
||||
size_t data_length,
|
||||
bool is_encrypted,
|
||||
const uint8_t *iv,
|
||||
size_t block_offset,
|
||||
OEMCrypto_DestBufferDesc* out_buffer,
|
||||
const OEMCrypto_PatternDesc* pattern,
|
||||
uint8_t subsample_flags);
|
||||
|
||||
|
||||
@@ -1037,9 +1087,9 @@ OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session,
|
||||
* Copies the payload in the buffer referenced by the *data_addr parameter into
|
||||
* the buffer referenced by the out_buffer parameter. The data is simply
|
||||
* copied. The definition of OEMCrypto_DestBufferDesc and subsample_flags are
|
||||
* the same as in OEMCrypto_DecryptCTR, above.
|
||||
* the same as in OEMCrypto_DecryptCENC, above.
|
||||
*
|
||||
* The main difference between this and DecryptCTR is that this function does
|
||||
* The main difference between this and DecryptCENC is that this function does
|
||||
* not need an open session, and it may be called concurrently with other
|
||||
* session functions on a multithreaded system. In particular, an application
|
||||
* will use this to copy the clear leader of a video to a secure buffer while
|
||||
@@ -1648,9 +1698,6 @@ OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey(OEMCrypto_SESSION session,
|
||||
* There is no plan to introduce forward-compatibility. Applications will reject
|
||||
* a library with a newer version of the API.
|
||||
*
|
||||
* The version specified in this document is 9. Any OEM that returns this
|
||||
* version number guarantees it passes all unit tests associated this version.
|
||||
*
|
||||
* Parameters:
|
||||
* none
|
||||
*
|
||||
@@ -1665,6 +1712,28 @@ OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey(OEMCrypto_SESSION session,
|
||||
*/
|
||||
uint32_t OEMCrypto_APIVersion();
|
||||
|
||||
/**
|
||||
* OEMCrypto_Security_Patch_Level()
|
||||
*
|
||||
* Description:
|
||||
* This function returns the current patch level of the software running in
|
||||
* the trusted environment. The patch level is defined by the OEM, and is
|
||||
* only incremented when a security update has been added.
|
||||
*
|
||||
* Parameters:
|
||||
* none
|
||||
*
|
||||
* Returns:
|
||||
* The OEM defined version number.
|
||||
*
|
||||
* Threading:
|
||||
* This function may be called simultaneously with any other functions.
|
||||
*
|
||||
* Version:
|
||||
* This method was introduced in API version 11.
|
||||
*/
|
||||
uint8_t OEMCrypto_Security_Patch_Level();
|
||||
|
||||
/*
|
||||
* OEMCrypto_SecurityLevel()
|
||||
*
|
||||
|
||||
@@ -77,6 +77,17 @@ OEMCryptoResult Level3_GenerateSignature(OEMCrypto_SESSION session,
|
||||
size_t message_length,
|
||||
uint8_t* signature,
|
||||
size_t* signature_length);
|
||||
// TODO(fredgc): move this to oemcrypto_adapter_dynamic.cpp
|
||||
typedef struct {
|
||||
const uint8_t* key_id;
|
||||
size_t key_id_length;
|
||||
const uint8_t* key_data_iv;
|
||||
const uint8_t* key_data;
|
||||
size_t key_data_length;
|
||||
const uint8_t* key_control_iv;
|
||||
const uint8_t* key_control;
|
||||
} OEMCrypto_KeyObject_V10;
|
||||
|
||||
OEMCryptoResult Level3_LoadKeys(OEMCrypto_SESSION session,
|
||||
const uint8_t* message,
|
||||
size_t message_length,
|
||||
@@ -85,7 +96,7 @@ OEMCryptoResult Level3_LoadKeys(OEMCrypto_SESSION session,
|
||||
const uint8_t* enc_mac_key_iv,
|
||||
const uint8_t* enc_mac_key,
|
||||
size_t num_keys,
|
||||
const OEMCrypto_KeyObject* key_array,
|
||||
const OEMCrypto_KeyObject_V10* key_array,
|
||||
const uint8_t* pst,
|
||||
size_t pst_length);
|
||||
OEMCryptoResult Level3_RefreshKeys(OEMCrypto_SESSION session,
|
||||
|
||||
@@ -596,13 +596,14 @@ OEMCryptoResult SetDestination(OEMCrypto_DestBufferDesc* out_buffer,
|
||||
}
|
||||
|
||||
extern "C"
|
||||
OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session,
|
||||
OEMCryptoResult OEMCrypto_DecryptCENC(OEMCrypto_SESSION session,
|
||||
const uint8_t* data_addr,
|
||||
size_t data_length,
|
||||
bool is_encrypted,
|
||||
const uint8_t* iv,
|
||||
size_t block_offset,
|
||||
OEMCrypto_DestBufferDesc* out_buffer,
|
||||
const OEMCrypto_PatternDesc* pattern,
|
||||
uint8_t subsample_flags) {
|
||||
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
||||
LOGI("-- OEMCryptoResult OEMCrypto_DecryptCTR"
|
||||
@@ -1207,7 +1208,13 @@ OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey(
|
||||
|
||||
extern "C"
|
||||
uint32_t OEMCrypto_APIVersion() {
|
||||
return 10;
|
||||
// TODO(fredgc): Implement new API.
|
||||
return 11;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
uint8_t OEMCrypto_Security_Patch_Level() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
|
||||
@@ -828,6 +828,7 @@ class Session {
|
||||
key_array[i].key_control_iv = data.keys[i].control_iv;
|
||||
key_array[i].key_control =
|
||||
reinterpret_cast<const uint8_t*>(&data.keys[i].control);
|
||||
key_array[i].cipher_mode = OEMCrypto_CipherMode_CTR;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -887,10 +888,14 @@ class Session {
|
||||
destBuffer.type = OEMCrypto_BufferType_Clear;
|
||||
destBuffer.buffer.clear.address = outputBuffer.data();
|
||||
destBuffer.buffer.clear.max_length = outputBuffer.size();
|
||||
OEMCrypto_PatternDesc pattern;
|
||||
pattern.encrypt = 1; // TODO(fredgc): test other values.
|
||||
pattern.skip = 0;
|
||||
pattern.offset = 0;
|
||||
// Decrypt the data
|
||||
sts = OEMCrypto_DecryptCTR(
|
||||
sts = OEMCrypto_DecryptCENC(
|
||||
session_id(), &encryptedData[0], encryptedData.size(), true,
|
||||
&encryptionIv[0], 0, &destBuffer,
|
||||
&encryptionIv[0], 0, &destBuffer, &pattern,
|
||||
OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample);
|
||||
// We only have a few errors that we test are reported.
|
||||
if (expected_result == OEMCrypto_SUCCESS) { // No error.
|
||||
@@ -1283,7 +1288,7 @@ TEST_F(OEMCryptoClientTest, VersionNumber) {
|
||||
cout << " OEMCrypto does not support usage tables." << endl;
|
||||
}
|
||||
ASSERT_GE(version, 8u);
|
||||
ASSERT_LE(version, 10u);
|
||||
ASSERT_LE(version, 11u);
|
||||
}
|
||||
|
||||
const char* HDCPCapabilityAsString(OEMCrypto_HDCP_Capability value) {
|
||||
@@ -2259,6 +2264,10 @@ TEST_F(OEMCryptoSessionTests, DecryptPerformance) {
|
||||
OEMCrypto_DestBufferDesc destBuffer;
|
||||
destBuffer.type = OEMCrypto_BufferType_Clear;
|
||||
destBuffer.buffer.clear.address = &output[0];
|
||||
OEMCrypto_PatternDesc pattern;
|
||||
pattern.encrypt = 1; // TODO(fredgc): test other values.
|
||||
pattern.skip = 0;
|
||||
pattern.offset = 0;
|
||||
|
||||
const char* level = OEMCrypto_SecurityLevel();
|
||||
const int n = 10;
|
||||
@@ -2278,9 +2287,9 @@ TEST_F(OEMCryptoSessionTests, DecryptPerformance) {
|
||||
size_t total = 0;
|
||||
do {
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_DecryptCTR(
|
||||
OEMCrypto_DecryptCENC(
|
||||
s.session_id(), &input[0], length, true,
|
||||
&encryptionIv[0], 0, &destBuffer,
|
||||
&encryptionIv[0], 0, &destBuffer, &pattern,
|
||||
OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample));
|
||||
count++;
|
||||
total += length;
|
||||
@@ -2377,6 +2386,11 @@ class OEMCryptoSessionTestsDecryptEdgeCases : public OEMCryptoSessionTests {
|
||||
s.license().keys[0].key_id_length);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
|
||||
OEMCrypto_PatternDesc pattern;
|
||||
pattern.encrypt = 1; // TODO(fredgc): test other values.
|
||||
pattern.skip = 0;
|
||||
pattern.offset = 0;
|
||||
|
||||
// We decrypt three subsamples. each with a block offset.
|
||||
vector<uint8_t> outputBuffer(total_size, 0xaa);
|
||||
size_t buffer_offset = 0;
|
||||
@@ -2395,9 +2409,9 @@ class OEMCryptoSessionTestsDecryptEdgeCases : public OEMCryptoSessionTests {
|
||||
memcpy(aes_iv, &encryptionIv[0], AES_BLOCK_SIZE);
|
||||
size_t iv_increment = buffer_offset / AES_BLOCK_SIZE;
|
||||
ctr128_inc64(iv_increment, aes_iv);
|
||||
sts = OEMCrypto_DecryptCTR(
|
||||
sts = OEMCrypto_DecryptCENC(
|
||||
s.session_id(), &encryptedData[buffer_offset], subsample_size[i],
|
||||
true, aes_iv, block_offset, &destBuffer, subsample_flags);
|
||||
true, aes_iv, block_offset, &destBuffer, &pattern, subsample_flags);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
buffer_offset += subsample_size[i];
|
||||
}
|
||||
@@ -2531,11 +2545,15 @@ TEST_F(OEMCryptoSessionTests, DecryptUnencrypted) {
|
||||
destBuffer.type = OEMCrypto_BufferType_Clear;
|
||||
destBuffer.buffer.clear.address = &outputBuffer[0];
|
||||
destBuffer.buffer.clear.max_length = outputBuffer.size();
|
||||
OEMCrypto_PatternDesc pattern;
|
||||
pattern.encrypt = 1; // TODO(fredgc): test other values.
|
||||
pattern.skip = 0;
|
||||
pattern.offset = 0;
|
||||
|
||||
// Decrypt the data
|
||||
sts = OEMCrypto_DecryptCTR(
|
||||
sts = OEMCrypto_DecryptCENC(
|
||||
s.session_id(), &unencryptedData[0], unencryptedData.size(), false,
|
||||
&encryptionIv[0], 0, &destBuffer,
|
||||
&encryptionIv[0], 0, &destBuffer, &pattern,
|
||||
OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
ASSERT_EQ(unencryptedData, outputBuffer);
|
||||
@@ -2566,11 +2584,15 @@ TEST_F(OEMCryptoSessionTests, DecryptUnencryptedNoKey) {
|
||||
destBuffer.type = OEMCrypto_BufferType_Clear;
|
||||
destBuffer.buffer.clear.address = &outputBuffer[0];
|
||||
destBuffer.buffer.clear.max_length = outputBuffer.size();
|
||||
OEMCrypto_PatternDesc pattern;
|
||||
pattern.encrypt = 1; // TODO(fredgc): test other values.
|
||||
pattern.skip = 0;
|
||||
pattern.offset = 0;
|
||||
|
||||
// Decrypt the data
|
||||
sts = OEMCrypto_DecryptCTR(
|
||||
sts = OEMCrypto_DecryptCENC(
|
||||
s.session_id(), &unencryptedData[0], unencryptedData.size(), false,
|
||||
&encryptionIv[0], 0, &destBuffer,
|
||||
&encryptionIv[0], 0, &destBuffer, &pattern,
|
||||
OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
ASSERT_EQ(unencryptedData, outputBuffer);
|
||||
|
||||
Reference in New Issue
Block a user