Repository navigation
ADR AMT22 support
Date: 2026-10-12
AMT 22 (Nova Lake) enforces CSME crypto-hardening that disallows use of AES-128, SHA-256, RSA-2K and ECC-256 which result into the following key requirements applicable for DMT.
| # | Requirement | Bearing |
|---|---|---|
| 1 | Remove TLS_RSA_WITH_AES_128_GCM_SHA256 / TLS_AES_128_GCM_SHA256
|
Constrains what the device offers; MPS cipher list is compliance only. |
| 2 | Do not accept leaf certificates with RSA-2K or ECC-256 keys in TLS handshake and all WSMAN certificate configuration APIs | Primary driver. Two clauses: the device's own TLS leaf, and the MPS server certificate the device validates on CIRA. |
| 3 | Block TLS RSA-2K Key Pair generation. WSMAN Key Generation API | Removes the alternative to ECC-384. |
| 4 |
HostBasedSetupServiceSetup() - hash the certificate with SHA-384, and change SigningAlgorithm to RSA SHA-384 or ECC-384
|
Sets the provisioning-certificate digest floor and the SigningAlgorithm value RPS must send (3). |
| 5 |
HBProvisioningValidateSignature() - validate the nonce signature with SHA-384
|
Sets the digest RPS signs the provisioning nonce pair with - SHA-384 on AMT 22, which is the firmware half of requirement 4's SigningAlgorithm change. Together they fix SigningAlgorithm=3 as the only admissible value RPS can send on AMT 22. |
| 6 |
HostBasedSetupServiceUpgradeToAdmin() - remove SHA-256 from TlsProvisionCertificateLeafTestCommon() and TlsProvisionVerifyLeafCertificate()
|
The ACM-upgrade path re-runs leaf validation, so the SHA-384 leaf requirement is enforced a second time at UpgradeClientToAdmin, not only at credential bind. |
| 7 |
HostBasedSetupServiceAddNextCertInChain() - TlsUtilsVerifyGeneralCert() checks key size and signing algorithm
|
Each certificate of the provisioning chain is validated as it is uploaded, so an RSA-2K or SHA-256 certificate anywhere in the chain - not just the leaf - is rejected. |
| 8 |
CFG_StartConfigurationHBased() (HECI API) - remove CERT_HASH_ALGORITHM_SHA256
|
The local HECI configuration entry point drops SHA-256 as well, so rpc-go's local path cannot be used to work around the WSMAN-side rules. |
| 9 |
TlsProvisionVerifyLeafCertificate() - remove SHA-256 |
Primary driver. Sets the device leaf signature digest. |
Independently of the rules above, AMT 22 on Nova Lake no longer presents a firmware TLS certificate issued under Intel's OnDie CA (ODCA). It presents a DICE chain instead - a device-identity hierarchy rooted in the chipset, whose lower levels are created on the part itself and whose serials are scoped to the firmware version. RPS validates the firmware's certificate when it opens the activation tunnel, so it must hold a trust anchor for this new hierarchy; otherwise every AMT 22 device either fails verification or is accepted unverified.
The CSME firmware reports the hardening through the HECI STATE_INDEPENDENCE_IsChangeToAMTEnabled response which packs
a WeakAlgorithmsRemoved flag into bit 4 of its single response byte which is valid only when the
IsNewInterfaceVersion bit (bit 7) is set.
typedef struct {
UINT8 Enabled : 1;
UINT8 CurrentOperationalState : 1;
UINT8 Reserved : 2;
UINT8 WeakAlgorithmsRemoved : 1; // bit 4
UINT8 CIRAPeriodicTimerFix : 1;
UINT8 TlsOnLocalPorts : 1;
UINT8 IsNewInterfaceVersion : 1; // bit 7
} STATE_INDEPENDENCE_IS_CHANGE_ENABLED_RESPONSE;Here's how the relevant bits appear across different AMT generations:
| Platform | RawResponse | bit 4 WeakAlgorithmsRemoved
|
bit 7 IsNewInterfaceVersion
|
|---|---|---|---|
| AMT 11 | 0x01 |
0 | 0 |
| AMT 16 | 0x02 |
0 | 0 |
| AMT 18 | 0xA2 |
0 | 1 |
| AMT 20 | 0xE2 |
0 | 1 |
| AMT 21 | 0xE2 |
0 | 1 |
| AMT 22 | 0xF2 |
1 | 1 |
Bit 4 is set on exactly the generation that has dropped AES-128, SHA-256, RSA-2K and ECC-256 - the requirement set in the table above. It is a capability report, not a version number: the hardening can reach an older platform through a firmware update, and when it does the AMT version still reads 11 or 16 while this bit is the only thing that has changed. That makes the bit, and not the version string, the correct input to the crypto policy - see D1.
One capability is reported only indirectly: whether host-based setup can verify a SHA-384 nonce signature. There
is no bit for it, and the generations do not agree - AMT 20.0.5 returns PT_STATUS_INVALID_PT_MODE for
SigningAlgorithm = 3, where AMT 21 and AMT 22 accept it. Bit 4 is still sufficient to decide, because the decision
only ever needs to be made in one direction: firmware that reports the hardening requires SHA-384 and therefore
verifies it, and firmware that does not report it accepts a SHA-256 nonce signature on every generation from AMT 11
upward. The nonce digest is independent of the digest the provisioning certificate itself was signed with, so nothing is
lost by signing the nonce with SHA-256 on unhardened firmware.
Where this leaves the implementation. Taken together, six things must hold for an AMT 22 device to activate and stay manageable:
- ECC-384 device TLS leaf (2, 3),
- SHA-384 on that leaf's signature (6, 9),
- SHA-384 provisioning chain validated certificate by certificate (4, 7, 8),
-
SHA-384 nonce signature labelled
SigningAlgorithm=3(4, 5), - RSA-3072 MPS server certificate on the CIRA connection (2, handshake clause), and
- A trust anchor for the Intel DICE hierarchy, so the firmware's own certificate chain can be verified (§1.2 - not a rule from the table above).
Note: 1-4 and 6 are RPS; 5 is MPS.
flowchart LR
subgraph device["Managed device"]
CSME["CSME / AMT firmware<br/>holds the device key and the DICE chain"]
RPC["rpc-go<br/>host agent"]
end
subgraph cloud["Management stack"]
RPS["RPS<br/>activation and TLS configuration"]
MPS["MPS<br/>CIRA endpoint"]
DB[("DB / Vault<br/>profiles, domain PFX, MPS certificates")]
end
MPS <-- "0 - at startup: root and leaf<br/>(RSA-3072 leaf for req 5)" --> DB
CSME -- "1 - HECI: WeakAlgorithmsRemoved bit 4" --> RPC
RPC -- "2 - activation payload carries the capability" --> RPS
DB -- "3 - profile, SHA-384 provisioning PFX,<br/>DICE anchor (req 6)" --> RPS
RPS -- "4 - WSMAN over the rpc-go tunnel:<br/>ECC-384 key pair (req 1), SHA-384 leaf (req 2),<br/>chain upload (req 3), SigningAlgorithm 3 (req 4)" --> CSME
RPS -- "5 - CIRA profile and MPS root" --> CSME
CSME <-- "6 - CIRA TLS: device validates the<br/>RSA-3072 MPS leaf (req 5)" --> MPS
Note: The leading number on each arrow is the order things happen;
req Npoints back to the six requirements listed above. Step 0 runs once at MPS startup, long before any device activates. Everything the firmware will accept follows from the one capability reported at step 1 - nothing in the stack infers it from the AMT version.
Goals.
- AMT 22 activates; The CIRA tunnel coming up - not activation reaching
PROVISIONED. - AMT 11-21 are unaffected on paths that already work;
A four-field value object resolved once per activation and threaded through provisioning. A new capability is a new tuple, not a new branch.
export interface AMTCertificatePolicy {
hashAlgorithm: 'sha256' | 'sha384' // digest of the TLS leaf RPS signs
rsaKeySize: 2048 | 3072 // the RPS-side root/CA key
deviceKeyPair: DeviceKeyPairParameters // what the FIRMWARE generates
requiresSha384ProvisioningCert: boolean // FW refuses a sha256 chain
}The key is the firmware's own report. The AMT version is not an input at all. rpc-go reads bit 4 of the
change-enabled response (§1.3) during activation and ships it in the activation payload as weakAlgorithmsRemoved; RPS
selects the tuple from that and from nothing else. There is no version threshold anywhere in the policy, and no version
string to parse.
weakAlgorithmsRemoved |
Tuple | hashAlgorithm |
rsaKeySize |
deviceKeyPair |
requiresSha384ProvisioningCert |
|---|---|---|---|---|---|
true |
HARDENED_CRYPTO_POLICY |
sha384 |
3072 |
{ keyAlgorithm: 1, keyLength: 384 } |
true |
false or absent
|
LEGACY_CRYPTO_POLICY |
sha256 |
2048 |
{ keyAlgorithm: 0, keyLength: 2048 } |
false |
Note: A missing field means the legacy policy. An activation payload with no
weakAlgorithmsRemovedis treated asfalse, not as "unknown, guess from the version" - that inference is exactly what this decision removes. The consequence is a rollout order: rpc-go ships before, or with, RPS. An AMT 22 device on an older agent reports nothing, takes the legacy policy, and fails thePut AMT_TLSCredentialContextbind withHTTP 500 / AMT-STATUS 1. Both logs name the cause - the device did not report the capability - but the firmware's response does not. An accepted deployment constraint, not a defect.
The same weakAlgorithmsRemoved report that selects the policy (D1) also decides whether a SHA-256 provisioning
certificate is usable. Firmware that reports the hardening will reject one, so RPS rejects it first and sends nothing:
if (policy.requiresSha384ProvisioningCert && certHashAlgorithm !== 'sha384') return falseThe check sits in createSignedString(), which runs on both paths that present a provisioning certificate -
AdminSetup (direct ACM activation) and UpgradeClientToAdmin (CCM to ACM). It is keyed on the firmware report,
not on a version, so it applies to any generation: a device is refused exactly when its own firmware says it would
refuse.
The gate is one-directional. A SHA-384 certificate is never rejected, because every generation tested accepts one (A2).
Improvement - reject earlier. The gate currently fires at signing time, which is the last moment before the
certificate is used rather than the first moment it could be judged. Both inputs are available much earlier: the
firmware report arrives in the first activation message, and the digest is known as soon as the PFX is parsed in
GetProvisioningCertObj(). Moving the check there closes the gap on the ACM path.
The CCM to ACM path needs the check earlier still. The device is already in CCM with a TLS credential by the time the domain certificate is fetched, so even a PFX-time refusal leaves work to undo. The right point is profile selection - validate the profile's stored certificate against the device's reported capability before the first activation message is sent, so an incompatible pair never starts provisioning at all.
Hardened firmware generates an ECC-384 key pair, and RPS has to put that public key into a TLS certificate signed by the RPS root's RSA key. RPS builds certificates with node-forge, which cannot read an elliptic-curve public key.
It does not need to. RPS only has to place the key in the certificate, never sign with it, so the key can stay opaque.
The firmware already returns it in the exact shape a certificate expects - AMT_PublicPrivateKeyPair.DERKey is a
DER-encoded SubjectPublicKeyInfo, which is the X.509 public-key field - and forge.pki.certificateToAsn1 will sign
a cert.tbsCertificate the caller supplies instead of building its own.
Decision. Splice the firmware's DER key into the certificate body as opaque bytes and let node-forge sign around it. Never parse or re-encode it. RSA device keys keep the existing direct path.
Decision. RPS carries Intel's published Intel DICE SubCA CAID:343_1 certificate (elliptic-curve P-384) as a
trust anchor alongside the existing ODCA anchors, and verifies the DICE chain by the same rules as any other: each
certificate within its validity window, each signed by the next, and the top of the chain matched to an anchor by
certificate fingerprint - identity proven cryptographically, never by comparing names. The anchor's fingerprint is
asserted by test so the embedded certificate cannot be substituted unnoticed.
Why the anchor sits at the SubCA and not at the root above it. Intel publishes two certificates for this hierarchy, a DCP DICE Global Root CA and the SubCA beneath it. They do not chain to each other: their key identifiers do not correspond, signature verification of the SubCA against the root's public key fails, and the published root's validity begins months after the SubCA was issued - the SubCA was signed by a different root key than the one published. Anchoring at the global root would therefore verify nothing and reject every AMT 22 device. Anyone "completing" the bundle by adding the global root will break AMT 22 activation. The SubCA is not a convenient shortcut; against the published material it is the only workable anchor - and it is the better posture besides, being an Intel-controlled anchor scoped to Intel's own enterprise identifier rather than an industry root that would admit any SubCA it ever signs.
Why a single anchor is sufficient. The device presents its chain all the way up to and including the SubCA, so the anchor appears in the chain itself and matches directly. No intermediate fetching or path building is required.
What is deliberately not checked. Extended Key Usage: AMT's activation leaf carries no serverAuth usage, so a
conventional purpose check would reject a chain that is otherwise entirely valid. Revocation is also not consulted - the
DICE hierarchy publishes a revocation list covering the on-device levels, but RPS makes no outbound fetch on this path
today.
AMT 22 needs a stronger MPS server certificate than earlier generations, so a deployment already in the field has to change what it serves without breaking the devices that trust it.
The root cannot move. It is a distributed anchor, not a local asset: RPS installs a copy into every provisioned device's trusted-root store and records a second copy in that device's CIRA configuration, and neither copy is ever reconciled with what MPS serves. Regenerating it invalidates both across the whole estate at the next restart, and each affected device needs re-provisioning. The leaf is held by nobody but MPS, so it can be replaced freely.
Decision. Split the certificate lifecycle along that line.
| Area | Decision |
|---|---|
| MPS root | Immutable for the deployment's lifetime. Created once at the strongest parameters any supported generation accepts (3072 / SHA-384), so it never needs to change |
| MPS leaf | Replaceable. On startup MPS reissues the leaf alone, under the existing root, if the certificate it holds is weaker than configured. The root key and certificate pass through untouched |
| Leaf strength | A per-deployment setting, defaulting to the weaker value. Raising it is an explicit operator choice, because the stronger leaf is the one older generations reject |
| Direction of change | Upwards only. A lowered setting is ignored, so a configuration edit can never downgrade a working deployment |
| On failure | Degrade, never regenerate. If the root is missing or unreadable, MPS warns and leaves the certificates alone - regeneration is destructive and must never be reachable by falling through an error path |
Leaf-only reissue is not the polite option. It is the only one that keeps the three copies of the root consistent, and it makes the blast radius one process restart instead of the whole fleet.
Both deployment ages follow the same rule. The difference is only whether a root already exists in the vault.
| Deployment | What happens at startup |
|---|---|
| Existing | The stored root is reused untouched. If the stored leaf is weaker than mps_cert_key_size, MPS reissues the leaf under that root; devices keep trusting the chain and nothing is re-provisioned. This is the AMT 22 upgrade path - a deployment that first started on the 2048-bit default cannot complete CIRA with AMT 22 until its leaf is reissued at 3072 |
| Fresh | No vault secret exists, so root and leaf are minted together. The root is 3072 regardless of configuration; the leaf follows mps_cert_key_size, which still defaults to 2048. Set it to 3072 before first start when the fleet includes AMT 22 - the correct leaf is then minted directly and the reissue path never runs |
A fresh deployment that must serve both sizes. mps_cert_key_size is a single value and one endpoint presents one
certificate, so a fleet containing both AMT 11/12 and AMT 22 is not a matter of picking the right number - it needs the
two-endpoint arrangement in D6. Greenfield makes that easier rather than harder: the root is minted at 3072 on first
start whatever the setting says, and both the 2048-bit and the 3072-bit leaf are issued under that one root, so every
device installs the same anchor whichever port it connects to. Decide the endpoint layout before first start - adding
the second endpoint later is only a configuration change, but re-pointing devices already provisioned against the first
one is not.
Caveat for testing. The upwards-only rule is silent - a lowered setting is ignored with nothing logged. Testing an older generation against a weaker leaf will show a firmware failure that is really a test-setup error, so confirm the leaf actually being served on the wire rather than from configuration.
Both sides must move together. Adding AMT 22 to an existing deployment requires a SHA-384 domain profile on the RPS
side and a 3072-bit MPS server certificate (mps_cert_key_size: 3072, applied at MPS startup) on the other. Neither
is inferred from the device. An estate that does only the first activates its AMT 22 devices and leaves them without
CIRA - provisioned, and unmanageable.
A single MPS certificate cannot serve a mixed fleet. The two ends of the supported range contradict each other on the CIRA handshake:
| Generation | MPS server certificate |
|---|---|
| AMT 11 / 12 | RSA-2048. AMT 12.0.95 rejects a 3072-bit leaf outright - confirmed on hardware |
| AMT 22 | RSA-3072. A 2048-bit leaf is refused under the hardening rules |
One listening endpoint presents one certificate, so no single value of the setting satisfies both. This cannot be detected or reported during activation: it surfaces only at the CIRA handshake, long after RPS has finished and reported success.
Decision. A deployment spanning AMT 11/12 and AMT 22 runs MPS with two CIRA endpoints on separate ports - one serving a 2048-bit leaf for the older generations, one serving a 3072-bit leaf for AMT 22 - and one CIRA profile per endpoint, so each device is configured to connect to the port whose certificate its firmware will accept. Profile selection is therefore by device generation, and is the operator's decision at enrolment.
Both leaves are issued under the same MPS root (D5). The root is what each device installs in its trusted-root store, so keeping it common means the two endpoints differ only in the leaf they present - and a device moved between profiles still trusts the anchor it already holds.
| Alternative | Why not |
|---|---|
A1 - Derive SigningAlgorithm from the provisioning certificate alone |
Tried. AMT 20.0.5 refused the ACM upgrade with ReturnValue 3. The firmware's capability is a second input, and it cannot be inferred from the certificate. |
| A2 - Refuse a SHA-384 certificate on older generations | Tried and wrong. AMT 11 and AMT 12 activate with a SHA-384 provisioning certificate, as do AMT 16/18/20, so there is no digest ceiling to enforce. |
A3 - One useSha384 flag for all three digests |
The TLS leaf, the provisioning chain and the nonce signature are not one decision - the nonce digest also depends on what the certificate actually is. The tuple names each digest separately even though the hardening bit moves all of them together today. |
| A4 - Anchor DICE at the DCP global root | It does not sign the SubCA (D4), so every AMT 22 device would be rejected. |
| A5 - Two full MPS instances instead of two ports on one | Reaches much further than the problem: it splits device state, the management API and the UI in two, for a difference that is only in the certificate presented at the handshake. Not rejected outright - see below; it remains a legitimate customer deployment choice where the generations are already operated as separate estates. |
A5 in more detail. Both options serve two certificates; they differ in how much of the system is duplicated to do it.
Running two instances means duplicating everything behind the endpoint, and the cost is paid by the components around MPS rather than by MPS itself:
- The Sample Web UI assumes one MPS. It is configured with a single MPS address and lists devices from it. With two instances a device appears in one or the other, so either the UI learns to merge two sources, or the operator switches between two UIs and has to know in advance which one holds a device.
- Device state splits in two. Connection status, and any record keyed to the live tunnel, lives with the instance the device actually connected to. "Which MPS has this device?" becomes a question somebody has to answer before any management action can be routed.
- Redirection must land on the right instance. KVM, SOL and storage redirection run over the device's existing CIRA tunnel, so a session request is only serviceable by the instance holding it. A load balancer in front of two instances cannot distribute these freely.
- Two of everything operationally - API endpoints and their authentication, certificate material and secrets, monitoring, upgrade and restart windows.
- A new way to break the root invariant. Two instances with independent certificate stores can drift onto two different MPS roots, which is precisely the estate-wide failure D5 exists to prevent. The two-port design keeps one root by construction; two instances keep it only by discipline.
Two ports on one instance avoid all of the above: one device list, one API, one certificate store, one root - and the only thing that differs is which leaf is presented on which port.
When A5 is nevertheless the right choice. Where the old and new generations are already run as separate estates - different sites, different operators, separate upgrade schedules, or a hard requirement to isolate legacy devices - the duplication is not an added cost, because it already exists. Treated as a customer decision rather than a product default.