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