From 9667b18f2300e4bf0f33d3aef51d2f48bcb6778b Mon Sep 17 00:00:00 2001 From: Alex Klyubin Date: Thu, 10 Dec 2015 13:38:50 -0800 Subject: [PATCH] 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 --- core/Makefile | 3 ++- core/config.mk | 3 +++ core/definitions.mk | 2 +- tools/releasetools/common.py | 13 +++++++++++-- tools/signapk/Android.mk | 13 +++++++++---- tools/signapk/SignApk.java | 14 ++++++++------ 6 files changed, 34 insertions(+), 14 deletions(-) diff --git a/core/Makefile b/core/Makefile index e1b1c05f2..301e8b295 100644 --- a/core/Makefile +++ b/core/Makefile @@ -1399,7 +1399,8 @@ OTATOOLS += \ $(HOST_LIBRARY_PATH)/libext2_e2p-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_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 otatools: $(OTATOOLS) diff --git a/core/config.mk b/core/config.mk index 597b0d7e2..450c06c22 100644 --- a/core/config.mk +++ b/core/config.mk @@ -453,6 +453,7 @@ AIDL := $(HOST_OUT_EXECUTABLES)/aidl AAPT := $(HOST_OUT_EXECUTABLES)/aapt ZIPALIGN := $(HOST_OUT_EXECUTABLES)/zipalign 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 BCC_COMPAT := $(HOST_OUT_EXECUTABLES)/bcc_compat @@ -469,6 +470,8 @@ AIDL := $(prebuilt_sdk_tools_bin)/aidl AAPT := $(prebuilt_sdk_tools_bin)/aapt ZIPALIGN := $(prebuilt_sdk_tools_bin)/zipalign 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 MAINDEXCLASSES := $(prebuilt_sdk_tools)/mainDexClasses diff --git a/core/definitions.mk b/core/definitions.mk index 19365ca21..5119d6586 100644 --- a/core/definitions.mk +++ b/core/definitions.mk @@ -2165,7 +2165,7 @@ endef # define sign-package $(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_ADDITIONAL_CERTIFICATES) $@.unsigned $@.signed $(hide) mv $@.signed $@ diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py index 3b2ce7292..ee0cdf97a 100644 --- a/tools/releasetools/common.py +++ b/tools/releasetools/common.py @@ -44,6 +44,7 @@ class Options(object): self.search_path = platform_search_path.get(sys.platform, None) 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.java_path = "java" # Use the one on the path by default. self.java_args = "-Xmx2048m" # JVM Args @@ -598,7 +599,12 @@ def SignFile(input_name, output_name, key, password, whole_file=False): 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)] cmd.extend(OPTIONS.extra_signapk_args) if whole_file: @@ -718,7 +724,8 @@ def ParseOptions(argv, try: opts, args = getopt.getopt( 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=", "private_key_suffix=", "boot_signer_path=", "boot_signer_args=", "verity_signer_path=", "verity_signer_args=", "device_specific=", @@ -739,6 +746,8 @@ def ParseOptions(argv, OPTIONS.search_path = a elif o in ("--signapk_path",): OPTIONS.signapk_path = a + elif o in ("--signapk_shared_library_path",): + OPTIONS.signapk_shared_library_path = a elif o in ("--extra_signapk_args",): OPTIONS.extra_signapk_args = shlex.split(a) elif o in ("--java_path",): diff --git a/tools/signapk/Android.mk b/tools/signapk/Android.mk index 620ccb1f4..da1501bc0 100644 --- a/tools/signapk/Android.mk +++ b/tools/signapk/Android.mk @@ -21,11 +21,16 @@ include $(CLEAR_VARS) LOCAL_MODULE := signapk LOCAL_SRC_FILES := SignApk.java 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) ifeq ($(TARGET_BUILD_APPS),) -# The post-build signing tools need signapk.jar, but we don't -# need this if we're just doing unbundled apps. -$(call dist-for-goals,droidcore,$(LOCAL_INSTALLED_MODULE)) +# The post-build signing tools need signapk.jar and its shared libraries, +# but we don't need this if we're just doing unbundled apps. +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 diff --git a/tools/signapk/SignApk.java b/tools/signapk/SignApk.java index 397f8cca5..5afb8d106 100644 --- a/tools/signapk/SignApk.java +++ b/tools/signapk/SignApk.java @@ -34,6 +34,7 @@ import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; import org.bouncycastle.util.encoders.Base64; +import org.conscrypt.OpenSSLProvider; import java.io.Console; import java.io.BufferedReader; @@ -110,8 +111,6 @@ class SignApk { 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. private static final int USE_SHA1 = 1; private static final int USE_SHA256 = 2; @@ -451,12 +450,10 @@ class SignApk { CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); ContentSigner signer = new JcaContentSignerBuilder(getSignatureAlgorithm(publicKey)) - .setProvider(sBouncyCastleProvider) .build(privateKey); gen.addSignerInfoGenerator( new JcaSignerInfoGeneratorBuilder( new JcaDigestCalculatorProviderBuilder() - .setProvider(sBouncyCastleProvider) .build()) .setDirectSignature(true) .build(signer, publicKey)); @@ -879,8 +876,13 @@ class SignApk { public static void main(String[] args) { if (args.length < 4) usage(); - sBouncyCastleProvider = new BouncyCastleProvider(); - Security.addProvider(sBouncyCastleProvider); + // Install Conscrypt as the highest-priority provider. Its crypto primitives are faster than + // 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; String providerClass = null;