Merge "Report app signing cert digest in license requests" into sc-dev

This commit is contained in:
Robert Shih
2021-02-18 21:07:09 +00:00
committed by Android (Google) Code Review
2 changed files with 79 additions and 4 deletions

View File

@@ -23,7 +23,11 @@ import android.annotation.Nullable;
import android.annotation.StringDef;
import android.annotation.TestApi;
import android.app.ActivityThread;
import android.app.Application;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.media.metrics.PlaybackComponent;
import android.os.Handler;
import android.os.HandlerExecutor;
@@ -39,7 +43,10 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
import java.time.Instant;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
@@ -144,6 +151,7 @@ public final class MediaDrm implements AutoCloseable {
private static final String PERMISSION = android.Manifest.permission.ACCESS_DRM_CERTIFICATES;
private long mNativeContext;
private final String mAppPackageName;
/**
* Specify no certificate type
@@ -281,8 +289,9 @@ public final class MediaDrm implements AutoCloseable {
/* Native setup requires a weak reference to our object.
* It's easier to create it here than in C++.
*/
mAppPackageName = ActivityThread.currentOpPackageName();
native_setup(new WeakReference<MediaDrm>(this),
getByteArrayFromUUID(uuid), ActivityThread.currentOpPackageName());
getByteArrayFromUUID(uuid), mAppPackageName);
mCloseGuard.open("release");
}
@@ -1144,13 +1153,79 @@ public final class MediaDrm implements AutoCloseable {
* problem with the certifcate
*/
@NonNull
public native KeyRequest getKeyRequest(
public KeyRequest getKeyRequest(
@NonNull byte[] scope, @Nullable byte[] init,
@Nullable String mimeType, @KeyType int keyType,
@Nullable HashMap<String, String> optionalParameters)
throws NotProvisionedException {
HashMap<String, String> internalParams;
if (optionalParameters == null) {
internalParams = new HashMap<>();
} else {
internalParams = new HashMap<>(optionalParameters);
}
byte[] rawBytes = getNewestAvailablePackageCertificateRawBytes();
byte[] hashBytes = null;
if (rawBytes != null) {
hashBytes = getDigestBytes(rawBytes, "SHA-256");
}
if (hashBytes != null) {
Base64.Encoder encoderB64 = Base64.getEncoder();
String hashBytesB64 = encoderB64.encodeToString(hashBytes);
internalParams.put("package_certificate_hash_bytes", hashBytesB64);
}
return getKeyRequestNative(scope, init, mimeType, keyType, internalParams);
}
@Nullable
private byte[] getNewestAvailablePackageCertificateRawBytes() {
Application application = ActivityThread.currentApplication();
if (application == null) {
Log.w(TAG, "pkg cert: Application is null");
return null;
}
PackageManager pm = application.getPackageManager();
if (pm == null) {
Log.w(TAG, "pkg cert: PackageManager is null");
return null;
}
PackageInfo packageInfo = null;
try {
packageInfo = pm.getPackageInfo(mAppPackageName,
PackageManager.GET_SIGNING_CERTIFICATES);
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, mAppPackageName, e);
}
if (packageInfo == null || packageInfo.signingInfo == null) {
Log.w(TAG, "pkg cert: PackageInfo or SigningInfo is null");
return null;
}
Signature[] signers = packageInfo.signingInfo.getApkContentsSigners();
if (signers != null && signers.length == 1) {
return signers[0].toByteArray();
}
Log.w(TAG, "pkg cert: " + signers.length + " signers");
return null;
}
@Nullable
private static byte[] getDigestBytes(@NonNull byte[] rawBytes, @NonNull String algorithm) {
try {
MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
return messageDigest.digest(rawBytes);
} catch (NoSuchAlgorithmException e) {
Log.w(TAG, algorithm, e);
}
return null;
}
@NonNull
private native KeyRequest getKeyRequestNative(
@NonNull byte[] scope, @Nullable byte[] init,
@Nullable String mimeType, @KeyType int keyType,
@Nullable HashMap<String, String> optionalParameters)
throws NotProvisionedException;
/**
* A key response is received from the license server by the app, then it is
* provided to the MediaDrm instance using provideKeyResponse. When the

View File

@@ -2056,7 +2056,7 @@ static const JNINativeMethod gMethods[] = {
{ "closeSessionNative", "([B)V",
(void *)android_media_MediaDrm_closeSession },
{ "getKeyRequest", "([B[BLjava/lang/String;ILjava/util/HashMap;)"
{ "getKeyRequestNative", "([B[BLjava/lang/String;ILjava/util/HashMap;)"
"Landroid/media/MediaDrm$KeyRequest;",
(void *)android_media_MediaDrm_getKeyRequest },