File util, generic crypto, and key query

This CL merges several CLs from the widevine repo:

http://go/wvgerrit/18012 Add support for querying allowed usage for key.
http://go/wvgerrit/17971 Add per-origin storage.
http://go/wvgerrit/18152 Add OEMCrypto's generic crypto operations to CDM.
http://go/wvgerrit/17911 QueryKeyControlInfo => QueryOemCryptoSessionId

Note: numbering in wv_cdm_types.h was added in this CL and will be
back ported to wvgerrit in a future CL.

Change-Id: Idb9e9a67e94f62f25dc16c5307f75a08b3430b64
This commit is contained in:
Fred Gylys-Colwell
2016-09-14 12:44:09 -07:00
parent 24124ea6e3
commit eb3f8b786a
56 changed files with 4632 additions and 2083 deletions

View File

@@ -56,17 +56,19 @@ void CryptoSession::Init() {
LOGV("CryptoSession::Init");
AutoLock auto_lock(crypto_lock_);
session_count_ += 1;
if (initialized_) return;
OEMCryptoResult sts = OEMCrypto_Initialize();
if (OEMCrypto_SUCCESS != sts) {
LOGE("OEMCrypto_Initialize failed: %d", sts);
return;
if (!initialized_) {
OEMCryptoResult sts = OEMCrypto_Initialize();
if (OEMCrypto_SUCCESS != sts) {
LOGE("OEMCrypto_Initialize failed: %d", sts);
return;
}
initialized_ = true;
}
initialized_ = true;
}
void CryptoSession::Terminate() {
LOGV("CryptoSession::Terminate");
LOGE("CryptoSession::Terminate: initialized_=%d, session_count_=%d",
initialized_, session_count_);
AutoLock auto_lock(crypto_lock_);
if (session_count_ > 0) {
session_count_ -= 1;
@@ -252,16 +254,15 @@ CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) {
LOGV("OpenSession: id= %ld", (uint32_t)oec_session_id_);
open_ = true;
} else if (OEMCrypto_ERROR_TOO_MANY_SESSIONS == sts) {
LOGE("OEMCrypto_Open failed: %d, open sessions: %ld, initialized: %d", sts,
session_count_, (int)initialized_);
LOGE("OEMCrypto_Open failed: %d, open sessions: %ld, initialized: %d",
sts, session_count_, (int)initialized_);
return INSUFFICIENT_CRYPTO_RESOURCES;
}
if (!open_) {
LOGE("OEMCrypto_Open failed: %d, open sessions: %ld, initialized: %d", sts,
session_count_, (int)initialized_);
LOGE("OEMCrypto_Open failed: %d, open sessions: %ld, initialized: %d",
sts, session_count_, (int)initialized_);
return UNKNOWN_ERROR;
}
OEMCrypto_GetRandom(reinterpret_cast<uint8_t*>(&request_id_base_),
sizeof(request_id_base_));
++request_id_index_;
@@ -507,12 +508,22 @@ bool CryptoSession::RefreshKeys(const std::string& message,
}
bool CryptoSession::SelectKey(const std::string& key_id) {
// Crypto session lock already locked.
if (!cached_key_id_.empty() && cached_key_id_ == key_id) {
// Already using the desired key.
return true;
}
cached_key_id_ = key_id;
const uint8_t* key_id_string =
reinterpret_cast<const uint8_t*>(key_id.data());
reinterpret_cast<const uint8_t*>(cached_key_id_.data());
OEMCryptoResult sts =
OEMCrypto_SelectKey(oec_session_id_, key_id_string, key_id.size());
OEMCrypto_SelectKey(oec_session_id_, key_id_string,
cached_key_id_.size());
if (OEMCrypto_SUCCESS != sts) {
cached_key_id_.clear();
return false;
}
return true;
@@ -567,78 +578,76 @@ bool CryptoSession::GenerateDerivedKeys(const std::string& message,
bool CryptoSession::GenerateSignature(const std::string& message,
std::string* signature) {
LOGV("GenerateSignature: id=%ld", (uint32_t)oec_session_id_);
if (!signature) return false;
if (!signature) {
LOGE("GenerateSignature: null signature string");
return false;
}
OEMCryptoResult sts;
size_t length = signature->size();
OEMCryptoResult sts = OEMCrypto_GenerateSignature(
oec_session_id_, reinterpret_cast<const uint8_t*>(message.data()),
message.size(),
reinterpret_cast<uint8_t*>(const_cast<char*>(signature->data())),
&length);
if (OEMCrypto_SUCCESS != sts) {
if (OEMCrypto_ERROR_SHORT_BUFFER != sts) {
LOGE("GenerateSignature: OEMCrypto_GenerateSignature err=%d", sts);
return false;
}
// Retry with proper-sized signature buffer
signature->resize(length);
// At most two attempts.
// The first attempt may fail due to buffer too short
for (int i = 0; i < 2; ++i) {
sts = OEMCrypto_GenerateSignature(
oec_session_id_, reinterpret_cast<const uint8_t*>(message.data()),
message.size(),
reinterpret_cast<uint8_t*>(const_cast<char*>(signature->data())),
&length);
if (OEMCrypto_SUCCESS != sts) {
LOGE("GenerateSignature: OEMCrypto_GenerateSignature err=%d", sts);
return false;
if (OEMCrypto_SUCCESS == sts) {
// Trim signature buffer and done
signature->resize(length);
return true;
}
if (OEMCrypto_ERROR_SHORT_BUFFER != sts) {
break;
}
// Retry with proper-sized signature buffer
signature->resize(length);
}
// Trim signature buffer
signature->resize(length);
return true;
LOGE("GenerateSignature: OEMCrypto_GenerateSignature err=%d", sts);
return false;
}
bool CryptoSession::GenerateRsaSignature(const std::string& message,
std::string* signature) {
LOGV("GenerateRsaSignature: id=%ld", (uint32_t)oec_session_id_);
if (!signature) return false;
if (!signature) {
LOGE("GenerateRsaSignature: null signature string");
return false;
}
OEMCryptoResult sts;
signature->resize(kRsaSignatureLength);
size_t length = signature->size();
OEMCryptoResult sts = OEMCrypto_GenerateRSASignature(
oec_session_id_, reinterpret_cast<const uint8_t*>(message.data()),
message.size(),
reinterpret_cast<uint8_t*>(const_cast<char*>(signature->data())), &length,
kSign_RSASSA_PSS);
if (OEMCrypto_SUCCESS != sts) {
if (OEMCrypto_ERROR_SHORT_BUFFER != sts) {
LOGE("GenerateRsaSignature: OEMCrypto_GenerateRSASignature err=%d", sts);
return false;
}
// Retry with proper-sized signature buffer
signature->resize(length);
// At most two attempts.
// The first attempt may fail due to buffer too short
for (int i = 0; i < 2; ++i) {
sts = OEMCrypto_GenerateRSASignature(
oec_session_id_, reinterpret_cast<const uint8_t*>(message.data()),
message.size(),
reinterpret_cast<uint8_t*>(const_cast<char*>(signature->data())),
&length, kSign_RSASSA_PSS);
if (OEMCrypto_SUCCESS != sts) {
LOGE("GenerateRsaSignature: OEMCrypto_GenerateRSASignature err=%d", sts);
return false;
if (OEMCrypto_SUCCESS == sts) {
// Trim signature buffer and done
signature->resize(length);
return true;
}
if (OEMCrypto_ERROR_SHORT_BUFFER != sts) {
break;
}
// Retry with proper-sized signature buffer
signature->resize(length);
}
// Trim signature buffer
signature->resize(length);
return true;
LOGE("GenerateRsaSignature: OEMCrypto_GenerateRSASignature err=%d", sts);
return false;
}
CdmResponseType CryptoSession::Decrypt(const CdmDecryptionParameters& params) {
@@ -693,12 +702,8 @@ CdmResponseType CryptoSession::Decrypt(const CdmDecryptionParameters& params) {
AutoLock auto_lock(crypto_lock_);
// Check if key needs to be selected
if (params.is_encrypted) {
if (key_id_ != *params.key_id) {
if (SelectKey(*params.key_id)) {
key_id_ = *params.key_id;
} else {
return NEED_KEY;
}
if (!SelectKey(*params.key_id)) {
return NEED_KEY;
}
}
sts = OEMCrypto_DecryptCENC(
@@ -1101,4 +1106,200 @@ bool CryptoSession::GetMaxNumberOfSessions(size_t* max) {
return true;
}
CdmResponseType CryptoSession::GenericEncrypt(const std::string& in_buffer,
const std::string& key_id,
const std::string& iv,
CdmEncryptionAlgorithm algorithm,
std::string* out_buffer) {
LOGV("GenericEncrypt: id=%ld", (uint32_t)oec_session_id_);
if (!out_buffer) return INVALID_PARAMETERS_ENG_9;
OEMCrypto_Algorithm oec_algorithm = GenericEncryptionAlgorithm(algorithm);
if (iv.size() != GenericEncryptionBlockSize(algorithm) ||
oec_algorithm == kInvalidAlgorithm) {
return INVALID_PARAMETERS_ENG_13;
}
if (out_buffer->size() < in_buffer.size()) {
out_buffer->resize(in_buffer.size());
}
AutoLock auto_lock(crypto_lock_);
if (!SelectKey(key_id)) {
return KEY_ERROR_1;
}
OEMCryptoResult sts = OEMCrypto_Generic_Encrypt(
oec_session_id_, reinterpret_cast<const uint8_t*>(in_buffer.data()),
in_buffer.size(), reinterpret_cast<const uint8_t*>(iv.data()),
oec_algorithm,
reinterpret_cast<uint8_t*>(const_cast<char*>(out_buffer->data())));
if (OEMCrypto_SUCCESS != sts) {
LOGE("GenericEncrypt: OEMCrypto_Generic_Encrypt err=%d", sts);
if (OEMCrypto_ERROR_KEY_EXPIRED == sts ||
OEMCrypto_ERROR_NO_CONTENT_KEY == sts) {
return KEY_NOT_FOUND_3;
} else {
return UNKNOWN_ERROR;
}
}
return NO_ERROR;
}
CdmResponseType CryptoSession::GenericDecrypt(const std::string& in_buffer,
const std::string& key_id,
const std::string& iv,
CdmEncryptionAlgorithm algorithm,
std::string* out_buffer) {
LOGV("GenericDecrypt: id=%ld", (uint32_t)oec_session_id_);
if (!out_buffer) return INVALID_PARAMETERS_ENG_10;
OEMCrypto_Algorithm oec_algorithm = GenericEncryptionAlgorithm(algorithm);
if (iv.size() != GenericEncryptionBlockSize(algorithm) ||
oec_algorithm == kInvalidAlgorithm) {
return INVALID_PARAMETERS_ENG_14;
}
if (out_buffer->size() < in_buffer.size()) {
out_buffer->resize(in_buffer.size());
}
AutoLock auto_lock(crypto_lock_);
if (!SelectKey(key_id)) {
return KEY_ERROR_2;
}
OEMCryptoResult sts = OEMCrypto_Generic_Decrypt(
oec_session_id_, reinterpret_cast<const uint8_t*>(in_buffer.data()),
in_buffer.size(), reinterpret_cast<const uint8_t*>(iv.data()),
oec_algorithm,
reinterpret_cast<uint8_t*>(const_cast<char*>(out_buffer->data())));
if (OEMCrypto_SUCCESS != sts) {
LOGE("GenericDecrypt: OEMCrypto_Generic_Decrypt err=%d", sts);
if (OEMCrypto_ERROR_KEY_EXPIRED == sts ||
OEMCrypto_ERROR_NO_CONTENT_KEY == sts) {
return KEY_NOT_FOUND_4;
} else {
return UNKNOWN_ERROR;
}
}
return NO_ERROR;
}
CdmResponseType CryptoSession::GenericSign(const std::string& message,
const std::string& key_id,
CdmSigningAlgorithm algorithm,
std::string* signature) {
LOGV("GenericSign: id=%ld", (uint32_t)oec_session_id_);
if (!signature) {
LOGE("GenerateSign: null signature string");
return INVALID_PARAMETERS_ENG_11;
}
OEMCrypto_Algorithm oec_algorithm = GenericSigningAlgorithm(algorithm);
if (oec_algorithm == kInvalidAlgorithm) {
return INVALID_PARAMETERS_ENG_15;
}
OEMCryptoResult sts;
size_t length = signature->size();
AutoLock auto_lock(crypto_lock_);
if (!SelectKey(key_id)) {
return KEY_ERROR_3;
}
// At most two attempts.
// The first attempt may fail due to buffer too short
for (int i = 0; i < 2; ++i) {
sts = OEMCrypto_Generic_Sign(
oec_session_id_, reinterpret_cast<const uint8_t*>(message.data()),
message.size(), oec_algorithm,
reinterpret_cast<uint8_t*>(const_cast<char*>(signature->data())),
&length);
if (OEMCrypto_SUCCESS == sts) {
// Trim signature buffer and done
signature->resize(length);
return NO_ERROR;
}
if (OEMCrypto_ERROR_SHORT_BUFFER != sts) {
break;
}
// Retry with proper-sized return buffer
signature->resize(length);
}
LOGE("GenericSign: OEMCrypto_Generic_Sign err=%d", sts);
if (OEMCrypto_ERROR_KEY_EXPIRED == sts ||
OEMCrypto_ERROR_NO_CONTENT_KEY == sts) {
return KEY_NOT_FOUND_5;
} else {
return UNKNOWN_ERROR;
}
}
CdmResponseType CryptoSession::GenericVerify(const std::string& message,
const std::string& key_id,
CdmSigningAlgorithm algorithm,
const std::string& signature) {
LOGV("GenericVerify: id=%ld", (uint32_t)oec_session_id_);
OEMCrypto_Algorithm oec_algorithm = GenericSigningAlgorithm(algorithm);
if (oec_algorithm == kInvalidAlgorithm) {
return INVALID_PARAMETERS_ENG_16;
}
AutoLock auto_lock(crypto_lock_);
if (!SelectKey(key_id)) {
return KEY_ERROR_4;
}
OEMCryptoResult sts = OEMCrypto_Generic_Verify(
oec_session_id_, reinterpret_cast<const uint8_t*>(message.data()),
message.size(), oec_algorithm,
reinterpret_cast<const uint8_t*>(signature.data()), signature.size());
if (OEMCrypto_SUCCESS != sts) {
LOGE("GenericVerify: OEMCrypto_Generic_Verify err=%d", sts);
if (OEMCrypto_ERROR_KEY_EXPIRED == sts ||
OEMCrypto_ERROR_NO_CONTENT_KEY == sts) {
return KEY_NOT_FOUND_6;
} else {
return UNKNOWN_ERROR;
}
}
return NO_ERROR;
}
OEMCrypto_Algorithm CryptoSession::GenericSigningAlgorithm(
CdmSigningAlgorithm algorithm) {
if (kSigningAlgorithmHmacSha256 == algorithm) {
return OEMCrypto_HMAC_SHA256;
} else {
return kInvalidAlgorithm;
}
}
OEMCrypto_Algorithm CryptoSession::GenericEncryptionAlgorithm(
CdmEncryptionAlgorithm algorithm) {
if (kEncryptionAlgorithmAesCbc128 == algorithm) {
return OEMCrypto_AES_CBC_128_NO_PADDING;
} else {
return kInvalidAlgorithm;
}
}
size_t CryptoSession::GenericEncryptionBlockSize(
CdmEncryptionAlgorithm algorithm) {
if (kEncryptionAlgorithmAesCbc128 == algorithm) {
return kAes128BlockSize;
} else {
return 0;
}
}
} // namespace wvcdm