Skip to content

Commit

Permalink
Passing the generated OpCSR back to the java layer
Browse files Browse the repository at this point in the history
  • Loading branch information
RitikaNanda committed Jun 18, 2021
1 parent 4b68052 commit 329efbb
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,8 @@ open class GenericChipDeviceListener : ChipDeviceController.CompletionListener {
override fun onError(error: Throwable?) {
// No op
}

override fun onOpCSRGenerationComplete(errorCode: ByteArray) {
// No op
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ class DeviceProvisioningFragment : Fragment() {
}
}

override fun onOpCSRGenerationComplete(errorCode: ByteArray) {
Log.d(TAG,String(errorCode))
}

override fun onPairingDeleted(code: Int) {
Log.d(TAG, "onPairingDeleted: $code")
}
Expand Down
74 changes: 72 additions & 2 deletions src/controller/java/AndroidDeviceControllerWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,17 @@
#include <algorithm>
#include <memory>

#include "JniReferences.h"
#include <support/CodeUtils.h>

#include <platform/KeyValueStoreManager.h>
#include <support/ThreadOperationalDataset.h>

using chip::Controller::DeviceCommissioner;

extern chip::Ble::BleLayer * GetJNIBleLayer();

constexpr const char kOperationalCredentialsIssuerKeypairStorage[] = "AndroidDeviceControllerKey";
AndroidDeviceControllerWrapper::~AndroidDeviceControllerWrapper()
{
if ((mJavaVM != nullptr) && (mJavaObjectRef != nullptr))
Expand All @@ -48,6 +52,15 @@ void AndroidDeviceControllerWrapper::CallJavaMethod(const char * methodName, jin
CallVoidInt(GetEnvForCurrentThread(), mJavaObjectRef, methodName, argument);
}

CHIP_ERROR AndroidDeviceControllerWrapper::GetRootCACertificate(chip::FabricId fabricId, uint8_t * certBuf, uint32_t certBufSize,
uint32_t & outCertLen)
{
Initialize();
VerifyOrReturnError(mInitialized, CHIP_ERROR_INCORRECT_STATE);
chip::X509CertRequestParams newCertParams = { 0, mIssuerId, mNow, mNow + mValidity, true, fabricId, false, 0 };
return NewRootX509Cert(newCertParams, mIssuer, certBuf, certBufSize, outCertLen);
}

AndroidDeviceControllerWrapper * AndroidDeviceControllerWrapper::AllocateNew(JavaVM * vm, jobject deviceControllerObj,
pthread_mutex_t * stackLock, chip::NodeId nodeId,
chip::System::Layer * systemLayer,
Expand Down Expand Up @@ -90,6 +103,7 @@ AndroidDeviceControllerWrapper * AndroidDeviceControllerWrapper::AllocateNew(Jav

initParams.storageDelegate = wrapper.get();
initParams.pairingDelegate = wrapper.get();
initParams.operationalCredentialsDelegate = wrapper.get();
initParams.systemLayer = systemLayer;
initParams.inetLayer = inetLayer;
initParams.bleLayer = GetJNIBleLayer();
Expand All @@ -100,8 +114,6 @@ AndroidDeviceControllerWrapper * AndroidDeviceControllerWrapper::AllocateNew(Jav
return nullptr;
}

initParams.operationalCredentialsDelegate = &wrapper->OpCredsIssuer();

*errInfoOnFailure = wrapper->Controller()->Init(nodeId, initParams);

if (*errInfoOnFailure != CHIP_NO_ERROR)
Expand Down Expand Up @@ -137,6 +149,64 @@ void AndroidDeviceControllerWrapper::OnPairingDeleted(CHIP_ERROR error)
CallJavaMethod("onPairingDeleted", static_cast<jint>(error));
}

CHIP_ERROR AndroidDeviceControllerWrapper::GenerateNodeOperationalCertificate(const chip::PeerId & peerId, const chip::ByteSpan & csr,
int64_t serialNumber, uint8_t * certBuf,
uint32_t certBufSize, uint32_t & outCertLen)
{
jmethodID method;
CHIP_ERROR err = CHIP_NO_ERROR;
err = FindMethod(GetEnvForCurrentThread(), mJavaObjectRef, "onOpCSRGenerationComplete", "([B)V", &method);
if (err != CHIP_NO_ERROR)
{
ChipLogError(Controller, "Error invoking onOpCSRGenerationComplete: %d", err);
return err;
}

// Initializing the KeyPair.
Initialize();

chip::X509CertRequestParams request = { serialNumber, mIssuerId, mNow, mNow + mValidity, true, peerId.GetFabricId(),
true, peerId.GetNodeId() };

chip::P256PublicKey pubkey;
ReturnErrorOnFailure(VerifyCertificateSigningRequest(csr.data(), csr.size(), pubkey));

ChipLogProgress(chipTool, "VerifyCertificateSigningRequest");


CHIP_ERROR generateCert = NewNodeOperationalX509Cert(request, chip::CertificateIssuerLevel::kIssuerIsRootCA, pubkey, mIssuer, certBuf, certBufSize,
outCertLen);
jbyteArray argument;
GetEnvForCurrentThread()->ExceptionClear();
N2J_ByteArray(GetEnvForCurrentThread(), csr.data(),csr.size(),argument);
GetEnvForCurrentThread()->CallVoidMethod(mJavaObjectRef, method, argument);
return generateCert;
}

CHIP_ERROR AndroidDeviceControllerWrapper::Initialize()
{
chip::Crypto::P256SerializedKeypair serializedKey;
uint16_t keySize = static_cast<uint16_t>(sizeof(serializedKey));

// TODO: Use Android keystore system instead of direct storage of private key and add specific errors to check if a specified item is not found in the keystore.
if (SyncGetKeyValue(kOperationalCredentialsIssuerKeypairStorage, &serializedKey, keySize) != CHIP_NO_ERROR)
{
// If storage doesn't have an existing keypair, create one and add it to the storage.
ReturnErrorOnFailure(mIssuer.Initialize());
ReturnErrorOnFailure(mIssuer.Serialize(serializedKey));
keySize = static_cast<uint16_t>(sizeof(serializedKey));
SyncSetKeyValue(kOperationalCredentialsIssuerKeypairStorage, &serializedKey, keySize);
}
else
{
// Use the keypair from the storage
ReturnErrorOnFailure(mIssuer.Deserialize(serializedKey));
}

mInitialized = true;
return CHIP_NO_ERROR;
}

void AndroidDeviceControllerWrapper::OnMessage(chip::System::PacketBufferHandle && msg) {}

void AndroidDeviceControllerWrapper::OnStatusChange(void) {}
Expand Down
14 changes: 14 additions & 0 deletions src/controller/java/AndroidDeviceControllerWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#include <controller/CHIPDeviceController.h>
#include <controller/ExampleOperationalCredentialsIssuer.h>
#include <support/TimeUtils.h>
#include <platform/internal/DeviceNetworkInfo.h>

/**
Expand All @@ -35,6 +36,7 @@
*/
class AndroidDeviceControllerWrapper : public chip::Controller::DevicePairingDelegate,
public chip::Controller::DeviceStatusDelegate,
public chip::Controller::OperationalCredentialsDelegate,
public chip::PersistentStorageDelegate
{
public:
Expand All @@ -59,12 +61,19 @@ class AndroidDeviceControllerWrapper : public chip::Controller::DevicePairingDel
jlong ToJNIHandle();

void CallJavaMethod(const char * methodName, jint argument);
CHIP_ERROR Initialize();

// DevicePairingDelegate implementation
void OnStatusUpdate(chip::Controller::DevicePairingDelegate::Status status) override;
void OnPairingComplete(CHIP_ERROR error) override;
void OnPairingDeleted(CHIP_ERROR error) override;

// OperationalCredentialsDelegate implementation
CHIP_ERROR GenerateNodeOperationalCertificate(const chip::PeerId & peerId, const chip::ByteSpan & csr, int64_t serialNumber,
uint8_t * certBuf, uint32_t certBufSize, uint32_t & outCertLen) override;

CHIP_ERROR GetRootCACertificate(chip::FabricId fabricId, uint8_t * certBuf, uint32_t certBufSize,uint32_t & outCertLen) override;

// DeviceStatusDelegate implementation
void OnMessage(chip::System::PacketBufferHandle && msg) override;
void OnStatusChange(void) override;
Expand All @@ -85,6 +94,11 @@ class AndroidDeviceControllerWrapper : public chip::Controller::DevicePairingDel

private:
using ChipDeviceControllerPtr = std::unique_ptr<chip::Controller::DeviceCommissioner>;
chip::Crypto::P256Keypair mIssuer;
bool mInitialized = false;
uint32_t mIssuerId = 0;
uint32_t mNow = chip::CalendarToChipEpochTime(2021, 06, 10, 0, 0, 0, mNow);
uint32_t mValidity = 10 * chip::kSecondsPerStandardYear;

ChipDeviceControllerPtr mController;
chip::Controller::ExampleOperationalCredentialsIssuer mOpCredsIssuer;
Expand Down
15 changes: 0 additions & 15 deletions src/controller/java/CHIPDeviceController-JNI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ static void HandleNewConnection(void * appState, const uint16_t discriminator);
static void ThrowError(JNIEnv * env, CHIP_ERROR errToThrow);
static void ReportError(JNIEnv * env, CHIP_ERROR cbErr, const char * cbName);
static void * IOThreadMain(void * arg);
static CHIP_ERROR N2J_ByteArray(JNIEnv * env, const uint8_t * inArray, uint32_t inArrayLen, jbyteArray & outArray);
static CHIP_ERROR N2J_Error(JNIEnv * env, CHIP_ERROR inErr, jthrowable & outEx);

namespace {
Expand Down Expand Up @@ -1116,20 +1115,6 @@ void ThrowError(JNIEnv * env, CHIP_ERROR errToThrow)
}
}

CHIP_ERROR N2J_ByteArray(JNIEnv * env, const uint8_t * inArray, uint32_t inArrayLen, jbyteArray & outArray)
{
CHIP_ERROR err = CHIP_NO_ERROR;

outArray = env->NewByteArray((int) inArrayLen);
VerifyOrExit(outArray != NULL, err = CHIP_ERROR_NO_MEMORY);

env->ExceptionClear();
env->SetByteArrayRegion(outArray, 0, inArrayLen, (jbyte *) inArray);
VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN);

exit:
return err;
}

CHIP_ERROR N2J_Error(JNIEnv * env, CHIP_ERROR inErr, jthrowable & outEx)
{
Expand Down
15 changes: 15 additions & 0 deletions src/controller/java/JniReferences.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,21 @@ CHIP_ERROR GetClassRef(JNIEnv * env, const char * clsType, jclass & outCls)
return err;
}

CHIP_ERROR N2J_ByteArray(JNIEnv * env, const uint8_t * inArray, uint32_t inArrayLen, jbyteArray & outArray)
{
CHIP_ERROR err = CHIP_NO_ERROR;

outArray = env->NewByteArray((int) inArrayLen);
VerifyOrExit(outArray != NULL, err = CHIP_ERROR_NO_MEMORY);

env->ExceptionClear();
env->SetByteArrayRegion(outArray, 0, inArrayLen, (jbyte *) inArray);
VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN);

exit:
return err;
}

CHIP_ERROR FindMethod(JNIEnv * env, jobject object, const char * methodName, const char * methodSignature, jmethodID * methodId)
{
CHIP_ERROR err = CHIP_NO_ERROR;
Expand Down
1 change: 1 addition & 0 deletions src/controller/java/JniReferences.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ void SetJavaVm(JavaVM * jvm);
JNIEnv * GetEnvForCurrentThread();

CHIP_ERROR GetClassRef(JNIEnv * env, const char * clsType, jclass & outCls);
CHIP_ERROR N2J_ByteArray(JNIEnv * env, const uint8_t * inArray, uint32_t inArrayLen, jbyteArray & outArray);
CHIP_ERROR FindMethod(JNIEnv * env, jobject object, const char * methodName, const char * methodSignature, jmethodID * methodId);
void CallVoidInt(JNIEnv * env, jobject object, const char * methodName, jint argument);
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ public void onPairingComplete(int errorCode) {
}
}

public void onOpCSRGenerationComplete(byte[] errorCode) {
if (completionListener != null) {
completionListener.onOpCSRGenerationComplete(errorCode);
}
}

public void onPairingDeleted(int errorCode) {
if (completionListener != null) {
completionListener.onPairingDeleted(errorCode);
Expand Down Expand Up @@ -259,5 +265,8 @@ public interface CompletionListener {

/** Notifies the listener of the error. */
void onError(Throwable error);

/** Notifies the Commissioner when the OpCSR for the Comissionee is generated. */
void onOpCSRGenerationComplete(byte[] errorCode);
}
}

0 comments on commit 329efbb

Please sign in to comment.