Loading core/java/android/security/rkp/IRemoteProvisioning.aidl +0 −7 Original line number Diff line number Diff line Loading @@ -58,11 +58,4 @@ oneway interface IRemoteProvisioning { * */ void getRegistration(String irpcName, IGetRegistrationCallback callback); /** * Cancel any active {@link getRegistration} call associated with the given * callback. If no getRegistration call is currently active, this function is * a noop. */ void cancelGetRegistration(IGetRegistrationCallback callback); } services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java 0 → 100644 +132 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 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.android.server.security.rkp; import android.os.CancellationSignal; import android.os.OperationCanceledException; import android.os.OutcomeReceiver; import android.security.rkp.IGetKeyCallback; import android.security.rkp.IRegistration; import android.security.rkp.service.RegistrationProxy; import android.security.rkp.service.RemotelyProvisionedKey; import android.util.Log; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; /** * Implements android.security.rkp.IRegistration as a thin wrapper around the java code * exported by com.android.rkp. * * @hide */ final class RemoteProvisioningRegistration extends IRegistration.Stub { static final String TAG = RemoteProvisioningService.TAG; private final ConcurrentHashMap<IGetKeyCallback, CancellationSignal> mOperations = new ConcurrentHashMap<>(); private final RegistrationProxy mRegistration; private final Executor mExecutor; private class GetKeyReceiver implements OutcomeReceiver<RemotelyProvisionedKey, Exception> { IGetKeyCallback mCallback; GetKeyReceiver(IGetKeyCallback callback) { mCallback = callback; } @Override public void onResult(RemotelyProvisionedKey result) { mOperations.remove(mCallback); Log.i(TAG, "Successfully fetched key for client " + mCallback.hashCode()); android.security.rkp.RemotelyProvisionedKey parcelable = new android.security.rkp.RemotelyProvisionedKey(); parcelable.keyBlob = result.getKeyBlob(); parcelable.encodedCertChain = result.getEncodedCertChain(); wrapCallback(() -> mCallback.onSuccess(parcelable)); } @Override public void onError(Exception e) { mOperations.remove(mCallback); if (e instanceof OperationCanceledException) { Log.i(TAG, "Operation cancelled for client " + mCallback.hashCode()); wrapCallback(mCallback::onCancel); } else { Log.e(TAG, "Error fetching key for client " + mCallback.hashCode(), e); wrapCallback(() -> mCallback.onError(e.getMessage())); } } } RemoteProvisioningRegistration(RegistrationProxy registration, Executor executor) { mRegistration = registration; mExecutor = executor; } @Override public void getKey(int keyId, IGetKeyCallback callback) { CancellationSignal cancellationSignal = new CancellationSignal(); if (mOperations.putIfAbsent(callback, cancellationSignal) != null) { Log.e(TAG, "Client can only request one call at a time " + callback.hashCode()); throw new IllegalArgumentException( "Callback is already associated with an existing operation: " + callback.hashCode()); } try { Log.i(TAG, "Fetching key " + keyId + " for client " + callback.hashCode()); mRegistration.getKeyAsync(keyId, cancellationSignal, mExecutor, new GetKeyReceiver(callback)); } catch (Exception e) { Log.e(TAG, "getKeyAsync threw an exception for client " + callback.hashCode(), e); mOperations.remove(callback); wrapCallback(() -> callback.onError(e.getMessage())); } } @Override public void cancelGetKey(IGetKeyCallback callback) { CancellationSignal cancellationSignal = mOperations.remove(callback); if (cancellationSignal == null) { throw new IllegalArgumentException( "Invalid client in cancelGetKey: " + callback.hashCode()); } Log.i(TAG, "Requesting cancellation for client " + callback.hashCode()); cancellationSignal.cancel(); } @Override public void storeUpgradedKey(byte[] oldKeyBlob, byte[] newKeyBlob) { // TODO(b/262748535) Log.e(TAG, "RegistrationBinder.storeUpgradedKey NOT YET IMPLEMENTED"); } interface CallbackRunner { void run() throws Exception; } private void wrapCallback(CallbackRunner callback) { // Exceptions resulting from notifications to IGetKeyCallback objects can only be logged, // since getKey execution is asynchronous, and there's no way for an exception to be // properly handled up the stack. try { callback.run(); } catch (Exception e) { Log.e(TAG, "Error invoking callback on client binder", e); } } } services/core/java/com/android/server/security/rkp/RemoteProvisioningService.java +34 −59 Original line number Diff line number Diff line Loading @@ -20,9 +20,7 @@ import android.content.Context; import android.os.Binder; import android.os.OutcomeReceiver; import android.os.RemoteException; import android.security.rkp.IGetKeyCallback; import android.security.rkp.IGetRegistrationCallback; import android.security.rkp.IRegistration; import android.security.rkp.IRemoteProvisioning; import android.security.rkp.service.RegistrationProxy; import android.util.Log; Loading @@ -30,6 +28,7 @@ import android.util.Log; import com.android.server.SystemService; import java.time.Duration; import java.util.concurrent.Executor; /** * Implements the remote provisioning system service. This service is backed by a mainline Loading @@ -43,84 +42,60 @@ public class RemoteProvisioningService extends SystemService { private static final Duration CREATE_REGISTRATION_TIMEOUT = Duration.ofSeconds(10); private final RemoteProvisioningImpl mBinderImpl = new RemoteProvisioningImpl(); /** @hide */ public RemoteProvisioningService(Context context) { super(context); private static class RegistrationReceiver implements OutcomeReceiver<RegistrationProxy, Exception> { private final Executor mExecutor; private final IGetRegistrationCallback mCallback; RegistrationReceiver(Executor executor, IGetRegistrationCallback callback) { mExecutor = executor; mCallback = callback; } @Override public void onStart() { publishBinderService(Context.REMOTE_PROVISIONING_SERVICE, mBinderImpl); public void onResult(RegistrationProxy registration) { try { mCallback.onSuccess(new RemoteProvisioningRegistration(registration, mExecutor)); } catch (RemoteException e) { Log.e(TAG, "Error calling success callback " + mCallback.hashCode(), e); } private final class RemoteProvisioningImpl extends IRemoteProvisioning.Stub { final class RegistrationBinder extends IRegistration.Stub { static final String TAG = RemoteProvisioningService.TAG; private final RegistrationProxy mRegistration; RegistrationBinder(RegistrationProxy registration) { mRegistration = registration; } @Override public void getKey(int keyId, IGetKeyCallback callback) { Log.e(TAG, "RegistrationBinder.getKey NOT YET IMPLEMENTED"); public void onError(Exception error) { try { mCallback.onError(error.toString()); } catch (RemoteException e) { Log.e(TAG, "Error calling error callback " + mCallback.hashCode(), e); } } } @Override public void cancelGetKey(IGetKeyCallback callback) { Log.e(TAG, "RegistrationBinder.cancelGetKey NOT YET IMPLEMENTED"); /** @hide */ public RemoteProvisioningService(Context context) { super(context); } @Override public void storeUpgradedKey(byte[] oldKeyBlob, byte[] newKeyBlob) { Log.e(TAG, "RegistrationBinder.storeUpgradedKey NOT YET IMPLEMENTED"); } public void onStart() { publishBinderService(Context.REMOTE_PROVISIONING_SERVICE, mBinderImpl); } private final class RemoteProvisioningImpl extends IRemoteProvisioning.Stub { @Override public void getRegistration(String irpcName, IGetRegistrationCallback callback) throws RemoteException { final int callerUid = Binder.getCallingUidOrThrow(); final long callingIdentity = Binder.clearCallingIdentity(); final Executor executor = getContext().getMainExecutor(); try { Log.i(TAG, "getRegistration(" + irpcName + ")"); RegistrationProxy.createAsync( getContext(), callerUid, irpcName, CREATE_REGISTRATION_TIMEOUT, getContext().getMainExecutor(), new OutcomeReceiver<>() { @Override public void onResult(RegistrationProxy registration) { try { callback.onSuccess(new RegistrationBinder(registration)); } catch (RemoteException e) { Log.e(TAG, "Error calling success callback", e); } } @Override public void onError(Exception error) { try { callback.onError(error.toString()); } catch (RemoteException e) { Log.e(TAG, "Error calling error callback", e); } } }); RegistrationProxy.createAsync(getContext(), callerUid, irpcName, CREATE_REGISTRATION_TIMEOUT, executor, new RegistrationReceiver(executor, callback)); } finally { Binder.restoreCallingIdentity(callingIdentity); } } @Override public void cancelGetRegistration(IGetRegistrationCallback callback) throws RemoteException { Log.i(TAG, "cancelGetRegistration()"); callback.onError("cancelGetRegistration not yet implemented"); } } } Loading
core/java/android/security/rkp/IRemoteProvisioning.aidl +0 −7 Original line number Diff line number Diff line Loading @@ -58,11 +58,4 @@ oneway interface IRemoteProvisioning { * */ void getRegistration(String irpcName, IGetRegistrationCallback callback); /** * Cancel any active {@link getRegistration} call associated with the given * callback. If no getRegistration call is currently active, this function is * a noop. */ void cancelGetRegistration(IGetRegistrationCallback callback); }
services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java 0 → 100644 +132 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 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.android.server.security.rkp; import android.os.CancellationSignal; import android.os.OperationCanceledException; import android.os.OutcomeReceiver; import android.security.rkp.IGetKeyCallback; import android.security.rkp.IRegistration; import android.security.rkp.service.RegistrationProxy; import android.security.rkp.service.RemotelyProvisionedKey; import android.util.Log; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; /** * Implements android.security.rkp.IRegistration as a thin wrapper around the java code * exported by com.android.rkp. * * @hide */ final class RemoteProvisioningRegistration extends IRegistration.Stub { static final String TAG = RemoteProvisioningService.TAG; private final ConcurrentHashMap<IGetKeyCallback, CancellationSignal> mOperations = new ConcurrentHashMap<>(); private final RegistrationProxy mRegistration; private final Executor mExecutor; private class GetKeyReceiver implements OutcomeReceiver<RemotelyProvisionedKey, Exception> { IGetKeyCallback mCallback; GetKeyReceiver(IGetKeyCallback callback) { mCallback = callback; } @Override public void onResult(RemotelyProvisionedKey result) { mOperations.remove(mCallback); Log.i(TAG, "Successfully fetched key for client " + mCallback.hashCode()); android.security.rkp.RemotelyProvisionedKey parcelable = new android.security.rkp.RemotelyProvisionedKey(); parcelable.keyBlob = result.getKeyBlob(); parcelable.encodedCertChain = result.getEncodedCertChain(); wrapCallback(() -> mCallback.onSuccess(parcelable)); } @Override public void onError(Exception e) { mOperations.remove(mCallback); if (e instanceof OperationCanceledException) { Log.i(TAG, "Operation cancelled for client " + mCallback.hashCode()); wrapCallback(mCallback::onCancel); } else { Log.e(TAG, "Error fetching key for client " + mCallback.hashCode(), e); wrapCallback(() -> mCallback.onError(e.getMessage())); } } } RemoteProvisioningRegistration(RegistrationProxy registration, Executor executor) { mRegistration = registration; mExecutor = executor; } @Override public void getKey(int keyId, IGetKeyCallback callback) { CancellationSignal cancellationSignal = new CancellationSignal(); if (mOperations.putIfAbsent(callback, cancellationSignal) != null) { Log.e(TAG, "Client can only request one call at a time " + callback.hashCode()); throw new IllegalArgumentException( "Callback is already associated with an existing operation: " + callback.hashCode()); } try { Log.i(TAG, "Fetching key " + keyId + " for client " + callback.hashCode()); mRegistration.getKeyAsync(keyId, cancellationSignal, mExecutor, new GetKeyReceiver(callback)); } catch (Exception e) { Log.e(TAG, "getKeyAsync threw an exception for client " + callback.hashCode(), e); mOperations.remove(callback); wrapCallback(() -> callback.onError(e.getMessage())); } } @Override public void cancelGetKey(IGetKeyCallback callback) { CancellationSignal cancellationSignal = mOperations.remove(callback); if (cancellationSignal == null) { throw new IllegalArgumentException( "Invalid client in cancelGetKey: " + callback.hashCode()); } Log.i(TAG, "Requesting cancellation for client " + callback.hashCode()); cancellationSignal.cancel(); } @Override public void storeUpgradedKey(byte[] oldKeyBlob, byte[] newKeyBlob) { // TODO(b/262748535) Log.e(TAG, "RegistrationBinder.storeUpgradedKey NOT YET IMPLEMENTED"); } interface CallbackRunner { void run() throws Exception; } private void wrapCallback(CallbackRunner callback) { // Exceptions resulting from notifications to IGetKeyCallback objects can only be logged, // since getKey execution is asynchronous, and there's no way for an exception to be // properly handled up the stack. try { callback.run(); } catch (Exception e) { Log.e(TAG, "Error invoking callback on client binder", e); } } }
services/core/java/com/android/server/security/rkp/RemoteProvisioningService.java +34 −59 Original line number Diff line number Diff line Loading @@ -20,9 +20,7 @@ import android.content.Context; import android.os.Binder; import android.os.OutcomeReceiver; import android.os.RemoteException; import android.security.rkp.IGetKeyCallback; import android.security.rkp.IGetRegistrationCallback; import android.security.rkp.IRegistration; import android.security.rkp.IRemoteProvisioning; import android.security.rkp.service.RegistrationProxy; import android.util.Log; Loading @@ -30,6 +28,7 @@ import android.util.Log; import com.android.server.SystemService; import java.time.Duration; import java.util.concurrent.Executor; /** * Implements the remote provisioning system service. This service is backed by a mainline Loading @@ -43,84 +42,60 @@ public class RemoteProvisioningService extends SystemService { private static final Duration CREATE_REGISTRATION_TIMEOUT = Duration.ofSeconds(10); private final RemoteProvisioningImpl mBinderImpl = new RemoteProvisioningImpl(); /** @hide */ public RemoteProvisioningService(Context context) { super(context); private static class RegistrationReceiver implements OutcomeReceiver<RegistrationProxy, Exception> { private final Executor mExecutor; private final IGetRegistrationCallback mCallback; RegistrationReceiver(Executor executor, IGetRegistrationCallback callback) { mExecutor = executor; mCallback = callback; } @Override public void onStart() { publishBinderService(Context.REMOTE_PROVISIONING_SERVICE, mBinderImpl); public void onResult(RegistrationProxy registration) { try { mCallback.onSuccess(new RemoteProvisioningRegistration(registration, mExecutor)); } catch (RemoteException e) { Log.e(TAG, "Error calling success callback " + mCallback.hashCode(), e); } private final class RemoteProvisioningImpl extends IRemoteProvisioning.Stub { final class RegistrationBinder extends IRegistration.Stub { static final String TAG = RemoteProvisioningService.TAG; private final RegistrationProxy mRegistration; RegistrationBinder(RegistrationProxy registration) { mRegistration = registration; } @Override public void getKey(int keyId, IGetKeyCallback callback) { Log.e(TAG, "RegistrationBinder.getKey NOT YET IMPLEMENTED"); public void onError(Exception error) { try { mCallback.onError(error.toString()); } catch (RemoteException e) { Log.e(TAG, "Error calling error callback " + mCallback.hashCode(), e); } } } @Override public void cancelGetKey(IGetKeyCallback callback) { Log.e(TAG, "RegistrationBinder.cancelGetKey NOT YET IMPLEMENTED"); /** @hide */ public RemoteProvisioningService(Context context) { super(context); } @Override public void storeUpgradedKey(byte[] oldKeyBlob, byte[] newKeyBlob) { Log.e(TAG, "RegistrationBinder.storeUpgradedKey NOT YET IMPLEMENTED"); } public void onStart() { publishBinderService(Context.REMOTE_PROVISIONING_SERVICE, mBinderImpl); } private final class RemoteProvisioningImpl extends IRemoteProvisioning.Stub { @Override public void getRegistration(String irpcName, IGetRegistrationCallback callback) throws RemoteException { final int callerUid = Binder.getCallingUidOrThrow(); final long callingIdentity = Binder.clearCallingIdentity(); final Executor executor = getContext().getMainExecutor(); try { Log.i(TAG, "getRegistration(" + irpcName + ")"); RegistrationProxy.createAsync( getContext(), callerUid, irpcName, CREATE_REGISTRATION_TIMEOUT, getContext().getMainExecutor(), new OutcomeReceiver<>() { @Override public void onResult(RegistrationProxy registration) { try { callback.onSuccess(new RegistrationBinder(registration)); } catch (RemoteException e) { Log.e(TAG, "Error calling success callback", e); } } @Override public void onError(Exception error) { try { callback.onError(error.toString()); } catch (RemoteException e) { Log.e(TAG, "Error calling error callback", e); } } }); RegistrationProxy.createAsync(getContext(), callerUid, irpcName, CREATE_REGISTRATION_TIMEOUT, executor, new RegistrationReceiver(executor, callback)); } finally { Binder.restoreCallingIdentity(callingIdentity); } } @Override public void cancelGetRegistration(IGetRegistrationCallback callback) throws RemoteException { Log.i(TAG, "cancelGetRegistration()"); callback.onError("cancelGetRegistration not yet implemented"); } } }