Home | History | Annotate | Download | only in verity
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.verity;
     18 
     19 import java.io.IOException;
     20 import java.security.PrivateKey;
     21 import java.security.PublicKey;
     22 import java.security.Signature;
     23 import org.bouncycastle.asn1.ASN1Encodable;
     24 import org.bouncycastle.asn1.ASN1EncodableVector;
     25 import org.bouncycastle.asn1.ASN1Integer;
     26 import org.bouncycastle.asn1.ASN1Object;
     27 import org.bouncycastle.asn1.ASN1Primitive;
     28 import org.bouncycastle.asn1.DEROctetString;
     29 import org.bouncycastle.asn1.DERPrintableString;
     30 import org.bouncycastle.asn1.DERSequence;
     31 import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
     32 import org.bouncycastle.asn1.pkcs.RSAPublicKey;
     33 import org.bouncycastle.asn1.util.ASN1Dump;
     34 import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
     35 
     36 /**
     37  * AndroidVerifiedBootKeystore DEFINITIONS ::=
     38  * BEGIN
     39  *     FormatVersion ::= INTEGER
     40  *     KeyBag ::= SEQUENCE {
     41  *         Key  ::= SEQUENCE {
     42  *             AlgorithmIdentifier  ::=  SEQUENCE {
     43  *                 algorithm OBJECT IDENTIFIER,
     44  *                 parameters ANY DEFINED BY algorithm OPTIONAL
     45  *             }
     46  *             KeyMaterial ::= RSAPublicKey
     47  *         }
     48  *     }
     49  *     Signature ::= AndroidVerifiedBootSignature
     50  * END
     51  */
     52 
     53 class BootKey extends ASN1Object
     54 {
     55     private AlgorithmIdentifier algorithmIdentifier;
     56     private RSAPublicKey keyMaterial;
     57 
     58     public BootKey(PublicKey key) throws Exception {
     59         java.security.interfaces.RSAPublicKey k =
     60                 (java.security.interfaces.RSAPublicKey) key;
     61         this.keyMaterial = new RSAPublicKey(
     62                 k.getModulus(),
     63                 k.getPublicExponent());
     64         this.algorithmIdentifier = new AlgorithmIdentifier(
     65                 PKCSObjectIdentifiers.sha256WithRSAEncryption);
     66     }
     67 
     68     public ASN1Primitive toASN1Primitive() {
     69         ASN1EncodableVector v = new ASN1EncodableVector();
     70         v.add(algorithmIdentifier);
     71         v.add(keyMaterial);
     72         return new DERSequence(v);
     73     }
     74 
     75     public void dump() throws Exception {
     76         System.out.println(ASN1Dump.dumpAsString(toASN1Primitive()));
     77     }
     78 }
     79 
     80 class BootKeystore extends ASN1Object
     81 {
     82     private ASN1Integer                     formatVersion;
     83     private ASN1EncodableVector             keyBag;
     84     private BootSignature    signature;
     85 
     86     public BootKeystore() {
     87         this.formatVersion = new ASN1Integer(0);
     88         this.keyBag = new ASN1EncodableVector();
     89     }
     90 
     91     public void addPublicKey(byte[] der) throws Exception {
     92         PublicKey pubkey = Utils.loadDERPublicKey(der);
     93         BootKey k = new BootKey(pubkey);
     94         keyBag.add(k);
     95     }
     96 
     97     public byte[] getInnerKeystore() throws Exception {
     98         ASN1EncodableVector v = new ASN1EncodableVector();
     99         v.add(formatVersion);
    100         v.add(new DERSequence(keyBag));
    101         return new DERSequence(v).getEncoded();
    102     }
    103 
    104     public ASN1Primitive toASN1Primitive() {
    105         ASN1EncodableVector v = new ASN1EncodableVector();
    106         v.add(formatVersion);
    107         v.add(new DERSequence(keyBag));
    108         v.add(signature);
    109         return new DERSequence(v);
    110     }
    111 
    112     public void sign(PrivateKey privateKey) throws Exception {
    113         byte[] innerKeystore = getInnerKeystore();
    114         byte[] rawSignature = Utils.sign(privateKey, innerKeystore);
    115         signature = new BootSignature("keystore", innerKeystore.length);
    116         signature.setSignature(rawSignature);
    117     }
    118 
    119     public void dump() throws Exception {
    120         System.out.println(ASN1Dump.dumpAsString(toASN1Primitive()));
    121     }
    122 
    123     // USAGE:
    124     //      AndroidVerifiedBootKeystoreSigner <privkeyFile> <outfile> <pubkeyFile0> ... <pubkeyFileN-1>
    125     // EG:
    126     //     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
    127     public static void main(String[] args) throws Exception {
    128         String privkeyFname = args[0];
    129         String outfileFname = args[1];
    130         BootKeystore ks = new BootKeystore();
    131         for (int i=2; i < args.length; i++) {
    132             ks.addPublicKey(Utils.read(args[i]));
    133         }
    134         ks.sign(Utils.loadPEMPrivateKeyFromFile(privkeyFname));
    135         Utils.write(ks.getEncoded(), outfileFname);
    136     }
    137 }