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.security.PublicKey; 22cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport java.security.Signature; 23cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport org.bouncycastle.asn1.ASN1Encodable; 24cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport org.bouncycastle.asn1.ASN1EncodableVector; 25cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport org.bouncycastle.asn1.ASN1Integer; 26cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport org.bouncycastle.asn1.ASN1Object; 27cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport org.bouncycastle.asn1.ASN1Primitive; 28cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport org.bouncycastle.asn1.DEROctetString; 29cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport org.bouncycastle.asn1.DERPrintableString; 30cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport org.bouncycastle.asn1.DERSequence; 31cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; 32cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport org.bouncycastle.asn1.pkcs.RSAPublicKey; 33cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport org.bouncycastle.asn1.util.ASN1Dump; 34cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraimport org.bouncycastle.asn1.x509.AlgorithmIdentifier; 35cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 36cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra/** 37cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * AndroidVerifiedBootKeystore DEFINITIONS ::= 38cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * BEGIN 39cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * FormatVersion ::= INTEGER 40cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * KeyBag ::= SEQUENCE { 41cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * Key ::= SEQUENCE { 42cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * AlgorithmIdentifier ::= SEQUENCE { 43cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * algorithm OBJECT IDENTIFIER, 44cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * parameters ANY DEFINED BY algorithm OPTIONAL 45cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * } 46cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * KeyMaterial ::= RSAPublicKey 47cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * } 48cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * } 49cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * Signature ::= AndroidVerifiedBootSignature 50cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra * END 51cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra */ 52cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 53cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraclass BootKey extends ASN1Object 54cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra{ 55cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra private AlgorithmIdentifier algorithmIdentifier; 56cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra private RSAPublicKey keyMaterial; 57cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 58cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra public BootKey(PublicKey key) throws Exception { 59cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra java.security.interfaces.RSAPublicKey k = 60cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra (java.security.interfaces.RSAPublicKey) key; 61cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra this.keyMaterial = new RSAPublicKey( 62cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra k.getModulus(), 63cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra k.getPublicExponent()); 64cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra this.algorithmIdentifier = new AlgorithmIdentifier( 65cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra PKCSObjectIdentifiers.sha256WithRSAEncryption); 66cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra } 67cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 68cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra public ASN1Primitive toASN1Primitive() { 69cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra ASN1EncodableVector v = new ASN1EncodableVector(); 70cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra v.add(algorithmIdentifier); 71cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra v.add(keyMaterial); 72cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra return new DERSequence(v); 73cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra } 74cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 75cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra public void dump() throws Exception { 76cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra System.out.println(ASN1Dump.dumpAsString(toASN1Primitive())); 77cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra } 78cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra} 79cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 80cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condraclass BootKeystore extends ASN1Object 81cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra{ 82cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra private ASN1Integer formatVersion; 83cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra private ASN1EncodableVector keyBag; 84cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra private BootSignature signature; 85cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 86cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra public BootKeystore() { 87cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra this.formatVersion = new ASN1Integer(0); 88cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra this.keyBag = new ASN1EncodableVector(); 89cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra } 90cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 91cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra public void addPublicKey(byte[] der) throws Exception { 92cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra PublicKey pubkey = Utils.loadDERPublicKey(der); 93cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra BootKey k = new BootKey(pubkey); 94cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra keyBag.add(k); 95cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra } 96cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 97cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra public byte[] getInnerKeystore() throws Exception { 98cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra ASN1EncodableVector v = new ASN1EncodableVector(); 99cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra v.add(formatVersion); 100cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra v.add(new DERSequence(keyBag)); 101cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra return new DERSequence(v).getEncoded(); 102cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra } 103cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 104cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra public ASN1Primitive toASN1Primitive() { 105cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra ASN1EncodableVector v = new ASN1EncodableVector(); 106cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra v.add(formatVersion); 107cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra v.add(new DERSequence(keyBag)); 108cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra v.add(signature); 109cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra return new DERSequence(v); 110cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra } 111cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 112cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra public void sign(PrivateKey privateKey) throws Exception { 113cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra byte[] innerKeystore = getInnerKeystore(); 114cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra byte[] rawSignature = Utils.sign(privateKey, innerKeystore); 115cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra signature = new BootSignature("keystore", innerKeystore.length); 116cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra signature.setSignature(rawSignature); 117cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra } 118cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 119cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra public void dump() throws Exception { 120cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra System.out.println(ASN1Dump.dumpAsString(toASN1Primitive())); 121cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra } 122cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra 123cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra // USAGE: 124cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra // AndroidVerifiedBootKeystoreSigner <privkeyFile> <outfile> <pubkeyFile0> ... <pubkeyFileN-1> 125cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra // EG: 126cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra // java -cp ../../../out/host/common/obj/JAVA_LIBRARIES/AndroidVerifiedBootKeystoreSigner_intermediates/classes/ com.android.verity.AndroidVerifiedBootKeystoreSigner ../../../build/target/product/security/verity_private_dev_key /tmp/keystore.out /tmp/k 127cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra public static void main(String[] args) throws Exception { 128cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra String privkeyFname = args[0]; 129cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra String outfileFname = args[1]; 130cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra BootKeystore ks = new BootKeystore(); 131cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra for (int i=2; i < args.length; i++) { 132cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra ks.addPublicKey(Utils.read(args[i])); 133cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra } 134cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra ks.sign(Utils.loadPEMPrivateKeyFromFile(privkeyFname)); 135cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra Utils.write(ks.getEncoded(), outfileFname); 136cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra } 137cee5bfdf119104b8ebce56d54dfcdcca1f537075Geremy Condra}