/* * Copyright (c) 2020-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 #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef JAVA_MATTER_CONTROLLER_TEST #include #include #else #include #include #endif // JAVA_MATTER_CONTROLLER_TEST #include "AndroidCheckInDelegate.h" #include "AndroidOperationalCredentialsIssuer.h" #include "AttestationTrustStoreBridge.h" #include "DeviceAttestationDelegateBridge.h" #if CHIP_DEVICE_CONFIG_DYNAMIC_SERVER #include "OTAProviderDelegateBridge.h" #endif constexpr uint8_t kUserActiveModeTriggerInstructionBufferLen = 128 + 1; // 128bytes is max UserActiveModeTriggerInstruction size and 1 byte is for escape sequence. constexpr uint8_t kCountryCodeBufferLen = 2; /** * This class contains all relevant information for the JNI view of CHIPDeviceController * to handle all controller-related processing. * * Generally it contains the DeviceController class itself, plus any related delegates/callbacks. */ class AndroidDeviceControllerWrapper : public chip::Controller::DevicePairingDelegate, public chip::PersistentStorageDelegate { public: ~AndroidDeviceControllerWrapper(); chip::Controller::DeviceCommissioner * Controller() { return mController.get(); } void SetJavaObjectRef(JavaVM * vm, jobject obj); jobject JavaObjectRef() { return mJavaObjectRef.ObjectRef(); } jlong ToJNIHandle(); #ifndef JAVA_MATTER_CONTROLLER_TEST /** * Returns a CHIPP256KeypairBridge which can be used to delegate signing operations * to a KeypairDelegate in the Java layer. Note that this will always return a pointer * to the same instance, once initialized. */ CHIPP256KeypairBridge * GetP256KeypairBridge() { if (mKeypairBridge == nullptr) { mKeypairBridge = chip::Platform::New(); } return mKeypairBridge; } #endif // JAVA_MATTER_CONTROLLER_TEST void CallJavaIntMethod(const char * methodName, jint argument); void CallJavaLongMethod(const char * methodName, jlong argument); CHIP_ERROR InitializeOperationalCredentialsIssuer(); /** * Convert network credentials from Java, and apply them to the commissioning parameters object. */ CHIP_ERROR ApplyNetworkCredentials(chip::Controller::CommissioningParameters & params, jobject networkCredentials); /** * Convert ICD Registration Infomations from Java, and apply them to the commissioning parameters object. */ CHIP_ERROR ApplyICDRegistrationInfo(chip::Controller::CommissioningParameters & params, jobject icdRegistrationInfo); /** * Update the CommissioningParameters used by the active device commissioner */ CHIP_ERROR UpdateCommissioningParameters(const chip::Controller::CommissioningParameters & params); // DevicePairingDelegate implementation void OnStatusUpdate(chip::Controller::DevicePairingDelegate::Status status) override; void OnPairingComplete(CHIP_ERROR error) override; void OnPairingDeleted(CHIP_ERROR error) override; void OnCommissioningComplete(chip::NodeId deviceId, CHIP_ERROR error) override; void OnCommissioningStatusUpdate(chip::PeerId peerId, chip::Controller::CommissioningStage stageCompleted, CHIP_ERROR error) override; void OnReadCommissioningInfo(const chip::Controller::ReadCommissioningInfo & info) override; void OnScanNetworksSuccess( const chip::app::Clusters::NetworkCommissioning::Commands::ScanNetworksResponse::DecodableType & dataResponse) override; void OnScanNetworksFailure(CHIP_ERROR error) override; void OnICDRegistrationInfoRequired() override; void OnICDRegistrationComplete(chip::ScopedNodeId icdNodeId, uint32_t icdCounter) override; // PersistentStorageDelegate implementation CHIP_ERROR SyncSetKeyValue(const char * key, const void * value, uint16_t size) override; CHIP_ERROR SyncGetKeyValue(const char * key, void * buffer, uint16_t & size) override; CHIP_ERROR SyncDeleteKeyValue(const char * key) override; chip::Controller::AutoCommissioner * GetAutoCommissioner() { return &mAutoCommissioner; } chip::Credentials::PartialDACVerifier * GetPartialDACVerifier() { return &mPartialDACVerifier; } const chip::Controller::CommissioningParameters & GetCommissioningParameters() const { return mCommissioningParameter; } static AndroidDeviceControllerWrapper * FromJNIHandle(jlong handle) { return reinterpret_cast(handle); } #ifdef JAVA_MATTER_CONTROLLER_TEST using ExampleOperationalCredentialsIssuerPtr = std::unique_ptr; #else using AndroidOperationalCredentialsIssuerPtr = std::unique_ptr; #endif /** * Initializes a new CHIPDeviceController using the given parameters, and returns a pointer to the * AndroidDeviceControllerWrapper that holds the underlying controller. * * If the keypairDelegate is provided, then the rootCertificate, nodeOperationalCertificate, and * ipkEpochKey must also be specified. If no operational credentials are specified here, then an * ephemeral signing configuration will be generated for you. * * If there are any errors during the initialization of this controller, then a nullptr will be * returned. * * @param[in] vm the JavaVM * @param[in] deviceControllerObj a reference to the Java ChipDeviceController * @param[in] nodeId the local node ID to use for this controller instance * @param[in] cats the set of CASE authenticated tags * @param[in] systemLayer a pointer to the System::Layer instance * @param[in] tcpEndpointManager a pointer to a Inet::EndPointManager for TCP connections * @param[in] udpEndpointManager a pointer to a Inet::EndPointManager for UDP connections * @param[in] opCredsIssuer a pointer to an issuer for Android operational credentials * @param[in] keypairDelegate a pointer to a Java KeypairDelegate implementation. * @param[in] rootCertificate an X.509 DER-encoded trusted root certificate for this node * @param[in] intermediateCertificate an X.509 DER-encoded intermediate certificate for this node * @param[in] nodeOperationalCertificate an X.509 DER-encoded operational certificate for this node * @param[in] ipkEpochKey the IPK epoch key to use for this node * @param[in] listenPort the UDP port to listen on * @param[in] controllerVendorId the vendor ID identifying the controller * @param[in] failsafeTimerSeconds the failsafe timer in seconds * @param[in] attemptNetworkScanWiFi whether to attempt a network scan when configuring the network for a WiFi device * @param[in] attemptNetworkScanThread whether to attempt a network scan when configuring the network for a Thread device * @param[in] skipCommissioningComplete whether to skip the CASE commissioningComplete command during commissioning * @param[out] errInfoOnFailure a pointer to a CHIP_ERROR that will be populated if this method returns nullptr */ static AndroidDeviceControllerWrapper * AllocateNew(JavaVM * vm, jobject deviceControllerObj, chip::NodeId nodeId, chip::FabricId fabricId, const chip::CATValues & cats, chip::System::Layer * systemLayer, chip::Inet::EndPointManager * tcpEndPointManager, chip::Inet::EndPointManager * udpEndPointManager, #ifdef JAVA_MATTER_CONTROLLER_TEST ExampleOperationalCredentialsIssuerPtr opCredsIssuer, #else AndroidOperationalCredentialsIssuerPtr opCredsIssuer, #endif jobject keypairDelegate, jbyteArray rootCertificate, jbyteArray intermediateCertificate, jbyteArray nodeOperationalCertificate, jbyteArray ipkEpochKey, uint16_t listenPort, uint16_t controllerVendorId, uint16_t failsafeTimerSeconds, bool attemptNetworkScanWiFi, bool attemptNetworkScanThread, bool skipCommissioningComplete, bool skipAttestationCertificateValidation, jstring countryCode, bool enableServerInteractions, CHIP_ERROR * errInfoOnFailure); void Shutdown(); #ifdef JAVA_MATTER_CONTROLLER_TEST chip::Controller::ExampleOperationalCredentialsIssuer * GetAndroidOperationalCredentialsIssuer() #else chip::Controller::AndroidOperationalCredentialsIssuer * GetAndroidOperationalCredentialsIssuer() #endif { return mOpCredsIssuer.get(); } DeviceAttestationDelegateBridge * GetDeviceAttestationDelegateBridge() { return mDeviceAttestationDelegateBridge; } CHIP_ERROR UpdateDeviceAttestationDelegateBridge(jobject deviceAttestationDelegate, chip::Optional expiryTimeoutSecs, bool shouldWaitAfterDeviceAttestation); CHIP_ERROR UpdateAttestationTrustStoreBridge(jobject attestationTrustStoreDelegate, jobject cdTrustKeys); CHIP_ERROR StartOTAProvider(jobject otaProviderDelegate); CHIP_ERROR FinishOTAProvider(); CHIP_ERROR SetICDCheckInDelegate(jobject checkInDelegate); void StartDnssd(); void StopDnssd(); private: using ChipDeviceControllerPtr = std::unique_ptr; ChipDeviceControllerPtr mController; // TODO: This may need to be injected as a GroupDataProvider* chip::Credentials::GroupDataProviderImpl mGroupDataProvider; // TODO: This may need to be injected as an OperationalCertificateStore * chip::Credentials::PersistentStorageOpCertStore mOpCertStore; // TODO: This may need to be injected as a SessionKeystore* chip::Crypto::RawKeySessionKeystore mSessionKeystore; chip::app::AndroidCheckInDelegate mCheckInDelegate; chip::app::CheckInHandler mCheckInHandler; JavaVM * mJavaVM = nullptr; chip::JniGlobalReference mJavaObjectRef; #ifdef JAVA_MATTER_CONTROLLER_TEST ExampleOperationalCredentialsIssuerPtr mOpCredsIssuer; PersistentStorage mExampleStorage; #else AndroidOperationalCredentialsIssuerPtr mOpCredsIssuer; CHIPP256KeypairBridge * mKeypairBridge = nullptr; #endif // JAVA_MATTER_CONTROLLER_TEST // These fields allow us to release the string/byte array memory later. jstring ssidStr = nullptr; jstring passwordStr = nullptr; const char * ssid = nullptr; const char * password = nullptr; jbyteArray operationalDatasetBytes = nullptr; jbyte * operationalDataset = nullptr; std::vector mNocCertificate; std::vector mIcacCertificate; std::vector mRcacCertificate; char mCountryCode[kCountryCodeBufferLen]; chip::Controller::AutoCommissioner mAutoCommissioner; chip::Credentials::PartialDACVerifier mPartialDACVerifier; DeviceAttestationDelegateBridge * mDeviceAttestationDelegateBridge = nullptr; AttestationTrustStoreBridge * mAttestationTrustStoreBridge = nullptr; chip::Credentials::DeviceAttestationVerifier * mDeviceAttestationVerifier = nullptr; #if CHIP_DEVICE_CONFIG_DYNAMIC_SERVER OTAProviderDelegateBridge * mOtaProviderBridge = nullptr; #endif bool mDeviceIsICD = false; uint8_t mICDSymmetricKey[chip::Crypto::kAES_CCM128_Key_Length]; char mUserActiveModeTriggerInstructionBuffer[kUserActiveModeTriggerInstructionBufferLen]; chip::MutableCharSpan mUserActiveModeTriggerInstruction = chip::MutableCharSpan(mUserActiveModeTriggerInstructionBuffer); chip::BitMask mUserActiveModeTriggerHint; uint32_t mIdleModeDuration = 0; uint32_t mActiveModeDuration = 0; uint16_t mActiveModeThreshold = 0; chip::Controller::CommissioningParameters mCommissioningParameter; AndroidDeviceControllerWrapper(ChipDeviceControllerPtr controller, #ifdef JAVA_MATTER_CONTROLLER_TEST ExampleOperationalCredentialsIssuerPtr opCredsIssuer #else AndroidOperationalCredentialsIssuerPtr opCredsIssuer #endif ) : mController(std::move(controller)), mOpCredsIssuer(std::move(opCredsIssuer)) {} }; inline jlong AndroidDeviceControllerWrapper::ToJNIHandle() { static_assert(sizeof(jlong) >= sizeof(void *), "Need to store a pointer in a java handle"); return reinterpret_cast(this); }