1 /* 2 * Copyright (C) 2020 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 android.security; 18 19 import android.annotation.NonNull; 20 import android.hardware.security.keymint.KeyParameter; 21 import android.os.Binder; 22 import android.os.RemoteException; 23 import android.os.ServiceSpecificException; 24 import android.os.StrictMode; 25 import android.security.keymaster.KeymasterDefs; 26 import android.system.keystore2.IKeystoreOperation; 27 import android.system.keystore2.ResponseCode; 28 import android.util.Log; 29 30 /** 31 * @hide 32 */ 33 public class KeyStoreOperation { 34 static final String TAG = "KeyStoreOperation"; 35 private final IKeystoreOperation mOperation; 36 private final Long mChallenge; 37 private final KeyParameter[] mParameters; 38 KeyStoreOperation( @onNull IKeystoreOperation operation, Long challenge, KeyParameter[] parameters )39 public KeyStoreOperation( 40 @NonNull IKeystoreOperation operation, 41 Long challenge, 42 KeyParameter[] parameters 43 ) { 44 Binder.allowBlocking(operation.asBinder()); 45 this.mOperation = operation; 46 this.mChallenge = challenge; 47 this.mParameters = parameters; 48 } 49 50 /** 51 * Gets the challenge associated with this operation. 52 * @return null if the operation does not required authorization. A 64bit operation 53 * challenge otherwise. 54 */ getChallenge()55 public Long getChallenge() { 56 return mChallenge; 57 } 58 59 /** 60 * Gets the parameters associated with this operation. 61 * @return 62 */ getParameters()63 public KeyParameter[] getParameters() { 64 return mParameters; 65 } 66 handleExceptions(@onNull CheckedRemoteRequest<R> request)67 private <R> R handleExceptions(@NonNull CheckedRemoteRequest<R> request) 68 throws KeyStoreException { 69 try { 70 return request.execute(); 71 } catch (ServiceSpecificException e) { 72 switch(e.errorCode) { 73 case ResponseCode.OPERATION_BUSY: { 74 throw new IllegalThreadStateException( 75 "Cannot update the same operation concurrently." 76 ); 77 } 78 default: 79 throw KeyStore2.getKeyStoreException(e.errorCode, e.getMessage()); 80 } 81 } catch (RemoteException e) { 82 // Log exception and report invalid operation handle. 83 // This should prompt the caller drop the reference to this operation and retry. 84 Log.e( 85 TAG, 86 "Remote exception while advancing a KeyStoreOperation.", 87 e 88 ); 89 throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_OPERATION_HANDLE, "", 90 e.getMessage()); 91 } 92 } 93 94 /** 95 * Updates the Keystore operation represented by this object with more associated data. 96 * @see IKeystoreOperation#updateAad(byte[]) for more details. 97 * @param input 98 * @throws KeyStoreException 99 */ updateAad(@onNull byte[] input)100 public void updateAad(@NonNull byte[] input) throws KeyStoreException { 101 StrictMode.noteSlowCall("updateAad"); 102 handleExceptions(() -> { 103 mOperation.updateAad(input); 104 return 0; 105 }); 106 } 107 108 /** 109 * Updates the Keystore operation represented by this object. 110 * @see IKeystoreOperation#update(byte[]) for more details. 111 * @param input 112 * @return 113 * @throws KeyStoreException 114 * @hide 115 */ update(@onNull byte[] input)116 public byte[] update(@NonNull byte[] input) throws KeyStoreException { 117 StrictMode.noteSlowCall("update"); 118 return handleExceptions(() -> mOperation.update(input)); 119 } 120 121 /** 122 * Finalizes the Keystore operation represented by this object. 123 * @see IKeystoreOperation#finish(byte[], byte[]) for more details. 124 * @param input 125 * @param signature 126 * @return 127 * @throws KeyStoreException 128 * @hide 129 */ finish(byte[] input, byte[] signature)130 public byte[] finish(byte[] input, byte[] signature) throws KeyStoreException { 131 StrictMode.noteSlowCall("finish"); 132 return handleExceptions(() -> mOperation.finish(input, signature)); 133 } 134 135 /** 136 * Aborts the Keystore operation represented by this object. 137 * @see IKeystoreOperation#abort() for more details. 138 * @throws KeyStoreException 139 * @hide 140 */ abort()141 public void abort() throws KeyStoreException { 142 StrictMode.noteSlowCall("abort"); 143 handleExceptions(() -> { 144 mOperation.abort(); 145 return 0; 146 }); 147 } 148 } 149