Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / transport / PASESession.h
1 /*
2  *
3  *    Copyright (c) 2020 Project CHIP Authors
4  *    All rights reserved.
5  *
6  *    Licensed under the Apache License, Version 2.0 (the "License");
7  *    you may not use this file except in compliance with the License.
8  *    You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *    Unless required by applicable law or agreed to in writing, software
13  *    distributed under the License is distributed on an "AS IS" BASIS,
14  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *    See the License for the specific language governing permissions and
16  *    limitations under the License.
17  */
18
19 /**
20  *    @file
21  *      This file defines the CHIP SPAKE2P Session object that provides
22  *      APIs for constructing spake2p messages and establishing encryption
23  *      keys.
24  *
25  */
26
27 #pragma once
28
29 #include <crypto/CHIPCryptoPAL.h>
30 #include <protocols/secure_channel/Constants.h>
31 #include <support/Base64.h>
32 #include <system/SystemPacketBuffer.h>
33 #include <transport/PeerConnectionState.h>
34 #include <transport/SecureSession.h>
35 #include <transport/SessionEstablishmentDelegate.h>
36 #include <transport/raw/MessageHeader.h>
37 #include <transport/raw/PeerAddress.h>
38
39 namespace chip {
40
41 extern const char * kSpake2pI2RSessionInfo;
42 extern const char * kSpake2pR2ISessionInfo;
43
44 constexpr uint16_t kPBKDFParamRandomNumberSize = 32;
45
46 using namespace Crypto;
47
48 constexpr size_t kSpake2p_WS_Length = kP256_FE_Length + 8;
49
50 struct PASESessionSerialized;
51
52 struct PASESessionSerializable
53 {
54     uint16_t mKeLen;
55     uint8_t mKe[kMAX_Hash_Length];
56     uint8_t mPairingComplete;
57     uint16_t mLocalKeyId;
58     uint16_t mPeerKeyId;
59 };
60
61 typedef uint8_t PASEVerifier[2][kSpake2p_WS_Length];
62
63 class DLL_EXPORT PASESession
64 {
65 public:
66     PASESession();
67     PASESession(PASESession &&)      = default;
68     PASESession(const PASESession &) = delete;
69     PASESession & operator=(const PASESession &) = default;
70     PASESession & operator=(PASESession &&) = default;
71
72     virtual ~PASESession();
73
74     /**
75      * @brief
76      *   Initialize using setup PIN code and wait for pairing requests.
77      *
78      * @param mySetUpPINCode  Setup PIN code of the local device
79      * @param pbkdf2IterCount Iteration count for PBKDF2 function
80      * @param salt            Salt to be used for SPAKE2P opertation
81      * @param saltLen         Length of salt
82      * @param myKeyId         Key ID to be assigned to the secure session on the peer node
83      * @param delegate        Callback object
84      *
85      * @return CHIP_ERROR     The result of initialization
86      */
87     CHIP_ERROR WaitForPairing(uint32_t mySetUpPINCode, uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen,
88                               uint16_t myKeyId, SessionEstablishmentDelegate * delegate);
89
90     /**
91      * @brief
92      *   Initialize using PASE verifier and wait for pairing requests.
93      *
94      * @param verifier        PASE verifier to be used for SPAKE2P pairing
95      * @param myKeyId         Key ID to be assigned to the secure session on the peer node
96      * @param delegate        Callback object
97      *
98      * @return CHIP_ERROR     The result of initialization
99      */
100     CHIP_ERROR WaitForPairing(const PASEVerifier & verifier, uint16_t myKeyId, SessionEstablishmentDelegate * delegate);
101
102     /**
103      * @brief
104      *   Create a pairing request using peer's setup PIN code.
105      *
106      * @param peerAddress      Address of peer to pair
107      * @param peerSetUpPINCode Setup PIN code of the peer device
108      * @param myKeyId          Key ID to be assigned to the secure session on the peer node
109      * @param delegate         Callback object
110      *
111      * @return CHIP_ERROR      The result of initialization
112      */
113     CHIP_ERROR Pair(const Transport::PeerAddress peerAddress, uint32_t peerSetUpPINCode, uint16_t myKeyId,
114                     SessionEstablishmentDelegate * delegate);
115
116     /**
117      * @brief
118      *   Create a pairing request using given PASE verifier.
119      *
120      * @param peerAddress      Address of peer to pair
121      * @param verifier         PASE verifier to be used for SPAKE2P pairing
122      * @param myKeyId          Key ID to be assigned to the secure session on the peer node
123      * @param delegate         Callback object
124      *
125      * @return CHIP_ERROR      The result of initialization
126      */
127     CHIP_ERROR Pair(const Transport::PeerAddress peerAddress, const PASEVerifier & verifier, uint16_t myKeyId,
128                     SessionEstablishmentDelegate * delegate);
129
130     /**
131      * @brief
132      *   Generate a new PASE verifier.
133      *
134      * @param verifier      The generated PASE verifier
135      * @param useRandomPIN  Generate a random setup PIN, if true. Else, use the provided PIN
136      * @param setupPIN      Provided setup PIN (if useRandomPIN is false), or the generated PIN
137      *
138      * @return CHIP_ERROR      The result of PASE verifier generation
139      */
140     static CHIP_ERROR GeneratePASEVerifier(PASEVerifier & verifier, bool useRandomPIN, uint32_t & setupPIN);
141
142     /**
143      * @brief
144      *   Derive a secure session from the paired session. The API will return error
145      *   if called before pairing is established.
146      *
147      * @param info        Information string used for key derivation
148      * @param info_len    Length of info string
149      * @param session     Referene to the sescure session that will be
150      *                    initialized once pairing is complete
151      * @return CHIP_ERROR The result of session derivation
152      */
153     CHIP_ERROR DeriveSecureSession(const uint8_t * info, size_t info_len, SecureSession & session);
154
155     /**
156      * @brief
157      *   Handler for peer's messages, exchanged during pairing handshake.
158      *
159      * @param packetHeader      Message header for the received message
160      * @param peerAddress Source of the message
161      * @param msg         Message sent by the peer
162      * @return CHIP_ERROR The result of message processing
163      */
164     virtual CHIP_ERROR HandlePeerMessage(const PacketHeader & packetHeader, const Transport::PeerAddress & peerAddress,
165                                          System::PacketBufferHandle msg);
166
167     /**
168      * @brief
169      *  Return the associated peer key id
170      *
171      * @return uint16_t The associated peer key id
172      */
173     uint16_t GetPeerKeyId() { return mConnectionState.GetPeerKeyID(); }
174
175     /**
176      * @brief
177      *  Return the associated local key id
178      *
179      * @return uint16_t The assocated local key id
180      */
181     uint16_t GetLocalKeyId() { return mConnectionState.GetLocalKeyID(); }
182
183     Transport::PeerConnectionState & PeerConnection() { return mConnectionState; }
184
185     /** @brief Serialize the Pairing Session to a string.
186      *
187      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
188      **/
189     CHIP_ERROR Serialize(PASESessionSerialized & output);
190
191     /** @brief Deserialize the Pairing Session from the string.
192      *
193      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
194      **/
195     CHIP_ERROR Deserialize(PASESessionSerialized & input);
196
197     /** @brief Serialize the PASESession to the given serializable data structure for secure pairing
198      *
199      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
200      **/
201     CHIP_ERROR ToSerializable(PASESessionSerializable & output);
202
203     /** @brief Reconstruct secure pairing class from the serializable data structure.
204      *
205      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
206      **/
207     CHIP_ERROR FromSerializable(const PASESessionSerializable & output);
208
209     /** @brief This function zeroes out and resets the memory used by the object.
210      **/
211     void Clear();
212
213 private:
214     enum Spake2pErrorType : uint8_t
215     {
216         kInvalidKeyConfirmation = 0x00,
217         kUnexpected             = 0xff,
218     };
219
220     CHIP_ERROR Init(uint16_t myKeyId, uint32_t setupCode, SessionEstablishmentDelegate * delegate);
221
222     static CHIP_ERROR ComputePASEVerifier(uint32_t mySetUpPINCode, uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen,
223                                           PASEVerifier & verifier);
224
225     CHIP_ERROR SetupSpake2p(uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen);
226
227     CHIP_ERROR SendPBKDFParamRequest();
228     CHIP_ERROR HandlePBKDFParamRequest(const PacketHeader & header, const System::PacketBufferHandle & msg);
229
230     CHIP_ERROR SendPBKDFParamResponse();
231     CHIP_ERROR HandlePBKDFParamResponse(const PacketHeader & header, const System::PacketBufferHandle & msg);
232
233     CHIP_ERROR SendMsg1();
234
235     CHIP_ERROR HandleMsg1_and_SendMsg2(const PacketHeader & header, const System::PacketBufferHandle & msg);
236     CHIP_ERROR HandleMsg2_and_SendMsg3(const PacketHeader & header, const System::PacketBufferHandle & msg);
237     CHIP_ERROR HandleMsg3(const PacketHeader & header, const System::PacketBufferHandle & msg);
238
239     void SendErrorMsg(Spake2pErrorType errorCode);
240     void HandleErrorMsg(const PacketHeader & header, const System::PacketBufferHandle & msg);
241
242     CHIP_ERROR AttachHeaderAndSend(Protocols::SecureChannel::MsgType msgType, System::PacketBufferHandle msgBuf);
243
244     SessionEstablishmentDelegate * mDelegate = nullptr;
245
246     Protocols::SecureChannel::MsgType mNextExpectedMsg = Protocols::SecureChannel::MsgType::PASE_Spake2pError;
247
248     Spake2p_P256_SHA256_HKDF_HMAC mSpake2p;
249
250     uint8_t mPoint[kMAX_Point_Length];
251
252     /* w0s and w1s */
253     PASEVerifier mPASEVerifier;
254
255     uint32_t mSetupPINCode;
256
257     bool mComputeVerifier = true;
258
259     Hash_SHA256_stream mCommissioningHash;
260     uint32_t mIterationCount = 0;
261     uint16_t mSaltLength     = 0;
262     uint8_t * mSalt          = nullptr;
263
264     struct Spake2pErrorMsg
265     {
266         Spake2pErrorType error;
267     };
268
269 protected:
270     uint8_t mKe[kMAX_Hash_Length];
271
272     size_t mKeLen = sizeof(mKe);
273
274     bool mPairingComplete = false;
275
276     Transport::PeerConnectionState mConnectionState;
277 };
278
279 /*
280  * The following constants are node IDs that test devices and test
281  * controllers use while using the SecurePairingUsingTestSecret to
282  * establish secure channel
283  */
284 constexpr chip::NodeId kTestControllerNodeId = 112233;
285 constexpr chip::NodeId kTestDeviceNodeId     = 12344321;
286
287 /*
288  * The following class should only be used for test usecases.
289  * The class is currently also used for devices that do no yet support
290  * rendezvous. Once all the non-test usecases start supporting
291  * rendezvous, this class will be moved to the test code.
292  */
293 class SecurePairingUsingTestSecret : public PASESession
294 {
295 public:
296     SecurePairingUsingTestSecret()
297     {
298         const char * secret = "Test secret for key derivation";
299         size_t secretLen    = strlen(secret);
300         mKeLen              = secretLen;
301         memmove(mKe, secret, mKeLen);
302         mConnectionState.SetPeerKeyID(0);
303         mConnectionState.SetLocalKeyID(0);
304         mPairingComplete = true;
305     }
306
307     SecurePairingUsingTestSecret(uint16_t peerKeyId, uint16_t localKeyId)
308     {
309         const char * secret = "Test secret for key derivation";
310         size_t secretLen    = strlen(secret);
311         mKeLen              = secretLen;
312         memmove(mKe, secret, mKeLen);
313         mConnectionState.SetPeerKeyID(peerKeyId);
314         mConnectionState.SetLocalKeyID(localKeyId);
315         mPairingComplete = true;
316     }
317
318     ~SecurePairingUsingTestSecret() override {}
319
320     CHIP_ERROR WaitForPairing(uint32_t mySetUpPINCode, uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen,
321                               uint16_t myKeyId, SessionEstablishmentDelegate * delegate)
322     {
323         return CHIP_NO_ERROR;
324     }
325
326     CHIP_ERROR Pair(uint32_t peerSetUpPINCode, uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen, uint16_t myKeyId,
327                     SessionEstablishmentDelegate * delegate)
328     {
329         return CHIP_NO_ERROR;
330     }
331
332     CHIP_ERROR HandlePeerMessage(const PacketHeader & packetHeader, const Transport::PeerAddress & peerAddress,
333                                  System::PacketBufferHandle msg) override
334     {
335         return CHIP_NO_ERROR;
336     }
337 };
338
339 typedef struct PASESessionSerialized
340 {
341     // Extra uint64_t to account for padding bytes (NULL termination, and some decoding overheads)
342     uint8_t inner[BASE64_ENCODED_LEN(sizeof(PASESessionSerializable) + sizeof(uint64_t))];
343 } PASESessionSerialized;
344
345 } // namespace chip