PQ-future of CCF #7971
Pinned
maxtropets
started this conversation in
Design
Replies: 1 comment 1 reply
|
This is very detailed, thanks for writing this up @maxtropets! Whenever you have some time (not urgent at all) I had some questions based off of this and impacts to ACL. Also, some questions may be a bit naive or the answer may not be fully thought out yet and I am happy to brainstorm some solutions.
Thanks! |
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Post-Quantum Support
This page defines the target shape for post-quantum support in CCF, not the current state of it.
Goals
The target design provides post-quantum safety for user-to-node TLS, node-to-node communication, ledger signatures, receipts, endorsements trust chain, member governance signatures, and user and member certificate authentication.
Identity type disclaimer
Identity references use
identity_type, not type-agnostic IDs.identity_typeis a CCF-specific enum, not the concrete crypto, e.g.ML-DSA-65orEC384.ML-DSA-65-1,ML-DSA-65-2.Reasons for that are:
[T1, ..., TN]identities it requires, making it possible to tell them apart in order to create/share missing ones.Switching to multiple identities
Service identity material is split by purpose, each purpose in its own
identity_type-keyed table.We bind
identity_typeto a purpose, and identities are not shared across purposes unless the same key material is deliberately reused.service_info(public:ccf.gov.service.info) stays a single, identity-independent value.It keeps the service-wide metadata (
status,recovery_count,current_service_create_txid,service_data) and may also track endorsement versions, but no longer holds identity or key material.The identities move into two new per-purpose tables:
identity_type)signing_identity0=EC384,1=ML-DSA-65, ...Identitytls_identity0=EC384,1=ML-DSA-65, ...IdentityIdentity{ kind: Kind, bytes }Kind0=x509 raw key,1=cose key,2=jwkidentity_type0=EC384,1=ML-DSA-65, ...These tables hold only the public identity material. Private keys are stored the same way as today, in memory in
NetworkStaterather than in the KV.All
identity_types present in a purpose's table are used for that purpose. For example:identity_typeinsigning_identity.tls_identity, and the TLS protocol selects one according to the client's capabilities.Nit. Users are mapped 1<->cert, so in order to get PQ TLS they'll need to have a PQ cert issued.
Node-to-node identity is separate
N2N is node-scoped, not service-scoped.
It is not listed in
service.identity_bindings.Current node identity state is split across node tables:
public:ccf.gov.nodes.infonode_idNodeInfopublic:ccf.gov.nodes.endorsed_certificatesnode_idCurrent
NodeInfoalready stores the node's quote, encryption public key, status, CSR, and public key.The
node_idis derived from the node public key.The N2N migration should be orthogonal: eventually replace the custom N2N channel with a PQ-safe transport via QUIC.
The internal node communication identity shape is left opaque for now.
During a rolling N2N upgrade, new nodes join with the communication identity required by their config and old nodes retire.
Since this is internal node communication, there is no need to offer several N2N identities in parallel, and the complete transition design is to be sorted out later.
Introducing and removing identities
Identity material and purpose bindings are introduced or removed atomically.
Join policy is also expressed in terms of service identity types and purposes.
It should distinguish required, allowed, and disallowed combinations.
If both EC and PQ signing are required, EC-only and PQ-only joiners are both rejected.
The concrete policy can be JSON/Rego.
The rollout shape mirrors the COSE-only ledger upgrade.
EC -> [TLS, SIGN]required EC -> [TLS, SIGN]EC -> [TLS, SIGN]required EC -> [TLS, SIGN]; allowed PQ -> [SIGN]EC -> [TLS, SIGN]; PQ -> [SIGN]EC -> [TLS, SIGN]; PQ -> [SIGN]EC -> [TLS, SIGN]; PQ -> [SIGN]required EC -> [TLS, SIGN]; required PQ -> [SIGN]EC -> [TLS, SIGN]; PQ -> [SIGN]Mixed identity periods are expected during the rolling update window.
This is an intentional design choice, not a temporary inconsistency.
If a joining node advertises an allowed identity type and the service does not have that identity yet, the identity must be created in the same join transaction.
The identity is then reused for future joiners of the same type, and its private material is shared with trusted nodes the same way service private material is shared today.
On recovery, the existing join policy is preserved.
On service creation, the initial join policy is operator-set in the current design; deriving it automatically from the configured service identities is still to be defined.
Previous identity endorsements
Only signing identities are endorsed.
Their endorsements are stored separately from the identity tables, keyed by
identity_type, so each signing identity has its own continuity chain: aT1identity endorses only the nextT1identity, and each type stays within its own chain.TLS identities are not endorsed and have no continuity chain.
Signing identities are created on each service create/recovery, the same as the service identity today.
Attestation
Today, CCF uses AMD SEV-SNP
report_dataas a node-identity binding:The rest of quote verification is separate: CCF verifies the AMD endorsements, the security policy in
host_data, the measurement or UVM endorsements, and the TCB version.With multiple identities,
report_datashould carry both the identity digest and the binding metadata:LAYOUTidentity_type, kind, purpose, algorithm suite, hash algorithmRESERVEDDIGESTLAYOUTis:identity_typeExamples:
For node join, attestation must bind the node identity used to request trust:
SHA-256 leaves 16 digest-slot bytes unused, so they must be zero.
SHA-384 consumes the whole 48-byte digest slot.
SHA-512 is not used because it would consume all 64 bytes of
report_data.The layout keeps 16 bytes for binding metadata and reserved space.
The verifier checks the digest and the metadata, so it can tell which identity type and purpose were attested.
Members and users
Members and users should mirror the current model.
Users use certificate authentication with PQ-enabled certificates.
Members use certificate authentication where needed, and governance messages are COSE-signed with PQ or composite COSE signatures.
Registering a new PQ-enabled cert creates a new user/member identity, same as any cert rotation today.
Member shares
For recovery shares, moving from RSA-OAEP to PQ is not a direct primitive swap. RSA-OAEP currently encrypts the raw share directly to the member's RSA encryption public key, and the member later decrypts that ciphertext with their RSA private key.
ML-KEM is different: it does not encrypt arbitrary share bytes. It encapsulates a shared secret to the member's ML-KEM public key. That shared secret must then be passed through a KDF and used with symmetric AEAD to encrypt the actual share.
For a real hybrid RSA+PQ design, we should not store independent RSA-wrapped and ML-KEM-wrapped copies of the same share, because either one would be sufficient to recover it and the weaker path would dominate. Instead, derive one share-wrapping key from both a classical RSA-protected secret and an ML-KEM-protected secret, then AEAD-encrypt the share once with that combined key.
This changes the stored share format from a single RSA ciphertext into a versioned envelope containing the RSA ciphertext, KEM ciphertext, KDF/AEAD metadata, nonce, ciphertext, and tag. It also requires corresponding member key-generation, registration, HSM/Key Vault, and recovery-tooling support.
Current platform and standards support
The standards RFCs/drafts possibly targeted by this design are:
draft-ietf-lamps-pq-composite-sigsfor Composite-ML-DSA X.509 certificatesdraft-reddy-tls-composite-mldsafor Composite-ML-DSA authentication in TLS 1.3.draft-ietf-jose-pq-composite-sigsfor JOSE/COSE composite signatures.RFC 9881for pure ML-DSA X.509 certificates.RFC 9964for pure ML-DSA JOSE/COSE signatures.FIPS 204for the ML-DSA algorithm itself.CCF will target Azure Linux 4 and OpenSSL 3.5, so here is the list of what is currently supported and not supported:
Azure Linux 4 confirmation
This was confirmed on Azure Linux 4 with OpenSSL 3.5, without SymCrypt yet.
Confirmed support:
ML-DSA-65X.509 certificates can be generated, DER-parsed, and verified withX509_verify.ML-DSA-65andSLH-DSA-SHA2-128ssignatures can be generated and verified.ML-KEM-512,ML-KEM-768, andML-KEM-1024encapsulation and decapsulation work.X25519MLKEM768hybrid group with anML-DSA-65server certificate,mldsa65CertificateVerify, and client certificate verification.EVP_PKEYkeymgmt and signature provider implementation, X.509 and TLS have no composite primitive to use.Composite certificates can be encoded, but stock OpenSSL 3.5 cannot use them as normal certificates.
OpenSSL has no Composite-ML-DSA key, signature, X.509, or TLS
SignatureSchemesupport.CCF therefore cannot ask OpenSSL to generate, verify, select, or present a Composite-ML-DSA certificate in TLS.
Composite COSE signatures are technically possible with stock OpenSSL 3.5, but not as one OpenSSL algorithm.
The JOSE/COSE draft reuses the LAMPS composite key and signature encoding, carried as AKP
pub/privbytes.CCF can implement the draft combiner and use OpenSSL only for the ML-DSA and classical component signatures.
This is draft-compliant if CCF pins the draft version, labels, prehash, key encodings, and COSE algorithm values.
The component keys must still be a single composite key.
The drafts require fresh component key generation and forbid reusing those keys in other contexts or as standalone keys.
For certificate-backed identities,
x5chain/x5cshould refer to a LAMPS composite X.509 certificate.Stock OpenSSL cannot create that certificate form, so this needs custom tooling or another provider/library.
It is not RFC-standard yet: RFC 9964 only standardizes pure ML-DSA for JOSE/COSE.
Path forward
Start with a PQ-only extra identity for RFC 9964 ML-DSA COSE signing.
Keep the existing classical identity and signature during migration.
For TLS confidentiality, enable OpenSSL 3.5 ML-KEM hybrid groups, starting with
X25519MLKEM768.Gradually move to PQ certs unless composites are possible.
Leave composite support for later.
Composite TLS depends on composite certificate and TLS signature support that stock OpenSSL does not provide.
For signing, require two COSE signatures for now: one classical and one ML-DSA.
All reactions