1 /*
2  * Copyright (C) 2016 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 android.keystore.cts;
18 
19 import com.google.common.io.BaseEncoding;
20 
21 import org.bouncycastle.asn1.ASN1Encodable;
22 import org.bouncycastle.asn1.ASN1Sequence;
23 
24 import java.security.cert.CertificateParsingException;
25 
26 public class RootOfTrust {
27     private static final int VERIFIED_BOOT_KEY_INDEX = 0;
28     private static final int DEVICE_LOCKED_INDEX = 1;
29     private static final int VERIFIED_BOOT_STATE_INDEX = 2;
30 
31     public static final int KM_VERIFIED_BOOT_VERIFIED = 0;
32     public static final int KM_VERIFIED_BOOT_SELF_SIGNED = 1;
33     public static final int KM_VERIFIED_BOOT_UNVERIFIED = 2;
34     public static final int KM_VERIFIED_BOOT_FAILED = 3;
35 
36     private final byte[] verifiedBootKey;
37     private final boolean deviceLocked;
38     private final int verifiedBootState;
39 
RootOfTrust(ASN1Encodable asn1Encodable)40     public RootOfTrust(ASN1Encodable asn1Encodable) throws CertificateParsingException {
41         this(asn1Encodable, true);
42     }
43 
RootOfTrust(ASN1Encodable asn1Encodable, boolean strictParsing)44     public RootOfTrust(ASN1Encodable asn1Encodable, boolean strictParsing)
45             throws CertificateParsingException {
46         if (!(asn1Encodable instanceof ASN1Sequence)) {
47             throw new CertificateParsingException("Expected sequence for root of trust, found "
48                     + asn1Encodable.getClass().getName());
49         }
50 
51         ASN1Sequence sequence = (ASN1Sequence) asn1Encodable;
52         verifiedBootKey =
53                 Asn1Utils.getByteArrayFromAsn1(sequence.getObjectAt(VERIFIED_BOOT_KEY_INDEX));
54         deviceLocked = Asn1Utils.getBooleanFromAsn1(
55                 sequence.getObjectAt(DEVICE_LOCKED_INDEX), strictParsing);
56         verifiedBootState =
57                 Asn1Utils.getIntegerFromAsn1(sequence.getObjectAt(VERIFIED_BOOT_STATE_INDEX));
58     }
59 
60 
RootOfTrust(byte[] verifiedBootKey, boolean deviceLocked, int verifiedBootState)61     RootOfTrust(byte[] verifiedBootKey, boolean deviceLocked, int verifiedBootState) {
62         this.verifiedBootKey = verifiedBootKey;
63         this.deviceLocked = deviceLocked;
64         this.verifiedBootState = verifiedBootState;
65     }
66 
verifiedBootStateToString(int verifiedBootState)67     public static String verifiedBootStateToString(int verifiedBootState) {
68         switch (verifiedBootState) {
69             case KM_VERIFIED_BOOT_VERIFIED:
70                 return "Verified";
71             case KM_VERIFIED_BOOT_SELF_SIGNED:
72                 return "Self-signed";
73             case KM_VERIFIED_BOOT_UNVERIFIED:
74                 return "Unverified";
75             case KM_VERIFIED_BOOT_FAILED:
76                 return "Failed";
77             default:
78                 return "Unknown";
79         }
80     }
81 
getVerifiedBootKey()82     public byte[] getVerifiedBootKey() {
83         return verifiedBootKey;
84     }
85 
isDeviceLocked()86     public boolean isDeviceLocked() {
87         return deviceLocked;
88     }
89 
getVerifiedBootState()90     public int getVerifiedBootState() {
91         return verifiedBootState;
92     }
93 
94     @Override
toString()95     public String toString() {
96         return new StringBuilder()
97                 .append("\nVerified boot Key: ")
98                 .append(verifiedBootKey != null ?
99                             BaseEncoding.base64().encode(verifiedBootKey) :
100                             "null")
101                 .append("\nDevice locked: ")
102                 .append(deviceLocked)
103                 .append("\nVerified boot state: ")
104                 .append(verifiedBootStateToString(verifiedBootState))
105                 .toString();
106     }
107 
108     public static class Builder {
109         private byte[] verifiedBootKey;
110         private boolean deviceLocked = false;
111         private int verifiedBootState = -1;
112 
setVerifiedBootKey(byte[] verifiedBootKey)113         public Builder setVerifiedBootKey(byte[] verifiedBootKey) {
114             this.verifiedBootKey = verifiedBootKey;
115             return this;
116         }
setDeviceLocked(boolean deviceLocked)117         public Builder setDeviceLocked(boolean deviceLocked) {
118             this.deviceLocked = deviceLocked;
119             return this;
120         }
setVerifiedBootState(int verifiedBootState)121         public Builder setVerifiedBootState(int verifiedBootState) {
122             this.verifiedBootState = verifiedBootState;
123             return this;
124         }
build()125         public RootOfTrust build() {
126             return new RootOfTrust(verifiedBootKey, deviceLocked, verifiedBootState);
127         }
128     }
129 }
130