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.car.encryptionrunner; 18 19 import android.annotation.NonNull; 20 21 /** 22 * A generalized interface that allows for generating shared secrets as well as encrypting 23 * messages. 24 * 25 * To use this interface: 26 * 27 * <p>1. As a client. 28 * 29 * {@code 30 * HandshakeMessage initialClientMessage = clientRunner.initHandshake(); 31 * sendToServer(initialClientMessage.getNextMessage()); 32 * byte message = getServerResponse(); 33 * HandshakeMessage message = clientRunner.continueHandshake(message); 34 * } 35 * 36 * <p>If it is a first-time connection, 37 * 38 * {@code message.getHandshakeState()} should be VERIFICATION_NEEDED, show user the verification 39 * code and ask to verify. 40 * After user confirmed, {@code HandshakeMessage lastMessage = clientRunner.verifyPin();} otherwise 41 * {@code clientRunner.invalidPin(); } 42 * 43 * Use {@code lastMessage.getKey()} to get the key for encryption. 44 * 45 * <p>If it is a reconnection, 46 * 47 * {@code message.getHandshakeState()} should be RESUMING_SESSION, PIN has been verified blindly, 48 * send the authentication message over to server, then authenticate the message from server. 49 * 50 * {@code 51 * clientMessage = clientRunner.initReconnectAuthentication(previousKey) 52 * sendToServer(clientMessage.getNextMessage()); 53 * HandshakeMessage lastMessage = clientRunner.authenticateReconnection(previousKey, message) 54 * } 55 * 56 * {@code lastMessage.getHandshakeState()} should be FINISHED if reconnection handshake is done. 57 * 58 * <p>2. As a server. 59 * 60 * {@code 61 * byte[] initialMessage = getClientMessageBytes(); 62 * HandshakeMessage message = serverRunner.respondToInitRequest(initialMessage); 63 * sendToClient(message.getNextMessage()); 64 * byte[] clientMessage = getClientResponse(); 65 * HandshakeMessage message = serverRunner.continueHandshake(clientMessage);} 66 * 67 * <p>if it is a first-time connection, 68 * 69 * {@code message.getHandshakeState()} should be VERIFICATION_NEEDED, show user the verification 70 * code and ask to verify. 71 * After PIN is confirmed, {@code HandshakeMessage lastMessage = serverRunner.verifyPin}, otherwise 72 * {@code clientRunner.invalidPin(); } 73 * Use {@code lastMessage.getKey()} to get the key for encryption. 74 * 75 * <p>If it is a reconnection, 76 * 77 * {@code message.getHandshakeState()} should be RESUMING_SESSION,PIN has been verified blindly, 78 * waiting for client message. 79 * After client message been received, 80 * {@code serverMessage = serverRunner.authenticateReconnection(previousKey, message); 81 * sendToClient(serverMessage.getNextMessage());} 82 * {@code serverMessage.getHandshakeState()} should be FINISHED if reconnection handshake is done. 83 * 84 * Also see {@link EncryptionRunnerTest} for examples. 85 */ 86 public interface EncryptionRunner { 87 88 String TAG = "EncryptionRunner"; 89 90 /** 91 * Starts an encryption handshake. 92 * 93 * @return A handshake message with information about the handshake that is started. 94 */ 95 @NonNull initHandshake()96 HandshakeMessage initHandshake(); 97 98 /** 99 * Starts an encryption handshake where the device that is being communicated with already 100 * initiated the request. 101 * 102 * @param initializationRequest the bytes that the other device sent over. 103 * @return a handshake message with information about the handshake. 104 * @throws HandshakeException if initialization request is invalid. 105 */ 106 @NonNull respondToInitRequest(@onNull byte[] initializationRequest)107 HandshakeMessage respondToInitRequest(@NonNull byte[] initializationRequest) 108 throws HandshakeException; 109 110 /** 111 * Continues a handshake after receiving another response from the connected device. 112 * 113 * @param response the response from the other device. 114 * @return a message that can be used to continue the handshake. 115 * @throws HandshakeException if unexpected bytes in response. 116 */ 117 @NonNull continueHandshake(@onNull byte[] response)118 HandshakeMessage continueHandshake(@NonNull byte[] response) throws HandshakeException; 119 120 /** 121 * Verifies the pin shown to the user. The result is the next handshake message and will 122 * typically contain an encryption key. 123 * 124 * @throws HandshakeException if not in state to verify pin. 125 */ 126 @NonNull verifyPin()127 HandshakeMessage verifyPin() throws HandshakeException; 128 129 /** 130 * Notifies the encryption runner that the user failed to validate the pin. After calling this 131 * method the runner should not be used, and will throw exceptions. 132 */ invalidPin()133 void invalidPin(); 134 135 /** 136 * Verifies the reconnection message. 137 * 138 * <p>The message passed to this method should have been generated by 139 * {@link #initReconnectAuthentication(byte[] previousKey)}. 140 * 141 * <p>If the message is valid, then a {@link HandshakeMessage} will be returned that contains 142 * the encryption key and a handshake message which can be used to verify the other side of the 143 * connection. 144 * 145 * @param previousKey previously stored key. 146 * @param message message from the client 147 * @return a handshake message with an encryption key if verification succeed. 148 * @throws HandshakeException if the message does not match. 149 */ 150 @NonNull authenticateReconnection(@onNull byte[] message, @NonNull byte[] previousKey)151 HandshakeMessage authenticateReconnection(@NonNull byte[] message, @NonNull byte[] previousKey) 152 throws HandshakeException; 153 154 /** 155 * Initiates the reconnection verification by generating a message that should be sent to the 156 * device that is being reconnected to. 157 * 158 * @param previousKey previously stored key. 159 * @return a handshake message with client's message which will be sent to server. 160 * @throws HandshakeException when get encryption key's unique session fail. 161 */ 162 @NonNull initReconnectAuthentication(@onNull byte[] previousKey)163 HandshakeMessage initReconnectAuthentication(@NonNull byte[] previousKey) 164 throws HandshakeException; 165 166 /** 167 * De-serializes a previously serialized key generated by an instance of this encryption runner. 168 * 169 * @param serialized the serialized bytes of the key. 170 * @return the Key object used for encryption. 171 */ 172 @NonNull keyOf(@onNull byte[] serialized)173 Key keyOf(@NonNull byte[] serialized); 174 175 /** 176 * Set the signal if it is a reconnection process. 177 * 178 * @param isReconnect {@code true} if it is a reconnect. 179 */ setIsReconnect(boolean isReconnect)180 void setIsReconnect(boolean isReconnect); 181 } 182