API Dynamic Architecture#
Dynamic View
|
status: invalid
security: YES
safety: QM
|
||||
Dynamic interactions for typical crypto operations. |
|||||
Typical Usage Flow#
The standard interaction sequence for performing a cryptographic operation:
Pre-Deployed Key Flow (Slot-Direct Path)#
Using a pre-deployed persistent key for encryption — the simplest path.
No LoadKey or guard needed; the context internally loads from the slot:
// 1. Create stack and context
CryptoStackConfig stack_config;
stack_config.SetConnectionEndpoint("unix:///var/run/crypto-daemon.sock");
auto stack = CreateCryptoStack(stack_config).value();
auto ctx = stack->CreateCryptoContext().value();
// 2. Resolve the pre-deployed key slot (no LoadKey needed)
auto slot = ctx->ResolveResource("PreDeployedSlot", ResourceType::kKeySlot).value();
// 3. Create cipher context — pass slot directly to SetKey
// The context factory internally loads key material from the slot.
CipherContextConfig enc_config;
enc_config.SetAlgorithm("AES-256-CBC").SetKey(slot).SetDirection(CipherDirection::kEncrypt);
auto enc = ctx->CreateCipherContext(enc_config).value();
// 4. Encrypt data
enc->Init(iv_span);
enc->Update(plaintext_span, ciphertext_span);
enc->Finalize(final_out_span);
// 5. Context destruction releases the internally-loaded key material.
Pre-Deployed Key Flow (Guard Path — Multi-Context Reuse)#
When the same key must be used across multiple contexts simultaneously,
use LoadKey() to get a CryptoResourceGuard:
// 1. Resolve slot and load key explicitly
auto slot = ctx->ResolveResource("PreDeployedSlot", ResourceType::kKeySlot).value();
auto key_mgmt = ctx->CreateKeyManagementContext(KeyManagementContextConfig{}).value();
auto key_guard = key_mgmt->LoadKey(slot).value();
// key_guard is a CryptoResourceGuard wrapping type == kKey
// 2. Query key slot metadata
auto info = key_mgmt->GetKeySlotInfo(slot).value();
// info == {kOccupied, "AES-256", provider=2, compatible=[2,5]}
// 3. Use the same loaded key in two contexts — implicit conversion
CipherContextConfig enc_config;
enc_config.SetAlgorithm("AES-256-CBC").SetKey(key_guard).SetDirection(CipherDirection::kEncrypt);
auto enc = ctx->CreateCipherContext(enc_config).value();
CipherContextConfig dec_config;
dec_config.SetAlgorithm("AES-256-CBC").SetKey(key_guard).SetDirection(CipherDirection::kDecrypt);
auto dec = ctx->CreateCipherContext(dec_config).value();
// 4. Use both contexts...
// 5. ~key_guard releases the loaded key material via ReleaseResource()
Ephemeral Key Generation and Use#
Generating an ephemeral key, using it, and optionally persisting:
// Generate ephemeral key (returns CryptoResourceGuard)
auto key_mgmt = ctx->CreateKeyManagementContext(KeyManagementContextConfig{}).value();
auto eph_key = key_mgmt->GenerateKey(GenerateKeyParams{}
.SetAlgorithm("AES-256")
.SetPermissions(KeyOperationPermission::kEncrypt | KeyOperationPermission::kDecrypt)).value();
// eph_key is a CryptoResourceGuard wrapping:
// type == ResourceType::kKey
// persistence == ResourcePersistence::kEphemeral
// permitted operations == kEncrypt | kDecrypt
// Use immediately in an operation — implicit conversion to const CryptoResourceId&
CipherContextConfig config;
config.SetAlgorithm("AES-256-GCM").SetKey(eph_key).SetDirection(CipherDirection::kEncrypt);
auto enc = ctx->CreateCipherContext(config).value();
// ... encrypt data ...
// Optionally persist for future use
auto target = ctx->ResolveResource("MyNewSlot", ResourceType::kKeySlot).value();
key_mgmt->PersistKey(target, eph_key); // copy semantics: eph_key guard stays active
// Use target (kKeySlot handle) for all future durable operations
Hashing Example#
HashContextConfig hash_config;
hash_config.SetAlgorithm("SHA-256");
auto hash = ctx->CreateHashContext(hash_config).value();
// Streaming
hash->Init();
hash->Update(chunk1);
hash->Update(chunk2);
auto bytes_written = hash->Finalize(digest_out).value();
// Or single-shot
auto bytes = hash->SingleShot(input, digest_out).value();
Context Reuse via Reset()#
// Create the context once — expensive (factory + IPC)
HashContextConfig hash_config;
hash_config.SetAlgorithm("SHA-256");
auto hash = ctx->CreateHashContext(hash_config).value();
// First message
hash->Init();
hash->Update(message1);
auto n1 = hash->Finalize(digest1).value();
// Reuse — cheap (single IPC call, no factory overhead)
hash->Reset();
// Second message with the same context
hash->Init();
hash->Update(message2);
auto n2 = hash->Finalize(digest2).value();
// Can also abort mid-stream and restart
hash->Init();
hash->Update(partial_data);
hash->Reset(); // discard partial work
hash->Init();
hash->Update(correct_data);
auto n3 = hash->Finalize(digest3).value();
Signing with PQC Algorithm#
// Generate ML-DSA-65 key pair (returns CryptoResourceGuard)
auto key_mgmt = ctx->CreateKeyManagementContext(KeyManagementContextConfig{}).value();
auto signing_key = key_mgmt->GenerateKey(GenerateKeyParams{}.SetAlgorithm("ML-DSA-65")).value();
// Sign data — implicit conversion passes guard to SetKey
SignContextConfig sign_config;
sign_config.SetAlgorithm("ML-DSA-65").SetKey(signing_key);
auto signer = ctx->CreateSignContext(sign_config).value();
auto sig_size = signer->GetSignatureSize(); // ~3293 bytes for ML-DSA-65
signer->Init();
signer->Update(message);
auto sig_len = signer->SignFinalize(signature_buf).value();
// ~signing_key releases the ephemeral key pair
Certificate Verification#
// Resolve certificate and verification trust store
auto cert = ctx->ResolveResource("DeviceCert", ResourceType::kCertSlot).value();
auto anchor = ctx->ResolveResource("RootCA", ResourceType::kVerificationTrustStore).value();
// Verify using builder-style context
CertificateVerificationContextConfig verify_cfg;
auto verifier = ctx->CreateCertificateVerificationContext(verify_cfg).value();
verifier->SetCertificate(cert);
verifier->SetVerificationTrustStore(anchor);
verifier->SetRevocationCheckPolicy(RevocationCheckPolicy::kCrlOnly);
auto result = verifier->Verify().value();
if (result == CertVerifyResult::kValid) {
// Extract public key for use — returns CryptoResourceGuard
auto [pub_key, alg] = cert_mgmt->LoadCertificatePublicKey(cert).value();
// pub_key is a CryptoResourceGuard; use via implicit conversion to const CryptoResourceId&
// ~pub_key releases the ephemeral key when it goes out of scope
}
Key Operation Permissions#
Enforcing least-privilege on cryptographic keys:
// 1. Generate an encryption-only key (cannot be used for signing)
auto key_mgmt = ctx->CreateKeyManagementContext(KeyManagementContextConfig{}).value();
auto enc_key = key_mgmt->GenerateKey(GenerateKeyParams{}
.SetAlgorithm("AES-256")
.SetPermissions(KeyOperationPermission::kEncrypt | KeyOperationPermission::kDecrypt)).value();
// 2. Encryption works — key has kEncrypt permission
CipherContextConfig enc_config;
enc_config.SetAlgorithm("AES-256-CBC").SetKey(enc_key).SetDirection(CipherDirection::kEncrypt);
auto enc = ctx->CreateCipherContext(enc_config).value(); // OK
// 3. Signing is rejected — key lacks kSign permission
SignContextConfig sign_config;
sign_config.SetAlgorithm("HMAC-SHA-256").SetKey(enc_key);
auto sign_result = ctx->CreateSignContext(sign_config);
// sign_result.error() == kKeyOperationNotPermitted
// 4. Query permissions from a key slot
auto slot = ctx->ResolveResource("SigningKey", ResourceType::kKeySlot).value();
auto slot_obj = ctx->GetKeySlotObject(slot).value();
auto perms = slot_obj->GetPermittedOperations();
if (HasPermission(perms, KeyOperationPermission::kSign)) {
// Key slot allows signing
}
// 5. Use composite presets for common patterns
auto auth_key = key_mgmt->GenerateKey(GenerateKeyParams{}
.SetAlgorithm("ECDSA-P256")
.SetPermissions(KeyOperationPermission::kAuthentication)).value();
// auth_key can sign, verify, MAC, and agree — but cannot encrypt or wrap
Operation Timeout Configuration#
Bounding all IPC calls with a per-call deadline for safety analysis:
// 1. Stack-wide default: 500 ms per IPC call
CryptoStackConfig stack_config;
stack_config.SetConnectionEndpoint("unix:///var/run/crypto-daemon.sock")
.SetDefaultOperationTimeout(std::chrono::milliseconds{500});
auto stack = CreateCryptoStack(stack_config).value();
auto ctx = stack->CreateCryptoContext().value();
// 2. Per-context override: tighter 200 ms deadline for hashing
HashContextConfig hash_cfg;
hash_cfg.SetAlgorithm("SHA-256")
.SetOperationTimeout(std::chrono::milliseconds{200});
auto hash = ctx->CreateHashContext(hash_cfg).value();
// Each Init(), Update(), Finalize() has its own 200 ms deadline.
hash->Init(); // ≤ 200 ms or kOperationTimedOut
hash->Update(chunk1); // ≤ 200 ms or kOperationTimedOut
auto result = hash->Finalize(digest_out);
if (!result.has_value()) {
// On timeout: context is in error state, must destroy and recreate.
// result.error() == kOperationTimedOut
}
// 3. Disable timeout for slow PQC key generation on HSM
KeyManagementContextConfig keygen_cfg;
keygen_cfg.DisableTimeout(); // No deadline — HSM may take seconds
auto key_mgmt = ctx->CreateKeyManagementContext(keygen_cfg).value();
auto pqc_key = key_mgmt->GenerateKey(GenerateKeyParams{}.SetAlgorithm("ML-KEM-768")).value();
// PQC key generation can take seconds on hardware — no timeout error