• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
BootKey(PublicKey key)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 
toASN1Primitive()68     public ASN1Primitive toASN1Primitive() {
69         ASN1EncodableVector v = new ASN1EncodableVector();
70         v.add(algorithmIdentifier);
71         v.add(keyMaterial);
72         return new DERSequence(v);
73     }
74 
dump()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 
BootKeystore()86     public BootKeystore() {
87         this.formatVersion = new ASN1Integer(0);
88         this.keyBag = new ASN1EncodableVector();
89     }
90 
addPublicKey(byte[] der)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 
getInnerKeystore()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 
toASN1Primitive()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 
sign(PrivateKey privateKey)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 
dump()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
main(String[] args)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 }