Skip to content

Commit 034c1fe

Browse files
committed
- Updated Critical Findings and Resolutions session of the design document.
- Ran cargo fmt.
1 parent 0abdd60 commit 034c1fe

File tree

2 files changed

+60
-41
lines changed

2 files changed

+60
-41
lines changed

docs/src/hash-driver-hubris.md

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Generic Digest Server Design Document
22

3+
This document describes the design and architecture of a generic digest server for Hubris OS that supports both SPDM and PLDM protocol implementations.
4+
35
## Requirements
46

57
### Primary Requirement
@@ -16,7 +18,7 @@
1618

1719
#### R2: Session Management
1820
- **R2.1**: Support incremental hash computation for large certificate chains and firmware images
19-
- **R2.2**: Support multiple concurrent digest sessions (≥8 concurrent operations)
21+
- **R2.2**: Support multiple concurrent digest sessions (hardware-dependent capacity)
2022
- **R2.3**: Provide session isolation between different SPDM and PLDM protocol flows
2123
- **R2.4**: Automatic session cleanup to prevent resource exhaustion
2224
- **R2.5**: Session timeout mechanism for abandoned operations
@@ -61,9 +63,9 @@
6163
- **R8.3**: Digest server fails fast on unrecoverable hardware errors rather than returning complex error states
6264
- **R8.4**: Support debugging via jefe external interface during development
6365

64-
## Implementation Overview
66+
## Design Overview
6567

66-
This digest server has been successfully converted to a generic implementation that can work with any device implementing the required digest traits from `openprot-hal-blocking`.
68+
This digest server provides a generic implementation that can work with any device implementing the required digest traits from `openprot-hal-blocking`. The design supports both single-context and multi-context hardware through hardware-adaptive session management.
6769

6870
## Architecture
6971

@@ -108,7 +110,7 @@ ServerImpl<D>
108110
├── Generic Type Parameter D
109111
│ └── Trait Bounds: DigestInit<Sha2_256/384/512>
110112
├── Session Management
111-
│ ├── Static session storage (MAX_SESSIONS = 8)
113+
│ ├── Static session storage (hardware-dependent capacity)
112114
│ ├── Session lifecycle (init → update → finalize)
113115
│ └── Automatic timeout and cleanup
114116
└── Hardware Abstraction
@@ -493,7 +495,7 @@ impl DigestHardwareCapabilities for Ast1060HashDevice {
493495

494496
// Example hypothetical multi-context implementation
495497
impl DigestHardwareCapabilities for HypotheticalMultiContextDevice {
496-
const MAX_CONCURRENT_SESSIONS: usize = 8; // Multiple contexts supported
498+
const MAX_CONCURRENT_SESSIONS: usize = 16; // Hardware-dependent capacity
497499
const SUPPORTS_HARDWARE_CONTEXT_SWITCHING: bool = true;
498500
}
499501

@@ -559,15 +561,18 @@ impl DigestOp for MyDigestContext<'_> {
559561
**Single-Context Hardware (ASPEED HACE):**
560562
```
561563
Client A calls init_sha256() → Blocks until complete → Returns session_id
562-
Client B calls init_sha384() → Blocks waiting for A to finish → Eventually proceeds
563-
Client C calls update() → Blocks waiting for B to finish → Eventually proceeds
564+
Client B calls init_sha384() → Blocks waiting for A to finish → Still blocked
565+
Client A calls update(session_id) → Blocks until complete → Returns success
566+
Client B calls update(session_id) → Still blocked waiting for A to finalize
567+
Client A calls finalize() → Releases hardware → Client B can now proceed
564568
```
565569

566570
**Multi-Context Hardware (Hypothetical):**
567571
```
568572
Client A calls init_sha256() → Creates session context → Returns immediately
569573
Client B calls init_sha384() → Creates different context → Returns immediately
570-
Client C calls update() → Uses appropriate context → Returns immediately
574+
Client A calls update(session_id) → Uses session context → Returns immediately
575+
Client B calls update(session_id) → Uses different context → Returns immediately
571576
```
572577

573578
#### Session Management Flow (Hardware-Dependent)
@@ -645,14 +650,22 @@ graph TB
645650
```
646651

647652
#### Hardware Capability Detection
653+
654+
The digest server adapts to different hardware capabilities through compile-time trait bounds:
655+
648656
```rust
649657
pub trait DigestHardwareCapabilities {
650-
const MAX_CONCURRENT_SESSIONS: usize;
658+
const MAX_CONCURRENT_SESSIONS: usize; // Hardware-dependent: 1 for single-context, 16+ for multi-context
651659
const SUPPORTS_CONTEXT_SWITCHING: bool;
652660
const MAX_UPDATE_SIZE: usize;
653661
}
654662
```
655663

664+
Examples of hardware-specific session limits:
665+
- **ASPEED AST1060**: `MAX_CONCURRENT_SESSIONS = 1` (single hardware context)
666+
- **Multi-context accelerators**: `MAX_CONCURRENT_SESSIONS = 16` (or higher based on hardware design)
667+
- **Software implementations**: Can support many concurrent sessions limited by memory
668+
656669
#### Session Management Strategy
657670
- **Single-context platforms**: Direct hardware operations, no session state
658671
- **Multi-context platforms**: Full session management with context switching
@@ -752,7 +765,7 @@ sequenceDiagram
752765
participant DS as Digest Server
753766
participant HW as Multi-Context Hardware
754767
755-
Note over DS: MAX_SESSIONS = 8, all contexts active
768+
Note over DS: Hardware capacity reached, all contexts active
756769
757770
S2->>DS: init_sha256()
758771
DS->>DS: find_free_hardware_context()
@@ -1311,7 +1324,7 @@ impl PldmFirmwareUpdate {
13111324
// Component 3: FPGA bitstream using SHA-512
13121325
let fpga_session = digest.init_sha512()?; // R1.3: SHA-512 support
13131326

1314-
// All components can be updated concurrently (up to 8 total - R2.2)
1327+
// All components can be updated concurrently (hardware-dependent capacity - R2.2)
13151328
// Each maintains independent digest state (R2.3: isolation)
13161329

13171330
// Store sessions for component tracking
@@ -1335,7 +1348,7 @@ impl PldmFirmwareUpdate {
13351348
| **R1.3** SHA-512 support || `init_sha512()`, `finalize_sha512()` with hardware context |
13361349
| **R1.4** Reject unsupported algorithms || SHA-3 functions return `UnsupportedAlgorithm` |
13371350
| **R2.1** Incremental hash computation || True streaming via `update_hardware_context()` |
1338-
| **R2.2** Multiple concurrent sessions || `MAX_SESSIONS = 8` with context switching |
1351+
| **R2.2** Multiple concurrent sessions || Hardware-dependent capacity with context switching |
13391352
| **R2.3** Session isolation || Independent hardware contexts in non-cacheable RAM |
13401353
| **R2.4** Automatic cleanup || `cleanup_expired_sessions()` with context cleanup |
13411354
| **R2.5** Session timeout || `SESSION_TIMEOUT_TICKS` with hardware context release |
@@ -1373,7 +1386,7 @@ The `ServerImpl<D>` struct is now generic over any device `D` that implements:
13731386
3. **Type Safety**: Associated type constraints ensure digest output sizes match expectations
13741387
4. **Zero Runtime Cost**: Uses static dispatch for optimal performance
13751388
5. **Memory Efficient**: Static session storage with hardware context simulation
1376-
6. **Concurrent Sessions**: Up to 8 concurrent digest operations with automatic context switching
1389+
6. **Concurrent Sessions**: Hardware-dependent concurrent digest operations with automatic context switching
13771390

13781391
## Usage Example
13791392

@@ -1432,7 +1445,11 @@ impl MyDigestDevice {
14321445
let server = ServerImpl::new(MyDigestDevice::new());
14331446
```
14341447

1435-
## Critical Findings
1448+
---
1449+
1450+
# Implementation Status and Development Notes
1451+
1452+
## Critical Findings and Resolutions
14361453

14371454
### Trait Lifetime Incompatibility with Session-Based Operations - RESOLVED
14381455

hal/blocking/src/digest.rs

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ use zerocopy::{FromBytes, Immutable, IntoBytes};
127127
/// fn process_digest(digest: Digest<8>) -> [u32; 8] {
128128
/// digest.into_array() // Safe, direct conversion
129129
/// }
130-
///
130+
///
131131
/// // ❌ OPAQUE: We don't know what D::Output actually is
132132
/// // fn process_generic<D>(output: D::Output) -> /* Unknown type */ {
133133
/// // // Cannot convert to [u32; 8] safely
@@ -140,7 +140,7 @@ use zerocopy::{FromBytes, Immutable, IntoBytes};
140140
/// ```rust
141141
/// # use openprot_hal_blocking::digest::Digest;
142142
/// let digest = Digest::<8> { value: [1, 2, 3, 4, 5, 6, 7, 8] };
143-
///
143+
///
144144
/// // Safe conversions - no unsafe code needed
145145
/// let array: [u32; 8] = digest.into_array(); // Owned conversion
146146
/// let array_ref: &[u32; 8] = digest.as_array(); // Borrowed conversion
@@ -170,7 +170,7 @@ use zerocopy::{FromBytes, Immutable, IntoBytes};
170170
/// sha256_results: Vec<Digest<8>>, // Can store concrete types
171171
/// sha384_results: Vec<Digest<12>>, // Different sizes supported
172172
/// }
173-
///
173+
///
174174
/// impl DigestCache {
175175
/// fn store_sha256(&mut self, digest: Digest<8>) {
176176
/// self.sha256_results.push(digest); // Direct storage
@@ -188,10 +188,10 @@ use zerocopy::{FromBytes, Immutable, IntoBytes};
188188
/// ```rust
189189
/// # use openprot_hal_blocking::digest::Digest;
190190
/// let digest = Digest::<8> { value: [1, 2, 3, 4, 5, 6, 7, 8] };
191-
///
191+
///
192192
/// // Zero-copy byte access via zerocopy traits
193193
/// let bytes: &[u8] = zerocopy::IntoBytes::as_bytes(&digest);
194-
///
194+
///
195195
/// // Safe transmutation between compatible layouts
196196
/// // (enabled by FromBytes + Immutable derives)
197197
/// ```
@@ -220,10 +220,10 @@ use zerocopy::{FromBytes, Immutable, IntoBytes};
220220
/// value: [0x12345678, 0x9abcdef0, 0x11111111, 0x22222222,
221221
/// 0x33333333, 0x44444444, 0x55555555, 0x66666666],
222222
/// };
223-
///
223+
///
224224
/// // Safe conversion to array for IPC
225225
/// let array = sha256_digest.into_array();
226-
///
226+
///
227227
/// // Access as bytes for serialization
228228
/// let bytes = sha256_digest.as_bytes();
229229
/// assert_eq!(bytes.len(), 32);
@@ -860,53 +860,55 @@ mod tests {
860860
let sha256_digest = Digest::<8> {
861861
value: [1, 2, 3, 4, 5, 6, 7, 8],
862862
};
863-
863+
864864
// Test into_array() method
865865
let array = sha256_digest.into_array();
866866
assert_eq!(array, [1, 2, 3, 4, 5, 6, 7, 8]);
867-
867+
868868
// Test as_array() method
869869
let sha256_digest = Digest::<8> {
870870
value: [1, 2, 3, 4, 5, 6, 7, 8],
871871
};
872872
let array_ref = sha256_digest.as_array();
873873
assert_eq!(array_ref, &[1, 2, 3, 4, 5, 6, 7, 8]);
874-
874+
875875
// Test as_bytes() method
876876
let bytes = sha256_digest.as_bytes();
877877
assert_eq!(bytes.len(), 32); // 8 words * 4 bytes each
878-
878+
879879
// Verify the bytes match the expected layout (little endian)
880880
let expected_bytes = [
881-
1, 0, 0, 0, // word 1
882-
2, 0, 0, 0, // word 2
883-
3, 0, 0, 0, // word 3
884-
4, 0, 0, 0, // word 4
885-
5, 0, 0, 0, // word 5
886-
6, 0, 0, 0, // word 6
887-
7, 0, 0, 0, // word 7
888-
8, 0, 0, 0, // word 8
881+
1, 0, 0, 0, // word 1
882+
2, 0, 0, 0, // word 2
883+
3, 0, 0, 0, // word 3
884+
4, 0, 0, 0, // word 4
885+
5, 0, 0, 0, // word 5
886+
6, 0, 0, 0, // word 6
887+
7, 0, 0, 0, // word 7
888+
8, 0, 0, 0, // word 8
889889
];
890890
assert_eq!(bytes, &expected_bytes);
891891
}
892892

893893
#[test]
894894
fn test_output_type_sizes() {
895895
use core::mem;
896-
896+
897897
// Verify that digest output types have correct sizes for IPC
898-
assert_eq!(mem::size_of::<Digest<8>>(), 32); // SHA-256: 8 words * 4 bytes
899-
assert_eq!(mem::size_of::<Digest<12>>(), 48); // SHA-384: 12 words * 4 bytes
900-
assert_eq!(mem::size_of::<Digest<16>>(), 64); // SHA-512: 16 words * 4 bytes
901-
898+
assert_eq!(mem::size_of::<Digest<8>>(), 32); // SHA-256: 8 words * 4 bytes
899+
assert_eq!(mem::size_of::<Digest<12>>(), 48); // SHA-384: 12 words * 4 bytes
900+
assert_eq!(mem::size_of::<Digest<16>>(), 64); // SHA-512: 16 words * 4 bytes
901+
902902
// Test alignment requirements
903-
assert_eq!(mem::align_of::<Digest<8>>(), 4); // Aligned to u32
903+
assert_eq!(mem::align_of::<Digest<8>>(), 4); // Aligned to u32
904904
}
905905

906906
#[test]
907907
fn test_digest_new_constructor() {
908-
let array = [0x12345678, 0x9abcdef0, 0x11111111, 0x22222222,
909-
0x33333333, 0x44444444, 0x55555555, 0x66666666];
908+
let array = [
909+
0x12345678, 0x9abcdef0, 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555,
910+
0x66666666,
911+
];
910912
let digest = Digest::new(array);
911913
assert_eq!(digest.value, array);
912914
assert_eq!(digest.into_array(), array);

0 commit comments

Comments
 (0)