Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Streaming API for CBC and CTR cipher modes #410

Merged
merged 8 commits into from
Jun 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 61 additions & 4 deletions aws-lc-rs/src/cipher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,58 @@
//! # }
//! ```
//!
//! ### AES-128 CBC Streaming Cipher
//!
//! ```rust
//! # use std::error::Error;
//! #
//! # fn main() -> Result<(), Box<dyn Error>> {
//! use aws_lc_rs::cipher::{
//! StreamingDecryptingKey, StreamingEncryptingKey, UnboundCipherKey, AES_128,
//! };
//! let original_message = "This is a secret message!".as_bytes();
//! let key_bytes: &[u8] = &[
//! 0xff, 0x0b, 0xe5, 0x84, 0x64, 0x0b, 0x00, 0xc8, 0x90, 0x7a, 0x4b, 0xbf, 0x82, 0x7c,
//! 0xb6, 0xd1,
//! ];
//! // Prepare ciphertext buffer
//! let mut ciphertext_buffer = vec![0u8; original_message.len() + AES_128.block_len()];
//! let ciphertext_slice = ciphertext_buffer.as_mut_slice();
//!
//! // Create StreamingEncryptingKey
//! let key = UnboundCipherKey::new(&AES_128, key_bytes).unwrap();
//! let mut encrypting_key = StreamingEncryptingKey::cbc_pkcs7(key).unwrap();
//!
//! // Encrypt
//! let mut first_update = encrypting_key
//! .update(original_message, ciphertext_slice)
//! .unwrap();
//! let first_update_len = first_update.written().len();
//! let (context, final_update) = encrypting_key.finish(first_update.remainder_mut()).unwrap();
//! let ciphertext_len = first_update_len + final_update.written().len();
//! let ciphertext = &ciphertext_slice[0..ciphertext_len];
//!
//! // Prepare plaintext buffer
//! let mut plaintext_buffer = vec![0u8; ciphertext_len + AES_128.block_len()];
//! let plaintext_slice = plaintext_buffer.as_mut_slice();
//!
//! // Create StreamingDecryptingKey
//! let key = UnboundCipherKey::new(&AES_128, key_bytes).unwrap();
//! let mut decrypting_key = StreamingDecryptingKey::cbc_pkcs7(key, context).unwrap();
//!
//! // Decrypt
//! let mut first_update = decrypting_key.update(ciphertext, plaintext_slice).unwrap();
//! let first_update_len = first_update.written().len();
//! let final_update = decrypting_key.finish(first_update.remainder_mut()).unwrap();
//! let plaintext_len = first_update_len + final_update.written().len();
//! let plaintext = &plaintext_slice[0..plaintext_len];
//!
//! assert_eq!(original_message, plaintext);
//! #
//! # Ok(())
//! # }
//! ```
//!
//! ## Constructing a `DecryptionContext` for decryption.
//!
//! ```rust
Expand Down Expand Up @@ -142,8 +194,10 @@ pub(crate) mod block;
pub(crate) mod chacha;
pub(crate) mod key;
mod padded;
mod streaming;

pub use padded::{PaddedBlockDecryptingKey, PaddedBlockEncryptingKey};
pub use streaming::{BufferUpdate, StreamingDecryptingKey, StreamingEncryptingKey};

use crate::buffer::Buffer;
use crate::error::Unspecified;
Expand Down Expand Up @@ -280,7 +334,9 @@ impl Algorithm {
&self.id
}

const fn block_len(&self) -> usize {
/// The block length of this cipher algorithm.
#[must_use]
justsmth marked this conversation as resolved.
Show resolved Hide resolved
pub const fn block_len(&self) -> usize {
self.block_len
}

Expand Down Expand Up @@ -354,8 +410,7 @@ impl UnboundCipherKey {
///
/// # Errors
///
/// * [`Unspecified`] if `key_bytes.len()` does not match the
/// length required by `algorithm`.
/// * [`Unspecified`] if `key_bytes.len()` does not match the length required by `algorithm`.
pub fn new(algorithm: &'static Algorithm, key_bytes: &[u8]) -> Result<Self, Unspecified> {
let key_bytes = Buffer::new(key_bytes.to_vec());
Ok(UnboundCipherKey {
Expand Down Expand Up @@ -438,7 +493,9 @@ impl EncryptingKey {
self.less_safe_encrypt(in_out, context)
}

/// Encrypts the data provided in `in_out` in-place using the provided `CipherContext`.
/// Encrypts the data provided in `in_out` in-place using the provided `EncryptionContext`.
/// This is considered "less safe" because the caller could potentially construct
/// a `EncryptionContext` from a previously used IV (initialization vector).
/// Returns a references to the decrypted data.
///
/// # Errors
Expand Down
Loading
Loading