Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Android] Commissioner attestation delegate should be able to override success and failure #23173

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
11b5724
[Android] Added mechanism to override device attestation failure base…
panliming-tuya Oct 13, 2022
ea40f1a
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Oct 14, 2022
5ed16c0
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Oct 14, 2022
d36248a
platform jar keep name of method parameters
panliming-tuya Oct 14, 2022
1c38401
Restyled by whitespace
restyled-commits Oct 14, 2022
587ac5f
Restyled by google-java-format
restyled-commits Oct 14, 2022
66bedd6
Restyled by clang-format
restyled-commits Oct 14, 2022
d9be2ba
Restyled by gn
restyled-commits Oct 14, 2022
afdf205
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Oct 16, 2022
e8f0495
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Oct 18, 2022
640ddbd
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Oct 18, 2022
3c4f499
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Oct 20, 2022
48ce640
fix copyright
panliming-tuya Oct 20, 2022
eb95edd
Merge branch 'additional-verification-after-attestation' of https://g…
panliming-tuya Oct 20, 2022
5e8723b
fix and modify comments
panliming-tuya Oct 20, 2022
79024b4
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Oct 21, 2022
2270c9d
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Oct 28, 2022
47f079e
Use setters instead of adding parameters to methods
panliming-tuya Oct 28, 2022
27a3862
fix NetworkCredentials NPE
panliming-tuya Oct 28, 2022
beb066a
Do not expose deviceController raw pointer
panliming-tuya Oct 28, 2022
f9d3dd5
add sample
panliming-tuya Oct 28, 2022
9e6a181
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Nov 2, 2022
38b0c0c
Create AttestationTrustStoreBridge when we know we have PAA certs.
panliming-tuya Nov 3, 2022
0ee733e
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Nov 3, 2022
8481cde
fix jni method
panliming-tuya Nov 3, 2022
e6211db
fix certs loss of scope and add some comments
panliming-tuya Nov 7, 2022
3bacfe3
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Nov 7, 2022
3b40467
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Nov 8, 2022
b26afb9
implement destructor
panliming-tuya Nov 8, 2022
27584d6
fix destructor crash
panliming-tuya Nov 8, 2022
a654ede
revoke vscode setting change
panliming-tuya Nov 8, 2022
6db2e8b
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Nov 9, 2022
52c5c30
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Nov 15, 2022
4958adb
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Nov 18, 2022
213164e
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Nov 18, 2022
a610fa5
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Nov 21, 2022
59c8ca6
Restyled by whitespace
panliming-tuya Nov 21, 2022
3811015
Restyled by google-java-format
panliming-tuya Nov 21, 2022
8c01083
Restyled by clang-format
panliming-tuya Nov 21, 2022
5dcbae5
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Dec 13, 2022
8837adf
fix conflict
panliming-tuya Dec 15, 2022
212dc10
add unit of failSafeExpiryTimeout
panliming-tuya Dec 15, 2022
9d41d26
add sample code
panliming-tuya Dec 15, 2022
37f760a
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Dec 15, 2022
747645d
Restyled by whitespace
panliming-tuya Dec 15, 2022
17348b2
Restyled by google-java-format
panliming-tuya Dec 15, 2022
e5972ae
Restyled by clang-format
panliming-tuya Dec 15, 2022
9d915df
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Dec 19, 2022
993b5cf
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Jan 4, 2023
f069618
fix comments
panliming-tuya Jan 4, 2023
f485757
remove android attestation trust store
panliming-tuya Jan 4, 2023
c027231
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Jan 4, 2023
2b094c8
restyle
panliming-tuya Jan 4, 2023
9ef054d
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Jan 6, 2023
e2448ec
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Jan 7, 2023
8b14201
Merge branch 'master' into additional-verification-after-attestation
panliming-tuya Jan 10, 2023
9e6211b
Fix compile error in java-matter-controller
yufengwangca Jan 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,19 @@
package com.google.chip.chiptool.provisioning

import android.bluetooth.BluetoothGatt
import android.content.DialogInterface
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import chip.devicecontroller.AttestationInfo
import chip.devicecontroller.DeviceAttestationDelegate.DeviceAttestationCompletionCallback
import chip.devicecontroller.DeviceAttestationDelegate.DeviceAttestationFailureCallback
import chip.devicecontroller.NetworkCredentials
import com.google.chip.chiptool.NetworkCredentialsParcelable
import com.google.chip.chiptool.ChipClient
Expand All @@ -38,7 +43,9 @@ import com.google.chip.chiptool.util.DeviceIdUtil
import com.google.chip.chiptool.util.FragmentUtil
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Runnable
import kotlinx.coroutines.launch
import java.lang.IllegalArgumentException

@ExperimentalCoroutinesApi
class DeviceProvisioningFragment : Fragment() {
Expand Down Expand Up @@ -132,7 +139,32 @@ class DeviceProvisioningFragment : Fragment() {
if (thread != null) {
network = NetworkCredentials.forThread(NetworkCredentials.ThreadCredentials(thread.operationalDataset))
}

deviceController.setDeviceAttestationFailureCallback(DEVICE_ATTESTATION_FAILED_TIMEOUT
) { devicePtr, errorCode ->
Log.i(TAG, "Device attestation errorCode: $errorCode, " +
"Look at 'src/credentials/attestation_verifier/DeviceAttestationVerifier.h' " +
"AttestationVerificationResult enum to understand the errors")
requireActivity().runOnUiThread(Runnable {
val alertDialog: AlertDialog? = activity?.let {
val builder = AlertDialog.Builder(it)
builder.apply {
setPositiveButton("Continue",
DialogInterface.OnClickListener { dialog, id ->
deviceController.continueCommissioning(devicePtr, true)
})
setNegativeButton("No",
DialogInterface.OnClickListener { dialog, id ->
deviceController.continueCommissioning(devicePtr, false)
})
}
builder.setTitle("Device Attestation")
builder.setMessage("Device Attestation failed for device under commissioning. Do you wish to continue pairing?")
panliming-tuya marked this conversation as resolved.
Show resolved Hide resolved
// Create the AlertDialog
builder.create()
}
alertDialog?.show()
})
}
deviceController.pairDevice(gatt, connId, deviceId, deviceInfo.setupPinCode, network)
DeviceIdUtil.setNextAvailableId(requireContext(), deviceId + 1)
}
Expand Down Expand Up @@ -203,6 +235,13 @@ class DeviceProvisioningFragment : Fragment() {
private const val ARG_NETWORK_CREDENTIALS = "network_credentials"
private const val STATUS_PAIRING_SUCCESS = 0

/**
* Set for the fail-safe timer before onDeviceAttestationFailed is invoked.
*
* This time depends on the Commissioning timeout of your app.
*/
private const val DEVICE_ATTESTATION_FAILED_TIMEOUT = 600

/**
* Return a new instance of [DeviceProvisioningFragment]. [networkCredentialsParcelable] can be null for
* IP commissioning.
Expand Down
6 changes: 6 additions & 0 deletions src/controller/java/AndroidDeviceControllerWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ AndroidDeviceControllerWrapper::~AndroidDeviceControllerWrapper()
mKeypairBridge = nullptr;
}
#endif // JAVA_MATTER_CONTROLLER_TEST

if (mDeviceAttestationDelegateBridge != nullptr)
{
delete mDeviceAttestationDelegateBridge;
mDeviceAttestationDelegateBridge = nullptr;
}
}

void AndroidDeviceControllerWrapper::SetJavaObjectRef(JavaVM * vm, jobject obj)
Expand Down
22 changes: 21 additions & 1 deletion src/controller/java/AndroidDeviceControllerWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@
#include <controller/ExampleOperationalCredentialsIssuer.h>
#include <controller/ExamplePersistentStorage.h>
#else
#include "AndroidOperationalCredentialsIssuer.h"
#include <platform/android/AndroidChipPlatform-JNI.h>
#include <platform/android/CHIPP256KeypairBridge.h>
#endif // JAVA_MATTER_CONTROLLER_TEST

#include "AndroidOperationalCredentialsIssuer.h"
#include "DeviceAttestationDelegateBridge.h"

/**
* This class contains all relevant information for the JNI view of CHIPDeviceController
* to handle all controller-related processing.
Expand Down Expand Up @@ -178,6 +180,22 @@ class AndroidDeviceControllerWrapper : public chip::Controller::DevicePairingDel
return mOpCredsIssuer.get();
}

void SetDeviceAttestationDelegateBridge(DeviceAttestationDelegateBridge * deviceAttestationDelegateBridge)
{
mDeviceAttestationDelegateBridge = deviceAttestationDelegateBridge;
}

DeviceAttestationDelegateBridge * GetDeviceAttestationDelegateBridge() { return mDeviceAttestationDelegateBridge; }

void ClearDeviceAttestationDelegateBridge()
{
if (mDeviceAttestationDelegateBridge != nullptr)
{
delete mDeviceAttestationDelegateBridge;
panliming-tuya marked this conversation as resolved.
Show resolved Hide resolved
mDeviceAttestationDelegateBridge = nullptr;
}
}

private:
using ChipDeviceControllerPtr = std::unique_ptr<chip::Controller::DeviceCommissioner>;

Expand Down Expand Up @@ -214,6 +232,8 @@ class AndroidDeviceControllerWrapper : public chip::Controller::DevicePairingDel

chip::Credentials::PartialDACVerifier mPartialDACVerifier;

DeviceAttestationDelegateBridge * mDeviceAttestationDelegateBridge = nullptr;

AndroidDeviceControllerWrapper(ChipDeviceControllerPtr controller,
#ifdef JAVA_MATTER_CONTROLLER_TEST
ExampleOperationalCredentialsIssuerPtr opCredsIssuer
Expand Down
8 changes: 7 additions & 1 deletion src/controller/java/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ shared_library("jni") {
"CHIPDefaultCallbacks.cpp",
"CHIPDefaultCallbacks.h",
"CHIPDeviceController-JNI.cpp",
"DeviceAttestationDelegateBridge.cpp",
"DeviceAttestationDelegateBridge.h",
"zap-generated/CHIPAttributeTLVValueDecoder.cpp",
"zap-generated/CHIPClustersWrite-JNI.cpp",
"zap-generated/CHIPEventTLVValueDecoder.cpp",
Expand Down Expand Up @@ -108,6 +110,7 @@ android_library("java") {
"src/chip/devicecontroller/ChipDeviceController.java",
"src/chip/devicecontroller/ChipDeviceControllerException.java",
"src/chip/devicecontroller/ControllerParams.java",
"src/chip/devicecontroller/DeviceAttestationDelegate.java",
"src/chip/devicecontroller/DiscoveredDevice.java",
"src/chip/devicecontroller/GetConnectedDeviceCallbackJni.java",
"src/chip/devicecontroller/KeypairDelegate.java",
Expand Down Expand Up @@ -151,7 +154,10 @@ android_library("java") {
data_deps += [ "${chip_root}/build/chip/java:shared_cpplib" ]
}

javac_flags = [ "-Xlint:deprecation" ]
javac_flags = [
"-Xlint:deprecation",
"-parameters", # Store infomation about method parameters
]

# TODO: add classpath support (we likely need to add something like
# ..../platforms/android-21/android.jar to access BLE items)
Expand Down
86 changes: 85 additions & 1 deletion src/controller/java/CHIPDeviceController-JNI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ static CHIP_ERROR ParseAttributePath(jobject attributePath, EndpointId & outEndp
static CHIP_ERROR ParseEventPathList(jobject eventPathList, std::vector<app::EventPathParams> & outEventPathParamsList);
static CHIP_ERROR ParseEventPath(jobject eventPath, EndpointId & outEndpointId, ClusterId & outClusterId, EventId & outEventId);
static CHIP_ERROR IsWildcardChipPathId(jobject chipPathId, bool & isWildcard);
static CHIP_ERROR CreateDeviceAttestationDelegateBridge(JNIEnv * env, jlong handle, jobject deviceAttestationDelegate,
jint failSafeExpiryTimeoutSecs,
DeviceAttestationDelegateBridge ** deviceAttestationDelegateBridge);

namespace {

Expand Down Expand Up @@ -410,6 +413,31 @@ JNI_METHOD(jlong, newDeviceController)(JNIEnv * env, jobject self, jobject contr
return result;
}

JNI_METHOD(void, setDeviceAttestationDelegate)
(JNIEnv * env, jobject self, jlong handle, jint failSafeExpiryTimeoutSecs, jobject deviceAttestationDelegate)
{
chip::DeviceLayer::StackLock lock;
CHIP_ERROR err = CHIP_NO_ERROR;
AndroidDeviceControllerWrapper * wrapper = AndroidDeviceControllerWrapper::FromJNIHandle(handle);

ChipLogProgress(Controller, "setDeviceAttestationDelegate() called");
if (deviceAttestationDelegate != nullptr)
{
wrapper->ClearDeviceAttestationDelegateBridge();
DeviceAttestationDelegateBridge * deviceAttestationDelegateBridge = nullptr;
err = CreateDeviceAttestationDelegateBridge(env, handle, deviceAttestationDelegate, failSafeExpiryTimeoutSecs,
&deviceAttestationDelegateBridge);
VerifyOrExit(err == CHIP_NO_ERROR, err = CHIP_JNI_ERROR_EXCEPTION_THROWN);
wrapper->SetDeviceAttestationDelegateBridge(deviceAttestationDelegateBridge);
}
exit:
if (err != CHIP_NO_ERROR)
{
ChipLogError(Controller, "Failed to set device attestation delegate.");
JniReferences::GetInstance().ThrowError(env, sChipDeviceControllerExceptionCls, err);
}
}

JNI_METHOD(void, commissionDevice)
(JNIEnv * env, jobject self, jlong handle, jlong deviceId, jbyteArray csrNonce, jobject networkCredentials)
{
Expand All @@ -425,7 +453,10 @@ JNI_METHOD(void, commissionDevice)
err = wrapper->ApplyNetworkCredentials(commissioningParams, networkCredentials);
VerifyOrExit(err == CHIP_NO_ERROR, err = CHIP_ERROR_INVALID_ARGUMENT);
}

if (wrapper->GetDeviceAttestationDelegateBridge() != nullptr)
{
commissioningParams.SetDeviceAttestationDelegate(wrapper->GetDeviceAttestationDelegateBridge());
}
if (csrNonce != nullptr)
{
JniByteArray jniCsrNonce(env, csrNonce);
Expand Down Expand Up @@ -471,6 +502,10 @@ JNI_METHOD(void, pairDevice)
JniByteArray jniCsrNonce(env, csrNonce);
commissioningParams.SetCSRNonce(jniCsrNonce.byteSpan());
}
if (wrapper->GetDeviceAttestationDelegateBridge() != nullptr)
{
commissioningParams.SetDeviceAttestationDelegate(wrapper->GetDeviceAttestationDelegateBridge());
}
err = wrapper->Controller()->PairDevice(deviceId, rendezvousParams, commissioningParams);

if (err != CHIP_NO_ERROR)
Expand Down Expand Up @@ -510,6 +545,10 @@ JNI_METHOD(void, pairDeviceWithAddress)
JniByteArray jniCsrNonce(env, csrNonce);
commissioningParams.SetCSRNonce(jniCsrNonce.byteSpan());
}
if (wrapper->GetDeviceAttestationDelegateBridge() != nullptr)
{
commissioningParams.SetDeviceAttestationDelegate(wrapper->GetDeviceAttestationDelegateBridge());
}
err = wrapper->Controller()->PairDevice(deviceId, rendezvousParams, commissioningParams);

if (err != CHIP_NO_ERROR)
Expand Down Expand Up @@ -576,6 +615,27 @@ JNI_METHOD(void, establishPaseConnectionByAddress)
}
}

JNI_METHOD(void, continueCommissioning)
(JNIEnv * env, jobject self, jlong handle, jlong devicePtr, jboolean ignoreAttestationFailure)
{
chip::DeviceLayer::StackLock lock;
ChipLogProgress(Controller, "continueCommissioning() called.");
CHIP_ERROR err = CHIP_NO_ERROR;
AndroidDeviceControllerWrapper * wrapper = AndroidDeviceControllerWrapper::FromJNIHandle(handle);
DeviceAttestationDelegateBridge * deviceAttestationDelegateBridge = wrapper->GetDeviceAttestationDelegateBridge();
auto lastAttestationResult = deviceAttestationDelegateBridge ? deviceAttestationDelegateBridge->attestationVerificationResult()
: chip::Credentials::AttestationVerificationResult::kSuccess;
chip::DeviceProxy * deviceProxy = reinterpret_cast<chip::DeviceProxy *>(devicePtr);
err = wrapper->Controller()->ContinueCommissioningAfterDeviceAttestation(
deviceProxy, ignoreAttestationFailure ? chip::Credentials::AttestationVerificationResult::kSuccess : lastAttestationResult);

if (err != CHIP_NO_ERROR)
{
ChipLogError(Controller, "Failed to continue commissioning.");
JniReferences::GetInstance().ThrowError(env, sChipDeviceControllerExceptionCls, err);
}
}

JNI_METHOD(void, setUseJavaCallbackForNOCRequest)
(JNIEnv * env, jobject self, jlong handle, jboolean useCallback)
{
Expand Down Expand Up @@ -1487,3 +1547,27 @@ CHIP_ERROR N2J_NetworkLocation(JNIEnv * env, jstring ipAddress, jint port, jint
exit:
return err;
}

CHIP_ERROR CreateDeviceAttestationDelegateBridge(JNIEnv * env, jlong handle, jobject deviceAttestationDelegate,
jint failSafeExpiryTimeoutSecs,
DeviceAttestationDelegateBridge ** deviceAttestationDelegateBridge)
{
CHIP_ERROR err = CHIP_NO_ERROR;
chip::Optional<uint16_t> timeoutSecs = chip::MakeOptional(static_cast<uint16_t>(failSafeExpiryTimeoutSecs));
bool shouldWaitAfterDeviceAttestation = false;
jclass completionCallbackCls = nullptr;
jobject deviceAttestationDelegateRef = env->NewGlobalRef(deviceAttestationDelegate);
VerifyOrExit(deviceAttestationDelegateRef != nullptr, err = CHIP_JNI_ERROR_NULL_OBJECT);
JniReferences::GetInstance().GetClassRef(
env, "chip/devicecontroller/DeviceAttestationDelegate$DeviceAttestationCompletionCallback", completionCallbackCls);
VerifyOrExit(completionCallbackCls != nullptr, err = CHIP_JNI_ERROR_TYPE_NOT_FOUND);

if (env->IsInstanceOf(deviceAttestationDelegate, completionCallbackCls))
{
shouldWaitAfterDeviceAttestation = true;
}
*deviceAttestationDelegateBridge =
new DeviceAttestationDelegateBridge(deviceAttestationDelegateRef, timeoutSecs, shouldWaitAfterDeviceAttestation);
exit:
return err;
}
Loading