1 /* 2 * Copyright (C) 2021 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.android.server.security; 18 19 import static android.Manifest.permission.USE_ATTESTATION_VERIFICATION_SERVICE; 20 import static android.security.attestationverification.AttestationVerificationManager.FLAG_FAILURE_CERTS; 21 import static android.security.attestationverification.AttestationVerificationManager.FLAG_FAILURE_UNSUPPORTED_PROFILE; 22 import static android.security.attestationverification.AttestationVerificationManager.PROFILE_PEER_DEVICE; 23 import static android.security.attestationverification.AttestationVerificationManager.PROFILE_SELF_TRUSTED; 24 25 import android.annotation.NonNull; 26 import android.annotation.Nullable; 27 import android.content.Context; 28 import android.os.Bundle; 29 import android.os.IBinder; 30 import android.os.ParcelDuration; 31 import android.os.RemoteException; 32 import android.security.attestationverification.AttestationProfile; 33 import android.security.attestationverification.IAttestationVerificationManagerService; 34 import android.security.attestationverification.IVerificationResult; 35 import android.security.attestationverification.VerificationToken; 36 import android.text.TextUtils; 37 import android.util.ExceptionUtils; 38 import android.util.IndentingPrintWriter; 39 import android.util.Slog; 40 import android.util.TimeUtils; 41 42 import com.android.internal.infra.AndroidFuture; 43 import com.android.internal.util.DumpUtils; 44 import com.android.server.SystemService; 45 46 import java.io.FileDescriptor; 47 import java.io.PrintWriter; 48 import java.util.ArrayDeque; 49 50 /** 51 * A {@link SystemService} which provides functionality related to verifying attestations of 52 * (usually) remote computing environments. 53 * 54 * @hide 55 */ 56 public class AttestationVerificationManagerService extends SystemService { 57 58 private static final String TAG = "AVF"; 59 private static final int DUMP_EVENT_LOG_SIZE = 10; 60 private final AttestationVerificationPeerDeviceVerifier mPeerDeviceVerifier; 61 private final DumpLogger mDumpLogger = new DumpLogger(); 62 AttestationVerificationManagerService(final Context context)63 public AttestationVerificationManagerService(final Context context) throws Exception { 64 super(context); 65 mPeerDeviceVerifier = new AttestationVerificationPeerDeviceVerifier(context, mDumpLogger); 66 } 67 68 private final IBinder mService = new IAttestationVerificationManagerService.Stub() { 69 @Override 70 public void verifyAttestation( 71 AttestationProfile profile, 72 int localBindingType, 73 Bundle requirements, 74 byte[] attestation, 75 AndroidFuture resultCallback) throws RemoteException { 76 enforceUsePermission(); 77 try { 78 Slog.d(TAG, "verifyAttestation"); 79 verifyAttestationForAllVerifiers(profile, localBindingType, requirements, 80 attestation, resultCallback); 81 } catch (Throwable t) { 82 Slog.e(TAG, "failed to verify attestation", t); 83 throw ExceptionUtils.propagate(t, RemoteException.class); 84 } 85 } 86 87 @Override 88 public void verifyToken(VerificationToken token, ParcelDuration parcelDuration, 89 AndroidFuture resultCallback) throws RemoteException { 90 enforceUsePermission(); 91 92 throw new UnsupportedOperationException(); 93 } 94 95 private void enforceUsePermission() { 96 getContext().enforceCallingOrSelfPermission(USE_ATTESTATION_VERIFICATION_SERVICE, null); 97 } 98 99 @Override 100 protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, 101 @Nullable String[] args) { 102 if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, writer)) return; 103 104 final IndentingPrintWriter fout = new IndentingPrintWriter(writer, " "); 105 106 fout.print("AttestationVerificationManagerService"); 107 fout.println(); 108 fout.increaseIndent(); 109 110 fout.println("Event Log:"); 111 fout.increaseIndent(); 112 mDumpLogger.dumpTo(fout); 113 fout.decreaseIndent(); 114 } 115 }; 116 verifyAttestationForAllVerifiers( AttestationProfile profile, int localBindingType, Bundle requirements, byte[] attestation, AndroidFuture<IVerificationResult> resultCallback)117 private void verifyAttestationForAllVerifiers( 118 AttestationProfile profile, int localBindingType, Bundle requirements, 119 byte[] attestation, AndroidFuture<IVerificationResult> resultCallback) { 120 IVerificationResult result = new IVerificationResult(); 121 result.token = null; 122 int profileId = profile.getAttestationProfileId(); 123 switch (profileId) { 124 case PROFILE_SELF_TRUSTED: 125 Slog.d(TAG, "Verifying Self Trusted profile."); 126 try { 127 result.resultCode = 128 AttestationVerificationSelfTrustedVerifierForTesting.getInstance() 129 .verifyAttestation(localBindingType, requirements, attestation); 130 } catch (Throwable t) { 131 result.resultCode = FLAG_FAILURE_CERTS; 132 } 133 break; 134 case PROFILE_PEER_DEVICE: 135 Slog.d(TAG, "Verifying Peer Device profile."); 136 result.resultCode = mPeerDeviceVerifier.verifyAttestation( 137 localBindingType, requirements, attestation); 138 break; 139 default: 140 Slog.e(TAG, "Profile [" + profileId + "] is not supported."); 141 result.resultCode = FLAG_FAILURE_UNSUPPORTED_PROFILE; 142 } 143 resultCallback.complete(result); 144 } 145 146 @Override onStart()147 public void onStart() { 148 Slog.d(TAG, "Started"); 149 publishBinderService(Context.ATTESTATION_VERIFICATION_SERVICE, mService); 150 } 151 152 153 static class DumpLogger { 154 private final ArrayDeque<DumpData> mData = new ArrayDeque<>(DUMP_EVENT_LOG_SIZE); 155 private int mEventsLogged = 0; 156 logAttempt(DumpData data)157 void logAttempt(DumpData data) { 158 synchronized (mData) { 159 if (mData.size() == DUMP_EVENT_LOG_SIZE) { 160 mData.removeFirst(); 161 } 162 163 mEventsLogged++; 164 data.mEventNumber = mEventsLogged; 165 166 data.mEventTimeMs = System.currentTimeMillis(); 167 168 mData.add(data); 169 } 170 } 171 dumpTo(IndentingPrintWriter writer)172 void dumpTo(IndentingPrintWriter writer) { 173 synchronized (mData) { 174 for (DumpData data : mData.reversed()) { 175 writer.println( 176 TextUtils.formatSimple("Verification #%d [%s]", data.mEventNumber, 177 TimeUtils.formatForLogging(data.mEventTimeMs))); 178 writer.increaseIndent(); 179 data.dumpTo(writer); 180 writer.decreaseIndent(); 181 } 182 } 183 } 184 } 185 186 abstract static class DumpData { 187 protected int mEventNumber = -1; 188 protected long mEventTimeMs = -1; 189 dumpTo(IndentingPrintWriter writer)190 abstract void dumpTo(IndentingPrintWriter writer); 191 } 192 } 193