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