src/pqc_enclave_sdk/backends/qsee.py
| 1 | """Qualcomm Secure Execution Environment (QSEE) backend (stub interface). |
| 2 | |
| 3 | Real integration uses Qualcomm's QSEE trusted application framework on |
| 4 | Snapdragon SoCs. This stub documents the expected shape; OEMs plug in |
| 5 | their signed Trusted App (TA) running inside the QSEE enclave. |
| 6 | |
| 7 | A production implementation of this backend is expected to: |
| 8 | |
| 9 | * Load a signed Trusted Application into QSEE via ``QSEECom_start_app``. |
| 10 | The TA implements session-key wrapping + AES-GCM on the secure side and |
| 11 | is the only code that ever touches the plaintext symmetric key. |
| 12 | * For :meth:`store_session_key`, send the 32-byte key over the QSEECom |
| 13 | SMC channel wrapped with a TA-resident KEK; persist the wrapped blob |
| 14 | in Android Keystore with the TA's key alias. |
| 15 | * For :meth:`load_session_key`, issue a QSEECom request that asks the TA |
| 16 | to unwrap into its own memory and return a session handle (not the raw |
| 17 | key). The vault then feeds ciphertext into the TA for decryption. |
| 18 | * For :meth:`save_artifacts` / :meth:`load_artifacts`, write the |
| 19 | encrypted artifact store under the app's private data dir; QSEE only |
| 20 | holds the key, not the ciphertext blobs. |
| 21 | * Use Qualcomm's Secure Processor (SPU) on newer Snapdragon parts for |
| 22 | additional isolation of the KEK against side-channel attacks. |
| 23 | |
| 24 | ML-KEM-768 / ML-DSA support is shipping in Qualcomm Crypto Engine |
| 25 | revisions; integrate that path when generating the session KEM keypair |
| 26 | currently done in-process. |
| 27 | """ |
| 28 | |
| 29 | from __future__ import annotations |
| 30 | |
| 31 | from pqc_enclave_sdk.artifact import EncryptedArtifact |
| 32 | from pqc_enclave_sdk.backends.base import EnclaveBackend |
| 33 | from pqc_enclave_sdk.errors import BackendError |
| 34 | |
| 35 | |
| 36 | class QSEEBackend(EnclaveBackend): |
| 37 | """Stub Qualcomm Secure Execution Environment backend. |
| 38 | |
| 39 | Raises :class:`BackendError` when invoked without a signed Trusted |
| 40 | Application loaded into QSEE. |
| 41 | """ |
| 42 | |
| 43 | name = "qualcomm-qsee" |
| 44 | platform = "qsee" |
| 45 | enclave_vendor = "qualcomm-qsee" |
| 46 | |
| 47 | def __init__( |
| 48 | self, |
| 49 | device_id: str = "snapdragon-unknown", |
| 50 | device_model: str = "snapdragon-unknown", |
| 51 | ta_name: str = "com.dyber.pqc.enclave.ta", |
| 52 | ) -> None: |
| 53 | self.device_id = device_id |
| 54 | self.device_model = device_model |
| 55 | self.ta_name = ta_name |
| 56 | |
| 57 | def store_session_key(self, key_id: str, key: bytes, expires_at: str) -> None: |
| 58 | raise BackendError( |
| 59 | "QSEEBackend.store_session_key is a stub. A real implementation " |
| 60 | f"sends the key to the signed Trusted App {self.ta_name!r} loaded " |
| 61 | "into QSEE via QSEECom_start_app + QSEECom_send_cmd." |
| 62 | ) |
| 63 | |
| 64 | def load_session_key(self, key_id: str) -> bytes | None: |
| 65 | raise BackendError( |
| 66 | "QSEEBackend.load_session_key is a stub. A real implementation " |
| 67 | f"asks the {self.ta_name!r} TA to unwrap key {key_id} inside QSEE " |
| 68 | "and returns only a session handle, never the raw bytes." |
| 69 | ) |
| 70 | |
| 71 | def save_artifacts(self, artifacts: dict[str, EncryptedArtifact]) -> None: |
| 72 | raise BackendError( |
| 73 | "QSEEBackend.save_artifacts is a stub. A real implementation writes " |
| 74 | "the encrypted artifacts to the app's private data directory; QSEE " |
| 75 | "only holds the wrapping key, not the ciphertext store." |
| 76 | ) |
| 77 | |
| 78 | def load_artifacts(self) -> dict[str, EncryptedArtifact]: |
| 79 | raise BackendError( |
| 80 | "QSEEBackend.load_artifacts is a stub. A real implementation reads " |
| 81 | "the encrypted artifact file and deserializes it via " |
| 82 | "EncryptedArtifact.from_dict." |
| 83 | ) |
| 84 | |