Skip to content

Commit 937d859

Browse files
committed
Implemented Suspendable for HKDF and a bunch of other tidy-up.
1 parent e464f68 commit 937d859

23 files changed

Lines changed: 530 additions & 279 deletions

File tree

alpha_0.1.2_release_notes.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,11 @@
4545
* mldsa-lowmemory -- runs in about 1/10th of the usual memory (~ 30 kb of stack) with comparable performance impact.
4646
* mlkem (FIPS 203)
4747
* mlkem-lowmemory -- runs in about 1/4th of the usual memory (~ 12 kb of stack) with comparable performance impact.
48-
* New traits SerializeState and SerializeKeyedState allow algorithms with a streaming API (`do_update()` ->
49-
`do_final()`) to be suspended to a small byte array and then resumed later, potentially from a different host. The
50-
intended use case is if you are processing a large input that depends on one or more network round-trips and you wish
51-
to suspect and potentially transfer to a new host while waiting for network IO.
48+
* New traits [Suspendable] and [SuspendableKeyed] allow algorithms with a streaming API (`do_update()` ->
49+
`do_final()`) to be suspended to a small byte array and then resumed later, potentially from a different host and
50+
potentially across versions of the library. The intended use case is if you are processing a large input that depends
51+
on one or more network round-trips and you wish to suspend to a cache and potentially transfer to a new host while
52+
waiting for network IO.
5253

5354
## Minor features / bug fixes
5455

crypto/core-test-framework/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ pub mod hash;
1313
pub mod kdf;
1414
pub mod kem;
1515
pub mod mac;
16-
pub mod serializable_state;
1716
pub mod signature;
17+
pub mod suspendable_state;
1818

1919
mod fixed_seed_rng;
2020
pub use fixed_seed_rng::FixedSeedRNG;

crypto/core-test-framework/src/serializable_state.rs renamed to crypto/core-test-framework/src/suspendable_state.rs

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
11
use bouncycastle_core::errors::SerializedStateError;
22
use bouncycastle_core::serializable_state::{LIB_VERSION, SemVer};
3-
use bouncycastle_core::traits::{SerializableKeyedState, SerializableState};
3+
use bouncycastle_core::traits::{Suspendable, SuspendableKeyed};
44

5-
pub struct TestFrameworkSerializableState {}
5+
pub struct TestFrameworkSuspendableState {}
66

7-
impl TestFrameworkSerializableState {
7+
impl TestFrameworkSuspendableState {
88
pub fn new() -> Self {
99
Self {}
1010
}
1111

1212
/// Test all the members of trait SerializableState.
1313
///
1414
/// Expects ta be handed an instance of the object that has some in-progress state to be serialized.
15-
pub fn test<
16-
const SERIALIZED_STATE_LEN: usize,
17-
S: SerializableState<SERIALIZED_STATE_LEN> + Clone,
18-
>(
15+
pub fn test<const SERIALIZED_STATE_LEN: usize, S: Suspendable<SERIALIZED_STATE_LEN> + Clone>(
1916
&self,
2017
instance: &S,
2118
) {
@@ -27,10 +24,10 @@ impl TestFrameworkSerializableState {
2724
let instance_clone = instance.clone();
2825

2926
// You can serialize and then deserialize the state.
30-
let serialized_state = instance_clone.serialize_state();
27+
let serialized_state = instance_clone.suspend();
3128
assert_eq!(serialized_state.len(), SERIALIZED_STATE_LEN);
3229

33-
let _deserialized_state = S::from_serialized_state(serialized_state).unwrap();
30+
let _deserialized_state = S::from_suspended(serialized_state).unwrap();
3431

3532
// The serialized state MUST include a prefix indicating the current version of the library.
3633
let state_sized: [u8; 3] = serialized_state[..3].try_into().unwrap();
@@ -41,7 +38,7 @@ impl TestFrameworkSerializableState {
4138
// used the helper functions.
4239
let mut ver0_serialized_state = serialized_state.clone();
4340
ver0_serialized_state[..3].copy_from_slice(&[0, 0, 0]);
44-
match S::from_serialized_state(ver0_serialized_state) {
41+
match S::from_suspended(ver0_serialized_state) {
4542
Err(SerializedStateError::IncompatibleVersion) => { /* good */ }
4643
_ => {
4744
panic!("Expected IncompatibleVersion error")
@@ -54,7 +51,7 @@ impl TestFrameworkSerializableState {
5451
let mut futurever_serialized_state = serialized_state.clone();
5552
futurever_serialized_state[..3]
5653
.copy_from_slice(&[future_ver.major, future_ver.minor, future_ver.patch]);
57-
match S::from_serialized_state(futurever_serialized_state) {
54+
match S::from_suspended(futurever_serialized_state) {
5855
Err(SerializedStateError::IncompatibleVersion) => { /* good */ }
5956
_ => {
6057
panic!("Expected IncompatibleVersion error")
@@ -63,9 +60,9 @@ impl TestFrameworkSerializableState {
6360
}
6461
}
6562

66-
pub struct TestFrameworkSerializableKeyedState {}
63+
pub struct TestFrameworkSuspendableKeyedState {}
6764

68-
impl TestFrameworkSerializableKeyedState {
65+
impl TestFrameworkSuspendableKeyedState {
6966
pub fn new() -> Self {
7067
Self {}
7168
}
@@ -75,7 +72,7 @@ impl TestFrameworkSerializableKeyedState {
7572
/// Expects ta be handed an instance of the object that has some in-progress state to be serialized.
7673
pub fn test<
7774
const SERIALIZED_STATE_LEN: usize,
78-
S: SerializableKeyedState<SERIALIZED_STATE_LEN> + Clone,
75+
S: SuspendableKeyed<SERIALIZED_STATE_LEN> + Clone,
7976
>(
8077
&self,
8178
instance: &S,
@@ -89,10 +86,10 @@ impl TestFrameworkSerializableKeyedState {
8986
let instance_clone = instance.clone();
9087

9188
// You can serialize and then deserialize the state.
92-
let serialized_state = instance_clone.serialize_state();
89+
let serialized_state = instance_clone.suspend();
9390
assert_eq!(serialized_state.len(), SERIALIZED_STATE_LEN);
9491

95-
let _deserialized_state = S::from_serialized_state(serialized_state, key).unwrap();
92+
let _deserialized_state = S::from_suspended(serialized_state, key).unwrap();
9693

9794
// The serialized state MUST include a prefix indicating the current version of the library.
9895
let state_sized: [u8; 3] = serialized_state[..3].try_into().unwrap();
@@ -103,7 +100,7 @@ impl TestFrameworkSerializableKeyedState {
103100
// used the helper functions.
104101
let mut ver0_serialized_state = serialized_state.clone();
105102
ver0_serialized_state[..3].copy_from_slice(&[0, 0, 0]);
106-
match S::from_serialized_state(ver0_serialized_state, key) {
103+
match S::from_suspended(ver0_serialized_state, key) {
107104
Err(SerializedStateError::IncompatibleVersion) => { /* good */ }
108105
_ => {
109106
panic!("Expected IncompatibleVersion error")
@@ -116,7 +113,7 @@ impl TestFrameworkSerializableKeyedState {
116113
let mut futurever_serialized_state = serialized_state.clone();
117114
futurever_serialized_state[..3]
118115
.copy_from_slice(&[future_ver.major, future_ver.minor, future_ver.patch]);
119-
match S::from_serialized_state(futurever_serialized_state, key) {
116+
match S::from_suspended(futurever_serialized_state, key) {
120117
Err(SerializedStateError::IncompatibleVersion) => { /* good */ }
121118
_ => {
122119
panic!("Expected IncompatibleVersion error")

crypto/core/src/errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ pub enum SerializedStateError {
7878
IncompatibleVersion,
7979
/// The serialized state is malformed or corrupt.
8080
InvalidData,
81-
/// The key supplied to [crate::traits::SerializableKeyedState::from_serialized_state] does not
81+
/// The key supplied to [crate::traits::SuspendableKeyed::from_suspended] does not
8282
/// match the key the state was created with (it is bound to a different public-key hash `tr`).
8383
IncorrectKey,
8484
}

crypto/core/src/traits.rs

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -488,8 +488,8 @@ pub trait RNG {
488488
#[allow(drop_bounds)]
489489
pub trait Secret: Drop + Debug + Display {}
490490

491-
/// Allows a stateful object to serialize its state so that it can be paused and resumed later,
492-
/// potentially from a different host.
491+
/// Allows a stateful object to suspend its operation by serializing its state into a byte array
492+
///so that it can be resumed later, potentially from a different host.
493493
///
494494
/// This is intended for situations where an object is being used through its streaming API
495495
/// (do_update, do_final) and the operation wants to be paused to a cache, for example while waiting
@@ -499,54 +499,56 @@ pub trait Secret: Drop + Debug + Display {}
499499
/// will be more straightforward.
500500
///
501501
/// The serialized state MAY contain short-term sensitive values such as nonces or IVs,
502-
/// but it MUST NOT include a serialized private key. Keyed algorithms MUST instead impl
503-
/// [SerializableKeyedState] which requires the key to be supplied independently at the time of deserialization.
504-
pub trait SerializableState<const SERIALIZED_STATE_LEN: usize>: Sized {
505-
/// Serialize the state of the object.
502+
/// but it MUST NOT include a serialized private key.
503+
/// Keyed algorithms MUST instead impl
504+
/// [SuspendableKeyed] which requires the key to be supplied independently at the time of deserialization.
505+
pub trait Suspendable<const SERIALIZED_STATE_LEN: usize>: Sized {
506+
/// Suspend operation by serializing out the state of the object.
506507
///
507508
/// Note that this consumes `self` to prevent accidentally continuing to use the object after serialization.
508509
/// If you want to do this intentionally, then you will need to clone the object before serializing it.
509510
///
510511
/// The serialized state MUST include a prefix indicating the version of the library that serialized it.
511-
fn serialize_state(self) -> [u8; SERIALIZED_STATE_LEN];
512+
fn suspend(self) -> [u8; SERIALIZED_STATE_LEN];
512513

513-
/// Create a new object from a serialized state.
514+
/// Resume operation from a serialized state.
514515
///
515516
/// Deserializers SHOULD check the version and reject serialized states from incompatible versions
516517
/// (including rejecting serializations from a future version of the library).
517518
/// For example, if a given object made a breaking change to its serialization in version 1.2.3, then its
518519
/// deserializer should reject serialized states from that version or older.
519-
fn from_serialized_state(
520-
serialized_state: [u8; SERIALIZED_STATE_LEN],
520+
fn from_suspended(
521+
state: [u8; SERIALIZED_STATE_LEN],
521522
) -> Result<Self, SerializedStateError>;
522523
}
523524

524-
/// Similar to [SerializableState] in that it allows a stateful object to serialize its state so that
525-
/// it can be paused and resumed later, potentially from a different host.
525+
/// Similar to [Suspendable] in that it allows a stateful object to suspend its operation by
526+
/// serializing its state into a byte array so that it can be resumed later, potentially from a different host.
526527
///
527528
/// The difference is that this trait is for keyed algorithms -- MACs, symmetric ciphers, signatures, etc --
528-
/// which require a private key. For security reasons, the private key is not included in the serialized state
529+
/// which require a private key in order to resume successfully.
530+
/// For security reasons, the private key is not included in the serialized state
529531
/// and must be provided separately as part of the deserialization process.
530-
pub trait SerializableKeyedState<const SERIALIZED_STATE_LEN: usize>: Sized {
532+
pub trait SuspendableKeyed<const SERIALIZED_STATE_LEN: usize>: Sized {
531533
/// The type of key that must be re-supplied to resume this object.
532534
type Key: ?Sized;
533535

534-
/// Serialize the state of the object.
536+
/// Suspend operation by serializing out the state of the object.
535537
///
536538
/// Note that this consumes `self` to prevent accidentally continuing to use the object after serialization.
537539
/// If you want to do this intentionally, then you will need to clone the object before serializing it.
538540
///
539541
/// The serialized state MUST include a prefix indicating the version of the library that serialized it.
540-
fn serialize_state(self) -> [u8; SERIALIZED_STATE_LEN];
542+
fn suspend(self) -> [u8; SERIALIZED_STATE_LEN];
541543

542-
/// Create a new object from a serialized state.
544+
/// Resume operation from a serialized state and the key.
543545
///
544546
/// Deserializers SHOULD check the version and reject serialized states from incompatible versions
545547
/// (including rejecting serializations from a future version of the library).
546548
/// For example, if a given object made a breaking change to its serialization in version 1.2.3, then its
547549
/// deserializer should reject serialized states from that version or older.
548-
fn from_serialized_state(
549-
serialized_state: [u8; SERIALIZED_STATE_LEN],
550+
fn from_suspended(
551+
state: [u8; SERIALIZED_STATE_LEN],
550552
key: &Self::Key,
551553
) -> Result<Self, SerializedStateError>;
552554
}

0 commit comments

Comments
 (0)