Communication Flow
Understanding the communication flow helps troubleshoot issues and optimize performance. This page gives a high-level view of how operations flow through the system from Oracle Database to DuoKey Cockpit and back.
Overview
Architecture
Communication overview
Oracle's calls pass through the PKCS#11 library to the Cockpit API and on to the backend HSM; responses return along the same path.
Typical Operation Flow
Initialization Flow
Sequence
Initialization flow
The library reads pkcs11.toml and presents its access_token on the first request; Cockpit validates it and resolves the tenant, with no separate token exchange.
Steps:
- Oracle calls C_Initialize(): Library initialization begins
- Read Configuration: Library reads
server_url(containing the non-secretaccess_guidrouting id) andaccess_tokenfrompkcs11.toml - Authentication: The library presents its
access_tokenbearer credential to the Cockpit on its first request - Server-side Validation: The Cockpit validates the
access_tokenand resolves the tenant from(app_id, access_guid); no separate token exchange is performed - Vault Verification: Verify access to specified vault
- Return Success: Library ready for operations
Session Creation Flow
Sequence
Session creation flow
No API call is needed for session creation; sessions are managed locally.
Steps:
- Oracle calls C_OpenSession(): Request new session
- Validate Slot: Ensure slot ID is valid
- Create Session: Create internal session object
- Initialize Tables: Create handle mapping table for session
- Return Handle: Return session handle to Oracle
Note: Session creation doesn't require API calls. Sessions are managed locally.
Login Flow
Sequence
Login flow
The bearer token was already presented in C_Initialize(); C_Login performs no additional API call.
Steps:
- Oracle calls C_Login(): Request session login
- Check Token: Verify the
access_tokenbearer credential is configured inpkcs11.toml - Mark Session: Mark session as authenticated
- Return Success: Return CKR_OK
Note: For DuoKey PKCS#11, authentication happens during C_Initialize(), when the library presents its access_token bearer credential to the Cockpit. The C_Login() function confirms the token is available but doesn't perform additional API calls.
Key Generation Flow
Sequence
Key generation flow
Cockpit has the backend HSM generate the key and returns its UUID, which the PKCS#11 layer maps to a handle for Oracle.
Steps:
- Oracle calls C_GenerateKey(): Request key generation
- Parse Template: Extract key attributes (type, size, label)
- Build API Request: Create key generation request
- API Call: Send the key-generation request to the Cockpit
- HSM Generation: Backend HSM generates key
- Receive UUID: Cockpit returns key UUID
- Create Handle: Map UUID to PKCS#11 handle
- Return Handle: Return handle to Oracle
Encryption Flow
Sequence
Encryption flow
Only the master-key path reaches the Cockpit. Bulk table/tablespace AES crypto stays local (AES-NI).
Steps:
- Oracle calls C_Encrypt() / C_WrapKey(): Request a wrap on the master-key path (e.g. protecting a tablespace key)
- Handle Lookup: Find UUID for provided master key handle
- Parse Mechanism: Extract algorithm (AES-CBC / AES-CBC-PAD) and IV
- Build Request: Create wrap request
- API Call: Send the wrap request to the Cockpit
- HSM Wrap: Backend HSM performs the length-preserving AES-CBC(-PAD) wrap
- Receive Wrapped Key: Get wrapped data
- Return Result: Return to Oracle
Note: The wrap uses a length-preserving AES-CBC / AES-CBC-PAD mechanism. An expanding AES-GCM envelope must not be used on this path — it breaks Oracle's SET KEY with ORA-00600 [kcbtse_populate_tbskey_1]. Bulk table and tablespace encryption is performed locally by Oracle using AES-NI and never leaves the database.
Decryption Flow
Sequence
Decryption flow
Only the master-key path reaches the Cockpit. Bulk table/tablespace AES crypto stays local (AES-NI).
Steps:
- Oracle calls C_Decrypt() / C_UnwrapKey(): Request an unwrap on the master-key path (e.g. recovering a tablespace key at keystore open /
SET KEY) - Handle Lookup: Find UUID for provided master key handle
- Parse Mechanism: Extract algorithm (AES-CBC / AES-CBC-PAD) and IV
- Build Request: Create unwrap request
- API Call: Send the unwrap request to the Cockpit
- HSM Unwrap: Backend HSM performs the length-preserving AES-CBC(-PAD) unwrap
- Receive Tablespace Key: Get the unwrapped key
- Return Result: Return to Oracle
Object Search Flow
Sequence
Object search flow
The search runs in Cockpit; the PKCS#11 layer maps the returned UUIDs to handles and keeps the search state locally.
Steps:
- C_FindObjectsInit(): Initialize search with template
- Parse Template: Extract search criteria (label, class, etc.)
- C_FindObjects(): Execute search
- API Call: Send the object-search request to the Cockpit
- Receive UUIDs: Get matching object UUIDs
- Create Handles: Map UUIDs to handles
- Return Handles: Return handle array to Oracle
- C_FindObjectsFinal(): Clean up search state
Error Handling Flow
Network Error Handling
Sequence
Network error handling
A timeout is retried with exponential backoff; a network error, or a retry that still fails at the max-retry limit, returns CKR_DEVICE_ERROR.
Authentication Error Handling
Sequence
Authentication error handling
Cockpit validates the access_token on every request; a rejected token surfaces as CKR_PIN_INCORRECT and is not retried.
Note: The access_token is a single static bearer credential (distinct from the non-secret access_guid routing id in server_url). There is no token endpoint and no refresh cycle, so a rejected token is a terminal error (check access_token in pkcs11.toml) rather than something the library retries.
HSM Error Handling
Flowchart
HSM error handling
The SDK layer maps each backend outcome to the matching PKCS#11 return code.
Performance Optimization
Connection Reuse
State machine
Connection reuse
After the first request the connection is cached; subsequent requests reuse the cached connection.
Benefits:
- Eliminates TCP handshake overhead
- Reduces connection establishment time
- Improves overall throughput
Bearer Token
The library authenticates every request with an access_token bearer credential from pkcs11.toml. The access_guid embedded in the app proxy server_url is a separate, non-secret routing id. There is no token endpoint and no refresh cycle: the same access_token is presented on each request and validated server-side by the Cockpit, which resolves the tenant from (app_id, access_guid).
Sequence
Bearer token authentication
The same access_token is presented on each request; Cockpit validates it and resolves the tenant from app_id and access_guid.
Benefits:
- No token-exchange round trips
- No runtime secret to rotate (no
client_id/client_secret) - Connection keep-alive reduces per-operation TLS handshakes
Handle Caching
Flowchart
Handle caching
A cached UUID returns its handle directly; a new UUID is assigned a handle and stored before use.
Benefits:
- Avoids duplicate API calls
- Faster handle resolution
- Reduced network traffic
Monitoring and Debugging
Request Tracing
Enable debug logging to trace requests:
export DKE_PKCS11_LOGGING_LEVEL=debug
export DKE_PKCS11_LOGGING_FOLDER=/var/log/dke-pkcs11
Log Output:
[2025-12-19 10:30:45] [DEBUG] C_Initialize() called
[2025-12-19 10:30:45] [DEBUG] Reading pkcs11.toml (server_url, access_token)
[2025-12-19 10:30:45] [INFO] Connecting to DuoKey Cockpit: https://cockpit-api-dev.duokey.cloud
[2025-12-19 10:30:46] [INFO] access_token bearer credential validated by Cockpit
[2025-12-19 10:30:46] [DEBUG] C_Initialize() completed: CKR_OK
Performance Metrics
Monitor key metrics:
- Request Latency: Time from Oracle call to response
- API Latency: Time for DuoKey Cockpit API calls
- Error Rate: Percentage of failed requests
- Auth Failures: Count of rejected
access_tokenbearer credentials
Network Monitoring
Monitor network traffic:
- HTTPS Connections: Number of active connections
- Request/Response Sizes: Payload sizes
- Retry Count: Number of retries per request
- Timeout Events: Frequency of timeouts
Best Practices
Error Handling
- Retry Transient Errors: Network errors, timeouts
- Don't Retry Auth Errors: Invalid credentials
- Log All Errors: For troubleshooting
- Return Appropriate Codes: Translate to PKCS#11 codes
Performance
- Reuse Connections: Use connection pooling
- Keep Connections Alive: Amortize TLS handshakes across operations
- Batch Operations: When possible (future)
- Monitor Latency: Track performance metrics
Security
- Use TLS: All connections encrypted
- Validate Certificates: Strict certificate validation
- Secure Credentials: Never log the
access_token(or theaccess_guid, unnecessarily) - Protect pkcs11.toml: Treat the
access_tokenas a secret; restrict file permissions. Theaccess_guidis not secret by itself but still identifies the app, so protect the whole file
Next Steps
- Architecture Overview → - Understand the overall architecture
- PKCS#11 Interface Layer → - Learn about the interface layer
- DuoKey SDK Layer → - Understand API communication