{"record":{"id":"47dbe48076a93a38","repo":"embassy-rs/embassy","slug":"the-pka-is-in-use","errorCode":null,"errorMessage":"the PKA is in use","messagePattern":"the PKA is in use","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-stm32/src/pka/driver.rs","lineNumber":54,"sourceCode":"use super::EccProjectivePoint;\nuse super::{EccPoint, EcdsaCurveParams, EcdsaPublicKey, EcdsaSignature, Error, Pka};\nuse crate::mode::Blocking;\nuse crate::suspend::ResumablePeripheral;\n\nforeach_peripheral!(\n    (pka, $inst:ident) => {\n        type BlockingPka = Pka<'static, crate::peripherals::$inst, Blocking>;\n\n        static DRIVER: Mutex<CriticalSectionRawMutex, ResumablePeripheral<BlockingPka>> =\n            Mutex::new(ResumablePeripheral::new_suspended(unsafe { crate::peripherals::$inst::steal() }));\n    };\n);\n\n/// Runs `f` with the engine enabled and initialized.\nfn with_pka<R>(f: impl FnOnce(&mut BlockingPka) -> R) -> R {\n    #[cfg(feature = \"embassy-crypto-rng\")]\n    crate::rng::driver::ensure_running();\n    let mut driver = DRIVER.try_lock().expect(\"the PKA is in use\");\n    let mut pka = driver.borrow();\n    #[cfg(any(pka_v1a, pka_n6))]\n    assert!(\n        !pka.is_limited(),\n        \"the PKA of this chip only verifies ECDSA signatures (limited mode)\"\n    );\n    f(&mut pka)\n}\n\n/// How many nonces ECDSA signing tries before giving up on the hardware.\nconst SIGN_ATTEMPTS: usize = 8;\n\n/// Montgomery constants of an odd big-endian modulus of exactly `L` limbs.\nconst fn monty<const L: usize>(n_be: &[u8]) -> FixedMontyParams<L> {\n    FixedMontyParams::new_vartime(Uint::from_be_slice(n_be).to_odd().expect_copied(\"odd modulus\"))\n}\n\n/// Big-endian bytes to an integer, `N == L * Limb::BYTES`.","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-stm32/src/pka/driver.rs#L36-L72","documentation":"The PKA driver wraps the hardware public-key accelerator in a global Mutex (DRIVER). with_pka uses try_lock().expect(\"the PKA is in use\"), so any attempt to run a PKA operation while another context already holds the accelerator panics rather than blocking. Like the AES driver, this enforces single-owner access to the peripheral.","triggerScenarios":"Calling public_key, shared_secret, sign, or verify while another task/ISR is executing a PKA operation; e.g. performing an ECDH key exchange and an ECDSA signature concurrently, or calling sign from an interrupt while a task verifies.","commonSituations":"TLS/embedded protocols spawning concurrent crypto tasks; calling PKA operations from both an ISR and the main loop; reentrant helper libraries that both use the PKA driver.","solutions":["Serialize PKA operations through a single task or an application-level async Mutex so calls never overlap.","Avoid calling PKA operations (sign/verify/shared_secret) from interrupt context.","Structure protocols so crypto steps complete before starting others (await the result first).","Keep the driver's guard scope minimal; do not hold BlockingPka across long waits."],"exampleFix":"// before\nlet sig = pka.sign(&key, &hash).await;\nspawn(async move { pka.verify(...).await }); // may overlap -> panic\n\n// after\nlet sig = pka.sign(&key, &hash).await;\npka.verify(&key, &hash, &sig).await; // sequential on same task","handlingStrategy":"try-catch","validationCode":"// Serialize PKA usage at the application level:\nstatic PKA_BUSY: AtomicBool = AtomicBool::new(false);\nfn pka_free() -> bool { !PKA_BUSY.load(Ordering::Acquire) }","typeGuard":"fn can_use_pka() -> bool {\n    !PKA_BUSY.load(core::sync::atomic::Ordering::Acquire)\n}","tryCatchPattern":"// Prevent instead of catch (embedded panics abort):\nstatic PKA: Mutex<CriticalSectionRawMutex, Pka<'static>> = Mutex::new(Pka::new());\nasync fn with_pka_app<T>(f: impl FnOnce(&Pka<'static>) -> T) -> T {\n    let p = PKA.lock().await;\n    f(&p)\n}","preventionTips":["Run all PKA operations (sign/verify/shared_secret) from one task or through an app-level async Mutex.","Never invoke PKA operations from ISR context.","Await each crypto operation to completion before starting the next."],"tags":["embedded","stm32","pka","crypto","concurrency","panic"],"backgroundTag":"internal-invariant-violation","analyzedSha":"463a07b963419a1bfe61d5d597c44acb810afb8b","analyzedAt":"2026-09-10T13:38:26.660Z","contentChangedAt":"2026-09-10T13:38:26.660Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}