summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/acp/Android.mk1
-rw-r--r--tools/droiddoc/templates-sac/assets/images/sac_logo.pngbin1760 -> 2298 bytes
-rw-r--r--tools/droiddoc/templates-sac/assets/images/sac_logo@2x.pngbin0 -> 4934 bytes
-rw-r--r--tools/droiddoc/templates-sac/components/masthead.cs4
-rw-r--r--tools/signapk/SignApk.java6
-rw-r--r--tools/signtos/Android.mk25
-rw-r--r--tools/signtos/SignTos.java314
-rw-r--r--tools/signtos/SignTos.mf1
-rw-r--r--tools/zipalign/Android.mk2
9 files changed, 350 insertions, 3 deletions
diff --git a/tools/acp/Android.mk b/tools/acp/Android.mk
index 33c5567..e819e0c 100644
--- a/tools/acp/Android.mk
+++ b/tools/acp/Android.mk
@@ -21,5 +21,6 @@ LOCAL_STATIC_LIBRARIES := libhost
LOCAL_C_INCLUDES := build/libs/host/include
LOCAL_MODULE := acp
LOCAL_ACP_UNAVAILABLE := true
+LOCAL_CXX_STL := none
include $(BUILD_HOST_EXECUTABLE)
diff --git a/tools/droiddoc/templates-sac/assets/images/sac_logo.png b/tools/droiddoc/templates-sac/assets/images/sac_logo.png
index 6dc126a..4ad113c 100644
--- a/tools/droiddoc/templates-sac/assets/images/sac_logo.png
+++ b/tools/droiddoc/templates-sac/assets/images/sac_logo.png
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/sac_logo@2x.png b/tools/droiddoc/templates-sac/assets/images/sac_logo@2x.png
new file mode 100644
index 0000000..4040f3f
--- /dev/null
+++ b/tools/droiddoc/templates-sac/assets/images/sac_logo@2x.png
Binary files differ
diff --git a/tools/droiddoc/templates-sac/components/masthead.cs b/tools/droiddoc/templates-sac/components/masthead.cs
index fb9b71d..a8618c0 100644
--- a/tools/droiddoc/templates-sac/components/masthead.cs
+++ b/tools/droiddoc/templates-sac/components/masthead.cs
@@ -253,7 +253,9 @@ onkeyup="return search_changed(event, false, '<?cs var:toroot ?>')" />
<div class="wrap" id="header-wrap">
<div class="col-3 saclogo">
<a href="<?cs var:toroot ?>index.html">
- <img src="<?cs var:toroot ?>assets/images/sac_logo.png" width="114" height="16" alt="Android Developers" />
+ <img src="<?cs var:toroot ?>assets/images/sac_logo.png"
+ srcset="<?cs var:toroot ?>assets/images/sac_logo@2x.png 2x"
+ width="123" height="25" alt="Android Developers" />
</a>
</div>
<ul class="nav-x col-9">
diff --git a/tools/signapk/SignApk.java b/tools/signapk/SignApk.java
index e661e50..d020736 100644
--- a/tools/signapk/SignApk.java
+++ b/tools/signapk/SignApk.java
@@ -621,8 +621,12 @@ class SignApk {
this.type = new ASN1ObjectIdentifier(CMSObjectIdentifiers.data.getId());
}
+ /**
+ * This should actually return byte[] or something similar, but nothing
+ * actually checks it currently.
+ */
public Object getContent() {
- throw new UnsupportedOperationException();
+ return this;
}
public ASN1ObjectIdentifier getContentType() {
diff --git a/tools/signtos/Android.mk b/tools/signtos/Android.mk
new file mode 100644
index 0000000..94ab944
--- /dev/null
+++ b/tools/signtos/Android.mk
@@ -0,0 +1,25 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+LOCAL_PATH := $(call my-dir)
+
+# the signtos tool - signs Trusty images
+# ============================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := signtos
+LOCAL_SRC_FILES := SignTos.java
+LOCAL_JAR_MANIFEST := SignTos.mf
+LOCAL_STATIC_JAVA_LIBRARIES := bouncycastle-host bouncycastle-bcpkix-host
+include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tools/signtos/SignTos.java b/tools/signtos/SignTos.java
new file mode 100644
index 0000000..485ad2f
--- /dev/null
+++ b/tools/signtos/SignTos.java
@@ -0,0 +1,314 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.signtos;
+
+import org.bouncycastle.asn1.ASN1InputStream;
+import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.lang.reflect.Constructor;
+import java.security.GeneralSecurityException;
+import java.security.Key;
+import java.security.KeyFactory;
+import java.security.MessageDigest;
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.PublicKey;
+import java.security.Security;
+import java.security.Signature;
+import java.security.interfaces.ECKey;
+import java.security.interfaces.ECPublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.Arrays;
+
+import javax.crypto.Cipher;
+import javax.crypto.EncryptedPrivateKeyInfo;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+
+/**
+ * Signs Trusty images for use with operating systems that support it.
+ */
+public class SignTos {
+ /** Size of the signature footer in bytes. */
+ private static final int SIGNATURE_BLOCK_SIZE = 256;
+
+ /** Current signature version code we use. */
+ private static final int VERSION_CODE = 1;
+
+ /** Size of the header on the file to skip. */
+ private static final int HEADER_SIZE = 512;
+
+ private static BouncyCastleProvider sBouncyCastleProvider;
+
+ /**
+ * Reads the password from stdin and returns it as a string.
+ *
+ * @param keyFile The file containing the private key. Used to prompt the user.
+ */
+ private static String readPassword(File keyFile) {
+ // TODO: use Console.readPassword() when it's available.
+ System.out.print("Enter password for " + keyFile + " (password will not be hidden): ");
+ System.out.flush();
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ try {
+ return stdin.readLine();
+ } catch (IOException ex) {
+ return null;
+ }
+ }
+
+ /**
+ * Decrypt an encrypted PKCS#8 format private key.
+ *
+ * Based on ghstark's post on Aug 6, 2006 at
+ * http://forums.sun.com/thread.jspa?threadID=758133&messageID=4330949
+ *
+ * @param encryptedPrivateKey The raw data of the private key
+ * @param keyFile The file containing the private key
+ */
+ private static PKCS8EncodedKeySpec decryptPrivateKey(byte[] encryptedPrivateKey, File keyFile)
+ throws GeneralSecurityException {
+ EncryptedPrivateKeyInfo epkInfo;
+ try {
+ epkInfo = new EncryptedPrivateKeyInfo(encryptedPrivateKey);
+ } catch (IOException ex) {
+ // Probably not an encrypted key.
+ return null;
+ }
+
+ char[] password = readPassword(keyFile).toCharArray();
+
+ SecretKeyFactory skFactory = SecretKeyFactory.getInstance(epkInfo.getAlgName());
+ Key key = skFactory.generateSecret(new PBEKeySpec(password));
+
+ Cipher cipher = Cipher.getInstance(epkInfo.getAlgName());
+ cipher.init(Cipher.DECRYPT_MODE, key, epkInfo.getAlgParameters());
+
+ try {
+ return epkInfo.getKeySpec(cipher);
+ } catch (InvalidKeySpecException ex) {
+ System.err.println("signapk: Password for " + keyFile + " may be bad.");
+ throw ex;
+ }
+ }
+
+ /** Read a PKCS#8 format private key. */
+ private static PrivateKey readPrivateKey(File file) throws IOException,
+ GeneralSecurityException {
+ DataInputStream input = new DataInputStream(new FileInputStream(file));
+ try {
+ byte[] bytes = new byte[(int) file.length()];
+ input.read(bytes);
+
+ /* Check to see if this is in an EncryptedPrivateKeyInfo structure. */
+ PKCS8EncodedKeySpec spec = decryptPrivateKey(bytes, file);
+ if (spec == null) {
+ spec = new PKCS8EncodedKeySpec(bytes);
+ }
+
+ /*
+ * Now it's in a PKCS#8 PrivateKeyInfo structure. Read its Algorithm
+ * OID and use that to construct a KeyFactory.
+ */
+ ASN1InputStream bIn = new ASN1InputStream(new ByteArrayInputStream(spec.getEncoded()));
+ PrivateKeyInfo pki = PrivateKeyInfo.getInstance(bIn.readObject());
+ String algOid = pki.getPrivateKeyAlgorithm().getAlgorithm().getId();
+
+ return KeyFactory.getInstance(algOid).generatePrivate(spec);
+ } finally {
+ input.close();
+ }
+ }
+
+ /**
+ * Tries to load a JSE Provider by class name. This is for custom PrivateKey
+ * types that might be stored in PKCS#11-like storage.
+ */
+ private static void loadProviderIfNecessary(String providerClassName) {
+ if (providerClassName == null) {
+ return;
+ }
+
+ final Class<?> klass;
+ try {
+ final ClassLoader sysLoader = ClassLoader.getSystemClassLoader();
+ if (sysLoader != null) {
+ klass = sysLoader.loadClass(providerClassName);
+ } else {
+ klass = Class.forName(providerClassName);
+ }
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ System.exit(1);
+ return;
+ }
+
+ Constructor<?> constructor = null;
+ for (Constructor<?> c : klass.getConstructors()) {
+ if (c.getParameterTypes().length == 0) {
+ constructor = c;
+ break;
+ }
+ }
+ if (constructor == null) {
+ System.err.println("No zero-arg constructor found for " + providerClassName);
+ System.exit(1);
+ return;
+ }
+
+ final Object o;
+ try {
+ o = constructor.newInstance();
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ return;
+ }
+ if (!(o instanceof Provider)) {
+ System.err.println("Not a Provider class: " + providerClassName);
+ System.exit(1);
+ }
+
+ Security.insertProviderAt((Provider) o, 1);
+ }
+
+ private static String getSignatureAlgorithm(Key key) {
+ if ("EC".equals(key.getAlgorithm())) {
+ ECKey ecKey = (ECKey) key;
+ int curveSize = ecKey.getParams().getOrder().bitLength();
+ if (curveSize <= 256) {
+ return "SHA256withECDSA";
+ } else if (curveSize <= 384) {
+ return "SHA384withECDSA";
+ } else {
+ return "SHA512withECDSA";
+ }
+ } else {
+ throw new IllegalArgumentException("Unsupported key type " + key.getAlgorithm());
+ }
+ }
+
+ /**
+ * @param inputFilename
+ * @param outputFilename
+ */
+ private static void signWholeFile(InputStream input, OutputStream output, PrivateKey signingKey)
+ throws Exception {
+ Signature sig = Signature.getInstance(getSignatureAlgorithm(signingKey));
+ sig.initSign(signingKey);
+
+ byte[] buffer = new byte[8192];
+
+ /* Skip the header. */
+ int skippedBytes = 0;
+ while (skippedBytes != HEADER_SIZE) {
+ int bytesRead = input.read(buffer, 0, HEADER_SIZE - skippedBytes);
+ output.write(buffer, 0, bytesRead);
+ skippedBytes += bytesRead;
+ }
+
+ int totalBytes = 0;
+ for (;;) {
+ int bytesRead = input.read(buffer);
+ if (bytesRead == -1) {
+ break;
+ }
+ totalBytes += bytesRead;
+ sig.update(buffer, 0, bytesRead);
+ output.write(buffer, 0, bytesRead);
+ }
+
+ byte[] sigBlock = new byte[SIGNATURE_BLOCK_SIZE];
+ sigBlock[0] = VERSION_CODE;
+ sig.sign(sigBlock, 1, sigBlock.length - 1);
+
+ output.write(sigBlock);
+ }
+
+ private static void usage() {
+ System.err.println("Usage: signtos " +
+ "[-providerClass <className>] " +
+ " privatekey.pk8 " +
+ "input.img output.img");
+ System.exit(2);
+ }
+
+ public static void main(String[] args) throws Exception {
+ if (args.length < 3) {
+ usage();
+ }
+
+ String providerClass = null;
+ String providerArg = null;
+
+ int argstart = 0;
+ while (argstart < args.length && args[argstart].startsWith("-")) {
+ if ("-providerClass".equals(args[argstart])) {
+ if (argstart + 1 >= args.length) {
+ usage();
+ }
+ providerClass = args[++argstart];
+ ++argstart;
+ } else {
+ usage();
+ }
+ }
+
+ /*
+ * Should only be "<privatekey> <input> <output>" left.
+ */
+ if (argstart != args.length - 3) {
+ usage();
+ }
+
+ sBouncyCastleProvider = new BouncyCastleProvider();
+ Security.addProvider(sBouncyCastleProvider);
+
+ loadProviderIfNecessary(providerClass);
+
+ String keyFilename = args[args.length - 3];
+ String inputFilename = args[args.length - 2];
+ String outputFilename = args[args.length - 1];
+
+ PrivateKey privateKey = readPrivateKey(new File(keyFilename));
+
+ InputStream input = new BufferedInputStream(new FileInputStream(inputFilename));
+ OutputStream output = new BufferedOutputStream(new FileOutputStream(outputFilename));
+ try {
+ SignTos.signWholeFile(input, output, privateKey);
+ } finally {
+ input.close();
+ output.close();
+ }
+
+ System.out.println("Successfully signed: " + outputFilename);
+ }
+}
diff --git a/tools/signtos/SignTos.mf b/tools/signtos/SignTos.mf
new file mode 100644
index 0000000..d860296
--- /dev/null
+++ b/tools/signtos/SignTos.mf
@@ -0,0 +1 @@
+Main-Class: com.android.signtos.SignTos
diff --git a/tools/zipalign/Android.mk b/tools/zipalign/Android.mk
index 7986798..4194f81 100644
--- a/tools/zipalign/Android.mk
+++ b/tools/zipalign/Android.mk
@@ -26,7 +26,7 @@ ifeq ($(HOST_OS),linux)
LOCAL_LDLIBS += -lrt
endif
-ifneq ($(strip $(USE_MINGW)),)
+ifdef USE_MINGW
LOCAL_STATIC_LIBRARIES += libz
else
LOCAL_LDLIBS += -lz