Skip to content

Commit

Permalink
Add parsed attestation and csr info for Android apps (#21648)
Browse files Browse the repository at this point in the history
* Draft: Add parsed attestation and csr info for Android apps

* Restyle Draft: Add parsed attestation and csr info for Android apps (#21649)

* Restyled by google-java-format

* Restyled by gn

Co-authored-by: Restyled.io <commits@restyled.io>

* Restyled by google-java-format (#21694)

Co-authored-by: Restyled.io <commits@restyled.io>

Co-authored-by: restyled-io[bot] <32688539+restyled-io[bot]@users.noreply.github.com>
Co-authored-by: Restyled.io <commits@restyled.io>
  • Loading branch information
3 people authored and pull[bot] committed Feb 15, 2024
1 parent 09ccb5b commit 1584108
Show file tree
Hide file tree
Showing 5 changed files with 235 additions and 55 deletions.
157 changes: 132 additions & 25 deletions src/controller/java/AndroidOperationalCredentialsIssuer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "AndroidOperationalCredentialsIssuer.h"
#include <algorithm>
#include <credentials/CHIPCert.h>
#include <credentials/DeviceAttestationConstructor.h>
#include <lib/core/CASEAuthTag.h>
#include <lib/core/CHIPTLV.h>
#include <lib/support/CHIPMem.h>
Expand All @@ -30,6 +31,7 @@

#include <lib/support/CHIPJNIError.h>
#include <lib/support/JniReferences.h>
#include <lib/support/JniTypeWrappers.h>

namespace chip {
namespace Controller {
Expand All @@ -40,6 +42,13 @@ using namespace Credentials;
using namespace Crypto;
using namespace TLV;

static CHIP_ERROR N2J_CSRInfo(JNIEnv * env, jbyteArray nonce, jbyteArray elements, jbyteArray elementsSignature, jbyteArray csr,
jobject & outCSRInfo);

static CHIP_ERROR N2J_AttestationInfo(JNIEnv * env, jbyteArray challenge, jbyteArray nonce, jbyteArray elements,
jbyteArray elementsSignature, jbyteArray dac, jbyteArray pai, jbyteArray cd,
jbyteArray firmwareInfo, jobject & outAttestationInfo);

CHIP_ERROR AndroidOperationalCredentialsIssuer::Initialize(PersistentStorageDelegate & storage, AutoCommissioner * autoCommissioner,
jobject javaObjectRef)
{
Expand Down Expand Up @@ -149,8 +158,9 @@ CHIP_ERROR AndroidOperationalCredentialsIssuer::CallbackGenerateNOCChain(const B
{
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);
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
err = JniReferences::GetInstance().FindMethod(env, 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());
Expand All @@ -159,52 +169,103 @@ CHIP_ERROR AndroidOperationalCredentialsIssuer::CallbackGenerateNOCChain(const B

mOnNOCCompletionCallback = onCompletion;

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

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

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

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

ChipLogProgress(Controller, "Parsing Certificate Signing Request");
TLVReader reader;
reader.Init(csrElements);

if (reader.GetType() == kTLVType_NotSpecified)
{
ReturnErrorOnFailure(reader.Next());
}

VerifyOrReturnError(reader.GetType() == kTLVType_Structure, CHIP_ERROR_WRONG_TLV_TYPE);
VerifyOrReturnError(reader.GetTag() == AnonymousTag(), CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);

TLVType containerType;
ReturnErrorOnFailure(reader.EnterContainer(containerType));
ReturnErrorOnFailure(reader.Next(kTLVType_ByteString, TLV::ContextTag(1)));

ByteSpan csr(reader.GetReadPoint(), reader.GetLength());
reader.ExitContainer(containerType);

jbyteArray javaCsr;
JniReferences::GetInstance().N2J_ByteArray(env, csr.data(), csr.size(), javaCsr);

jobject csrInfo;
err = N2J_CSRInfo(env, javaCsrNonce, javaCsrElements, javaCsrSignature, javaCsr, csrInfo);
if (err != CHIP_NO_ERROR)
{
ChipLogError(Controller, "Failed to create CSRInfo");
return err;
}

jbyteArray javaAttestationChallenge;
JniReferences::GetInstance().N2J_ByteArray(JniReferences::GetInstance().GetEnvForCurrentThread(), attestationChallenge.data(),
attestationChallenge.size(), javaAttestationChallenge);
JniReferences::GetInstance().N2J_ByteArray(env, 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);
JniReferences::GetInstance().N2J_ByteArray(env, 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);
JniReferences::GetInstance().N2J_ByteArray(env, 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(),
JniReferences::GetInstance().N2J_ByteArray(env, attestationElementsSignature.data(), attestationElementsSignature.size(),
javaAttestationElementsSignature);

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

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

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

err = DeconstructAttestationElements(attestationElements, certificationDeclarationSpan, attestationNonceSpan,
timestampDeconstructed, firmwareInfoSpan, vendorReserved);
if (err != CHIP_NO_ERROR)
{
ChipLogError(Controller, "Failed to create parse attestation elements");
return err;
}

jbyteArray javaCD;
JniReferences::GetInstance().N2J_ByteArray(env, certificationDeclarationSpan.data(), certificationDeclarationSpan.size(),
javaCD);

JniReferences::GetInstance().GetEnvForCurrentThread()->CallVoidMethod(
mJavaObjectRef, method, javaCsr, javaCsrNonce, javaCsrSignature, javaAttestationChallenge, javaAttestationElements,
javaAttestationNonce, javaAttestationElementsSignature, javaDAC, javaPAI);
jbyteArray javaFirmwareInfo;
JniReferences::GetInstance().N2J_ByteArray(env, firmwareInfoSpan.data(), firmwareInfoSpan.size(), javaFirmwareInfo);

jobject attestationInfo;
err = N2J_AttestationInfo(env, javaAttestationChallenge, javaAttestationNonce, javaAttestationElements,
javaAttestationElementsSignature, javaDAC, javaPAI, javaCD, javaFirmwareInfo, attestationInfo);
if (err != CHIP_NO_ERROR)
{
ChipLogError(Controller, "Failed to create AttestationInfo");
return err;
}

env->CallVoidMethod(mJavaObjectRef, method, csrInfo, attestationInfo);
return CHIP_NO_ERROR;
}

Expand Down Expand Up @@ -312,5 +373,51 @@ CHIP_ERROR AndroidOperationalCredentialsIssuer::LocalGenerateNOCChain(const Byte
return CHIP_NO_ERROR;
}

CHIP_ERROR N2J_CSRInfo(JNIEnv * env, jbyteArray nonce, jbyteArray elements, jbyteArray elementsSignature, jbyteArray csr,
jobject & outCSRInfo)
{
CHIP_ERROR err = CHIP_NO_ERROR;
jmethodID constructor;
jclass infoClass;

err = JniReferences::GetInstance().GetClassRef(env, "chip/devicecontroller/CSRInfo", infoClass);
JniClass attestationInfoClass(infoClass);
SuccessOrExit(err);

env->ExceptionClear();
constructor = env->GetMethodID(infoClass, "<init>", "([B[B[B[B)V");
VerifyOrExit(constructor != nullptr, err = CHIP_JNI_ERROR_METHOD_NOT_FOUND);

outCSRInfo = (jobject) env->NewObject(infoClass, constructor, nonce, elements, elementsSignature, csr);

VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN);
exit:
return err;
}

CHIP_ERROR N2J_AttestationInfo(JNIEnv * env, jbyteArray challenge, jbyteArray nonce, jbyteArray elements,
jbyteArray elementsSignature, jbyteArray dac, jbyteArray pai, jbyteArray cd, jbyteArray firmwareInfo,
jobject & outAttestationInfo)
{
CHIP_ERROR err = CHIP_NO_ERROR;
jmethodID constructor;
jclass infoClass;

err = JniReferences::GetInstance().GetClassRef(env, "chip/devicecontroller/AttestationInfo", infoClass);
JniClass attestationInfoClass(infoClass);
SuccessOrExit(err);

env->ExceptionClear();
constructor = env->GetMethodID(infoClass, "<init>", "([B[B[B[B[B[B[B[B)V");
VerifyOrExit(constructor != nullptr, err = CHIP_JNI_ERROR_METHOD_NOT_FOUND);

outAttestationInfo =
(jobject) env->NewObject(infoClass, constructor, challenge, nonce, elements, elementsSignature, dac, pai, cd, firmwareInfo);

VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN);
exit:
return err;
}

} // namespace Controller
} // namespace chip
2 changes: 2 additions & 0 deletions src/controller/java/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ android_library("java") {
"src/chip/clusterinfo/CommandResponseInfo.java",
"src/chip/clusterinfo/DelegatedClusterCallback.java",
"src/chip/clusterinfo/InteractionInfo.java",
"src/chip/devicecontroller/AttestationInfo.java",
"src/chip/devicecontroller/CSRInfo.java",
"src/chip/devicecontroller/ChipClusterException.java",
"src/chip/devicecontroller/ChipCommandType.java",
"src/chip/devicecontroller/ChipDeviceController.java",
Expand Down
65 changes: 65 additions & 0 deletions src/controller/java/src/chip/devicecontroller/AttestationInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package chip.devicecontroller;

/** Represents information relating to product attestation. */
public final class AttestationInfo {

private byte[] challenge;
private byte[] nonce;
private byte[] elements;
private byte[] elementsSignature;
private byte[] dac;
private byte[] pai;
private byte[] certificationDeclaration;
private byte[] firmwareInfo;

public AttestationInfo(
byte[] challenge,
byte[] nonce,
byte[] elements,
byte[] elementsSignature,
byte[] dac,
byte[] pai,
byte[] certificationDeclaration,
byte[] firmwareInfo) {
this.challenge = challenge;
this.nonce = nonce;
this.elements = elements;
this.elementsSignature = elementsSignature;
this.dac = dac;
this.pai = pai;
this.certificationDeclaration = certificationDeclaration;
this.firmwareInfo = firmwareInfo;
}

public byte[] getChallenge() {
return challenge;
}

public byte[] getNonce() {
return nonce;
}

public byte[] getElements() {
return elements;
}

public byte[] getElementsSignature() {
return elementsSignature;
}

public byte[] getDAC() {
return dac;
}

public byte[] getPAI() {
return pai;
}

public byte[] getCertificationDeclaration() {
return certificationDeclaration;
}

public byte[] getFirmwareInfo() {
return firmwareInfo;
}
}
33 changes: 33 additions & 0 deletions src/controller/java/src/chip/devicecontroller/CSRInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package chip.devicecontroller;

/** Represents information relating to NOC CSR. */
public final class CSRInfo {

private byte[] nonce;
private byte[] elements;
private byte[] elementsSignature;
private byte[] csr;

public CSRInfo(byte[] nonce, byte[] elements, byte[] elementsSignature, byte[] csr) {
this.nonce = nonce;
this.elements = elements;
this.elementsSignature = elementsSignature;
this.csr = csr;
}

public byte[] getNonce() {
return nonce;
}

public byte[] getElements() {
return elements;
}

public byte[] getElementsSignature() {
return elementsSignature;
}

public byte[] getCSR() {
return csr;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -349,27 +349,9 @@ public void onError(Throwable error) {
completionListener.onError(error);
}

public void onNOCChainGenerationNeeded(
byte[] csrElements,
byte[] csrNonce,
byte[] csrElementsSignature,
byte[] attestationChallenge,
byte[] attestationElements,
byte[] attestationNonce,
byte[] attestationElementsSignature,
byte[] dac,
byte[] pai) {
public void onNOCChainGenerationNeeded(CSRInfo csrInfo, AttestationInfo attestationInfo) {
if (nocChainIssuer != null) {
nocChainIssuer.onNOCChainGenerationNeeded(
csrElements,
csrNonce,
csrElementsSignature,
attestationChallenge,
attestationElements,
attestationNonce,
attestationElementsSignature,
dac,
pai);
nocChainIssuer.onNOCChainGenerationNeeded(csrInfo, attestationInfo);
}
}

Expand Down Expand Up @@ -739,16 +721,7 @@ public interface NOCChainIssuer {
*
* <p>All csr and attestation fields are provided to allow for custom attestestation checks.
*/
void onNOCChainGenerationNeeded(
byte[] csrElements,
byte[] csrNonce,
byte[] csrElementsSignature,
byte[] attestationChallenge,
byte[] attestationElements,
byte[] attestationNonce,
byte[] attestationElementsSignature,
byte[] dac,
byte[] pai);
void onNOCChainGenerationNeeded(CSRInfo csrInfo, AttestationInfo attestationInfo);
}

/**
Expand Down

0 comments on commit 1584108

Please sign in to comment.