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 com.android.org.bouncycastle.asn1.ASN1Encodable;
22 import com.android.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         if (!(asn1Encodable instanceof ASN1Sequence)) {
42             throw new CertificateParsingException("Expected sequence for root of trust, found "
43                     + asn1Encodable.getClass().getName());
44         }
45 
46         ASN1Sequence sequence = (ASN1Sequence) asn1Encodable;
47         verifiedBootKey =
48                 Asn1Utils.getByteArrayFromAsn1(sequence.getObjectAt(VERIFIED_BOOT_KEY_INDEX));
49         deviceLocked = Asn1Utils.getBooleanFromAsn1(sequence.getObjectAt(DEVICE_LOCKED_INDEX));
50         verifiedBootState =
51                 Asn1Utils.getIntegerFromAsn1(sequence.getObjectAt(VERIFIED_BOOT_STATE_INDEX));
52     }
53 
verifiedBootStateToString(int verifiedBootState)54     public static String verifiedBootStateToString(int verifiedBootState) {
55         switch (verifiedBootState) {
56             case KM_VERIFIED_BOOT_VERIFIED:
57                 return "Verified";
58             case KM_VERIFIED_BOOT_SELF_SIGNED:
59                 return "Self-signed";
60             case KM_VERIFIED_BOOT_UNVERIFIED:
61                 return "Unverified";
62             case KM_VERIFIED_BOOT_FAILED:
63                 return "Failed";
64             default:
65                 return "Unknown";
66         }
67     }
68 
getVerifiedBootKey()69     public byte[] getVerifiedBootKey() {
70         return verifiedBootKey;
71     }
72 
isDeviceLocked()73     public boolean isDeviceLocked() {
74         return deviceLocked;
75     }
76 
getVerifiedBootState()77     public int getVerifiedBootState() {
78         return verifiedBootState;
79     }
80 
81     @Override
toString()82     public String toString() {
83         return new StringBuilder()
84                 .append("\nVerified boot Key: ")
85                 .append(BaseEncoding.base64().encode(verifiedBootKey))
86                 .append("\nDevice locked: ")
87                 .append(deviceLocked)
88                 .append("\nVerified boot state: ")
89                 .append(verifiedBootStateToString(verifiedBootState))
90                 .toString();
91     }
92 }
93