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