1cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra/* 2cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * Copyright (C) 2014 The Android Open Source Project 3cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * 4cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * Licensed under the Apache License, Version 2.0 (the "License"); 5cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * you may not use this file except in compliance with the License. 6cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * You may obtain a copy of the License at 7cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * 8cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * http://www.apache.org/licenses/LICENSE-2.0 9cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * 10cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * Unless required by applicable law or agreed to in writing, software 11cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * distributed under the License is distributed on an "AS IS" BASIS, 12cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * See the License for the specific language governing permissions and 14cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * limitations under the License. 15cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra */ 16cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 17cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condrapackage com.android.verity; 18cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 19cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport java.io.IOException; 20cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport java.security.PrivateKey; 21cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport java.util.Arrays; 22cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport org.bouncycastle.asn1.ASN1Encodable; 23cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport org.bouncycastle.asn1.ASN1EncodableVector; 24cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport org.bouncycastle.asn1.ASN1Integer; 25cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport org.bouncycastle.asn1.ASN1Object; 26cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport org.bouncycastle.asn1.ASN1Primitive; 27cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport org.bouncycastle.asn1.DEROctetString; 28cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport org.bouncycastle.asn1.DERPrintableString; 29cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport org.bouncycastle.asn1.DERSequence; 30cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; 31cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport org.bouncycastle.asn1.util.ASN1Dump; 32cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport org.bouncycastle.asn1.x509.AlgorithmIdentifier; 33cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 34cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra/** 35cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * AndroidVerifiedBootSignature DEFINITIONS ::= 36cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * BEGIN 37cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * FormatVersion ::= INTEGER 38cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * AlgorithmIdentifier ::= SEQUENCE { 39cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * algorithm OBJECT IDENTIFIER, 40cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * parameters ANY DEFINED BY algorithm OPTIONAL 41cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * } 42cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * AuthenticatedAttributes ::= SEQUENCE { 43cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * target CHARACTER STRING, 44cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * length INTEGER 45cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * } 46cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * Signature ::= OCTET STRING 47cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * END 48cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra */ 49cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 50cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condrapublic class BootSignature extends ASN1Object 51cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra{ 52cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra private ASN1Integer formatVersion; 53cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra private AlgorithmIdentifier algorithmIdentifier; 54cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra private DERPrintableString target; 55cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra private ASN1Integer length; 56cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra private DEROctetString signature; 57cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 58cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra public BootSignature(String target, int length) { 59cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra this.formatVersion = new ASN1Integer(0); 60cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra this.target = new DERPrintableString(target); 61cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra this.length = new ASN1Integer(length); 62cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra this.algorithmIdentifier = new AlgorithmIdentifier( 63cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra PKCSObjectIdentifiers.sha256WithRSAEncryption); 64cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra } 65cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 66cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra public ASN1Object getAuthenticatedAttributes() { 67cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra ASN1EncodableVector attrs = new ASN1EncodableVector(); 68cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra attrs.add(target); 69cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra attrs.add(length); 70cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra return new DERSequence(attrs); 71cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra } 72cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 73cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra public byte[] getEncodedAuthenticatedAttributes() throws IOException { 74cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra return getAuthenticatedAttributes().getEncoded(); 75cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra } 76cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 77cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra public void setSignature(byte[] sig) { 78cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra signature = new DEROctetString(sig); 79cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra } 80cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 81cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra public byte[] generateSignableImage(byte[] image) throws IOException { 82cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra byte[] attrs = getEncodedAuthenticatedAttributes(); 83cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra byte[] signable = Arrays.copyOf(image, image.length + attrs.length); 84cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra for (int i=0; i < attrs.length; i++) { 85cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra signable[i+image.length] = attrs[i]; 86cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra } 87cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra return signable; 88cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra } 89cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 90cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra public byte[] sign(byte[] image, PrivateKey key) throws Exception { 91cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra byte[] signable = generateSignableImage(image); 92cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra byte[] signature = Utils.sign(key, signable); 93cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra byte[] signed = Arrays.copyOf(image, image.length + signature.length); 94cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra for (int i=0; i < signature.length; i++) { 95cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra signed[i+image.length] = signature[i]; 96cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra } 97cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra return signed; 98cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra } 99cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 100cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra public ASN1Primitive toASN1Primitive() { 101cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra ASN1EncodableVector v = new ASN1EncodableVector(); 102cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra v.add(formatVersion); 103cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra v.add(algorithmIdentifier); 104cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra v.add(getAuthenticatedAttributes()); 105cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra v.add(signature); 106cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra return new DERSequence(v); 107cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra } 108cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 109cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra public static void doSignature( String target, 110cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra String imagePath, 111cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra String keyPath, 112cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra String outPath) throws Exception { 113cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra byte[] image = Utils.read(imagePath); 114cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra BootSignature bootsig = new BootSignature(target, image.length); 115cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra PrivateKey key = Utils.loadPEMPrivateKeyFromFile(keyPath); 116cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra byte[] signature = bootsig.sign(image, key); 117cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra Utils.write(signature, outPath); 118cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra } 119cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 120cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra // 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 121cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra public static void main(String[] args) throws Exception { 122cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra doSignature(args[0], args[1], args[2], args[3]); 123cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra } 124cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra}