Skip to content

Commit

Permalink
[Android] Implement generate certificiation API (#27159)
Browse files Browse the repository at this point in the history
* Implement Android Generate Cert API

* restyle

* Add comment
  • Loading branch information
joonhaengHeo authored and pull[bot] committed Nov 23, 2023
1 parent c3f3538 commit 4079427
Show file tree
Hide file tree
Showing 4 changed files with 461 additions and 15 deletions.
86 changes: 71 additions & 15 deletions src/controller/java/AndroidOperationalCredentialsIssuer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,27 +111,14 @@ CHIP_ERROR AndroidOperationalCredentialsIssuer::GenerateNOCChainAfterValidation(
// If root certificate not found in the storage, generate new root certificate.
else
{
ReturnErrorOnFailure(rcac_dn.AddAttribute_MatterRCACId(mIssuerId));

ChipLogProgress(Controller, "Generating RCAC");
chip::Credentials::X509CertRequestParams rcac_request = { 0, mNow, mNow + mValidity, rcac_dn, rcac_dn };
ReturnErrorOnFailure(NewRootX509Cert(rcac_request, mIssuer, rcac));

VerifyOrReturnError(CanCastTo<uint16_t>(rcac.size()), CHIP_ERROR_INTERNAL);
ReturnErrorOnFailure(GenerateRootCertificate(mIssuer, mIssuerId, Optional<FabricId>(), mNow, mNow + mValidity, rcac));
PERSISTENT_KEY_OP(fabricId, kOperationalCredentialsRootCertificateStorage, key,
ReturnErrorOnFailure(mStorage->SyncSetKeyValue(key, rcac.data(), static_cast<uint16_t>(rcac.size()))));
}

icac.reduce_size(0);

ChipDN noc_dn;
ReturnErrorOnFailure(noc_dn.AddAttribute_MatterFabricId(fabricId));
ReturnErrorOnFailure(noc_dn.AddAttribute_MatterNodeId(nodeId));
ReturnErrorOnFailure(noc_dn.AddCATs(cats));

ChipLogProgress(Controller, "Generating NOC");
chip::Credentials::X509CertRequestParams noc_request = { 1, mNow, mNow + mValidity, noc_dn, rcac_dn };
return NewNodeOperationalX509Cert(noc_request, pubkey, mIssuer, noc);
return GenerateOperationalCertificate(mIssuer, rcac, pubkey, fabricId, nodeId, cats, mNow, mNow + mValidity, noc);
}

CHIP_ERROR AndroidOperationalCredentialsIssuer::GenerateNOCChain(const ByteSpan & csrElements, const ByteSpan & csrNonce,
Expand Down Expand Up @@ -403,6 +390,75 @@ CHIP_ERROR AndroidOperationalCredentialsIssuer::LocalGenerateNOCChain(const Byte
return CHIP_NO_ERROR;
}

CHIP_ERROR AndroidOperationalCredentialsIssuer::GenerateRootCertificate(Crypto::P256Keypair & keypair, uint64_t issuerId,
Optional<FabricId> fabricId, uint32_t validityStart,
uint32_t validityEnd, MutableByteSpan & rcac)
{
ChipDN rcac_dn;
ReturnErrorOnFailure(rcac_dn.AddAttribute_MatterRCACId(issuerId));

if (fabricId.HasValue())
{
FabricId fabric = fabricId.Value();
VerifyOrReturnError(IsValidFabricId(fabric), CHIP_ERROR_INVALID_ARGUMENT);
ReturnErrorOnFailure(rcac_dn.AddAttribute_MatterFabricId(fabric));
}

ChipLogProgress(Controller, "Generating RCAC");
chip::Credentials::X509CertRequestParams rcac_request = { 0, validityStart, validityEnd, rcac_dn, rcac_dn };
ReturnErrorOnFailure(NewRootX509Cert(rcac_request, keypair, rcac));

VerifyOrReturnError(CanCastTo<uint16_t>(rcac.size()), CHIP_ERROR_INTERNAL);

return CHIP_NO_ERROR;
}

CHIP_ERROR AndroidOperationalCredentialsIssuer::GenerateIntermediateCertificate(
Crypto::P256Keypair & rootKeypair, const ByteSpan & rcac, const Crypto::P256PublicKey & intermediatePublicKey,
uint64_t issuerId, Optional<FabricId> fabricId, uint32_t validityStart, uint32_t validityEnd, MutableByteSpan & icac)
{
ChipDN rcac_dn;
ReturnErrorOnFailure(ExtractSubjectDNFromX509Cert(rcac, rcac_dn));

ChipDN icac_dn;
ReturnErrorOnFailure(icac_dn.AddAttribute_MatterICACId(issuerId));

if (fabricId.HasValue())
{
FabricId fabric = fabricId.Value();
VerifyOrReturnError(IsValidFabricId(fabric), CHIP_ERROR_INVALID_ARGUMENT);
ReturnErrorOnFailure(icac_dn.AddAttribute_MatterFabricId(fabric));
}

ChipLogProgress(Controller, "Generating ICAC");
chip::Credentials::X509CertRequestParams icac_request = { 0, validityStart, validityEnd, icac_dn, rcac_dn };
ReturnErrorOnFailure(NewICAX509Cert(icac_request, intermediatePublicKey, rootKeypair, icac));

VerifyOrReturnError(CanCastTo<uint16_t>(icac.size()), CHIP_ERROR_INTERNAL);

return CHIP_NO_ERROR;
}

CHIP_ERROR AndroidOperationalCredentialsIssuer::GenerateOperationalCertificate(Crypto::P256Keypair & signingKeypair,
const ByteSpan & signingCertificate,
const Crypto::P256PublicKey & operationalPublicKey,
FabricId fabricId, NodeId nodeId,
const chip::CATValues & cats, uint32_t validityStart,
uint32_t validityEnd, MutableByteSpan & noc)
{
ChipDN rcac_dn;
ReturnErrorOnFailure(ExtractSubjectDNFromX509Cert(signingCertificate, rcac_dn));

ChipDN noc_dn;
ReturnErrorOnFailure(noc_dn.AddAttribute_MatterFabricId(fabricId));
ReturnErrorOnFailure(noc_dn.AddAttribute_MatterNodeId(nodeId));
ReturnErrorOnFailure(noc_dn.AddCATs(cats));

ChipLogProgress(Controller, "Generating NOC");
chip::Credentials::X509CertRequestParams noc_request = { 1, validityStart, validityEnd, noc_dn, rcac_dn };
return NewNodeOperationalX509Cert(noc_request, operationalPublicKey, signingKeypair, noc);
}

CHIP_ERROR N2J_CSRInfo(JNIEnv * env, jbyteArray nonce, jbyteArray elements, jbyteArray csrElementsSignature, jbyteArray csr,
jobject & outCSRInfo)
{
Expand Down
33 changes: 33 additions & 0 deletions src/controller/java/AndroidOperationalCredentialsIssuer.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,39 @@ class DLL_EXPORT AndroidOperationalCredentialsIssuer : public OperationalCredent
const Crypto::P256PublicKey & pubkey, MutableByteSpan & rcac, MutableByteSpan & icac,
MutableByteSpan & noc);

/**
* Create a root (self-signed) X.509 DER encoded certificate that has the
* right fields to be a valid Matter root certificate.
*/
static CHIP_ERROR GenerateRootCertificate(Crypto::P256Keypair & keypair, uint64_t issuerId, Optional<FabricId> fabricId,
uint32_t validityStart, uint32_t validityEnd, MutableByteSpan & rcac);

/**
* Create an intermediate X.509 DER encoded certificate that has the
* right fields to be a valid Matter intermediate certificate.
*/
static CHIP_ERROR GenerateIntermediateCertificate(Crypto::P256Keypair & rootKeypair, const ByteSpan & rcac,
const Crypto::P256PublicKey & intermediatePublicKey, uint64_t issuerId,
Optional<FabricId> fabricId, uint32_t validityStart, uint32_t validityEnd,
MutableByteSpan & icac);

/**
* Create an X.509 DER encoded certificate that has the
* right fields to be a valid Matter operational certificate.
*
* signingKeypair and signingCertificate are the root or intermediate that is
* signing the operational certificate.
*
* cats may be null to indicate no CASE Authenticated Tags
* should be used. If cats is not null, it must contain at most
* 3 numbers, which are expected to be 32-bit unsigned Case Authenticated Tag
* values.
*/
static CHIP_ERROR GenerateOperationalCertificate(Crypto::P256Keypair & signingKeypair, const ByteSpan & signingCertificate,
const Crypto::P256PublicKey & operationalPublicKey, FabricId fabricId,
NodeId nodeId, const chip::CATValues & cats, uint32_t validityStart,
uint32_t validityEnd, MutableByteSpan & noc);

private:
CHIP_ERROR CallbackGenerateNOCChain(const ByteSpan & csrElements, const ByteSpan & csrNonce,
const ByteSpan & attestationSignature, const ByteSpan & attestationChallenge,
Expand Down
Loading

0 comments on commit 4079427

Please sign in to comment.