Skip to content

Generic remote attestation implementation#148

Open
Akretsch wants to merge 4 commits into
mainfrom
feat_generic_RAT_impl
Open

Generic remote attestation implementation#148
Akretsch wants to merge 4 commits into
mainfrom
feat_generic_RAT_impl

Conversation

@Akretsch

Copy link
Copy Markdown
Collaborator

Description

Implement remote attestation message flow over CMP as far as specified and stable in

@Akretsch
Akretsch force-pushed the feat_generic_RAT_impl branch 2 times, most recently from da71f21 to 86b8402 Compare October 30, 2025 10:22
@Akretsch Akretsch changed the title Generic remote attestation imlementation Generic remote attestation implementation Oct 30, 2025
@Akretsch
Akretsch force-pushed the feat_generic_RAT_impl branch 3 times, most recently from 0814d99 to 0e2e343 Compare October 30, 2025 16:12
@Akretsch
Akretsch force-pushed the feat_generic_RAT_impl branch 2 times, most recently from bbab075 to 812c16d Compare November 4, 2025 11:27
@sonarqubecloud

sonarqubecloud Bot commented Nov 6, 2025

Copy link
Copy Markdown

Comment on lines +946 to +948
EvidenceBundle evidenceBundle = EvidenceBundle.getInstance(evidenceItav.getParsedValue());
EvidenceStatement[] evidences = evidenceBundle.getEvidences();
AttestationResult[] attestationResults = new AttestationResult[evidences.length];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be feasible for an attacker to craft a message that makes it look like evidences.length is a very large number?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but ASN.1 is unlimited too.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO consider writing some tests to check if BouncyCastle itself will take care of such malicious payloads.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the worst thing that could happen here is a OutOfMemoryError exception, right?
If so, at which level would it be caught and handled?

NonceRequest aktRequest = nonceRequests[i];
NonceResponseRet ret = verifyAdapter.generateNonce(
msg.getHeader().getTransactionID().getOctets(),
ifNotNull(aktRequest.getLen(), ASN1Integer::getValue),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to set an upper bound to the size of the nonce we generate?

ASN1 Integers are essentially unbounded, so a specially crafted request could potentially exhaust our memory.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the nonce must be PQ-safe it could become bigger :-)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ralienpp is right, an attacker could easily provoke an out-of-memory condition and thus do a DoS attack.
Clearly the size of the nonces should be limited to a sensible value.

@ralienpp

Copy link
Copy Markdown
Collaborator

Additional recommended reading material: RFC 9334, esp. section 5.2 background check model.

@Akretsch
Akretsch force-pushed the feat_generic_RAT_impl branch 2 times, most recently from ce8b445 to 2cef504 Compare January 28, 2026 07:27
@sonarqubecloud

Copy link
Copy Markdown

@DDvO DDvO left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice first draft.

At appropriate time, some updates and improvements will be due.

Comment on lines +425 to +430
NonceRequest nonceRequest = new NonceRequest(
attestationContext.getNonceRequestLen(),
attestationContext.getNonceRequestType(),
attestationContext.getNonceRequestHint(),
attestationContext.getNonceRequestVendorextension());
NonceRequestValue nonceRequestValue = new NonceRequestValue(new NonceRequest[] {nonceRequest});

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So here you generate a request for a single nonce.
Please add at least a TODO that this should be generalized to request for multiple nonces.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs change of
ClientAttestationContext ClientContext:getAttestationContext()
replace with
Collection <ClientAttestationContext> ClientContext:getAttestationContext()

final InfoTypeAndValue[] itav = content.toInfoTypeAndValueArray();
if (itav != null) {
for (final InfoTypeAndValue aktitav : itav) {
if (AttestationObjectIdentifiers.id_it_NonceResponse.equals(aktitav.getInfoType())) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Otherwise should throw an error

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its about robustness -> Ignore, what you are unable to handle.

final GenRepContent content = (GenRepContent) ratNonceResponseBody.getContent();
final InfoTypeAndValue[] itav = content.toInfoTypeAndValueArray();
if (itav != null) {
for (final InfoTypeAndValue aktitav : itav) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should throw an error if not getting exactly one ITAV

return null;
}
final NonceResponseValue ratNonce = NonceResponseValue.getInstance(infoValue);
NonceResponse[] nonceResponses = ratNonce.getNonceResponse();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should check that the number of nonces obtains equals the number requested, which so far is always 1.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Robustness.

Comment on lines +946 to +948
EvidenceBundle evidenceBundle = EvidenceBundle.getInstance(evidenceItav.getParsedValue());
EvidenceStatement[] evidences = evidenceBundle.getEvidences();
AttestationResult[] attestationResults = new AttestationResult[evidences.length];

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the worst thing that could happen here is a OutOfMemoryError exception, right?
If so, at which level would it be caught and handled?

* @param evidence evidence provided by EE as DER encoded {@link EvidenceStatement}
* @return verification result as DER encoded {@link AttestationResult}
*/
byte[] processRatVerification(byte[] transactionId, byte[] evidence);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the verifier should also get the certs from the evicence/attestation bundle.

Comment on lines +29 to +33
* AttestationResultBundle ::= SEQUENCE {
* results SEQUENCE SIZE (1..MAX) OF AttestationResult,
* certs SEQUENCE SIZE (1..MAX) OF CertificateChoices OPTIONAL,
* -- CertificateChoices MUST only contain certificate or other,
* -- see Section 10.2.2 of [RFC5652]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason, this structure has disappeared in https://datatracker.ietf.org/doc/html/draft-ietf-lamps-csr-attestation-22

}
final NonceResponseValue ratNonce = NonceResponseValue.getInstance(infoValue);
NonceResponse[] nonceResponses = ratNonce.getNonceResponse();
EvidenceStatement[] evidenceStatements = new EvidenceStatement[nonceResponses.length];

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the number of evidence statements always follow the number of nonce responses?
Please add at least a respective TODO to generalize this.

return null;
}
EvidenceBundle evidenceBundle = EvidenceBundle.getInstance(evidenceItav.getParsedValue());
EvidenceStatement[] evidences = evidenceBundle.getEvidences();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the number of evidence/attestation statements follow the number of nonce requests/responses?
Please add at least a respective TODO to possibly check for this.

NonceRequest aktRequest = nonceRequests[i];
NonceResponseRet ret = verifyAdapter.generateNonce(
msg.getHeader().getTransactionID().getOctets(),
ifNotNull(aktRequest.getLen(), ASN1Integer::getValue),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ralienpp is right, an attacker could easily provoke an out-of-memory condition and thus do a DoS attack.
Clearly the size of the nonces should be limited to a sensible value.

Comment on lines +187 to +191
PKIMessage buildFurtherRequest(
final PKIMessage formerResponse,
final PKIBody requestBody,
final boolean withImplicitConfirm,
final int pvno)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it is simpler to keep at least part of these argument in some state fields and take them from there?
I suppose one could even avoid distinguishing between methods building initial vs. further requests.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Holding (transaction) states global and non final makes it hard to implement concurrency and slows down the VM. So I would keep everything local and final as much as possible.

* Siemens proprietary extension to carry additional data
* @return additional data or <code>null</code>
*/
default byte[] getNonceRequestVendorextension() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider getNonceRequestVendorExtension (camelCase) instead of getNonceRequestVendorextension.

@@ -409,6 +418,51 @@ private boolean grantsImplicitConfirm(final PKIMessage msg) {
public EnrollmentResult invokeEnrollment() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is around 200 lines of code with a high complexity.
I recommend refactoring it into smaller methods to improve readability and simplify unit testing. Helps future maintenance.

* Siemens proprietary extension to carry additional data
* @return additional data or <code>null</code>
*/
default byte[] getVendorextension() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommended to rename getVendorextension to getVendorExtension

BigInteger len,
String type,
String hint,
byte[] vendorextension,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to vendorExtension

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants