/* * Copyright (c) 2024 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 #include #include #include #include #include #include #include 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 (*OnOpenCommissioningWindowWithVerifier)(void * context, NodeId deviceId, CHIP_ERROR status); typedef void (*OnOpenBasicCommissioningWindow)(void * context, NodeId deviceId, CHIP_ERROR status); template class CommissioningWindowCommonParams { public: CommissioningWindowCommonParams() = default; bool HasNodeId() const { return mNodeId != kUndefinedNodeId; } NodeId GetNodeId() const { VerifyOrDie(HasNodeId()); return mNodeId; } // The node identifier of device Derived & SetNodeId(NodeId nodeId) { mNodeId = nodeId; return static_cast(*this); } EndpointId GetEndpointId() const { return mEndpointId; } Derived & SetEndpointId(EndpointId endpointId) { mEndpointId = endpointId; return static_cast(*this); } System::Clock::Seconds16 GetTimeout() const { return mTimeout; } // The duration for which the commissioning window should remain open. Derived & SetTimeout(System::Clock::Seconds16 timeout) { mTimeout = timeout; return static_cast(*this); } Derived & SetTimeout(uint16_t timeoutSeconds) { return SetTimeout(System::Clock::Seconds16(timeoutSeconds)); } // The PAKE iteration count associated with the PAKE Passcode ID and // ephemeral PAKE passcode verifier to be used for this commissioning. uint32_t GetIteration() const { return mIteration; } Derived & SetIteration(uint32_t iteration) { mIteration = iteration; return static_cast(*this); } // The long discriminator for the DNS-SD advertisement. uint16_t GetDiscriminator() const { return mDiscriminator.Value(); } bool HasDiscriminator() const { return mDiscriminator.HasValue(); } Derived & SetDiscriminator(uint16_t discriminator) { mDiscriminator = MakeOptional(discriminator); return static_cast(*this); } private: NodeId mNodeId = kUndefinedNodeId; EndpointId mEndpointId = kRootEndpointId; // Default endpoint for Administrator Commissioning Cluster System::Clock::Seconds16 mTimeout = System::Clock::Seconds16(300); // Defaulting uint32_t mIteration = 1000; // Defaulting Optional mDiscriminator = NullOptional; // Using optional type to avoid picking a sentinnel in valid range }; class CommissioningWindowPasscodeParams : public CommissioningWindowCommonParams { public: CommissioningWindowPasscodeParams() = default; bool HasSetupPIN() const { return mSetupPIN.HasValue(); } // Get the value of setup PIN (Passcode) if present, crashes otherwise. uint32_t GetSetupPIN() const { return mSetupPIN.Value(); } // The setup PIN (Passcode) to use. A random one will be generated if not provided. CommissioningWindowPasscodeParams & SetSetupPIN(uint32_t setupPIN) { return SetSetupPIN(MakeOptional(setupPIN)); } // The setup PIN (Passcode) to use. A random one will be generated if NullOptional is used. CommissioningWindowPasscodeParams & SetSetupPIN(Optional setupPIN) { mSetupPIN = setupPIN; return *this; } bool HasSalt() const { return mSalt.HasValue(); } // Get the value of salt if present. // Dies if absent! Make sure to check HasSalt() ByteSpan GetSalt() const { return mSalt.Value(); } // The salt to use. A random one will be generated if not provided. // If provided, must be at least kSpake2p_Min_PBKDF_Salt_Length bytes // and at most kSpake2p_Max_PBKDF_Salt_Length bytes in length. CommissioningWindowPasscodeParams & SetSalt(ByteSpan salt) { return SetSalt(MakeOptional(salt)); } // The salt to use. A random one will be generated if NullOptional is used. // If provided, must be at least kSpake2p_Min_PBKDF_Salt_Length bytes // and at most kSpake2p_Max_PBKDF_Salt_Length bytes in length. // Note that this an overloaded optional arg function to support existing APIs. CommissioningWindowPasscodeParams & SetSalt(Optional salt) { mSalt = salt; return *this; } bool GetReadVIDPIDAttributes() const { return mReadVIDPIDAttributes; } // 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. CommissioningWindowPasscodeParams & SetReadVIDPIDAttributes(bool readVIDPIDAttributes) { mReadVIDPIDAttributes = readVIDPIDAttributes; return *this; } Callback::Callback * GetCallback() const { return mCallback; } // The function to be called on success or failure of opening the commissioning window. // This will include the SetupPayload generated from provided parameters. CommissioningWindowPasscodeParams & SetCallback(Callback::Callback * callback) { mCallback = callback; return *this; } private: Optional mSetupPIN = NullOptional; Optional mSalt = NullOptional; bool mReadVIDPIDAttributes = false; Callback::Callback * mCallback = nullptr; }; class CommissioningWindowVerifierParams : public CommissioningWindowCommonParams { public: CommissioningWindowVerifierParams() = default; ByteSpan GetVerifier() const { return mVerifier.Value(); } // The PAKE passcode verifier generated with enclosed iterations, salt and not-enclosed passcode. CommissioningWindowVerifierParams & SetVerifier(ByteSpan verifier) { mVerifier = MakeOptional(verifier); return *this; } ByteSpan GetSalt() const { return mSalt.Value(); } // The salt that was used to generate the verifier. // It must be at least kSpake2p_Min_PBKDF_Salt_Length bytes. // Note: This is REQUIRED when verifier is used CommissioningWindowVerifierParams & SetSalt(ByteSpan salt) { mSalt = MakeOptional(salt); return *this; } Callback::Callback * GetCallback() const { return mCallback; } // The function to be called on success or failure of opening the // commissioning window. This will NOT include the SetupPayload. CommissioningWindowVerifierParams & SetCallback(Callback::Callback * callback) { mCallback = callback; return *this; } private: Optional mSalt; Optional mVerifier; Callback::Callback * mCallback = nullptr; }; } // namespace Controller } // namespace chip