Merge "No need to JAR-sign OTA update packages."

am: 094caf99aa

* commit '094caf99aab48c7ef62fd635503a0c70c18ecfde':
  No need to JAR-sign OTA update packages.

Change-Id: I0a0e73cc5f64ba20600c30b9f304b0ff06705693
This commit is contained in:
Alex Klyubin
2016-05-16 17:18:20 +00:00
committed by android-build-merger

View File

@@ -200,10 +200,10 @@ class SignApk {
} }
} }
// Files matching this pattern are not copied to the output. /* Files matching this pattern are not copied to the output. */
private static Pattern stripPattern = private static final Pattern STRIP_PATTERN =
Pattern.compile("^(META-INF/((.*)[.](SF|RSA|DSA|EC)|com/android/otacert))|(" + Pattern.compile("^(META-INF/((.*)[.](SF|RSA|DSA|EC)|com/android/otacert))|("
Pattern.quote(JarFile.MANIFEST_NAME) + ")$"); + Pattern.quote(JarFile.MANIFEST_NAME) + ")$");
private static X509Certificate readPublicKey(File file) private static X509Certificate readPublicKey(File file)
throws IOException, GeneralSecurityException { throws IOException, GeneralSecurityException {
@@ -313,8 +313,9 @@ class SignApk {
* Add the hash(es) of every file to the manifest, creating it if * Add the hash(es) of every file to the manifest, creating it if
* necessary. * necessary.
*/ */
private static Manifest addDigestsToManifest(JarFile jar, int hashes) private static Manifest addDigestsToManifest(
throws IOException, GeneralSecurityException { JarFile jar, Pattern ignoredFilenamePattern, int hashes)
throws IOException, GeneralSecurityException {
Manifest input = jar.getManifest(); Manifest input = jar.getManifest();
Manifest output = new Manifest(); Manifest output = new Manifest();
Attributes main = output.getMainAttributes(); Attributes main = output.getMainAttributes();
@@ -350,8 +351,9 @@ class SignApk {
for (JarEntry entry: byName.values()) { for (JarEntry entry: byName.values()) {
String name = entry.getName(); String name = entry.getName();
if (!entry.isDirectory() && if (!entry.isDirectory()
(stripPattern == null || !stripPattern.matcher(name).matches())) { && (ignoredFilenamePattern == null
|| !ignoredFilenamePattern.matcher(name).matches())) {
InputStream data = jar.getInputStream(entry); InputStream data = jar.getInputStream(entry);
while ((num = data.read(buffer)) > 0) { while ((num = data.read(buffer)) > 0) {
if (md_sha1 != null) md_sha1.update(buffer, 0, num); if (md_sha1 != null) md_sha1.update(buffer, 0, num);
@@ -394,16 +396,13 @@ class SignApk {
* Add a copy of the public key to the archive; this should * Add a copy of the public key to the archive; this should
* exactly match one of the files in * exactly match one of the files in
* /system/etc/security/otacerts.zip on the device. (The same * /system/etc/security/otacerts.zip on the device. (The same
* cert can be extracted from the CERT.RSA file but this is much * cert can be extracted from the OTA update package's signature
* easier to get at.) * block but this is much easier to get at.)
*/ */
private static void addOtacert(JarOutputStream outputJar, private static void addOtacert(JarOutputStream outputJar,
File publicKeyFile, File publicKeyFile,
long timestamp, long timestamp)
Manifest manifest,
int hash)
throws IOException, GeneralSecurityException { throws IOException, GeneralSecurityException {
MessageDigest md = MessageDigest.getInstance(hash == USE_SHA1 ? "SHA1" : "SHA256");
JarEntry je = new JarEntry(OTACERT_NAME); JarEntry je = new JarEntry(OTACERT_NAME);
je.setTime(timestamp); je.setTime(timestamp);
@@ -413,14 +412,8 @@ class SignApk {
int read; int read;
while ((read = input.read(b)) != -1) { while ((read = input.read(b)) != -1) {
outputJar.write(b, 0, read); outputJar.write(b, 0, read);
md.update(b, 0, read);
} }
input.close(); input.close();
Attributes attr = new Attributes();
attr.putValue(hash == USE_SHA1 ? "SHA1-Digest" : "SHA-256-Digest",
new String(Base64.encode(md.digest()), "ASCII"));
manifest.getEntries().put(OTACERT_NAME, attr);
} }
@@ -545,18 +538,31 @@ class SignApk {
} }
/** /**
* Copy all the files in a manifest from input to output. We set * Copy all JAR entries from input to output. We set the modification times in the output to a
* the modification times in the output to a fixed time, so as to * fixed time, so as to reduce variation in the output file and make incremental OTAs more
* reduce variation in the output file and make incremental OTAs * efficient.
* more efficient.
*/ */
private static void copyFiles(Manifest manifest, JarFile in, JarOutputStream out, private static void copyFiles(JarFile in,
long timestamp, int defaultAlignment) throws IOException { Pattern ignoredFilenamePattern,
JarOutputStream out,
long timestamp,
int defaultAlignment) throws IOException {
byte[] buffer = new byte[4096]; byte[] buffer = new byte[4096];
int num; int num;
Map<String, Attributes> entries = manifest.getEntries(); ArrayList<String> names = new ArrayList<String>();
ArrayList<String> names = new ArrayList<String>(entries.keySet()); for (Enumeration<JarEntry> e = in.entries(); e.hasMoreElements();) {
JarEntry entry = e.nextElement();
if (entry.isDirectory()) {
continue;
}
String entryName = entry.getName();
if ((ignoredFilenamePattern != null)
&& (ignoredFilenamePattern.matcher(entryName).matches())) {
continue;
}
names.add(entryName);
}
Collections.sort(names); Collections.sort(names);
boolean firstEntry = true; boolean firstEntry = true;
@@ -757,17 +763,8 @@ class SignApk {
signer = new WholeFileSignerOutputStream(out, outputStream); signer = new WholeFileSignerOutputStream(out, outputStream);
JarOutputStream outputJar = new JarOutputStream(signer); JarOutputStream outputJar = new JarOutputStream(signer);
Manifest manifest = addDigestsToManifest(inputJar, hash); copyFiles(inputJar, STRIP_PATTERN, outputJar, timestamp, 0);
copyFiles(manifest, inputJar, outputJar, timestamp, 0); addOtacert(outputJar, publicKeyFile, timestamp);
addOtacert(outputJar, publicKeyFile, timestamp, manifest, hash);
signFile(manifest,
new X509Certificate[]{ publicKey },
new PrivateKey[]{ privateKey },
new int[] { hash },
timestamp,
false, // Don't sign using APK Signature Scheme v2
outputJar);
signer.notifyClosing(); signer.notifyClosing();
outputJar.close(); outputJar.close();
@@ -1156,8 +1153,9 @@ class SignApk {
v1DigestAlgorithm[i] = getV1DigestAlgorithmForApk(publicKey[i], minSdkVersion); v1DigestAlgorithm[i] = getV1DigestAlgorithmForApk(publicKey[i], minSdkVersion);
v1DigestAlgorithmBitSet |= v1DigestAlgorithm[i]; v1DigestAlgorithmBitSet |= v1DigestAlgorithm[i];
} }
Manifest manifest = addDigestsToManifest(inputJar, v1DigestAlgorithmBitSet); Manifest manifest =
copyFiles(manifest, inputJar, outputJar, timestamp, alignment); addDigestsToManifest(inputJar, STRIP_PATTERN, v1DigestAlgorithmBitSet);
copyFiles(inputJar, STRIP_PATTERN, outputJar, timestamp, alignment);
signFile( signFile(
manifest, manifest,
publicKey, privateKey, v1DigestAlgorithm, publicKey, privateKey, v1DigestAlgorithm,