Tenant Crypto Policy System
The tenant crypto policy system ensures consistent algorithm selection across all QNSI services based on tenant billing tiers, custom policies, and compliance requirements.
The tenant crypto policy system ensures consistent algorithm selection across all QNSI services based on tenant billing tiers, custom policies, and compliance requirements.
Overview
Every tenant has a crypto policy that determines:
- Which PQC algorithms are allowed for encryption and signatures
- Default algorithms for new cryptographic operations
- Custom algorithm allowlists and forbidden lists
- HSM requirements for root keys
- Maximum key age before rotation
QNSI currently supports two policy models:
- v0 tiers (legacy): default/strict/maximum/government
- v1 profiles + tiers (evidence-first): profile constraints plus tier gates
Services still use the v0 policy via @heossihq/qnsi-security tenant-crypto-policy-client while migration completes. The v1 policy is stored in tenant_crypto_policy and is returned by /platform/v1/crypto/policy when an X-Tenant-Id header is supplied.
Crypto Policy V1 (Profiles + Tiers)
V1 policies focus on profiles (policy intent) and tiers (evidence/gating). Profiles define which tiers are allowed and set default KEM/signature algorithms.
V1 Profiles
| Profile | Summary | Allowed Tiers |
|---|---|---|
gov-high-assurance |
Procurement-safe baseline | TIER1_APPROVED |
defense-long-life-data |
High assurance + stateful options | TIER1_APPROVED, TIER2_HIGH_ASSURANCE |
financial-hybrid-pqc |
Migration/hybrid posture | TIER1_APPROVED, TIER0_LEGACY, TIER3_DIVERSITY |
research-eval |
Gated non-compliant research | TIER1_APPROVED, TIER3_DIVERSITY, TIER4_EXPERIMENTAL |
V1 Tier Gates
TIER0_LEGACYrequires an expiry (tier0Expiry) and explicit enablement.TIER4_EXPERIMENTALrequires an acknowledgement (tier4Acknowledgement).TIER2_HIGH_ASSURANCErequires stateful lifecycle guards.TIER3_DIVERSITYis only allowed for hybrid/alternate risk models.
Tenant Defaults (Examples)
Defaults are derived from tenant plan → tenant type mapping:
FREE_FOREVER→gov-high-assuranceDEV_PRO/DEV_ELITE→financial-hybrid-pqcENTERPRISE_PRO/ENTERPRISE_ELITE→defense-long-life-data
Legacy Policy Tiers (v0)
Policy Tiers
Default Tier
Target: Standard business customers Algorithms:
- KEM: Kyber-512, Kyber-768, Kyber-1024 (default: Kyber-768)
- Signatures: Dilithium-2, Dilithium-3, Dilithium-5 (default: Dilithium-3) Performance: Balanced security and performance
Strict Tier
Target: Security-conscious organizations Algorithms:
- KEM: Kyber-768, Kyber-1024 (default: Kyber-768)
- Signatures: Dilithium-3, Dilithium-5, Falcon-1024 (default: Dilithium-3) Performance: Enhanced security with moderate performance impact
Maximum Tier
Target: High-security environments Algorithms:
- KEM: Kyber-1024 (default: Kyber-1024)
- Signatures: Dilithium-5, Falcon-1024, SPHINCS-SHAKE-256f (default: Dilithium-5) Performance: Maximum security, higher computational cost
Government Tier
Target: Government and military customers Algorithms:
- KEM: Kyber-1024 (default: Kyber-1024)
- Signatures: Dilithium-5, SPHINCS-SHAKE-256f (default: Dilithium-5) Performance: Government-approved algorithms only
Algorithm Naming
The system supports both internal and NIST standardized algorithm names:
Internal Names (used in code)
kyber-512,kyber-768,kyber-1024dilithium-2,dilithium-3,dilithium-5falcon-512,falcon-1024sphincs-shake-128f-simple,sphincs-shake-256f-simple
NIST Names (for display/compliance)
ML-KEM-512,ML-KEM-768,ML-KEM-1024ML-DSA-44,ML-DSA-65,ML-DSA-87FN-DSA-512,FN-DSA-1024SLH-DSA-SHAKE-128f,SLH-DSA-SHAKE-256f
Service Integration
Client Creation
Services create a crypto policy client from environment variables:
// Internal platform source (readable in the public mirror) - @heossihq/qnsi-security is
// NOT published to npm. This shows how QNSI's own services resolve tenant crypto policy.
import { createTenantCryptoPolicyClientFromEnv } from '../../packages/security/src/index.js';
const cryptoPolicyClient = createTenantCryptoPolicyClientFromEnv();
Environment Variables
TENANT_SERVICE_URL=https://tenant-service:8108
TENANT_SERVICE_API_TOKEN=<static-token>
# OR service token flow:
AUTH_SERVICE_URL=https://auth-service:8081
SERVICE_ID=kms-service
SERVICE_SECRET=<service-secret>
# Optional only for explicitness; fail_closed is the sole accepted value.
# Omitted configuration also fails closed.
TENANT_CRYPTO_POLICY_FAILURE_MODE=fail_closed
Algorithm Selection
// Get default algorithms for new operations
const kemAlgorithm = await cryptoPolicyClient.getDefaultKemAlgorithm(tenantId);
const signatureAlgorithm = await cryptoPolicyClient.getDefaultSignatureAlgorithm(tenantId);
// Get all allowed algorithms
const allowedKem = await cryptoPolicyClient.getAllowedKemAlgorithms(tenantId);
const allowedSig = await cryptoPolicyClient.getAllowedSignatureAlgorithms(tenantId);
// Validate algorithm is allowed
const isKemAllowed = await cryptoPolicyClient.isAlgorithmAllowed(tenantId, 'kyber-1024', 'kem');
const isSigAllowed = await cryptoPolicyClient.isAlgorithmAllowed(tenantId, 'dilithium-5', 'signature');
Caching and Performance
- Cache TTL: 60 seconds by default (configurable)
- Failure mode: Mandatory fail-closed behavior returns
503 CRYPTO_POLICY_UNAVAILABLEfor outages, malformed responses, or tenant mismatches - Missing policy: A
404selects the PQC default tier with enforcement enabled; it is not an outage fallback - Service Tokens: Automatic token refresh for service-to-service auth
- Response validation: Tenant policy responses are schema-validated before caching
API Endpoints
Get Tenant Crypto Policy (v0)
GET /tenant/v1/tenants/{tenantId}/crypto-policy
Authorization: Bearer <token>
Response:
{
"tenantId": "tenant-123",
"policyTier": "strict",
"customAllowedKemAlgorithms": null,
"customAllowedSignatureAlgorithms": ["dilithium-5", "falcon-1024"],
"customForbiddenAlgorithms": ["dilithium-2"],
"requireHsmForRootKeys": true,
"maxKeyAgeDays": 180,
"enforcementMode": "enforce",
"cryptoEntropySource": "csprng",
"createdAt": "2026-01-04T10:00:00Z",
"updatedAt": "2026-01-04T10:00:00Z"
}
cryptoEntropySource
Declarative entropy-source contract for the tenant. Added 2026-05-13. See https://qnsi.heossi.com/trust/entropy for the auditable end-to-end chain (NIST SP 800-90A/B/C citations, OpenSSL DRBG, Linux getrandom + CPU TRNG, HSM DRBGs).
| Value | Where | Default for tiers |
|---|---|---|
csprng |
OpenSSL SP 800-90A AES-CTR-DRBG seeded from Linux getrandom + RDRAND / RDSEED / Nitro TRNG. |
default, strict |
hsm-byo |
Customer-managed FIPS 140-3 L3 HSM DRBG via PKCS#11 (AWS CloudHSM, Azure Managed HSM, Thales Luna, Entrust nShield, Utimaco, Marvell LiquidHSM, Fortanix DSM, HashiCorp Vault HSM). | maximum, government |
qrng-mixin |
Customer-supplied QRNG (Qrypt / Quantum Dice / ID Quantique Quantis / Quantum-Origin) mixed into HSM DRBG seed per NIST SP 800-90C RBG3 prediction-resistance reseed. Sales-assisted add-on (byoh-qrng-mixin). |
Optional on Maximum/Government tiers |
The field is currently a declarative contract surfaced through the audit trail and billing layer; per-tenant entropy-source routing is on the platform roadmap. Today every backend service draws from the platform CSPRNG except for root-key operations on tiers that route through the BYOH HSM channel.
Get Tenant Crypto Policy (v1)
GET /tenant/v1/tenants/{tenantId}/crypto-policy-v1
Authorization: Bearer <token>
List Policy History (v1)
GET /tenant/v1/tenants/{tenantId}/crypto-policy-v1/history?limit=50
Authorization: Bearer <token>
Update Policy (v1)
PUT /tenant/v1/tenants/{tenantId}/crypto-policy-v1
Authorization: Bearer <token>
If-Match: <etag>
Content-Type: application/json
{
"policy": { ... }
}
Tier Gates + Rollback (v1)
POST /tenant/v1/tenants/{tenantId}/crypto-policy-v1/tier0/enable
POST /tenant/v1/tenants/{tenantId}/crypto-policy-v1/tier0/disable
POST /tenant/v1/tenants/{tenantId}/crypto-policy-v1/tier4/enable
POST /tenant/v1/tenants/{tenantId}/crypto-policy-v1/rollback
Create/Update Crypto Policy (v0)
PUT /tenant/v1/tenants/{tenantId}/crypto-policy
Authorization: Bearer <token>
Content-Type: application/json
{
"policyTier": "maximum",
"customAllowedSignatureAlgorithms": ["dilithium-5", "sphincs-shake-256f-simple"],
"requireHsmForRootKeys": true,
"maxKeyAgeDays": 90,
"enforcementMode": "enforce",
"cryptoEntropySource": "hsm-byo"
}
Service-Specific Usage
KMS Service
Uses crypto policy for:
- Key generation algorithm selection
- Key rotation algorithm upgrades
- HSM requirement enforcement
Storage Service
Uses crypto policy for:
- File encryption algorithm selection
- Metadata encryption
- Search index encryption
Auth Service
Uses crypto policy for:
- JWT signing algorithm selection
- Session token encryption
- WebAuthn credential protection
Vault Service
Uses crypto policy for:
- Secret encryption algorithms
- Lease token signing
- Backup encryption
Compliance and Auditing
Enforcement Posture
- enforce: Every service blocks operations that violate the resolved policy.
- Audit events are observational evidence only; an
auditlabel never authorizes a violating operation.
Audit Events
Crypto policy decisions emit audit-service events for:
- Algorithm selection decisions
- Policy violations
- Selection of the mandatory default after an authoritative
404 - Policy-store outages, malformed responses, and tenant mismatches
Compliance Mapping
- FIPS 140-3: Government tier uses FIPS-approved algorithms
- Common Criteria: Maximum tier provides CC-evaluated algorithms
- NIST Guidelines: All tiers follow NIST PQC recommendations
Troubleshooting
Common Issues
Policy not found (404)
- Tenant has no custom policy, so the enforcing PQC default tier is selected
- Normal behavior for new tenants
Policy service unavailable or response rejected
- Services return
503 CRYPTO_POLICY_UNAVAILABLE; they never substitute policy after an outage - Verify tenant-service health, authentication, network connectivity, and response contract
- Remove stale
fail_openvalues; the only accepted explicit setting isfail_closed
Algorithm not allowed
- Requested algorithm not in tenant's allowed list
- Check tenant's policy tier and custom restrictions
- Use
isAlgorithmAllowed()to validate before operations
Cache inconsistency
- Policy updated but service still using cached version
- Wait for cache TTL (60s) or call
clearCache(tenantId) - Consider reducing cache TTL for frequently changing policies
Monitoring
Existing policy telemetry must be verified from the deployed observability pipeline before relying on a metric name or dashboard value.
Debugging
Enable debug logging:
const client = new TenantCryptoPolicyClient({
tenantServiceUrl: 'https://tenant-service:8108',
logLevel: 'debug'
});
Migration and Upgrades
Algorithm Migration
When new PQC algorithms are standardized:
- Add algorithms to tier configurations
- Update tenant policies to include new algorithms
- Services automatically use new algorithms for new operations
- Background re-encryption migrates existing data
Policy Tier Upgrades
Tenants can upgrade their policy tier through billing:
- Purchase crypto policy add-on
- tenant-service updates policy tier
- Services pick up new policy within cache TTL
- New operations use upgraded algorithms
Backward Compatibility
- Old algorithms remain supported for decryption
- New encryptions use current policy algorithms
- Gradual migration prevents breaking existing data