diff --git a/cast_auth/mediadrm/Android.bp b/cast_auth/mediadrm/Android.bp new file mode 100644 index 0000000..e113d24 --- /dev/null +++ b/cast_auth/mediadrm/Android.bp @@ -0,0 +1,55 @@ +// ---------------------------------------------------------------------------- +// Builds android.hardware.drm-service.castkey +// +// TODO(b/366426322): Merge these targets into `device/google/gs-common`. + +soong_namespace { +} + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "device_google_tangorpro_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["device_google_tangorpro_license"], +} + +cc_binary { + name: "android.hardware.drm-service.castkey", + defaults: ["castkey_service_defaults"], + srcs: ["Service.cpp"], + init_rc: ["android.hardware.drm-service.castkey.rc"], + vintf_fragments: ["manifest_android.hardware.drm-service.castkey.xml"], +} + +cc_defaults { + name: "castkey_service_defaults", + vendor: true, + proprietary: true, + srcs: [ + "CreatePluginFactories.cpp", + "DrmFactory.cpp", + "DrmPlugin.cpp", + "SessionLibrary.cpp", + ], + + relative_install_path: "hw", + + cflags: [ + "-Wall", + "-Werror", + ], + + include_dirs: [ + "device/google/tangorpro/cast_auth/mediadrm/include", + ], + + shared_libs: [ + "android.hardware.drm-V1-ndk", + "libbase", + "libbinder_ndk", + "liblog", + "libutils", + ], +} diff --git a/cast_auth/mediadrm/CreatePluginFactories.cpp b/cast_auth/mediadrm/CreatePluginFactories.cpp new file mode 100644 index 0000000..23dee4e --- /dev/null +++ b/cast_auth/mediadrm/CreatePluginFactories.cpp @@ -0,0 +1,17 @@ +#include "CreatePluginFactories.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace drm { +namespace castkey { + +std::shared_ptr createDrmFactory() { + return ::ndk::SharedRefBase::make(); +} + +} // namespace castkey +} // namespace drm +} // namespace hardware +} // namespace android +} // namespace aidl \ No newline at end of file diff --git a/cast_auth/mediadrm/DrmFactory.cpp b/cast_auth/mediadrm/DrmFactory.cpp new file mode 100644 index 0000000..e127186 --- /dev/null +++ b/cast_auth/mediadrm/DrmFactory.cpp @@ -0,0 +1,82 @@ +#define LOG_TAG "castkey-DrmFactory" + +#include + +#include "DrmFactory.h" + +#include "DrmPlugin.h" +#include "Utils.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace drm { +namespace castkey { + +namespace { + +const std::array kCastKeyUUID{ + 0xBC, 0xB4, 0x81, 0xCB, 0xA1, 0xD5, 0x42, 0xAF, + 0xB1, 0xE3, 0x7B, 0xFF, 0x14, 0x73, 0xEB, 0x85 +}; + +bool isCastKeyUUID(const uint8_t uuid[16]) { + return !memcmp(uuid, kCastKeyUUID.data(), 16); +} + +} + +using std::string; +using std::vector; + +using ::aidl::android::hardware::drm::Status; +using ::aidl::android::hardware::drm::Uuid; +using namespace castkeydrm; + +::ndk::ScopedAStatus DrmFactory::createDrmPlugin( + const Uuid& in_uuid, const string& in_appPackageName, + std::shared_ptr<::aidl::android::hardware::drm::IDrmPlugin>* _aidl_return) { + UNUSED(in_appPackageName); + if (!isCastKeyUUID(in_uuid.uuid.data())) { + ALOGE("Castkey Drm HAL: failed to create drm plugin, " + "invalid crypto scheme"); + *_aidl_return = nullptr; + return toNdkScopedAStatus(Status::BAD_VALUE); + } + std::shared_ptr plugin = + ::ndk::SharedRefBase::make(); + *_aidl_return = plugin; + return toNdkScopedAStatus(Status::OK); +} + +::ndk::ScopedAStatus DrmFactory::createCryptoPlugin( + const Uuid& in_uuid, const std::vector& in_initData, + std::shared_ptr<::aidl::android::hardware::drm::ICryptoPlugin>* _aidl_return) { + UNUSED(in_uuid); + UNUSED(in_initData); + UNUSED(_aidl_return); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmFactory::getSupportedCryptoSchemes(CryptoSchemes* _aidl_return) { + CryptoSchemes schemes{}; + schemes.uuids.push_back({kCastKeyUUID}); + *_aidl_return = schemes; + return toNdkScopedAStatus(Status::OK); +} + +binder_status_t DrmFactory::dump(int fd, const char** args, uint32_t numArgs) { + UNUSED(args); + UNUSED(numArgs); + if (fd < 0) { + ALOGE("%s: negative fd", __FUNCTION__); + return STATUS_BAD_VALUE; + } + return STATUS_OK; +} + +} // namespace castkey +} // namespace drm +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/cast_auth/mediadrm/DrmPlugin.cpp b/cast_auth/mediadrm/DrmPlugin.cpp new file mode 100644 index 0000000..00b7956 --- /dev/null +++ b/cast_auth/mediadrm/DrmPlugin.cpp @@ -0,0 +1,419 @@ +#define LOG_TAG "castkey-DrmPlugin" + +#include +#include +#include +#include +#include + +#include "Utils.h" +#include "DrmPlugin.h" +#include "SessionLibrary.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace drm { +namespace castkey { + +using namespace castkeydrm; + +DrmPlugin::DrmPlugin() {}; +DrmPlugin::~DrmPlugin() {}; + +constexpr char CAST_CRT_FILE[] = "/mnt/vendor/persist/nest/cast_auth.crt"; +constexpr char CAST_ICA_FILE[] = "/vendor/etc/cert-chain.crt"; +constexpr unsigned char kSha1Prefix[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, + 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14}; +constexpr unsigned char kSha256Prefix[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, + 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, + 0x01, 0x05, 0x00, 0x04, 0x20}; +constexpr int kSHA1Length = 20; +constexpr int kSHA256Length = 32; +constexpr int DigestInfoPrefixesSize = 2; + +struct DigestInfoPrefix { + const unsigned char* bytes; + size_t size; + size_t hash_size; +}; + +// Array of DigestInfoPrefixes that are currently supported (SHA1 and SHA256). +const DigestInfoPrefix kDigestInfoPrefixes[] = { + {kSha1Prefix, sizeof(kSha1Prefix), kSHA1Length}, + {kSha256Prefix, sizeof(kSha256Prefix), kSHA256Length}, +}; + +// If we find a raw hash, prepend the appropriate DER prefix. +std::vector adjustHash(const std::vector& hash) { + std::vector adjusted_hash(hash); + for (size_t i = 0; i < DigestInfoPrefixesSize; i++) { + const DigestInfoPrefix& prefix = kDigestInfoPrefixes[i]; + if (hash.size() == prefix.hash_size) { + adjusted_hash.insert(adjusted_hash.begin(), prefix.bytes, + &prefix.bytes[prefix.size]); + break; + } + } + return adjusted_hash; +} + +std::vector readBinaryFile(const std::string& file_path) { + std::ifstream fin(file_path, std::ios::in | std::ios::binary); + fin >> std::noskipws; + std::vector buffer((std::istream_iterator(fin)), + std::istream_iterator()); + return buffer; +} + +::ndk::ScopedAStatus DrmPlugin::openSession( + ::aidl::android::hardware::drm::SecurityLevel in_securityLevel, + std::vector* _aidl_return) { + UNUSED(in_securityLevel); + std::vector sessionId = SessionLibrary::get()->createSession(); + *_aidl_return = sessionId; + return toNdkScopedAStatus(Status::OK); +} + +::ndk::ScopedAStatus DrmPlugin::closeSession(const std::vector& in_sessionId) { + if (in_sessionId.size() == 0) { + return toNdkScopedAStatus(Status::BAD_VALUE); + } + SessionLibrary::get()->closeSession(in_sessionId); + return toNdkScopedAStatus(Status::OK); +} + +::ndk::ScopedAStatus DrmPlugin::getPropertyByteArray(const std::string& in_propertyName, + std::vector* _aidl_return) { + Status status = Status::OK; + std::string name(in_propertyName.c_str()); + std::vector value; + if (name == "castcert") { + std::vector device_cert = readBinaryFile(CAST_CRT_FILE); + std::vector ica = readBinaryFile(CAST_ICA_FILE); + value = std::move(device_cert); + value.insert(value.end(), ica.begin(), ica.end()); + } else { + status = Status::ERROR_DRM_CANNOT_HANDLE; + ALOGE("Unsupported Property: %s", in_propertyName.c_str()); + } + *_aidl_return = value; + return toNdkScopedAStatus(status); +} + +::ndk::ScopedAStatus DrmPlugin::signRSA(const std::vector& in_sessionId, + const std::string& in_algorithm, + const std::vector& in_message, + const std::vector& in_wrappedkey, + std::vector* _aidl_return) { + if (in_sessionId.size() == 0 || in_message.size() == 0) { + return toNdkScopedAStatus(Status::BAD_VALUE); + } + UNUSED(in_algorithm); + UNUSED(in_wrappedkey); + Status status = Status::ERROR_DRM_CANNOT_HANDLE; + std::vector signature; + *_aidl_return = std::vector(); + void* cast_auth_handle = ::dlopen("libcast_auth.so", RTLD_LAZY); + if (!cast_auth_handle) { + ALOGE("Fail to get TA for signing"); + return toNdkScopedAStatus(status); + } + typedef bool (*func_type)(const std::vector&, + std::vector*); + func_type sign_hash_func = + reinterpret_cast(::dlsym(cast_auth_handle, "SignHash")); + if (!sign_hash_func) { + ALOGE("Fail to apply signing method"); + dlclose(cast_auth_handle); + return toNdkScopedAStatus(status); + } + const std::vector msg = adjustHash(in_message); + int res = sign_hash_func(msg, &signature); + dlclose(cast_auth_handle); + if (res == 0) { + *_aidl_return = signature; + return toNdkScopedAStatus(Status::OK); + } + ALOGE("Get empty result from TA"); + return toNdkScopedAStatus(status); +} + +::ndk::ScopedAStatus DrmPlugin::decrypt(const std::vector& in_sessionId, + const std::vector& in_keyId, + const std::vector& in_input, + const std::vector& in_iv, + std::vector* _aidl_return) { + UNUSED(in_sessionId); + UNUSED(in_keyId); + UNUSED(in_input); + UNUSED(in_iv); + UNUSED(_aidl_return); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::encrypt(const std::vector& in_sessionId, + const std::vector& in_keyId, + const std::vector& in_input, + const std::vector& in_iv, + std::vector* _aidl_return) { + UNUSED(in_sessionId); + UNUSED(in_keyId); + UNUSED(in_input); + UNUSED(in_iv); + UNUSED(_aidl_return); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::getHdcpLevels( + ::aidl::android::hardware::drm::HdcpLevels* _aidl_return) { + UNUSED(_aidl_return); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::getKeyRequest( + const std::vector& in_scope, + const std::vector& in_initData, + const std::string& in_mimeType, + ::aidl::android::hardware::drm::KeyType in_keyType, + const std::vector<::aidl::android::hardware::drm::KeyValue>& in_optionalParameters, + ::aidl::android::hardware::drm::KeyRequest* _aidl_return) { + UNUSED(in_scope); + UNUSED(in_initData); + UNUSED(in_mimeType); + UNUSED(in_keyType); + UNUSED(in_optionalParameters); + UNUSED(_aidl_return); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::getLogMessages( + std::vector<::aidl::android::hardware::drm::LogMessage>* _aidl_return) { + UNUSED(_aidl_return); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::getMetrics( + std::vector<::aidl::android::hardware::drm::DrmMetricGroup>* _aidl_return) { + UNUSED(_aidl_return); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::getNumberOfSessions( + ::aidl::android::hardware::drm::NumberOfSessions* _aidl_return) { + UNUSED(_aidl_return); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::getOfflineLicenseKeySetIds( + std::vector<::aidl::android::hardware::drm::KeySetId>* _aidl_return) { + UNUSED(_aidl_return); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::getOfflineLicenseState( + const ::aidl::android::hardware::drm::KeySetId& in_keySetId, + ::aidl::android::hardware::drm::OfflineLicenseState* _aidl_return) { + UNUSED(in_keySetId); + UNUSED(_aidl_return); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::getPropertyString(const std::string& in_propertyName, + std::string* _aidl_return) { + UNUSED(in_propertyName); + UNUSED(_aidl_return); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::getProvisionRequest( + const std::string& in_certificateType, + const std::string& in_certificateAuthority, + ::aidl::android::hardware::drm::ProvisionRequest* _aidl_return) { + UNUSED(in_certificateType); + UNUSED(in_certificateAuthority); + UNUSED(_aidl_return); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::getSecureStop( + const ::aidl::android::hardware::drm::SecureStopId& in_secureStopId, + ::aidl::android::hardware::drm::SecureStop* _aidl_return) { + UNUSED(in_secureStopId); + UNUSED(_aidl_return); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::getSecureStopIds( + std::vector<::aidl::android::hardware::drm::SecureStopId>* _aidl_return) { + UNUSED(_aidl_return); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::getSecureStops( + std::vector<::aidl::android::hardware::drm::SecureStop>* _aidl_return) { + UNUSED(_aidl_return); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::getSecurityLevel( + const std::vector& in_sessionId, + ::aidl::android::hardware::drm::SecurityLevel* _aidl_return) { + UNUSED(in_sessionId); + UNUSED(_aidl_return); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::provideKeyResponse( + const std::vector& in_scope, + const std::vector& in_response, + ::aidl::android::hardware::drm::KeySetId* _aidl_return) { + UNUSED(in_scope); + UNUSED(in_response); + UNUSED(_aidl_return); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::provideProvisionResponse( + const std::vector& in_response, + ::aidl::android::hardware::drm::ProvideProvisionResponseResult* _aidl_return) { + UNUSED(in_response); + UNUSED(_aidl_return); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::queryKeyStatus( + const std::vector& in_sessionId, + std::vector<::aidl::android::hardware::drm::KeyValue>* _aidl_return) { + UNUSED(in_sessionId); + UNUSED(_aidl_return); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::releaseAllSecureStops() { + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::releaseSecureStop( + const ::aidl::android::hardware::drm::SecureStopId& in_secureStopId) { + UNUSED(in_secureStopId); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::releaseSecureStops( + const ::aidl::android::hardware::drm::OpaqueData& in_ssRelease) { + UNUSED(in_ssRelease); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::removeAllSecureStops() { + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::removeKeys(const std::vector& in_sessionId) { + UNUSED(in_sessionId); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::removeOfflineLicense( + const ::aidl::android::hardware::drm::KeySetId& in_keySetId) { + UNUSED(in_keySetId); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::removeSecureStop( + const ::aidl::android::hardware::drm::SecureStopId& in_secureStopId) { + UNUSED(in_secureStopId); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::requiresSecureDecoder( + const std::string& in_mime, + ::aidl::android::hardware::drm::SecurityLevel in_level, + bool* _aidl_return) { + UNUSED(in_mime); + UNUSED(in_level); + UNUSED(_aidl_return); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::restoreKeys( + const std::vector& in_sessionId, + const ::aidl::android::hardware::drm::KeySetId& in_keySetId) { + UNUSED(in_sessionId); + UNUSED(in_keySetId); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::setCipherAlgorithm(const std::vector& in_sessionId, + const std::string& in_algorithm) { + UNUSED(in_sessionId); + UNUSED(in_algorithm); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::setListener( + const std::shared_ptr<::aidl::android::hardware::drm::IDrmPluginListener>& + in_listener) { + UNUSED(in_listener); + return toNdkScopedAStatus(Status::OK); +} + +::ndk::ScopedAStatus DrmPlugin::setMacAlgorithm(const std::vector& in_sessionId, + const std::string& in_algorithm) { + UNUSED(in_sessionId); + UNUSED(in_algorithm); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::setPlaybackId(const std::vector& in_sessionId, + const std::string& in_playbackId) { + UNUSED(in_sessionId); + UNUSED(in_playbackId); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::setPropertyByteArray(const std::string& in_propertyName, + const std::vector& in_value) { + UNUSED(in_propertyName); + UNUSED(in_value); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::setPropertyString(const std::string& in_propertyName, + const std::string& in_value) { + UNUSED(in_propertyName); + UNUSED(in_value); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::sign(const std::vector& in_sessionId, + const std::vector& in_keyId, + const std::vector& in_message, + std::vector* _aidl_return) { + UNUSED(in_sessionId); + UNUSED(in_keyId); + UNUSED(in_message); + UNUSED(_aidl_return); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + +::ndk::ScopedAStatus DrmPlugin::verify(const std::vector& in_sessionId, + const std::vector& in_keyId, + const std::vector& in_message, + const std::vector& in_signature, + bool* _aidl_return) { + UNUSED(in_sessionId); + UNUSED(in_keyId); + UNUSED(in_message); + UNUSED(in_signature); + UNUSED(_aidl_return); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); +} + + +} // namespace castkey +} // namespace drm +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/cast_auth/mediadrm/Service.cpp b/cast_auth/mediadrm/Service.cpp new file mode 100644 index 0000000..53b50e2 --- /dev/null +++ b/cast_auth/mediadrm/Service.cpp @@ -0,0 +1,23 @@ +#define LOG_TAG "castkey-main" + +#include +#include +#include +#include "CreatePluginFactories.h" + +using ::android::base::InitLogging; +using ::android::base::LogdLogger; +using ::aidl::android::hardware::drm::castkey::createDrmFactory; +using ::aidl::android::hardware::drm::castkey::DrmFactory; + +int main(int /*argc*/, char* argv[]) { + InitLogging(argv, LogdLogger()); + ABinderProcess_setThreadPoolMaxThreadCount(8); + std::shared_ptr drmFactory = createDrmFactory(); + const std::string drmInstance = std::string() + DrmFactory::descriptor + "/castkey"; + binder_status_t status = + AServiceManager_addService(drmFactory->asBinder().get(), drmInstance.c_str()); + CHECK(status == STATUS_OK); + ABinderProcess_joinThreadPool(); + return EXIT_FAILURE; +} \ No newline at end of file diff --git a/cast_auth/mediadrm/SessionLibrary.cpp b/cast_auth/mediadrm/SessionLibrary.cpp new file mode 100644 index 0000000..8d56660 --- /dev/null +++ b/cast_auth/mediadrm/SessionLibrary.cpp @@ -0,0 +1,39 @@ +#include "SessionLibrary.h" + +#include +#include + +namespace castkeydrm { + +std::mutex SessionLibrary::singleton_lock_; +SessionLibrary* SessionLibrary::singleton_ = NULL; + +SessionLibrary* SessionLibrary::get() { + std::lock_guard guard(singleton_lock_); + + if (singleton_ == NULL) { + singleton_ = new SessionLibrary(); + } + + return singleton_; +} + +std::vector SessionLibrary::createSession() { + std::lock_guard guard(session_lock_); + + std::string session_string = std::to_string(next_session_id_); + next_session_id_ += 1; + sessions_.emplace_back(session_string.begin(), session_string.end()); + return sessions_.back(); +} + +void SessionLibrary::closeSession(const std::vector& session) { + std::lock_guard guard(session_lock_); + sessions_.erase(std::remove_if(sessions_.begin(), sessions_.end(), + [&session](const std::vector& e) { + return std::equal(e.begin(), e.end(), session.begin()); + }), + sessions_.end()); +} + +} // namespace castkeydrm \ No newline at end of file diff --git a/cast_auth/mediadrm/android.hardware.drm-service.castkey.rc b/cast_auth/mediadrm/android.hardware.drm-service.castkey.rc new file mode 100644 index 0000000..73106a9 --- /dev/null +++ b/cast_auth/mediadrm/android.hardware.drm-service.castkey.rc @@ -0,0 +1,6 @@ +service vendor.drm-castkey-service /vendor/bin/hw/android.hardware.drm-service.castkey + class hal + user media + group mediadrm drmrpc + ioprio rt 4 + interface aidl android.hardware.drm.IDrmFactory/castkey diff --git a/cast_auth/mediadrm/include/CastKeyTypes.h b/cast_auth/mediadrm/include/CastKeyTypes.h new file mode 100644 index 0000000..5eb17f7 --- /dev/null +++ b/cast_auth/mediadrm/include/CastKeyTypes.h @@ -0,0 +1,48 @@ +#ifndef CASTKEY_TYPES_H_ +#define CASTKEY_TYPES_H_ + +#include +#include +#include + +namespace castkeydrm { + +const uint8_t kBlockSize = 16; // AES_BLOCK_SIZE; +typedef uint8_t KeyId[kBlockSize]; +typedef uint8_t Iv[kBlockSize]; + +typedef std::map, std::vector> KeyMap; + +#define CASTKEY_DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&) = delete; \ + void operator=(const TypeName&) = delete; + +#define CASTKEY_DISALLOW_COPY_AND_ASSIGN_AND_NEW(TypeName) \ + TypeName() = delete; \ + TypeName(const TypeName&) = delete; \ + void operator=(const TypeName&) = delete; + +enum CdmResponseType : int32_t { + OK = 0, + ERROR_NO_LICENSE = 1, + ERROR_SESSION_NOT_OPENED = 3, + ERROR_CANNOT_HANDLE = 4, + ERROR_INVALID_STATE = 5, + BAD_VALUE = 6, + ERROR_DECRYPT = 11, + ERROR_UNKNOWN = 12, + ERROR_INSUFFICIENT_SECURITY = 13, + ERROR_FRAME_TOO_LARGE = 14, + ERROR_SESSION_LOST_STATE = 15, + ERROR_RESOURCE_CONTENTION = 16, +}; + +enum CdmKeyType : int32_t { + KEY_TYPE_OFFLINE = 0, + KEY_TYPE_STREAMING = 1, + KEY_TYPE_RELEASE = 2, +}; + +} // namespace castkeydrm + +#endif // CASTKEY_TYPES_H_ \ No newline at end of file diff --git a/cast_auth/mediadrm/include/CreatePluginFactories.h b/cast_auth/mediadrm/include/CreatePluginFactories.h new file mode 100644 index 0000000..acf9545 --- /dev/null +++ b/cast_auth/mediadrm/include/CreatePluginFactories.h @@ -0,0 +1,20 @@ +#ifndef CREATE_PLUGIN_FACTORIES_H_ +#define CREATE_PLUGIN_FACTORIES_H_ + +#include "DrmFactory.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace drm { +namespace castkey { + +std::shared_ptr createDrmFactory(); + +} // namespace castkey +} // namespace drm +} // namespace hardware +} // namespace android +} // namespace aidl + +#endif // CREATE_PLUGIN_FACTORIES_H_ \ No newline at end of file diff --git a/cast_auth/mediadrm/include/DrmFactory.h b/cast_auth/mediadrm/include/DrmFactory.h new file mode 100644 index 0000000..eb0816d --- /dev/null +++ b/cast_auth/mediadrm/include/DrmFactory.h @@ -0,0 +1,50 @@ +#ifndef DRM_FACTORY_H_ +#define DRM_FACTORY_H_ + +#include +#include +#include +#include + +#include +#include + +#include "CastKeyTypes.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace drm { +namespace castkey { + +struct DrmFactory : public BnDrmFactory { + DrmFactory() {}; + virtual ~DrmFactory() {}; + + ::ndk::ScopedAStatus createDrmPlugin( + const ::aidl::android::hardware::drm::Uuid& in_uuid, + const std::string& in_appPackageName, + std::shared_ptr<::aidl::android::hardware::drm::IDrmPlugin>* _aidl_return) override; + + ::ndk::ScopedAStatus createCryptoPlugin( + const ::aidl::android::hardware::drm::Uuid& in_uuid, + const std::vector& in_initData, + std::shared_ptr<::aidl::android::hardware::drm::ICryptoPlugin>* _aidl_return) override; + + ::ndk::ScopedAStatus getSupportedCryptoSchemes( + ::aidl::android::hardware::drm::CryptoSchemes* _aidl_return) override; + + binder_status_t dump(int fd, const char** args, uint32_t numArgs) override; + + + private: + CASTKEY_DISALLOW_COPY_AND_ASSIGN(DrmFactory); +}; + +} // namespace castkey +} // namespace drm +} // namespace hardware +} // namespace android +} // namespace aidl + +#endif // DRM_FACTORIES_H_ diff --git a/cast_auth/mediadrm/include/DrmPlugin.h b/cast_auth/mediadrm/include/DrmPlugin.h new file mode 100644 index 0000000..f6a3f6f --- /dev/null +++ b/cast_auth/mediadrm/include/DrmPlugin.h @@ -0,0 +1,143 @@ +#ifndef DRM_PLUGIN_H_ +#define DRM_PLUGIN_H_ + +#include +#include +#include + +#include +#include + +#include + +namespace aidl { +namespace android { +namespace hardware { +namespace drm { +namespace castkey { + +using namespace castkeydrm; +using ::aidl::android::hardware::drm::KeyType; +using ::aidl::android::hardware::drm::Status; + +struct DrmPlugin : public BnDrmPlugin { +public: + explicit DrmPlugin(); + virtual ~DrmPlugin(); + + ::ndk::ScopedAStatus closeSession(const std::vector& in_sessionId) override; + ::ndk::ScopedAStatus decrypt(const std::vector& in_sessionId, + const std::vector& in_keyId, + const std::vector& in_input, + const std::vector& in_iv, + std::vector* _aidl_return) override; + ::ndk::ScopedAStatus encrypt(const std::vector& in_sessionId, + const std::vector& in_keyId, + const std::vector& in_input, + const std::vector& in_iv, + std::vector* _aidl_return) override; + ::ndk::ScopedAStatus getHdcpLevels( + ::aidl::android::hardware::drm::HdcpLevels* _aidl_return) override; + ::ndk::ScopedAStatus getKeyRequest( + const std::vector& in_scope, + const std::vector& in_initData, + const std::string& in_mimeType, + ::aidl::android::hardware::drm::KeyType in_keyType, + const std::vector<::aidl::android::hardware::drm::KeyValue>& in_optionalParameters, + ::aidl::android::hardware::drm::KeyRequest* _aidl_return) override; + ::ndk::ScopedAStatus getLogMessages( + std::vector<::aidl::android::hardware::drm::LogMessage>* _aidl_return) override; + + ::ndk::ScopedAStatus getMetrics( + std::vector<::aidl::android::hardware::drm::DrmMetricGroup>* _aidl_return) override; + ::ndk::ScopedAStatus getNumberOfSessions( + ::aidl::android::hardware::drm::NumberOfSessions* _aidl_return) override; + ::ndk::ScopedAStatus getOfflineLicenseKeySetIds( + std::vector<::aidl::android::hardware::drm::KeySetId>* _aidl_return) override; + ::ndk::ScopedAStatus getOfflineLicenseState( + const ::aidl::android::hardware::drm::KeySetId& in_keySetId, + ::aidl::android::hardware::drm::OfflineLicenseState* _aidl_return) override; + ::ndk::ScopedAStatus getPropertyByteArray(const std::string& in_propertyName, + std::vector* _aidl_return) override; + ::ndk::ScopedAStatus getPropertyString(const std::string& in_propertyName, + std::string* _aidl_return) override; + ::ndk::ScopedAStatus getProvisionRequest( + const std::string& in_certificateType, + const std::string& in_certificateAuthority, + ::aidl::android::hardware::drm::ProvisionRequest* _aidl_return) override; + ::ndk::ScopedAStatus getSecureStop( + const ::aidl::android::hardware::drm::SecureStopId& in_secureStopId, + ::aidl::android::hardware::drm::SecureStop* _aidl_return) override; + ::ndk::ScopedAStatus getSecureStopIds( + std::vector<::aidl::android::hardware::drm::SecureStopId>* _aidl_return) override; + ::ndk::ScopedAStatus getSecureStops( + std::vector<::aidl::android::hardware::drm::SecureStop>* _aidl_return) override; + ::ndk::ScopedAStatus getSecurityLevel( + const std::vector& in_sessionId, + ::aidl::android::hardware::drm::SecurityLevel* _aidl_return) override; + ::ndk::ScopedAStatus openSession(::aidl::android::hardware::drm::SecurityLevel in_securityLevel, + std::vector* _aidl_return) override; + ::ndk::ScopedAStatus provideKeyResponse( + const std::vector& in_scope, + const std::vector& in_response, + ::aidl::android::hardware::drm::KeySetId* _aidl_return) override; + ::ndk::ScopedAStatus provideProvisionResponse( + const std::vector& in_response, + ::aidl::android::hardware::drm::ProvideProvisionResponseResult* _aidl_return) override; + ::ndk::ScopedAStatus queryKeyStatus( + const std::vector& in_sessionId, + std::vector<::aidl::android::hardware::drm::KeyValue>* _aidl_return) override; + ::ndk::ScopedAStatus releaseAllSecureStops() override; + ::ndk::ScopedAStatus releaseSecureStop( + const ::aidl::android::hardware::drm::SecureStopId& in_secureStopId) override; + ::ndk::ScopedAStatus releaseSecureStops( + const ::aidl::android::hardware::drm::OpaqueData& in_ssRelease) override; + ::ndk::ScopedAStatus removeAllSecureStops() override; + ::ndk::ScopedAStatus removeKeys(const std::vector& in_sessionId) override; + ::ndk::ScopedAStatus removeOfflineLicense( + const ::aidl::android::hardware::drm::KeySetId& in_keySetId) override; + ::ndk::ScopedAStatus removeSecureStop( + const ::aidl::android::hardware::drm::SecureStopId& in_secureStopId) override; + ::ndk::ScopedAStatus requiresSecureDecoder( + const std::string& in_mime, + ::aidl::android::hardware::drm::SecurityLevel in_level, + bool* _aidl_return) override; + ::ndk::ScopedAStatus restoreKeys( + const std::vector& in_sessionId, + const ::aidl::android::hardware::drm::KeySetId& in_keySetId) override; + ::ndk::ScopedAStatus setCipherAlgorithm(const std::vector& in_sessionId, + const std::string& in_algorithm) override; + ::ndk::ScopedAStatus setListener( + const std::shared_ptr<::aidl::android::hardware::drm::IDrmPluginListener>& + in_listener) override; + ::ndk::ScopedAStatus setMacAlgorithm(const std::vector& in_sessionId, + const std::string& in_algorithm) override; + ::ndk::ScopedAStatus setPlaybackId(const std::vector& in_sessionId, + const std::string& in_playbackId) override; + ::ndk::ScopedAStatus setPropertyByteArray(const std::string& in_propertyName, + const std::vector& in_value) override; + ::ndk::ScopedAStatus setPropertyString(const std::string& in_propertyName, + const std::string& in_value) override; + ::ndk::ScopedAStatus sign(const std::vector& in_sessionId, + const std::vector& in_keyId, + const std::vector& in_message, + std::vector* _aidl_return) override; + ::ndk::ScopedAStatus signRSA(const std::vector& in_sessionId, + const std::string& in_algorithm, + const std::vector& in_message, + const std::vector& in_wrappedkey, + std::vector* _aidl_return) override; + ::ndk::ScopedAStatus verify(const std::vector& in_sessionId, + const std::vector& in_keyId, + const std::vector& in_message, + const std::vector& in_signature, + bool* _aidl_return) override; +}; + +} // namespace castkey +} // namespace drm +} // namespace hardware +} // namespace android +} // namespace aidl + +#endif // DRM_PLUGIN_H_ \ No newline at end of file diff --git a/cast_auth/mediadrm/include/SessionLibrary.h b/cast_auth/mediadrm/include/SessionLibrary.h new file mode 100644 index 0000000..d2d0e49 --- /dev/null +++ b/cast_auth/mediadrm/include/SessionLibrary.h @@ -0,0 +1,28 @@ +#ifndef SESSION_LIBRARY_H_ +#define SESSION_LIBRARY_H_ + +#include +#include + +namespace castkeydrm { + +class SessionLibrary { +public: + static SessionLibrary* get(); + std::vector createSession(); + void closeSession(const std::vector& session); + +private: + SessionLibrary() : next_session_id_(1) {} + + static std::mutex singleton_lock_; + static SessionLibrary* singleton_; + + std::mutex session_lock_; + uint32_t next_session_id_; + std::vector> sessions_; +}; + +} // namespace castkeydrm + +#endif // SESSION_LIBRARY_H_ \ No newline at end of file diff --git a/cast_auth/mediadrm/include/Utils.h b/cast_auth/mediadrm/include/Utils.h new file mode 100644 index 0000000..98821f4 --- /dev/null +++ b/cast_auth/mediadrm/include/Utils.h @@ -0,0 +1,44 @@ +#ifndef UTILS_H_ +#define UTILS_H_ + +#include + +#include "SessionLibrary.h" + +#include +#include "aidl/android/hardware/drm/Status.h" +#include "CastKeyTypes.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace drm { +namespace castkey { + +inline ::ndk::ScopedAStatus toNdkScopedAStatus(::aidl::android::hardware::drm::Status status, + const char* msg = nullptr) { + if (Status::OK == status) { + return ::ndk::ScopedAStatus::ok(); + } else { + auto err = static_cast(status); + if (msg) { + return ::ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(err, msg); + } else { + return ::ndk::ScopedAStatus::fromServiceSpecificError(err); + } + } +} + +inline ::ndk::ScopedAStatus toNdkScopedAStatus(castkeydrm::CdmResponseType res) { + return toNdkScopedAStatus(static_cast<::aidl::android::hardware::drm::Status>(res)); +} + +#define UNUSED(x) (void)(x); + +} // namespace castkey +} // namespace drm +} // namespace hardware +} // namespace android +} // namespace aidl + +#endif // UTILS_H_ diff --git a/cast_auth/mediadrm/manifest_android.hardware.drm-service.castkey.xml b/cast_auth/mediadrm/manifest_android.hardware.drm-service.castkey.xml new file mode 100644 index 0000000..412a10b --- /dev/null +++ b/cast_auth/mediadrm/manifest_android.hardware.drm-service.castkey.xml @@ -0,0 +1,7 @@ + + + android.hardware.drm + 1 + IDrmFactory/castkey + + \ No newline at end of file diff --git a/device-tangorpro.mk b/device-tangorpro.mk index 3c6a790..d1d1ada 100644 --- a/device-tangorpro.mk +++ b/device-tangorpro.mk @@ -258,6 +258,13 @@ PRODUCT_VENDOR_PROPERTIES += \ PRODUCT_SOONG_NAMESPACES += \ vendor/lib64 +# TODO(b/366426322): Merge CastKey Drm plugin into `device/google/gs-common`. +# CastKey Drm plugin modules +PRODUCT_SOONG_NAMESPACES += \ + device/google/tangorpro/cast_auth/mediadrm +PRODUCT_PACKAGES += \ + android.hardware.drm-service.castkey + # MIPI Coex Configs PRODUCT_COPY_FILES += \ device/google/tangorpro/radio/tangor_camera_front_mipi_coex_table.csv:$(TARGET_COPY_OUT_VENDOR)/etc/modem/camera_front_mipi_coex_table.csv \