blob: c1421863bbf29db8a3b6af30beb8696ef8eff654 [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 <lib/support/JniReferences.h>
#include <memory>
#include <vector>
#include <jni.h>
#include <controller/CHIPDeviceController.h>
#include <credentials/GroupDataProviderImpl.h>
#include <credentials/PersistentStorageOpCertStore.h>
#include <credentials/attestation_verifier/DacOnlyPartialAttestationVerifier.h>
#include <lib/support/TimeUtils.h>
#include <platform/android/CHIPP256KeypairBridge.h>
#include <platform/internal/DeviceNetworkInfo.h>
#include "AndroidOperationalCredentialsIssuer.h"
/**
* 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; }
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 CallJavaMethod(const char * methodName, jint 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);
/**
* 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;
// 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 mAutoCommissioner.GetCommissioningParameters();
}
static AndroidDeviceControllerWrapper * FromJNIHandle(jlong handle)
{
return reinterpret_cast<AndroidDeviceControllerWrapper *>(handle);
}
using AndroidOperationalCredentialsIssuerPtr = std::unique_ptr<chip::Controller::AndroidOperationalCredentialsIssuer>;
/**
* 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,
AndroidOperationalCredentialsIssuerPtr opCredsIssuer, 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, CHIP_ERROR * errInfoOnFailure);
chip::Controller::AndroidOperationalCredentialsIssuer * GetAndroidOperationalCredentialsIssuer()
{
return mOpCredsIssuer.get();
}
private:
using ChipDeviceControllerPtr = std::unique_ptr<chip::Controller::DeviceCommissioner>;
ChipDeviceControllerPtr mController;
AndroidOperationalCredentialsIssuerPtr mOpCredsIssuer;
// 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;
JavaVM * mJavaVM = nullptr;
jobject mJavaObjectRef = nullptr;
CHIPP256KeypairBridge * mKeypairBridge = nullptr;
// 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;
chip::Controller::AutoCommissioner mAutoCommissioner;
chip::Credentials::PartialDACVerifier mPartialDACVerifier;
AndroidDeviceControllerWrapper(ChipDeviceControllerPtr controller, AndroidOperationalCredentialsIssuerPtr opCredsIssuer) :
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);
}