summaryrefslogtreecommitdiffstats
path: root/tools/signapk
diff options
context:
space:
mode:
authorDoug Zongker <dougz@android.com>2012-05-11 09:20:50 -0700
committerDoug Zongker <dougz@android.com>2012-05-11 09:22:29 -0700
commit7bb042317ab4df86b9962f30399c7728e8b84599 (patch)
treeb87cdb532b45b4696164d671fbd372448db61335 /tools/signapk
parent3742983d3becfa141557d9f5b461c8d39e9d31c0 (diff)
downloadbuild-7bb042317ab4df86b9962f30399c7728e8b84599.zip
build-7bb042317ab4df86b9962f30399c7728e8b84599.tar.gz
build-7bb042317ab4df86b9962f30399c7728e8b84599.tar.bz2
add copy of public cert used for signing to OTA packages
When signing a file with -w (ie, an OTA package), add the file META-INF/com/android/otacert, which is a copy of the public key certificate. While this can be extracted from the CERT.RSA file, having a copy of it more easily accessible makes it easier to write tools. Bug: 6477365 Change-Id: I8cdb19536eca9a223c2b954e3f8ea0d9f3f86f02
Diffstat (limited to 'tools/signapk')
-rw-r--r--tools/signapk/SignApk.java53
1 files changed, 48 insertions, 5 deletions
diff --git a/tools/signapk/SignApk.java b/tools/signapk/SignApk.java
index c4d73c8..d8d9bf1 100644
--- a/tools/signapk/SignApk.java
+++ b/tools/signapk/SignApk.java
@@ -76,6 +76,8 @@ class SignApk {
private static final String CERT_SF_NAME = "META-INF/CERT.SF";
private static final String CERT_RSA_NAME = "META-INF/CERT.RSA";
+ private static final String OTACERT_NAME = "META-INF/com/android/otacert";
+
// Files matching this pattern are not copied to the output.
private static Pattern stripPattern =
Pattern.compile("^META-INF/(.*)[.](SF|RSA|DSA)$");
@@ -199,6 +201,7 @@ class SignApk {
String name = entry.getName();
if (!entry.isDirectory() && !name.equals(JarFile.MANIFEST_NAME) &&
!name.equals(CERT_SF_NAME) && !name.equals(CERT_RSA_NAME) &&
+ !name.equals(OTACERT_NAME) &&
(stripPattern == null ||
!stripPattern.matcher(name).matches())) {
InputStream data = jar.getInputStream(entry);
@@ -217,6 +220,39 @@ class SignApk {
return output;
}
+ /**
+ * Add a copy of the public key to the archive; this should
+ * exactly match one of the files in
+ * /system/etc/security/otacerts.zip on the device. (The same
+ * cert can be extracted from the CERT.RSA file but this is much
+ * easier to get at.)
+ */
+ private static void addOtacert(JarOutputStream outputJar,
+ File publicKeyFile,
+ long timestamp,
+ Manifest manifest)
+ throws IOException, GeneralSecurityException {
+ BASE64Encoder base64 = new BASE64Encoder();
+ MessageDigest md = MessageDigest.getInstance("SHA1");
+
+ JarEntry je = new JarEntry(OTACERT_NAME);
+ je.setTime(timestamp);
+ outputJar.putNextEntry(je);
+ FileInputStream input = new FileInputStream(publicKeyFile);
+ byte[] b = new byte[4096];
+ int read;
+ while ((read = input.read(b)) != -1) {
+ outputJar.write(b, 0, read);
+ md.update(b, 0, read);
+ }
+ input.close();
+
+ Attributes attr = new Attributes();
+ attr.putValue("SHA1-Digest", base64.encode(md.digest()));
+ manifest.getEntries().put(OTACERT_NAME, attr);
+ }
+
+
/** Write to another stream and also feed it to the Signature object. */
private static class SignatureOutputStream extends FilterOutputStream {
private Signature mSignature;
@@ -445,7 +481,8 @@ class SignApk {
FileOutputStream outputFile = null;
try {
- X509Certificate publicKey = readPublicKey(new File(args[argstart+0]));
+ File publicKeyFile = new File(args[argstart+0]);
+ X509Certificate publicKey = readPublicKey(publicKeyFile);
// Assume the certificate is valid for at least an hour.
long timestamp = publicKey.getNotBefore().getTime() + 3600L * 1000;
@@ -464,8 +501,17 @@ class SignApk {
JarEntry je;
- // MANIFEST.MF
Manifest manifest = addDigestsToManifest(inputJar);
+
+ // Everything else
+ copyFiles(manifest, inputJar, outputJar, timestamp);
+
+ // otacert
+ if (signWholeFile) {
+ addOtacert(outputJar, publicKeyFile, timestamp, manifest);
+ }
+
+ // MANIFEST.MF
je = new JarEntry(JarFile.MANIFEST_NAME);
je.setTime(timestamp);
outputJar.putNextEntry(je);
@@ -486,9 +532,6 @@ class SignApk {
outputJar.putNextEntry(je);
writeSignatureBlock(signature, publicKey, outputJar);
- // Everything else
- copyFiles(manifest, inputJar, outputJar, timestamp);
-
outputJar.close();
outputJar = null;
outputStream.flush();