| /* |
| * 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 <controller/java/ControllerConfig.h> |
| #include <lib/support/JniReferences.h> |
| |
| #include <memory> |
| #include <vector> |
| |
| #include <jni.h> |
| |
| #include <app/icd/client/CheckInHandler.h> |
| #include <app/icd/client/DefaultICDClientStorage.h> |
| #include <controller/CHIPDeviceController.h> |
| #include <controller/java/CHIPP256KeypairBridge.h> |
| #include <credentials/GroupDataProviderImpl.h> |
| #include <credentials/PersistentStorageOpCertStore.h> |
| #include <credentials/attestation_verifier/DacOnlyPartialAttestationVerifier.h> |
| #include <crypto/RawKeySessionKeystore.h> |
| #include <lib/support/TimeUtils.h> |
| #include <platform/internal/DeviceNetworkInfo.h> |
| #ifdef JAVA_MATTER_CONTROLLER_TEST |
| #include <controller/ExampleOperationalCredentialsIssuer.h> |
| #include <controller/ExamplePersistentStorage.h> |
| #else |
| #include <platform/android/AndroidChipPlatform-JNI.h> |
| #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(); |
| |
| /** |
| * 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<CHIPP256KeypairBridge>(); |
| } |
| return mKeypairBridge; |
| } |
| |
| 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<AndroidDeviceControllerWrapper *>(handle); |
| } |
| |
| #ifdef JAVA_MATTER_CONTROLLER_TEST |
| using ExampleOperationalCredentialsIssuerPtr = std::unique_ptr<chip::Controller::ExampleOperationalCredentialsIssuer>; |
| #else |
| using AndroidOperationalCredentialsIssuerPtr = std::unique_ptr<chip::Controller::AndroidOperationalCredentialsIssuer>; |
| #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<chip::Inet::TCPEndPoint> * tcpEndPointManager, |
| chip::Inet::EndPointManager<chip::Inet::UDPEndPoint> * 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<uint16_t> 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<chip::Controller::DeviceCommissioner>; |
| |
| 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; |
| CHIPP256KeypairBridge * mKeypairBridge = nullptr; |
| #ifdef JAVA_MATTER_CONTROLLER_TEST |
| ExampleOperationalCredentialsIssuerPtr mOpCredsIssuer; |
| PersistentStorage mExampleStorage; |
| #else |
| AndroidOperationalCredentialsIssuerPtr mOpCredsIssuer; |
| #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<uint8_t> mNocCertificate; |
| std::vector<uint8_t> mIcacCertificate; |
| std::vector<uint8_t> 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<chip::app::Clusters::IcdManagement::UserActiveModeTriggerBitmap> 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<jlong>(this); |
| } |