| # SpdmCertStore Implementation Summary |
| |
| ## Completed Implementation |
| |
| ✅ **File Structure Created:** |
| - `services/spdm/cert-store/src/lib.rs` - Main implementation |
| - `services/spdm/cert-store/BUILD.bazel` - Bazel build configuration |
| - `services/spdm/cert-store/Cargo.toml` - Cargo package manifest |
| - `services/spdm/cert-store/README.md` - Documentation |
| - Updated `Cargo.toml` workspace members |
| |
| ## Implementation Details |
| |
| ### Constants Defined |
| ```rust |
| const CERT_CHAIN_PLACEHOLDER_SIZE: usize = 32; |
| ``` |
| |
| ### Imported Library Constants |
| - `SHA384_HASH_SIZE = 48` (from spdm-lib) |
| - `ECC_P384_SIGNATURE_SIZE = 96` (from spdm-lib) |
| - `ECDSA_P384_PRIVATE_KEY_SIZE = 48` (from crypto-api) |
| |
| ### Struct Definition |
| ```rust |
| pub struct Ast1060CertStore { |
| crypto: CryptoClient, |
| } |
| ``` |
| |
| ### Static Data (Placeholder for Development) |
| - `SLOT_0_CERT_CHAIN: [u8; 32]` = `[0xAA; 32]` |
| - `SLOT_0_ROOT_HASH: [u8; 48]` = `[0xBB; 48]` |
| - `SLOT_0_PRIVATE_KEY: [u8; 48]` = `[0xCC; 48]` |
| |
| ### Trait Implementation: `SpdmCertStore` |
| |
| #### Implemented Methods |
| |
| 1. **`slot_count() -> u8`** |
| - Returns: `2` |
| |
| 2. **`is_provisioned(slot_id: u8) -> bool`** |
| - Returns: `slot_id == 0` |
| |
| 3. **`cert_chain_len(&mut self, asym_algo, slot_id) -> Result<usize>`** |
| - Validates: slot ID, algorithm, provisioning status |
| - Returns: `CERT_CHAIN_PLACEHOLDER_SIZE` (32) |
| |
| 4. **`get_cert_chain(&mut self, slot_id, asym_algo, offset, cert_portion) -> Result<usize>`** |
| - Validates: slot, algorithm, offset |
| - Copies cert data from static array |
| - Zero-fills remaining buffer |
| - Returns: bytes copied |
| |
| 5. **`root_cert_hash(&mut self, slot_id, asym_algo, cert_hash) -> Result<()>`** |
| - Validates: slot and algorithm |
| - Copies pre-calculated hash |
| |
| 6. **`sign_hash(&self, slot_id, hash, signature) -> Result<()>`** |
| - Validates: slot ID |
| - Calls: `crypto.ecdsa_p384_sign(&SLOT_0_PRIVATE_KEY, hash)` |
| - Maps: `ClientError` → `CertStoreError::PlatformError` |
| |
| 7. **`key_pair_id(&self, slot_id) -> Option<u8>`** |
| - Returns: `None` |
| |
| 8. **`cert_info(&self, slot_id) -> Option<CertificateInfo>`** |
| - Returns: `None` |
| |
| 9. **`key_usage_mask(&self, slot_id) -> Option<KeyUsageMask>`** |
| - Returns: `None` |
| |
| ### Error Handling |
| |
| | Condition | Error Returned | |
| |-----------|----------------| |
| | `slot_id >= 2` | `CertStoreError::InvalidSlotId(slot_id)` | |
| | `slot_id == 1` | `CertStoreError::CertReadError` | |
| | `asym_algo != EccP384` | `CertStoreError::UnsupportedHashAlgo` | |
| | `offset >= cert_len` | `CertStoreError::InvalidOffset` | |
| | IPC failure | `CertStoreError::PlatformError` | |
| |
| ### Unit Tests Included |
| |
| ✅ `test_slot_count()` - Verifies 2 slots |
| ✅ `test_is_provisioned()` - Slot 0 provisioned, others not |
| ✅ `test_invalid_slot()` - Rejects invalid slot IDs |
| ✅ `test_unprovisioned_slot()` - Rejects slot 1 |
| ✅ `test_cert_chain_len()` - Returns correct length |
| ✅ `test_get_cert_chain_full()` - Full chain retrieval |
| ✅ `test_get_cert_chain_with_offset()` - Offset reading |
| ✅ `test_get_cert_chain_zero_fill()` - Zero-fill behavior |
| ✅ `test_get_cert_chain_invalid_offset()` - Offset validation |
| ✅ `test_root_hash_copy()` - Hash retrieval |
| ✅ `test_optional_methods_return_none()` - Optional methods |
| |
| ## Build Configuration |
| |
| ### BUILD.bazel |
| ```python |
| rust_library( |
| name = "spdm_cert_store_lib", |
| srcs = glob(["src/**/*.rs"]), |
| crate_name = "openprot_spdm_cert_store", |
| edition = "2024", |
| visibility = ["//visibility:public"], |
| deps = [ |
| "//services/crypto/api:crypto_api", |
| "//services/crypto/client:crypto_client", |
| "@rust_crates//:spdm-lib", |
| ], |
| ) |
| ``` |
| |
| ### Cargo.toml |
| ```toml |
| [dependencies] |
| spdm-lib = { git = "https://github.com/9elements/spdm-lib.git", branch = "buildup" } |
| crypto-client = { path = "../../crypto/client" } |
| crypto-api = { path = "../../crypto/api" } |
| ``` |
| |
| ## Build Notes |
| |
| The library cannot be built standalone using Bazel due to platform constraints: |
| - `crypto-client` depends on `pw_kernel/userspace` |
| - This requires building as part of a full system image with `--platforms=//target/ast1060-evb:ast1060-evb` |
| |
| This is expected and correct - the library is meant to be used by userspace SPDM applications on the target platform. |
| |
| ## Integration Usage |
| |
| To use in an SPDM server application: |
| |
| ```rust |
| use openprot_spdm_cert_store::Ast1060CertStore; |
| use spdm_lib::cert_store::SpdmCertStore; |
| |
| // In your SPDM server init code: |
| let cert_store = Ast1060CertStore::new(handle::CRYPTO); |
| |
| // Pass to SPDM responder |
| let responder = SpdmResponder::new(cert_store, ...); |
| ``` |
| |
| ## Next Steps |
| |
| To verify the implementation: |
| |
| 1. **Create SPDM server application** that uses this cert store |
| 2. **Build system image** with the SPDM server: |
| ```bash |
| bazel build --platforms=//target/ast1060-evb:ast1060-evb \ |
| //target/ast1060-evb/spdm:system_image |
| ``` |
| 3. **Run integration tests** in QEMU or on hardware |
| 4. **Test SPDM protocol operations** (GET_DIGESTS, GET_CERTIFICATE, CHALLENGE) |
| |
| ## Production Deployment |
| |
| Before production use, replace placeholder data: |
| |
| 1. Generate real ECC P-384 key pair |
| 2. Obtain X.509 certificate chain |
| 3. Calculate SHA-384 root hash |
| 4. Update static arrays with `include_bytes!()` |
| 5. Consider secure key storage (OTP/HSM) |
| |
| ## Conformance to Plan |
| |
| ✅ All planned methods implemented |
| ✅ Error handling complete |
| ✅ Unit tests included |
| ✅ Documentation complete |
| ✅ Build configuration correct |
| ✅ Following spdm-lib patterns |
| ✅ IPC integration with crypto service |
| ✅ Placeholder data for development |