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

Panic on empty input for Secure Cell #363

Closed
wants to merge 1 commit into from
Closed
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
4 changes: 4 additions & 0 deletions src/wrappers/themis/rust/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ The version currently under development.
`encrypt` and `decrypt` respectively. Their parameters have been
changed to use _impl Trait_ instead of explicit generics. ([#358])

- `SecureCell` methods panic instead of returning errors when called with
forbidden empty key, message, token, or user context parameters. ([#363])

[#358]: https://github.com/cossacklabs/themis/pull/358
[#363]: https://github.com/cossacklabs/themis/pull/363

Version 0.0.3 — 2019-01-17
==========================
Expand Down
121 changes: 81 additions & 40 deletions src/wrappers/themis/rust/src/secure_cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ pub struct SecureCell {
impl SecureCell {
/// Constructs a new cell secured by a master key.
///
/// # Panics
///
/// Panics if the provided master key is empty.
///
/// # Examples
///
/// A master key may be provided as anything convertible to a byte slice: a byte slice or an
Expand All @@ -126,6 +130,8 @@ impl SecureCell {
///
/// [`keygen`]: ../keygen/index.html
pub fn with_key(master_key: impl AsRef<[u8]>) -> Self {
assert!(!master_key.as_ref().is_empty(), "empty master key");

Self {
master_key: KeyBytes::copy_slice(master_key.as_ref()),
}
Expand Down Expand Up @@ -171,6 +177,10 @@ pub struct SecureCellSeal(SecureCell);
impl SecureCellSeal {
/// Encrypts and puts the provided message into a sealed cell.
///
/// # Panics
///
/// Panics if the message is empty.
///
/// # Examples
///
/// You can use anything convertible into a byte slice as a message: a byte slice or an array,
Expand All @@ -189,22 +199,16 @@ impl SecureCellSeal {
/// # Ok(())
/// # }
/// ```
///
/// However, the message must not be empty:
///
/// ```
/// # use themis::secure_cell::SecureCell;
/// #
/// # let cell = SecureCell::with_key(b"password").seal();
/// #
/// assert!(cell.encrypt(&[]).is_err());
/// ```
pub fn encrypt(&self, message: impl AsRef<[u8]>) -> Result<Vec<u8>> {
self.encrypt_with_context(message, &[])
}

/// Encrypts and puts the provided message together with the context into a sealed cell.
///
/// # Panics
///
/// Panics if the message is empty.
///
/// # Examples
///
/// You can use anything convertible into a byte slice as a message or a context: a byte slice
Expand All @@ -223,15 +227,19 @@ impl SecureCellSeal {
/// ```
///
/// The context may be empty (in which case this call is equivalent to [`encrypt`]).
/// However, the message must not be empty.
///
/// ```
/// # fn main() -> Result<(), themis::Error> {
/// # use themis::secure_cell::SecureCell;
/// #
/// # let cell = SecureCell::with_key(b"password").seal();
/// #
/// assert!(cell.encrypt_with_context(b"message", &[]).is_ok());
/// assert!(cell.encrypt_with_context(&[], b"context").is_err());
/// let encrypted = cell.encrypt_with_context(b"message", &[])?;
/// let decrypted = cell.decrypt(&encrypted)?;
///
/// assert_eq!(decrypted, b"message");
/// # Ok(())
/// # }
/// ```
///
/// [`encrypt`]: struct.SecureCellSeal.html#method.encrypt
Expand All @@ -249,6 +257,10 @@ impl SecureCellSeal {

/// Extracts the original message from a sealed cell.
///
/// # Panics
///
/// Panics if the encrypted message is empty.
///
/// # Examples
///
/// If you know the master key then getting back your data is easy:
Expand Down Expand Up @@ -300,6 +312,10 @@ impl SecureCellSeal {

/// Extracts the original message from a sealed cell given the context.
///
/// # Panics
///
/// Panics if the encrypted message is empty.
///
/// # Examples
///
/// If you know the master key and the context then getting back your data is easy:
Expand Down Expand Up @@ -361,6 +377,9 @@ impl SecureCellSeal {

/// Encrypts `message` with `master_key` including optional `user_context` for verification.
fn encrypt_seal(master_key: &[u8], user_context: &[u8], message: &[u8]) -> Result<Vec<u8>> {
assert!(!master_key.is_empty(), "empty master key");
assert!(!message.is_empty(), "empty message");

let (master_key_ptr, master_key_len) = into_raw_parts(master_key);
let (user_context_ptr, user_context_len) = into_raw_parts(user_context);
let (message_ptr, message_len) = into_raw_parts(message);
Expand Down Expand Up @@ -411,6 +430,9 @@ fn encrypt_seal(master_key: &[u8], user_context: &[u8], message: &[u8]) -> Resul

/// Decrypts `message` with `master_key` and verifies authenticity of `user_context`.
fn decrypt_seal(master_key: &[u8], user_context: &[u8], message: &[u8]) -> Result<Vec<u8>> {
assert!(!master_key.is_empty(), "empty master key");
assert!(!message.is_empty(), "empty message");

let (master_key_ptr, master_key_len) = into_raw_parts(master_key);
let (user_context_ptr, user_context_len) = into_raw_parts(user_context);
let (message_ptr, message_len) = into_raw_parts(message);
Expand Down Expand Up @@ -488,6 +510,10 @@ impl SecureCellTokenProtect {
/// The results can be stored or transmitted separately. You will need to provide both later
/// for successful decryption.
///
/// # Panics
///
/// Panics if the message is empty.
///
/// # Examples
///
/// You can use anything convertible into a byte slice as a message: a byte slice or an array,
Expand All @@ -506,16 +532,6 @@ impl SecureCellTokenProtect {
/// # Ok(())
/// # }
/// ```
///
/// However, the message must not be empty:
///
/// ```
/// # use themis::secure_cell::SecureCell;
/// #
/// # let cell = SecureCell::with_key(b"password").token_protect();
/// #
/// assert!(cell.encrypt(&[]).is_err());
/// ```
pub fn encrypt(&self, message: impl AsRef<[u8]>) -> Result<(Vec<u8>, Vec<u8>)> {
self.encrypt_with_context(message, &[])
}
Expand All @@ -526,6 +542,10 @@ impl SecureCellTokenProtect {
/// The results can be stored or transmitted separately. You will need to provide all three
/// parts later for successful decryption.
///
/// # Panics
///
/// Panics if the message is empty.
///
/// # Examples
///
/// You can use anything convertible into a byte slice as a message or a context: a byte slice
Expand All @@ -544,15 +564,19 @@ impl SecureCellTokenProtect {
/// ```
///
/// The context may be empty (in which case this call is equivalent to [`encrypt`]).
/// However, the message must not be empty.
///
/// ```
/// # fn main() -> Result<(), themis::Error> {
/// # use themis::secure_cell::SecureCell;
/// #
/// # let cell = SecureCell::with_key(b"password").token_protect();
/// #
/// assert!(cell.encrypt_with_context(b"message", &[]).is_ok());
/// assert!(cell.encrypt_with_context(&[], b"context").is_err());
/// let (encrypted, token) = cell.encrypt_with_context(b"message", &[])?;
/// let decrypted = cell.decrypt(&encrypted, &token)?;
///
/// assert_eq!(decrypted, b"message");
/// # Ok(())
/// # }
/// ```
///
/// [`encrypt`]: struct.SecureCellTokenProtect.html#method.encrypt
Expand All @@ -575,6 +599,10 @@ impl SecureCellTokenProtect {
///
/// [`encrypt`]: struct.SecureCellTokenProtect.html#method.encrypt
///
/// # Panics
///
/// Panics if the encrypted message or the token is empty.
///
/// # Examples
///
/// If you know the master key and the token then getting back your data is easy:
Expand Down Expand Up @@ -652,6 +680,10 @@ impl SecureCellTokenProtect {
///
/// [`encrypt_with_context`]: struct.SecureCellTokenProtect.html#method.encrypt_with_context
///
/// # Panics
///
/// Panics if the encrypted message or the token is empty.
///
/// # Examples
///
/// If you know the master key, the context, and the token then getting back your data is easy:
Expand Down Expand Up @@ -731,6 +763,9 @@ fn encrypt_token_protect(
user_context: &[u8],
message: &[u8],
) -> Result<(Vec<u8>, Vec<u8>)> {
assert!(!master_key.is_empty(), "empty master key");
assert!(!message.is_empty(), "empty message");

let (master_key_ptr, master_key_len) = into_raw_parts(master_key);
let (user_context_ptr, user_context_len) = into_raw_parts(user_context);
let (message_ptr, message_len) = into_raw_parts(message);
Expand Down Expand Up @@ -795,6 +830,10 @@ fn decrypt_token_protect(
message: &[u8],
token: &[u8],
) -> Result<Vec<u8>> {
assert!(!master_key.is_empty(), "empty master key");
assert!(!message.is_empty(), "empty message");
assert!(!token.is_empty(), "empty token");

let (master_key_ptr, master_key_len) = into_raw_parts(master_key);
let (user_context_ptr, user_context_len) = into_raw_parts(user_context);
let (message_ptr, message_len) = into_raw_parts(message);
Expand Down Expand Up @@ -874,8 +913,6 @@ fn decrypt_token_protect(
/// some other means in place to validate the output.
pub struct SecureCellContextImprint(SecureCell);

// TODO: maybe panic if a SecureCell with an empty context is switched into context imprint mode

impl SecureCellContextImprint {
/// Encrypts the provided message, combining it with provided user context, and returns
/// the encrypted data.
Expand All @@ -884,6 +921,10 @@ impl SecureCellContextImprint {
/// an authentication token. Secure Cell cannot ensure correctness of later decryption
/// if the message gets corrupted or a different master key is used.
///
/// # Panics
///
/// Panics if the message or the user context is empty.
///
/// # Examples
///
/// You can use anything convertible into a byte slice as a message or a context: a byte slice
Expand All @@ -900,18 +941,6 @@ impl SecureCellContextImprint {
/// # Ok(())
/// # }
/// ```
///
/// However, the message and context must not be empty:
///
/// ```
/// # use themis::secure_cell::SecureCell;
/// #
/// # let cell = SecureCell::with_key(b"password").context_imprint();
/// #
/// assert!(cell.encrypt_with_context(b"message", b"context").is_ok());
/// assert!(cell.encrypt_with_context(b"", b"context").is_err());
/// assert!(cell.encrypt_with_context(b"message", b"").is_err());
/// ```
pub fn encrypt_with_context(
&self,
message: impl AsRef<[u8]>,
Expand All @@ -930,6 +959,10 @@ impl SecureCellContextImprint {
/// integrity validation, thus the returned message might not be the original one even if
/// it has been decrypted ‘successfully’.
///
/// # Panics
///
/// Panics if the encrypted message or the user context is empty.
///
/// # Examples
///
/// If you know the master key and the context then getting back your data is easy:
Expand Down Expand Up @@ -995,6 +1028,10 @@ impl SecureCellContextImprint {

/// Encrypts `message` with `master_key` including required `context`.
fn encrypt_context_imprint(master_key: &[u8], message: &[u8], context: &[u8]) -> Result<Vec<u8>> {
assert!(!master_key.is_empty(), "empty master key");
assert!(!message.is_empty(), "empty message");
assert!(!context.is_empty(), "empty user context");

let (master_key_ptr, master_key_len) = into_raw_parts(master_key);
let (message_ptr, message_len) = into_raw_parts(message);
let (context_ptr, context_len) = into_raw_parts(context);
Expand Down Expand Up @@ -1045,6 +1082,10 @@ fn encrypt_context_imprint(master_key: &[u8], message: &[u8], context: &[u8]) ->

/// Decrypts `message` with `master_key` and expected `context`, but do not verify data.
fn decrypt_context_imprint(master_key: &[u8], message: &[u8], context: &[u8]) -> Result<Vec<u8>> {
assert!(!master_key.is_empty(), "empty master key");
assert!(!message.is_empty(), "empty message");
assert!(!context.is_empty(), "empty user context");

let (master_key_ptr, master_key_len) = into_raw_parts(master_key);
let (message_ptr, message_len) = into_raw_parts(message);
let (context_ptr, context_len) = into_raw_parts(context);
Expand Down
Loading