Skip to content

Commit 2fce505

Browse files
authored
Implement SetIvState trait (#114)
See RustCrypto/traits#2420
1 parent e9a0336 commit 2fce505

42 files changed

Lines changed: 795 additions & 107 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Cargo.lock

Lines changed: 20 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

belt-ctr/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## 0.2.1 (2026-05-20)
9+
### Added
10+
- Implementation of the `SetIvState` trait ([#114])
11+
12+
[#114]: https://github.com/RustCrypto/block-modes/pull/114
13+
814
## 0.2.0 (2026-04-10)
915
## Added
1016
- `GenericBeltCtr` and `GenericBeltCtrCore` types ([#112])

belt-ctr/Cargo.toml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
[package]
22
name = "belt-ctr"
3-
version = "0.2.0"
4-
description = "CTR block mode of operation specified by the BelT standard"
3+
version = "0.2.1"
54
authors = ["RustCrypto Developers"]
6-
license = "MIT OR Apache-2.0"
75
edition = "2024"
86
rust-version = "1.85"
9-
readme = "README.md"
107
documentation = "https://docs.rs/belt-ctr"
8+
readme = "README.md"
119
repository = "https://github.com/RustCrypto/block-modes"
10+
license = "MIT OR Apache-2.0"
1211
keywords = ["crypto", "block-mode", "stream-cipher", "ciphers", "belt"]
1312
categories = ["cryptography", "no-std"]
13+
description = "CTR block mode of operation specified by the BelT standard"
1414

1515
[dependencies]
16-
cipher = { version = "0.5", features = ["stream-wrapper"] }
16+
cipher = { version = "0.5.2", features = ["stream-wrapper"] }
1717
belt-block = "0.2"
1818

1919
[dev-dependencies]
20+
cipher = { version = "0.5.2", features = ["dev"] }
2021
hex-literal = "1"
21-
cipher = { version = "0.5", features = ["dev"] }
2222

2323
[features]
2424
alloc = ["cipher/alloc"]

belt-ctr/src/lib.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use belt_block::BeltBlock;
1212
use cipher::{
1313
AlgorithmName, Block, BlockCipherDecrypt, BlockCipherEncBackend, BlockCipherEncClosure,
1414
BlockCipherEncrypt, BlockSizeUser, InOut, InnerIvInit, Iv, IvSizeUser, IvState, ParBlocks,
15-
ParBlocksSizeUser, StreamCipherBackend, StreamCipherClosure, StreamCipherCore,
15+
ParBlocksSizeUser, SetIvState, StreamCipherBackend, StreamCipherClosure, StreamCipherCore,
1616
StreamCipherCoreWrapper, StreamCipherSeekCore, array::Array, common::InnerUser, consts::U16,
1717
};
1818
use core::fmt;
@@ -41,11 +41,13 @@ impl<C> StreamCipherCore for GenericBeltCtrCore<C>
4141
where
4242
C: BlockCipherEncrypt + BlockSizeUser<BlockSize = U16>,
4343
{
44+
#[inline]
4445
fn remaining_blocks(&self) -> Option<usize> {
4546
let used = self.s.wrapping_sub(self.s_init);
4647
(u128::MAX - used).try_into().ok()
4748
}
4849

50+
#[inline]
4951
fn process_with_backend(&mut self, f: impl StreamCipherClosure<BlockSize = Self::BlockSize>) {
5052
struct Closure<'a, C: StreamCipherClosure<BlockSize = U16>> {
5153
s: &'a mut u128,
@@ -75,10 +77,12 @@ where
7577
{
7678
type Counter = u128;
7779

80+
#[inline]
7881
fn get_block_pos(&self) -> Self::Counter {
7982
self.s.wrapping_sub(self.s_init)
8083
}
8184

85+
#[inline]
8286
fn set_block_pos(&mut self, pos: Self::Counter) {
8387
self.s = self.s_init.wrapping_add(pos);
8488
}
@@ -126,17 +130,31 @@ impl<C> IvState for GenericBeltCtrCore<C>
126130
where
127131
C: BlockCipherEncrypt + BlockCipherDecrypt + BlockSizeUser<BlockSize = U16>,
128132
{
133+
#[inline]
129134
fn iv_state(&self) -> Iv<Self> {
130135
let mut t = self.s.to_le_bytes().into();
131136
self.cipher.decrypt_block(&mut t);
132137
t
133138
}
134139
}
135140

141+
impl<C> SetIvState for GenericBeltCtrCore<C>
142+
where
143+
C: BlockCipherEncrypt + BlockCipherDecrypt + BlockSizeUser<BlockSize = U16>,
144+
{
145+
#[inline]
146+
fn set_iv(&mut self, iv: &Iv<Self>) {
147+
let mut iv = *iv;
148+
self.cipher.encrypt_block(&mut iv);
149+
self.s = u128::from_le_bytes(iv.0);
150+
}
151+
}
152+
136153
impl<C> AlgorithmName for GenericBeltCtrCore<C>
137154
where
138155
C: BlockCipherEncrypt + BlockSizeUser<BlockSize = U16> + AlgorithmName,
139156
{
157+
#[inline]
140158
fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
141159
f.write_str("BeltCtr<")?;
142160
<C as AlgorithmName>::write_alg_name(f)?;
@@ -160,6 +178,7 @@ impl<C: BlockCipherEncrypt> Drop for GenericBeltCtrCore<C>
160178
where
161179
C: BlockCipherEncrypt + BlockSizeUser<BlockSize = U16>,
162180
{
181+
#[inline]
163182
fn drop(&mut self) {
164183
#[cfg(feature = "zeroize")]
165184
{

belt-ctr/tests/iv_state.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//! Basic tests for `IvState` and `SetIvState` trait impls
2+
use belt_ctr::BeltCtrCore;
3+
use cipher::{IvState, KeyIvInit, SetIvState, StreamCipherCore};
4+
5+
cipher::iv_state_test!(belt_ctr_iv_state, BeltCtrCore, apply_ks);
6+
7+
#[test]
8+
fn belt_ctr_set_iv() {
9+
let key = Default::default();
10+
let iv = Default::default();
11+
let mut mode = BeltCtrCore::new(&key, &iv);
12+
13+
let mut blocks = [Default::default(); 16];
14+
15+
mode.apply_keystream_blocks(&mut blocks);
16+
let iv = mode.iv_state();
17+
18+
let mut buf1 = blocks;
19+
let mut buf2 = blocks;
20+
21+
mode.peek(|m| m.apply_keystream_blocks(&mut buf1));
22+
assert_eq!(mode.iv_state(), iv);
23+
24+
mode.apply_keystream_blocks(&mut blocks);
25+
let iv2 = mode.iv_state();
26+
27+
mode.set_iv(&iv);
28+
mode.apply_keystream_blocks(&mut buf2);
29+
30+
assert_eq!(blocks, buf1);
31+
assert_eq!(blocks, buf2);
32+
assert_eq!(mode.iv_state(), iv2);
33+
}

belt-ctr/tests/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//! Test vectors from the BelT standard (tables A.15 and A.16):
22
//! https://apmi.bsu.by/assets/files/std/belt-spec371.pdf
3-
use belt_ctr::{BeltCtr, BeltCtrCore};
3+
use belt_ctr::BeltCtr;
44

55
cipher::stream_cipher_test!(belt_ctr_core, "belt-ctr", BeltCtr);
66
cipher::stream_cipher_seek_test!(belt_ctr_seek, BeltCtr);
7-
cipher::iv_state_test!(belt_ctr_iv_state, BeltCtrCore, apply_ks);

cbc/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## 0.2.1 (2026-05-20)
9+
### Added
10+
- Implementation of the `SetIvState` trait ([#114])
11+
12+
[#114]: https://github.com/RustCrypto/block-modes/pull/114
13+
814
## 0.2.0 (2026-04-10)
915
### Removed
1016
- `std` feature ([#76])

cbc/Cargo.toml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
[package]
22
name = "cbc"
3-
version = "0.2.0"
4-
description = "Cipher Block Chaining (CBC) block cipher mode of operation"
3+
version = "0.2.1"
54
authors = ["RustCrypto Developers"]
6-
license = "MIT OR Apache-2.0"
75
edition = "2024"
86
rust-version = "1.85"
9-
readme = "README.md"
107
documentation = "https://docs.rs/cbc"
8+
readme = "README.md"
119
repository = "https://github.com/RustCrypto/block-modes"
10+
license = "MIT OR Apache-2.0"
1211
keywords = ["crypto", "block-mode", "ciphers"]
1312
categories = ["cryptography", "no-std"]
13+
description = "Cipher Block Chaining (CBC) block cipher mode of operation"
1414

1515
[dependencies]
16-
cipher = "0.5"
16+
cipher = "0.5.2"
1717

1818
[dev-dependencies]
19-
aes = "0.9"
20-
cipher = { version = "0.5", features = ["dev"] }
19+
cipher = { version = "0.5.2", features = ["dev"] }
2120
hex-literal = "1"
21+
aes = "0.9"
2222

2323
[features]
2424
default = ["block-padding"]

cbc/src/decrypt.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::xor;
22
use cipher::{
33
AlgorithmName, Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt,
44
BlockModeDecBackend, BlockModeDecClosure, BlockModeDecrypt, BlockSizeUser, InnerIvInit, Iv,
5-
IvState, ParBlocks, ParBlocksSizeUser,
5+
IvState, ParBlocks, ParBlocksSizeUser, SetIvState,
66
array::{Array, ArraySize},
77
common::{InnerUser, IvSizeUser},
88
inout::InOut,
@@ -107,6 +107,16 @@ where
107107
}
108108
}
109109

110+
impl<C> SetIvState for Decryptor<C>
111+
where
112+
C: BlockCipherDecrypt,
113+
{
114+
#[inline]
115+
fn set_iv(&mut self, iv: &Iv<Self>) {
116+
self.iv = iv.clone();
117+
}
118+
}
119+
110120
impl<C> AlgorithmName for Decryptor<C>
111121
where
112122
C: BlockCipherDecrypt + AlgorithmName,

0 commit comments

Comments
 (0)