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

Add Java callbacks for NOC Generation #21522

Merged
merged 12 commits into from
Aug 4, 2022
6 changes: 6 additions & 0 deletions src/controller/AutoCommissioner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ CHIP_ERROR AutoCommissioner::SetCommissioningParameters(const CommissioningParam
mParams.SetFailsafeTimerSeconds(params.GetFailsafeTimerSeconds().Value());
}

if (params.GetAdminSubject().HasValue())
{
ChipLogProgress(Controller, "Setting adminSubject from parameters");
mParams.SetAdminSubject(params.GetAdminSubject().Value());
}

if (params.GetThreadOperationalDataset().HasValue())
{
ByteSpan dataset = params.GetThreadOperationalDataset().Value();
Expand Down
2 changes: 1 addition & 1 deletion src/controller/java/AndroidDeviceControllerWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ AndroidDeviceControllerWrapper * AndroidDeviceControllerWrapper::AllocateNew(
initParams.opCertStore = &wrapper->mOpCertStore;

// TODO: Init IPK Epoch Key in opcreds issuer, so that commissionees get the right IPK
opCredsIssuer->Initialize(*wrapper.get(), wrapper.get()->mJavaObjectRef);
opCredsIssuer->Initialize(*wrapper.get(), &wrapper->mAutoCommissioner, wrapper.get()->mJavaObjectRef);

Platform::ScopedMemoryBuffer<uint8_t> noc;
if (!noc.Alloc(kMaxCHIPDERCertLength))
Expand Down
5 changes: 5 additions & 0 deletions src/controller/java/AndroidDeviceControllerWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,11 @@ class AndroidDeviceControllerWrapper : public chip::Controller::DevicePairingDel
uint16_t listenPort, uint16_t controllerVendorId, uint16_t failsafeTimerSeconds, bool attemptNetworkScanWiFi,
bool attemptNetworkScanThread, CHIP_ERROR * errInfoOnFailure);

chip::Controller::AndroidOperationalCredentialsIssuer * GetAndroidOperationalCredentialsIssuer()
{
return mOpCredsIssuer.get();
}

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

Expand Down
103 changes: 101 additions & 2 deletions src/controller/java/AndroidOperationalCredentialsIssuer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ using namespace Credentials;
using namespace Crypto;
using namespace TLV;

CHIP_ERROR AndroidOperationalCredentialsIssuer::Initialize(PersistentStorageDelegate & storage, jobject javaObjectRef)
CHIP_ERROR AndroidOperationalCredentialsIssuer::Initialize(PersistentStorageDelegate & storage, AutoCommissioner * autoCommissioner,
jobject javaObjectRef)
{
using namespace ASN1;
ASN1UniversalTime effectiveTime;
Expand Down Expand Up @@ -71,6 +72,7 @@ CHIP_ERROR AndroidOperationalCredentialsIssuer::Initialize(PersistentStorageDele
}

mStorage = &storage;
mAutoCommissioner = autoCommissioner;
mJavaObjectRef = javaObjectRef;

mInitialized = true;
Expand Down Expand Up @@ -128,11 +130,108 @@ CHIP_ERROR AndroidOperationalCredentialsIssuer::GenerateNOCChain(const ByteSpan
const ByteSpan & attestationChallenge, const ByteSpan & DAC,
const ByteSpan & PAI,
Callback::Callback<OnNOCChainGeneration> * onCompletion)
{
if (mUseJavaCallbackForNOCRequest)
{
return CallbackGenerateNOCChain(csrElements, csrNonce, attestationSignature, attestationChallenge, DAC, PAI, onCompletion);
}
else
{
return LocalGenerateNOCChain(csrElements, csrNonce, attestationSignature, attestationChallenge, DAC, PAI, onCompletion);
}
}

CHIP_ERROR AndroidOperationalCredentialsIssuer::CallbackGenerateNOCChain(const ByteSpan & csrElements, const ByteSpan & csrNonce,
const ByteSpan & csrSignature,
const ByteSpan & attestationChallenge,
const ByteSpan & DAC, const ByteSpan & PAI,
Callback::Callback<OnNOCChainGeneration> * onCompletion)
{
jmethodID method;
CHIP_ERROR err = CHIP_NO_ERROR;
err = JniReferences::GetInstance().FindMethod(JniReferences::GetInstance().GetEnvForCurrentThread(), mJavaObjectRef,
"onNOCChainGenerationNeeded", "([B[B[B[B[B[B[B[B[B)V", &method);
if (err != CHIP_NO_ERROR)
{
ChipLogError(Controller, "Error invoking onNOCChainGenerationNeeded: %" CHIP_ERROR_FORMAT, err.Format());
return err;
}

mOnNOCCompletionCallback = onCompletion;

JniReferences::GetInstance().GetEnvForCurrentThread()->ExceptionClear();

jbyteArray javaCsr;
JniReferences::GetInstance().N2J_ByteArray(JniReferences::GetInstance().GetEnvForCurrentThread(), csrElements.data(),
csrElements.size(), javaCsr);

jbyteArray javaCsrNonce;
JniReferences::GetInstance().N2J_ByteArray(JniReferences::GetInstance().GetEnvForCurrentThread(), csrNonce.data(),
csrNonce.size(), javaCsrNonce);

jbyteArray javaCsrSignature;
JniReferences::GetInstance().N2J_ByteArray(JniReferences::GetInstance().GetEnvForCurrentThread(), csrSignature.data(),
csrSignature.size(), javaCsrSignature);

jbyteArray javaAttestationChallenge;
JniReferences::GetInstance().N2J_ByteArray(JniReferences::GetInstance().GetEnvForCurrentThread(), attestationChallenge.data(),
attestationChallenge.size(), javaAttestationChallenge);

const ByteSpan & attestationElements = mAutoCommissioner->GetCommissioningParameters().GetAttestationElements().Value();
jbyteArray javaAttestationElements;
JniReferences::GetInstance().N2J_ByteArray(JniReferences::GetInstance().GetEnvForCurrentThread(), attestationElements.data(),
attestationElements.size(), javaAttestationElements);

const ByteSpan & attestationNonce = mAutoCommissioner->GetCommissioningParameters().GetAttestationNonce().Value();
jbyteArray javaAttestationNonce;
JniReferences::GetInstance().N2J_ByteArray(JniReferences::GetInstance().GetEnvForCurrentThread(), attestationNonce.data(),
attestationNonce.size(), javaAttestationNonce);

const ByteSpan & attestationElementsSignature =
mAutoCommissioner->GetCommissioningParameters().GetAttestationSignature().Value();
jbyteArray javaAttestationElementsSignature;
JniReferences::GetInstance().N2J_ByteArray(JniReferences::GetInstance().GetEnvForCurrentThread(),
attestationElementsSignature.data(), attestationElementsSignature.size(),
javaAttestationElementsSignature);

jbyteArray javaDAC;
JniReferences::GetInstance().N2J_ByteArray(JniReferences::GetInstance().GetEnvForCurrentThread(), DAC.data(), DAC.size(),
javaDAC);

jbyteArray javaPAI;
JniReferences::GetInstance().N2J_ByteArray(JniReferences::GetInstance().GetEnvForCurrentThread(), PAI.data(), PAI.size(),
javaPAI);

JniReferences::GetInstance().GetEnvForCurrentThread()->CallVoidMethod(
mJavaObjectRef, method, javaCsr, javaCsrNonce, javaCsrSignature, javaAttestationChallenge, javaAttestationElements,
javaAttestationNonce, javaAttestationElementsSignature, javaDAC, javaPAI);
return CHIP_NO_ERROR;
}

CHIP_ERROR AndroidOperationalCredentialsIssuer::NOCChainGenerated(CHIP_ERROR status, const ByteSpan & noc, const ByteSpan & icac,
const ByteSpan & rcac, Optional<Crypto::AesCcm128KeySpan> ipk,
Optional<NodeId> adminSubject)
{
ReturnErrorCodeIf(mOnNOCCompletionCallback == nullptr, CHIP_ERROR_INCORRECT_STATE);

Callback::Callback<OnNOCChainGeneration> * onCompletion = mOnNOCCompletionCallback;
mOnNOCCompletionCallback = nullptr;

// Call-back into commissioner with the generated data.
onCompletion->mCall(onCompletion->mContext, status, noc, icac, rcac, ipk, adminSubject);
return CHIP_NO_ERROR;
}

CHIP_ERROR AndroidOperationalCredentialsIssuer::LocalGenerateNOCChain(const ByteSpan & csrElements, const ByteSpan & csrNonce,
const ByteSpan & attestationSignature,
const ByteSpan & attestationChallenge, const ByteSpan & DAC,
const ByteSpan & PAI,
Callback::Callback<OnNOCChainGeneration> * onCompletion)
{
jmethodID method;
CHIP_ERROR err = CHIP_NO_ERROR;
err = JniReferences::GetInstance().FindMethod(JniReferences::GetInstance().GetEnvForCurrentThread(), mJavaObjectRef,
"onOpCSRGenerationComplete", "([B)V", &method);
"onOpCSRGenerationComplete", "([B)V", &method);
if (err != CHIP_NO_ERROR)
{
ChipLogError(Controller, "Error invoking onOpCSRGenerationComplete: %" CHIP_ERROR_FORMAT, err.Format());
Expand Down
24 changes: 23 additions & 1 deletion src/controller/java/AndroidOperationalCredentialsIssuer.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

#pragma once

#include <controller/AutoCommissioner.h>
#include <controller/OperationalCredentialsDelegate.h>
#include <crypto/CHIPCryptoPAL.h>
#include <lib/core/CASEAuthTag.h>
Expand All @@ -51,6 +52,14 @@ class DLL_EXPORT AndroidOperationalCredentialsIssuer : public OperationalCredent
const ByteSpan & attestationChallenge, const ByteSpan & DAC, const ByteSpan & PAI,
Callback::Callback<OnNOCChainGeneration> * onCompletion) override;

CHIP_ERROR NOCChainGenerated(CHIP_ERROR status, const ByteSpan & noc, const ByteSpan & icac, const ByteSpan & rcac,
Optional<Crypto::AesCcm128KeySpan> ipk, Optional<NodeId> adminSubject);

void SetUseJavaCallbackForNOCRequest(bool useJavaCallbackForNOCRequest)
{
mUseJavaCallbackForNOCRequest = useJavaCallbackForNOCRequest;
}

void SetNodeIdForNextNOCRequest(NodeId nodeId) override
{
mNextRequestedNodeId = nodeId;
Expand All @@ -69,7 +78,7 @@ class DLL_EXPORT AndroidOperationalCredentialsIssuer : public OperationalCredent
*
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR Initialize(PersistentStorageDelegate & storage, jobject javaObjectRef);
CHIP_ERROR Initialize(PersistentStorageDelegate & storage, AutoCommissioner * autoCommissioner, jobject javaObjectRef);

void SetIssuerId(uint32_t id) { mIssuerId = id; }

Expand All @@ -87,6 +96,15 @@ class DLL_EXPORT AndroidOperationalCredentialsIssuer : public OperationalCredent
MutableByteSpan & noc);

private:
CHIP_ERROR CallbackGenerateNOCChain(const ByteSpan & csrElements, const ByteSpan & csrNonce,
const ByteSpan & attestationSignature, const ByteSpan & attestationChallenge,
const ByteSpan & DAC, const ByteSpan & PAI,
Callback::Callback<OnNOCChainGeneration> * onCompletion);

CHIP_ERROR LocalGenerateNOCChain(const ByteSpan & csrElements, const ByteSpan & csrNonce, const ByteSpan & attestationSignature,
const ByteSpan & attestationChallenge, const ByteSpan & DAC, const ByteSpan & PAI,
Callback::Callback<OnNOCChainGeneration> * onCompletion);

Crypto::P256Keypair mIssuer;
bool mInitialized = false;
uint32_t mIssuerId = 0;
Expand All @@ -97,12 +115,16 @@ class DLL_EXPORT AndroidOperationalCredentialsIssuer : public OperationalCredent

NodeId mNextAvailableNodeId = 1;
PersistentStorageDelegate * mStorage = nullptr;
AutoCommissioner * mAutoCommissioner = nullptr;

NodeId mNextRequestedNodeId = 1;
FabricId mNextFabricId = 1;
bool mNodeIdRequested = false;

jobject mJavaObjectRef = nullptr;

bool mUseJavaCallbackForNOCRequest = false;
Callback::Callback<OnNOCChainGeneration> * mOnNOCCompletionCallback = nullptr;
};

} // namespace Controller
Expand Down
Loading