Tools release: 1.2.0
This commit is contained in:
BIN
tools/bin/published_devices_client/published_devices_cli_deploy.jar
Executable file → Normal file
BIN
tools/bin/published_devices_client/published_devices_cli_deploy.jar
Executable file → Normal file
Binary file not shown.
BIN
tools/bin/published_devices_delta/published_devices_delta_deploy.jar
Executable file → Normal file
BIN
tools/bin/published_devices_delta/published_devices_delta_deploy.jar
Executable file → Normal file
Binary file not shown.
@@ -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()
|
||||
|
||||
@@ -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"],
|
||||
)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
0
tools/source/published_devices_client/google/chrome/widevine/contentpartners/v1beta1/published_devices.proto
Executable file → Normal file
0
tools/source/published_devices_client/google/chrome/widevine/contentpartners/v1beta1/published_devices.proto
Executable file → Normal file
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -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.
|
||||
* <p>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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -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",
|
||||
|
||||
@@ -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.
|
||||
* <p>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.
|
||||
* <p>Default Widevine Service API path: widevine.googleapis.com.
|
||||
*
|
||||
* To build:
|
||||
* Bazel build java/com/google/video/widevine/jts/tools:published_devices_client_deploy.jar
|
||||
* <p>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 \
|
||||
* <p>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<String> DATA_TYPE_LIST =
|
||||
ImmutableList.of(PUBLISHED_DEVICES, DSP);
|
||||
|
||||
private WvPLCASProxyEnvironment environment = null;
|
||||
private PublishedDevicesProvider publishedDevices = null;
|
||||
private String serviceCertPath = null;
|
||||
@@ -47,39 +52,65 @@ public final class PublishedDevicesCli {
|
||||
static class Flags {
|
||||
private Flags() {}
|
||||
|
||||
@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_cert_path", description = "Path to service certificate")
|
||||
private String serviceCertPath = "";
|
||||
|
||||
@Parameter(names = "-service_private_key_path",
|
||||
@Parameter(
|
||||
names = "-service_private_key_path",
|
||||
description = "Path to private key file needed to decrypt service certificate")
|
||||
private String servicePrivateKeyPath = "";
|
||||
|
||||
@Parameter(names = "-service_private_key_passphrase",
|
||||
@Parameter(
|
||||
names = "-service_private_key_passphrase",
|
||||
description = "Passphrase needed to decrypt the private key")
|
||||
private String servicePrivateKeyPassphrase = "";
|
||||
|
||||
@Parameter(names = "-service_account_path",
|
||||
@Parameter(
|
||||
names = "-service_account_path",
|
||||
description = "Path to a GCP Service Account json file")
|
||||
private String serviceAccountPath = "";
|
||||
|
||||
@Parameter(names = "-api_service_path",
|
||||
@Parameter(
|
||||
names = "-api_service_path",
|
||||
description = "Optional. Path to a Widevine API service.")
|
||||
private String apiServicePath = "widevine.googleapis.com";
|
||||
|
||||
@Parameter(names = "-s",
|
||||
description = "Save PublishedDevices file path.")
|
||||
@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;
|
||||
// Construct PublishedDevicesProvider to obtain PUBLISHED_DEVICES or DSPs.
|
||||
if (dataType.equals(PUBLISHED_DEVICES)) {
|
||||
initializeWvplEnvironment();
|
||||
publishedDevices = new PublishedDevicesProvider(
|
||||
environment, serviceAccountPath, apiServicePath);
|
||||
}
|
||||
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(
|
||||
// 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.apiServicePath,
|
||||
flags.provider);
|
||||
if (flags.dataType.equals(PUBLISHED_DEVICES)) {
|
||||
PublishedDevices publishedDevices = devices.getPublishedDevices();
|
||||
if (flags.saveFilePath != null) {
|
||||
savePublishedDevicesDataToFile(flags.saveFilePath, publishedDevices);
|
||||
saveByteArrayToFile(flags.saveFilePath, publishedDevices.toByteArray());
|
||||
}
|
||||
} else {
|
||||
SignedDeviceSecurityProfiles signedDeviceSecurityProfiles =
|
||||
devices.getSignedDeviceSecurityProfiles();
|
||||
if (flags.saveFilePath != null) {
|
||||
saveByteArrayToFile(flags.saveFilePath, signedDeviceSecurityProfiles.toByteArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"],
|
||||
)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
0
tools/source/published_devices_delta/google/chrome/widevine/contentpartners/v1beta1/published_devices.proto
Executable file → Normal file
0
tools/source/published_devices_delta/google/chrome/widevine/contentpartners/v1beta1/published_devices.proto
Executable file → Normal file
@@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -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<SecurityProfile> dspAddedList = new ArrayList<>();
|
||||
private final List<SecurityProfile> dspRemovedList = new ArrayList<>();
|
||||
private final List<Modified> 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<SecurityProfile> getAddedDeviceSecurityProfiles() {
|
||||
return dspAddedList;
|
||||
}
|
||||
|
||||
/** Returns a list of removed DSPs from DeviceSecurityProfilesDelta for all content owners. */
|
||||
public List<SecurityProfile> getRemovedDeviceSecurityProfiles() {
|
||||
return dspRemovedList;
|
||||
}
|
||||
|
||||
/** Returns a list of modified DSPs from DeviceSecurityProfilesDelta for all content owners. */
|
||||
public List<Modified> 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<String, List<SecurityProfile>> originalDspMap = initializeDspMap(originalDspList);
|
||||
Map<String, List<SecurityProfile>> newDspMap = initializeDspMap(newDspList);
|
||||
// Create a map to store DspDelta.Builder. Key is content owner name, value is dspDelta for each
|
||||
// owner.
|
||||
Map<String, DspDelta.Builder> 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<String, List<SecurityProfile>> initializeDspMap(
|
||||
DeviceSecurityProfileList dspList) {
|
||||
Map<String, List<SecurityProfile>> 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<String, DspDelta.Builder> calculateDspDelta(
|
||||
Map<String, List<SecurityProfile>> originalDspMap,
|
||||
Map<String, List<SecurityProfile>> newDspMap) {
|
||||
Map<String, DspDelta.Builder> dspDeltaBuilderMap = new LinkedHashMap<>();
|
||||
for (String owner : newDspMap.keySet()) {
|
||||
// Record already-processed original dsp set.
|
||||
Set<SecurityProfile> 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;
|
||||
}
|
||||
}
|
||||
@@ -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<String, List<SecurityProfile>> dspMap = new LinkedHashMap<>();
|
||||
private Set<String> 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<SecurityProfile>} a list of DSPs for specific content owner. Return null if
|
||||
* none of the DSPs belongs to the specific content owner.
|
||||
*/
|
||||
public List<SecurityProfile> getDeviceSecurityProfiles(String owner) {
|
||||
if (isNullOrEmpty(owner)) {
|
||||
return null;
|
||||
}
|
||||
return dspMap.get(owner);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the content owner list from the DSPs.
|
||||
*
|
||||
* @return {@link List<String>} a list of content owners shown in the DSPs. Return null if owner
|
||||
* set is null or empty.
|
||||
*/
|
||||
public List<String> 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<SecurityProfile> 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();
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
*
|
||||
* <p>Provides a command line tool to get the diff between two PublishedDevices Proto, parse the
|
||||
* PublishedDevices and PublishedDevicesDelta.
|
||||
* <p>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.
|
||||
*
|
||||
* <p>To build: Bazel build tools:published_devices_delta_deploy.jar
|
||||
*
|
||||
* <p>To run: java -jar /path/to/published_devices_lib_deploy.jar -new_published_devices_path path
|
||||
* -original_published_devices_path path -print
|
||||
* <p>Commands for PublishedDevices:
|
||||
*
|
||||
* <p>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
|
||||
* <p>To run: java -jar /path/to/published_devices_lib_deploy.jar -new_file_path path
|
||||
* -original_file_path path -print
|
||||
*
|
||||
* <p>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
|
||||
*
|
||||
* <p>To run: java -jar /path/to/published_devices_lib_deploy.jar -query path -system_id 100
|
||||
*
|
||||
* <p>Commands for DeviceSecurityProfiles:
|
||||
*
|
||||
* <p>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
|
||||
*
|
||||
* <p>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
|
||||
*
|
||||
* <p>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
|
||||
*
|
||||
* <p>Get DSPs for specific owner: java -jar /path/to/published_devices_lib_deploy.jar -data_type
|
||||
* DSP -query path -content_owner owner_name
|
||||
*
|
||||
* <p>Get owner list from one retrieved dsp list: java -jar
|
||||
* /path/to/published_devices_lib_deploy.jar -data_type DSP -query path -get_owners
|
||||
*
|
||||
* <p>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<String> 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) {
|
||||
// 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) {
|
||||
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);
|
||||
queryPublishedDevices(flags);
|
||||
}
|
||||
System.out.println(deviceCertificateStatus);
|
||||
// TODO(b/160253740): Add ProvisonedStatus, ProvisionedDeviceInfo and function.
|
||||
} else if (flags.dataType.equals(DSP)) {
|
||||
if (flags.newFilePath != null && flags.originalFilePath != null) {
|
||||
parseDeviceSecurityProfilesDelta(flags);
|
||||
} else if (flags.query != null) {
|
||||
queryDeviceSecurityProfiles(flags);
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
} 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<SecurityProfile> 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<String> 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,17 +383,21 @@ 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;
|
||||
}
|
||||
byte[] serializedList;
|
||||
if (dataType.equals(PUBLISHED_DEVICES)) {
|
||||
String requestBody = "";
|
||||
try {
|
||||
// Parse both PublishedDevices v1 output.
|
||||
@@ -198,9 +407,11 @@ final class PublishedDevicesMain {
|
||||
// Parse both PublishedDevices v2 output.
|
||||
requestBody = result;
|
||||
}
|
||||
byte[] serializedDCSL = base64Decode(requestBody);
|
||||
|
||||
return serializedDCSL;
|
||||
serializedList = base64Decode(requestBody);
|
||||
} else {
|
||||
serializedList = base64Decode(result);
|
||||
}
|
||||
return serializedList;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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"],
|
||||
)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
@@ -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)
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user