Skip to content

Commit

Permalink
Update from comment
Browse files Browse the repository at this point in the history
  • Loading branch information
joonhaengHeo committed Feb 23, 2024
1 parent f64c44f commit a38c3f3
Show file tree
Hide file tree
Showing 7 changed files with 287 additions and 196 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.google.chip.chiptool.attestation
import android.util.Base64
import chip.devicecontroller.AttestationTrustStoreDelegate
import chip.devicecontroller.ChipDeviceController
import chip.devicecontroller.DeviceAttestation
import java.util.*

class ExampleAttestationTrustStoreDelegate(val chipDeviceController: ChipDeviceController) :
Expand All @@ -14,7 +15,7 @@ class ExampleAttestationTrustStoreDelegate(val chipDeviceController: ChipDeviceC
return paaCerts
.map { Base64.decode(it, Base64.DEFAULT) }
.firstOrNull { cert ->
Arrays.equals(chipDeviceController.extractSkidFromPaaCert(cert), skid)
Arrays.equals(DeviceAttestation.extractSkidFromPaaCert(cert), skid)
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/controller/java/AndroidOperationalCredentialsIssuer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,14 +272,14 @@ CHIP_ERROR AndroidOperationalCredentialsIssuer::CallbackGenerateNOCChain(const B
JniReferences::GetInstance().N2J_ByteArray(env, firmwareInfoSpan.data(), static_cast<jint>(firmwareInfoSpan.size()),
javaFirmwareInfo);

uint16_t vendorId =
mAutoCommissioner->GetCommissioningParameters().GetRemoteVendorId().ValueOr(0x0000); // 0x0000 is Unspecified vendor ID value.
chip::VendorId vendorId =
mAutoCommissioner->GetCommissioningParameters().GetRemoteVendorId().ValueOr(chip::VendorId::Unspecified);
uint16_t productId =
mAutoCommissioner->GetCommissioningParameters().GetRemoteProductId().ValueOr(0x0000); // 0x0000 is invalid product ID value.

jobject attestationInfo;
err = N2J_AttestationInfo(env, javaAttestationChallenge, javaAttestationNonce, javaAttestationElements,
javaAttestationElementsSignature, javaDAC, javaPAI, javaCD, javaFirmwareInfo, vendorId, productId,
javaAttestationElementsSignature, javaDAC, javaPAI, javaCD, javaFirmwareInfo, static_cast<uint16_t>(vendorId), productId,
attestationInfo);
if (err != CHIP_NO_ERROR)
{
Expand Down
2 changes: 2 additions & 0 deletions src/controller/java/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ shared_library("jni") {
"CHIPAttributeTLVValueDecoder.h",
"CHIPDeviceController-JNI.cpp",
"CHIPEventTLVValueDecoder.h",
"DeviceAttestation-JNI.cpp",
"DeviceAttestationDelegateBridge.cpp",
"DeviceAttestationDelegateBridge.h",
"GroupDeviceProxy.h",
Expand Down Expand Up @@ -459,6 +460,7 @@ android_library("java") {
"src/chip/devicecontroller/ChipDeviceControllerException.java",
"src/chip/devicecontroller/ConnectionFailureException.java",
"src/chip/devicecontroller/ControllerParams.java",
"src/chip/devicecontroller/DeviceAttestation.java",
"src/chip/devicecontroller/DeviceAttestationDelegate.java",
"src/chip/devicecontroller/DiscoveredDevice.java",
"src/chip/devicecontroller/GetConnectedDeviceCallbackJni.java",
Expand Down
179 changes: 0 additions & 179 deletions src/controller/java/CHIPDeviceController-JNI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1238,185 +1238,6 @@ 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<uint8_t> 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<uint32_t>(outBytes.size()), err = CHIP_ERROR_INTERNAL);

err = JniReferences::GetInstance().N2J_ByteArray(env, outBytes.data(), static_cast<jsize>(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(jbyteArray, extractAkidFromPaiCert)
(JNIEnv * env, jclass clazz, jbyteArray paiCert)
{
uint32_t allocatedCertLength = chip::Credentials::kMaxCHIPCertLength;
chip::Platform::ScopedMemoryBuffer<uint8_t> outBuf;
jbyteArray outJbytes = nullptr;
JniByteArray paiCertBytes(env, paiCert);

CHIP_ERROR err = CHIP_NO_ERROR;
VerifyOrExit(outBuf.Alloc(allocatedCertLength), err = CHIP_ERROR_NO_MEMORY);
{
MutableByteSpan outBytes(outBuf.Get(), allocatedCertLength);

err = chip::Crypto::ExtractAKIDFromX509Cert(paiCertBytes.byteSpan(), outBytes);
SuccessOrExit(err);

VerifyOrExit(chip::CanCastTo<uint32_t>(outBytes.size()), err = CHIP_ERROR_INTERNAL);

err = JniReferences::GetInstance().N2J_ByteArray(env, outBytes.data(), static_cast<jsize>(outBytes.size()), outJbytes);
SuccessOrExit(err);
}

exit:
if (err != CHIP_NO_ERROR)
{
ChipLogError(Controller, "Failed to extract akid frome X509 cert. Err = %" CHIP_ERROR_FORMAT, err.Format());
JniReferences::GetInstance().ThrowError(env, sChipDeviceControllerExceptionCls, err);
}

return outJbytes;
}

JNI_METHOD(void, validateAttestationInfo)
(JNIEnv * env, jclass clazz, jint vendorId, jint productId, jbyteArray paaCert, jbyteArray paiCert, jbyteArray dacCert,
jbyteArray attestationElementsBuffer)
{
AttestationVerificationResult attestationError = AttestationVerificationResult::kSuccess;
CHIP_ERROR err = CHIP_NO_ERROR;

DeviceInfoForAttestation deviceInfo{
.vendorId = static_cast<uint16_t>(vendorId),
.productId = static_cast<uint16_t>(productId),
};

VerifyOrExit(paaCert != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(paiCert != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(dacCert != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);

{
JniByteArray paaCertBytes(env, paaCert);
JniByteArray paiCertBytes(env, paiCert);
JniByteArray dacCertBytes(env, dacCert);

AttestationCertVidPid paaVidPid;
AttestationCertVidPid paiVidPid;
AttestationCertVidPid dacVidPid;

uint8_t skidBuf[chip::Crypto::kAuthorityKeyIdentifierLength];
MutableByteSpan paaSKID(skidBuf);

CertificateChainValidationResult chainValidationResult;

err = chip::Crypto::VerifyAttestationCertificateFormat(paiCertBytes.byteSpan(), AttestationCertType::kPAI);
VerifyOrExit(err == CHIP_NO_ERROR,
ChipLogError(Controller, "Verify PAI Attestation Cert format Error! : %" CHIP_ERROR_FORMAT, err.Format()));

err = chip::Crypto::VerifyAttestationCertificateFormat(dacCertBytes.byteSpan(), AttestationCertType::kDAC);
VerifyOrExit(err == CHIP_NO_ERROR,
ChipLogError(Controller, "Verify DAC Attestation Cert format Error! : %" CHIP_ERROR_FORMAT, err.Format()));

err = chip::Crypto::ExtractVIDPIDFromX509Cert(paaCertBytes.byteSpan(), paaVidPid);
VerifyOrExit(err == CHIP_NO_ERROR,
ChipLogError(Controller, "Extract VID, PID from PAA Error! : %" CHIP_ERROR_FORMAT, err.Format()));

err = chip::Crypto::ExtractVIDPIDFromX509Cert(paiCertBytes.byteSpan(), paiVidPid);
VerifyOrExit(err == CHIP_NO_ERROR,
ChipLogError(Controller, "Extract VID, PID from PAI Error! : %" CHIP_ERROR_FORMAT, err.Format()));

err = chip::Crypto::ExtractVIDPIDFromX509Cert(dacCertBytes.byteSpan(), dacVidPid);
VerifyOrExit(err == CHIP_NO_ERROR,
ChipLogError(Controller, "Extract VID, PID from DAC Error! : %" CHIP_ERROR_FORMAT, err.Format()));

if (paaVidPid.mVendorId.HasValue())
{
VerifyOrExit(paaVidPid.mVendorId == paiVidPid.mVendorId,
attestationError = AttestationVerificationResult::kPaiVendorIdMismatch);
}

VerifyOrExit(!paaVidPid.mProductId.HasValue(), attestationError = AttestationVerificationResult::kPaaFormatInvalid);

err = chip::Crypto::ValidateCertificateChain(
paaCertBytes.byteSpan().data(), paaCertBytes.byteSpan().size(), paiCertBytes.byteSpan().data(),
paiCertBytes.byteSpan().size(), dacCertBytes.byteSpan().data(), dacCertBytes.byteSpan().size(), chainValidationResult);
VerifyOrExit(err == CHIP_NO_ERROR, attestationError = static_cast<AttestationVerificationResult>(chainValidationResult));

err = ExtractSKIDFromX509Cert(paaCertBytes.byteSpan(), paaSKID);
VerifyOrExit(err == CHIP_NO_ERROR, attestationError = AttestationVerificationResult::kPaaFormatInvalid);
VerifyOrExit(paaSKID.size() == chip::Crypto::kAuthorityKeyIdentifierLength,
attestationError = AttestationVerificationResult::kPaaFormatInvalid);

deviceInfo.dacVendorId = dacVidPid.mVendorId.Value();
deviceInfo.dacProductId = dacVidPid.mProductId.Value();
deviceInfo.paiVendorId = paiVidPid.mVendorId.Value();
deviceInfo.paiProductId = paiVidPid.mProductId.ValueOr(0);
deviceInfo.paaVendorId = paaVidPid.mVendorId.ValueOr(VendorId::NotSpecified);
}

{
VerifyOrExit(attestationElementsBuffer != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);

JniByteArray attestationElementsBytes(env, attestationElementsBuffer);

ByteSpan certificationDeclarationSpan;
ByteSpan attestationNonceSpan;
uint32_t timestampDeconstructed;
ByteSpan firmwareInfoSpan;
DeviceAttestationVendorReservedDeconstructor vendorReserved;
ByteSpan certificationDeclarationPayload;

const chip::Credentials::AttestationTrustStore * testingRootStore = chip::Credentials::GetTestAttestationTrustStore();
chip::Credentials::DeviceAttestationVerifier * dacVertifier = chip::Credentials::GetDefaultDACVerifier(testingRootStore);

err = chip::Credentials::DeconstructAttestationElements(attestationElementsBytes.byteSpan(), certificationDeclarationSpan,
attestationNonceSpan, timestampDeconstructed, firmwareInfoSpan,
vendorReserved);

VerifyOrExit(err == CHIP_NO_ERROR, attestationError = AttestationVerificationResult::kAttestationElementsMalformed);

attestationError =
dacVertifier->ValidateCertificationDeclarationSignature(certificationDeclarationSpan, certificationDeclarationPayload);
VerifyOrExit(attestationError == AttestationVerificationResult::kSuccess, err = CHIP_ERROR_INTERNAL);
}

exit:
if (err == CHIP_NO_ERROR && attestationError != AttestationVerificationResult::kSuccess)
{
err = CHIP_ERROR_INTERNAL;
}

if (err != CHIP_NO_ERROR)
{
ChipLogError(Controller, "Failed to validate Attestation Info. Err = %u, %" CHIP_ERROR_FORMAT,
static_cast<uint16_t>(attestationError), err.Format());
JniReferences::GetInstance().ThrowError(env, sChipDeviceControllerExceptionCls, err);
}
}

JNI_METHOD(void, unpairDevice)(JNIEnv * env, jobject self, jlong handle, jlong deviceId)
{
chip::DeviceLayer::StackLock lock;
Expand Down
Loading

0 comments on commit a38c3f3

Please sign in to comment.