forked from nrfconnect/sdk-connectedhomeip
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCommissioningWindowOpener.h
181 lines (163 loc) · 9.1 KB
/
CommissioningWindowOpener.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*
* Copyright (c) 2022 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <app/OperationalSessionSetup.h>
#include <app/data-model/NullObject.h>
#include <controller/CHIPDeviceController.h>
#include <crypto/CHIPCryptoPAL.h>
#include <lib/core/CHIPCallback.h>
#include <lib/core/CHIPError.h>
#include <lib/core/NodeId.h>
#include <lib/core/Optional.h>
#include <setup_payload/SetupPayload.h>
#include <system/SystemClock.h>
namespace chip {
namespace Controller {
// Passing SetupPayload by value on purpose, in case a consumer decides to reuse
// this object from inside the callback.
typedef void (*OnOpenCommissioningWindow)(void * context, NodeId deviceId, CHIP_ERROR status, SetupPayload payload);
typedef void (*OnOpenBasicCommissioningWindow)(void * context, NodeId deviceId, CHIP_ERROR status);
/**
* A helper class to open a commissioning window given some parameters.
*/
class CommissioningWindowOpener
{
public:
CommissioningWindowOpener(DeviceController * controller) :
mController(controller), mDeviceConnected(&OnDeviceConnectedCallback, this),
mDeviceConnectionFailure(&OnDeviceConnectionFailureCallback, this)
{}
enum class CommissioningWindowOption : uint8_t
{
kOriginalSetupCode = 0,
kTokenWithRandomPIN,
kTokenWithProvidedPIN,
};
/*
* @brief
* Try to look up the device attached to our controller with the given
* node id and ask it to re-enter commissioning mode with its original
* PASE verifier, discriminator, etc. The device will exit commissioning
* mode after a successful commissioning, or after the given `timeout`
* time.
*
* @param[in] deviceId The device Id.
* @param[in] timeout The commissioning mode should terminate after this much time.
* @param[in] callback The callback to call once the commissioning window is
* open or if an error occurs.
*/
CHIP_ERROR OpenBasicCommissioningWindow(NodeId deviceId, System::Clock::Seconds16 timeout,
Callback::Callback<OnOpenBasicCommissioningWindow> * callback);
/**
* @brief
* Try to look up the device attached to our controller with the given
* node id and ask it to re-enter commissioning mode with a PASE verifier
* derived from the given information and the given discriminator. The
* device will exit commissioning mode after a successful commissioning,
* or after the given `timeout` time.
*
* @param[in] deviceId The device Id.
* @param[in] timeout The commissioning mode should terminate after this much time.
* @param[in] iteration The PAKE iteration count associated with the PAKE Passcode ID and ephemeral
* PAKE passcode verifier to be used for this commissioning.
* @param[in] discriminator The long discriminator for the DNS-SD advertisement.
* @param[in] setupPIN The setup PIN to use, or NullOptional to use a randomly-generated one.
* @param[in] salt The salt to use, or NullOptional to use a
* randomly-generated one. If provided, must be at
* least kSpake2p_Min_PBKDF_Salt_Length bytes and
* at most kSpake2p_Max_PBKDF_Salt_Length bytes in
* length.
* @param[in] callback The function to be called on success or failure of opening of commissioning window.
* @param[out] payload The setup payload, not including the VID/PID bits,
* even if those were asked for, that is generated
* based on the passed-in information. The payload
* provided to the callback function, unlike this
* out parameter, will include the VID/PID bits if
* readVIDPIDAttributes is true.
*
* @param[in] readVIDPIDAttributes Should the API internally read VID and PID from the device while opening the
* commissioning window. If this argument is `true`, the API will read VID and
* PID from the device and include them in the setup payload passed to the
* callback.
*/
CHIP_ERROR OpenCommissioningWindow(NodeId deviceId, System::Clock::Seconds16 timeout, uint32_t iteration,
uint16_t discriminator, Optional<uint32_t> setupPIN, Optional<ByteSpan> salt,
Callback::Callback<OnOpenCommissioningWindow> * callback, SetupPayload & payload,
bool readVIDPIDAttributes = false);
private:
enum class Step : uint8_t
{
// Ready to start opening a commissioning window.
kAcceptCommissioningStart,
// Need to read VID.
kReadVID,
// Need to read PID.
kReadPID,
// Need to open commissioning window.
kOpenCommissioningWindow,
};
CHIP_ERROR OpenCommissioningWindowInternal(Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle);
static void OnPIDReadResponse(void * context, uint16_t value);
static void OnVIDReadResponse(void * context, VendorId value);
static void OnVIDPIDReadFailureResponse(void * context, CHIP_ERROR error);
static void OnOpenCommissioningWindowSuccess(void * context, const app::DataModel::NullObjectType &);
static void OnOpenCommissioningWindowFailure(void * context, CHIP_ERROR error);
static void OnDeviceConnectedCallback(void * context, Messaging::ExchangeManager & exchangeMgr,
const SessionHandle & sessionHandle);
static void OnDeviceConnectionFailureCallback(void * context, const ScopedNodeId & peerId, CHIP_ERROR error);
DeviceController * const mController = nullptr;
Step mNextStep = Step::kAcceptCommissioningStart;
Callback::Callback<OnOpenCommissioningWindow> * mCommissioningWindowCallback = nullptr;
Callback::Callback<OnOpenBasicCommissioningWindow> * mBasicCommissioningWindowCallback = nullptr;
SetupPayload mSetupPayload;
NodeId mNodeId = kUndefinedNodeId;
System::Clock::Seconds16 mCommissioningWindowTimeout = System::Clock::kZero;
CommissioningWindowOption mCommissioningWindowOption = CommissioningWindowOption::kOriginalSetupCode;
Spake2pVerifier mVerifier; // Used for non-basic commissioning.
// Parameters needed for non-basic commissioning.
uint32_t mPBKDFIterations = 0;
uint8_t mPBKDFSaltBuffer[kSpake2p_Max_PBKDF_Salt_Length];
ByteSpan mPBKDFSalt;
Callback::Callback<OnDeviceConnected> mDeviceConnected;
Callback::Callback<OnDeviceConnectionFailure> mDeviceConnectionFailure;
};
/**
* A helper class that can be used by consumers that don't care about the callback from the
* open-commissioning-window process and just want automatic cleanup of the CommissioningWindowOpener when done
* with it.
*/
class AutoCommissioningWindowOpener : private CommissioningWindowOpener
{
public:
// Takes the same arguments as CommissioningWindowOpener::OpenBasicCommissioningWindow except without the
// callback.
static CHIP_ERROR OpenBasicCommissioningWindow(DeviceController * controller, NodeId deviceId,
System::Clock::Seconds16 timeout);
// Takes the same arguments as CommissioningWindowOpener::OpenCommissioningWindow except without the
// callback.
static CHIP_ERROR OpenCommissioningWindow(DeviceController * controller, NodeId deviceId, System::Clock::Seconds16 timeout,
uint32_t iteration, uint16_t discriminator, Optional<uint32_t> setupPIN,
Optional<ByteSpan> salt, SetupPayload & payload, bool readVIDPIDAttributes = false);
private:
AutoCommissioningWindowOpener(DeviceController * controller);
static void OnOpenCommissioningWindowResponse(void * context, NodeId deviceId, CHIP_ERROR status, chip::SetupPayload payload);
static void OnOpenBasicCommissioningWindowResponse(void * context, NodeId deviceId, CHIP_ERROR status);
chip::Callback::Callback<chip::Controller::OnOpenCommissioningWindow> mOnOpenCommissioningWindowCallback;
chip::Callback::Callback<chip::Controller::OnOpenBasicCommissioningWindow> mOnOpenBasicCommissioningWindowCallback;
};
} // Namespace Controller
} // namespace chip