blob: 1d26d31d112774013da564880db761345600722b [file] [log] [blame]
/*
* 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 <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>
#include <platform/android/CHIPP256KeypairBridge.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();
#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<CHIPP256KeypairBridge>();
}
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::NodeId 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;
#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<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);
}