KSN · DUKPT CAPK · A000000003 ARQC → ARPC P2PE · BDK RKI · 9F26
Paying.co · Foundry · Crypto & Key Management · deep dive

The keys. Provision the crypto,
never compute it.

The last core subsystem. Foundry manages and provisions keys and transports cryptograms — the kernel and the issuer do the math. This doc draws the exact line: what the L2 kernel owns, what Foundry provisions, what the adapter supplies, and how DUKPT, CAPK, and the ARQC/ARPC handshake move through the system without Foundry ever touching a primitive. In the native C engine the crypto service is a portable module fronting the platform secure element; the Kotlin SDK wraps the same contract.

status shipped DUKPT · P2PE CAPK · CRL · RKI ARQC → ARPC
The line · who does the math, who moves it

The single most important boundary in this doc. Foundry never generates or verifies a cryptogram, never derives a session key, never encrypts a PAN. Those are kernel and issuer operations. Foundry's crypto job is logistics: get the right keys loaded, move the right bytes, surface the result.

Kernel & issuer own the math never Foundry

happens in firmware / at the issuer — opaque to us
  • Offline data authentication — SDA/DDA/CDA using the CAPK we loaded
  • Session key derivation — DUKPT future-keys from the BDK, on-device
  • PAN / track encryption — P2PE inside the secure processor
  • ARQC generation — the request cryptogram, by the card + kernel
  • ARQC verification & ARPC — at the issuer, off-device entirely

Foundry provisions & moves logistics, not math

load keys, transport cryptograms, surface results
  • Load CAPK / CRL into the kernel — ctls_setCAPK, emv_setCRL
  • Inject keys remotelydevice_startRKI, CA certs via device_loadCertCA
  • Read KSN for the encrypted payload — device_getKSN
  • Transport the ARQC to the adapter → host, verbatim
  • Feed ARPC back to the kernel — emv_completeTransaction
if Foundry code ever computes a key or cryptogram, the line has been crossed — that work belongs to the kernel
Two channels · config and secrets travel separately

A deliberate separation carried from doc 05. Public key material and config ride the config feed; secret symmetric keys ride a dedicated injection channel. They never mix — secrets never sit in a config manifest, and the config path never carries a clear key.

Channel A · Config feedpublic material
CAPKs (CA public keys), CRL, and CA certs — non-secret, ride in the signed manifest, loaded by the provisioning service. Verifiable by checksum & check-value like any other parameter.
ctls_setCAPKemv_setCRLdevice_loadCertCActls_retrieveCAPKList
Channel B · Key injectionsecret material
Symmetric secrets — DUKPT initial keys, P2PE — never travel as data. Injected remotely into the secure processor via RKI against a trusted endpoint, or loaded under a key-transport scheme. Foundry sets the endpoint and triggers; the secure element holds the secret.
device_setSymmetric_RKI_URLdevice_startRKI
why it matters PCI scope follows the secrets. By keeping symmetric key material on Channel B — injected straight into the secure element, never serialized into a manifest or a log — the config feed and Foundry's own storage stay out of key scope. The canonical model's no-clear-PAN rule is the same instinct applied to card data.
Key inventory · what exists, who owns it

The keys in play, and the ownership tag that decides where each is handled. Note that no row is owned by Foundry core compute — Foundry only ever loads, triggers, or transports.

Key / artifactPurposeLives whereOwner
CAPKCA public key for offline data auth (SDA/DDA/CDA)loaded into kernelFoundry loads
CRLRevoked certificate list for offline authloaded into kernelFoundry loads
CA certTrust anchor for RKI / secure provisioningsecure elementFoundry loads
BDK / IPEKDUKPT base / initial PIN-encryption keysecure processorkernel · injected
DUKPT future keysPer-transaction session keys derived from KSNsecure processorkernel derives
P2PE keyEncrypts PAN / track at the read headsecure processorkernel encrypts
KSNKey serial number — names the session key to the decryptortravels with payloadFoundry reads
Zone / working keysHost-link MAC & field encryption to the processoradapter / HSMadapter supplies
ARQC / ARPCOnline auth cryptogram & issuer responsetransportedFoundry moves
read it this way Three owners, never four: the kernel derives and encrypts, the adapter supplies host-link keys through keyContext(), and Foundry only loads, reads, and moves. There is no column for "Foundry computes." That absence is the design.
The handshake · how crypto moves through one transaction

DUKPT-encrypted card data and the ARQC/ARPC cycle, traced through a single tap — with Foundry's role marked at each step. Foundry appears only as a courier; the math happens in the blue (kernel) and at the issuer.

1
Card data encrypted on-device
At the tap, the secure processor derives a fresh DUKPT session key and encrypts the PAN/track under P2PE. Foundry never sees clear data. Kernel-owned, in firmware.
2
Foundry reads the KSN
The encrypted blocks arrive with a Key Serial Number. Foundry reads it via device_getKSN so the eventual decryptor knows which session key was used. Pure logistics — a label, not a secret.
device_getKSN
3
Kernel generates the ARQC
The card + kernel produce the request cryptogram (9F26) over the transaction data. This lands in canonical's crypto group — carried, never computed.
4
Foundry transports to the adapter
The ARQC + supporting tags pass through canonical to the active processor adapter, which formats them into the host message and applies its own zone-key MAC via keyContext(). Adapter-owned crypto, isolated.
5
Issuer verifies, returns ARPC
Off-device, the issuer verifies the ARQC and returns the response cryptogram (ARPC) with the auth decision. Neither Foundry nor the adapter validates it — they relay it.
6
Foundry feeds ARPC to the kernel
The result returns through canonical; Foundry hands the ARPC to the kernel to finalize. The kernel validates issuer authentication and completes. Foundry's last courier step.
emv_authenticateTransactionemv_completeTransactionctls_displayOnlineAuthResult
the discipline Across all six steps, every Foundry action is load, read, transport, or feed — never derive, encrypt, sign, or verify. If a future requirement seems to need Foundry to do crypto math, that's the signal to push it into the kernel (firmware) or the adapter (host-link), not to implement it in core. The distilled common crypto interface exists precisely to keep this line clean.
Design rules for crypto & keys

What keeps Foundry on the right side of every key boundary.

Provision, don't compute
Foundry loads, reads, and moves. The kernel derives & encrypts; the issuer verifies. No crypto primitive lives in core.
Two channels, never mixed
Public material (CAPK/CRL/certs) on the config feed; secret keys via RKI into the secure element. Secrets never become data.
Carry the cryptogram verbatim
ARQC and supporting tags transit canonical untouched. ARPC returns the same way. Foundry is the courier.
Keys out of PCI scope
Secret material lands in the secure element only — never in a manifest, log, or Foundry store. Scope follows the secrets.
Host-link keys are the adapter's
Zone / working keys & MAC schemes live in keyContext(), sealed per processor — not in the shared crypto interface.
One common interface
The core speaks a single distilled crypto vocabulary — provision, getKSN, authenticated-complete — so processor differences stay in the adapter.