/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.attestationexample; import com.google.common.io.BaseEncoding; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1Sequence; import java.security.cert.CertificateParsingException; public class RootOfTrust { private static final int VERIFIED_BOOT_KEY_INDEX = 0; private static final int DEVICE_LOCKED_INDEX = 1; private static final int VERIFIED_BOOT_STATE_INDEX = 2; private static final int VERIFIED_BOOT_HASH_INDEX = 3; public static final int KM_VERIFIED_BOOT_VERIFIED = 0; public static final int KM_VERIFIED_BOOT_SELF_SIGNED = 1; public static final int KM_VERIFIED_BOOT_UNVERIFIED = 2; public static final int KM_VERIFIED_BOOT_FAILED = 3; private final byte[] verifiedBootKey; private final byte[] verifiedBootHash; private final boolean deviceLocked; private final int verifiedBootState; public RootOfTrust(ASN1Encodable asn1Encodable) throws CertificateParsingException { if (!(asn1Encodable instanceof ASN1Sequence)) { throw new CertificateParsingException("Expected sequence for root of trust, found " + asn1Encodable.getClass().getName()); } ASN1Sequence sequence = (ASN1Sequence) asn1Encodable; if (sequence.size() != 4) { throw new CertificateParsingException( "Incorrect size, actual size is:" + sequence.size()); } verifiedBootKey = Asn1Utils.getByteArrayFromAsn1(sequence.getObjectAt(VERIFIED_BOOT_KEY_INDEX)); deviceLocked = Asn1Utils.getBooleanFromAsn1(sequence.getObjectAt(DEVICE_LOCKED_INDEX)); verifiedBootState = Asn1Utils.getIntegerFromAsn1(sequence.getObjectAt(VERIFIED_BOOT_STATE_INDEX)); verifiedBootHash = Asn1Utils.getByteArrayFromAsn1(sequence.getObjectAt(VERIFIED_BOOT_HASH_INDEX)); } public static String verifiedBootStateToString(int verifiedBootState) { switch (verifiedBootState) { case KM_VERIFIED_BOOT_VERIFIED: return "Verified"; case KM_VERIFIED_BOOT_SELF_SIGNED: return "Self-signed"; case KM_VERIFIED_BOOT_UNVERIFIED: return "Unverified"; case KM_VERIFIED_BOOT_FAILED: return "Failed"; default: return "Unknown"; } } public byte[] getVerifiedBootKey() { return verifiedBootKey; } public boolean isDeviceLocked() { return deviceLocked; } public int getVerifiedBootState() { return verifiedBootState; } public byte[] getVerifiedBootHash() { return verifiedBootHash; } @Override public String toString() { return new StringBuilder() .append("Verified boot Key: ") .append(BaseEncoding.base64().encode(verifiedBootKey)) .append("\nDevice locked: ") .append(deviceLocked) .append("\nVerified boot state: ") .append(verifiedBootStateToString(verifiedBootState)) .append("\nVerified boot hash: ") .append(BaseEncoding.base64().encode(verifiedBootHash)) .toString(); } }