// Copyright 2012 Google Inc. All Rights Reserved. // // Crypto - wrapper classes for OEMCrypto interface // #include "crypto_engine.h" #include // TODO(fredgc): Add ntoh to wv_cdm_utilities.h #include #include #include "log.h" #include "OEMCryptoCENC.h" #include "properties.h" #include "wv_cdm_constants.h" namespace wvcdm { CryptoEngine* CryptoEngine::crypto_engine_ = NULL; Lock CryptoEngine::crypto_engine_lock_; // wrapper classes for OEMCrypto interface // CryptoEngine -- top-level interface // CryptoSession -- session-specific interface // CryptoKey -- key interface // CryptoEngine methods CryptoEngine::CryptoEngine() : initialized_(false) {} CryptoEngine::~CryptoEngine() { if (initialized_) { Terminate(); } CryptoSessionMap::iterator i(sessions_.begin()); for (; i != sessions_.end(); ++i) delete i->second; sessions_.clear(); } // get the instance of OEMCrypto Client CryptoEngine* CryptoEngine::GetInstance() { if (NULL == crypto_engine_) { crypto_engine_ = CreateSingleton(); } return crypto_engine_; } CryptoEngine* CryptoEngine::CreateSingleton() { AutoLock auto_lock(crypto_engine_lock_); if (NULL == crypto_engine_) { crypto_engine_ = new CryptoEngine; } return crypto_engine_; } void CryptoEngine::DeleteInstance() { if (NULL != crypto_engine_) { delete crypto_engine_; LOGV("CryptoEngine::DeleteInstance"); crypto_engine_ = NULL; } } bool CryptoEngine::Init() { LOGV("CryptoEngine::Init: Lock"); AutoLock auto_lock(crypto_lock_); if (!initialized_) { OEMCryptoResult result = OEMCrypto_Initialize(); initialized_ = (OEMCrypto_SUCCESS == result); } return initialized_; } bool CryptoEngine::Terminate() { DestroySessions(); LOGV("CryptoEngine::Terminate: Lock"); AutoLock auto_lock(crypto_lock_); OEMCryptoResult result = OEMCrypto_Terminate(); if (OEMCrypto_SUCCESS == result) { initialized_ = false; } return !initialized_; } bool CryptoEngine::ValidateKeybox() { LOGV("CryptoEngine::ValidateKeybox: Lock"); AutoLock auto_lock(crypto_lock_); OEMCryptoResult result = OEMCrypto_IsKeyboxValid(); return (OEMCrypto_SUCCESS == result); } CryptoSession* CryptoEngine::CreateSession(const CdmSessionId& session_id) { LOGV("CryptoEngine::CreateSession: SLock"); AutoLock auto_lock(sessions_lock_); if (0 == sessions_.size()) { if (!Init()) { return NULL; } } CryptoSessionMap::iterator it = sessions_.find(session_id); if (it != sessions_.end()) { LOGE("CryptoEngine::CreateSession : Duplicate session ID."); return NULL; } CryptoSession* new_session = new CryptoSession(session_id); if (!new_session) { return NULL; } if (!new_session->Open()) { delete new_session; return NULL; } sessions_[session_id] = new_session; return new_session; } CryptoSession* CryptoEngine::FindSessionInternal( const CdmSessionId& session_id) { // must hold sessions_lock_ CryptoSessionMap::iterator it = sessions_.find(session_id); if (it != sessions_.end()) { return it->second; } return NULL; } CryptoSession* CryptoEngine::FindSession(const CdmSessionId& session_id) { LOGV("CryptoEngine::FindSession: SLock"); AutoLock auto_lock(sessions_lock_); return FindSessionInternal(session_id); } bool CryptoEngine::DestroySession(const CdmSessionId& session_id) { LOGV("CryptoEngine::DestroySession: SLock"); AutoLock auto_lock(sessions_lock_); if (0 == sessions_.size()) { return false; } CryptoSession* session = FindSessionInternal(session_id); if (session) { delete session; sessions_.erase(session_id); return true; } else { return false; } } bool CryptoEngine::DestroySessions() { for (CryptoSessionMap::iterator it = sessions_.begin(); it != sessions_.end(); ++it) { delete it->second; } sessions_.clear(); return true; } bool CryptoEngine::GetToken(std::string* token) { LOGV("CryptoEngine::GetToken: Lock"); AutoLock auto_lock(crypto_lock_); if (!token) { LOGE("CryptoEngine::GetToken : No token passed to method."); return false; } uint8_t buf[72]; size_t buflen = 72; OEMCryptoResult sts = OEMCrypto_GetKeyData(buf, &buflen); if (OEMCrypto_SUCCESS != sts) { return false; } token->assign((const char*)buf, (size_t)buflen); return true; } CryptoEngine::SecurityLevel CryptoEngine::GetSecurityLevel() { if (!Init()) return kSecurityLevelUnknown; std::string security_level = OEMCrypto_SecurityLevel(); if ((security_level.size() != 2) || (security_level.at(0) != 'L')) { return kSecurityLevelUnknown; } switch (security_level.at(1)) { case '1': return kSecurityLevelL1; case '2': return kSecurityLevelL2; case '3': return kSecurityLevelL3; default : return kSecurityLevelUnknown; } return kSecurityLevelUnknown; } bool CryptoEngine::GetDeviceUniqueId(std::string* deviceId) { if (!Init()) return false; std::vector id; size_t idLength = 32; id.resize(idLength); OEMCryptoResult sts = OEMCrypto_GetDeviceID(&id[0], &idLength); if (OEMCrypto_SUCCESS != sts) { return false; } *deviceId = reinterpret_cast(&id[0]); return true; } bool CryptoEngine::GetSystemId(uint32_t* systemId) { if (!Init()) return false; uint8_t buf[72]; size_t buflen = 72; OEMCryptoResult sts = OEMCrypto_GetKeyData(buf, &buflen); if (OEMCrypto_SUCCESS != sts) { return false; } // Decode 32-bit int encoded as network-byte-order byte array starting at // index 4. uint32_t* id = reinterpret_cast(&buf[4]); *systemId = ntohl(*id); return true; } }; // namespace wvcdm