blob: d57f328fe01d45ec544cd66ddbf0dc073a910381 [file] [log] [blame]
Geremy Condracee5bfd2014-06-11 13:38:45 -07001/*
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
17package com.android.verity;
18
19import java.io.IOException;
20import java.security.PrivateKey;
21import java.security.PublicKey;
22import java.security.Signature;
23import org.bouncycastle.asn1.ASN1Encodable;
24import org.bouncycastle.asn1.ASN1EncodableVector;
25import org.bouncycastle.asn1.ASN1Integer;
26import org.bouncycastle.asn1.ASN1Object;
27import org.bouncycastle.asn1.ASN1Primitive;
28import org.bouncycastle.asn1.DEROctetString;
29import org.bouncycastle.asn1.DERPrintableString;
30import org.bouncycastle.asn1.DERSequence;
31import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
32import org.bouncycastle.asn1.pkcs.RSAPublicKey;
33import org.bouncycastle.asn1.util.ASN1Dump;
34import 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
53class 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
80class 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}