(This is a merge of go/wvgerrit/23182) This patch adds the framework for Stable Per-Origin Identifiers to the CDM. Calculating SPOIDs will be done on the client-side, and they are sent as part of the provisioning request. SPOIDs are also available to the app as the Device Unique ID, replacing the previous method of returning the actual Device Unique ID from the keybox / OEM certificate. Different SPOIDs must use separate storage, just as different origins already do. Support for this has been added to the Android adapter to the CDM Core. However, the code in the Android glue layer that would drive this behavior will be checked in in a separate change. As such, all Android devices will continue using the legacy behavior even after this patch goes in, until the glue layer code can be updated. Bug: 27101531 Test: CE CDM Unit Tests Test: Linux Jenkins Unit Tests Test: Android Unit Tests (with and without SPOIDs forced on) Test: Android GTS Tests Change-Id: Ia0caf890381cbcb97504d08b19aeab8b29bd07ae
301 lines
9.6 KiB
C++
301 lines
9.6 KiB
C++
//
|
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
|
//
|
|
|
|
#ifndef WV_DRM_PLUGIN_H_
|
|
#define WV_DRM_PLUGIN_H_
|
|
|
|
#include <stdint.h>
|
|
#include <map>
|
|
|
|
#include "cdm_client_property_set.h"
|
|
#include "cdm_identifier.h"
|
|
#include "media/drm/DrmAPI.h"
|
|
#include "media/stagefright/foundation/ABase.h"
|
|
#include "media/stagefright/foundation/AString.h"
|
|
#include "OEMCryptoCENC.h"
|
|
#include "utils/Errors.h"
|
|
#include "utils/KeyedVector.h"
|
|
#include "utils/List.h"
|
|
#include "utils/String8.h"
|
|
#include "utils/StrongPointer.h"
|
|
#include "utils/Vector.h"
|
|
#include "wv_cdm_event_listener.h"
|
|
#include "wv_content_decryption_module.h"
|
|
#include "WVGenericCryptoInterface.h"
|
|
|
|
namespace wvdrm {
|
|
|
|
using android::KeyedVector;
|
|
using android::List;
|
|
using android::status_t;
|
|
using android::String8;
|
|
using android::Vector;
|
|
using std::map;
|
|
using wvcdm::CdmIdentifier;
|
|
using wvcdm::CdmKeyStatusMap;
|
|
using wvcdm::CdmSessionId;
|
|
using wvcdm::CdmResponseType;
|
|
using wvcdm::WvContentDecryptionModule;
|
|
|
|
const OEMCrypto_Algorithm kInvalidCryptoAlgorithm =
|
|
static_cast<OEMCrypto_Algorithm>(-1);
|
|
|
|
class WVDrmPlugin : public android::DrmPlugin,
|
|
public wvcdm::WvCdmEventListener {
|
|
public:
|
|
WVDrmPlugin(const android::sp<wvcdm::WvContentDecryptionModule>& cdm,
|
|
WVGenericCryptoInterface* crypto);
|
|
|
|
virtual ~WVDrmPlugin();
|
|
|
|
virtual status_t openSession(Vector<uint8_t>& sessionId);
|
|
|
|
virtual status_t closeSession(const Vector<uint8_t>& sessionId);
|
|
|
|
virtual status_t getKeyRequest(
|
|
const Vector<uint8_t>& scope,
|
|
const Vector<uint8_t>& initData,
|
|
const String8& initDataType,
|
|
KeyType keyType,
|
|
const KeyedVector<String8, String8>& optionalParameters,
|
|
Vector<uint8_t>& request,
|
|
String8& defaultUrl,
|
|
KeyRequestType *keyRequestType);
|
|
|
|
virtual status_t provideKeyResponse(const Vector<uint8_t>& scope,
|
|
const Vector<uint8_t>& response,
|
|
Vector<uint8_t>& keySetId);
|
|
|
|
virtual status_t removeKeys(const Vector<uint8_t>& sessionId);
|
|
|
|
virtual status_t restoreKeys(const Vector<uint8_t>& sessionId,
|
|
const Vector<uint8_t>& keySetId);
|
|
|
|
virtual status_t queryKeyStatus(
|
|
const Vector<uint8_t>& sessionId,
|
|
KeyedVector<String8, String8>& infoMap) const;
|
|
|
|
virtual status_t getProvisionRequest(const String8& cert_type,
|
|
const String8& cert_authority,
|
|
Vector<uint8_t>& request,
|
|
String8& defaultUrl);
|
|
|
|
virtual status_t provideProvisionResponse(const Vector<uint8_t>& response,
|
|
Vector<uint8_t>& certificate,
|
|
Vector<uint8_t>& wrapped_key);
|
|
|
|
virtual status_t unprovisionDevice();
|
|
|
|
virtual status_t getSecureStop(const Vector<uint8_t>& ssid,
|
|
Vector<uint8_t>& secureStop);
|
|
|
|
virtual status_t getSecureStops(List<Vector<uint8_t> >& secureStops);
|
|
|
|
virtual status_t releaseAllSecureStops();
|
|
|
|
virtual status_t releaseSecureStops(const Vector<uint8_t>& ssRelease);
|
|
|
|
virtual status_t getPropertyString(const String8& name, String8& value) const;
|
|
|
|
virtual status_t getPropertyByteArray(const String8& name,
|
|
Vector<uint8_t>& value) const;
|
|
|
|
virtual status_t setPropertyString(const String8& name, const String8& value);
|
|
|
|
virtual status_t setPropertyByteArray(const String8& name,
|
|
const Vector<uint8_t>& value);
|
|
|
|
virtual status_t setCipherAlgorithm(const Vector<uint8_t>& sessionId,
|
|
const String8& algorithm);
|
|
|
|
virtual status_t setMacAlgorithm(const Vector<uint8_t>& sessionId,
|
|
const String8& algorithm);
|
|
|
|
virtual status_t encrypt(const Vector<uint8_t>& sessionId,
|
|
const Vector<uint8_t>& keyId,
|
|
const Vector<uint8_t>& input,
|
|
const Vector<uint8_t>& iv,
|
|
Vector<uint8_t>& output);
|
|
|
|
virtual status_t decrypt(const Vector<uint8_t>& sessionId,
|
|
const Vector<uint8_t>& keyId,
|
|
const Vector<uint8_t>& input,
|
|
const Vector<uint8_t>& iv,
|
|
Vector<uint8_t>& output);
|
|
|
|
virtual status_t sign(const Vector<uint8_t>& sessionId,
|
|
const Vector<uint8_t>& keyId,
|
|
const Vector<uint8_t>& message,
|
|
Vector<uint8_t>& signature);
|
|
|
|
virtual status_t verify(const Vector<uint8_t>& sessionId,
|
|
const Vector<uint8_t>& keyId,
|
|
const Vector<uint8_t>& message,
|
|
const Vector<uint8_t>& signature,
|
|
bool& match);
|
|
|
|
virtual status_t signRSA(const Vector<uint8_t>& sessionId,
|
|
const String8& algorithm,
|
|
const Vector<uint8_t>& message,
|
|
const Vector<uint8_t>& wrappedKey,
|
|
Vector<uint8_t>& signature);
|
|
|
|
virtual void OnSessionRenewalNeeded(const CdmSessionId& cdmSessionId);
|
|
|
|
virtual void OnSessionKeysChange(const CdmSessionId& cdmSessionId,
|
|
const CdmKeyStatusMap& cdmKeysStatus,
|
|
bool hasNewUsableKey);
|
|
|
|
virtual void OnExpirationUpdate(const CdmSessionId& cdmSessionId,
|
|
int64_t newExpiryTimeSeconds);
|
|
|
|
private:
|
|
DISALLOW_EVIL_CONSTRUCTORS(WVDrmPlugin);
|
|
|
|
struct CryptoSession {
|
|
public:
|
|
CryptoSession()
|
|
: mOecSessionId(-1),
|
|
mCipherAlgorithm(kInvalidCryptoAlgorithm),
|
|
mMacAlgorithm(kInvalidCryptoAlgorithm) {}
|
|
|
|
CryptoSession(OEMCrypto_SESSION sessionId)
|
|
: mOecSessionId(sessionId),
|
|
mCipherAlgorithm(kInvalidCryptoAlgorithm),
|
|
mMacAlgorithm(kInvalidCryptoAlgorithm) {}
|
|
|
|
OEMCrypto_SESSION oecSessionId() const { return mOecSessionId; }
|
|
|
|
OEMCrypto_Algorithm cipherAlgorithm() const { return mCipherAlgorithm; }
|
|
|
|
void setCipherAlgorithm(OEMCrypto_Algorithm newAlgorithm) {
|
|
mCipherAlgorithm = newAlgorithm;
|
|
}
|
|
|
|
OEMCrypto_Algorithm macAlgorithm() const { return mMacAlgorithm; }
|
|
|
|
void setMacAlgorithm(OEMCrypto_Algorithm newAlgorithm) {
|
|
mMacAlgorithm = newAlgorithm;
|
|
}
|
|
|
|
private:
|
|
OEMCrypto_SESSION mOecSessionId;
|
|
OEMCrypto_Algorithm mCipherAlgorithm;
|
|
OEMCrypto_Algorithm mMacAlgorithm;
|
|
};
|
|
|
|
class WVClientPropertySet : public wvcdm::CdmClientPropertySet {
|
|
public:
|
|
WVClientPropertySet()
|
|
: mUsePrivacyMode(false), mShareKeys(false), mSessionSharingId(0) {}
|
|
|
|
virtual ~WVClientPropertySet() {}
|
|
|
|
virtual const std::string& security_level() const {
|
|
return mSecurityLevel;
|
|
}
|
|
|
|
void set_security_level(const std::string& securityLevel) {
|
|
mSecurityLevel = securityLevel;
|
|
}
|
|
|
|
virtual bool use_privacy_mode() const {
|
|
return mUsePrivacyMode;
|
|
}
|
|
|
|
void set_use_privacy_mode(bool usePrivacyMode) {
|
|
mUsePrivacyMode = usePrivacyMode;
|
|
}
|
|
|
|
virtual const std::string& service_certificate() const {
|
|
return mServiceCertificate;
|
|
}
|
|
|
|
virtual void set_service_certificate(
|
|
const std::string& serviceCertificate) {
|
|
mServiceCertificate = serviceCertificate;
|
|
}
|
|
|
|
virtual const std::string& device_provisioning_service_certificate() const {
|
|
// Android does not support service certificates for provisioning.
|
|
return mEmptyString;
|
|
}
|
|
|
|
virtual void set_device_provisioning_service_certificate(
|
|
const std::string& ) {
|
|
// Ignore. Android does not support service certificates for provisioning
|
|
}
|
|
|
|
virtual bool is_session_sharing_enabled() const {
|
|
return mShareKeys;
|
|
}
|
|
|
|
void set_is_session_sharing_enabled(bool shareKeys) {
|
|
mShareKeys = shareKeys;
|
|
}
|
|
|
|
virtual uint32_t session_sharing_id() const {
|
|
return mSessionSharingId;
|
|
}
|
|
|
|
virtual void set_session_sharing_id(uint32_t id) {
|
|
mSessionSharingId = id;
|
|
}
|
|
|
|
virtual const std::string& app_id() const {
|
|
return mAppId;
|
|
}
|
|
|
|
void set_app_id(const std::string& appId) {
|
|
mAppId = appId;
|
|
}
|
|
|
|
private:
|
|
DISALLOW_EVIL_CONSTRUCTORS(WVClientPropertySet);
|
|
|
|
std::string mSecurityLevel;
|
|
bool mUsePrivacyMode;
|
|
std::string mServiceCertificate;
|
|
bool mShareKeys;
|
|
uint32_t mSessionSharingId;
|
|
std::string mAppId;
|
|
const std::string mEmptyString;
|
|
} mPropertySet;
|
|
|
|
android::sp<wvcdm::WvContentDecryptionModule> const mCDM;
|
|
WVGenericCryptoInterface* mCrypto;
|
|
map<CdmSessionId, CryptoSession> mCryptoSessions;
|
|
|
|
CdmIdentifier mCdmIdentifier;
|
|
|
|
status_t queryProperty(const std::string& property,
|
|
std::string& stringValue) const;
|
|
|
|
status_t queryProperty(wvcdm::SecurityLevel securityLevel,
|
|
const std::string& property,
|
|
std::string& stringValue) const;
|
|
|
|
status_t queryProperty(const std::string& property,
|
|
String8& string8_value) const;
|
|
|
|
status_t queryProperty(const std::string& property,
|
|
Vector<uint8_t>& vector_value) const;
|
|
|
|
status_t mapAndNotifyOfCdmResponseType(const Vector<uint8_t>& sessionId,
|
|
CdmResponseType res);
|
|
|
|
status_t mapAndNotifyOfOEMCryptoResult(const Vector<uint8_t>& sessionId,
|
|
OEMCryptoResult res);
|
|
|
|
status_t mapOEMCryptoResult(OEMCryptoResult res);
|
|
|
|
bool initDataResemblesPSSH(const Vector<uint8_t>& initData);
|
|
|
|
status_t unprovision(const CdmIdentifier& identifier);
|
|
};
|
|
|
|
} // namespace wvdrm
|
|
|
|
#endif // WV_DRM_PLUGIN_H_
|