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 }