From 7377e002421ed9a04cc94cd808c234f48d93924d Mon Sep 17 00:00:00 2001 From: Paul Lawrence Date: Thu, 13 Nov 2014 22:03:31 +0000 Subject: Revert "Update boot image signature format to version 1" This reverts commit b62eabde2db40f01dfed1cef48ac2cbabdff4d03. Change-Id: I98019b7990c5436fe6ad5ef1052729478bccbe17 --- verity/BootSignature.java | 112 +++++++-------------------------------------- verity/KeystoreSigner.java | 5 +- verity/Utils.java | 110 +++----------------------------------------- 3 files changed, 25 insertions(+), 202 deletions(-) (limited to 'verity') diff --git a/verity/BootSignature.java b/verity/BootSignature.java index 4ee3309d..740e226a 100644 --- a/verity/BootSignature.java +++ b/verity/BootSignature.java @@ -17,58 +17,50 @@ package com.android.verity; import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; import java.security.PrivateKey; -import java.security.Security; -import java.security.cert.X509Certificate; -import java.security.cert.CertificateEncodingException; import java.util.Arrays; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.ASN1Object; import org.bouncycastle.asn1.ASN1Primitive; -import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERPrintableString; import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.util.ASN1Dump; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; -import org.bouncycastle.jce.provider.BouncyCastleProvider; /** * AndroidVerifiedBootSignature DEFINITIONS ::= * BEGIN - * formatVersion ::= INTEGER - * certificate ::= Certificate - * algorithmIdentifier ::= SEQUENCE { + * FormatVersion ::= INTEGER + * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL * } - * authenticatedAttributes ::= SEQUENCE { + * AuthenticatedAttributes ::= SEQUENCE { * target CHARACTER STRING, * length INTEGER * } - * signature ::= OCTET STRING + * Signature ::= OCTET STRING * END */ public class BootSignature extends ASN1Object { private ASN1Integer formatVersion; - private ASN1Encodable certificate; private AlgorithmIdentifier algorithmIdentifier; private DERPrintableString target; private ASN1Integer length; private DEROctetString signature; - private static final int FORMAT_VERSION = 1; - public BootSignature(String target, int length) { - this.formatVersion = new ASN1Integer(FORMAT_VERSION); + this.formatVersion = new ASN1Integer(0); this.target = new DERPrintableString(target); this.length = new ASN1Integer(length); + this.algorithmIdentifier = new AlgorithmIdentifier( + PKCSObjectIdentifiers.sha1WithRSAEncryption); } public ASN1Object getAuthenticatedAttributes() { @@ -82,17 +74,10 @@ public class BootSignature extends ASN1Object return getAuthenticatedAttributes().getEncoded(); } - public void setSignature(byte[] sig, AlgorithmIdentifier algId) { - algorithmIdentifier = algId; + public void setSignature(byte[] sig) { signature = new DEROctetString(sig); } - public void setCertificate(X509Certificate cert) - throws Exception, IOException, CertificateEncodingException { - ASN1InputStream s = new ASN1InputStream(cert.getEncoded()); - certificate = s.readObject(); - } - public byte[] generateSignableImage(byte[] image) throws IOException { byte[] attrs = getEncodedAuthenticatedAttributes(); byte[] signable = Arrays.copyOf(image, image.length + attrs.length); @@ -110,93 +95,30 @@ public class BootSignature extends ASN1Object public ASN1Primitive toASN1Primitive() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(formatVersion); - v.add(certificate); v.add(algorithmIdentifier); v.add(getAuthenticatedAttributes()); v.add(signature); return new DERSequence(v); } - public static int getSignableImageSize(byte[] data) throws Exception { - if (!Arrays.equals(Arrays.copyOfRange(data, 0, 8), - "ANDROID!".getBytes("US-ASCII"))) { - throw new IllegalArgumentException("Invalid image header: missing magic"); - } - - ByteBuffer image = ByteBuffer.wrap(data); - image.order(ByteOrder.LITTLE_ENDIAN); - - image.getLong(); // magic - int kernelSize = image.getInt(); - image.getInt(); // kernel_addr - int ramdskSize = image.getInt(); - image.getInt(); // ramdisk_addr - int secondSize = image.getInt(); - image.getLong(); // second_addr + tags_addr - int pageSize = image.getInt(); - - int length = pageSize // include the page aligned image header - + ((kernelSize + pageSize - 1) / pageSize) * pageSize - + ((ramdskSize + pageSize - 1) / pageSize) * pageSize - + ((secondSize + pageSize - 1) / pageSize) * pageSize; - - length = ((length + pageSize - 1) / pageSize) * pageSize; - - if (length <= 0) { - throw new IllegalArgumentException("Invalid image header: invalid length"); - } - - return length; - } - public static void doSignature( String target, String imagePath, String keyPath, - String certPath, String outPath) throws Exception { - byte[] image = Utils.read(imagePath); - int signableSize = getSignableImageSize(image); - - if (signableSize < image.length) { - System.err.println("NOTE: truncating file " + imagePath + - " from " + image.length + " to " + signableSize + " bytes"); - image = Arrays.copyOf(image, signableSize); - } else if (signableSize > image.length) { - throw new IllegalArgumentException("Invalid image: too short, expected " + - signableSize + " bytes"); - } - BootSignature bootsig = new BootSignature(target, image.length); - - X509Certificate cert = Utils.loadPEMCertificate(certPath); - bootsig.setCertificate(cert); - - PrivateKey key = Utils.loadDERPrivateKeyFromFile(keyPath); - bootsig.setSignature(bootsig.sign(image, key), - Utils.getSignatureAlgorithmIdentifier(key)); - + PrivateKey key = Utils.loadPEMPrivateKeyFromFile(keyPath); + bootsig.setSignature(bootsig.sign(image, key)); byte[] encoded_bootsig = bootsig.getEncoded(); byte[] image_with_metadata = Arrays.copyOf(image, image.length + encoded_bootsig.length); - - System.arraycopy(encoded_bootsig, 0, image_with_metadata, - image.length, encoded_bootsig.length); - + for (int i=0; i < encoded_bootsig.length; i++) { + image_with_metadata[i+image.length] = encoded_bootsig[i]; + } Utils.write(image_with_metadata, outPath); } - /* java -cp - ../../../out/host/common/obj/JAVA_LIBRARIES/BootSignature_intermediates/\ - classes/com.android.verity.BootSignature \ - boot \ - ../../../out/target/product/flounder/boot.img \ - ../../../build/target/product/security/verity_private_dev_key \ - ../../../build/target/product/security/verity.pk8 \ - ../../../build/target/product/security/verity.x509.pem \ - /tmp/boot.img.signed - */ + // java -cp ../../../out/host/common/obj/JAVA_LIBRARIES/AndroidVerifiedBootSigner_intermediates/classes/ com.android.verity.AndroidVerifiedBootSigner boot ../../../out/target/product/flounder/boot.img ../../../build/target/product/security/verity_private_dev_key /tmp/boot.img.signed public static void main(String[] args) throws Exception { - Security.addProvider(new BouncyCastleProvider()); - doSignature(args[0], args[1], args[2], args[3], args[4]); + doSignature(args[0], args[1], args[2], args[3]); } -} +} \ No newline at end of file diff --git a/verity/KeystoreSigner.java b/verity/KeystoreSigner.java index c020fb60..d57f328f 100644 --- a/verity/KeystoreSigner.java +++ b/verity/KeystoreSigner.java @@ -113,8 +113,7 @@ class BootKeystore extends ASN1Object byte[] innerKeystore = getInnerKeystore(); byte[] rawSignature = Utils.sign(privateKey, innerKeystore); signature = new BootSignature("keystore", innerKeystore.length); - signature.setSignature(rawSignature, - new AlgorithmIdentifier(PKCSObjectIdentifiers.sha1WithRSAEncryption)); + signature.setSignature(rawSignature); } public void dump() throws Exception { @@ -135,4 +134,4 @@ class BootKeystore extends ASN1Object ks.sign(Utils.loadPEMPrivateKeyFromFile(privkeyFname)); Utils.write(ks.getEncoded(), outfileFname); } -} +} \ No newline at end of file diff --git a/verity/Utils.java b/verity/Utils.java index 4eba5527..2c1e7bb4 100644 --- a/verity/Utils.java +++ b/verity/Utils.java @@ -18,60 +18,22 @@ package com.android.verity; import java.lang.reflect.Constructor; import java.io.File; -import java.io.ByteArrayInputStream; -import java.io.Console; import java.io.FileInputStream; import java.io.FileOutputStream; -import java.io.InputStreamReader; import java.io.IOException; -import java.security.GeneralSecurityException; -import java.security.Key; import java.security.PrivateKey; import java.security.PublicKey; import java.security.KeyFactory; import java.security.Provider; import java.security.Security; import java.security.Signature; -import java.security.cert.Certificate; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; import java.security.spec.X509EncodedKeySpec; import java.security.spec.PKCS8EncodedKeySpec; -import java.security.spec.InvalidKeySpecException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -import javax.crypto.Cipher; -import javax.crypto.EncryptedPrivateKeyInfo; -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.PBEKeySpec; - -import org.bouncycastle.asn1.ASN1InputStream; -import org.bouncycastle.asn1.ASN1ObjectIdentifier; -import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; -import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; -import org.bouncycastle.asn1.x509.AlgorithmIdentifier; + import org.bouncycastle.util.encoders.Base64; public class Utils { - private static final Map ID_TO_ALG; - private static final Map ALG_TO_ID; - - static { - ID_TO_ALG = new HashMap(); - ALG_TO_ID = new HashMap(); - - ID_TO_ALG.put(PKCSObjectIdentifiers.sha1WithRSAEncryption.getId(), "SHA1withRSA"); - ID_TO_ALG.put(PKCSObjectIdentifiers.sha256WithRSAEncryption.getId(), "SHA256withRSA"); - ID_TO_ALG.put(PKCSObjectIdentifiers.sha512WithRSAEncryption.getId(), "SHA512withRSA"); - - ALG_TO_ID.put("SHA1withRSA", PKCSObjectIdentifiers.sha1WithRSAEncryption.getId()); - ALG_TO_ID.put("SHA256withRSA", PKCSObjectIdentifiers.sha256WithRSAEncryption.getId()); - ALG_TO_ID.put("SHA512withRSA", PKCSObjectIdentifiers.sha512WithRSAEncryption.getId()); - } - private static void loadProviderIfNecessary(String providerClassName) { if (providerClassName == null) { return; @@ -126,45 +88,10 @@ public class Utils { return Base64.decode(base64_der); } - private static PKCS8EncodedKeySpec decryptPrivateKey(byte[] encryptedPrivateKey) - throws GeneralSecurityException { - EncryptedPrivateKeyInfo epkInfo; - try { - epkInfo = new EncryptedPrivateKeyInfo(encryptedPrivateKey); - } catch (IOException ex) { - // Probably not an encrypted key. - return null; - } - - char[] password = System.console().readPassword("Password for the private key file: "); - - SecretKeyFactory skFactory = SecretKeyFactory.getInstance(epkInfo.getAlgName()); - Key key = skFactory.generateSecret(new PBEKeySpec(password)); - Arrays.fill(password, '\0'); - - 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("Password may be bad."); - throw ex; - } - } - static PrivateKey loadDERPrivateKey(byte[] der) throws Exception { - PKCS8EncodedKeySpec spec = decryptPrivateKey(der); - - if (spec == null) { - spec = new PKCS8EncodedKeySpec(der); - } - - 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); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(der); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + return (PrivateKey) keyFactory.generatePrivate(keySpec); } static PrivateKey loadPEMPrivateKey(byte[] pem) throws Exception { @@ -201,33 +128,8 @@ public class Utils { return loadDERPublicKey(read(keyFname)); } - static X509Certificate loadPEMCertificate(String fname) throws Exception { - try (FileInputStream fis = new FileInputStream(fname)) { - CertificateFactory cf = CertificateFactory.getInstance("X.509"); - return (X509Certificate) cf.generateCertificate(fis); - } - } - - private static String getSignatureAlgorithm(Key key) { - if ("RSA".equals(key.getAlgorithm())) { - return "SHA256withRSA"; - } else { - throw new IllegalArgumentException("Unsupported key type " + key.getAlgorithm()); - } - } - - static AlgorithmIdentifier getSignatureAlgorithmIdentifier(Key key) { - String id = ALG_TO_ID.get(getSignatureAlgorithm(key)); - - if (id == null) { - throw new IllegalArgumentException("Unsupported key type " + key.getAlgorithm()); - } - - return new AlgorithmIdentifier(new ASN1ObjectIdentifier(id)); - } - static byte[] sign(PrivateKey privateKey, byte[] input) throws Exception { - Signature signer = Signature.getInstance(getSignatureAlgorithm(privateKey)); + Signature signer = Signature.getInstance("SHA1withRSA"); signer.initSign(privateKey); signer.update(input); return signer.sign(); @@ -251,4 +153,4 @@ public class Utils { out.write(data); out.close(); } -} +} \ No newline at end of file -- cgit v1.2.3