• 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.util.Arrays;
22 import org.bouncycastle.asn1.ASN1Encodable;
23 import org.bouncycastle.asn1.ASN1EncodableVector;
24 import org.bouncycastle.asn1.ASN1Integer;
25 import org.bouncycastle.asn1.ASN1Object;
26 import org.bouncycastle.asn1.ASN1Primitive;
27 import org.bouncycastle.asn1.DEROctetString;
28 import org.bouncycastle.asn1.DERPrintableString;
29 import org.bouncycastle.asn1.DERSequence;
30 import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
31 import org.bouncycastle.asn1.util.ASN1Dump;
32 import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
33 
34 /**
35  *    AndroidVerifiedBootSignature DEFINITIONS ::=
36  *    BEGIN
37  *        FormatVersion ::= INTEGER
38  *        AlgorithmIdentifier ::=  SEQUENCE {
39  *            algorithm OBJECT IDENTIFIER,
40  *            parameters ANY DEFINED BY algorithm OPTIONAL
41  *        }
42  *        AuthenticatedAttributes ::= SEQUENCE {
43  *            target CHARACTER STRING,
44  *            length INTEGER
45  *        }
46  *        Signature ::= OCTET STRING
47  *     END
48  */
49 
50 public class BootSignature extends ASN1Object
51 {
52     private ASN1Integer             formatVersion;
53     private AlgorithmIdentifier     algorithmIdentifier;
54     private DERPrintableString      target;
55     private ASN1Integer             length;
56     private DEROctetString          signature;
57 
BootSignature(String target, int length)58     public BootSignature(String target, int length) {
59         this.formatVersion = new ASN1Integer(0);
60         this.target = new DERPrintableString(target);
61         this.length = new ASN1Integer(length);
62         this.algorithmIdentifier = new AlgorithmIdentifier(
63                 PKCSObjectIdentifiers.sha256WithRSAEncryption);
64     }
65 
getAuthenticatedAttributes()66     public ASN1Object getAuthenticatedAttributes() {
67         ASN1EncodableVector attrs = new ASN1EncodableVector();
68         attrs.add(target);
69         attrs.add(length);
70         return new DERSequence(attrs);
71     }
72 
getEncodedAuthenticatedAttributes()73     public byte[] getEncodedAuthenticatedAttributes() throws IOException {
74         return getAuthenticatedAttributes().getEncoded();
75     }
76 
setSignature(byte[] sig)77     public void setSignature(byte[] sig) {
78         signature = new DEROctetString(sig);
79     }
80 
generateSignableImage(byte[] image)81     public byte[] generateSignableImage(byte[] image) throws IOException {
82         byte[] attrs = getEncodedAuthenticatedAttributes();
83         byte[] signable = Arrays.copyOf(image, image.length + attrs.length);
84         for (int i=0; i < attrs.length; i++) {
85             signable[i+image.length] = attrs[i];
86         }
87         return signable;
88     }
89 
sign(byte[] image, PrivateKey key)90     public byte[] sign(byte[] image, PrivateKey key) throws Exception {
91         byte[] signable = generateSignableImage(image);
92         byte[] signature = Utils.sign(key, signable);
93         byte[] signed = Arrays.copyOf(image, image.length + signature.length);
94         for (int i=0; i < signature.length; i++) {
95             signed[i+image.length] = signature[i];
96         }
97         return signed;
98     }
99 
toASN1Primitive()100     public ASN1Primitive toASN1Primitive() {
101         ASN1EncodableVector v = new ASN1EncodableVector();
102         v.add(formatVersion);
103         v.add(algorithmIdentifier);
104         v.add(getAuthenticatedAttributes());
105         v.add(signature);
106         return new DERSequence(v);
107     }
108 
doSignature( String target, String imagePath, String keyPath, String outPath)109     public static void doSignature( String target,
110                                     String imagePath,
111                                     String keyPath,
112                                     String outPath) throws Exception {
113         byte[] image = Utils.read(imagePath);
114         BootSignature bootsig = new BootSignature(target, image.length);
115         PrivateKey key = Utils.loadPEMPrivateKeyFromFile(keyPath);
116         byte[] signature = bootsig.sign(image, key);
117         Utils.write(signature, outPath);
118     }
119 
120     // java -cp ../../../out/host/common/obj/JAVA_LIBRARIES/AndroidVerifiedBootSigner_intermediates/classes/ com.android.verity.AndroidVerifiedBootSigner boot ../../../out/target/product/flounder/boot.img ../../../build/target/product/security/verity_private_dev_key /tmp/boot.img.signed
main(String[] args)121     public static void main(String[] args) throws Exception {
122         doSignature(args[0], args[1], args[2], args[3]);
123     }
124 }