7693c2d94ecf9d7dc2028be5f52ebfbf941b9abb
[platform/upstream/connectedhomeip.git] / src / transport / SecurePairingSession.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 <support/Base64.h>
31 #include <system/SystemPacketBuffer.h>
32 #include <transport/SecureSession.h>
33 #include <transport/raw/MessageHeader.h>
34 #include <transport/raw/PeerAddress.h>
35
36 namespace chip {
37
38 extern const char * kSpake2pI2RSessionInfo;
39 extern const char * kSpake2pR2ISessionInfo;
40
41 using namespace Crypto;
42
43 class DLL_EXPORT SecurePairingSessionDelegate
44 {
45 public:
46     /**
47      * @brief
48      *   Called when pairing session generates a new message that should be sent to peer.
49      *
50      * @param header the message header for the sent message
51      * @param peerAddress the destination of the message
52      * @param msgBuf the raw data for the message being sent
53      * @return CHIP_ERROR Error thrown when sending the message
54      */
55     virtual CHIP_ERROR SendPairingMessage(const PacketHeader & header, const Transport::PeerAddress & peerAddress,
56                                           System::PacketBuffer * msgBuf)
57     {
58         return CHIP_ERROR_NOT_IMPLEMENTED;
59     }
60
61     /**
62      * @brief
63      *   Called when pairing fails with an error
64      *
65      * @param error error code
66      */
67     virtual void OnPairingError(CHIP_ERROR error) {}
68
69     /**
70      * @brief
71      *   Called when the pairing is complete and the new secure session has been established
72      */
73     virtual void OnPairingComplete() {}
74
75     virtual ~SecurePairingSessionDelegate() {}
76 };
77
78 struct SecurePairingSessionSerialized;
79
80 struct SecurePairingSessionSerializable
81 {
82     uint16_t mKeLen;
83     uint8_t mKe[kMAX_Hash_Length];
84     uint8_t mPairingComplete;
85     uint64_t mLocalNodeId;
86     uint64_t mPeerNodeId;
87     uint16_t mLocalKeyId;
88     uint16_t mPeerKeyId;
89 };
90
91 class DLL_EXPORT SecurePairingSession
92 {
93 public:
94     SecurePairingSession();
95     SecurePairingSession(SecurePairingSession &&)      = default;
96     SecurePairingSession(const SecurePairingSession &) = delete;
97     SecurePairingSession & operator=(const SecurePairingSession &) = default;
98     SecurePairingSession & operator=(SecurePairingSession &&) = default;
99
100     virtual ~SecurePairingSession();
101
102     /**
103      * @brief
104      *   Initialize using setup PIN code and wait for pairing requests.
105      *
106      * @param mySetUpPINCode  Setup PIN code of the local device
107      * @param pbkdf2IterCount Iteration count for PBKDF2 function
108      * @param salt            Salt to be used for SPAKE2P opertation
109      * @param saltLen         Length of salt
110      * @param myNodeId        Optional node id of local node
111      * @param myKeyId         Key ID to be assigned to the secure session on the peer node
112      * @param delegate        Callback object
113      *
114      * @return CHIP_ERROR     The result of initialization
115      */
116     CHIP_ERROR WaitForPairing(uint32_t mySetUpPINCode, uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen,
117                               Optional<NodeId> myNodeId, uint16_t myKeyId, SecurePairingSessionDelegate * delegate);
118
119     /**
120      * @brief
121      *   Create a pairing request using peer's setup PIN code.
122      *
123      * @param peerAddress      Address of peer to pair
124      * @param peerSetUpPINCode Setup PIN code of the peer device
125      * @param pbkdf2IterCount  Iteration count for PBKDF2 function
126      * @param salt             Salt to be used for SPAKE2P opertation
127      * @param saltLen          Length of salt
128      * @param myNodeId         Optional node id of local node
129      * @param myKeyId          Key ID to be assigned to the secure session on the peer node
130      * @param delegate         Callback object
131      *
132      * @return CHIP_ERROR      The result of initialization
133      */
134     CHIP_ERROR Pair(const Transport::PeerAddress peerAddress, uint32_t peerSetUpPINCode, uint32_t pbkdf2IterCount,
135                     const uint8_t * salt, size_t saltLen, Optional<NodeId> myNodeId, uint16_t myKeyId,
136                     SecurePairingSessionDelegate * delegate);
137
138     /**
139      * @brief
140      *   Derive a secure session from the paired session. The API will return error
141      *   if called before pairing is established.
142      *
143      * @param info        Information string used for key derivation
144      * @param info_len    Length of info string
145      * @param session     Referene to the sescure session that will be
146      *                    initialized once pairing is complete
147      * @return CHIP_ERROR The result of session derivation
148      */
149     virtual CHIP_ERROR DeriveSecureSession(const uint8_t * info, size_t info_len, SecureSession & session);
150
151     /**
152      * @brief
153      *   Handler for peer's messages, exchanged during pairing handshake.
154      *
155      * @param packetHeader      Message header for the received message
156      * @param peerAddress Source of the message
157      * @param msg         Message sent by the peer
158      * @return CHIP_ERROR The result of message processing
159      */
160     virtual CHIP_ERROR HandlePeerMessage(const PacketHeader & packetHeader, const Transport::PeerAddress & peerAddress,
161                                          System::PacketBufferHandle msg);
162
163     /**
164      * @brief
165      *  Return the associated secure session peer NodeId
166      *
167      * @return Optional<NodeId> The associated peer NodeId
168      */
169     NodeId GetPeerNodeId() const { return mPeerNodeId.Value(); }
170
171     /**
172      * @brief
173      *  Return the associated peer key id
174      *
175      * @return uint16_t The associated peer key id
176      */
177     uint16_t GetPeerKeyId() { return mPeerKeyId; }
178
179     /**
180      * @brief
181      *  Return the associated local key id
182      *
183      * @return uint16_t The assocated local key id
184      */
185     uint16_t GetLocalKeyId() { return mLocalKeyId; }
186
187     /** @brief Serialize the Pairing Session to a string.
188      *
189      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
190      **/
191     CHIP_ERROR Serialize(SecurePairingSessionSerialized & output);
192
193     /** @brief Deserialize the Pairing Session from the string.
194      *
195      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
196      **/
197     CHIP_ERROR Deserialize(SecurePairingSessionSerialized & input);
198
199     /** @brief Serialize the SecurePairingSession to the given serializable data structure for secure pairing
200      *
201      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
202      **/
203     CHIP_ERROR ToSerializable(SecurePairingSessionSerializable & output);
204
205     /** @brief Reconstruct secure pairing class from the serializable data structure.
206      *
207      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
208      **/
209     CHIP_ERROR FromSerializable(const SecurePairingSessionSerializable & output);
210
211 private:
212     CHIP_ERROR Init(uint32_t setupCode, uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen, Optional<NodeId> myNodeId,
213                     uint16_t myKeyId, SecurePairingSessionDelegate * delegate);
214
215     CHIP_ERROR HandleCompute_pA(const PacketHeader & header, const System::PacketBufferHandle & msg);
216     CHIP_ERROR HandleCompute_pB_cB(const PacketHeader & header, const System::PacketBufferHandle & msg);
217     CHIP_ERROR HandleCompute_cA(const PacketHeader & header, const System::PacketBufferHandle & msg);
218
219     CHIP_ERROR AttachHeaderAndSend(uint8_t msgType, System::PacketBuffer * msgBuf);
220
221     static constexpr size_t kSpake2p_WS_Length = kP256_FE_Length + 8;
222
223     enum Spake2pMsgType : uint8_t
224     {
225         kSpake2pCompute_pA    = 0,
226         kSpake2pCompute_pB_cB = 1,
227         kSpake2pCompute_cA    = 2,
228         kSpake2pMsgTypeMax    = 3,
229     };
230
231     SecurePairingSessionDelegate * mDelegate = nullptr;
232
233     Spake2pMsgType mNextExpectedMsg = Spake2pMsgType::kSpake2pMsgTypeMax;
234
235     Spake2p_P256_SHA256_HKDF_HMAC mSpake2p;
236
237     uint8_t mPoint[kMAX_Point_Length];
238
239     /* w0s and w1s */
240     uint8_t mWS[2][kSpake2p_WS_Length];
241
242 protected:
243     Optional<NodeId> mLocalNodeId = Optional<NodeId>::Value(kUndefinedNodeId);
244
245     Optional<NodeId> mPeerNodeId = Optional<NodeId>::Value(kUndefinedNodeId);
246
247     uint16_t mLocalKeyId;
248
249     uint16_t mPeerKeyId;
250
251     Transport::PeerAddress mPeerAddress;
252
253     uint8_t mKe[kMAX_Hash_Length];
254
255     size_t mKeLen = sizeof(mKe);
256
257     bool mPairingComplete = false;
258 };
259
260 /*
261  * The following constants are node IDs that test devices and test
262  * controllers use while using the SecurePairingUsingTestSecret to
263  * establish secure channel
264  */
265 constexpr chip::NodeId kTestControllerNodeId = 112233;
266 constexpr chip::NodeId kTestDeviceNodeId     = 12344321;
267
268 /*
269  * The following class should only be used for test usecases.
270  * The class is currently also used for devices that do no yet support
271  * rendezvous. Once all the non-test usecases start supporting
272  * rendezvous, this class will be moved to the test code.
273  */
274 class SecurePairingUsingTestSecret : public SecurePairingSession
275 {
276 public:
277     SecurePairingUsingTestSecret()
278     {
279         const char * secret = "Test secret for key derivation";
280         size_t secretLen    = strlen(secret);
281         mKeLen              = secretLen;
282         memmove(mKe, secret, mKeLen);
283         mPairingComplete = true;
284     }
285
286     SecurePairingUsingTestSecret(Optional<NodeId> peerNodeId, uint16_t peerKeyId, uint16_t localKeyId)
287     {
288         const char * secret = "Test secret for key derivation";
289         size_t secretLen    = strlen(secret);
290         mPeerNodeId         = peerNodeId;
291         mPeerKeyId          = peerKeyId;
292         mLocalKeyId         = localKeyId;
293         mKeLen              = secretLen;
294         memmove(mKe, secret, mKeLen);
295         mPairingComplete = true;
296     }
297
298     ~SecurePairingUsingTestSecret() override {}
299
300     CHIP_ERROR WaitForPairing(uint32_t mySetUpPINCode, uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen,
301                               Optional<NodeId> myNodeId, uint16_t myKeyId, SecurePairingSessionDelegate * delegate)
302     {
303         return CHIP_NO_ERROR;
304     }
305
306     CHIP_ERROR Pair(uint32_t peerSetUpPINCode, uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen,
307                     Optional<NodeId> myNodeId, uint16_t myKeyId, SecurePairingSessionDelegate * delegate)
308     {
309         return CHIP_NO_ERROR;
310     }
311
312     CHIP_ERROR HandlePeerMessage(const PacketHeader & packetHeader, const Transport::PeerAddress & peerAddress,
313                                  System::PacketBufferHandle msg) override
314     {
315         return CHIP_NO_ERROR;
316     }
317 };
318
319 typedef struct SecurePairingSessionSerialized
320 {
321     // Extra uint64_t to account for padding bytes (NULL termination, and some decoding overheads)
322     uint8_t inner[BASE64_ENCODED_LEN(sizeof(SecurePairingSessionSerializable) + sizeof(uint64_t))];
323 } SecurePairingSessionSerialized;
324
325 } // namespace chip