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 private static final int VERIFIED_BOOT_HASH_INDEX = 3; 31 32 public static final int KM_VERIFIED_BOOT_VERIFIED = 0; 33 public static final int KM_VERIFIED_BOOT_SELF_SIGNED = 1; 34 public static final int KM_VERIFIED_BOOT_UNVERIFIED = 2; 35 public static final int KM_VERIFIED_BOOT_FAILED = 3; 36 37 private final byte[] mVerifiedBootKey; 38 private final boolean mDeviceLocked; 39 private final int mVerifiedBootState; 40 private final byte[] mVerifiedBootHash; 41 RootOfTrust(ASN1Encodable asn1Encodable)42 public RootOfTrust(ASN1Encodable asn1Encodable) throws CertificateParsingException { 43 this(asn1Encodable, true); 44 } 45 RootOfTrust(ASN1Encodable asn1Encodable, boolean strictParsing)46 public RootOfTrust(ASN1Encodable asn1Encodable, boolean strictParsing) 47 throws CertificateParsingException { 48 if (!(asn1Encodable instanceof ASN1Sequence)) { 49 throw new CertificateParsingException("Expected sequence for root of trust, found " 50 + asn1Encodable.getClass().getName()); 51 } 52 53 ASN1Sequence sequence = (ASN1Sequence) asn1Encodable; 54 mVerifiedBootKey = 55 Asn1Utils.getByteArrayFromAsn1(sequence.getObjectAt(VERIFIED_BOOT_KEY_INDEX)); 56 mDeviceLocked = Asn1Utils.getBooleanFromAsn1( 57 sequence.getObjectAt(DEVICE_LOCKED_INDEX), strictParsing); 58 mVerifiedBootState = 59 Asn1Utils.getIntegerFromAsn1(sequence.getObjectAt(VERIFIED_BOOT_STATE_INDEX)); 60 mVerifiedBootHash = 61 Asn1Utils.getByteArrayFromAsn1(sequence.getObjectAt(VERIFIED_BOOT_HASH_INDEX)); 62 } 63 64 RootOfTrust(byte[] verifiedBootKey, boolean deviceLocked, int verifiedBootState, byte[] verifiedBootHash)65 RootOfTrust(byte[] verifiedBootKey, boolean deviceLocked, int verifiedBootState, 66 byte[] verifiedBootHash) { 67 this.mVerifiedBootKey = verifiedBootKey; 68 this.mDeviceLocked = deviceLocked; 69 this.mVerifiedBootState = verifiedBootState; 70 this.mVerifiedBootHash = verifiedBootHash; 71 } 72 verifiedBootStateToString(int verifiedBootState)73 public static String verifiedBootStateToString(int verifiedBootState) { 74 switch (verifiedBootState) { 75 case KM_VERIFIED_BOOT_VERIFIED: 76 return "Verified"; 77 case KM_VERIFIED_BOOT_SELF_SIGNED: 78 return "Self-signed"; 79 case KM_VERIFIED_BOOT_UNVERIFIED: 80 return "Unverified"; 81 case KM_VERIFIED_BOOT_FAILED: 82 return "Failed"; 83 default: 84 return "Unknown"; 85 } 86 } 87 getVerifiedBootKey()88 public byte[] getVerifiedBootKey() { 89 return mVerifiedBootKey; 90 } 91 isDeviceLocked()92 public boolean isDeviceLocked() { 93 return mDeviceLocked; 94 } 95 getVerifiedBootState()96 public int getVerifiedBootState() { 97 return mVerifiedBootState; 98 } 99 getVerifiedBootHash()100 public byte[] getVerifiedBootHash() { 101 return mVerifiedBootHash; 102 } 103 104 @Override toString()105 public String toString() { 106 return new StringBuilder() 107 .append("\nVerified boot Key: ") 108 .append(mVerifiedBootKey != null 109 ? BaseEncoding.base64().encode(mVerifiedBootKey) 110 : "null") 111 .append("\nDevice locked: ") 112 .append(mDeviceLocked) 113 .append("\nVerified boot state: ") 114 .append(verifiedBootStateToString(mVerifiedBootState)) 115 .append("\nVerified boot hash: ") 116 .append(mVerifiedBootHash != null 117 ? BaseEncoding.base64().encode(mVerifiedBootHash) 118 : "null") 119 .toString(); 120 } 121 122 public static class Builder { 123 private byte[] mVerifiedBootKey; 124 private boolean mDeviceLocked = false; 125 private int mVerifiedBootState = -1; 126 private byte[] mVerifiedBootHash; 127 setVerifiedBootKey(byte[] verifiedBootKey)128 public Builder setVerifiedBootKey(byte[] verifiedBootKey) { 129 this.mVerifiedBootKey = verifiedBootKey; 130 return this; 131 } setDeviceLocked(boolean deviceLocked)132 public Builder setDeviceLocked(boolean deviceLocked) { 133 this.mDeviceLocked = deviceLocked; 134 return this; 135 } setVerifiedBootState(int verifiedBootState)136 public Builder setVerifiedBootState(int verifiedBootState) { 137 this.mVerifiedBootState = verifiedBootState; 138 return this; 139 } setVerifiedBootHash(byte[] verifiedBootHash)140 public Builder setVerifiedBootHash(byte[] verifiedBootHash) { 141 this.mVerifiedBootHash = verifiedBootHash; 142 return this; 143 } build()144 public RootOfTrust build() { 145 return new RootOfTrust(mVerifiedBootKey, mDeviceLocked, 146 mVerifiedBootState, mVerifiedBootHash); 147 } 148 } 149 } 150