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

[Android] Implement generate certificiation API #27159

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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