Skip to main content
Promotional banner ad for the Penetration Testing Report Kit
Your Cryptographic Policy Is Still Enforced by HopeTechnical Security Controls
6 min readFor GRC Practitioners

Your Cryptographic Policy Is Still Enforced by Hope

You've chosen ML-DSA-65 and ML-DSA-87 for your quantum-resistant signing architecture. You've documented the decision and communicated it to engineering. Yet, nothing stops someone from using an ML-DSA-44 key tomorrow. You've written a policy, but you haven't enforced it.

This isn't just about ML-DSA. It's about the gap between "we decided" and "we can't do anything else." That gap is where cryptographic policy fails, and it's why organizations struggle when standards evolve. You're not just managing algorithms; you're managing the ability to adapt when a parameter set gets deprecated, a new variant arrives, or NIST updates FIPS 204. If your controls are static, you're already behind.

Why Mistakes Persist

Most teams treat cryptographic policy as a documentation task. You capture the decision in a standards document, maybe add it to an architecture review checklist, and assume compliance follows. It doesn't. Without enforcement at the API layer, your policy is just a suggestion.

The problem worsens when transitioning to post-quantum cryptography. ML-DSA offers three parameter sets (ML-DSA-44, ML-DSA-65, ML-DSA-87), each with different security margins, signature sizes, and performance characteristics. All three are FIPS 204-standardized. But "valid" doesn't mean "approved for your environment," and AWS KMS doesn't know which variant your risk assessment approved. By default, everything is permitted until you explicitly block it.

These mistakes aren't about carelessness. They're about treating cloud cryptography like on-premises key management, where physical access and procurement cycles created natural gates. In AWS, those gates don't exist unless you build them.

Mistake 1: Blocking Creation but Not Use

You write a Service Control Policy (SCP) that denies kms:CreateKey for ML_DSA_44. You're done, right?

Not if ML-DSA-44 keys already exist. Maybe they were created before the SCP was applied. Maybe they live in a sandbox account that later got moved into the production OU. Maybe they were created in the management account, where SCPs don't apply.

Those keys still work. kms:Sign, kms:Verify, and kms:GetPublicKey will succeed against them until you explicitly restrict those operations.

The fix: Extend your SCP to cover both creation and use. Your deny statement needs to include kms:Sign, kms:Verify, and kms:GetPublicKey, all conditioned on kms:KeySpec matching ML_DSA_44. This closes the gap for existing keys. If your organization has a key inventory process, audit for ML-DSA-44 keys outside your approved set and schedule them for rotation.

Mistake 2: Confusing Key Spec with Signing Algorithm

You try to write a policy that blocks ML-DSA-44 by restricting kms:SigningAlgorithm to exclude it. The policy doesn't fire. ML-DSA-44 operations sail through.

Here's why: all three ML-DSA variants use the same signing algorithm value, ML_DSA_SHAKE_256. The kms:SigningAlgorithm condition key can't distinguish ML-DSA-44 from ML-DSA-65 or ML-DSA-87 because they all present the same algorithm identifier.

kms:KeySpec is what differentiates them. It reflects the parameter set: ML_DSA_44, ML_DSA_65, or ML_DSA_87. That's the condition key you need for variant-level control.

The fix: Condition your deny statements on kms:KeySpec, not kms:SigningAlgorithm. For example, a condition that denies when kms:KeySpec equals ML_DSA_44 will block that variant while leaving ML-DSA-65 and ML-DSA-87 operations untouched. Test this in a non-production account first; IAM and SCP evaluation can be counterintuitive when multiple conditions interact.

Mistake 3: Forgetting the Management Account

You've locked down your production OU with an SCP. Your security team runs quarterly audits. You're confident ML-DSA-44 can't be introduced.

Then someone in the management account creates an ML-DSA-44 key for testing, uses it to sign a container image, and that image gets deployed to production. The SCP never saw it, because SCPs don't apply to the management account.

This isn't theoretical. The management account is where break-glass access lives, where security tooling often runs, and where exceptions accumulate. If you're not treating it as in-scope for cryptographic policy, you have a blind spot.

The fix: Don't run workloads that perform cryptographic operations in the management account. Move signing pipelines, certificate issuance, and anything that touches KMS keys into member accounts where your SCPs apply. If you must keep cryptographic operations in the management account (for example, organization-wide security automation), enforce the policy through IAM permission boundaries on the roles that perform those operations. Permission boundaries apply even when SCPs don't.

Mistake 4: Default-Allow for New Variants

Your SCP denies ML-DSA-44. Six months from now, NIST releases a new parameter set or AWS adds support for a variant you haven't evaluated. By default, it's usable, because your policy only named ML-DSA-44.

This is the cryptographic agility problem in reverse. You've built controls that adapt to deprecation (add the deprecated variant to the deny list), but you haven't protected against the introduction of something new.

The fix: Decide whether you want default-deny or default-allow for new variants. Default-deny means writing your condition as StringNotEquals against the approved set: deny any ML-DSA key spec that isn't ML-DSA-65 or ML-DSA-87. When a new variant arrives, it's blocked until you add it to the approved list. Default-allow means denying only the specific variants you've rejected; new ones are usable until you notice and evaluate them. Neither is wrong, but you need to know which model you're operating under and pair it with detection. Set up AWS Config rules or EventBridge patterns that alert when a key is created with a spec you haven't explicitly approved or denied.

Mistake 5: Ignoring Certificate and Private CA Surfaces

You've locked down KMS key creation. You haven't touched AWS Private Certificate Authority or AWS Certificate Manager. Someone stands up a subordinate CA with an ML-DSA-44 key and starts issuing certificates.

KMS controls govern KMS keys. They don't govern the key material AWS Private CA generates and holds in its own HSMs, and they don't govern certificates imported through acm:ImportCertificate or iam:UploadServerCertificate. Those are separate attack surfaces.

The fix: Extend your policy to Private CA and certificate operations. For Private CA, deny acm-pca:CreateCertificateAuthority when the CA configuration specifies ML-DSA-44 as the signing algorithm. For ACM, you can't inspect the algorithm of imported certificates through IAM conditions, so this is where detective controls matter: monitor CloudTrail for ImportCertificate events and validate the certificate's signature algorithm out-of-band. If you're using IAM Roles Anywhere, audit the trust anchors and CRLs for algorithm compliance separately; those aren't covered by KMS or Private CA controls.

Prevention Checklist

Before you call your cryptographic policy enforced, verify:

  • Your SCP or IAM policy denies both creation (kms:CreateKey) and use (kms:Sign, kms:Verify, kms:GetPublicKey) of non-approved variants
  • You're conditioning on kms:KeySpec, not kms:SigningAlgorithm
  • You've scoped the control to ML-DSA variants with StringLike on kms:KeySpec matching ML_DSA_* so it doesn't affect other key types
  • You've inventoried existing keys and identified any that predate the policy
  • You've moved cryptographic workloads out of the management account or applied permission boundaries there
  • You've decided whether new variants should be default-deny or default-allow and documented the model
  • You've extended controls to Private CA creation and certificate import operations
  • You've set up detection for algorithm use outside your approved set (AWS Config, CloudTrail, or EventBridge)
  • You've tested the policy in a non-production account and confirmed approved variants still work
  • You've scheduled a review cycle to update the policy when standards or service capabilities change

Cryptographic agility isn't just about adopting new algorithms. It's about enforcing the ones you've chosen and adapting enforcement when choices change. Build these controls now, before the next variant arrives.

Promotional banner for the Penetration Report Template Kit

You Might Also Like