blob: 740e226a10ccaee9870c5a5309d49ff0205f91d2 [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.util.Arrays;
22import org.bouncycastle.asn1.ASN1Encodable;
23import org.bouncycastle.asn1.ASN1EncodableVector;
24import org.bouncycastle.asn1.ASN1Integer;
25import org.bouncycastle.asn1.ASN1Object;
26import org.bouncycastle.asn1.ASN1Primitive;
27import org.bouncycastle.asn1.DEROctetString;
28import org.bouncycastle.asn1.DERPrintableString;
29import org.bouncycastle.asn1.DERSequence;
30import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
31import org.bouncycastle.asn1.util.ASN1Dump;
32import 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
50public 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
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(
Geremy Condrad66cefd2014-08-14 16:44:31 -070063 PKCSObjectIdentifiers.sha1WithRSAEncryption);
Geremy Condracee5bfd2014-06-11 13:38:45 -070064 }
65
66 public ASN1Object getAuthenticatedAttributes() {
67 ASN1EncodableVector attrs = new ASN1EncodableVector();
68 attrs.add(target);
69 attrs.add(length);
70 return new DERSequence(attrs);
71 }
72
73 public byte[] getEncodedAuthenticatedAttributes() throws IOException {
74 return getAuthenticatedAttributes().getEncoded();
75 }
76
77 public void setSignature(byte[] sig) {
78 signature = new DEROctetString(sig);
79 }
80
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
90 public byte[] sign(byte[] image, PrivateKey key) throws Exception {
91 byte[] signable = generateSignableImage(image);
Geremy Condrad66cefd2014-08-14 16:44:31 -070092 return Utils.sign(key, signable);
Geremy Condracee5bfd2014-06-11 13:38:45 -070093 }
94
95 public ASN1Primitive toASN1Primitive() {
96 ASN1EncodableVector v = new ASN1EncodableVector();
97 v.add(formatVersion);
98 v.add(algorithmIdentifier);
99 v.add(getAuthenticatedAttributes());
100 v.add(signature);
101 return new DERSequence(v);
102 }
103
104 public static void doSignature( String target,
105 String imagePath,
106 String keyPath,
107 String outPath) throws Exception {
108 byte[] image = Utils.read(imagePath);
109 BootSignature bootsig = new BootSignature(target, image.length);
110 PrivateKey key = Utils.loadPEMPrivateKeyFromFile(keyPath);
Geremy Condrad66cefd2014-08-14 16:44:31 -0700111 bootsig.setSignature(bootsig.sign(image, key));
112 byte[] encoded_bootsig = bootsig.getEncoded();
113 byte[] image_with_metadata = Arrays.copyOf(image, image.length + encoded_bootsig.length);
114 for (int i=0; i < encoded_bootsig.length; i++) {
115 image_with_metadata[i+image.length] = encoded_bootsig[i];
116 }
117 Utils.write(image_with_metadata, outPath);
Geremy Condracee5bfd2014-06-11 13:38:45 -0700118 }
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
121 public static void main(String[] args) throws Exception {
122 doSignature(args[0], args[1], args[2], args[3]);
123 }
124}