diff --git a/tools/bin/published_devices_client/published_devices_cli_deploy.jar b/tools/bin/published_devices_client/published_devices_cli_deploy.jar
old mode 100755
new mode 100644
index 40936b0..ab0ddf4
Binary files a/tools/bin/published_devices_client/published_devices_cli_deploy.jar and b/tools/bin/published_devices_client/published_devices_cli_deploy.jar differ
diff --git a/tools/bin/published_devices_delta/published_devices_delta_deploy.jar b/tools/bin/published_devices_delta/published_devices_delta_deploy.jar
old mode 100755
new mode 100644
index cc18dd5..e59e6ec
Binary files a/tools/bin/published_devices_delta/published_devices_delta_deploy.jar and b/tools/bin/published_devices_delta/published_devices_delta_deploy.jar differ
diff --git a/tools/source/published_devices_client/WORKSPACE b/tools/source/published_devices_client/WORKSPACE
index c09fe7a..d6827ee 100644
--- a/tools/source/published_devices_client/WORKSPACE
+++ b/tools/source/published_devices_client/WORKSPACE
@@ -103,65 +103,29 @@ maven_install(
)
# GRPC
-git_repository(
+http_archive(
name = "io_grpc_grpc_java",
- remote = "https://github.com/grpc/grpc-java.git",
- tag = "v1.23.0",
+ strip_prefix = "grpc-java-1.36.0",
+ url = "https://github.com/grpc/grpc-java/archive/v1.36.0.zip",
)
-# GRPC Core
+load("@io_grpc_grpc_java//:repositories.bzl", "IO_GRPC_GRPC_JAVA_ARTIFACTS")
+load("@io_grpc_grpc_java//:repositories.bzl", "IO_GRPC_GRPC_JAVA_OVERRIDE_TARGETS")
+
maven_install(
- name = "grpc_core",
- artifacts = ["io.grpc:grpc-core:1.23.0"],
+ artifacts = IO_GRPC_GRPC_JAVA_ARTIFACTS,
+ generate_compat_repositories = True,
+ override_targets = IO_GRPC_GRPC_JAVA_OVERRIDE_TARGETS,
repositories = [
- "https://jcenter.bintray.com",
- "https://maven.google.com",
- "https://repo1.maven.org/maven2",
+ "https://repo.maven.apache.org/maven2/",
],
)
-# GRPC Netty
-maven_install(
- name = "grpc_netty",
- artifacts = ["io.grpc:grpc-netty:1.23.0"],
- repositories = [
- "https://jcenter.bintray.com",
- "https://maven.google.com",
- "https://repo1.maven.org/maven2",
- ],
-)
+load("@maven//:compat.bzl", "compat_repositories")
+compat_repositories()
-maven_install(
- name = "grpc_netty_all",
- artifacts = ["io.netty:netty-all:4.1.41.Final"],
- repositories = [
- "https://jcenter.bintray.com",
- "https://maven.google.com",
- "https://repo1.maven.org/maven2",
- ],
-)
-
-# GRPC Stub
-maven_install(
- name = "grpc_stub",
- artifacts = ["io.grpc:grpc-stub:1.23.0"],
- repositories = [
- "https://jcenter.bintray.com",
- "https://maven.google.com",
- "https://repo1.maven.org/maven2",
- ],
-)
-
-# GRPC Contenxt
-maven_install(
- name = "grpc_context",
- artifacts = ["io.grpc:grpc-context:1.18.0"],
- repositories = [
- "https://jcenter.bintray.com",
- "https://maven.google.com",
- "https://repo1.maven.org/maven2",
- ],
-)
+load("@io_grpc_grpc_java//:repositories.bzl", "grpc_java_repositories")
+grpc_java_repositories()
# GSON
maven_install(
@@ -174,80 +138,6 @@ maven_install(
],
)
-# Netty TcNative (for GRPC)
-maven_install(
- name = "netty_tcnative",
- artifacts = ["io.netty:netty-tcnative:2.0.25.Final"],
- repositories = [
- "https://jcenter.bintray.com",
- "https://maven.google.com",
- "https://repo1.maven.org/maven2",
- ],
-)
-
-# Netty BoringSSL
-maven_install(
- name = "netty_boringssl",
- artifacts = ["io.netty:netty-tcnative-boringssl-static:2.0.25.Final"],
- repositories = [
- "https://jcenter.bintray.com",
- "https://maven.google.com",
- "https://repo1.maven.org/maven2",
- ],
-)
-
-# Open Census (for GRPC)
-maven_install(
- name = "open_census_api",
- artifacts = ["io.opencensus:opencensus-api:0.24.0"],
- repositories = [
- "https://jcenter.bintray.com",
- "https://maven.google.com",
- "https://repo1.maven.org/maven2",
- ],
-)
-
-maven_install(
- name = "open_census",
- artifacts = ["io.opencensus:opencensus-contrib-http-jetty-client:0.19.0"],
- repositories = [
- "https://jcenter.bintray.com",
- "https://maven.google.com",
- "https://repo1.maven.org/maven2",
- ],
-)
-
-maven_install(
- name = "open_census_util",
- artifacts = ["io.opencensus:opencensus-contrib-http-util:0.19.0"],
- repositories = [
- "https://jcenter.bintray.com",
- "https://maven.google.com",
- "https://repo1.maven.org/maven2",
- ],
-)
-
-maven_install(
- name = "open_census_grpc_metrics",
- artifacts = ["io.opencensus:opencensus-contrib-grpc-metrics:0.24.0"],
- repositories = [
- "https://jcenter.bintray.com",
- "https://maven.google.com",
- "https://repo1.maven.org/maven2",
- ],
-)
-
-# Perfmark (GRPC)
-maven_install(
- name = "io_perfmark_api",
- artifacts = ["io.perfmark:perfmark-api:0.17.0"],
- repositories = [
- "https://jcenter.bintray.com",
- "https://maven.google.com",
- "https://repo1.maven.org/maven2",
- ],
-)
-
# Google Protobuf Protos
PROTOBUF_BUILD_FILE = """
package(default_visibility = ["//visibility:public"])
@@ -361,9 +251,5 @@ bind(
actual = "@com_google_protobuf//:protobuf_java",
)
-# Loads necessary bazel rules for later consumption.
-load("@io_grpc_grpc_java//:repositories.bzl", "grpc_java_repositories")
-grpc_java_repositories()
-
load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
protobuf_deps()
diff --git a/tools/source/published_devices_client/google/chrome/widevine/contentpartners/v1beta1/BUILD b/tools/source/published_devices_client/google/chrome/widevine/contentpartners/v1beta1/BUILD
index 4175520..b7c2d55 100644
--- a/tools/source/published_devices_client/google/chrome/widevine/contentpartners/v1beta1/BUILD
+++ b/tools/source/published_devices_client/google/chrome/widevine/contentpartners/v1beta1/BUILD
@@ -28,7 +28,6 @@ proto_library(
java_proto_library(
name = "published_devices_java_proto",
deps = [":published_devices_proto"],
-
)
java_grpc_library(
@@ -38,3 +37,8 @@ java_grpc_library(
":published_devices_java_proto",
],
)
+
+java_proto_library(
+ name = "device_security_profiles_java_proto",
+ deps = [":device_security_profiles_proto"],
+)
diff --git a/tools/source/published_devices_client/google/chrome/widevine/contentpartners/v1beta1/device_security_profiles.proto b/tools/source/published_devices_client/google/chrome/widevine/contentpartners/v1beta1/device_security_profiles.proto
index 83abdc2..afe2a9d 100644
--- a/tools/source/published_devices_client/google/chrome/widevine/contentpartners/v1beta1/device_security_profiles.proto
+++ b/tools/source/published_devices_client/google/chrome/widevine/contentpartners/v1beta1/device_security_profiles.proto
@@ -91,4 +91,6 @@ enum HashAlgorithm {
HASH_ALGORITHM_SHA_1 = 1;
// Secure Hash Algorithm 2 256 bits (SHA-256).
HASH_ALGORITHM_SHA_256 = 2;
+ // Secure Hash Algorithm 2 384 bits (SHA-384).
+ HASH_ALGORITHM_SHA_384 = 3;
}
diff --git a/tools/source/published_devices_client/google/chrome/widevine/contentpartners/v1beta1/published_devices.proto b/tools/source/published_devices_client/google/chrome/widevine/contentpartners/v1beta1/published_devices.proto
old mode 100755
new mode 100644
diff --git a/tools/source/published_devices_client/interfaces/BUILD b/tools/source/published_devices_client/interfaces/BUILD
index 4735f66..c75c5e0 100644
--- a/tools/source/published_devices_client/interfaces/BUILD
+++ b/tools/source/published_devices_client/interfaces/BUILD
@@ -10,6 +10,7 @@ java_library(
name = "interfaces",
srcs = glob(["*.java"]),
deps = [
+ "//google/chrome/widevine/contentpartners/v1beta1:device_security_profiles_java_proto",
"//google/chrome/widevine/contentpartners/v1beta1:published_devices_java_proto",
"@com_google_protobuf//:protobuf_java",
"@apache_httpcore//:org_apache_httpcomponents_httpcore",
diff --git a/tools/source/published_devices_client/interfaces/DeviceSecurityProfile.java b/tools/source/published_devices_client/interfaces/DeviceSecurityProfile.java
new file mode 100644
index 0000000..624a17e
--- /dev/null
+++ b/tools/source/published_devices_client/interfaces/DeviceSecurityProfile.java
@@ -0,0 +1,16 @@
+// Copyright 2020 Google LLC. All rights reserved.
+package com.google.video.widevine.jts.interfaces;
+
+import com.google.chrome.widevine.contentpartners.v1beta1.SignedDeviceSecurityProfiles;
+
+/** DeviceSecurityProfile defines APIs for getting Signed Device Security Profile list. */
+public interface DeviceSecurityProfile {
+
+ /**
+ * Get the latest {@code SignedDeviceSecurityProfiles} containing Device Security Profile list
+ * data.
+ *
+ * @return {@code SignedDeviceSecurityProfiles} containing Device Security Profile list data.
+ */
+ public SignedDeviceSecurityProfiles getSignedDeviceSecurityProfiles() throws Exception;
+}
diff --git a/tools/source/published_devices_client/providers/BUILD b/tools/source/published_devices_client/providers/BUILD
index 506b639..be099ba 100644
--- a/tools/source/published_devices_client/providers/BUILD
+++ b/tools/source/published_devices_client/providers/BUILD
@@ -9,29 +9,24 @@ package(
java_library(
name = "providers",
srcs = glob(["*.java"]),
- runtime_deps = [
- "@grpc_context//:io_grpc_grpc_context",
- "@grpc_netty_all//:io_netty_netty_all",
- "@io_perfmark_api//:io_perfmark_perfmark_api",
- "@netty_boringssl//:io_netty_netty_tcnative_boringssl_static",
- "@open_census//:io_opencensus_opencensus_contrib_http_jetty_client",
- "@open_census_api//:io_opencensus_opencensus_api",
- "@open_census_grpc_metrics//:io_opencensus_opencensus_contrib_grpc_metrics",
- "@open_census_util//:io_opencensus_opencensus_contrib_http_util",
- ],
deps = [
":libwvpl_cas_proxy_sdk_lib.jar",
+ "//google/chrome/widevine/contentpartners/v1beta1:device_security_profiles_java_proto",
"//google/chrome/widevine/contentpartners/v1beta1:published_devices_grpc",
"//google/chrome/widevine/contentpartners/v1beta1:published_devices_java_proto",
"//httpclient",
"//interfaces",
"@google_guice//:com_google_inject_guice",
"@json//:org_json_json",
+ "@jsr305_annotations//:com_google_code_findbugs_jsr305",
"@com_google_protobuf//:protobuf_java",
"@google_guava//:com_google_guava_guava",
- "@grpc_core//:io_grpc_grpc_core",
- "@grpc_netty//:io_grpc_grpc_netty",
- "@grpc_stub//:io_grpc_grpc_stub",
"@io_grpc_grpc_java//api",
+ "@io_grpc_grpc_java//netty",
+ "@io_grpc_grpc_java//protobuf",
+ "@io_grpc_grpc_java//stub",
+ "@maven//:com_google_api_grpc_proto_google_common_protos",
+ "@maven//:com_google_code_findbugs_jsr305",
+ "@maven//:com_google_code_gson_gson",
],
)
diff --git a/tools/source/published_devices_client/providers/PublishedDevicesProvider.java b/tools/source/published_devices_client/providers/PublishedDevicesProvider.java
index ff5733d..7018325 100644
--- a/tools/source/published_devices_client/providers/PublishedDevicesProvider.java
+++ b/tools/source/published_devices_client/providers/PublishedDevicesProvider.java
@@ -2,13 +2,18 @@
package com.google.video.widevine.jts.providers;
+import com.google.chrome.widevine.contentpartners.v1beta1.DeviceSecurityProfileCriteria;
+import com.google.chrome.widevine.contentpartners.v1beta1.ListDeviceSecurityProfilesRequest;
import com.google.chrome.widevine.contentpartners.v1beta1.PublishedDevices;
import com.google.chrome.widevine.contentpartners.v1beta1.PublishedDevicesRequest;
import com.google.chrome.widevine.contentpartners.v1beta1.PublishedDevicesServiceGrpc;
+import com.google.chrome.widevine.contentpartners.v1beta1.SignedDeviceSecurityProfiles;
import com.google.inject.Inject;
+import com.google.protobuf.ExtensionRegistry;
import com.google.protobuf.TextFormat;
import com.google.video.widevine.jts.httpclient.Credentials;
import com.google.video.widevine.jts.interfaces.DeviceCertificate;
+import com.google.video.widevine.jts.interfaces.DeviceSecurityProfile;
import com.google.video.widevine.sdk.wvpl.WvPLBaseEnvironment;
import com.google.video.widevine.sdk.wvpl.WvPLStatusException;
import io.grpc.ManagedChannel;
@@ -19,18 +24,22 @@ import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.annotation.Nullable;
/**
- * Provides the latest {@code PublishedDevices} data from the Widevine Published Devices Service.
+ * Provides the latest {@code PublishedDevices} or {@code SignedDeviceSecurityProfiles} data from
+ * the Widevine Published Devices Service.
*
- * This implementation uses the Widevine Published Devices API, and support a gRPC method for
- * retrieving PublishedDevices with an embedded Published Devices list.
+ *
This implementation uses the Widevine Published Devices API, and support a gRPC method for
+ * retrieving PublishedDevices with an embedded Published Devices list, or Device Security Profiles
+ * list.
*/
-public class PublishedDevicesProvider implements DeviceCertificate {
+public class PublishedDevicesProvider implements DeviceCertificate, DeviceSecurityProfile {
private static final Logger logger = Logger.getLogger(PublishedDevicesProvider.class.getName());
private WvPLBaseEnvironment> environment = null;
private String apiServicePath = null;
private Credentials credentials = null;
+ private String provider = null;
/**
* PublishedDevicesProvider constructor.
@@ -38,15 +47,21 @@ public class PublishedDevicesProvider implements DeviceCertificate {
* @param environment A WvPLBaseEnvironment object initialized with a Service Certificate.
* @param serviceAccountPath Path to a GCP Service Account json file, used in OAUTH.
* @param apiServicePath Path to a Widevine Published Devices API service.
+ * @param provider Provider name, necessary for creating ListDSP request. It could be null if it
+ * is not used by dsps.
* @throws IOException upon failure creating OAUTH credentials.
*/
@Inject
public PublishedDevicesProvider(
- WvPLBaseEnvironment> environment, String serviceAccountPath, String apiServicePath)
+ WvPLBaseEnvironment> environment,
+ String serviceAccountPath,
+ String apiServicePath,
+ @Nullable String provider)
throws IOException {
this.environment = environment;
this.apiServicePath = apiServicePath;
credentials = new Credentials(serviceAccountPath);
+ this.provider = provider;
}
/**
@@ -57,7 +72,7 @@ public class PublishedDevicesProvider implements DeviceCertificate {
* @throws WvPLStatusException upon WvPLBaseEnvironment errors.
*/
@Override
- public PublishedDevices getPublishedDevices() throws InterruptedException, WvPLStatusException{
+ public PublishedDevices getPublishedDevices() throws InterruptedException, WvPLStatusException {
ManagedChannel channel = null;
PublishedDevices devicesResponse = null;
@@ -70,10 +85,20 @@ public class PublishedDevicesProvider implements DeviceCertificate {
PublishedDevicesServiceGrpc.PublishedDevicesServiceBlockingStub blockingStub =
PublishedDevicesServiceGrpc.newBlockingStub(channel)
.withInterceptors(MetadataUtils.newAttachHeadersInterceptor(metadata));
- devicesResponse = blockingStub.getPublishedDevices(PublishedDevicesRequest.parseFrom(
- environment.generateDeviceStatusListRequest()));
- logger.log(Level.INFO, "GRPC Call to PublishedDevicesService.GetSignedList returned:\n %s"
- + TextFormat.printer().printToString(devicesResponse));
+ devicesResponse =
+ blockingStub.getPublishedDevices(
+ PublishedDevicesRequest.parseFrom(
+ environment.generateDeviceStatusListRequest(),
+ ExtensionRegistry.getEmptyRegistry()));
+ String truncatedLogString = TextFormat.printer().printToString(devicesResponse);
+ int tenLines = 800;
+ if (truncatedLogString.length() > tenLines) {
+ truncatedLogString = truncatedLogString.substring(0, tenLines) + "...";
+ }
+ logger.log(
+ Level.INFO,
+ "GRPC Call to PublishedDevicesService.GetPublishedDevices returned:\n %s"
+ + truncatedLogString);
} catch (IOException e) {
logger.log(Level.INFO, "IOException encountered trying to retrieve the signed list: " + e);
} finally {
@@ -85,6 +110,50 @@ public class PublishedDevicesProvider implements DeviceCertificate {
return devicesResponse;
}
+ @Override
+ public SignedDeviceSecurityProfiles getSignedDeviceSecurityProfiles()
+ throws InterruptedException, WvPLStatusException {
+ // Generate list dsp request.
+ ListDeviceSecurityProfilesRequest listDspRequest =
+ ListDeviceSecurityProfilesRequest.newBuilder()
+ .setDeviceSecurityProfileCriteria(
+ DeviceSecurityProfileCriteria.newBuilder()
+ .setContentProvider(this.provider)
+ .build())
+ .build();
+
+ ManagedChannel channel = null;
+ SignedDeviceSecurityProfiles signedMessageInResponse = null;
+
+ logger.log(Level.INFO, "Getting DeviceSecurityProfilesList...");
+ try {
+ channel = createRpcChannel(apiServicePath);
+ Metadata metadata = new Metadata();
+ String token = "Bearer " + credentials.getAccessToken();
+ metadata.put(Metadata.Key.of("authorization", Metadata.ASCII_STRING_MARSHALLER), token);
+
+ PublishedDevicesServiceGrpc.PublishedDevicesServiceBlockingStub blockingStub =
+ PublishedDevicesServiceGrpc.newBlockingStub(channel)
+ .withInterceptors(MetadataUtils.newAttachHeadersInterceptor(metadata));
+
+ signedMessageInResponse =
+ blockingStub.listDeviceSecurityProfiles(listDspRequest).getSignedDeviceSecurityProfiles();
+ logger.log(
+ Level.INFO,
+ "GRPC Call to PublishedDevicesService.ListDeviceSecurityProfiles returned:\n %s"
+ + TextFormat.printer().printToString(signedMessageInResponse));
+ } catch (IOException e) {
+ logger.log(
+ Level.INFO, "IOException encountered trying to retrieve the signed dsp list: " + e);
+ } finally {
+ if (channel != null) {
+ channel.shutdown();
+ channel.awaitTermination(1, TimeUnit.SECONDS);
+ }
+ }
+ return signedMessageInResponse;
+ }
+
private static ManagedChannel createRpcChannel(String host) {
return NettyChannelBuilder.forTarget(host).build();
}
diff --git a/tools/source/published_devices_client/providers/libwvpl_cas_proxy_sdk_lib.jar b/tools/source/published_devices_client/providers/libwvpl_cas_proxy_sdk_lib.jar
new file mode 100644
index 0000000..e4c25d4
Binary files /dev/null and b/tools/source/published_devices_client/providers/libwvpl_cas_proxy_sdk_lib.jar differ
diff --git a/tools/source/published_devices_client/tools/BUILD b/tools/source/published_devices_client/tools/BUILD
index 4e9dccb..dbb35da 100644
--- a/tools/source/published_devices_client/tools/BUILD
+++ b/tools/source/published_devices_client/tools/BUILD
@@ -9,18 +9,8 @@ java_library(
srcs = [
"PublishedDevicesCli.java",
],
- runtime_deps = [
- "@grpc_context//:io_grpc_grpc_context",
- "@grpc_netty_all//:io_netty_netty_all",
- "@io_perfmark_api//:io_perfmark_perfmark_api",
- "@netty_boringssl//:io_netty_netty_tcnative_boringssl_static",
- "@netty_tcnative//:io_netty_netty_tcnative",
- "@open_census//:io_opencensus_opencensus_contrib_http_jetty_client",
- "@open_census_api//:io_opencensus_opencensus_api",
- "@open_census_grpc_metrics//:io_opencensus_opencensus_contrib_grpc_metrics",
- "@open_census_util//:io_opencensus_opencensus_contrib_http_util",
- ],
deps = [
+ "//google/chrome/widevine/contentpartners/v1beta1:device_security_profiles_java_proto",
"//google/chrome/widevine/contentpartners/v1beta1:published_devices_grpc",
"//google/chrome/widevine/contentpartners/v1beta1:published_devices_java_proto",
"//providers",
diff --git a/tools/source/published_devices_client/tools/PublishedDevicesCli.java b/tools/source/published_devices_client/tools/PublishedDevicesCli.java
index 92219fe..ccd72cd 100644
--- a/tools/source/published_devices_client/tools/PublishedDevicesCli.java
+++ b/tools/source/published_devices_client/tools/PublishedDevicesCli.java
@@ -7,6 +7,8 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import com.google.chrome.widevine.contentpartners.v1beta1.PublishedDevices;
+import com.google.chrome.widevine.contentpartners.v1beta1.SignedDeviceSecurityProfiles;
+import com.google.common.collect.ImmutableList;
import com.google.common.io.BaseEncoding;
import com.google.video.widevine.jts.providers.PublishedDevicesProvider;
import com.google.video.widevine.sdk.wvpl.WvPLCASProxyEnvironment;
@@ -18,25 +20,28 @@ import java.nio.file.Paths;
import java.util.HashMap;
/**
- * Published Devices Command Line Interface.
+ * Published Devices Client command line tool.
*
- * Provides a command line interface to get the latest {@code PublishedDevices} data from the
- * Widevine Published Devices Service.
+ *
Provides a command line interface to get the latest {@code PublishedDevices} and {@code
+ * SignedDeviceSecurityProfiles} data from the Widevine Published Devices Service.
*
- * Default Widevine Service API path: widevine.googleapis.com.
+ *
Default Widevine Service API path: widevine.googleapis.com.
*
- * To build:
- * Bazel build java/com/google/video/widevine/jts/tools:published_devices_client_deploy.jar
+ *
To build: bazel build
+ * java/com/google/video/widevine/jts/tools:published_devices_cli_deploy.jar
*
- * To run:
- * java -Djava.library.path=./path/to/license/sdk.so \
- * -jar /path/to/published_devices_client_deploy.jar \
- * -service_cert_path /path/to/cert_file.der \
- * -service_private_key_path /path/to/private_key.der \
- * -service_private_key_passphrase theprivatekeypassphrase
- * -service_account_path /path/to/service-account.json \
+ *
To run: java -Djava.library.path=./path/to/license/sdk.so \ -jar
+ * /path/to/published_devices_cli_deploy.jar \ -data_type PUBLISHED_DEVICESOrDSPInString \
+ * -service_cert_path /path/to/cert_file.der \ -service_private_key_path /path/to/private_key.der \
+ * -service_private_key_passphrase theprivatekeypassphrase \ -service_account_path
+ * /path/to/service-account.json \ -provider_name providerNameInString
*/
public final class PublishedDevicesCli {
+ private static final String PUBLISHED_DEVICES = "PUBLISHED_DEVICES";
+ private static final String DSP = "DSP";
+ private static final ImmutableList DATA_TYPE_LIST =
+ ImmutableList.of(PUBLISHED_DEVICES, DSP);
+
private WvPLCASProxyEnvironment environment = null;
private PublishedDevicesProvider publishedDevices = null;
private String serviceCertPath = null;
@@ -44,42 +49,68 @@ public final class PublishedDevicesCli {
private String privateKeyPassphrase = null;
/** Command Line Flags. */
- static class Flags{
- private Flags() {}
+ static class Flags {
+ private Flags() {}
- @Parameter(names = "-service_cert_path", description = "Path to service certificate")
- private String serviceCertPath = "";
+ @Parameter(
+ names = "-data_type",
+ description =
+ "Set retrieved data type. Must be \"PUBLISHED_DEVICES\" or \"DSP\". Default is"
+ + " \"PUBLISHED_DEVICES\".")
+ private String dataType = "PUBLISHED_DEVICES";
- @Parameter(names = "-service_private_key_path",
- description = "Path to private key file needed to decrypt service certificate")
- private String servicePrivateKeyPath = "";
+ @Parameter(names = "-service_cert_path", description = "Path to service certificate")
+ private String serviceCertPath = "";
- @Parameter(names = "-service_private_key_passphrase",
- description = "Passphrase needed to decrypt the private key")
- private String servicePrivateKeyPassphrase = "";
+ @Parameter(
+ names = "-service_private_key_path",
+ description = "Path to private key file needed to decrypt service certificate")
+ private String servicePrivateKeyPath = "";
- @Parameter(names = "-service_account_path",
- description = "Path to a GCP Service Account json file")
- private String serviceAccountPath = "";
+ @Parameter(
+ names = "-service_private_key_passphrase",
+ description = "Passphrase needed to decrypt the private key")
+ private String servicePrivateKeyPassphrase = "";
- @Parameter(names = "-api_service_path",
- description = "Optional. Path to a Widevine API service.")
- private String apiServicePath = "widevine.googleapis.com";
+ @Parameter(
+ names = "-service_account_path",
+ description = "Path to a GCP Service Account json file")
+ private String serviceAccountPath = "";
- @Parameter(names = "-s",
- description = "Save PublishedDevices file path.")
- private String saveFilePath = null;
+ @Parameter(
+ names = "-api_service_path",
+ description = "Optional. Path to a Widevine API service.")
+ private String apiServicePath = "widevine.googleapis.com";
+
+ @Parameter(
+ names = "-provider_name",
+ description =
+ "Set provider name. Must provide when obtaining DSPs. Optional for obtaining"
+ + " PUBLISHED_DEVICES.")
+ private String provider = "";
+
+ @Parameter(names = "-s", description = "Save retrieved file path.")
+ private String saveFilePath = null;
}
- public PublishedDevicesCli(String serviceCertPath, String privateKeyPath,
- String privateKeyPassphrase, String serviceAccountPath, String apiServicePath)
+ public PublishedDevicesCli(
+ String dataType,
+ String serviceCertPath,
+ String privateKeyPath,
+ String privateKeyPassphrase,
+ String serviceAccountPath,
+ String apiServicePath,
+ String provider)
throws Exception {
this.serviceCertPath = serviceCertPath;
this.privateKeyPath = privateKeyPath;
this.privateKeyPassphrase = privateKeyPassphrase;
- initializeWvplEnvironment();
- publishedDevices = new PublishedDevicesProvider(
- environment, serviceAccountPath, apiServicePath);
+ // Construct PublishedDevicesProvider to obtain PUBLISHED_DEVICES or DSPs.
+ if (dataType.equals(PUBLISHED_DEVICES)) {
+ initializeWvplEnvironment();
+ }
+ publishedDevices =
+ new PublishedDevicesProvider(environment, serviceAccountPath, apiServicePath, provider);
}
/**
@@ -94,30 +125,61 @@ public final class PublishedDevicesCli {
}
/**
- * Saves PublishedDevices proto data to a file.
+ * Get the latest {@code SignedDeviceSecurityProfiles} from the Widevine Published Devices
+ * Service.
+ *
+ * @return The latest SignedDeviceSecurityProfiles data.
+ */
+ public SignedDeviceSecurityProfiles getSignedDeviceSecurityProfiles()
+ throws InterruptedException, WvPLStatusException {
+ return publishedDevices.getSignedDeviceSecurityProfiles();
+ }
+
+ /**
+ * Saves byte array to a file.
*
* @param saveFilePath The path to the save file.
- * @param publishedDevices A PublishedDevices proto.
+ * @param byteArray a byte array transformed from proto.
*/
- public static void savePublishedDevicesDataToFile(String saveFilePath,
- PublishedDevices publishedDevices) throws IOException {
+ public static void saveByteArrayToFile(String saveFilePath, byte[] byteArray) throws IOException {
Files.write(
- Paths.get(saveFilePath),
- BaseEncoding.base64Url().encode(publishedDevices.toByteArray()).getBytes(UTF_8));
+ Paths.get(saveFilePath), BaseEncoding.base64Url().encode(byteArray).getBytes(UTF_8));
}
public static void main(String[] args) throws Exception {
Flags flags = new Flags();
new JCommander(flags, args);
- PublishedDevicesCli devices = new PublishedDevicesCli(
- flags.serviceCertPath,
- flags.servicePrivateKeyPath,
- flags.servicePrivateKeyPassphrase,
- flags.serviceAccountPath,
- flags.apiServicePath);
- PublishedDevices publishedDevices = devices.getPublishedDevices();
- if (flags.saveFilePath != null) {
- savePublishedDevicesDataToFile(flags.saveFilePath, publishedDevices);
+ // Check flags.
+ if (!DATA_TYPE_LIST.contains(flags.dataType)) {
+ System.out.println("Data type should be selected from:" + DATA_TYPE_LIST);
+ System.err.println("Error selecting data type. Exit");
+ System.exit(-1);
+ }
+ if (flags.dataType.equals(DSP) && flags.provider.isEmpty()) {
+ System.err.println("Failed to provide the provider name for obtaining DSP list. Exit");
+ System.exit(-1);
+ }
+
+ PublishedDevicesCli devices =
+ new PublishedDevicesCli(
+ flags.dataType,
+ flags.serviceCertPath,
+ flags.servicePrivateKeyPath,
+ flags.servicePrivateKeyPassphrase,
+ flags.serviceAccountPath,
+ flags.apiServicePath,
+ flags.provider);
+ if (flags.dataType.equals(PUBLISHED_DEVICES)) {
+ PublishedDevices publishedDevices = devices.getPublishedDevices();
+ if (flags.saveFilePath != null) {
+ saveByteArrayToFile(flags.saveFilePath, publishedDevices.toByteArray());
+ }
+ } else {
+ SignedDeviceSecurityProfiles signedDeviceSecurityProfiles =
+ devices.getSignedDeviceSecurityProfiles();
+ if (flags.saveFilePath != null) {
+ saveByteArrayToFile(flags.saveFilePath, signedDeviceSecurityProfiles.toByteArray());
+ }
}
}
diff --git a/tools/source/published_devices_delta/WORKSPACE b/tools/source/published_devices_delta/WORKSPACE
index c09fe7a..d6827ee 100644
--- a/tools/source/published_devices_delta/WORKSPACE
+++ b/tools/source/published_devices_delta/WORKSPACE
@@ -103,65 +103,29 @@ maven_install(
)
# GRPC
-git_repository(
+http_archive(
name = "io_grpc_grpc_java",
- remote = "https://github.com/grpc/grpc-java.git",
- tag = "v1.23.0",
+ strip_prefix = "grpc-java-1.36.0",
+ url = "https://github.com/grpc/grpc-java/archive/v1.36.0.zip",
)
-# GRPC Core
+load("@io_grpc_grpc_java//:repositories.bzl", "IO_GRPC_GRPC_JAVA_ARTIFACTS")
+load("@io_grpc_grpc_java//:repositories.bzl", "IO_GRPC_GRPC_JAVA_OVERRIDE_TARGETS")
+
maven_install(
- name = "grpc_core",
- artifacts = ["io.grpc:grpc-core:1.23.0"],
+ artifacts = IO_GRPC_GRPC_JAVA_ARTIFACTS,
+ generate_compat_repositories = True,
+ override_targets = IO_GRPC_GRPC_JAVA_OVERRIDE_TARGETS,
repositories = [
- "https://jcenter.bintray.com",
- "https://maven.google.com",
- "https://repo1.maven.org/maven2",
+ "https://repo.maven.apache.org/maven2/",
],
)
-# GRPC Netty
-maven_install(
- name = "grpc_netty",
- artifacts = ["io.grpc:grpc-netty:1.23.0"],
- repositories = [
- "https://jcenter.bintray.com",
- "https://maven.google.com",
- "https://repo1.maven.org/maven2",
- ],
-)
+load("@maven//:compat.bzl", "compat_repositories")
+compat_repositories()
-maven_install(
- name = "grpc_netty_all",
- artifacts = ["io.netty:netty-all:4.1.41.Final"],
- repositories = [
- "https://jcenter.bintray.com",
- "https://maven.google.com",
- "https://repo1.maven.org/maven2",
- ],
-)
-
-# GRPC Stub
-maven_install(
- name = "grpc_stub",
- artifacts = ["io.grpc:grpc-stub:1.23.0"],
- repositories = [
- "https://jcenter.bintray.com",
- "https://maven.google.com",
- "https://repo1.maven.org/maven2",
- ],
-)
-
-# GRPC Contenxt
-maven_install(
- name = "grpc_context",
- artifacts = ["io.grpc:grpc-context:1.18.0"],
- repositories = [
- "https://jcenter.bintray.com",
- "https://maven.google.com",
- "https://repo1.maven.org/maven2",
- ],
-)
+load("@io_grpc_grpc_java//:repositories.bzl", "grpc_java_repositories")
+grpc_java_repositories()
# GSON
maven_install(
@@ -174,80 +138,6 @@ maven_install(
],
)
-# Netty TcNative (for GRPC)
-maven_install(
- name = "netty_tcnative",
- artifacts = ["io.netty:netty-tcnative:2.0.25.Final"],
- repositories = [
- "https://jcenter.bintray.com",
- "https://maven.google.com",
- "https://repo1.maven.org/maven2",
- ],
-)
-
-# Netty BoringSSL
-maven_install(
- name = "netty_boringssl",
- artifacts = ["io.netty:netty-tcnative-boringssl-static:2.0.25.Final"],
- repositories = [
- "https://jcenter.bintray.com",
- "https://maven.google.com",
- "https://repo1.maven.org/maven2",
- ],
-)
-
-# Open Census (for GRPC)
-maven_install(
- name = "open_census_api",
- artifacts = ["io.opencensus:opencensus-api:0.24.0"],
- repositories = [
- "https://jcenter.bintray.com",
- "https://maven.google.com",
- "https://repo1.maven.org/maven2",
- ],
-)
-
-maven_install(
- name = "open_census",
- artifacts = ["io.opencensus:opencensus-contrib-http-jetty-client:0.19.0"],
- repositories = [
- "https://jcenter.bintray.com",
- "https://maven.google.com",
- "https://repo1.maven.org/maven2",
- ],
-)
-
-maven_install(
- name = "open_census_util",
- artifacts = ["io.opencensus:opencensus-contrib-http-util:0.19.0"],
- repositories = [
- "https://jcenter.bintray.com",
- "https://maven.google.com",
- "https://repo1.maven.org/maven2",
- ],
-)
-
-maven_install(
- name = "open_census_grpc_metrics",
- artifacts = ["io.opencensus:opencensus-contrib-grpc-metrics:0.24.0"],
- repositories = [
- "https://jcenter.bintray.com",
- "https://maven.google.com",
- "https://repo1.maven.org/maven2",
- ],
-)
-
-# Perfmark (GRPC)
-maven_install(
- name = "io_perfmark_api",
- artifacts = ["io.perfmark:perfmark-api:0.17.0"],
- repositories = [
- "https://jcenter.bintray.com",
- "https://maven.google.com",
- "https://repo1.maven.org/maven2",
- ],
-)
-
# Google Protobuf Protos
PROTOBUF_BUILD_FILE = """
package(default_visibility = ["//visibility:public"])
@@ -361,9 +251,5 @@ bind(
actual = "@com_google_protobuf//:protobuf_java",
)
-# Loads necessary bazel rules for later consumption.
-load("@io_grpc_grpc_java//:repositories.bzl", "grpc_java_repositories")
-grpc_java_repositories()
-
load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
protobuf_deps()
diff --git a/tools/source/published_devices_delta/google/chrome/widevine/contentpartners/v1beta1/BUILD b/tools/source/published_devices_delta/google/chrome/widevine/contentpartners/v1beta1/BUILD
index 4175520..b7c2d55 100644
--- a/tools/source/published_devices_delta/google/chrome/widevine/contentpartners/v1beta1/BUILD
+++ b/tools/source/published_devices_delta/google/chrome/widevine/contentpartners/v1beta1/BUILD
@@ -28,7 +28,6 @@ proto_library(
java_proto_library(
name = "published_devices_java_proto",
deps = [":published_devices_proto"],
-
)
java_grpc_library(
@@ -38,3 +37,8 @@ java_grpc_library(
":published_devices_java_proto",
],
)
+
+java_proto_library(
+ name = "device_security_profiles_java_proto",
+ deps = [":device_security_profiles_proto"],
+)
diff --git a/tools/source/published_devices_delta/google/chrome/widevine/contentpartners/v1beta1/device_security_profiles.proto b/tools/source/published_devices_delta/google/chrome/widevine/contentpartners/v1beta1/device_security_profiles.proto
index 83abdc2..afe2a9d 100644
--- a/tools/source/published_devices_delta/google/chrome/widevine/contentpartners/v1beta1/device_security_profiles.proto
+++ b/tools/source/published_devices_delta/google/chrome/widevine/contentpartners/v1beta1/device_security_profiles.proto
@@ -91,4 +91,6 @@ enum HashAlgorithm {
HASH_ALGORITHM_SHA_1 = 1;
// Secure Hash Algorithm 2 256 bits (SHA-256).
HASH_ALGORITHM_SHA_256 = 2;
+ // Secure Hash Algorithm 2 384 bits (SHA-384).
+ HASH_ALGORITHM_SHA_384 = 3;
}
diff --git a/tools/source/published_devices_delta/google/chrome/widevine/contentpartners/v1beta1/published_devices.proto b/tools/source/published_devices_delta/google/chrome/widevine/contentpartners/v1beta1/published_devices.proto
old mode 100755
new mode 100644
diff --git a/tools/source/published_devices_delta/tools/BUILD b/tools/source/published_devices_delta/tools/BUILD
index fd75ed8..f9f6e6c 100644
--- a/tools/source/published_devices_delta/tools/BUILD
+++ b/tools/source/published_devices_delta/tools/BUILD
@@ -21,6 +21,22 @@ java_library(
],
)
+java_library(
+ name = "device_security_profiles_lib",
+ srcs = [
+ "DeviceSecurityProfilesDeltaWrapper.java",
+ "DeviceSecurityProfilesWrapper.java",
+ ],
+ deps = [
+ "//google/chrome/widevine/contentpartners/v1beta1:device_security_profiles_java_proto",
+ "@com_google_protobuf//:protobuf_java",
+ "//video/widevine/protos/public:device_security_profile_list_java_proto",
+ "//video/widevine/protos/public:device_security_profiles_delta_java_proto",
+ "//video/widevine/protos/public:security_profile_java_proto",
+ "@google_guava//:com_google_guava_guava",
+ ],
+)
+
java_binary(
name = "published_devices_delta",
srcs = [
@@ -28,14 +44,18 @@ java_binary(
],
main_class = "com.google.video.widevine.jts.tools.PublishedDevicesMain",
deps = [
+ ":device_security_profiles_lib",
":published_devices_delta_lib",
"@com_google_protobuf//:protobuf_java",
"@jcommander//:com_beust_jcommander",
"@json//:org_json_json",
"//video/widevine/protos/public:device_certificate_status_java_proto",
"//video/widevine/protos/public:device_certificate_status_proto",
+ "//video/widevine/protos/public:device_security_profiles_delta_java_proto",
+ "//video/widevine/protos/public:device_security_profiles_delta_proto",
"//video/widevine/protos/public:published_devices_delta_java_proto",
"//video/widevine/protos/public:published_devices_delta_proto",
+ "//video/widevine/protos/public:security_profile_java_proto",
"@google_guava//:com_google_guava_guava",
],
)
diff --git a/tools/source/published_devices_delta/tools/DeviceSecurityProfilesDeltaWrapper.java b/tools/source/published_devices_delta/tools/DeviceSecurityProfilesDeltaWrapper.java
new file mode 100644
index 0000000..a47e628
--- /dev/null
+++ b/tools/source/published_devices_delta/tools/DeviceSecurityProfilesDeltaWrapper.java
@@ -0,0 +1,259 @@
+// Copyright 2020 Google LLC. All rights reserved.
+package com.google.video.widevine.jts.tools;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.chrome.widevine.contentpartners.v1beta1.SignedDeviceSecurityProfiles;
+import com.google.protobuf.ExtensionRegistry;
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.video.widevine.protos.DeviceSecurityProfileListProtos.DeviceSecurityProfileList;
+import com.google.video.widevine.protos.DeviceSecurityProfilesDeltaProtos.DeviceSecurityProfilesDelta;
+import com.google.video.widevine.protos.DeviceSecurityProfilesDeltaProtos.DeviceSecurityProfilesDelta.DspDelta;
+import com.google.video.widevine.protos.DeviceSecurityProfilesDeltaProtos.DeviceSecurityProfilesDelta.Header;
+import com.google.video.widevine.protos.DeviceSecurityProfilesDeltaProtos.DeviceSecurityProfilesDelta.Modified;
+import com.google.video.widevine.protos.SecurityProfileProtos.SecurityProfile;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/** Device Security Profiles Delta Wrapper class to find the diff of two DSPs list. */
+final class DeviceSecurityProfilesDeltaWrapper {
+ private DeviceSecurityProfileList originalDspList = null;
+ private DeviceSecurityProfileList newDspList = null;
+ private DeviceSecurityProfilesDelta dspDelta = null;
+ private final List dspAddedList = new ArrayList<>();
+ private final List dspRemovedList = new ArrayList<>();
+ private final List dspModifiedList = new ArrayList<>();
+
+ /**
+ * DeviceSecurityProfilesDeltaWrapper constructor. The input is two {@link
+ * SignedDeviceSecurityProfiles} proto messages.
+ *
+ * @param signedDspList1 first {@link SignedDeviceSecurityProfiles} proto message.
+ * @param signedDspList2 second {@link SignedDeviceSecurityProfiles} proto message.
+ * @throws InvalidProtocolBufferException if failed to parse DeviceSecurityProfileList from {@link
+ * SignedDeviceSecurityProfiles}.
+ */
+ public DeviceSecurityProfilesDeltaWrapper(
+ SignedDeviceSecurityProfiles signedDspList1, SignedDeviceSecurityProfiles signedDspList2)
+ throws InvalidProtocolBufferException {
+ checkNotNull(signedDspList1, "'signedDspList1' must not be null");
+ checkNotNull(signedDspList2, "'signedDspList2' must not be null");
+ parseDeviceSecurityProfilesList(signedDspList1, signedDspList2);
+ this.dspDelta = createDeviceSecurityProfilesDelta(originalDspList, newDspList);
+ createDeviceSecurityProfilesDeltaInfo(this.dspDelta);
+ }
+ /**
+ * DeviceSecurityProfilesDeltaWrapper constructor. The input is two byte arrays of serialized
+ * {@link SignedDeviceSecurityProfiles} proto.
+ *
+ * @param signedDspListInBytes1 first serialized {@link SignedDeviceSecurityProfiles} proto in
+ * bytes.
+ * @param signedDspListInBytes2 second serialized {@link SignedDeviceSecurityProfiles} proto in
+ * bytes.
+ * @throws InvalidProtocolBufferException if failed to parse {@link SignedDeviceSecurityProfiles}
+ * or if failed to parse {@link DeviceSecurityProfileList}.
+ */
+ public DeviceSecurityProfilesDeltaWrapper(
+ byte[] signedDspListInBytes1, byte[] signedDspListInBytes2)
+ throws InvalidProtocolBufferException {
+ checkNotNull(signedDspListInBytes1, "'signedDspListInBytes1' must not be null");
+ checkNotNull(signedDspListInBytes2, "'signedDspListInBytes2' must not be null");
+ SignedDeviceSecurityProfiles signedDspListProto1 =
+ SignedDeviceSecurityProfiles.parseFrom(
+ signedDspListInBytes1, ExtensionRegistry.getEmptyRegistry());
+ SignedDeviceSecurityProfiles signedDspListProto2 =
+ SignedDeviceSecurityProfiles.parseFrom(
+ signedDspListInBytes2, ExtensionRegistry.getEmptyRegistry());
+ parseDeviceSecurityProfilesList(signedDspListProto1, signedDspListProto2);
+ this.dspDelta = createDeviceSecurityProfilesDelta(originalDspList, newDspList);
+ createDeviceSecurityProfilesDeltaInfo(this.dspDelta);
+ }
+
+ /** Returns {@link DeviceSecurityProfilesDelta} of two dsp lists. */
+ public DeviceSecurityProfilesDelta getDelta() {
+ return dspDelta;
+ }
+
+ /**
+ * Returns {@link DspDelta} for a specific content owner. If no matched result, return empty
+ * DspDelta proto.
+ */
+ public DspDelta getDeviceSecurityProfilesDelta(String owner) {
+ for (DspDelta dspDeltaEntry : dspDelta.getDspDeltaList()) {
+ if (dspDeltaEntry.getOwner().equals(owner)) {
+ return dspDeltaEntry;
+ }
+ }
+ return DspDelta.getDefaultInstance();
+ }
+
+ /** Returns a list of added DSPs from DeviceSecurityProfilesDelta for all content owners. */
+ public List getAddedDeviceSecurityProfiles() {
+ return dspAddedList;
+ }
+
+ /** Returns a list of removed DSPs from DeviceSecurityProfilesDelta for all content owners. */
+ public List getRemovedDeviceSecurityProfiles() {
+ return dspRemovedList;
+ }
+
+ /** Returns a list of modified DSPs from DeviceSecurityProfilesDelta for all content owners. */
+ public List getModifiedDeviceSecurityProfiles() {
+ return dspModifiedList;
+ }
+
+ /** Parse {@link DeviceSecurityProfileList} from {@link SignedDeviceSecurityProfiles}. */
+ private void parseDeviceSecurityProfilesList(
+ SignedDeviceSecurityProfiles signedDspList1, SignedDeviceSecurityProfiles signedDspList2)
+ throws InvalidProtocolBufferException {
+ originalDspList =
+ DeviceSecurityProfileList.parseFrom(
+ signedDspList1.getDeviceSecurityProfiles(), ExtensionRegistry.getEmptyRegistry());
+ newDspList =
+ DeviceSecurityProfileList.parseFrom(
+ signedDspList2.getDeviceSecurityProfiles(), ExtensionRegistry.getEmptyRegistry());
+
+ // Swap the DeviceSecurityProfileList if originalDspList is newer than signedDspList2.
+ if (originalDspList.getCreationTimeSeconds() > newDspList.getCreationTimeSeconds()) {
+ DeviceSecurityProfileList tempList = newDspList;
+ newDspList = originalDspList;
+ originalDspList = tempList;
+ }
+ }
+
+ /** Creates a {@link DeviceSecurityProfilesDelta} of originalDspList and newDspList. */
+ private static DeviceSecurityProfilesDelta createDeviceSecurityProfilesDelta(
+ DeviceSecurityProfileList originalDspList, DeviceSecurityProfileList newDspList) {
+ Header header =
+ Header.newBuilder()
+ .setPrevCreationTimeSeconds(originalDspList.getCreationTimeSeconds())
+ .setNewCreationTimeSeconds(newDspList.getCreationTimeSeconds())
+ .build();
+ DeviceSecurityProfilesDelta.Builder deltaBuilder =
+ DeviceSecurityProfilesDelta.newBuilder().setHeader(header);
+
+ // Separately add all original dsps and new dsps into two maps. Key is content owner name,
+ // value is a list of dsps created by this content owner.
+ Map> originalDspMap = initializeDspMap(originalDspList);
+ Map> newDspMap = initializeDspMap(newDspList);
+ // Create a map to store DspDelta.Builder. Key is content owner name, value is dspDelta for each
+ // owner.
+ Map dspDeltaBuilderMap = calculateDspDelta(originalDspMap, newDspMap);
+
+ // Export dspDeltaBuilderMap and return DeviceSecurityProfilesDelta proto.
+ for (String owner : dspDeltaBuilderMap.keySet()) {
+ DspDelta.Builder dspDeltaBuilder = dspDeltaBuilderMap.get(owner).setOwner(owner);
+ deltaBuilder.addDspDelta(dspDeltaBuilder.build());
+ }
+ return deltaBuilder.build();
+ }
+
+ /**
+ * Parses {@link DeviceSecurityProfilesDelta} to obtain AddedList, RemovedList and ModifiedList
+ * for all content owners from DeviceSecurityProfilesList.
+ */
+ private void createDeviceSecurityProfilesDeltaInfo(DeviceSecurityProfilesDelta dspDelta) {
+ for (DspDelta dspDeltaEntry : dspDelta.getDspDeltaList()) {
+ dspAddedList.addAll(dspDeltaEntry.getAddedList());
+ dspRemovedList.addAll(dspDeltaEntry.getRemovedList());
+ dspModifiedList.addAll(dspDeltaEntry.getModifiedList());
+ }
+ }
+
+ /**
+ * Creates dsp map storing dsp list.
+ *
+ * @param dspList dsp list in DeviceSecurityProfileList proto.
+ * @return a map which stores dsp list. Key is content owner name, value is a list of dsps for
+ * that owner.
+ */
+ private static Map> initializeDspMap(
+ DeviceSecurityProfileList dspList) {
+ Map> dspMap = new LinkedHashMap<>();
+ for (SecurityProfile dsp : dspList.getDeviceSecurityProfilesList()) {
+ dspMap.putIfAbsent(dsp.getOwner(), new ArrayList<>());
+ dspMap.get(dsp.getOwner()).add(dsp);
+ }
+ return dspMap;
+ }
+
+ /**
+ * Calculates dsp delta based on the original dsp and new dsp map.
+ *
+ * @param originalDspMap original dsp map.
+ * @param newDspMap new dsp map.
+ * @return a dsp delta map. Key is content owner name, value is the dsp delta builder belongs to
+ * that owner.
+ */
+ private static Map calculateDspDelta(
+ Map> originalDspMap,
+ Map> newDspMap) {
+ Map dspDeltaBuilderMap = new LinkedHashMap<>();
+ for (String owner : newDspMap.keySet()) {
+ // Record already-processed original dsp set.
+ Set processedOriginalDspSet = new HashSet<>();
+
+ // If current owner is not shown in the original dsp map, add all new dsps to Add field for
+ // this content owner and then continue checking the next owner from new dsp map.
+ if (!originalDspMap.containsKey(owner)) {
+ dspDeltaBuilderMap.putIfAbsent(owner, DspDelta.newBuilder().setOwner(owner));
+ dspDeltaBuilderMap.get(owner).addAllAdded(newDspMap.get(owner));
+ continue;
+ }
+ for (SecurityProfile newDsp : newDspMap.get(owner)) {
+ // For each new dsp, compare with the original dsp list.
+ // If two dsps are identical, record it to the already-processed list. And pass to the next
+ // new dsp.
+ if (originalDspMap.get(owner).contains(newDsp)) {
+ // Record the original dsp which is dentical to new dsp in the already_processed list.
+ processedOriginalDspSet.add(newDsp);
+ continue;
+ } else {
+ // If new dsp can't find the equivalent dsp in the original list, need to figure out it is
+ // an new added one or a modified one -modified one comes with the same dsp unique key
+ // {dspName, owner, provider, startTime}.
+ boolean sameDspUniqueKeyFound = false;
+ for (SecurityProfile originalDsp : originalDspMap.get(owner)) {
+ // Owner and provider are identical. Only need to compare dspName and startTime.
+ if (originalDsp.getName().equals(newDsp.getName())
+ && (originalDsp.getControlTime().getStartTimeSeconds()
+ == newDsp.getControlTime().getStartTimeSeconds())) {
+ // Add original and new dsp to Modified field for this content owner.
+ dspDeltaBuilderMap.putIfAbsent(owner, DspDelta.newBuilder().setOwner(owner));
+ dspDeltaBuilderMap
+ .get(owner)
+ .addModifiedBuilder()
+ .setPrevDsp(originalDsp)
+ .setNewDsp(newDsp);
+ // Record the original dsp in the already_processed list.
+ processedOriginalDspSet.add(originalDsp);
+ sameDspUniqueKeyFound = true;
+ break;
+ }
+ }
+ if (!sameDspUniqueKeyFound) {
+ // Add new dsp to Added field for this content owner.
+ dspDeltaBuilderMap.putIfAbsent(owner, DspDelta.newBuilder().setOwner(owner));
+ dspDeltaBuilderMap.get(owner).addAdded(newDsp);
+ }
+ }
+ }
+ // Remove already-processed dsps from originalDspMap for this content owner.
+ originalDspMap.get(owner).removeAll(processedOriginalDspSet);
+ }
+
+ // Add all remaining dsps from originalDspMap to Removed field.
+ for (String owner : originalDspMap.keySet()) {
+ if (!originalDspMap.get(owner).isEmpty()) {
+ dspDeltaBuilderMap.putIfAbsent(owner, DspDelta.newBuilder().setOwner(owner));
+ dspDeltaBuilderMap.get(owner).addAllRemoved(originalDspMap.get(owner));
+ }
+ }
+
+ return dspDeltaBuilderMap;
+ }
+}
diff --git a/tools/source/published_devices_delta/tools/DeviceSecurityProfilesWrapper.java b/tools/source/published_devices_delta/tools/DeviceSecurityProfilesWrapper.java
new file mode 100644
index 0000000..39266fb
--- /dev/null
+++ b/tools/source/published_devices_delta/tools/DeviceSecurityProfilesWrapper.java
@@ -0,0 +1,150 @@
+// Copyright 2020 Google LLC. All rights reserved.
+package com.google.video.widevine.jts.tools;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Strings.isNullOrEmpty;
+
+import com.google.chrome.widevine.contentpartners.v1beta1.SignedDeviceSecurityProfiles;
+import com.google.protobuf.ExtensionRegistry;
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.video.widevine.protos.DeviceSecurityProfileListProtos.DeviceSecurityProfileList;
+import com.google.video.widevine.protos.DeviceSecurityProfilesDeltaProtos.DeviceSecurityProfilesDelta;
+import com.google.video.widevine.protos.SecurityProfileProtos.SecurityProfile;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/** Device Security Profiles Wrapper class to parse and discover retrieved DSPs. */
+final class DeviceSecurityProfilesWrapper {
+ private SignedDeviceSecurityProfiles signedDspList = null;
+ private DeviceSecurityProfileList dspList = null;
+ private final Map> dspMap = new LinkedHashMap<>();
+ private Set ownerSet = null;
+
+ /**
+ * Constructor to create DeviceSecurityProfilesWrapper object with {@link
+ * SignedDeviceSecurityProfiles} as input.
+ *
+ * @param signedDspList SignedDeviceSecurityProfiles proto.
+ */
+ public DeviceSecurityProfilesWrapper(SignedDeviceSecurityProfiles signedDspList)
+ throws InvalidProtocolBufferException {
+ checkNotNull(signedDspList, "'signedDspList' must not be null");
+ this.signedDspList = signedDspList;
+ parseDeviceSecurityProfilesList();
+ }
+
+ /**
+ * Constructor to create DeviceSecurityProfilesWrapper object with byte array from {@link
+ * SignedDeviceSecurityProfiles} serialized proto.
+ *
+ * @param signedDspListInfo a serialized SignedDeviceSecurityProfiles proto.
+ */
+ public DeviceSecurityProfilesWrapper(byte[] signedDspListInfo)
+ throws InvalidProtocolBufferException {
+ checkNotNull(signedDspListInfo, "'signedDspListInfo' must not be null");
+ signedDspList =
+ SignedDeviceSecurityProfiles.parseFrom(
+ signedDspListInfo, ExtensionRegistry.getEmptyRegistry());
+ parseDeviceSecurityProfilesList();
+ }
+
+ /**
+ * Get DeviceSecurityProfileList.
+ *
+ * @return DeviceSecurityProfileList a deserialized DeviceSecurityProfiles message from
+ * SignedDeviceSecurityProfiles.
+ */
+ public DeviceSecurityProfileList getDeviceSecurityProfileList() {
+ return dspList;
+ }
+
+ /**
+ * Get the number of DSPs shown in DeviceSecurityProfileList.
+ *
+ * @return int Number of DSPs shown in DeviceSecurityProfileList.
+ */
+ public int getSize() {
+ return dspList.getDeviceSecurityProfilesCount();
+ }
+
+ /**
+ * Get a list of DeviceSecurityProfiles for specific content owner.
+ *
+ * @param owner content owner name in String.
+ * @return {@link List} a list of DSPs for specific content owner. Return null if
+ * none of the DSPs belongs to the specific content owner.
+ */
+ public List getDeviceSecurityProfiles(String owner) {
+ if (isNullOrEmpty(owner)) {
+ return null;
+ }
+ return dspMap.get(owner);
+ }
+
+ /**
+ * Get the content owner list from the DSPs.
+ *
+ * @return {@link List} a list of content owners shown in the DSPs. Return null if owner
+ * set is null or empty.
+ */
+ public List getOwners() {
+ if (ownerSet == null || ownerSet.isEmpty()) {
+ return null;
+ }
+ return new ArrayList<>(ownerSet);
+ }
+
+ /**
+ * Get one DeviceSecurityProfile given content owner and profile name.
+ *
+ * @param owner content owner name in String.
+ * @param profileName dsp name in String.
+ * @return {@link SecurityProfile) One specific DSP which matches content owner and profile name.
+ * Return null if such DSP couldn't be found.
+ */
+ SecurityProfile getDeviceSecurityProfile(String owner, String profileName) {
+ List list = dspMap.get(owner);
+ if (list == null) {
+ return null;
+ }
+ for (SecurityProfile securityProfile : list) {
+ if (securityProfile.getName().equals(profileName)) {
+ return securityProfile;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get {@link DeviceSecurityProfilesDelta} of new signedDspList with current signedDspList.
+ *
+ * @param newSignedDspList new signed dsp list in SignedDeviceSecurityProfiles proto.
+ * @return {@link DeviceSecurityProfilesDelta}.
+ * @throws InvalidProtocolBufferException if failed to parse DeviceSecurityProfileList from
+ * SignedDeviceSecurityProfiles.
+ */
+ public DeviceSecurityProfilesDelta getDeviceSecurityProfilesDelta(
+ SignedDeviceSecurityProfiles newSignedDspList) throws InvalidProtocolBufferException {
+ checkNotNull(newSignedDspList, "'newSignedDspList' must not be null");
+ DeviceSecurityProfilesDeltaWrapper dspDeltaWrapper =
+ new DeviceSecurityProfilesDeltaWrapper(this.signedDspList, newSignedDspList);
+ return dspDeltaWrapper.getDelta();
+ }
+
+ private void parseDeviceSecurityProfilesList() throws InvalidProtocolBufferException {
+ dspList =
+ DeviceSecurityProfileList.parseFrom(
+ signedDspList.getDeviceSecurityProfiles(), ExtensionRegistry.getEmptyRegistry());
+
+ // Add all DSPs into a map where key is dsp owner, value is a list of DSPs.
+ for (SecurityProfile dsp : dspList.getDeviceSecurityProfilesList()) {
+ dspMap.putIfAbsent(dsp.getOwner(), new ArrayList<>());
+ dspMap.get(dsp.getOwner()).add(dsp);
+ }
+ // Get owner set from key set of dspMap.
+ ownerSet = dspMap.keySet();
+ }
+}
diff --git a/tools/source/published_devices_delta/tools/PublishedDevicesMain.java b/tools/source/published_devices_delta/tools/PublishedDevicesMain.java
index 4709723..ce867a4 100644
--- a/tools/source/published_devices_delta/tools/PublishedDevicesMain.java
+++ b/tools/source/published_devices_delta/tools/PublishedDevicesMain.java
@@ -6,12 +6,18 @@ import static com.google.common.io.BaseEncoding.base64Url;
import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
+import com.google.common.base.Ascii;
+import com.google.common.collect.ImmutableList;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.video.widevine.protos.DeviceCertificateStatusProtos.DeviceCertificateStatus;
+import com.google.video.widevine.protos.DeviceSecurityProfilesDeltaProtos.DeviceSecurityProfilesDelta;
+import com.google.video.widevine.protos.DeviceSecurityProfilesDeltaProtos.DeviceSecurityProfilesDelta.DspDelta;
import com.google.video.widevine.protos.PublishedDevicesDeltaProtos.PublishedDevicesDelta;
+import com.google.video.widevine.protos.SecurityProfileProtos.SecurityProfile;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
+import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -21,47 +27,93 @@ import org.json.JSONObject;
/**
* Published Devices command line tool.
*
- * Provides a command line tool to get the diff between two PublishedDevices Proto, parse the
- * PublishedDevices and PublishedDevicesDelta.
+ *
Provides a command line tool which could help to (1) get the diff between two PublishedDevices
+ * Proto, parse the PublishedDevices and PublishedDevicesDelta. (2) get the diff between two
+ * SignedDeviceSecurityProfiles Proto, parse the DeviceSecurityProfiles and
+ * DeviceSecurityProfilesDelta.
*
*
To build: Bazel build tools:published_devices_delta_deploy.jar
*
- *
To run: java -jar /path/to/published_devices_lib_deploy.jar -new_published_devices_path path
- * -original_published_devices_path path -print
+ *
Commands for PublishedDevices:
*
- *
To run: java -jar /path/to/published_devices_lib_deploy.jar -new_published_devices_path path
- * -original_published_devices_path path -system_id 100 -get_system_ids
+ *
To run: java -jar /path/to/published_devices_lib_deploy.jar -new_file_path path
+ * -original_file_path path -print
+ *
+ *
To run: java -jar /path/to/published_devices_lib_deploy.jar -new_file_path path
+ * -original_file_path path -system_id 100 -get_system_ids
*
*
To run: java -jar /path/to/published_devices_lib_deploy.jar -query path -system_id 100
+ *
+ *
Commands for DeviceSecurityProfiles:
+ *
+ *
Get DSP delta, save and print it: java -jar /path/to/published_devices_lib_deploy.jar
+ * -data_type DSP -new_file_path path -original_file_path path -print
+ *
+ *
Obtain the dsp delta per content owner: java -jar /path/to/published_devices_lib_deploy.jar
+ * -data_type DSP -new_file_path path -original_file_path path -content_owner owner_name
+ *
+ *
Obtain Added/Removed/Modified list in dsp delta: java -jar
+ * /path/to/published_devices_lib_deploy.jar -data_type DSP -new_file_path path -original_file_path
+ * path -get_specific_field_in_dsp_delta field_name
+ *
+ *
Get DSPs for specific owner: java -jar /path/to/published_devices_lib_deploy.jar -data_type
+ * DSP -query path -content_owner owner_name
+ *
+ *
Get owner list from one retrieved dsp list: java -jar
+ * /path/to/published_devices_lib_deploy.jar -data_type DSP -query path -get_owners
+ *
+ *
Get targeted dsp given contentOwner and profile name: java -jar
+ * /path/to/published_devices_lib_deploy.jar -data_type DSP -query path -content_owner owner_name
+ * -profile_name profile_name
*/
final class PublishedDevicesMain {
private static final Logger logger = Logger.getLogger(PublishedDevicesMain.class.getName());
private static final int ZERO_SYSTEM_ID = 0;
private static final String JSON_NAME = "signedList";
+ private static final String PUBLISHED_DEVICES = "PUBLISHED_DEVICES";
+ private static final String DSP = "DSP";
+ private static final ImmutableList DATA_TYPE_LIST =
+ ImmutableList.of(PUBLISHED_DEVICES, DSP);
+ private static final String ADDED_FIELD_IN_DSP_DELTA = "added";
+ private static final String MODIFIED_FIELD_IN_DSP_DELTA = "modified";
+ private static final String REMOVED_FIELD_IN_DSP_DELTA = "removed";
+
/** Command Line Flags. */
static class Flags {
private Flags() {}
+ // Shared parameters for both PublishedDevices and DSP.
@Parameter(
- names = "-original_published_devices_path",
- description = "Path to original PublishedDevices file")
- private String originalPublishedDevicesPath = null;
+ names = "-data_type",
+ description = "Set parsed data type. Must be \"PUBLISHED_DEVICES\" or \"DSP\".")
+ private String dataType = "PUBLISHED_DEVICES";
@Parameter(
- names = "-new_published_devices_path",
- description = "Path to new PublishedDevices file")
- private String newPublishedDevicesPath = null;
+ names = "-original_file_path",
+ description =
+ "Path to original file. Could be the original file for either PublishedDevices or"
+ + " DeviceSecurityProfiles.")
+ private String originalFilePath = null;
+
+ @Parameter(
+ names = "-new_file_path",
+ description =
+ "Path to new file. Could be the new file for either PublishedDevices or"
+ + " DeviceSecurityProfiles.")
+ private String newFilePath = null;
@Parameter(
names = "-print",
- description =
- "Setting to true, if content provider want to print the published devices in String.")
+ description = "Setting to true, if content provider wants to print the delta in String.")
private boolean print = false;
- @Parameter(names = "-query", description = "Parse published devices file.")
+ @Parameter(names = "-query", description = "Parse the input file.")
private String query = null;
- @Parameter(names = "-system_id", description = "Device system-id.")
+ // Unique parameters for PublishedDevices.
+ @Parameter(
+ names = "-system_id",
+ description = "Device system-id shown in PublishedDevicesList.")
private int systemId = ZERO_SYSTEM_ID;
@Parameter(
@@ -69,48 +121,51 @@ final class PublishedDevicesMain {
description =
"Boolean to get list of system_ids in added/removed/modified PublishedDevicesList.")
private boolean getSystenIdsList = false;
+
+ // Unique parameters for DeviceSecurityProfiles.
+ @Parameter(
+ names = "-content_owner",
+ description = "Content owner name to retrieve corresponding DeviceSecurityProfiles.")
+ private String contentOwner = null;
+
+ @Parameter(
+ names = "-get_specific_field_in_dsp_delta",
+ description =
+ "Optional. Obtain one specific field (added, removed or modified) in dsp delta."
+ + " Returned list covers all content owners.")
+ private String getSpecificFieldInDspDelta = null;
+
+ @Parameter(
+ names = "-get_owners",
+ description = "Obtain owner list from one DeviceSecurityProfilesList.")
+ private boolean getOwners = false;
+
+ @Parameter(names = "-profile_name", description = "device security profile name.")
+ private String profileName = null;
}
/** Main function to run Published Devices Delta command line tool. */
public static void main(String[] args) {
Flags flags = new Flags();
new JCommander(flags, args);
- if (flags.newPublishedDevicesPath != null && flags.originalPublishedDevicesPath != null) {
- parsePublishedDevicesDelta(flags);
- } else if (flags.query != null) {
- try {
- byte[] publishedDevices = getPublishedDevicesAsBytes(flags.query);
- checkLoadFileResult(flags.query, publishedDevices);
- PublishedDevicesWrapper wrapper = new PublishedDevicesWrapper(publishedDevices);
- if (flags.systemId != ZERO_SYSTEM_ID) {
- DeviceCertificateStatus deviceCertificateStatus =
- wrapper.getDeviceCertificateStatus(flags.systemId);
- if (deviceCertificateStatus == null) {
- logger.log(
- Level.SEVERE,
- flags.systemId
- + " (system-id) does not found in PublishedDevicesList from "
- + flags.query);
- System.exit(1);
- }
- System.out.println(deviceCertificateStatus);
- // TODO(b/160253740): Add ProvisonedStatus, ProvisionedDeviceInfo and function.
- }
- } catch (InvalidProtocolBufferException e) {
- logger.log(
- Level.SEVERE,
- "InvalidProtocolBufferException encountered to parse device certificate status list"
- + " or published devices proto:"
- + e);
- } catch (IOException e) {
- logger.log(
- Level.SEVERE, "IOException encountered trying to open published devices file: " + e);
+ // Check the FLAGs.
+ if (!DATA_TYPE_LIST.contains(flags.dataType)) {
+ System.out.println("Data type should be selected from:" + DATA_TYPE_LIST);
+ logger.log(Level.SEVERE, "Data type should match with PUBLISHED_DEVICES or DSP.");
+ }
+
+ if (flags.dataType.equals(PUBLISHED_DEVICES)) {
+ if (flags.newFilePath != null && flags.originalFilePath != null) {
+ parsePublishedDevicesDelta(flags);
+ } else if (flags.query != null) {
+ queryPublishedDevices(flags);
+ }
+ } else if (flags.dataType.equals(DSP)) {
+ if (flags.newFilePath != null && flags.originalFilePath != null) {
+ parseDeviceSecurityProfilesDelta(flags);
+ } else if (flags.query != null) {
+ queryDeviceSecurityProfiles(flags);
}
- } else if (flags.originalPublishedDevicesPath != null
- || flags.newPublishedDevicesPath != null) {
- logger.log(
- Level.SEVERE,
- "Both originalPublishedDevicesPath and newPublishedDevicesPath should be specified.");
}
}
@@ -118,10 +173,11 @@ final class PublishedDevicesMain {
private static void parsePublishedDevicesDelta(Flags flags) {
try {
byte[] originalPublishedDevices =
- getPublishedDevicesAsBytes(flags.originalPublishedDevicesPath);
- byte[] newPublishedDevices = getPublishedDevicesAsBytes(flags.newPublishedDevicesPath);
- checkLoadFileResult(flags.originalPublishedDevicesPath, originalPublishedDevices);
- checkLoadFileResult(flags.newPublishedDevicesPath, newPublishedDevices);
+ getPublishedDevicesOrDSPFileAsBytes(flags.originalFilePath, flags.dataType);
+ byte[] newPublishedDevices =
+ getPublishedDevicesOrDSPFileAsBytes(flags.newFilePath, flags.dataType);
+ checkLoadFileResult(flags.originalFilePath, originalPublishedDevices);
+ checkLoadFileResult(flags.newFilePath, newPublishedDevices);
PublishedDevicesDeltaWrapper devices =
new PublishedDevicesDeltaWrapper(originalPublishedDevices, newPublishedDevices);
PublishedDevicesDelta delta = devices.getDelta();
@@ -135,7 +191,31 @@ final class PublishedDevicesMain {
}
}
- /** Parse the argument related to PublishedDevicesDelta. */
+ /** Parse the argument related to DeviceSecurityProfilesDelta. */
+ private static void parseDeviceSecurityProfilesDelta(Flags flags) {
+ try {
+ byte[] originalDeviceSecurityProfiles =
+ getPublishedDevicesOrDSPFileAsBytes(flags.originalFilePath, flags.dataType);
+ byte[] newDeviceSecurityProfiles =
+ getPublishedDevicesOrDSPFileAsBytes(flags.newFilePath, flags.dataType);
+ checkLoadFileResult(flags.originalFilePath, originalDeviceSecurityProfiles);
+ checkLoadFileResult(flags.newFilePath, newDeviceSecurityProfiles);
+ DeviceSecurityProfilesDeltaWrapper dspDeltaWrapper =
+ new DeviceSecurityProfilesDeltaWrapper(
+ originalDeviceSecurityProfiles, newDeviceSecurityProfiles);
+ DeviceSecurityProfilesDelta delta = dspDeltaWrapper.getDelta();
+ if (flags.print) {
+ System.out.println(delta);
+ }
+ parseDeltaInfo(dspDeltaWrapper, flags);
+ } catch (IOException e) {
+ logger.log(
+ Level.SEVERE,
+ "IOException encountered trying to open device security profiles files: " + e);
+ }
+ }
+
+ /** Parse the detailed info shown in PublishedDevicesDelta. */
private static void parseDeltaInfo(
PublishedDevicesDeltaWrapper publishedDevicesDelta, Flags flags) {
if (flags.systemId != 0) {
@@ -154,7 +234,7 @@ final class PublishedDevicesMain {
System.out.println(
publishedDevicesDelta.getModifiedDeviceCertificateStatus(flags.systemId));
} else {
- logger.log(Level.SEVERE, flags.systemId + "does not found in the PublishedDevicesDelta.");
+ logger.log(Level.SEVERE, flags.systemId + "was not found in the PublishedDevicesDelta.");
}
}
if (flags.getSystenIdsList) {
@@ -170,6 +250,131 @@ final class PublishedDevicesMain {
}
}
+ /** Parse the detailed info shown in DeviceSecurityProfilesDelta. */
+ private static void parseDeltaInfo(
+ DeviceSecurityProfilesDeltaWrapper dspDeltaWrapper, Flags flags) {
+ if (flags.getSpecificFieldInDspDelta != null) {
+ if (Ascii.toLowerCase(flags.getSpecificFieldInDspDelta).equals(ADDED_FIELD_IN_DSP_DELTA)) {
+ System.out.println(
+ "List of added DSPs in device security profiles delta: "
+ + dspDeltaWrapper.getAddedDeviceSecurityProfiles());
+ } else if (Ascii.toLowerCase(flags.getSpecificFieldInDspDelta)
+ .equals(MODIFIED_FIELD_IN_DSP_DELTA)) {
+ System.out.println(
+ "List of modified DSPs in device security profiles delta: "
+ + dspDeltaWrapper.getModifiedDeviceSecurityProfiles());
+ } else if (Ascii.toLowerCase(flags.getSpecificFieldInDspDelta)
+ .equals(REMOVED_FIELD_IN_DSP_DELTA)) {
+ System.out.println(
+ "List of removed DSPs in device security profiles delta: "
+ + dspDeltaWrapper.getRemovedDeviceSecurityProfiles());
+ } else {
+ logger.log(
+ Level.SEVERE,
+ flags.getSpecificFieldInDspDelta
+ + "is not a valid field in DeviceSecurityProfilesDelta.");
+ }
+ }
+
+ if (flags.contentOwner != null) {
+ DspDelta dspDelta = dspDeltaWrapper.getDeviceSecurityProfilesDelta(flags.contentOwner);
+ if (dspDelta != null) {
+ System.out.println("Obtain the dsp delta for specific content owner: " + dspDelta);
+ } else {
+ logger.log(
+ Level.WARNING, flags.contentOwner + "is not shown in DeviceSecurityProfilesDelta.");
+ }
+ }
+ }
+
+ private static void queryPublishedDevices(Flags flags) {
+ try {
+ byte[] publishedDevices = getPublishedDevicesOrDSPFileAsBytes(flags.query, flags.dataType);
+ checkLoadFileResult(flags.query, publishedDevices);
+ PublishedDevicesWrapper wrapper = new PublishedDevicesWrapper(publishedDevices);
+ if (flags.systemId != ZERO_SYSTEM_ID) {
+ DeviceCertificateStatus deviceCertificateStatus =
+ wrapper.getDeviceCertificateStatus(flags.systemId);
+ if (deviceCertificateStatus == null) {
+ logger.log(
+ Level.SEVERE,
+ flags.systemId
+ + " (system-id) was not found in PublishedDevicesList from "
+ + flags.query);
+ System.exit(1);
+ }
+ System.out.println(deviceCertificateStatus);
+ // TODO(b/160253740): Add ProvisonedStatus and ProvisionedDeviceInfo functions.
+ }
+ } catch (InvalidProtocolBufferException e) {
+ logger.log(
+ Level.SEVERE,
+ "InvalidProtocolBufferException encountered to parse device certificate status list"
+ + " or published devices proto:"
+ + e);
+ } catch (IOException e) {
+ logger.log(
+ Level.SEVERE, "IOException encountered trying to open published devices file: " + e);
+ }
+ }
+
+ private static void queryDeviceSecurityProfiles(Flags flags) {
+ try {
+ byte[] deviceSecurityProfiles =
+ getPublishedDevicesOrDSPFileAsBytes(flags.query, flags.dataType);
+ checkLoadFileResult(flags.query, deviceSecurityProfiles);
+ DeviceSecurityProfilesWrapper dspWrapper =
+ new DeviceSecurityProfilesWrapper(deviceSecurityProfiles);
+ if (flags.contentOwner != null && flags.profileName != null) {
+ SecurityProfile securityProfile =
+ dspWrapper.getDeviceSecurityProfile(flags.contentOwner, flags.profileName);
+ if (securityProfile == null) {
+ logger.log(
+ Level.WARNING,
+ flags.contentOwner
+ + " (content owner) and"
+ + flags.profileName
+ + " (profile name) "
+ + "were not found in DeviceSecurityProfiles from "
+ + flags.query);
+ } else {
+ System.out.println(securityProfile);
+ }
+ } else if (flags.contentOwner != null) {
+ List securityProfiles =
+ dspWrapper.getDeviceSecurityProfiles(flags.contentOwner);
+ if (securityProfiles == null || securityProfiles.isEmpty()) {
+ logger.log(
+ Level.WARNING,
+ flags.contentOwner
+ + " (content owner) was not found in DeviceSecurityProfiles from "
+ + flags.query);
+ } else {
+ System.out.println(Arrays.toString(securityProfiles.toArray()));
+ }
+ }
+ if (flags.getOwners) {
+ List ownerList = dspWrapper.getOwners();
+ if (ownerList == null || ownerList.isEmpty()) {
+ logger.log(
+ Level.WARNING,
+ " owner list was not found in DeviceSecurityProfiles from " + flags.query);
+ }
+ System.out.println(Arrays.toString(ownerList.toArray()));
+ }
+ } catch (InvalidProtocolBufferException e) {
+ logger.log(
+ Level.SEVERE,
+ "InvalidProtocolBufferException encountered while parsing device security profile list"
+ + " or device security profiles proto:"
+ + e);
+ } catch (IOException e) {
+ logger.log(
+ Level.SEVERE,
+ "IOException encountered trying to open device security profiles file: " + e);
+ }
+ }
+
private static void checkLoadFileResult(String filePath, byte[] result) {
if (result == null) {
logger.log(Level.SEVERE, "Fail to load the file:" + filePath);
@@ -178,29 +383,35 @@ final class PublishedDevicesMain {
}
/**
- * Load published devices Json file into string.
+ * Load published devices or device security profiles file into string. For published devices v1,
+ * it would be a json file.
*
* @param filePath file path in String.
* @return byte array file content in String.
* @throws IOException if failed to read the file.
*/
- public static byte[] getPublishedDevicesAsBytes(String filePath) throws IOException {
+ public static byte[] getPublishedDevicesOrDSPFileAsBytes(String filePath, String dataType)
+ throws IOException {
String result = loadFile(filePath);
- if (result == null) {
+ if (!DATA_TYPE_LIST.contains(dataType) || result == null) {
return null;
}
- String requestBody = "";
- try {
- // Parse both PublishedDevices v1 output.
- JSONObject obj = new JSONObject(result);
- requestBody = obj.getString(JSON_NAME);
- } catch (JSONException e) {
- // Parse both PublishedDevices v2 output.
- requestBody = result;
+ byte[] serializedList;
+ if (dataType.equals(PUBLISHED_DEVICES)) {
+ String requestBody = "";
+ try {
+ // Parse both PublishedDevices v1 output.
+ JSONObject obj = new JSONObject(result);
+ requestBody = obj.getString(JSON_NAME);
+ } catch (JSONException e) {
+ // Parse both PublishedDevices v2 output.
+ requestBody = result;
+ }
+ serializedList = base64Decode(requestBody);
+ } else {
+ serializedList = base64Decode(result);
}
- byte[] serializedDCSL = base64Decode(requestBody);
-
- return serializedDCSL;
+ return serializedList;
}
/**
diff --git a/tools/source/published_devices_delta/video/widevine/protos/public/BUILD b/tools/source/published_devices_delta/video/widevine/protos/public/BUILD
index e4c94f5..3eca1fe 100644
--- a/tools/source/published_devices_delta/video/widevine/protos/public/BUILD
+++ b/tools/source/published_devices_delta/video/widevine/protos/public/BUILD
@@ -19,9 +19,11 @@ proto_library(
srcs = [
"client_identification.proto",
"errors.proto",
+ "external_license.proto",
"hash_algorithm.proto",
"license_protocol.proto",
"license_server_sdk.proto",
+ "playready.proto",
"provisioned_device_info.proto",
"remote_attestation.proto",
"sdk_license_data_config.proto",
@@ -38,6 +40,7 @@ proto_library(
"device_certificate_status.proto",
"drm_certificate.proto",
"errors.proto",
+ "external_license.proto",
"hash_algorithm.proto",
"license_protocol.proto",
"license_server_sdk.proto",
@@ -60,6 +63,20 @@ java_proto_library(
deps = [":exported_wvdrm_license_server_sdk_proto"],
)
+proto_library(
+ name = "external_license_proto",
+ srcs = ["external_license.proto"],
+ deps = [
+ ":client_identification_proto",
+ ":license_protocol_proto",
+ ],
+)
+
+java_proto_library(
+ name = "external_license_java_proto",
+ deps = [":external_license_proto"],
+)
+
proto_library(
name = "client_identification_proto",
srcs = ["client_identification.proto"],
@@ -245,6 +262,7 @@ java_proto_library(
proto_library(
name = "signed_drm_certificate_proto",
srcs = ["signed_drm_certificate.proto"],
+ deps = [":hash_algorithm_proto"],
)
java_proto_library(
@@ -297,3 +315,92 @@ java_proto_library(
name = "hash_algorithm_java_proto",
deps = [":hash_algorithm_proto"],
)
+
+proto_library(
+ name = "device_security_profile_data_proto",
+ srcs = ["device_security_profile_data.proto"],
+ deps = [
+ ":client_identification_proto",
+ ":device_common_proto",
+ ":provisioned_device_info_proto",
+ ],
+)
+
+cc_proto_library(
+ name = "device_security_profile_data_cc_proto",
+ deps = [":device_security_profile_data_proto"],
+)
+
+java_proto_library(
+ name = "device_security_profile_data_java_proto",
+ deps = [":device_security_profile_data_proto"],
+)
+
+proto_library(
+ name = "security_profile_proto",
+ srcs = ["security_profile.proto"],
+ deps = [
+ ":device_common_proto",
+ ":device_security_profile_data_proto",
+ ],
+)
+
+cc_proto_library(
+ name = "security_profile_cc_proto",
+ deps = [":security_profile_proto"],
+)
+
+java_proto_library(
+ name = "security_profile_java_proto",
+ deps = [":security_profile_proto"],
+)
+
+proto_library(
+ name = "device_security_profile_list_proto",
+ srcs = ["device_security_profile_list.proto"],
+ deps = [
+ ":hash_algorithm_proto",
+ ":security_profile_proto",
+ ],
+)
+
+java_proto_library(
+ name = "device_security_profile_list_java_proto",
+ deps = [":device_security_profile_list_proto"],
+)
+
+cc_proto_library(
+ name = "device_security_profile_list_cc_proto",
+ deps = [":device_security_profile_list_proto"],
+)
+
+proto_library(
+ name = "device_security_profiles_delta_proto",
+ srcs = ["device_security_profiles_delta.proto"],
+ deps = [":security_profile_proto"],
+)
+
+cc_proto_library(
+ name = "device_security_profiles_delta_cc_proto",
+ deps = [":device_security_profiles_delta_proto"],
+)
+
+java_proto_library(
+ name = "device_security_profiles_delta_java_proto",
+ deps = [":device_security_profiles_delta_proto"],
+)
+
+proto_library(
+ name = "playready_proto",
+ srcs = ["playready.proto"],
+)
+
+cc_proto_library(
+ name = "playready_cc_proto",
+ deps = [":playready_proto"],
+)
+
+java_proto_library(
+ name = "playready_java_proto",
+ deps = [":playready_proto"],
+)
diff --git a/tools/source/published_devices_delta/video/widevine/protos/public/client_identification.proto b/tools/source/published_devices_delta/video/widevine/protos/public/client_identification.proto
new file mode 100644
index 0000000..d94ad4a
--- /dev/null
+++ b/tools/source/published_devices_delta/video/widevine/protos/public/client_identification.proto
@@ -0,0 +1,132 @@
+// Copyright 2016 Google LLC. All rights reserved.
+
+// Author: tinskip@google.com (Thomas Inskip)
+//
+// Description:
+// ClientIdentification messages used by provisioning and license protocols.
+
+syntax = "proto2";
+
+package video_widevine;
+
+
+// go/jspb-correct-proto2
+
+option java_package = "com.google.video.widevine.protos";
+option java_outer_classname = "ClientIdentificationProtos";
+
+
+ // See http://go/go-api-flag.
+
+
+// ClientIdentification message used to authenticate the client device.
+message ClientIdentification {
+ enum TokenType {
+ KEYBOX = 0;
+ DRM_DEVICE_CERTIFICATE = 1;
+ REMOTE_ATTESTATION_CERTIFICATE = 2;
+ OEM_DEVICE_CERTIFICATE = 3;
+ }
+
+ message NameValue {
+ optional string name = 1;
+ optional string value = 2;
+ }
+
+ // Capabilities which not all clients may support. Used for the license
+ // exchange protocol only.
+ message ClientCapabilities {
+ enum HdcpVersion {
+ HDCP_NONE = 0;
+ HDCP_V1 = 1;
+ HDCP_V2 = 2;
+ HDCP_V2_1 = 3;
+ HDCP_V2_2 = 4;
+ HDCP_V2_3 = 5;
+ HDCP_NO_DIGITAL_OUTPUT = 0xff;
+ }
+
+ enum CertificateKeyType {
+ RSA_2048 = 0;
+ RSA_3072 = 1;
+ ECC_SECP256R1 = 2;
+ ECC_SECP384R1 = 3;
+ ECC_SECP521R1 = 4;
+ }
+
+ enum AnalogOutputCapabilities {
+ ANALOG_OUTPUT_UNKNOWN = 0;
+ ANALOG_OUTPUT_NONE = 1;
+ ANALOG_OUTPUT_SUPPORTED = 2;
+ ANALOG_OUTPUT_SUPPORTS_CGMS_A = 3;
+ }
+
+ optional bool client_token = 1 [default = false];
+ optional bool session_token = 2 [default = false];
+ optional bool video_resolution_constraints = 3 [default = false];
+ optional HdcpVersion max_hdcp_version = 4 [default = HDCP_NONE];
+ optional uint32 oem_crypto_api_version = 5;
+ // Client has hardware support for protecting the usage table, such as
+ // storing the generation number in secure memory. For Details, see:
+ // https://docs.google.com/document/d/1Mm8oB51SYAgry62mEuh_2OEkabikBiS61kN7HsDnh9Y/edit#heading=h.xgjl2srtytjt
+ optional bool anti_rollback_usage_table = 6 [default = false];
+ // The client shall report |srm_version| if available.
+ optional uint32 srm_version = 7;
+ // A device may have SRM data, and report a version, but may not be capable
+ // of updating SRM data.
+ optional bool can_update_srm = 8 [default = false];
+ repeated CertificateKeyType supported_certificate_key_type = 9;
+ optional AnalogOutputCapabilities analog_output_capabilities = 10
+ [default = ANALOG_OUTPUT_UNKNOWN];
+ optional bool can_disable_analog_output = 11 [default = false];
+ // Clients can indicate a performance level supported by OEMCrypto.
+ // This will allow applications and providers to choose an appropriate
+ // quality of content to serve. Currently defined tiers are
+ // 1 (low), 2 (medium) and 3 (high). Any other value indicate that
+ // the resource rating is unavailable or reporting erroneous values
+ // for that device. For details see,
+ // https://docs.google.com/document/d/1wodSYK-Unj3AgTSXqujWuBCAFC00qF85G1AhfLtqdko
+ optional uint32 resource_rating_tier = 12 [default = 0];
+ }
+
+ message ClientCredentials {
+ optional TokenType type = 1 [default = KEYBOX];
+ optional bytes token = 2;
+ }
+
+ // Type of factory-provisioned device root of trust. Optional.
+ optional TokenType type = 1 [default = KEYBOX];
+ // Factory-provisioned device root of trust. Required.
+ optional bytes token = 2;
+ // Optional client information name/value pairs.
+ repeated NameValue client_info = 3;
+ // Client token generated by the content provider. Optional.
+ optional bytes provider_client_token = 4;
+ // Number of licenses received by the client to which the token above belongs.
+ // Only present if client_token is specified.
+ optional uint32 license_counter = 5;
+ // List of non-baseline client capabilities.
+ optional ClientCapabilities client_capabilities = 6;
+ // Serialized VmpData message. Optional.
+ optional bytes vmp_data = 7;
+ // Optional field that may contain additional provisioning credentials.
+ optional ClientCredentials device_credentials = 8;
+}
+
+// EncryptedClientIdentification message used to hold ClientIdentification
+// messages encrypted for privacy purposes.
+message EncryptedClientIdentification {
+ // Provider ID for which the ClientIdentifcation is encrypted (owner of
+ // service certificate).
+ optional string provider_id = 1;
+ // Serial number for the service certificate for which ClientIdentification is
+ // encrypted.
+ optional bytes service_certificate_serial_number = 2;
+ // Serialized ClientIdentification message, encrypted with the privacy key
+ // using AES-128-CBC with PKCS#5 padding.
+ optional bytes encrypted_client_id = 3;
+ // Initialization vector needed to decrypt encrypted_client_id.
+ optional bytes encrypted_client_id_iv = 4;
+ // AES-128 privacy key, encrypted with the service public key using RSA-OAEP.
+ optional bytes encrypted_privacy_key = 5;
+}
diff --git a/tools/source/published_devices_delta/video/widevine/protos/public/device_certificate_status.proto b/tools/source/published_devices_delta/video/widevine/protos/public/device_certificate_status.proto
index 7f01e43..b9a2c44 100644
--- a/tools/source/published_devices_delta/video/widevine/protos/public/device_certificate_status.proto
+++ b/tools/source/published_devices_delta/video/widevine/protos/public/device_certificate_status.proto
@@ -61,6 +61,19 @@ message DeviceCertificateStatus {
// RevokedIdentifiers collect all the serial_numbers or unique_id_hashes used
// for individual drm certificate revocation.
optional RevokedIdentifiers revoked_identifiers = 7;
+
+ // Vulnerability levels as defined by NIST national vulnerability database.
+ // https://nvd.nist.gov/vuln-metrics/cvss
+ enum DeviceVulnerabilityLevel {
+ DEVICE_VULNERABILITY_LEVEL_UNSPECIFIED = 0;
+ DEVICE_VULNERABILITY_LEVEL_NONE = 1;
+ DEVICE_VULNERABILITY_LEVEL_LOW = 2;
+ DEVICE_VULNERABILITY_LEVEL_MEDIUM = 3;
+ DEVICE_VULNERABILITY_LEVEL_HIGH = 4;
+ DEVICE_VULNERABILITY_LEVEL_CRITICAL = 5;
+ }
+ // Specifies the device vulnerability level.
+ optional DeviceVulnerabilityLevel device_vulnerability_level = 8;
}
// List of DeviceCertificateStatus. Used to propagate certificate revocation
diff --git a/tools/source/published_devices_delta/video/widevine/protos/public/device_common.proto b/tools/source/published_devices_delta/video/widevine/protos/public/device_common.proto
index f7e5428..7451375 100644
--- a/tools/source/published_devices_delta/video/widevine/protos/public/device_common.proto
+++ b/tools/source/published_devices_delta/video/widevine/protos/public/device_common.proto
@@ -10,9 +10,9 @@ package video_widevine;
option java_package = "com.google.video.widevine.protos";
-// MOE:begin_strip
+
// See http://go/go-api-flag.
-// MOE:end_strip
+
// Allows additional make/models to be associated with a system_id.
message DeviceModel {
@@ -73,6 +73,12 @@ message DeviceModel {
// service should honor requests (classic nor MDRM/CENC) from one of
// these devices. The device serial number and its REVOKED status will
// appear in keysmith's certificate status list.
+// REVOKED_LICENSING: Indicates that the device was revoked. A device series
+// in this state will still allow provisioning of those devices. Licensing
+// will be prohibited just as the REVOKED state. However, the licensing
+// host can choose to override this state and allow licensing.
+// The device serial number and the REVOKED status (not REVOKED_LICENSING)
+// will appear in keysmith's certificate status list.
//
// Devices in the above states have the following behaviors in widevince
// services:
@@ -85,7 +91,12 @@ message DeviceModel {
// PRE_RELEASE Yes Yes Yes Yes VALID false yes
// RELEASED Yes Yes Yes Yes VALID false no
// REVOKED No No No Yes REVOKED false no
+// REVOKED_ No No No Yes REVOKED false no
+// LICENSING No* No* Yes Yes REVOKED false no
// DELETED No No No No n/a n/a n/a
+//
+// * - REVOKED_LICENSING will not issue licenses by default but can be
+// overridden by the host.
enum DeviceState {
DEVICE_STATE_UNKNOWN = 0;
IN_TESTING = 1;
@@ -94,6 +105,7 @@ enum DeviceState {
TEST_ONLY = 4;
REVOKED = 5;
PRE_RELEASE = 6;
+ REVOKED_LICENSING = 7;
}
// Specifies the device type, or form factor of a device.
@@ -167,3 +179,42 @@ enum DeviceSecurityLevel {
LEVEL_2 = 2;
LEVEL_3 = 3;
}
+
+// Defines the possible key types that can be issued for certificates.
+// Historically, we only supported RSA with a standard Euler totient
+// calculation. b/65383373 required that we distinguish between Euler and
+// Carmichael totients for RSA keys. We also now support elliptic curve (EC)
+// keys for certificates.
+enum CertificateKeyType {
+ // Code should treat UNSPECIFIED as RSA key type.
+ // Code should treat UNSPECIFIED as NONE for a secondary encryption key in a
+ // dual keyed cert.
+ CERTIFICATE_KEY_TYPE_UNSPECIFIED = 0;
+ // RSA key with the Euler OR Carmichael totient may be used.
+ CERTIFICATE_KEY_TYPE_RSA = 1;
+ // RSA key with ONLY Euler totient may be used.
+ CERTIFICATE_KEY_TYPE_RSA_EULER = 2;
+ // EC key.
+ CERTIFICATE_KEY_TYPE_EC = 3;
+}
+
+// Vulnerability levels as defined by NIST national vulnerability database.
+// https://nvd.nist.gov/vuln-metrics/cvss
+enum VulnerabilityLevel {
+ VULNERABILITY_LEVEL_UNSPECIFIED = 0;
+ VULNERABILITY_LEVEL_NONE = 1;
+ VULNERABILITY_LEVEL_LOW = 2;
+ VULNERABILITY_LEVEL_MEDIUM = 3;
+ VULNERABILITY_LEVEL_HIGH = 4;
+ VULNERABILITY_LEVEL_CRITICAL = 5;
+}
+
+// Device vulnerability information.
+message VulnerabilityInfo {
+ // Description of the vulnerability.
+ string description = 1;
+ // Buganizer number associated with the vulnerability.
+ uint64 buganizer_number = 2;
+ // Vulnerablity level of a device.
+ VulnerabilityLevel vulnerability_level = 3;
+}
diff --git a/tools/source/published_devices_delta/video/widevine/protos/public/device_security_profile_data.proto b/tools/source/published_devices_delta/video/widevine/protos/public/device_security_profile_data.proto
new file mode 100644
index 0000000..0d21f5e
--- /dev/null
+++ b/tools/source/published_devices_delta/video/widevine/protos/public/device_security_profile_data.proto
@@ -0,0 +1,70 @@
+// Copyright 2020 Google LLC. All rights reserved.
+
+syntax = "proto2";
+
+package video_widevine;
+
+import "video/widevine/protos/public/client_identification.proto";
+import "video/widevine/protos/public/device_common.proto";
+import "video/widevine/protos/public/provisioned_device_info.proto";
+
+option java_package = "com.google.video.widevine.protos";
+
+
+
+
+ // See http://go/go-api-flag.
+
+
+enum SecurityProfileLevel {
+ SECURITY_PROFILE_LEVEL_UNDEFINED = 0;
+ SECURITY_PROFILE_LEVEL_1 = 1;
+ SECURITY_PROFILE_LEVEL_2 = 2;
+ SECURITY_PROFILE_LEVEL_3 = 3;
+ SECURITY_PROFILE_LEVEL_4 = 4;
+ SECURITY_PROFILE_LEVEL_5 = 5;
+}
+
+message OutputRequirement {
+ // Version of HDCP.
+ optional ClientIdentification.ClientCapabilities.HdcpVersion hdcp_version = 1;
+ // Analog output capabilities.
+ optional ClientIdentification.ClientCapabilities.AnalogOutputCapabilities
+ analog_output_capabilities = 2;
+}
+
+message SecurityRequirement {
+ // Version of OEMCrypto.
+ optional uint32 oemcrypto_api_version = 1;
+ // Required. Security level.
+ optional ProvisionedDeviceInfo.WvSecurityLevel security_level = 2;
+ // Resource rating tier based on:
+ // https://docs.google.com/document/d/1wodSYK-Unj3AgTSXqujWuBCAFC00qF85G1AhfLtqdko/edit
+ optional uint32 resource_rating_tier = 3;
+ // Security vulnerability level.
+ optional VulnerabilityLevel vulnerability_level = 4;
+}
+
+message DeviceException {
+ enum ExceptionAction {
+ DEVICE_EXCEPTION_UNSPECIFIED = 0;
+ // Include this profile for the system Id regardless of other profile
+ // requirements.
+ DEVICE_EXCEPTION_ALLOW = 1;
+ // Do not use this profile for the system Id regardless of other profile
+ // requirements.
+ DEVICE_EXCEPTION_BLOCK = 2;
+ }
+ // System Id for the exceptional device.
+ optional uint32 system_id = 1;
+ // Override action is taken if override is specified.
+ optional ExceptionAction action = 2;
+}
+
+message ControlTime {
+ // Timestamp that this dsp should be effective (in seconds since epoch).
+ optional int64 start_time_seconds = 1;
+ // Timestamp that this dsp should be invalid (in seconds since epoch).
+ // Value 0 (default) means never expire.
+ optional int64 end_time_seconds = 2 [default = 0];
+}
diff --git a/tools/source/published_devices_delta/video/widevine/protos/public/device_security_profile_list.proto b/tools/source/published_devices_delta/video/widevine/protos/public/device_security_profile_list.proto
new file mode 100644
index 0000000..b9b3c67
--- /dev/null
+++ b/tools/source/published_devices_delta/video/widevine/protos/public/device_security_profile_list.proto
@@ -0,0 +1,39 @@
+// Copyright 2020 Google LLC. All rights reserved.
+//
+//
+// Description:
+// Device security profile list object definitions.
+
+syntax = "proto2";
+
+package video_widevine;
+
+import "video/widevine/protos/public/hash_algorithm.proto";
+import "video/widevine/protos/public/security_profile.proto";
+
+option java_outer_classname = "DeviceSecurityProfileListProtos";
+option java_package = "com.google.video.widevine.protos";
+
+// List of DeviceSecurityProfiles. Used to propagate device security profiles to
+// a list.
+message DeviceSecurityProfileList {
+ // POSIX time, in seconds, when the list was created. Required.
+ optional uint64 creation_time_seconds = 1;
+ // A list of DeviceSecurityProfiles.
+ repeated SecurityProfile device_security_profiles = 2;
+}
+
+// TODO(b/169442909): Consider removing the duplicated proto defition.
+// A signed message which contains a serialized DeviceSecurityProfileList and
+// the signature.
+// LINT.IfChange
+message SignedDeviceSecurityProfiles {
+ // Serialized DeviceSecurityProfileList. Required.
+ optional bytes device_security_profiles = 1;
+ // Signature of device_security_profiles. Signed with root
+ // certificate private key using RSASSA-PSS. Required.
+ optional bytes signature = 2;
+ // Optional field that indicates the hash algorithm used in signature scheme.
+ optional HashAlgorithmProto hash_algorithm = 3;
+}
+// LINT.ThenChange(//depot/google3/google/chrome/widevine/contentpartners/v1beta1/device_security_profiles.proto)
diff --git a/tools/source/published_devices_delta/video/widevine/protos/public/device_security_profiles_delta.proto b/tools/source/published_devices_delta/video/widevine/protos/public/device_security_profiles_delta.proto
new file mode 100644
index 0000000..6231508
--- /dev/null
+++ b/tools/source/published_devices_delta/video/widevine/protos/public/device_security_profiles_delta.proto
@@ -0,0 +1,45 @@
+// Copyright 2020 Google LLC. All rights reserved.
+//
+// Description:
+// DeviceSecurityProfilesDelta object definitions.
+
+syntax = "proto2";
+
+package video_widevine;
+
+import "video/widevine/protos/public/security_profile.proto";
+
+option java_outer_classname = "DeviceSecurityProfilesDeltaProtos";
+option java_package = "com.google.video.widevine.protos";
+
+// Represents the delta of two lists of DeviceSecurityProfiles. This message
+// contains a header of creation time for both pieces of DSPs, and also a list
+// of DspDeltas.
+message DeviceSecurityProfilesDelta {
+ // POSIX time, in seconds, show the delta of creation_time_seconds. Optional.
+ message Header {
+ optional uint64 prev_creation_time_seconds = 1;
+ optional uint64 new_creation_time_seconds = 2;
+ }
+
+ message Modified {
+ optional SecurityProfile prev_dsp = 1;
+ optional SecurityProfile new_dsp = 2;
+ }
+
+ // DspDelta contains the content owner name and added/removed/modified fields
+ // for DSPs.
+ message DspDelta {
+ // Content owner who the compared Dsps belongs to.
+ optional string owner = 1;
+ // List of added DeviceSecurityProfiles.
+ repeated SecurityProfile added = 2;
+ // List of removed DeviceSecurityProfiles.
+ repeated SecurityProfile removed = 3;
+ // List of modified DeviceSecurityProfiles.
+ repeated Modified modified = 4;
+ }
+
+ optional Header header = 1;
+ repeated DspDelta dsp_delta = 2;
+}
diff --git a/tools/source/published_devices_delta/video/widevine/protos/public/hash_algorithm.proto b/tools/source/published_devices_delta/video/widevine/protos/public/hash_algorithm.proto
index a0a17ea..47ca34e 100644
--- a/tools/source/published_devices_delta/video/widevine/protos/public/hash_algorithm.proto
+++ b/tools/source/published_devices_delta/video/widevine/protos/public/hash_algorithm.proto
@@ -11,5 +11,6 @@ enum HashAlgorithmProto {
HASH_ALGORITHM_UNSPECIFIED = 0;
HASH_ALGORITHM_SHA_1 = 1;
HASH_ALGORITHM_SHA_256 = 2;
+ HASH_ALGORITHM_SHA_384 = 3;
}
// LINT.ThenChange(//depot/google3/google/chrome/widevine/contentpartners/v1beta1/device_security_profiles.proto)
diff --git a/tools/source/published_devices_delta/video/widevine/protos/public/provisioned_device_info.proto b/tools/source/published_devices_delta/video/widevine/protos/public/provisioned_device_info.proto
index 8415bce..5f3183c 100644
--- a/tools/source/published_devices_delta/video/widevine/protos/public/provisioned_device_info.proto
+++ b/tools/source/published_devices_delta/video/widevine/protos/public/provisioned_device_info.proto
@@ -12,11 +12,12 @@ import "video/widevine/protos/public/device_common.proto";
option java_package = "com.google.video.widevine.protos";
option java_outer_classname = "ProvisionedDeviceInfoProto";
-// MOE:begin_strip
+
// See http://go/go-api-flag.
-// MOE:end_strip
+
// Contains device model information for a provisioned device.
+// Next Id: 12
message ProvisionedDeviceInfo {
enum WvSecurityLevel {
// Defined in Widevine Security Integration Guide for DASH on Android:
@@ -75,4 +76,6 @@ message ProvisionedDeviceInfo {
optional ProvisioningMethod provisioning_method = 9;
// A list of ModelInfo using the same system_id.
repeated DeviceModel model_info = 10;
+ // The platform that the device is using.
+ optional Platform platform = 11;
}
diff --git a/tools/source/published_devices_delta/video/widevine/protos/public/security_profile.proto b/tools/source/published_devices_delta/video/widevine/protos/public/security_profile.proto
new file mode 100644
index 0000000..5a54c75
--- /dev/null
+++ b/tools/source/published_devices_delta/video/widevine/protos/public/security_profile.proto
@@ -0,0 +1,86 @@
+// Copyright 2019 Google LLC. All rights reserved.
+//
+// Definitions of the protocol buffer messages for security profile level.
+
+syntax = "proto2";
+
+package video_widevine;
+
+import "video/widevine/protos/public/device_common.proto";
+import "video/widevine/protos/public/device_security_profile_data.proto";
+
+option java_outer_classname = "SecurityProfileProtos";
+option java_package = "com.google.video.widevine.protos";
+
+
+ // See http://go/go-api-flag.
+
+
+message SecurityProfile {
+ // TODO(hali): Remove this enum and use enum defined in
+ // protos/internal/devcei_data.proto.
+ enum DeviceState {
+ DEVICE_STATE_UNKNOWN = 0;
+ IN_TESTING = 1;
+ RELEASED = 2;
+ DELETED = 3;
+ TEST_ONLY = 4;
+ REVOKED = 5;
+ PRE_RELEASE = 6;
+ }
+
+ message ClientInfo {
+ message ProductInfo {
+ // The 'product_name' as specified in the
+ // ClientIdentification.names_values. Optional.
+ optional string product_name = 1;
+ // The 'build_info' as specified in the
+ // ClientIdentification.names_values. Optional.
+ optional string build_info = 2;
+ // The 'oem_crypto_security_patch_level' as specified in the
+ // ClientIdentification.names_values. Optional.
+ optional string oem_crypto_security_patch_level = 3;
+ // Widevine device platform.
+ optional string platform = 4;
+ }
+ // The 'device_name' as specified in the
+ // ClientIdentification.names_values. Optional.
+ optional string device_name = 1;
+ // Product fields that are specified in the
+ // ClientIdentification.names_values.
+ optional ProductInfo product_info = 2;
+ }
+
+ message DrmInfo {
+ // Make/Model specified by the client.
+ optional DeviceModel request_model_info = 1;
+ // Widevine device system id.
+ optional uint32 system_id = 2;
+ // Output requirements
+ optional OutputRequirement output = 3;
+ // Security requirements
+ optional SecurityRequirement security = 4;
+ // Device status such as RELEASED or REVOKED.
+ optional DeviceState device_model_state = 5;
+ // ClientIdentification.names_values fields.
+ optional ClientInfo client_info = 6;
+ }
+
+ // Required. Widevine security profile name.
+ optional string name = 1;
+ // Optional. Widevine security profile level.
+ optional SecurityProfileLevel level = 2;
+ // Minimum output requirements for this profile.
+ optional OutputRequirement min_output_requirements = 3;
+ // Minimum security requirements for this profile.
+ optional SecurityRequirement min_security_requirements = 4;
+ // Name of content owner who owns this security profile.
+ optional string owner = 5 [default = "Widevine"];
+ // Special handling of devices to override the default capabilities of a
+ // device.
+ repeated DeviceException device_exceptions = 6;
+ // Optional. Control time indicates the timestamps when this profile is
+ // effective and when it is expired. For default DSPs provided by Widevine,
+ // they are always being active and never expiring.
+ optional ControlTime control_time = 7;
+}