diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/ChipClient.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/ChipClient.kt index 6e3833820716a3..568046623c15a2 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/ChipClient.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/ChipClient.kt @@ -30,6 +30,7 @@ import chip.platform.NsdManagerServiceBrowser import chip.platform.NsdManagerServiceResolver import chip.platform.PreferencesConfigurationManager import chip.platform.PreferencesKeyValueStoreManager +import com.google.chip.chiptool.attestation.ExampleAttestationTrustStoreDelegate import kotlin.coroutines.resume import kotlin.coroutines.resumeWithException import kotlin.coroutines.suspendCoroutine @@ -47,6 +48,9 @@ object ChipClient { if (!this::chipDeviceController.isInitialized) { chipDeviceController = ChipDeviceController(ControllerParams.newBuilder().setControllerVendorId(VENDOR_ID).build()) + // Set delegate for attestation trust store for device attestation verifier. + // It will replace the default attestation trust store. + chipDeviceController.setAttestationTrustStoreDelegate(ExampleAttestationTrustStoreDelegate(chipDeviceController)) } return chipDeviceController } diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/attestation/ExampleAttestationTrustStoreDelegate.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/attestation/ExampleAttestationTrustStoreDelegate.kt new file mode 100644 index 00000000000000..f5ae91dff353ee --- /dev/null +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/attestation/ExampleAttestationTrustStoreDelegate.kt @@ -0,0 +1,48 @@ +package com.google.chip.chiptool.attestation + +import android.util.Base64 +import chip.devicecontroller.AttestationTrustStoreDelegate +import chip.devicecontroller.ChipDeviceController +import java.util.* + +class ExampleAttestationTrustStoreDelegate(val chipDeviceController: ChipDeviceController) : + AttestationTrustStoreDelegate { + + private val paaCerts = arrayListOf(TEST_PAA_FFF1_Cert, TEST_PAA_NOVID_CERT) + + override fun getProductAttestationAuthorityCert(skid: ByteArray): ByteArray? { + for (paaCert in paaCerts) { + val paaCertBytes = Base64.decode(paaCert, Base64.DEFAULT) + val skidFromPaaCert = chipDeviceController.extractSkidFromPaaCert(paaCertBytes) + if (Arrays.equals(skid, skidFromPaaCert)) { + return paaCertBytes + } + } + return null + } + + companion object { + const val TEST_PAA_FFF1_Cert = + "MIIBvTCCAWSgAwIBAgIITqjoMYLUHBwwCgYIKoZIzj0EAwIwMDEYMBYGA1UEAwwP\n" + + "TWF0dGVyIFRlc3QgUEFBMRQwEgYKKwYBBAGConwCAQwERkZGMTAgFw0yMTA2Mjgx\n" + + "NDIzNDNaGA85OTk5MTIzMTIzNTk1OVowMDEYMBYGA1UEAwwPTWF0dGVyIFRlc3Qg\n" + + "UEFBMRQwEgYKKwYBBAGConwCAQwERkZGMTBZMBMGByqGSM49AgEGCCqGSM49AwEH\n" + + "A0IABLbLY3KIfyko9brIGqnZOuJDHK2p154kL2UXfvnO2TKijs0Duq9qj8oYShpQ\n" + + "NUKWDUU/MD8fGUIddR6Pjxqam3WjZjBkMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD\n" + + "VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRq/SJ3H1Ef7L8WQZdnENzcMaFxfjAfBgNV\n" + + "HSMEGDAWgBRq/SJ3H1Ef7L8WQZdnENzcMaFxfjAKBggqhkjOPQQDAgNHADBEAiBQ\n" + + "qoAC9NkyqaAFOPZTaK0P/8jvu8m+t9pWmDXPmqdRDgIgI7rI/g8j51RFtlM5CBpH\n" + + "mUkpxyqvChVI1A0DTVFLJd4=" + + const val TEST_PAA_NOVID_CERT = + "MIIBkTCCATegAwIBAgIHC4+6qN2G7jAKBggqhkjOPQQDAjAaMRgwFgYDVQQDDA9N\n" + + "YXR0ZXIgVGVzdCBQQUEwIBcNMjEwNjI4MTQyMzQzWhgPOTk5OTEyMzEyMzU5NTla\n" + + "MBoxGDAWBgNVBAMMD01hdHRlciBUZXN0IFBBQTBZMBMGByqGSM49AgEGCCqGSM49\n" + + "AwEHA0IABBDvAqgah7aBIfuo0xl4+AejF+UKqKgoRGgokUuTPejt1KXDnJ/3Gkzj\n" + + "ZH/X9iZTt9JJX8ukwPR/h2iAA54HIEqjZjBkMBIGA1UdEwEB/wQIMAYBAf8CAQEw\n" + + "DgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR4XOcFuGuPTm/Hk6pgy0PqaWiC1TAf\n" + + "BgNVHSMEGDAWgBR4XOcFuGuPTm/Hk6pgy0PqaWiC1TAKBggqhkjOPQQDAgNIADBF\n" + + "AiEAue/bPqBqUuwL8B5h2u0sLRVt22zwFBAdq3mPrAX6R+UCIGAGHT411g2dSw1E\n" + + "ja12EvfoXFguP8MS3Bh5TdNzcV5d" + } +} diff --git a/src/controller/java/AndroidDeviceControllerWrapper.cpp b/src/controller/java/AndroidDeviceControllerWrapper.cpp index 701d6d6683aad7..272f115d952a25 100644 --- a/src/controller/java/AndroidDeviceControllerWrapper.cpp +++ b/src/controller/java/AndroidDeviceControllerWrapper.cpp @@ -67,6 +67,16 @@ AndroidDeviceControllerWrapper::~AndroidDeviceControllerWrapper() delete mDeviceAttestationDelegateBridge; mDeviceAttestationDelegateBridge = nullptr; } + if (mDeviceAttestationVerifier != nullptr) + { + delete mDeviceAttestationVerifier; + mDeviceAttestationVerifier = nullptr; + } + if (mAttestationTrustStoreBridge != nullptr) + { + delete mAttestationTrustStoreBridge; + mAttestationTrustStoreBridge = nullptr; + } } void AndroidDeviceControllerWrapper::SetJavaObjectRef(JavaVM * vm, jobject obj) @@ -158,7 +168,7 @@ AndroidDeviceControllerWrapper * AndroidDeviceControllerWrapper::AllocateNew( // Initialize device attestation verifier // TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available const chip::Credentials::AttestationTrustStore * testingRootStore = chip::Credentials::GetTestAttestationTrustStore(); - SetDeviceAttestationVerifier(GetDefaultDACVerifier(testingRootStore)); + chip::Credentials::SetDeviceAttestationVerifier(GetDefaultDACVerifier(testingRootStore)); chip::Controller::FactoryInitParams initParams; chip::Controller::SetupParams setupParams; diff --git a/src/controller/java/AndroidDeviceControllerWrapper.h b/src/controller/java/AndroidDeviceControllerWrapper.h index 3267f7fc4519b5..a7191a9004bdd7 100644 --- a/src/controller/java/AndroidDeviceControllerWrapper.h +++ b/src/controller/java/AndroidDeviceControllerWrapper.h @@ -40,6 +40,7 @@ #endif // JAVA_MATTER_CONTROLLER_TEST #include "AndroidOperationalCredentialsIssuer.h" +#include "AttestationTrustStoreBridge.h" #include "DeviceAttestationDelegateBridge.h" /** @@ -196,6 +197,38 @@ class AndroidDeviceControllerWrapper : public chip::Controller::DevicePairingDel } } + void SetAttestationTrustStoreBridge(AttestationTrustStoreBridge * attestationTrustStoreBridge) + { + mAttestationTrustStoreBridge = attestationTrustStoreBridge; + } + + AttestationTrustStoreBridge * GetAttestationTrustStoreBridge() { return mAttestationTrustStoreBridge; } + + void ClearAttestationTrustStoreBridge() + { + if (mAttestationTrustStoreBridge != nullptr) + { + delete mAttestationTrustStoreBridge; + mAttestationTrustStoreBridge = nullptr; + } + } + + void SetDeviceAttestationVerifier(chip::Credentials::DeviceAttestationVerifier * deviceAttestationVerifier) + { + mDeviceAttestationVerifier = deviceAttestationVerifier; + } + + chip::Credentials::DeviceAttestationVerifier * GetDeviceAttestationVerifier() { return mDeviceAttestationVerifier; } + + void ClearDeviceAttestationVerifier() + { + if (mDeviceAttestationVerifier != nullptr) + { + delete mDeviceAttestationVerifier; + mDeviceAttestationVerifier = nullptr; + } + } + private: using ChipDeviceControllerPtr = std::unique_ptr; @@ -232,7 +265,9 @@ class AndroidDeviceControllerWrapper : public chip::Controller::DevicePairingDel chip::Credentials::PartialDACVerifier mPartialDACVerifier; - DeviceAttestationDelegateBridge * mDeviceAttestationDelegateBridge = nullptr; + DeviceAttestationDelegateBridge * mDeviceAttestationDelegateBridge = nullptr; + AttestationTrustStoreBridge * mAttestationTrustStoreBridge = nullptr; + chip::Credentials::DeviceAttestationVerifier * mDeviceAttestationVerifier = nullptr; AndroidDeviceControllerWrapper(ChipDeviceControllerPtr controller, #ifdef JAVA_MATTER_CONTROLLER_TEST diff --git a/src/controller/java/AttestationTrustStoreBridge.cpp b/src/controller/java/AttestationTrustStoreBridge.cpp new file mode 100644 index 00000000000000..d5915543fa0be0 --- /dev/null +++ b/src/controller/java/AttestationTrustStoreBridge.cpp @@ -0,0 +1,93 @@ +/** + * + * Copyright (c) 2023 Project CHIP Authors + * + * 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. + */ + +#include "AttestationTrustStoreBridge.h" +#include +#include +#include +#include +#include +#include + +using namespace chip; + +AttestationTrustStoreBridge::~AttestationTrustStoreBridge() +{ + if (mAttestationTrustStoreDelegate != nullptr) + { + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread")); + env->DeleteGlobalRef(mAttestationTrustStoreDelegate); + mAttestationTrustStoreDelegate = nullptr; + } +} + +CHIP_ERROR AttestationTrustStoreBridge::GetProductAttestationAuthorityCert(const chip::ByteSpan & skid, + chip::MutableByteSpan & outPaaDerBuffer) const +{ + VerifyOrReturnError(skid.size() == chip::Crypto::kSubjectKeyIdentifierLength, CHIP_ERROR_INVALID_ARGUMENT); + + constexpr size_t paaCertAllocatedLen = chip::Credentials::kMaxDERCertLength; + Platform::ScopedMemoryBuffer paaCert; + VerifyOrReturnError(paaCert.Alloc(paaCertAllocatedLen), CHIP_ERROR_NO_MEMORY); + + MutableByteSpan paaDerBuffer{ paaCert.Get(), paaCertAllocatedLen }; + ReturnErrorOnFailure(GetPaaCertFromJava(skid, paaDerBuffer)); + + uint8_t skidBuf[chip::Crypto::kSubjectKeyIdentifierLength] = { 0 }; + chip::MutableByteSpan candidateSkidSpan{ skidBuf }; + VerifyOrReturnError(CHIP_NO_ERROR == chip::Crypto::ExtractSKIDFromX509Cert(paaDerBuffer, candidateSkidSpan), + CHIP_ERROR_INTERNAL); + + // Make sure the skid of the paa cert is match. + if (skid.data_equal(candidateSkidSpan)) + { + // Found a match + return CopySpanToMutableSpan(paaDerBuffer, outPaaDerBuffer); + } + return CHIP_ERROR_CA_CERT_NOT_FOUND; +} + +CHIP_ERROR AttestationTrustStoreBridge::GetPaaCertFromJava(const chip::ByteSpan & skid, + chip::MutableByteSpan & outPaaDerBuffer) const +{ + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + jclass attestationTrustStoreDelegateCls = nullptr; + jbyteArray javaSkid = nullptr; + jmethodID getProductAttestationAuthorityCertMethod = nullptr; + + JniReferences::GetInstance().GetClassRef(env, "chip/devicecontroller/AttestationTrustStoreDelegate", + attestationTrustStoreDelegateCls); + VerifyOrReturnError(attestationTrustStoreDelegateCls != nullptr, CHIP_JNI_ERROR_TYPE_NOT_FOUND); + JniClass attestationTrustStoreDelegateJniCls(attestationTrustStoreDelegateCls); + + JniReferences::GetInstance().FindMethod(env, mAttestationTrustStoreDelegate, "getProductAttestationAuthorityCert", "([B)[B", + &getProductAttestationAuthorityCertMethod); + VerifyOrReturnError(getProductAttestationAuthorityCertMethod != nullptr, CHIP_JNI_ERROR_METHOD_NOT_FOUND); + + JniReferences::GetInstance().N2J_ByteArray(env, skid.data(), static_cast(skid.size()), javaSkid); + VerifyOrReturnError(javaSkid != nullptr, CHIP_ERROR_NO_MEMORY); + + jbyteArray javaPaaCert = + (jbyteArray) env->CallObjectMethod(mAttestationTrustStoreDelegate, getProductAttestationAuthorityCertMethod, javaSkid); + VerifyOrReturnError(javaPaaCert != nullptr, CHIP_ERROR_CA_CERT_NOT_FOUND); + + JniByteArray paaCertBytes(env, javaPaaCert); + CopySpanToMutableSpan(paaCertBytes.byteSpan(), outPaaDerBuffer); + + return CHIP_NO_ERROR; +} diff --git a/src/controller/java/AttestationTrustStoreBridge.h b/src/controller/java/AttestationTrustStoreBridge.h new file mode 100644 index 00000000000000..be84be2f530307 --- /dev/null +++ b/src/controller/java/AttestationTrustStoreBridge.h @@ -0,0 +1,36 @@ +/** + * + * Copyright (c) 2023 Project CHIP Authors + * + * 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. + */ +#include +#include +#include + +class AttestationTrustStoreBridge : public chip::Credentials::AttestationTrustStore +{ +public: + AttestationTrustStoreBridge(jobject attestationTrustStoreDelegate) : + mAttestationTrustStoreDelegate(attestationTrustStoreDelegate) + {} + ~AttestationTrustStoreBridge(); + + CHIP_ERROR GetProductAttestationAuthorityCert(const chip::ByteSpan & skid, + chip::MutableByteSpan & outPaaDerBuffer) const override; + +protected: + jobject mAttestationTrustStoreDelegate = nullptr; + + CHIP_ERROR GetPaaCertFromJava(const chip::ByteSpan & skid, chip::MutableByteSpan & outPaaDerBuffer) const; +}; diff --git a/src/controller/java/BUILD.gn b/src/controller/java/BUILD.gn index 70f2b136747ae1..277f8dc27eb255 100644 --- a/src/controller/java/BUILD.gn +++ b/src/controller/java/BUILD.gn @@ -39,6 +39,8 @@ shared_library("jni") { "AndroidDeviceControllerWrapper.h", "AndroidOperationalCredentialsIssuer.cpp", "AndroidOperationalCredentialsIssuer.h", + "AttestationTrustStoreBridge.cpp", + "AttestationTrustStoreBridge.h", "BaseCHIPCluster-JNI.cpp", "CHIPAttributeTLVValueDecoder.h", "CHIPDefaultCallbacks.cpp", @@ -136,6 +138,7 @@ android_library("java") { "src/chip/clusterinfo/DelegatedClusterCallback.java", "src/chip/clusterinfo/InteractionInfo.java", "src/chip/devicecontroller/AttestationInfo.java", + "src/chip/devicecontroller/AttestationTrustStoreDelegate.java", "src/chip/devicecontroller/CSRInfo.java", "src/chip/devicecontroller/ChipClusterException.java", "src/chip/devicecontroller/ChipCommandType.java", diff --git a/src/controller/java/CHIPDeviceController-JNI.cpp b/src/controller/java/CHIPDeviceController-JNI.cpp index 44f305d2bb13d5..2cd6702bb14ecb 100644 --- a/src/controller/java/CHIPDeviceController-JNI.cpp +++ b/src/controller/java/CHIPDeviceController-JNI.cpp @@ -438,6 +438,41 @@ JNI_METHOD(void, setDeviceAttestationDelegate) } } +JNI_METHOD(void, setAttestationTrustStoreDelegate) +(JNIEnv * env, jobject self, jlong handle, jobject attestationTrustStoreDelegate) +{ + chip::DeviceLayer::StackLock lock; + CHIP_ERROR err = CHIP_NO_ERROR; + AndroidDeviceControllerWrapper * wrapper = AndroidDeviceControllerWrapper::FromJNIHandle(handle); + + ChipLogProgress(Controller, "setAttestationTrustStoreDelegate() called"); + + if (attestationTrustStoreDelegate != nullptr) + { + jobject attestationTrustStoreDelegateRef = env->NewGlobalRef(attestationTrustStoreDelegate); + AttestationTrustStoreBridge * attestationTrustStoreBridge = + new AttestationTrustStoreBridge(attestationTrustStoreDelegateRef); + VerifyOrExit(attestationTrustStoreBridge != nullptr, err = CHIP_ERROR_NO_MEMORY); + wrapper->ClearAttestationTrustStoreBridge(); + wrapper->SetAttestationTrustStoreBridge(attestationTrustStoreBridge); + + DeviceAttestationVerifier * deviceAttestationVerifier = + new Credentials::DefaultDACVerifier(wrapper->GetAttestationTrustStoreBridge()); + VerifyOrExit(deviceAttestationVerifier != nullptr, err = CHIP_ERROR_NO_MEMORY); + wrapper->ClearDeviceAttestationVerifier(); + wrapper->SetDeviceAttestationVerifier(deviceAttestationVerifier); + + wrapper->Controller()->SetDeviceAttestationVerifier(wrapper->GetDeviceAttestationVerifier()); + } + +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) { @@ -730,6 +765,38 @@ JNI_METHOD(jbyteArray, convertX509CertToMatterCert) return outJbytes; } +JNI_METHOD(jbyteArray, extractSkidFromPaaCert) +(JNIEnv * env, jobject self, jbyteArray paaCert) +{ + uint32_t allocatedCertLength = chip::Credentials::kMaxCHIPCertLength; + chip::Platform::ScopedMemoryBuffer outBuf; + jbyteArray outJbytes = nullptr; + JniByteArray paaCertBytes(env, paaCert); + + CHIP_ERROR err = CHIP_NO_ERROR; + VerifyOrExit(outBuf.Alloc(allocatedCertLength), err = CHIP_ERROR_NO_MEMORY); + { + MutableByteSpan outBytes(outBuf.Get(), allocatedCertLength); + + err = chip::Crypto::ExtractSKIDFromX509Cert(paaCertBytes.byteSpan(), outBytes); + SuccessOrExit(err); + + VerifyOrExit(chip::CanCastTo(outBytes.size()), err = CHIP_ERROR_INTERNAL); + + err = JniReferences::GetInstance().N2J_ByteArray(env, outBytes.data(), static_cast(outBytes.size()), outJbytes); + SuccessOrExit(err); + } + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Controller, "Failed to extract skid frome X509 cert. Err = %" CHIP_ERROR_FORMAT, err.Format()); + JniReferences::GetInstance().ThrowError(env, sChipDeviceControllerExceptionCls, err); + } + + return outJbytes; +} + JNI_METHOD(void, unpairDevice)(JNIEnv * env, jobject self, jlong handle, jlong deviceId) { chip::DeviceLayer::StackLock lock; diff --git a/src/controller/java/DeviceAttestationDelegateBridge.cpp b/src/controller/java/DeviceAttestationDelegateBridge.cpp index be46a783b197ad..5f002c726c175d 100644 --- a/src/controller/java/DeviceAttestationDelegateBridge.cpp +++ b/src/controller/java/DeviceAttestationDelegateBridge.cpp @@ -77,11 +77,14 @@ void DeviceAttestationDelegateBridge::OnDeviceAttestationCompleted( env, "chip/devicecontroller/DeviceAttestationDelegate$DeviceAttestationCompletionCallback", completionCallbackCls); VerifyOrReturn(completionCallbackCls != nullptr, ChipLogError(Controller, "Could not find device attestation completion callback class.")); + JniClass completionCallbackJniCls(completionCallbackCls); + jclass failureCallbackCls = nullptr; JniReferences::GetInstance().GetClassRef( env, "chip/devicecontroller/DeviceAttestationDelegate$DeviceAttestationFailureCallback", failureCallbackCls); VerifyOrReturn(failureCallbackCls != nullptr, ChipLogError(Controller, "Could not find device attestation failure callback class.")); + JniClass failureCallbackJniCls(failureCallbackCls); if (env->IsInstanceOf(mDeviceAttestationDelegate, completionCallbackCls)) { diff --git a/src/controller/java/src/chip/devicecontroller/AttestationTrustStoreDelegate.java b/src/controller/java/src/chip/devicecontroller/AttestationTrustStoreDelegate.java new file mode 100644 index 00000000000000..f4fbec34386b5c --- /dev/null +++ b/src/controller/java/src/chip/devicecontroller/AttestationTrustStoreDelegate.java @@ -0,0 +1,25 @@ +package chip.devicecontroller; + +import javax.annotation.Nullable; + +/** + * Delegate for attestation trust store for device attestation verifiers. + * + *

API is synchronous. This implementation will replace the built-in attestation trust store, + * please make sure you have the required paa certificate before commissioning. + */ +public interface AttestationTrustStoreDelegate { + /** + * Look-up a product attestation authority (PAA) cert by subject key identifier (SKID). + * + *

The implementations of this interface must have access to a set of PAAs to trust. + * + *

Interface is synchronous, and therefore this should not be used unless to expose a PAA store + * that is both fully local and quick to access. + * + * @param skid Buffer containing the subject key identifier (SKID) of the PAA to look-up + * @return If found, the result should return paa cert in x.509 format, if not found, return null. + */ + @Nullable + byte[] getProductAttestationAuthorityCert(byte[] skid); +} diff --git a/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java b/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java index bdcd60233c0b63..99214ec881d0d3 100644 --- a/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java +++ b/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java @@ -123,6 +123,19 @@ public void setDeviceAttestationFailureCallback( setDeviceAttestationDelegate(deviceControllerPtr, failSafeExpiryTimeoutSecs, failureCallback); } + /** + * Set delegate for attestation trust store for device attestation verifiers. + * + *

It will replace the built-in attestation trust store, please make sure you have the required + * paa certificate before commissioning. + * + * @param attestationTrustStoreDelegate Delegate for attestation trust store + */ + public void setAttestationTrustStoreDelegate( + AttestationTrustStoreDelegate attestationTrustStoreDelegate) { + setAttestationTrustStoreDelegate(deviceControllerPtr, attestationTrustStoreDelegate); + } + public void pairDevice( BluetoothGatt bleServer, int connId, @@ -626,6 +639,14 @@ public void readPath( */ public native byte[] convertX509CertToMatterCert(byte[] x509Cert); + /** + * Extract skid from paa cert. + * + * @param paaCert The product attestation authority (PAA) cert + * @return The subject key identifier (SKID) + */ + public native byte[] extractSkidFromPaaCert(byte[] paaCert); + /** * Generates a new PASE verifier for the given setup PIN code. * @@ -670,6 +691,9 @@ private native void read( private native void setDeviceAttestationDelegate( long deviceControllerPtr, int failSafeExpiryTimeoutSecs, DeviceAttestationDelegate delegate); + private native void setAttestationTrustStoreDelegate( + long deviceControllerPtr, AttestationTrustStoreDelegate delegate); + private native void pairDevice( long deviceControllerPtr, long deviceId,