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

ssh-cipher: make ChaCha20Poly1305 public #256

Merged
merged 1 commit into from
Jul 29, 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
28 changes: 20 additions & 8 deletions ssh-cipher/src/chacha20poly1305.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
//! OpenSSH variant of ChaCha20Poly1305: `[email protected]`
//!
//! Differences from ChaCha20Poly1305 as described in RFC8439:
//! - The input of Poly1305 is not padded
//! - The lengths of ciphertext and AAD are not authenticated using Poly1305
//!
//! [PROTOCOL.chacha20poly1305]: https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.chacha20poly1305?annotate=HEAD
//! OpenSSH variant of ChaCha20Poly1305.

use crate::{Error, Nonce, Result, Tag};
use chacha20::{ChaCha20, Key};
use cipher::{KeyInit, KeyIvInit, StreamCipher, StreamCipherSeek};
use poly1305::Poly1305;
use subtle::ConstantTimeEq;

pub(crate) struct ChaCha20Poly1305 {
/// OpenSSH variant of ChaCha20Poly1305: `[email protected]`
/// as described in [PROTOCOL.chacha20poly1305].
///
/// Differences from ChaCha20Poly1305-IETF as described in [RFC8439]:
/// - The input of Poly1305 is not padded.
/// - AAD is unsupported.
/// - The lengths of ciphertext (and AAD) are not authenticated using Poly1305.
///
/// [PROTOCOL.chacha20poly1305]: https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.chacha20poly1305?annotate=HEAD
/// [RFC8439]: https://datatracker.ietf.org/doc/html/rfc8439
pub struct ChaCha20Poly1305 {
cipher: ChaCha20,
mac: Poly1305,
}
Expand All @@ -36,12 +40,20 @@ impl ChaCha20Poly1305 {
Ok(Self { cipher, mac })
}

/// Encrypt the provided `buffer` in-place, returning the Poly1305 authentication tag.
#[inline]
pub fn encrypt(mut self, buffer: &mut [u8]) -> Tag {
self.cipher.apply_keystream(buffer);
self.mac.compute_unpadded(buffer).into()
}

/// Decrypt the provided `buffer` in-place, verifying it against the provided Poly1305
/// authentication `tag`.
///
/// In the event tag verification fails, [`Error::Crypto`] is returned, and `buffer` is not
/// modified.
///
/// Upon success, `Ok(())` is returned and `buffer` is rewritten with the decrypted plaintext.
#[inline]
pub fn decrypt(mut self, buffer: &mut [u8], tag: Tag) -> Result<()> {
let expected_tag = self.mac.compute_unpadded(buffer);
Expand Down
6 changes: 3 additions & 3 deletions ssh-cipher/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ mod encryptor;

pub use crate::error::{Error, Result};

#[cfg(feature = "chacha20poly1305")]
pub use crate::chacha20poly1305::ChaCha20Poly1305;

#[cfg(any(feature = "aes-cbc", feature = "aes-ctr", feature = "tdes"))]
pub use crate::{decryptor::Decryptor, encryptor::Encryptor};

Expand All @@ -44,9 +47,6 @@ use encoding::{Label, LabelError};
#[cfg(feature = "aes-gcm")]
use aes_gcm::{aead::AeadInPlace, Aes128Gcm, Aes256Gcm};

#[cfg(feature = "chacha20poly1305")]
use crate::chacha20poly1305::ChaCha20Poly1305;

#[cfg(feature = "aes-gcm")]
use cipher::KeyInit;

Expand Down
Loading