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.
API reference: Detailed API endpoints and request/response formats are documented separately in the Developer Docs.
Overview
Oracle calls flow left-to-right to the backend HSM; responses return along the same path.
Typical Operation Flow
Initialization Flow
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
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
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
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
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
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
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
This flow is kept as a sequence diagram because it has nested retry branching (timeout → backoff → retry → success or max-retries) that a linear diagram cannot represent faithfully.
Authentication Error Handling
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
The SDK layer maps each backend outcome to the matching PKCS#11 return code.
Performance Optimization
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).
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
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