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.text.TextUtils; 20 21 import androidx.annotation.IntDef; 22 import androidx.annotation.NonNull; 23 import androidx.annotation.Nullable; 24 25 import java.lang.annotation.Retention; 26 import java.lang.annotation.RetentionPolicy; 27 28 /** 29 * During an {@link EncryptionRunner} handshake process, these are the messages returned as part 30 * of each step. 31 */ 32 public class HandshakeMessage { 33 34 /** 35 * States for handshake progress. 36 */ 37 @Retention(RetentionPolicy.SOURCE) 38 @IntDef({HandshakeState.UNKNOWN, HandshakeState.IN_PROGRESS, HandshakeState.VERIFICATION_NEEDED, 39 HandshakeState.FINISHED, HandshakeState.INVALID, HandshakeState.RESUMING_SESSION, 40 HandshakeState.OOB_VERIFICATION_NEEDED}) 41 public @interface HandshakeState { 42 /** 43 * The initial state, this value is not expected to be returned. 44 */ 45 int UNKNOWN = 0; 46 /** 47 * The handshake is in progress. 48 */ 49 int IN_PROGRESS = 1; 50 /** 51 * The handshake is complete, but verification of the code is needed. 52 */ 53 int VERIFICATION_NEEDED = 2; 54 /** 55 * The handshake is complete. 56 */ 57 int FINISHED = 3; 58 /** 59 * The handshake is complete and not successful. 60 */ 61 int INVALID = 4; 62 /** 63 * The handshake is complete, but extra verification is needed. 64 */ 65 int RESUMING_SESSION = 5; 66 /** 67 * The handshake is complete, but out of band verification of the code is needed. 68 */ 69 int OOB_VERIFICATION_NEEDED = 6; 70 } 71 72 @HandshakeState 73 private final int mHandshakeState; 74 private final Key mKey; 75 private final byte[] mNextMessage; 76 private final String mVerificationCode; 77 private final byte[] mOobVerificationCode; 78 79 /** 80 * @return Returns a builder for {@link HandshakeMessage}. 81 */ newBuilder()82 public static Builder newBuilder() { 83 return new Builder(); 84 } 85 86 /** 87 * Use the builder; 88 */ HandshakeMessage( @andshakeState int handshakeState, @Nullable Key key, @Nullable byte[] nextMessage, @Nullable String verificationCode, @Nullable byte[] oobVerificationCode)89 private HandshakeMessage( 90 @HandshakeState int handshakeState, 91 @Nullable Key key, 92 @Nullable byte[] nextMessage, 93 @Nullable String verificationCode, 94 @Nullable byte[] oobVerificationCode) { 95 mHandshakeState = handshakeState; 96 mKey = key; 97 mNextMessage = nextMessage; 98 mVerificationCode = verificationCode; 99 mOobVerificationCode = oobVerificationCode; 100 } 101 102 /** 103 * Returns the next message to send in a handshake. 104 */ 105 @Nullable getNextMessage()106 public byte[] getNextMessage() { 107 return mNextMessage == null ? null : mNextMessage.clone(); 108 } 109 110 /** 111 * Returns the state of the handshake. 112 */ 113 @HandshakeState getHandshakeState()114 public int getHandshakeState() { 115 return mHandshakeState; 116 } 117 118 /** 119 * Returns the encryption key that can be used to encrypt data. 120 */ 121 @Nullable getKey()122 public Key getKey() { 123 return mKey; 124 } 125 126 /** 127 * Returns a verification code to show to the user. 128 */ 129 @Nullable getVerificationCode()130 public String getVerificationCode() { 131 return mVerificationCode; 132 } 133 134 /** 135 * Returns a verification code to be encrypted using an out-of-band key and sent to the remote 136 * device. 137 */ 138 @Nullable getOobVerificationCode()139 public byte[] getOobVerificationCode() { 140 return mOobVerificationCode; 141 } 142 143 static class Builder { 144 @HandshakeState 145 int mHandshakeState; 146 Key mKey; 147 byte[] mNextMessage; 148 String mVerificationCode; 149 byte[] mOobVerificationCode; 150 setHandshakeState(@andshakeState int handshakeState)151 Builder setHandshakeState(@HandshakeState int handshakeState) { 152 mHandshakeState = handshakeState; 153 return this; 154 } 155 setKey(@ullable Key key)156 Builder setKey(@Nullable Key key) { 157 mKey = key; 158 return this; 159 } 160 setNextMessage(@ullable byte[] nextMessage)161 Builder setNextMessage(@Nullable byte[] nextMessage) { 162 mNextMessage = nextMessage == null ? null : nextMessage.clone(); 163 return this; 164 } 165 setVerificationCode(@ullable String verificationCode)166 Builder setVerificationCode(@Nullable String verificationCode) { 167 mVerificationCode = verificationCode; 168 return this; 169 } 170 setOobVerificationCode(@onNull byte[] oobVerificationCode)171 Builder setOobVerificationCode(@NonNull byte[] oobVerificationCode) { 172 mOobVerificationCode = oobVerificationCode; 173 return this; 174 } 175 build()176 HandshakeMessage build() { 177 if (mHandshakeState == HandshakeState.UNKNOWN) { 178 throw new IllegalStateException("must set handshake state before calling build"); 179 } 180 if (mHandshakeState == HandshakeState.VERIFICATION_NEEDED 181 && TextUtils.isEmpty(mVerificationCode)) { 182 throw new IllegalStateException( 183 "State is verification needed, but verification code null."); 184 } 185 if (mHandshakeState == HandshakeState.OOB_VERIFICATION_NEEDED 186 && (mOobVerificationCode == null || mOobVerificationCode.length == 0)) { 187 throw new IllegalStateException( 188 "State is OOB verification needed, but OOB verification code null."); 189 } 190 return new HandshakeMessage(mHandshakeState, mKey, mNextMessage, mVerificationCode, 191 mOobVerificationCode); 192 } 193 194 } 195 } 196