Skip to content
Open
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
13 changes: 13 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,16 @@ updates:
interval: "weekly"
cooldown:
default-days: 7
- package-ecosystem: "cargo"
directory: "/native"
schedule:
interval: "weekly"
day: "monday"
open-pull-requests-limit: 10
groups:
rust-development-dependencies:
dependency-type: "development"
patterns: ["*"]

# Native vcpkg/OpenSSL baseline updates are reviewed manually because they
# change the cryptographic/runtime trusted computing base.
74 changes: 74 additions & 0 deletions .github/workflows/native-primitives.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: Native Primitives Windows CI

on:
push:
branches: [dev]
paths:
- "native/**"
- ".github/workflows/native-primitives.yml"
pull_request:
branches: [dev]
paths:
- "native/**"
- ".github/workflows/native-primitives.yml"
workflow_dispatch:

permissions:
contents: read

defaults:
run:
shell: pwsh
working-directory: native

jobs:
test:
runs-on: windows-2022
timeout-minutes: 60

steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

- uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772
with:
toolchain: 1.97.1-x86_64-pc-windows-msvc
components: clippy, rustfmt

- name: Fetch pinned vcpkg baseline
run: |
$manifest = Get-Content vcpkg.json | ConvertFrom-Json
$baseline = $manifest.'builtin-baseline'
git -C $env:VCPKG_INSTALLATION_ROOT fetch --refetch --depth=1 origin $baseline
if ($LASTEXITCODE -ne 0) { throw "Fetching the native vcpkg baseline failed." }

- name: Configure native test harness
run: |
cmake -S . -B build -G "Visual Studio 17 2022" -A x64 `
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_INSTALLATION_ROOT\scripts\buildsystems\vcpkg.cmake" `
-DVCPKG_TARGET_TRIPLET=x64-windows
if ($LASTEXITCODE -ne 0) { throw "Configuring the native test harness failed." }

- name: Run complete matrix
run: .\scripts\test.ps1

dependency-policy:
runs-on: windows-2025
timeout-minutes: 30

steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

- uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772
with:
toolchain: 1.97.1-x86_64-pc-windows-msvc

- uses: taiki-e/install-action@a2a5f6e99e1a31540baa0468acfa302cff0f359f # v2
with:
tool: cargo-audit@0.22.2,cargo-deny@0.20.2
fallback: none

- name: Audit Rust dependencies
run: cargo audit

- name: Enforce dependency policy
run: cargo deny check
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@ You can follow the latest updates and plans for MSAL Python in the [Roadmap](htt

## Samples and Documentation

The repository also hosts the pre-release
[Microsoft.Identity.Native.Primitives](https://github.com/AzureAD/microsoft-authentication-library-for-python/tree/dev/native)
project under `native/`. It provides Windows CNG/OpenSSL and bounded mTLS
transport primitives through a C ABI. It builds and tests independently and
is not integrated into the `msal` Python package or its PyPI distributions.

MSAL Python supports multiple [application types and authentication scenarios](https://docs.microsoft.com/azure/active-directory/develop/authentication-flows-app-scenarios).
The generic documents on
[Auth Scenarios](https://docs.microsoft.com/azure/active-directory/develop/authentication-scenarios)
Expand Down
24 changes: 24 additions & 0 deletions native/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.{rs,c,h}]
indent_style = space
indent_size = 4

[*.{md,yml,yaml,json,toml}]
indent_style = space
indent_size = 2

[*.ps1]
end_of_line = crlf
indent_style = space
indent_size = 4

[CMakeLists.txt]
indent_style = space
indent_size = 4
24 changes: 24 additions & 0 deletions native/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
* text=auto

*.rs text eol=lf
*.c text eol=lf
*.h text eol=lf
*.md text eol=lf
*.yml text eol=lf
*.yaml text eol=lf
*.json text eol=lf
*.toml text eol=lf
CMakeLists.txt text eol=lf

*.ps1 text eol=crlf
*.bat text eol=crlf
*.cmd text eol=crlf

*.dll binary
*.exe binary
*.lib binary
*.pdb binary
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
10 changes: 10 additions & 0 deletions native/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/build/
/Testing/

/artifacts/
/target/

*.log
*.pdb
*.user
*.suo
107 changes: 107 additions & 0 deletions native/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Microsoft.Identity.Native.Primitives instructions

These instructions apply to the standalone native project under `native/`,
not the `msal/` Python implementation. Python package behavior and packaging
must remain independent unless a separate integration change is approved.

## Review priorities

- Review bugs, security issues, ownership/lifetime errors, and ABI contract
violations before style.
- Comment only on concrete, actionable issues introduced by the change.
- Prefer no review comment over a speculative security finding.
- Require regression tests for fixes and negative/adversarial tests for
security-sensitive changes where practical.

## Native project boundary

- Production implementation is Rust.
- Never add production Python, Node.js, or C++ implementations.
- C is allowed only for external ABI/conformance tests and minimal native
examples.
- Do not add MSAL, token acquisition, token caching, Managed Identity
orchestration, Azure Identity, or Azure SDK authentication behavior.
- Language-specific integrations are outside this native project's scope.

## Key and cryptographic invariants

- Never suggest exporting a private key as a workaround.
- Preserve opaque, non-exportable key semantics.
- Private-key bytes and private RSA parameters must not leave the CNG/KSP
boundary.
- Treat CNG key creation, key usage, export policy, KSP selection,
KeyGuard/VBS, and attestation changes as security-sensitive.
- Do not claim hardware/VBS/attestation guarantees unless the implementation
verifies the required policy and evidence.
- Treat algorithm, digest, padding, PSS salt, and certificate/key-binding
changes as security-sensitive.

## Unsafe Rust, FFI, and ownership

- Treat all unsafe and FFI code as security-critical.
- Every unsafe block requires a precise `SAFETY:` comment describing pointer,
lifetime, aliasing, threading, and ownership invariants as applicable.
- Check `Send` and `Sync` assumptions against the underlying native API.
- Check native handle ownership, partial initialization, cancellation, and
every error-path cleanup.
- Keep allocation/free pairing explicit and within the same allocator family.
- Document caller-owned versus callee-owned memory.
- Bound lengths before pointer traversal, string scanning, or allocation.
- Do not add infallible allocation to provider callbacks where allocation
failure is expected to become a structured native error.
- Preserve panic containment across exported ABI and OpenSSL callback
boundaries.

## Native ABI

- Public ABI changes require compatibility and versioning review.
- Check structure size, order, alignment, field types, enum numeric values,
calling convention, ownership, allocation/free rules, nullability, and field
interpretation.
- Update the public header, Rust layouts, C conformance tests, documentation,
changelog, exported-symbol checks, and
`MICROSOFT_IDENTITY_NATIVE_ABI_VERSION` when required.
- Do not add compatibility aliases or silently reinterpret existing fields
without an approved design.

## TLS, networking, and HTTP

- Treat TLS trust, SNI, certificate-chain, hostname, and IP verification
changes as security-sensitive.
- Do not weaken peer verification or add success-shaped fallbacks.
- Treat DNS cancellation, socket inheritance, deadlines, and concurrency as
native ownership/security concerns.
- Treat HTTP parsing and framing changes as security-sensitive.
- Do not add arbitrary redirects, proxy selection, Host-header overrides,
transfer encoding, duplicate framing, or ambiguous message lengths without
an approved design.
- Preserve bounded requests, responses, headers, and total I/O deadlines.
- Do not log tokens, private keys, credentials, secret bodies, secret
responses, or sensitive key identifiers.

## Intentional patterns not to "fix"

- Internal crate names such as `cng-core`, `cng-provider`, and `mtls-bridge`
intentionally describe the current implementation.
- C files under `tests/native` and `examples/c` intentionally exercise the
external compiler/ABI boundary; they are not production implementations.
- The caller supplies an already-acquired certificate-bound token; token
acquisition and token semantic validation are outside this native project.
- The raw ABI accepts a caller-selected destination; authorization belongs in
a trusted higher-level host.
- The library does not isolate mutually untrusted callers in one process.
- Exact `Content-Length` framing, no redirects, no proxy selection, no
transfer encoding, and strict header validation are intentional.
- Reserving the bounded response capacity before reading plaintext is an
intentional zeroization tradeoff; optimize it only with an approved design
that preserves plaintext cleanup guarantees.
- The explicit provider module path and private OpenSSL library context are
intentional loading and isolation choices.

## Validation

- Follow `CONTRIBUTING.md`, `docs/security-review.md`, and
`docs/versioning.md`.
- Run the complete Debug and Release Rust/native matrix.
- Keep formatting, Clippy, dependency audit, and dependency policy checks
clean.
99 changes: 99 additions & 0 deletions native/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Changelog

All user-visible changes and security fixes must be recorded in this file.
This project follows [Semantic Versioning](docs/versioning.md) for its product
version and versions its native ABI separately.

## Unreleased

### Added

- Microsoft contribution, code-of-conduct, support, maintainer, ownership, and
release-governance documentation.
- Structured bug, feature, design-proposal, documentation, and pull-request
templates.
- Native ABI versioning, development, release, and security-review guides.
- Cargo and GitHub Actions Dependabot monitoring and repository-specific
Copilot instructions.

### Changed

- Moved the standalone native project under `native/` in the MSAL Python
repository, preserving the Rust implementation, native ABI, and lockfile.
- Expressed workspace dependency requirements as explicit compatible ranges
and documented reviewed dependency updates.
- Scoped native CI and Dependabot to the new location without integrating
native sources or binaries into the Python package.
- Adopted Microsoft Security Response Center vulnerability reporting and
Microsoft repository legal/trademark language.

### Fixed

- Preserve available public material when OpenSSL duplicates a public-only RSA
key with a selection that also includes unavailable private material.
- Resolve the example's provider DLL path before passing it to the ABI, which
requires absolute paths.
- Configure the pinned OpenSSL installation and native test harness before the
first quick-start build command.
- Reject digest updates that conflict with retained explicit PSS MGF1 state
before changing the signature context.
- Include IPv6 Host brackets in HTTP header/request limits and the reservation
made before copying authorization or body plaintext.
- Wipe copied request paths, STORE URIs, header values, and bodies on validation
failures by retaining them in zeroizing storage immediately after copying.
- Accept valid HTTP response token field names and surrounding Content-Length
whitespace without permitting duplicate or ambiguous framing.
- Permit secure server-initiated TLS 1.2 renegotiation for delayed client
authentication without enabling unsafe legacy renegotiation or resetting the
total I/O deadline.
- Retain the key, digest, padding, MGF1, and salt settings during null-key
signing-context reuse while resetting message hashing.
- Bound RSA modulus and exponent encodings before BIGNUM conversion, retaining
mathematical limits and supported native-word padding.
- Wipe NUL-terminated STORE URI copies, decoded identifiers, STORE descriptions,
and temporary UTF-16 provider/key names on success and failure paths.

### Security

- Documented mandatory review areas and evidence for unsafe Rust, FFI, CNG,
OpenSSL provider, TLS, HTTP framing, secret handling, and ABI changes.

### Breaking

## 0.2.0 - Pre-release

### Added

- Rust OpenSSL 3 provider for persisted Windows CNG RSA signing keys.
- Opaque CNG key loading through a strict `cng://` STORE URI.
- Bounded Rust TLS/HTTP transport for certificate-bound identity requests.
- Language-neutral C ABI and external C conformance tests.
- Debug and Release Windows validation, dependency auditing, and security
documentation.

### Changed

- Renamed the pre-release project and public native surface to
Microsoft.Identity.Native.Primitives.
- Aligned the Rust crates, CMake/vcpkg metadata, provider identity, public DLL
names, header, exported functions, and public ABI prefix at version 0.2.0.
- Clarified that token acquisition, MSAL, Azure SDK integration, and
language-specific SDKs are outside the repository scope.

### Fixed

- Hardened FFI string ownership, native allocation failures, signature state
updates, CNG key-policy checks, provider loading, DNS cancellation, socket
inheritance, TLS IP verification, HTTP framing, and plaintext zeroization.

### Security

- Enforced non-exportable private-key policy and bounded native inputs and
outputs.
- Added explicit security-boundary, deployment, release, and dependency-policy
requirements.

### Breaking

- Replaced the former pre-release product and ABI names without compatibility
aliases. No stable public release preceded this rename.
Loading
Loading