From cab1ff9cf129ee7d2b79c225a4682fca2f0bc1e8 Mon Sep 17 00:00:00 2001 From: Kevin Coppock <47542933+g-coppock@users.noreply.github.com> Date: Tue, 8 Feb 2022 20:53:46 -0600 Subject: [PATCH] Surface an accessor for the PASE attestation challenge in Java (#14894) Fixes #14893 Tested: - Ran locally against a device being commissioned, and verified a challenge was returned as expected. --- src/controller/CHIPDeviceController.cpp | 13 ++++++++ src/controller/CHIPDeviceController.h | 10 ++++++ .../java/CHIPDeviceController-JNI.cpp | 31 +++++++++++++++++++ .../ChipDeviceController.java | 13 ++++++++ 4 files changed, 67 insertions(+) diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 1e4fb605f75dc5..7fc59e44864572 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -932,6 +932,19 @@ CHIP_ERROR DeviceCommissioner::Commission(NodeId remoteDeviceId, CommissioningPa return CHIP_NO_ERROR; } +CHIP_ERROR DeviceCommissioner::GetAttestationChallenge(ByteSpan & attestationChallenge) +{ + Optional secureSessionHandle; + + VerifyOrReturnError(mDeviceBeingCommissioned != nullptr, CHIP_ERROR_INCORRECT_STATE); + + secureSessionHandle = mDeviceBeingCommissioned->GetSecureSession(); + VerifyOrReturnError(secureSessionHandle.HasValue(), CHIP_ERROR_INCORRECT_STATE); + + attestationChallenge = secureSessionHandle.Value()->AsSecureSession()->GetCryptoContext().GetAttestationChallenge(); + return CHIP_NO_ERROR; +} + CHIP_ERROR DeviceCommissioner::StopPairing(NodeId remoteDeviceId) { VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE); diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index 81170a48df4376..f05ba0a840bd98 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -531,6 +531,16 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, CHIP_ERROR GetConnectedDevice(NodeId deviceId, chip::Callback::Callback * onConnection, chip::Callback::Callback * onFailure) override; + /** + * @brief + * This function returns the attestation challenge for the secure session of the device being commissioned. + * + * @param[out] attestationChallenge The output for the attestationChallenge + * + * @return CHIP_ERROR CHIP_NO_ERROR on success, or CHIP_ERROR_INVALID_ARGUMENT if no secure session is active + */ + CHIP_ERROR GetAttestationChallenge(ByteSpan & attestationChallenge); + /** * @brief * This function stops a pairing process that's in progress. It does not delete the pairing of a previously diff --git a/src/controller/java/CHIPDeviceController-JNI.cpp b/src/controller/java/CHIPDeviceController-JNI.cpp index 73849bd74ce3d4..09a79d386677cf 100644 --- a/src/controller/java/CHIPDeviceController-JNI.cpp +++ b/src/controller/java/CHIPDeviceController-JNI.cpp @@ -572,6 +572,37 @@ JNI_METHOD(jboolean, openPairingWindowWithPIN) return true; } +JNI_METHOD(jbyteArray, getAttestationChallenge) +(JNIEnv * env, jobject self, jlong handle, jlong devicePtr) +{ + chip::DeviceLayer::StackLock lock; + CHIP_ERROR err = CHIP_NO_ERROR; + ByteSpan attestationChallenge; + jbyteArray attestationChallengeJbytes = nullptr; + + DeviceProxy * chipDevice = reinterpret_cast(devicePtr); + if (chipDevice == nullptr) + { + ChipLogProgress(Controller, "Could not cast device pointer to Device object"); + JniReferences::GetInstance().ThrowError(env, sChipDeviceControllerExceptionCls, CHIP_ERROR_INCORRECT_STATE); + } + + AndroidDeviceControllerWrapper * wrapper = AndroidDeviceControllerWrapper::FromJNIHandle(handle); + err = wrapper->Controller()->GetAttestationChallenge(attestationChallenge); + SuccessOrExit(err); + + err = JniReferences::GetInstance().N2J_ByteArray(env, attestationChallenge.data(), sizeof(attestationChallenge.data()), + attestationChallengeJbytes); + SuccessOrExit(err); + +exit: + if (err != CHIP_NO_ERROR) + { + JniReferences::GetInstance().ThrowError(env, sChipDeviceControllerExceptionCls, err); + } + return attestationChallengeJbytes; +} + JNI_METHOD(void, deleteDeviceController)(JNIEnv * env, jobject self, jlong handle) { chip::DeviceLayer::StackLock lock; diff --git a/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java b/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java index 1e47838e2df2e7..ef36c3e8e91b44 100644 --- a/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java +++ b/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java @@ -300,6 +300,17 @@ public void shutdownSubscriptions(long devicePtr) { shutdownSubscriptions(deviceControllerPtr, devicePtr); } + /** + * Returns an attestation challenge for the given device, for which there must be an existing + * secure session. + * + * @param devicePtr a pointer to the device from which to retrieve the challenge + * @throws ChipDeviceControllerException if there is no secure session for the given device + */ + public byte[] getAttestationChallenge(long devicePtr) { + return getAttestationChallenge(deviceControllerPtr, devicePtr); + } + /** Subscribe to the given attribute path. */ public void subscribeToPath( SubscriptionEstablishedCallback subscriptionEstablishedCallback, @@ -417,6 +428,8 @@ private native boolean openPairingWindowWithPIN( private native boolean isActive(long deviceControllerPtr, long deviceId); + private native byte[] getAttestationChallenge(long deviceControllerPtr, long devicePtr); + private native void shutdownSubscriptions(long deviceControllerPtr, long devicePtr); static {