Make signapk use Conscrypt.

This makes the signapk tool use Conscrypt (where possible) instead of
the platform-default JCA providers and the Bouncy Castle JCA provider.
This speeds up (by 10-30%) APK and OTA update signing because
Conscrypt's crypto primitives are backed by BoringSSL.

Previously, the signapk tool consisted only of the signapk.jar.
Because Conscrypt is backed by native code, signapk now consists of
signapk.jar and crypto_openjdk_jni shared library. This requires that
users of the tool be updated to provide a suitable -Djava.library.path
argument to the Java runtime. This change updates all known users of
the tool inside the Android source tree to do so.

Bug: 26097626
Change-Id: I8411b37d7f771ed99269751a3007dff103083552
This commit is contained in:
Alex Klyubin
2015-12-10 13:38:50 -08:00
parent 6950168f1d
commit 9667b18f23
6 changed files with 34 additions and 14 deletions

View File

@@ -1399,7 +1399,8 @@ OTATOOLS += \
$(HOST_LIBRARY_PATH)/libext2_e2p-host$(HOST_SHLIB_SUFFIX) \ $(HOST_LIBRARY_PATH)/libext2_e2p-host$(HOST_SHLIB_SUFFIX) \
$(HOST_LIBRARY_PATH)/libext2_profile-host$(HOST_SHLIB_SUFFIX) \ $(HOST_LIBRARY_PATH)/libext2_profile-host$(HOST_SHLIB_SUFFIX) \
$(HOST_LIBRARY_PATH)/libext2_quota-host$(HOST_SHLIB_SUFFIX) \ $(HOST_LIBRARY_PATH)/libext2_quota-host$(HOST_SHLIB_SUFFIX) \
$(HOST_LIBRARY_PATH)/libext2_uuid-host$(HOST_SHLIB_SUFFIX) $(HOST_LIBRARY_PATH)/libext2_uuid-host$(HOST_SHLIB_SUFFIX) \
$(HOST_LIBRARY_PATH)/libconscrypt_openjdk_jni$(HOST_SHLIB_SUFFIX)
.PHONY: otatools .PHONY: otatools
otatools: $(OTATOOLS) otatools: $(OTATOOLS)

View File

@@ -453,6 +453,7 @@ AIDL := $(HOST_OUT_EXECUTABLES)/aidl
AAPT := $(HOST_OUT_EXECUTABLES)/aapt AAPT := $(HOST_OUT_EXECUTABLES)/aapt
ZIPALIGN := $(HOST_OUT_EXECUTABLES)/zipalign ZIPALIGN := $(HOST_OUT_EXECUTABLES)/zipalign
SIGNAPK_JAR := $(HOST_OUT_JAVA_LIBRARIES)/signapk$(COMMON_JAVA_PACKAGE_SUFFIX) SIGNAPK_JAR := $(HOST_OUT_JAVA_LIBRARIES)/signapk$(COMMON_JAVA_PACKAGE_SUFFIX)
SIGNAPK_JNI_LIBRARY_PATH := $(HOST_OUT_SHARED_LIBRARIES)
LLVM_RS_CC := $(HOST_OUT_EXECUTABLES)/llvm-rs-cc LLVM_RS_CC := $(HOST_OUT_EXECUTABLES)/llvm-rs-cc
BCC_COMPAT := $(HOST_OUT_EXECUTABLES)/bcc_compat BCC_COMPAT := $(HOST_OUT_EXECUTABLES)/bcc_compat
@@ -469,6 +470,8 @@ AIDL := $(prebuilt_sdk_tools_bin)/aidl
AAPT := $(prebuilt_sdk_tools_bin)/aapt AAPT := $(prebuilt_sdk_tools_bin)/aapt
ZIPALIGN := $(prebuilt_sdk_tools_bin)/zipalign ZIPALIGN := $(prebuilt_sdk_tools_bin)/zipalign
SIGNAPK_JAR := $(prebuilt_sdk_tools)/lib/signapk$(COMMON_JAVA_PACKAGE_SUFFIX) SIGNAPK_JAR := $(prebuilt_sdk_tools)/lib/signapk$(COMMON_JAVA_PACKAGE_SUFFIX)
# Use 64-bit libraries unconditionally because 32-bit JVMs are no longer supported
SIGNAPK_JNI_LIBRARY_PATH := $(prebuilt_sdk_tools)/$(HOST_OS)/lib64
DX := $(prebuilt_sdk_tools)/dx DX := $(prebuilt_sdk_tools)/dx
MAINDEXCLASSES := $(prebuilt_sdk_tools)/mainDexClasses MAINDEXCLASSES := $(prebuilt_sdk_tools)/mainDexClasses

View File

@@ -2165,7 +2165,7 @@ endef
# #
define sign-package define sign-package
$(hide) mv $@ $@.unsigned $(hide) mv $@ $@.unsigned
$(hide) java -jar $(SIGNAPK_JAR) \ $(hide) java -Djava.library.path=$(SIGNAPK_JNI_LIBRARY_PATH) -jar $(SIGNAPK_JAR) \
$(PRIVATE_CERTIFICATE) $(PRIVATE_PRIVATE_KEY) \ $(PRIVATE_CERTIFICATE) $(PRIVATE_PRIVATE_KEY) \
$(PRIVATE_ADDITIONAL_CERTIFICATES) $@.unsigned $@.signed $(PRIVATE_ADDITIONAL_CERTIFICATES) $@.unsigned $@.signed
$(hide) mv $@.signed $@ $(hide) mv $@.signed $@

View File

@@ -44,6 +44,7 @@ class Options(object):
self.search_path = platform_search_path.get(sys.platform, None) self.search_path = platform_search_path.get(sys.platform, None)
self.signapk_path = "framework/signapk.jar" # Relative to search_path self.signapk_path = "framework/signapk.jar" # Relative to search_path
self.signapk_shared_library_path = "lib64" # Relative to search_path
self.extra_signapk_args = [] self.extra_signapk_args = []
self.java_path = "java" # Use the one on the path by default. self.java_path = "java" # Use the one on the path by default.
self.java_args = "-Xmx2048m" # JVM Args self.java_args = "-Xmx2048m" # JVM Args
@@ -598,7 +599,12 @@ def SignFile(input_name, output_name, key, password, whole_file=False):
zip file. zip file.
""" """
cmd = [OPTIONS.java_path, OPTIONS.java_args, "-jar", java_library_path = os.path.join(
OPTIONS.search_path, OPTIONS.signapk_shared_library_path)
cmd = [OPTIONS.java_path, OPTIONS.java_args,
"-Djava.library.path=" + java_library_path,
"-jar",
os.path.join(OPTIONS.search_path, OPTIONS.signapk_path)] os.path.join(OPTIONS.search_path, OPTIONS.signapk_path)]
cmd.extend(OPTIONS.extra_signapk_args) cmd.extend(OPTIONS.extra_signapk_args)
if whole_file: if whole_file:
@@ -718,7 +724,8 @@ def ParseOptions(argv,
try: try:
opts, args = getopt.getopt( opts, args = getopt.getopt(
argv, "hvp:s:x:" + extra_opts, argv, "hvp:s:x:" + extra_opts,
["help", "verbose", "path=", "signapk_path=", "extra_signapk_args=", ["help", "verbose", "path=", "signapk_path=",
"signapk_shared_library_path=", "extra_signapk_args=",
"java_path=", "java_args=", "public_key_suffix=", "java_path=", "java_args=", "public_key_suffix=",
"private_key_suffix=", "boot_signer_path=", "boot_signer_args=", "private_key_suffix=", "boot_signer_path=", "boot_signer_args=",
"verity_signer_path=", "verity_signer_args=", "device_specific=", "verity_signer_path=", "verity_signer_args=", "device_specific=",
@@ -739,6 +746,8 @@ def ParseOptions(argv,
OPTIONS.search_path = a OPTIONS.search_path = a
elif o in ("--signapk_path",): elif o in ("--signapk_path",):
OPTIONS.signapk_path = a OPTIONS.signapk_path = a
elif o in ("--signapk_shared_library_path",):
OPTIONS.signapk_shared_library_path = a
elif o in ("--extra_signapk_args",): elif o in ("--extra_signapk_args",):
OPTIONS.extra_signapk_args = shlex.split(a) OPTIONS.extra_signapk_args = shlex.split(a)
elif o in ("--java_path",): elif o in ("--java_path",):

View File

@@ -21,11 +21,16 @@ include $(CLEAR_VARS)
LOCAL_MODULE := signapk LOCAL_MODULE := signapk
LOCAL_SRC_FILES := SignApk.java LOCAL_SRC_FILES := SignApk.java
LOCAL_JAR_MANIFEST := SignApk.mf LOCAL_JAR_MANIFEST := SignApk.mf
LOCAL_STATIC_JAVA_LIBRARIES := bouncycastle-host bouncycastle-bcpkix-host LOCAL_STATIC_JAVA_LIBRARIES := bouncycastle-host bouncycastle-bcpkix-host conscrypt-host
LOCAL_REQUIRED_MODULES := libconscrypt_openjdk_jni
include $(BUILD_HOST_JAVA_LIBRARY) include $(BUILD_HOST_JAVA_LIBRARY)
ifeq ($(TARGET_BUILD_APPS),) ifeq ($(TARGET_BUILD_APPS),)
# The post-build signing tools need signapk.jar, but we don't # The post-build signing tools need signapk.jar and its shared libraries,
# need this if we're just doing unbundled apps. # but we don't need this if we're just doing unbundled apps.
$(call dist-for-goals,droidcore,$(LOCAL_INSTALLED_MODULE)) my_dist_files := $(LOCAL_INSTALLED_MODULE) \
$(HOST_OUT_SHARED_LIBRARIES)/libconscrypt_openjdk_jni$(HOST_SHLIB_SUFFIX)
$(call dist-for-goals,droidcore,$(my_dist_files))
my_dist_files :=
endif endif

View File

@@ -34,6 +34,7 @@ import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.bouncycastle.util.encoders.Base64; import org.bouncycastle.util.encoders.Base64;
import org.conscrypt.OpenSSLProvider;
import java.io.Console; import java.io.Console;
import java.io.BufferedReader; import java.io.BufferedReader;
@@ -110,8 +111,6 @@ class SignApk {
private static final String OTACERT_NAME = "META-INF/com/android/otacert"; private static final String OTACERT_NAME = "META-INF/com/android/otacert";
private static Provider sBouncyCastleProvider;
// bitmasks for which hash algorithms we need the manifest to include. // bitmasks for which hash algorithms we need the manifest to include.
private static final int USE_SHA1 = 1; private static final int USE_SHA1 = 1;
private static final int USE_SHA256 = 2; private static final int USE_SHA256 = 2;
@@ -451,12 +450,10 @@ class SignApk {
CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
ContentSigner signer = new JcaContentSignerBuilder(getSignatureAlgorithm(publicKey)) ContentSigner signer = new JcaContentSignerBuilder(getSignatureAlgorithm(publicKey))
.setProvider(sBouncyCastleProvider)
.build(privateKey); .build(privateKey);
gen.addSignerInfoGenerator( gen.addSignerInfoGenerator(
new JcaSignerInfoGeneratorBuilder( new JcaSignerInfoGeneratorBuilder(
new JcaDigestCalculatorProviderBuilder() new JcaDigestCalculatorProviderBuilder()
.setProvider(sBouncyCastleProvider)
.build()) .build())
.setDirectSignature(true) .setDirectSignature(true)
.build(signer, publicKey)); .build(signer, publicKey));
@@ -879,8 +876,13 @@ class SignApk {
public static void main(String[] args) { public static void main(String[] args) {
if (args.length < 4) usage(); if (args.length < 4) usage();
sBouncyCastleProvider = new BouncyCastleProvider(); // Install Conscrypt as the highest-priority provider. Its crypto primitives are faster than
Security.addProvider(sBouncyCastleProvider); // the standard or Bouncy Castle ones.
Security.insertProviderAt(new OpenSSLProvider(), 1);
// Install Bouncy Castle (as the lowest-priority provider) because Conscrypt does not offer
// DSA which may still be needed.
// TODO: Stop installing Bouncy Castle provider once DSA is no longer needed.
Security.addProvider(new BouncyCastleProvider());
boolean signWholeFile = false; boolean signWholeFile = false;
String providerClass = null; String providerClass = null;