• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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