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 com.google.attestationexample; 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[] verifiedBootKey; 38 private final byte[] verifiedBootHash; 39 private final boolean deviceLocked; 40 private final int verifiedBootState; 41 RootOfTrust(ASN1Encodable asn1Encodable)42 public RootOfTrust(ASN1Encodable asn1Encodable) throws CertificateParsingException { 43 if (!(asn1Encodable instanceof ASN1Sequence)) { 44 throw new CertificateParsingException("Expected sequence for root of trust, found " 45 + asn1Encodable.getClass().getName()); 46 } 47 48 ASN1Sequence sequence = (ASN1Sequence) asn1Encodable; 49 if (sequence.size() != 4) { 50 throw new CertificateParsingException( 51 "Incorrect size, actual size is:" + sequence.size()); 52 } 53 verifiedBootKey = 54 Asn1Utils.getByteArrayFromAsn1(sequence.getObjectAt(VERIFIED_BOOT_KEY_INDEX)); 55 deviceLocked = Asn1Utils.getBooleanFromAsn1(sequence.getObjectAt(DEVICE_LOCKED_INDEX)); 56 verifiedBootState = 57 Asn1Utils.getIntegerFromAsn1(sequence.getObjectAt(VERIFIED_BOOT_STATE_INDEX)); 58 verifiedBootHash = 59 Asn1Utils.getByteArrayFromAsn1(sequence.getObjectAt(VERIFIED_BOOT_HASH_INDEX)); 60 } 61 verifiedBootStateToString(int verifiedBootState)62 public static String verifiedBootStateToString(int verifiedBootState) { 63 switch (verifiedBootState) { 64 case KM_VERIFIED_BOOT_VERIFIED: 65 return "Verified"; 66 case KM_VERIFIED_BOOT_SELF_SIGNED: 67 return "Self-signed"; 68 case KM_VERIFIED_BOOT_UNVERIFIED: 69 return "Unverified"; 70 case KM_VERIFIED_BOOT_FAILED: 71 return "Failed"; 72 default: 73 return "Unknown"; 74 } 75 } 76 getVerifiedBootKey()77 public byte[] getVerifiedBootKey() { 78 return verifiedBootKey; 79 } 80 isDeviceLocked()81 public boolean isDeviceLocked() { 82 return deviceLocked; 83 } 84 getVerifiedBootState()85 public int getVerifiedBootState() { 86 return verifiedBootState; 87 } 88 getVerifiedBootHash()89 public byte[] getVerifiedBootHash() { return verifiedBootHash; } 90 91 @Override toString()92 public String toString() { 93 return new StringBuilder() 94 .append("Verified boot Key: ") 95 .append(BaseEncoding.base64().encode(verifiedBootKey)) 96 .append("\nDevice locked: ") 97 .append(deviceLocked) 98 .append("\nVerified boot state: ") 99 .append(verifiedBootStateToString(verifiedBootState)) 100 .append("\nVerified boot hash: ") 101 .append(BaseEncoding.base64().encode(verifiedBootHash)) 102 .toString(); 103 } 104 } 105