Merge "Support CAST V2 Authentication in MediaDrm" into klp-modular-dev
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -21,12 +21,15 @@ import java.lang.ref.WeakReference;
|
||||
import java.util.UUID;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import android.os.Binder;
|
||||
import android.os.Debug;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.util.Log;
|
||||
import android.content.Context;
|
||||
|
||||
/**
|
||||
* MediaDrm can be used to obtain keys for decrypting protected media streams, in
|
||||
@@ -102,6 +105,20 @@ public final class MediaDrm {
|
||||
|
||||
private long mNativeContext;
|
||||
|
||||
/**
|
||||
* Specify no certificate type
|
||||
*
|
||||
* @hide - not part of the public API at this time
|
||||
*/
|
||||
public static final int CERTIFICATE_TYPE_NONE = 0;
|
||||
|
||||
/**
|
||||
* Specify X.509 certificate type
|
||||
*
|
||||
* @hide - not part of the public API at this time
|
||||
*/
|
||||
public static final int CERTIFICATE_TYPE_X509 = 1;
|
||||
|
||||
/**
|
||||
* Query if the given scheme identified by its UUID is supported on
|
||||
* this device.
|
||||
@@ -318,6 +335,9 @@ public final class MediaDrm {
|
||||
* Contains the opaque data an app uses to request keys from a license server
|
||||
*/
|
||||
public final static class KeyRequest {
|
||||
private byte[] mData;
|
||||
private String mDefaultUrl;
|
||||
|
||||
KeyRequest() {}
|
||||
|
||||
/**
|
||||
@@ -331,9 +351,6 @@ public final class MediaDrm {
|
||||
* server URL from other sources.
|
||||
*/
|
||||
public String getDefaultUrl() { return mDefaultUrl; }
|
||||
|
||||
private byte[] mData;
|
||||
private String mDefaultUrl;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -458,7 +475,12 @@ public final class MediaDrm {
|
||||
* is returned in ProvisionRequest.data. The recommended URL to deliver the provision
|
||||
* request to is returned in ProvisionRequest.defaultUrl.
|
||||
*/
|
||||
public native ProvisionRequest getProvisionRequest();
|
||||
public ProvisionRequest getProvisionRequest() {
|
||||
return getProvisionRequestNative(CERTIFICATE_TYPE_NONE, "");
|
||||
}
|
||||
|
||||
private native ProvisionRequest getProvisionRequestNative(int certType,
|
||||
String certAuthority);
|
||||
|
||||
/**
|
||||
* After a provision response is received by the app, it is provided to the DRM
|
||||
@@ -470,7 +492,12 @@ public final class MediaDrm {
|
||||
* @throws DeniedByServerException if the response indicates that the
|
||||
* server rejected the request
|
||||
*/
|
||||
public native void provideProvisionResponse(byte[] response)
|
||||
public void provideProvisionResponse(byte[] response)
|
||||
throws DeniedByServerException {
|
||||
provideProvisionResponseNative(response);
|
||||
}
|
||||
|
||||
private native Certificate provideProvisionResponseNative(byte[] response)
|
||||
throws DeniedByServerException;
|
||||
|
||||
/**
|
||||
@@ -685,6 +712,120 @@ public final class MediaDrm {
|
||||
return new CryptoSession(this, sessionId, cipherAlgorithm, macAlgorithm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains the opaque data an app uses to request a certificate from a provisioning
|
||||
* server
|
||||
*
|
||||
* @hide - not part of the public API at this time
|
||||
*/
|
||||
public final static class CertificateRequest {
|
||||
private byte[] mData;
|
||||
private String mDefaultUrl;
|
||||
|
||||
CertificateRequest(byte[] data, String defaultUrl) {
|
||||
mData = data;
|
||||
mDefaultUrl = defaultUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the opaque message data
|
||||
*/
|
||||
public byte[] getData() { return mData; }
|
||||
|
||||
/**
|
||||
* Get the default URL to use when sending the certificate request
|
||||
* message to a server, if known. The app may prefer to use a different
|
||||
* certificate server URL obtained from other sources.
|
||||
*/
|
||||
public String getDefaultUrl() { return mDefaultUrl; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a certificate request, specifying the certificate type
|
||||
* and authority. The response received should be passed to
|
||||
* provideCertificateResponse.
|
||||
*
|
||||
* @param certType Specifies the certificate type.
|
||||
*
|
||||
* @param certAuthority is passed to the certificate server to specify
|
||||
* the chain of authority.
|
||||
*
|
||||
* @hide - not part of the public API at this time
|
||||
*/
|
||||
public CertificateRequest getCertificateRequest(int certType,
|
||||
String certAuthority)
|
||||
{
|
||||
ProvisionRequest provisionRequest = getProvisionRequestNative(certType, certAuthority);
|
||||
return new CertificateRequest(provisionRequest.getData(),
|
||||
provisionRequest.getDefaultUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains the wrapped private key and public certificate data associated
|
||||
* with a certificate.
|
||||
*
|
||||
* @hide - not part of the public API at this time
|
||||
*/
|
||||
public final static class Certificate {
|
||||
Certificate() {}
|
||||
|
||||
/**
|
||||
* Get the wrapped private key data
|
||||
*/
|
||||
public byte[] getWrappedPrivateKey() { return mWrappedKey; }
|
||||
|
||||
/**
|
||||
* Get the PEM-encoded certificate chain
|
||||
*/
|
||||
public byte[] getContent() { return mCertificateData; }
|
||||
|
||||
private byte[] mWrappedKey;
|
||||
private byte[] mCertificateData;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process a response from the certificate server. The response
|
||||
* is obtained from an HTTP Post to the url provided by getCertificateRequest.
|
||||
* <p>
|
||||
* The public X509 certificate chain and wrapped private key are returned
|
||||
* in the returned Certificate objec. The certificate chain is in PEM format.
|
||||
* The wrapped private key should be stored in application private
|
||||
* storage, and used when invoking the signRSA method.
|
||||
*
|
||||
* @param response the opaque certificate response byte array to provide to the
|
||||
* DRM engine plugin.
|
||||
*
|
||||
* @throws DeniedByServerException if the response indicates that the
|
||||
* server rejected the request
|
||||
*
|
||||
* @hide - not part of the public API at this time
|
||||
*/
|
||||
public Certificate provideCertificateResponse(byte[] response)
|
||||
throws DeniedByServerException {
|
||||
return provideProvisionResponseNative(response);
|
||||
}
|
||||
|
||||
private static final native byte[] signRSANative(MediaDrm drm, byte[] sessionId,
|
||||
String algorithm, byte[] wrappedKey,
|
||||
byte[] message);
|
||||
|
||||
/**
|
||||
* Sign data using an RSA key
|
||||
*
|
||||
* @param context the app context
|
||||
* @param sessionId a sessionId obtained from openSession on the MediaDrm object
|
||||
* @param algorithm the signing algorithm to use, e.g. "PKCS1-BlockType1"
|
||||
* @param wrappedKey - the wrapped (encrypted) RSA private key obtained
|
||||
* from provideCertificateResponse
|
||||
* @param message the data for which a signature is to be computed
|
||||
*
|
||||
* @hide - not part of the public API at this time
|
||||
*/
|
||||
public byte[] signRSA(Context context, byte[] sessionId, String algorithm, byte[] wrappedKey, byte[] message) {
|
||||
return signRSANative(this, sessionId, algorithm, wrappedKey, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() {
|
||||
native_finalize();
|
||||
|
||||
@@ -100,6 +100,16 @@ struct KeyTypes {
|
||||
jint kKeyTypeRelease;
|
||||
} gKeyTypes;
|
||||
|
||||
struct CertificateTypes {
|
||||
jint kCertificateTypeNone;
|
||||
jint kCertificateTypeX509;
|
||||
} gCertificateTypes;
|
||||
|
||||
struct CertificateFields {
|
||||
jfieldID wrappedPrivateKey;
|
||||
jfieldID certificateData;
|
||||
};
|
||||
|
||||
struct fields_t {
|
||||
jfieldID context;
|
||||
jmethodID post_event;
|
||||
@@ -110,6 +120,11 @@ struct fields_t {
|
||||
SetFields set;
|
||||
IteratorFields iterator;
|
||||
EntryFields entry;
|
||||
CertificateFields certificate;
|
||||
jclass certificateClassId;
|
||||
jclass hashmapClassId;
|
||||
jclass arraylistClassId;
|
||||
jclass stringClassId;
|
||||
};
|
||||
|
||||
static fields_t gFields;
|
||||
@@ -406,8 +421,7 @@ static String8 JStringToString8(JNIEnv *env, jstring const &jstr) {
|
||||
*/
|
||||
|
||||
static KeyedVector<String8, String8> HashMapToKeyedVector(JNIEnv *env, jobject &hashMap) {
|
||||
jclass clazz;
|
||||
FIND_CLASS(clazz, "java/lang/String");
|
||||
jclass clazz = gFields.stringClassId;
|
||||
KeyedVector<String8, String8> keyedVector;
|
||||
|
||||
jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet);
|
||||
@@ -450,8 +464,7 @@ static KeyedVector<String8, String8> HashMapToKeyedVector(JNIEnv *env, jobject &
|
||||
}
|
||||
|
||||
static jobject KeyedVectorToHashMap (JNIEnv *env, KeyedVector<String8, String8> const &map) {
|
||||
jclass clazz;
|
||||
FIND_CLASS(clazz, "java/util/HashMap");
|
||||
jclass clazz = gFields.hashmapClassId;
|
||||
jobject hashMap = env->NewObject(clazz, gFields.hashmap.init);
|
||||
for (size_t i = 0; i < map.size(); ++i) {
|
||||
jstring jkey = env->NewStringUTF(map.keyAt(i).string());
|
||||
@@ -465,8 +478,7 @@ static jobject KeyedVectorToHashMap (JNIEnv *env, KeyedVector<String8, String8>
|
||||
|
||||
static jobject ListOfVectorsToArrayListOfByteArray(JNIEnv *env,
|
||||
List<Vector<uint8_t> > list) {
|
||||
jclass clazz;
|
||||
FIND_CLASS(clazz, "java/util/ArrayList");
|
||||
jclass clazz = gFields.arraylistClassId;
|
||||
jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
|
||||
List<Vector<uint8_t> >::iterator iter = list.begin();
|
||||
while (iter != list.end()) {
|
||||
@@ -542,6 +554,11 @@ static void android_media_MediaDrm_native_init(JNIEnv *env) {
|
||||
GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_RELEASE", "I");
|
||||
gKeyTypes.kKeyTypeRelease = env->GetStaticIntField(clazz, field);
|
||||
|
||||
GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_NONE", "I");
|
||||
gCertificateTypes.kCertificateTypeNone = env->GetStaticIntField(clazz, field);
|
||||
GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_X509", "I");
|
||||
gCertificateTypes.kCertificateTypeX509 = env->GetStaticIntField(clazz, field);
|
||||
|
||||
FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
|
||||
GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B");
|
||||
GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
|
||||
@@ -550,6 +567,11 @@ static void android_media_MediaDrm_native_init(JNIEnv *env) {
|
||||
GET_FIELD_ID(gFields.provisionRequest.data, clazz, "mData", "[B");
|
||||
GET_FIELD_ID(gFields.provisionRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
|
||||
|
||||
FIND_CLASS(clazz, "android/media/MediaDrm$Certificate");
|
||||
GET_FIELD_ID(gFields.certificate.wrappedPrivateKey, clazz, "mWrappedKey", "[B");
|
||||
GET_FIELD_ID(gFields.certificate.certificateData, clazz, "mCertificateData", "[B");
|
||||
gFields.certificateClassId = reinterpret_cast<jclass>(env->NewGlobalRef(clazz));
|
||||
|
||||
FIND_CLASS(clazz, "java/util/ArrayList");
|
||||
GET_METHOD_ID(gFields.arraylist.init, clazz, "<init>", "()V");
|
||||
GET_METHOD_ID(gFields.arraylist.add, clazz, "add", "(Ljava/lang/Object;)Z");
|
||||
@@ -571,6 +593,15 @@ static void android_media_MediaDrm_native_init(JNIEnv *env) {
|
||||
FIND_CLASS(clazz, "java/util/Map$Entry");
|
||||
GET_METHOD_ID(gFields.entry.getKey, clazz, "getKey", "()Ljava/lang/Object;");
|
||||
GET_METHOD_ID(gFields.entry.getValue, clazz, "getValue", "()Ljava/lang/Object;");
|
||||
|
||||
FIND_CLASS(clazz, "java/util/HashMap");
|
||||
gFields.hashmapClassId = reinterpret_cast<jclass>(env->NewGlobalRef(clazz));
|
||||
|
||||
FIND_CLASS(clazz, "java/lang/String");
|
||||
gFields.stringClassId = reinterpret_cast<jclass>(env->NewGlobalRef(clazz));
|
||||
|
||||
FIND_CLASS(clazz, "java/util/ArrayList");
|
||||
gFields.arraylistClassId = reinterpret_cast<jclass>(env->NewGlobalRef(clazz));
|
||||
}
|
||||
|
||||
static void android_media_MediaDrm_native_setup(
|
||||
@@ -826,8 +857,8 @@ static jobject android_media_MediaDrm_queryKeyStatus(
|
||||
return KeyedVectorToHashMap(env, infoMap);
|
||||
}
|
||||
|
||||
static jobject android_media_MediaDrm_getProvisionRequest(
|
||||
JNIEnv *env, jobject thiz) {
|
||||
static jobject android_media_MediaDrm_getProvisionRequestNative(
|
||||
JNIEnv *env, jobject thiz, jint jcertType, jstring jcertAuthority) {
|
||||
sp<IDrm> drm = GetDrm(env, thiz);
|
||||
|
||||
if (drm == NULL) {
|
||||
@@ -839,7 +870,17 @@ static jobject android_media_MediaDrm_getProvisionRequest(
|
||||
Vector<uint8_t> request;
|
||||
String8 defaultUrl;
|
||||
|
||||
status_t err = drm->getProvisionRequest(request, defaultUrl);
|
||||
String8 certType;
|
||||
if (jcertType == gCertificateTypes.kCertificateTypeX509) {
|
||||
certType = "X.509";
|
||||
} else if (jcertType == gCertificateTypes.kCertificateTypeNone) {
|
||||
certType = "none";
|
||||
} else {
|
||||
certType = "invalid";
|
||||
}
|
||||
|
||||
String8 certAuthority = JStringToString8(env, jcertAuthority);
|
||||
status_t err = drm->getProvisionRequest(certType, certAuthority, request, defaultUrl);
|
||||
|
||||
if (throwExceptionAsNecessary(env, err, "Failed to get provision request")) {
|
||||
return NULL;
|
||||
@@ -863,27 +904,43 @@ static jobject android_media_MediaDrm_getProvisionRequest(
|
||||
return provisionObj;
|
||||
}
|
||||
|
||||
static void android_media_MediaDrm_provideProvisionResponse(
|
||||
static jobject android_media_MediaDrm_provideProvisionResponseNative(
|
||||
JNIEnv *env, jobject thiz, jbyteArray jresponse) {
|
||||
sp<IDrm> drm = GetDrm(env, thiz);
|
||||
|
||||
if (drm == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException",
|
||||
"MediaDrm obj is null");
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (jresponse == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException",
|
||||
"provision response is null");
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
|
||||
Vector<uint8_t> certificate, wrappedKey;
|
||||
|
||||
status_t err = drm->provideProvisionResponse(response);
|
||||
status_t err = drm->provideProvisionResponse(response, certificate, wrappedKey);
|
||||
|
||||
// Fill out return obj
|
||||
jclass clazz = gFields.certificateClassId;
|
||||
|
||||
jobject certificateObj = NULL;
|
||||
|
||||
if (clazz && certificate.size() && wrappedKey.size()) {
|
||||
certificateObj = env->AllocObject(clazz);
|
||||
jbyteArray jcertificate = VectorToJByteArray(env, certificate);
|
||||
env->SetObjectField(certificateObj, gFields.certificate.certificateData, jcertificate);
|
||||
|
||||
jbyteArray jwrappedKey = VectorToJByteArray(env, wrappedKey);
|
||||
env->SetObjectField(certificateObj, gFields.certificate.wrappedPrivateKey, jwrappedKey);
|
||||
}
|
||||
|
||||
throwExceptionAsNecessary(env, err, "Failed to handle provision response");
|
||||
return certificateObj;
|
||||
}
|
||||
|
||||
static jobject android_media_MediaDrm_getSecureStops(
|
||||
@@ -1209,6 +1266,38 @@ static jboolean android_media_MediaDrm_verifyNative(
|
||||
}
|
||||
|
||||
|
||||
static jbyteArray android_media_MediaDrm_signRSANative(
|
||||
JNIEnv *env, jobject thiz, jobject jdrm, jbyteArray jsessionId,
|
||||
jstring jalgorithm, jbyteArray jwrappedKey, jbyteArray jmessage) {
|
||||
|
||||
sp<IDrm> drm = GetDrm(env, jdrm);
|
||||
|
||||
if (!CheckSession(env, drm, jsessionId)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (jalgorithm == NULL || jwrappedKey == NULL || jmessage == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException",
|
||||
"required argument is null");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
|
||||
String8 algorithm = JStringToString8(env, jalgorithm);
|
||||
Vector<uint8_t> wrappedKey(JByteArrayToVector(env, jwrappedKey));
|
||||
Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
|
||||
Vector<uint8_t> signature;
|
||||
|
||||
status_t err = drm->signRSA(sessionId, algorithm, message, wrappedKey, signature);
|
||||
|
||||
if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return VectorToJByteArray(env, signature);
|
||||
}
|
||||
|
||||
|
||||
static JNINativeMethod gMethods[] = {
|
||||
{ "release", "()V", (void *)android_media_MediaDrm_release },
|
||||
{ "native_init", "()V", (void *)android_media_MediaDrm_native_init },
|
||||
@@ -1244,11 +1333,11 @@ static JNINativeMethod gMethods[] = {
|
||||
{ "queryKeyStatus", "([B)Ljava/util/HashMap;",
|
||||
(void *)android_media_MediaDrm_queryKeyStatus },
|
||||
|
||||
{ "getProvisionRequest", "()Landroid/media/MediaDrm$ProvisionRequest;",
|
||||
(void *)android_media_MediaDrm_getProvisionRequest },
|
||||
{ "getProvisionRequestNative", "(ILjava/lang/String;)Landroid/media/MediaDrm$ProvisionRequest;",
|
||||
(void *)android_media_MediaDrm_getProvisionRequestNative },
|
||||
|
||||
{ "provideProvisionResponse", "([B)V",
|
||||
(void *)android_media_MediaDrm_provideProvisionResponse },
|
||||
{ "provideProvisionResponseNative", "([B)Landroid/media/MediaDrm$Certificate;",
|
||||
(void *)android_media_MediaDrm_provideProvisionResponseNative },
|
||||
|
||||
{ "getSecureStops", "()Ljava/util/List;",
|
||||
(void *)android_media_MediaDrm_getSecureStops },
|
||||
@@ -1287,6 +1376,9 @@ static JNINativeMethod gMethods[] = {
|
||||
|
||||
{ "verifyNative", "(Landroid/media/MediaDrm;[B[B[B[B)Z",
|
||||
(void *)android_media_MediaDrm_verifyNative },
|
||||
|
||||
{ "signRSANative", "(Landroid/media/MediaDrm;[BLjava/lang/String;[B[B)[B",
|
||||
(void *)android_media_MediaDrm_signRSANative },
|
||||
};
|
||||
|
||||
int register_android_media_Drm(JNIEnv *env) {
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
# the library
|
||||
# the remotedisplay library
|
||||
# ============================================================
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
@@ -23,7 +23,7 @@ LOCAL_MODULE:= com.android.media.remotedisplay
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
$(call all-subdir-java-files) \
|
||||
$(call all-java-files-under, java) \
|
||||
$(call all-aidl-files-under, java)
|
||||
|
||||
include $(BUILD_JAVA_LIBRARY)
|
||||
@@ -25,4 +25,3 @@ with the framework in a new API. That API isn't ready yet so this
|
||||
library is a compromise to make new capabilities available to the system
|
||||
without exposing the full surface area of the support library media
|
||||
route provider protocol.
|
||||
|
||||
45
media/lib/signer/Android.mk
Normal file
45
media/lib/signer/Android.mk
Normal file
@@ -0,0 +1,45 @@
|
||||
#
|
||||
# Copyright (C) 2013 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
# the mediadrm signer library
|
||||
# ============================================================
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE:= com.android.mediadrm.signer
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
$(call all-java-files-under, java)
|
||||
|
||||
include $(BUILD_STATIC_JAVA_LIBRARY)
|
||||
|
||||
|
||||
# ==== com.android.mediadrm.signer.xml lib def ========================
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := com.android.mediadrm.signer.xml
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
LOCAL_MODULE_CLASS := ETC
|
||||
|
||||
# This will install the file in /system/etc/permissions
|
||||
#
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions
|
||||
|
||||
LOCAL_SRC_FILES := $(LOCAL_MODULE)
|
||||
|
||||
include $(BUILD_PREBUILT)
|
||||
28
media/lib/signer/README.txt
Normal file
28
media/lib/signer/README.txt
Normal file
@@ -0,0 +1,28 @@
|
||||
This library (com.android.mediadrm.signer.jar) is a shared java library
|
||||
containing classes required by unbundled apps running on devices that use
|
||||
the certficate provisioning and private key signing capabilities provided
|
||||
by the MediaDrm API.
|
||||
|
||||
--- Rules of this library ---
|
||||
o This library is effectively a PUBLIC API for unbundled CAST receivers
|
||||
that may be distributed outside the system image. So it MUST BE API STABLE.
|
||||
You can add but not remove. The rules are the same as for the
|
||||
public platform SDK API.
|
||||
o This library can see and instantiate internal platform classes, but it must not
|
||||
expose them in any public method (or by extending them via inheritance). This would
|
||||
break clients of the library because they cannot see the internal platform classes.
|
||||
|
||||
This library is distributed in the system image, and loaded as
|
||||
a shared library. So you can change the implementation, but not
|
||||
the interface. In this way it is like framework.jar.
|
||||
|
||||
--- Why does this library exist? ---
|
||||
|
||||
Unbundled apps cannot use internal platform classes.
|
||||
|
||||
This library will eventually be replaced when the provisioned certificate-
|
||||
based signing infrastructure that is currently defined in the support library
|
||||
is reintegrated with the framework in a new API. That API isn't ready yet so
|
||||
this library is a compromise to make new capabilities available to the system
|
||||
without exposing the full surface area of the support library.
|
||||
|
||||
20
media/lib/signer/com.android.mediadrm.signer.xml
Normal file
20
media/lib/signer/com.android.mediadrm.signer.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<permissions>
|
||||
<library name="com.android.media.drm.signer"
|
||||
file="/system/framework/com.android.media.drm.signer.jar" />
|
||||
</permissions>
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.mediadrm.signer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.MediaDrm;
|
||||
import android.media.DeniedByServerException;
|
||||
|
||||
/**
|
||||
* Provides certificate request generation, response handling and
|
||||
* signing APIs
|
||||
*/
|
||||
public final class MediaDrmSigner {
|
||||
private MediaDrmSigner() {}
|
||||
|
||||
/**
|
||||
* Specify X.509 certificate type
|
||||
*/
|
||||
public static final int CERTIFICATE_TYPE_X509 = MediaDrm.CERTIFICATE_TYPE_X509;
|
||||
|
||||
/**
|
||||
* Contains the opaque data an app uses to request a certificate from a provisioning
|
||||
* server
|
||||
*/
|
||||
public final static class CertificateRequest {
|
||||
private MediaDrm.CertificateRequest mCertRequest;
|
||||
|
||||
CertificateRequest(MediaDrm.CertificateRequest certRequest) {
|
||||
mCertRequest = certRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the opaque message data
|
||||
*/
|
||||
public byte[] getData() {
|
||||
return mCertRequest.getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default URL to use when sending the certificate request
|
||||
* message to a server, if known. The app may prefer to use a different
|
||||
* certificate server URL obtained from other sources.
|
||||
*/
|
||||
public String getDefaultUrl() {
|
||||
return mCertRequest.getDefaultUrl();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains the wrapped private key and public certificate data associated
|
||||
* with a certificate.
|
||||
*/
|
||||
public final static class Certificate {
|
||||
private MediaDrm.Certificate mCertificate;
|
||||
|
||||
Certificate(MediaDrm.Certificate certificate) {
|
||||
mCertificate = certificate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the wrapped private key data
|
||||
*/
|
||||
public byte[] getWrappedPrivateKey() {
|
||||
return mCertificate.getWrappedPrivateKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PEM-encoded public certificate chain
|
||||
*/
|
||||
public byte[] getContent() {
|
||||
return mCertificate.getContent();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a certificate request, specifying the certificate type
|
||||
* and authority. The response received should be passed to
|
||||
* provideCertificateResponse.
|
||||
*
|
||||
* @param drm the MediaDrm object
|
||||
* @param certType Specifies the certificate type.
|
||||
* @param certAuthority is passed to the certificate server to specify
|
||||
* the chain of authority.
|
||||
*/
|
||||
public static CertificateRequest getCertificateRequest(MediaDrm drm, int certType,
|
||||
String certAuthority) {
|
||||
return new CertificateRequest(drm.getCertificateRequest(certType, certAuthority));
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a response from the provisioning server. The response
|
||||
* is obtained from an HTTP Post to the url provided by getCertificateRequest.
|
||||
*
|
||||
* The public X509 certificate chain and wrapped private key are returned
|
||||
* in the returned Certificate objec. The certificate chain is in BIO serialized
|
||||
* PEM format. The wrapped private key should be stored in application private
|
||||
* storage, and used when invoking the signRSA method.
|
||||
*
|
||||
* @param drm the MediaDrm object
|
||||
* @param response the opaque certificate response byte array to provide to the
|
||||
* DRM engine plugin.
|
||||
* @throws android.media.DeniedByServerException if the response indicates that the
|
||||
* server rejected the request
|
||||
*/
|
||||
public static Certificate provideCertificateResponse(MediaDrm drm, byte[] response)
|
||||
throws DeniedByServerException {
|
||||
return new Certificate(drm.provideCertificateResponse(response));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign data using an RSA key
|
||||
*
|
||||
* @param context the App context
|
||||
* @param drm the MediaDrm object
|
||||
* @param sessionId a sessionId obtained from openSession on the MediaDrm object
|
||||
* @param algorithm the signing algorithm to use, e.g. "PKCS1-BlockType1"
|
||||
* @param wrappedKey - the wrapped (encrypted) RSA private key obtained
|
||||
* from provideCertificateResponse
|
||||
* @param message the data for which a signature is to be computed
|
||||
*/
|
||||
public static byte[] signRSA(Context context, MediaDrm drm, byte[] sessionId,
|
||||
String algorithm, byte[] wrappedKey, byte[] message) {
|
||||
return drm.signRSA(context, sessionId, algorithm, wrappedKey, message);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user