AEAD: Move each key type into its own submodule.
Encapsulate each key type in its own module.
This commit is contained in:
parent
47edace294
commit
e8620224e6
@ -117,10 +117,13 @@ include = [
|
||||
"src/aead/gcm/gcm_nohw.rs",
|
||||
"src/aead/less_safe_key.rs",
|
||||
"src/aead/nonce.rs",
|
||||
"src/aead/opening_key.rs",
|
||||
"src/aead/poly1305.rs",
|
||||
"src/aead/poly1305_test.txt",
|
||||
"src/aead/quic.rs",
|
||||
"src/aead/sealing_key.rs",
|
||||
"src/aead/shift.rs",
|
||||
"src/aead/unbound_key.rs",
|
||||
"src/agreement.rs",
|
||||
"src/arithmetic.rs",
|
||||
"src/arithmetic/bigint.rs",
|
||||
|
247
src/aead.rs
247
src/aead.rs
@ -22,13 +22,15 @@
|
||||
//! [`crypto.cipher.AEAD`]: https://golang.org/pkg/crypto/cipher/#AEAD
|
||||
|
||||
use crate::{cpu, error, hkdf, polyfill};
|
||||
use core::ops::RangeFrom;
|
||||
|
||||
pub use self::{
|
||||
aes_gcm::{AES_128_GCM, AES_256_GCM},
|
||||
chacha20_poly1305::CHACHA20_POLY1305,
|
||||
less_safe_key::LessSafeKey,
|
||||
nonce::{Nonce, NONCE_LEN},
|
||||
opening_key::OpeningKey,
|
||||
sealing_key::SealingKey,
|
||||
unbound_key::UnboundKey,
|
||||
};
|
||||
|
||||
/// A sequences of unique nonces.
|
||||
@ -60,202 +62,6 @@ pub trait BoundKey<N: NonceSequence>: core::fmt::Debug {
|
||||
fn algorithm(&self) -> &'static Algorithm;
|
||||
}
|
||||
|
||||
/// An AEAD key for authenticating and decrypting ("opening"), bound to a nonce
|
||||
/// sequence.
|
||||
///
|
||||
/// Intentionally not `Clone` or `Copy` since cloning would allow duplication
|
||||
/// of the nonce sequence.
|
||||
pub struct OpeningKey<N: NonceSequence> {
|
||||
key: LessSafeKey,
|
||||
nonce_sequence: N,
|
||||
}
|
||||
|
||||
impl<N: NonceSequence> BoundKey<N> for OpeningKey<N> {
|
||||
fn new(key: UnboundKey, nonce_sequence: N) -> Self {
|
||||
Self {
|
||||
key: key.inner,
|
||||
nonce_sequence,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn algorithm(&self) -> &'static Algorithm {
|
||||
self.key.algorithm()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: NonceSequence> core::fmt::Debug for OpeningKey<N> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
|
||||
self.key.fmt_debug("OpeningKey", f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: NonceSequence> OpeningKey<N> {
|
||||
/// Authenticates and decrypts (“opens”) data in place.
|
||||
///
|
||||
/// `aad` is the additional authenticated data (AAD), if any.
|
||||
///
|
||||
/// On input, `in_out` must be the ciphertext followed by the tag. When
|
||||
/// `open_in_place()` returns `Ok(plaintext)`, the input ciphertext
|
||||
/// has been overwritten by the plaintext; `plaintext` will refer to the
|
||||
/// plaintext without the tag.
|
||||
///
|
||||
/// When `open_in_place()` returns `Err(..)`, `in_out` may have been
|
||||
/// overwritten in an unspecified way.
|
||||
#[inline]
|
||||
pub fn open_in_place<'in_out, A>(
|
||||
&mut self,
|
||||
aad: Aad<A>,
|
||||
in_out: &'in_out mut [u8],
|
||||
) -> Result<&'in_out mut [u8], error::Unspecified>
|
||||
where
|
||||
A: AsRef<[u8]>,
|
||||
{
|
||||
self.key
|
||||
.open_in_place(self.nonce_sequence.advance()?, aad, in_out)
|
||||
}
|
||||
|
||||
/// Authenticates and decrypts (“opens”) data in place, with a shift.
|
||||
///
|
||||
/// `aad` is the additional authenticated data (AAD), if any.
|
||||
///
|
||||
/// On input, `in_out[ciphertext_and_tag]` must be the ciphertext followed
|
||||
/// by the tag. When `open_within()` returns `Ok(plaintext)`, the plaintext
|
||||
/// will be at `in_out[0..plaintext.len()]`. In other words, the following
|
||||
/// two code fragments are equivalent for valid values of
|
||||
/// `ciphertext_and_tag`, except `open_within` will often be more efficient:
|
||||
///
|
||||
///
|
||||
/// ```skip
|
||||
/// let plaintext = key.open_within(aad, in_out, cipertext_and_tag)?;
|
||||
/// ```
|
||||
///
|
||||
/// ```skip
|
||||
/// let ciphertext_and_tag_len = in_out[ciphertext_and_tag].len();
|
||||
/// in_out.copy_within(ciphertext_and_tag, 0);
|
||||
/// let plaintext = key.open_in_place(aad, &mut in_out[..ciphertext_and_tag_len])?;
|
||||
/// ```
|
||||
///
|
||||
/// Similarly, `key.open_within(aad, in_out, 0..)` is equivalent to
|
||||
/// `key.open_in_place(aad, in_out)`.
|
||||
///
|
||||
/// When `open_in_place()` returns `Err(..)`, `in_out` may have been
|
||||
/// overwritten in an unspecified way.
|
||||
///
|
||||
/// The shifting feature is useful in the case where multiple packets are
|
||||
/// being reassembled in place. Consider this example where the peer has
|
||||
/// sent the message “Split stream reassembled in place” split into
|
||||
/// three sealed packets:
|
||||
///
|
||||
/// ```ascii-art
|
||||
/// Packet 1 Packet 2 Packet 3
|
||||
/// Input: [Header][Ciphertext][Tag][Header][Ciphertext][Tag][Header][Ciphertext][Tag]
|
||||
/// | +--------------+ |
|
||||
/// +------+ +-----+ +----------------------------------+
|
||||
/// v v v
|
||||
/// Output: [Plaintext][Plaintext][Plaintext]
|
||||
/// “Split stream reassembled in place”
|
||||
/// ```
|
||||
///
|
||||
/// This reassembly be accomplished with three calls to `open_within()`.
|
||||
#[inline]
|
||||
pub fn open_within<'in_out, A>(
|
||||
&mut self,
|
||||
aad: Aad<A>,
|
||||
in_out: &'in_out mut [u8],
|
||||
ciphertext_and_tag: RangeFrom<usize>,
|
||||
) -> Result<&'in_out mut [u8], error::Unspecified>
|
||||
where
|
||||
A: AsRef<[u8]>,
|
||||
{
|
||||
self.key.open_within(
|
||||
self.nonce_sequence.advance()?,
|
||||
aad,
|
||||
in_out,
|
||||
ciphertext_and_tag,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// An AEAD key for encrypting and signing ("sealing"), bound to a nonce
|
||||
/// sequence.
|
||||
///
|
||||
/// Intentionally not `Clone` or `Copy` since cloning would allow duplication
|
||||
/// of the nonce sequence.
|
||||
pub struct SealingKey<N: NonceSequence> {
|
||||
key: LessSafeKey,
|
||||
nonce_sequence: N,
|
||||
}
|
||||
|
||||
impl<N: NonceSequence> BoundKey<N> for SealingKey<N> {
|
||||
fn new(key: UnboundKey, nonce_sequence: N) -> Self {
|
||||
Self {
|
||||
key: key.inner,
|
||||
nonce_sequence,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn algorithm(&self) -> &'static Algorithm {
|
||||
self.key.algorithm()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: NonceSequence> core::fmt::Debug for SealingKey<N> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
|
||||
self.key.fmt_debug("SealingKey", f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: NonceSequence> SealingKey<N> {
|
||||
/// Encrypts and signs (“seals”) data in place, appending the tag to the
|
||||
/// resulting ciphertext.
|
||||
///
|
||||
/// `key.seal_in_place_append_tag(aad, in_out)` is equivalent to:
|
||||
///
|
||||
/// ```skip
|
||||
/// key.seal_in_place_separate_tag(aad, in_out.as_mut())
|
||||
/// .map(|tag| in_out.extend(tag.as_ref()))
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn seal_in_place_append_tag<A, InOut>(
|
||||
&mut self,
|
||||
aad: Aad<A>,
|
||||
in_out: &mut InOut,
|
||||
) -> Result<(), error::Unspecified>
|
||||
where
|
||||
A: AsRef<[u8]>,
|
||||
InOut: AsMut<[u8]> + for<'in_out> Extend<&'in_out u8>,
|
||||
{
|
||||
self.key
|
||||
.seal_in_place_append_tag(self.nonce_sequence.advance()?, aad, in_out)
|
||||
}
|
||||
|
||||
/// Encrypts and signs (“seals”) data in place.
|
||||
///
|
||||
/// `aad` is the additional authenticated data (AAD), if any. This is
|
||||
/// authenticated but not encrypted. The type `A` could be a byte slice
|
||||
/// `&[u8]`, a byte array `[u8; N]` for some constant `N`, `Vec<u8>`, etc.
|
||||
/// If there is no AAD then use `Aad::empty()`.
|
||||
///
|
||||
/// The plaintext is given as the input value of `in_out`. `seal_in_place()`
|
||||
/// will overwrite the plaintext with the ciphertext and return the tag.
|
||||
/// For most protocols, the caller must append the tag to the ciphertext.
|
||||
/// The tag will be `self.algorithm.tag_len()` bytes long.
|
||||
#[inline]
|
||||
pub fn seal_in_place_separate_tag<A>(
|
||||
&mut self,
|
||||
aad: Aad<A>,
|
||||
in_out: &mut [u8],
|
||||
) -> Result<Tag, error::Unspecified>
|
||||
where
|
||||
A: AsRef<[u8]>,
|
||||
{
|
||||
self.key
|
||||
.seal_in_place_separate_tag(self.nonce_sequence.advance()?, aad, in_out)
|
||||
}
|
||||
}
|
||||
|
||||
/// The additionally authenticated data (AAD) for an opening or sealing
|
||||
/// operation. This data is authenticated but is **not** encrypted.
|
||||
///
|
||||
@ -320,56 +126,12 @@ where
|
||||
|
||||
impl<A> Eq for Aad<A> where A: Eq {}
|
||||
|
||||
/// An AEAD key without a designated role or nonce sequence.
|
||||
pub struct UnboundKey {
|
||||
inner: LessSafeKey,
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for UnboundKey {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
|
||||
self.inner.fmt_debug("UnboundKey", f)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant, variant_size_differences)]
|
||||
enum KeyInner {
|
||||
AesGcm(aes_gcm::Key),
|
||||
ChaCha20Poly1305(chacha20_poly1305::Key),
|
||||
}
|
||||
|
||||
impl UnboundKey {
|
||||
/// Constructs a `UnboundKey`.
|
||||
///
|
||||
/// Fails if `key_bytes.len() != algorithm.key_len()`.
|
||||
#[inline]
|
||||
pub fn new(
|
||||
algorithm: &'static Algorithm,
|
||||
key_bytes: &[u8],
|
||||
) -> Result<Self, error::Unspecified> {
|
||||
Ok(Self {
|
||||
inner: LessSafeKey::new_(algorithm, key_bytes)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// The key's AEAD algorithm.
|
||||
#[inline]
|
||||
pub fn algorithm(&self) -> &'static Algorithm {
|
||||
self.inner.algorithm()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<hkdf::Okm<'_, &'static Algorithm>> for UnboundKey {
|
||||
fn from(okm: hkdf::Okm<&'static Algorithm>) -> Self {
|
||||
let mut key_bytes = [0; MAX_KEY_LEN];
|
||||
let key_bytes = &mut key_bytes[..okm.len().key_len];
|
||||
let algorithm = *okm.len();
|
||||
okm.fill(key_bytes).unwrap();
|
||||
Self {
|
||||
inner: LessSafeKey::new_(algorithm, key_bytes).unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl hkdf::KeyType for &'static Algorithm {
|
||||
#[inline]
|
||||
fn len(&self) -> usize {
|
||||
@ -485,6 +247,9 @@ pub mod chacha20_poly1305_openssh;
|
||||
mod gcm;
|
||||
mod less_safe_key;
|
||||
mod nonce;
|
||||
mod opening_key;
|
||||
mod poly1305;
|
||||
pub mod quic;
|
||||
mod sealing_key;
|
||||
mod shift;
|
||||
mod unbound_key;
|
||||
|
@ -30,7 +30,7 @@ impl LessSafeKey {
|
||||
/// Constructs a `LessSafeKey`.
|
||||
#[inline]
|
||||
pub fn new(key: UnboundKey) -> Self {
|
||||
key.inner
|
||||
key.into_inner()
|
||||
}
|
||||
|
||||
pub(super) fn new_(
|
||||
|
143
src/aead/opening_key.rs
Normal file
143
src/aead/opening_key.rs
Normal file
@ -0,0 +1,143 @@
|
||||
// Copyright 2015-2021 Brian Smith.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
//! Authenticated Encryption with Associated Data (AEAD).
|
||||
//!
|
||||
//! See [Authenticated encryption: relations among notions and analysis of the
|
||||
//! generic composition paradigm][AEAD] for an introduction to the concept of
|
||||
//! AEADs.
|
||||
//!
|
||||
//! [AEAD]: http://www-cse.ucsd.edu/~mihir/papers/oem.html
|
||||
//! [`crypto.cipher.AEAD`]: https://golang.org/pkg/crypto/cipher/#AEAD
|
||||
|
||||
use super::{Aad, Algorithm, BoundKey, LessSafeKey, NonceSequence, UnboundKey};
|
||||
use crate::error;
|
||||
use core::ops::RangeFrom;
|
||||
|
||||
/// An AEAD key for authenticating and decrypting ("opening"), bound to a nonce
|
||||
/// sequence.
|
||||
///
|
||||
/// Intentionally not `Clone` or `Copy` since cloning would allow duplication
|
||||
/// of the nonce sequence.
|
||||
pub struct OpeningKey<N: NonceSequence> {
|
||||
key: LessSafeKey,
|
||||
nonce_sequence: N,
|
||||
}
|
||||
|
||||
impl<N: NonceSequence> BoundKey<N> for OpeningKey<N> {
|
||||
fn new(key: UnboundKey, nonce_sequence: N) -> Self {
|
||||
Self {
|
||||
key: key.into_inner(),
|
||||
nonce_sequence,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn algorithm(&self) -> &'static Algorithm {
|
||||
self.key.algorithm()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: NonceSequence> core::fmt::Debug for OpeningKey<N> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
|
||||
self.key.fmt_debug("OpeningKey", f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: NonceSequence> OpeningKey<N> {
|
||||
/// Authenticates and decrypts (“opens”) data in place.
|
||||
///
|
||||
/// `aad` is the additional authenticated data (AAD), if any.
|
||||
///
|
||||
/// On input, `in_out` must be the ciphertext followed by the tag. When
|
||||
/// `open_in_place()` returns `Ok(plaintext)`, the input ciphertext
|
||||
/// has been overwritten by the plaintext; `plaintext` will refer to the
|
||||
/// plaintext without the tag.
|
||||
///
|
||||
/// When `open_in_place()` returns `Err(..)`, `in_out` may have been
|
||||
/// overwritten in an unspecified way.
|
||||
#[inline]
|
||||
pub fn open_in_place<'in_out, A>(
|
||||
&mut self,
|
||||
aad: Aad<A>,
|
||||
in_out: &'in_out mut [u8],
|
||||
) -> Result<&'in_out mut [u8], error::Unspecified>
|
||||
where
|
||||
A: AsRef<[u8]>,
|
||||
{
|
||||
self.key
|
||||
.open_in_place(self.nonce_sequence.advance()?, aad, in_out)
|
||||
}
|
||||
|
||||
/// Authenticates and decrypts (“opens”) data in place, with a shift.
|
||||
///
|
||||
/// `aad` is the additional authenticated data (AAD), if any.
|
||||
///
|
||||
/// On input, `in_out[ciphertext_and_tag]` must be the ciphertext followed
|
||||
/// by the tag. When `open_within()` returns `Ok(plaintext)`, the plaintext
|
||||
/// will be at `in_out[0..plaintext.len()]`. In other words, the following
|
||||
/// two code fragments are equivalent for valid values of
|
||||
/// `ciphertext_and_tag`, except `open_within` will often be more efficient:
|
||||
///
|
||||
///
|
||||
/// ```skip
|
||||
/// let plaintext = key.open_within(aad, in_out, cipertext_and_tag)?;
|
||||
/// ```
|
||||
///
|
||||
/// ```skip
|
||||
/// let ciphertext_and_tag_len = in_out[ciphertext_and_tag].len();
|
||||
/// in_out.copy_within(ciphertext_and_tag, 0);
|
||||
/// let plaintext = key.open_in_place(aad, &mut in_out[..ciphertext_and_tag_len])?;
|
||||
/// ```
|
||||
///
|
||||
/// Similarly, `key.open_within(aad, in_out, 0..)` is equivalent to
|
||||
/// `key.open_in_place(aad, in_out)`.
|
||||
///
|
||||
/// When `open_in_place()` returns `Err(..)`, `in_out` may have been
|
||||
/// overwritten in an unspecified way.
|
||||
///
|
||||
/// The shifting feature is useful in the case where multiple packets are
|
||||
/// being reassembled in place. Consider this example where the peer has
|
||||
/// sent the message “Split stream reassembled in place” split into
|
||||
/// three sealed packets:
|
||||
///
|
||||
/// ```ascii-art
|
||||
/// Packet 1 Packet 2 Packet 3
|
||||
/// Input: [Header][Ciphertext][Tag][Header][Ciphertext][Tag][Header][Ciphertext][Tag]
|
||||
/// | +--------------+ |
|
||||
/// +------+ +-----+ +----------------------------------+
|
||||
/// v v v
|
||||
/// Output: [Plaintext][Plaintext][Plaintext]
|
||||
/// “Split stream reassembled in place”
|
||||
/// ```
|
||||
///
|
||||
/// This reassembly be accomplished with three calls to `open_within()`.
|
||||
#[inline]
|
||||
pub fn open_within<'in_out, A>(
|
||||
&mut self,
|
||||
aad: Aad<A>,
|
||||
in_out: &'in_out mut [u8],
|
||||
ciphertext_and_tag: RangeFrom<usize>,
|
||||
) -> Result<&'in_out mut [u8], error::Unspecified>
|
||||
where
|
||||
A: AsRef<[u8]>,
|
||||
{
|
||||
self.key.open_within(
|
||||
self.nonce_sequence.advance()?,
|
||||
aad,
|
||||
in_out,
|
||||
ciphertext_and_tag,
|
||||
)
|
||||
}
|
||||
}
|
104
src/aead/sealing_key.rs
Normal file
104
src/aead/sealing_key.rs
Normal file
@ -0,0 +1,104 @@
|
||||
// Copyright 2015-2021 Brian Smith.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
//! Authenticated Encryption with Associated Data (AEAD).
|
||||
//!
|
||||
//! See [Authenticated encryption: relations among notions and analysis of the
|
||||
//! generic composition paradigm][AEAD] for an introduction to the concept of
|
||||
//! AEADs.
|
||||
//!
|
||||
//! [AEAD]: http://www-cse.ucsd.edu/~mihir/papers/oem.html
|
||||
//! [`crypto.cipher.AEAD`]: https://golang.org/pkg/crypto/cipher/#AEAD
|
||||
|
||||
use super::{Aad, Algorithm, BoundKey, LessSafeKey, NonceSequence, Tag, UnboundKey};
|
||||
use crate::error;
|
||||
|
||||
/// An AEAD key for encrypting and signing ("sealing"), bound to a nonce
|
||||
/// sequence.
|
||||
///
|
||||
/// Intentionally not `Clone` or `Copy` since cloning would allow duplication
|
||||
/// of the nonce sequence.
|
||||
pub struct SealingKey<N: NonceSequence> {
|
||||
key: LessSafeKey,
|
||||
nonce_sequence: N,
|
||||
}
|
||||
|
||||
impl<N: NonceSequence> BoundKey<N> for SealingKey<N> {
|
||||
fn new(key: UnboundKey, nonce_sequence: N) -> Self {
|
||||
Self {
|
||||
key: key.into_inner(),
|
||||
nonce_sequence,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn algorithm(&self) -> &'static Algorithm {
|
||||
self.key.algorithm()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: NonceSequence> core::fmt::Debug for SealingKey<N> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
|
||||
self.key.fmt_debug("SealingKey", f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: NonceSequence> SealingKey<N> {
|
||||
/// Encrypts and signs (“seals”) data in place, appending the tag to the
|
||||
/// resulting ciphertext.
|
||||
///
|
||||
/// `key.seal_in_place_append_tag(aad, in_out)` is equivalent to:
|
||||
///
|
||||
/// ```skip
|
||||
/// key.seal_in_place_separate_tag(aad, in_out.as_mut())
|
||||
/// .map(|tag| in_out.extend(tag.as_ref()))
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn seal_in_place_append_tag<A, InOut>(
|
||||
&mut self,
|
||||
aad: Aad<A>,
|
||||
in_out: &mut InOut,
|
||||
) -> Result<(), error::Unspecified>
|
||||
where
|
||||
A: AsRef<[u8]>,
|
||||
InOut: AsMut<[u8]> + for<'in_out> Extend<&'in_out u8>,
|
||||
{
|
||||
self.key
|
||||
.seal_in_place_append_tag(self.nonce_sequence.advance()?, aad, in_out)
|
||||
}
|
||||
|
||||
/// Encrypts and signs (“seals”) data in place.
|
||||
///
|
||||
/// `aad` is the additional authenticated data (AAD), if any. This is
|
||||
/// authenticated but not encrypted. The type `A` could be a byte slice
|
||||
/// `&[u8]`, a byte array `[u8; N]` for some constant `N`, `Vec<u8>`, etc.
|
||||
/// If there is no AAD then use `Aad::empty()`.
|
||||
///
|
||||
/// The plaintext is given as the input value of `in_out`. `seal_in_place()`
|
||||
/// will overwrite the plaintext with the ciphertext and return the tag.
|
||||
/// For most protocols, the caller must append the tag to the ciphertext.
|
||||
/// The tag will be `self.algorithm.tag_len()` bytes long.
|
||||
#[inline]
|
||||
pub fn seal_in_place_separate_tag<A>(
|
||||
&mut self,
|
||||
aad: Aad<A>,
|
||||
in_out: &mut [u8],
|
||||
) -> Result<Tag, error::Unspecified>
|
||||
where
|
||||
A: AsRef<[u8]>,
|
||||
{
|
||||
self.key
|
||||
.seal_in_place_separate_tag(self.nonce_sequence.advance()?, aad, in_out)
|
||||
}
|
||||
}
|
74
src/aead/unbound_key.rs
Normal file
74
src/aead/unbound_key.rs
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright 2015-2021 Brian Smith.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
//! Authenticated Encryption with Associated Data (AEAD).
|
||||
//!
|
||||
//! See [Authenticated encryption: relations among notions and analysis of the
|
||||
//! generic composition paradigm][AEAD] for an introduction to the concept of
|
||||
//! AEADs.
|
||||
//!
|
||||
//! [AEAD]: http://www-cse.ucsd.edu/~mihir/papers/oem.html
|
||||
//! [`crypto.cipher.AEAD`]: https://golang.org/pkg/crypto/cipher/#AEAD
|
||||
|
||||
use super::{Algorithm, LessSafeKey, MAX_KEY_LEN};
|
||||
use crate::{error, hkdf};
|
||||
|
||||
/// An AEAD key without a designated role or nonce sequence.
|
||||
pub struct UnboundKey {
|
||||
inner: LessSafeKey,
|
||||
}
|
||||
|
||||
impl UnboundKey {
|
||||
/// Constructs a `UnboundKey`.
|
||||
///
|
||||
/// Fails if `key_bytes.len() != algorithm.key_len()`.
|
||||
#[inline]
|
||||
pub fn new(
|
||||
algorithm: &'static Algorithm,
|
||||
key_bytes: &[u8],
|
||||
) -> Result<Self, error::Unspecified> {
|
||||
Ok(Self {
|
||||
inner: LessSafeKey::new_(algorithm, key_bytes)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// The key's AEAD algorithm.
|
||||
#[inline]
|
||||
pub fn algorithm(&self) -> &'static Algorithm {
|
||||
self.inner.algorithm()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn into_inner(self) -> LessSafeKey {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for UnboundKey {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
|
||||
self.inner.fmt_debug("UnboundKey", f)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<hkdf::Okm<'_, &'static Algorithm>> for UnboundKey {
|
||||
fn from(okm: hkdf::Okm<&'static Algorithm>) -> Self {
|
||||
let mut key_bytes = [0; MAX_KEY_LEN];
|
||||
let key_bytes = &mut key_bytes[..okm.len().key_len];
|
||||
let algorithm = *okm.len();
|
||||
okm.fill(key_bytes).unwrap();
|
||||
Self {
|
||||
inner: LessSafeKey::new_(algorithm, key_bytes).unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user