Skip to content

[C] Managed provider: validate stored chains; atomic owner-only writes - #410

Merged
Ewerton Scaboro da Silva (ewertons) merged 7 commits into
mainfrom
feature/c-managed-provider-storage
Oct 11, 2026
Merged

Ewerton Scaboro da Silva (ewertons) merged 7 commits into
mainfrom
feature/c-managed-provider-storage

Conversation

@ewertons

Copy link
Copy Markdown
Contributor

The managed certificate provider stores only chains for its own key and writes its files atomically, readable only by the current user.

Store (store_issued_certificate)

  • Refused (AZ_IOT_ERR_INVALID_ARG) unless every entry is a non-empty, parseable PEM certificate, the parsed count matches the issued count, the leaf certifies the operational key, and the PEM chain is at most 64 KiB. Each entry is sized before it is decoded.
  • A refused or failed store keeps the previous chain.

Init

  • A persisted chain is used only if it passes the same checks; the read is bounded to 64 KiB.

Writes (key and chain)

  • Uniquely named, exclusively created file next to the destination: mkstemp + fchmod(0600) on POSIX, owner-only protected DACL (owner, SYSTEM) on Windows. Flushed, then renamed over the destination.
  • A failed write leaves the destination untouched. A symlink at the destination is replaced, not followed. The mode of an existing key file is not changed.

Tests: unit tests for each behavior. Permission, mode and symlink tests are POSIX only; a Windows test checks the DACL.

Validation (Linux, gcc): all unit suites pass, the provider suite also under ASan/UBSan; clang-tidy 18.1.8 clean on the provider; clang-format 18 and repo lint scripts pass. The Windows code was syntax-checked with MinGW only.

- store_issued_certificate() refuses a chain unless every entry is a
  non-empty, parseable PEM certificate, the count matches, the leaf
  certifies the operational key, and the PEM chain is at most 64 KiB.
  Each entry is sized before it is decoded. A refused store keeps the
  previous chain.
- init() uses a persisted chain only if it passes the same checks; the
  read is bounded to 64 KiB.
- The key and chain are written to a uniquely named, exclusively created
  file next to the destination (0600 on POSIX, owner-only DACL on
  Windows), flushed, then renamed over it. A failed write leaves the
  destination untouched; a symlink there is replaced, not followed. The
  mode of an existing key file is not changed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Windows consumers lack the provider’s required system-library linkage, and malformed base64 returns the wrong result code.

3 open findings
What changed in this PR

Hardens managed certificate persistence through chain validation, bounded reads, and atomic owner-only file replacement.

Changes:

  • Validates certificate chains against the operational key and 64 KiB limit.
  • Adds secure atomic writes for POSIX and Windows.
  • Expands platform-specific tests and coverage documentation.
File Description
c/​adapters/​cert_openssl/​az_iot_certificate_provider_managed.c Implements validation and secure atomic persistence.
c/​adapters/​cert_openssl/​az_iot_certificate_provider_managed.h Documents validation and file protections.
c/​tests/​unit/​certificate_provider_managed_test.c Adds validation, permissions, DACL, and symlink tests.
c/​tests/​CMakeLists.txt Adds Windows security-library linkage for tests.
c/​docs/​eng/​test-coverage.md Records expanded managed-provider coverage.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread c/tests/CMakeLists.txt
Comment thread c/adapters/cert_openssl/az_iot_certificate_provider_managed.c
Comment thread c/adapters/cert_openssl/az_iot_certificate_provider_managed.c Outdated
…e and rename failures

- The provider target links advapi32 on Windows, so every consumer gets it.
- An issued entry that is not base64 is AZ_IOT_ERR_INVALID_ARG, not
  AZ_IOT_ERR_INTERNAL; allocation and write failures keep their codes.
- Windows: GetTickCount64 for the temp-name seed; a NULL handle is a failure.
- POSIX tests: a failed write or rename keeps the destination and leaves
  no temporary file.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The managed provider’s required vtable ABI-version assertion was removed without replacement.

3 open findings
1 resolved since last review

🧠 Review effort: Balanced

Comment thread c/tests/unit/certificate_provider_managed_test.c
Copilot AI balanced review requested due to automatic review settings October 11, 2026 07:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Strict certificate validation still accepts DER certificates with trailing decoded data, and one documented key-file guarantee is inaccurate.

4 open findings
1 resolved since last review

🧠 Review effort: Balanced

Comment thread c/adapters/cert_openssl/az_iot_certificate_provider_managed.c Outdated
Comment thread c/adapters/cert_openssl/az_iot_certificate_provider_managed.h Outdated
…ate; key-file doc

- A certificate followed by more bytes in the same block is refused at
  store and not used at init.
- The operational key option documents that only a key that loads is left
  as is; a missing, unreadable or malformed file is replaced.
Copilot AI balanced review requested due to automatic review settings October 11, 2026 07:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comment thread c/adapters/cert_openssl/az_iot_certificate_provider_managed.c
Copilot AI balanced review requested due to automatic review settings October 11, 2026 07:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Security-sensitive cross-platform filesystem behavior, particularly the Windows path without native runtime validation, warrants final human review.

3 open findings

🧠 Review effort: Balanced

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Approved

@ewertons
Ewerton Scaboro da Silva (ewertons) merged commit 5919c2e into main Oct 11, 2026
57 checks passed
@ewertons
Ewerton Scaboro da Silva (ewertons) deleted the feature/c-managed-provider-storage branch October 11, 2026 15:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants