From a5db8f2d8e07593883e7e6aba27eb4e9d54b9460 Mon Sep 17 00:00:00 2001 From: James Cape Date: Fri, 26 Jul 2019 15:18:36 -0700 Subject: [PATCH 01/17] Initial import of aead crate --- .gitignore | 2 + Cargo.toml | 1 + aead/Cargo.toml | 22 +++++ aead/LICENSE-APACHE | 202 +++++++++++++++++++++++++++++++++++++++++ aead/LICENSE-MIT | 25 ++++++ aead/README.md | 6 ++ aead/rustfmt.toml | 1 + aead/src/lib.rs | 214 ++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 473 insertions(+) create mode 100644 aead/Cargo.toml create mode 100644 aead/LICENSE-APACHE create mode 100644 aead/LICENSE-MIT create mode 100644 aead/README.md create mode 100644 aead/rustfmt.toml create mode 100644 aead/src/lib.rs diff --git a/.gitignore b/.gitignore index 9de1de063..37af649ab 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ target/ */target/ */*/target/ Cargo.lock +.idea + diff --git a/Cargo.toml b/Cargo.toml index dca699d61..4cd5b075e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,6 @@ [workspace] members = [ + "aead", "block-cipher-trait", "crypto-mac", "digest", diff --git a/aead/Cargo.toml b/aead/Cargo.toml new file mode 100644 index 000000000..40cbb570e --- /dev/null +++ b/aead/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "aead" +version = "0.1.0" +authors = ["James Cape "] +edition = "2018" +description = """ +The RFC5116 AEAD API, as a trait. +""" + +[features] +nightly = [ + "clear_on_drop/nightly", +] + +[dependencies] +cfg-if = "0.1" +clear_on_drop = { version = "0.2.3", default-features = false } +failure = { version = "0.1.5", default-features = false, features = ["derive"] } +generic-array = { version = "0.12", default-features = false } +rand_core = { version = "0.4", default-features = false } +serde = { version = "1.0", default-features = false, optional = true, features = ["derive"] } +serde_derive = { version = "1.0", optional = true } diff --git a/aead/LICENSE-APACHE b/aead/LICENSE-APACHE new file mode 100644 index 000000000..7650239c7 --- /dev/null +++ b/aead/LICENSE-APACHE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + diff --git a/aead/LICENSE-MIT b/aead/LICENSE-MIT new file mode 100644 index 000000000..8dcb85b30 --- /dev/null +++ b/aead/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2017 Artyom Pavlov + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/aead/README.md b/aead/README.md new file mode 100644 index 000000000..ee6d0e6b5 --- /dev/null +++ b/aead/README.md @@ -0,0 +1,6 @@ +# Authenticated Encryption with Additional Data + +This crate provides the rust trait equivilent of the AEAD API defined in +RFC5116. As a result, it should provide nearly drop-in support for any +compliant AEAD scheme, including AES-GCM, AES-CCM, ChaCha20-Poly1305, +AES-CBC-HMAC, etc. diff --git a/aead/rustfmt.toml b/aead/rustfmt.toml new file mode 100644 index 000000000..7d2cf549d --- /dev/null +++ b/aead/rustfmt.toml @@ -0,0 +1 @@ +merge_imports = true diff --git a/aead/src/lib.rs b/aead/src/lib.rs new file mode 100644 index 000000000..17a5d8473 --- /dev/null +++ b/aead/src/lib.rs @@ -0,0 +1,214 @@ +//! A set of traits designed to support authenticated encryption. + +#![no_std] + +extern crate alloc; + +use alloc::vec::Vec; +use core::{ + convert::TryFrom, + fmt::{Debug, Display, Formatter, Result as FmtResult}, +}; +use failure::Fail; +use generic_array::{ + typenum::{Unsigned, U0}, + ArrayLength, +}; +use rand_core::{CryptoRng, RngCore}; + +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialze}; + +/// An enum describing possible failure modes +#[cfg(feature = "serde")] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Fail, Hash, Ord, PartialEq, PartialOrd, Serialize)] +pub enum AeadError { + /// The nonce provided is the wrong size for this algorithm. + #[fail(display = "The nonce given is the wrong size for the algorithm")] + InvalidNonceSize, + /// The ciphertext buffer is not a multiple of the block size + #[fail(display = "The buffer given is the wrong size for the algorithm")] + InvalidBufferSize, + /// The "bytes used" provided is larger than the provided buffer + #[fail(display = "The buffer usage is larger than the buffer size")] + InvalidBufferUsed, + /// The authentication tag is not the correct size + #[fail(display = "The authentication tag is the wrong size for the algorithm")] + InvalidTagSize, + /// The cipher key was not the size of a block + #[fail(display = "The cipher key given on creation was the wrong size")] + InvalidCipherKeySize, + /// The initialization vector was not the size of a block + #[fail(display = "The IV given on creation was the wrong size")] + InvalidIvSize, + /// The authentication tag is not the size expected by this algorithm + #[fail(display = "The key used for the authentication algorithm was the wrong size")] + InvalidTagKeySize, + + #[fail( + display = "The given ciphertext is larger than the maximum size allowed by this algorithm" + )] + CiphertextTooLarge, + #[fail( + display = "The given plaintext is larger than the maximum size allowed by this algorithm" + )] + PlaintextTooLarge, + + /// The MAC failed to validate. This should be used to indicated a modified + /// ciphertext, modified additional data, or key mismatch. + #[fail(display = "The MAC failed to validate")] + MacFailure, + /// There was an error parsing the padding of this message + #[fail(display = "The padding was not correct")] + PaddingFailure, +} + +/// An enum describing possible failure modes +#[cfg(not(feature = "serde"))] +#[derive(Clone, Copy, Debug, Eq, Fail, Hash, Ord, PartialEq, PartialOrd)] +pub enum AeadError { + /// The nonce provided is the wrong size for this algorithm. + #[fail(display = "The nonce given is the wrong size for the algorithm")] + InvalidNonceSize, + /// The ciphertext buffer is not a multiple of the block size + #[fail(display = "The buffer given is the wrong size for the algorithm")] + InvalidBufferSize, + /// The "bytes used" provided is larger than the provided buffer + #[fail(display = "The buffer usage is larger than the buffer size")] + InvalidBufferUsed, + /// The authentication tag is not the correct size + #[fail(display = "The authentication tag is the wrong size for the algorithm")] + InvalidTagSize, + /// The cipher key was not the size of a block + #[fail(display = "The cipher key given on creation was the wrong size")] + InvalidCipherKeySize, + /// The initialization vector was not the size of a block + #[fail(display = "The IV given on creation was the wrong size")] + InvalidIvSize, + /// The authentication tag is not the size expected by this algorithm + #[fail(display = "The key used for the authentication algorithm was the wrong size")] + InvalidTagKeySize, + + #[fail( + display = "The given ciphertext is larger than the maximum size allowed by this algorithm" + )] + CiphertextTooLarge, + #[fail( + display = "The given plaintext is larger than the maximum size allowed by this algorithm" + )] + PlaintextTooLarge, + + /// The MAC failed to validate. This should be used to indicated a modified + /// ciphertext, modified additional data, or key mismatch. + #[fail(display = "The MAC failed to validate")] + MacFailure, + /// There was an error parsing the padding of this message + #[fail(display = "The padding was not correct")] + PaddingFailure, +} + +/// A trait used to tag ciphertext inputs/outputs for an authenticated block cipher +pub trait Ciphertext: + Clone + + Debug + + Display + + Into> + + Send + + Sized + + Sync + + for<'bytes> TryFrom<&'bytes [u8], Error = AeadError> +{ + /// Retrieve the length of the ciphertext, in bytes + fn len(&self) -> usize; +} + +/// An explicit cryptographic nonce, which may be optionally used for +/// authenticated block ciphers. +pub trait Nonce: + Clone + + Debug + + Display + + Into> + + Send + + Sized + + Sync + + for<'bytes> TryFrom<&'bytes [u8], Error = AeadError> +{ + /// The length of an explicit nonce, in bytes. + type Len: ArrayLength + Unsigned; +} + +/// A standard nonce implementation for AEAD algorithms which do not use +/// explicit nonces. +#[cfg(feature = "serde")] +#[derive( + Clone, Copy, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, +)] +pub struct EmptyNonce; +#[cfg(not(feature = "serde"))] +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct EmptyNonce; + +/// Output an empty-array style string for the EmptyNonce display. +impl Display for EmptyNonce { + fn fmt(&self, f: &mut Formatter) -> FmtResult { + write!(f, "[]") + } +} + +/// Size restrictions for the Emtpy Nonce type +impl Nonce for EmptyNonce { + type Len = U0; +} + +/// An empty nonce can be converted into an empty vector +impl Into> for EmptyNonce { + fn into(self) -> Vec { + Vec::default() + } +} + +/// Load this nonce from a byte slice (myst be zero-length) +impl<'bytes> TryFrom<&'bytes [u8]> for EmptyNonce { + type Error = AeadError; + + fn try_from(src: &[u8]) -> Result { + if src.len() != 0 { + Err(AeadError::InvalidNonceSize) + } else { + Ok(EmptyNonce) + } + } +} + +/// A trait which can support an RFC5116-style authenticated encryption scheme. +/// +/// In order to reduce the opportunity for misuse, the nonce used for +/// encryption is meant to be managed internally by the implementation itself. +pub trait AuthenticatedBlockCipher: Sized + Send + Sync +where + for<'ciphertext> Vec: From<&'ciphertext Self::Ciphertext>, +{ + /// The message encapsulation type + type Ciphertext: Ciphertext; + + /// The cryptographic nonce object used for this cipher + type Nonce: Nonce; + + /// Encrypts the given plaintext into a new ciphertext object and the nonce + fn encrypt<'ad, RngType: CryptoRng + RngCore>( + &mut self, + csprng: &mut RngType, + additional_data: impl Iterator, + plaintext: &[u8], + ) -> Result<(Self::Ciphertext, Self::Nonce), AeadError>; + + /// Authenticates the ciphertext, nonce, and additional data, then + /// decrypts the ciphertext contents into plaintext. + fn decrypt<'ad>( + &self, + additional_data: impl Iterator, + nonce: Self::Nonce, + ciphertext: Self::Ciphertext, + ) -> Result, AeadError>; +} From 318a345b945fdb035d920d2c241134188dd2a156 Mon Sep 17 00:00:00 2001 From: James Cape Date: Tue, 6 Aug 2019 16:33:22 -0700 Subject: [PATCH 02/17] Changes based on PR discussion: 1. Remove alloc 1. enum AeadError { ... } -> struct Error(); 1. Remove "helper" associated types 1. Adjust API to work in-place with buffer+len 1. Distinguish between the RFC-default "stateless" APIs and the stateful APIs. 1. Provide a compatibility wrapper for treating stateless APIs as stateful. 1. Remove direct support for randomized AEADs, because an RNG is a subset of "external state", AEADs which do need it can handle it internally. --- aead/Cargo.toml | 11 -- aead/src/lib.rs | 322 +++++++++++++++++++----------------------------- 2 files changed, 128 insertions(+), 205 deletions(-) diff --git a/aead/Cargo.toml b/aead/Cargo.toml index 40cbb570e..93a39fdbf 100644 --- a/aead/Cargo.toml +++ b/aead/Cargo.toml @@ -7,16 +7,5 @@ description = """ The RFC5116 AEAD API, as a trait. """ -[features] -nightly = [ - "clear_on_drop/nightly", -] - [dependencies] -cfg-if = "0.1" -clear_on_drop = { version = "0.2.3", default-features = false } -failure = { version = "0.1.5", default-features = false, features = ["derive"] } generic-array = { version = "0.12", default-features = false } -rand_core = { version = "0.4", default-features = false } -serde = { version = "1.0", default-features = false, optional = true, features = ["derive"] } -serde_derive = { version = "1.0", optional = true } diff --git a/aead/src/lib.rs b/aead/src/lib.rs index 17a5d8473..772d989a7 100644 --- a/aead/src/lib.rs +++ b/aead/src/lib.rs @@ -2,213 +2,147 @@ #![no_std] -extern crate alloc; - -use alloc::vec::Vec; -use core::{ - convert::TryFrom, - fmt::{Debug, Display, Formatter, Result as FmtResult}, -}; -use failure::Fail; -use generic_array::{ - typenum::{Unsigned, U0}, - ArrayLength, -}; -use rand_core::{CryptoRng, RngCore}; - -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialze}; - -/// An enum describing possible failure modes -#[cfg(feature = "serde")] -#[derive(Clone, Copy, Debug, Deserialize, Eq, Fail, Hash, Ord, PartialEq, PartialOrd, Serialize)] -pub enum AeadError { - /// The nonce provided is the wrong size for this algorithm. - #[fail(display = "The nonce given is the wrong size for the algorithm")] - InvalidNonceSize, - /// The ciphertext buffer is not a multiple of the block size - #[fail(display = "The buffer given is the wrong size for the algorithm")] - InvalidBufferSize, - /// The "bytes used" provided is larger than the provided buffer - #[fail(display = "The buffer usage is larger than the buffer size")] - InvalidBufferUsed, - /// The authentication tag is not the correct size - #[fail(display = "The authentication tag is the wrong size for the algorithm")] - InvalidTagSize, - /// The cipher key was not the size of a block - #[fail(display = "The cipher key given on creation was the wrong size")] - InvalidCipherKeySize, - /// The initialization vector was not the size of a block - #[fail(display = "The IV given on creation was the wrong size")] - InvalidIvSize, - /// The authentication tag is not the size expected by this algorithm - #[fail(display = "The key used for the authentication algorithm was the wrong size")] - InvalidTagKeySize, - - #[fail( - display = "The given ciphertext is larger than the maximum size allowed by this algorithm" - )] - CiphertextTooLarge, - #[fail( - display = "The given plaintext is larger than the maximum size allowed by this algorithm" - )] - PlaintextTooLarge, - - /// The MAC failed to validate. This should be used to indicated a modified - /// ciphertext, modified additional data, or key mismatch. - #[fail(display = "The MAC failed to validate")] - MacFailure, - /// There was an error parsing the padding of this message - #[fail(display = "The padding was not correct")] - PaddingFailure, -} - -/// An enum describing possible failure modes -#[cfg(not(feature = "serde"))] -#[derive(Clone, Copy, Debug, Eq, Fail, Hash, Ord, PartialEq, PartialOrd)] -pub enum AeadError { - /// The nonce provided is the wrong size for this algorithm. - #[fail(display = "The nonce given is the wrong size for the algorithm")] - InvalidNonceSize, - /// The ciphertext buffer is not a multiple of the block size - #[fail(display = "The buffer given is the wrong size for the algorithm")] - InvalidBufferSize, - /// The "bytes used" provided is larger than the provided buffer - #[fail(display = "The buffer usage is larger than the buffer size")] - InvalidBufferUsed, - /// The authentication tag is not the correct size - #[fail(display = "The authentication tag is the wrong size for the algorithm")] - InvalidTagSize, - /// The cipher key was not the size of a block - #[fail(display = "The cipher key given on creation was the wrong size")] - InvalidCipherKeySize, - /// The initialization vector was not the size of a block - #[fail(display = "The IV given on creation was the wrong size")] - InvalidIvSize, - /// The authentication tag is not the size expected by this algorithm - #[fail(display = "The key used for the authentication algorithm was the wrong size")] - InvalidTagKeySize, - - #[fail( - display = "The given ciphertext is larger than the maximum size allowed by this algorithm" - )] - CiphertextTooLarge, - #[fail( - display = "The given plaintext is larger than the maximum size allowed by this algorithm" - )] - PlaintextTooLarge, - - /// The MAC failed to validate. This should be used to indicated a modified - /// ciphertext, modified additional data, or key mismatch. - #[fail(display = "The MAC failed to validate")] - MacFailure, - /// There was an error parsing the padding of this message - #[fail(display = "The padding was not correct")] - PaddingFailure, +use generic_array::{GenericArray, ArrayLength, typenum::Unsigned}; +use core::marker::PhantomData; + +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct Error; + +/// A trait which can support a stateful, RFC5116 authenticated encryption +/// scheme. +pub trait Aead: Sized { + /// The key size in a new method. + type KeyLength: ArrayLength + Unsigned; + /// The maximum length a plaintext can be. + type PlaintextMax: ArrayLength + Unsigned; + /// The maximum length a ciphertext can be. + type CiphertextMax: ArrayLength + Unsigned; + /// The maximum length of the associated data. + type AssociatedDataMax: ArrayLength + Unsigned; + /// The minimum length of the nonce. + type NonceMin: ArrayLength + Unsigned; + /// The maximum length of the nonce. + type NonceMax: ArrayLength + Unsigned; + + /// An actual type for the nonce + type Nonce; + + /// Retrieve the size of the buffer required for plaintext of a given size. + fn ciphertext_len(&self, plaintext_used: usize) -> usize; + + /// Construct a new stateful instance for the given key. + fn for_key(key: GenericArray) -> Self; + + /// Perform an in-place encryption of the given plaintext, which is built + /// from the first plaintext_used bytes of the pre-populated plaintext + /// buffer. + /// + /// Implementers are responsible for shifting any existing contents of the + /// plaintext, if necessary, and returning a slice trimmed to the + /// algorithm-specific ciphertext. + fn encrypt<'in_out>( + &mut self, + additional_data: impl Iterator>, + nonce: &mut Self::Nonce, + plaintext: &'in_out mut [u8], + plaintext_used: usize, + ) -> Result<&'in_out mut [u8], Error>; + + /// Perform an in-place decryption of the given ciphertext, as constructed + /// by the algorithm's `encrypt()` method, and returns a slice of the + /// plaintext. + fn decrypt<'in_out>( + &mut self, + additional_data: impl Iterator>, + nonce: &Self::Nonce, + ciphertext: &'in_out mut [u8], + ) -> Result<&'in_out mut [u8], Error>; } -/// A trait used to tag ciphertext inputs/outputs for an authenticated block cipher -pub trait Ciphertext: - Clone - + Debug - + Display - + Into> - + Send - + Sized - + Sync - + for<'bytes> TryFrom<&'bytes [u8], Error = AeadError> -{ - /// Retrieve the length of the ciphertext, in bytes - fn len(&self) -> usize; -} +/// A trait which can support a stateless RFC5116 authenticated encryption +/// scheme. This is the standard RFC algorithm. +pub trait StatelessAead { + /// The key size in a new method. + type KeyLength: ArrayLength + Unsigned; + /// The maximum length a plaintext can be. + type PlaintextMax: ArrayLength + Unsigned; + /// The maximum length a ciphertext can be. + type CiphertextMax: ArrayLength + Unsigned; + /// The maximum length of the associated data. + type AssociatedDataMax: ArrayLength + Unsigned; + /// The minimum length of the nonce. + type NonceMin: ArrayLength + Unsigned; + /// The maximum length of the nonce. + type NonceMax: ArrayLength + Unsigned; + + /// An actual type indicating the nonce + type Nonce; + + /// Retrieve the size of the buffer required for plaintext of a given size. + fn ciphertext_len(plaintext_used: usize) -> usize; -/// An explicit cryptographic nonce, which may be optionally used for -/// authenticated block ciphers. -pub trait Nonce: - Clone - + Debug - + Display - + Into> - + Send - + Sized - + Sync - + for<'bytes> TryFrom<&'bytes [u8], Error = AeadError> -{ - /// The length of an explicit nonce, in bytes. - type Len: ArrayLength + Unsigned; -} + /// Encrypts the given plaintext into a new ciphertext object and the nonce + fn encrypt<'in_out>( + key: &GenericArray, + additional_data: impl Iterator>, + nonce: &mut Self::Nonce, + plaintext: &'in_out mut [u8], + plaintext_used: usize, + ) -> Result<&'in_out mut [u8], Error>; -/// A standard nonce implementation for AEAD algorithms which do not use -/// explicit nonces. -#[cfg(feature = "serde")] -#[derive( - Clone, Copy, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, -)] -pub struct EmptyNonce; -#[cfg(not(feature = "serde"))] -#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct EmptyNonce; - -/// Output an empty-array style string for the EmptyNonce display. -impl Display for EmptyNonce { - fn fmt(&self, f: &mut Formatter) -> FmtResult { - write!(f, "[]") - } + /// Authenticates the ciphertext, nonce, and additional data, then + /// decrypts the ciphertext contents into plaintext. + fn decrypt<'in_out>( + key: &GenericArray, + additional_data: impl Iterator>, + nonce: &Self::Nonce, + ciphertext: &'in_out mut [u8], + ) -> Result<&'in_out mut [u8], Error>; } -/// Size restrictions for the Emtpy Nonce type -impl Nonce for EmptyNonce { - type Len = U0; +/// A wrapper structure to allow using a stateless AEAD from the stateful +/// interface. +pub struct Stateful { + key: GenericArray::KeyLength>, + _aead: PhantomData Algo> } -/// An empty nonce can be converted into an empty vector -impl Into> for EmptyNonce { - fn into(self) -> Vec { - Vec::default() +impl Aead for Stateful { + type KeyLength = Algo::KeyLength; + type PlaintextMax = Algo::PlaintextMax; + type CiphertextMax = Algo::CiphertextMax; + type AssociatedDataMax = Algo::AssociatedDataMax; + type NonceMin = Algo::NonceMin; + type NonceMax = Algo::NonceMax; + type Nonce = Algo::Nonce; + + fn ciphertext_len(&self, plaintext_used: usize) -> usize { + Algo::ciphertext_len(plaintext_used) } -} -/// Load this nonce from a byte slice (myst be zero-length) -impl<'bytes> TryFrom<&'bytes [u8]> for EmptyNonce { - type Error = AeadError; - - fn try_from(src: &[u8]) -> Result { - if src.len() != 0 { - Err(AeadError::InvalidNonceSize) - } else { - Ok(EmptyNonce) + fn for_key(key: GenericArray) -> Self { + Self { + key, + _aead: PhantomData::default(), } } -} - -/// A trait which can support an RFC5116-style authenticated encryption scheme. -/// -/// In order to reduce the opportunity for misuse, the nonce used for -/// encryption is meant to be managed internally by the implementation itself. -pub trait AuthenticatedBlockCipher: Sized + Send + Sync -where - for<'ciphertext> Vec: From<&'ciphertext Self::Ciphertext>, -{ - /// The message encapsulation type - type Ciphertext: Ciphertext; - /// The cryptographic nonce object used for this cipher - type Nonce: Nonce; - - /// Encrypts the given plaintext into a new ciphertext object and the nonce - fn encrypt<'ad, RngType: CryptoRng + RngCore>( + fn encrypt<'in_out>( &mut self, - csprng: &mut RngType, - additional_data: impl Iterator, - plaintext: &[u8], - ) -> Result<(Self::Ciphertext, Self::Nonce), AeadError>; + additional_data: impl Iterator>, + nonce: &mut Self::Nonce, + plaintext: &'in_out mut [u8], + plaintext_used: usize, + ) -> Result<&'in_out mut [u8], Error> { + Algo::encrypt(&self.key, additional_data, nonce, plaintext, plaintext_used) + } - /// Authenticates the ciphertext, nonce, and additional data, then - /// decrypts the ciphertext contents into plaintext. - fn decrypt<'ad>( - &self, - additional_data: impl Iterator, - nonce: Self::Nonce, - ciphertext: Self::Ciphertext, - ) -> Result, AeadError>; + fn decrypt<'in_out>( + &mut self, + additional_data: impl Iterator>, + nonce: &Self::Nonce, + ciphertext: &'in_out mut [u8], + ) -> Result<&'in_out mut [u8], Error> { + Algo::decrypt(&self.key, additional_data, nonce, ciphertext) + } } From 407f921f289da13fc352a6bd1d0b1e276f95f58b Mon Sep 17 00:00:00 2001 From: James Cape Date: Tue, 6 Aug 2019 16:50:26 -0700 Subject: [PATCH 03/17] Fix compile error on older rust --- aead/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aead/src/lib.rs b/aead/src/lib.rs index 772d989a7..3b525e714 100644 --- a/aead/src/lib.rs +++ b/aead/src/lib.rs @@ -2,7 +2,8 @@ #![no_std] -use generic_array::{GenericArray, ArrayLength, typenum::Unsigned}; +use generic_array::typenum::Unsigned; +use generic_array::{GenericArray, ArrayLength}; use core::marker::PhantomData; #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] From ccfc6700b6b4f7dacf849a994916211c62f48047 Mon Sep 17 00:00:00 2001 From: James Cape Date: Tue, 6 Aug 2019 17:59:02 -0700 Subject: [PATCH 04/17] 1.21.0 build fixes: - Don't make Aead Sized (not required here). - Don't do 2018 edition. - Use extern crate. - Don't use impl Trait. --- aead/Cargo.toml | 1 - aead/src/lib.rs | 30 ++++++++++++++++-------------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/aead/Cargo.toml b/aead/Cargo.toml index 93a39fdbf..16f9cdef0 100644 --- a/aead/Cargo.toml +++ b/aead/Cargo.toml @@ -2,7 +2,6 @@ name = "aead" version = "0.1.0" authors = ["James Cape "] -edition = "2018" description = """ The RFC5116 AEAD API, as a trait. """ diff --git a/aead/src/lib.rs b/aead/src/lib.rs index 3b525e714..f8744704e 100644 --- a/aead/src/lib.rs +++ b/aead/src/lib.rs @@ -2,6 +2,8 @@ #![no_std] +extern crate generic_array; + use generic_array::typenum::Unsigned; use generic_array::{GenericArray, ArrayLength}; use core::marker::PhantomData; @@ -11,7 +13,7 @@ pub struct Error; /// A trait which can support a stateful, RFC5116 authenticated encryption /// scheme. -pub trait Aead: Sized { +pub trait Aead { /// The key size in a new method. type KeyLength: ArrayLength + Unsigned; /// The maximum length a plaintext can be. @@ -41,9 +43,9 @@ pub trait Aead: Sized { /// Implementers are responsible for shifting any existing contents of the /// plaintext, if necessary, and returning a slice trimmed to the /// algorithm-specific ciphertext. - fn encrypt<'in_out>( + fn encrypt<'in_out, AdItem: AsRef<[u8]>, AdIter: Iterator>( &mut self, - additional_data: impl Iterator>, + additional_data: AdIter, nonce: &mut Self::Nonce, plaintext: &'in_out mut [u8], plaintext_used: usize, @@ -52,9 +54,9 @@ pub trait Aead: Sized { /// Perform an in-place decryption of the given ciphertext, as constructed /// by the algorithm's `encrypt()` method, and returns a slice of the /// plaintext. - fn decrypt<'in_out>( + fn decrypt<'in_out, AdItem: AsRef<[u8]>, AdIter: Iterator>( &mut self, - additional_data: impl Iterator>, + additional_data: AdIter, nonce: &Self::Nonce, ciphertext: &'in_out mut [u8], ) -> Result<&'in_out mut [u8], Error>; @@ -83,9 +85,9 @@ pub trait StatelessAead { fn ciphertext_len(plaintext_used: usize) -> usize; /// Encrypts the given plaintext into a new ciphertext object and the nonce - fn encrypt<'in_out>( + fn encrypt<'in_out, AdItem: AsRef<[u8]>, AdIter: Iterator>( key: &GenericArray, - additional_data: impl Iterator>, + additional_data: AdIter, nonce: &mut Self::Nonce, plaintext: &'in_out mut [u8], plaintext_used: usize, @@ -93,9 +95,9 @@ pub trait StatelessAead { /// Authenticates the ciphertext, nonce, and additional data, then /// decrypts the ciphertext contents into plaintext. - fn decrypt<'in_out>( + fn decrypt<'in_out, AdItem: AsRef<[u8]>, AdIter: Iterator>( key: &GenericArray, - additional_data: impl Iterator>, + additional_data: AdIter, nonce: &Self::Nonce, ciphertext: &'in_out mut [u8], ) -> Result<&'in_out mut [u8], Error>; @@ -104,7 +106,7 @@ pub trait StatelessAead { /// A wrapper structure to allow using a stateless AEAD from the stateful /// interface. pub struct Stateful { - key: GenericArray::KeyLength>, + key: GenericArray, _aead: PhantomData Algo> } @@ -128,9 +130,9 @@ impl Aead for Stateful { } } - fn encrypt<'in_out>( + fn encrypt<'in_out, AdItem: AsRef<[u8]>, AdIter: Iterator>( &mut self, - additional_data: impl Iterator>, + additional_data: AdIter, nonce: &mut Self::Nonce, plaintext: &'in_out mut [u8], plaintext_used: usize, @@ -138,9 +140,9 @@ impl Aead for Stateful { Algo::encrypt(&self.key, additional_data, nonce, plaintext, plaintext_used) } - fn decrypt<'in_out>( + fn decrypt<'in_out, AdItem: AsRef<[u8]>, AdIter: Iterator>( &mut self, - additional_data: impl Iterator>, + additional_data: AdIter, nonce: &Self::Nonce, ciphertext: &'in_out mut [u8], ) -> Result<&'in_out mut [u8], Error> { From 055cf26d0cd864b59e809d7407eb9a54656f42c6 Mon Sep 17 00:00:00 2001 From: James Cape Date: Tue, 6 Aug 2019 18:11:55 -0700 Subject: [PATCH 05/17] Add no-op std/dev features to pass CI --- aead/Cargo.toml | 4 ++++ aead/src/lib.rs | 2 ++ 2 files changed, 6 insertions(+) diff --git a/aead/Cargo.toml b/aead/Cargo.toml index 16f9cdef0..6c6eb74b5 100644 --- a/aead/Cargo.toml +++ b/aead/Cargo.toml @@ -6,5 +6,9 @@ description = """ The RFC5116 AEAD API, as a trait. """ +[features] +std = [] +dev = [] + [dependencies] generic-array = { version = "0.12", default-features = false } diff --git a/aead/src/lib.rs b/aead/src/lib.rs index f8744704e..92ab6374e 100644 --- a/aead/src/lib.rs +++ b/aead/src/lib.rs @@ -149,3 +149,5 @@ impl Aead for Stateful { Algo::decrypt(&self.key, additional_data, nonce, ciphertext) } } + + From 9370d14ca477ddbf057708d2927d29dac368bd49 Mon Sep 17 00:00:00 2001 From: James Cape Date: Wed, 7 Aug 2019 13:17:28 -0700 Subject: [PATCH 06/17] PR Comments + Vec API - Add an alloc feature, make std do stuff. - Reduce volume of associated-types, adjust appropriately. Note, this deviates from RFC5116 in that we only support fixed-length nonces, instead of the N_MAX/N_MIN from the RFC. --- aead/Cargo.toml | 1 + aead/src/lib.rs | 204 ++++++++++++++++++++++++++++++++++-------------- 2 files changed, 148 insertions(+), 57 deletions(-) diff --git a/aead/Cargo.toml b/aead/Cargo.toml index 6c6eb74b5..85978c519 100644 --- a/aead/Cargo.toml +++ b/aead/Cargo.toml @@ -9,6 +9,7 @@ The RFC5116 AEAD API, as a trait. [features] std = [] dev = [] +alloc = [] [dependencies] generic-array = { version = "0.12", default-features = false } diff --git a/aead/src/lib.rs b/aead/src/lib.rs index 92ab6374e..d7c8cc694 100644 --- a/aead/src/lib.rs +++ b/aead/src/lib.rs @@ -1,7 +1,10 @@ //! A set of traits designed to support authenticated encryption. -#![no_std] +#![cfg_attr(not(any(feature = "std", feature = "alloc")), no_std)] +#![cfg_attr(all(feature = "alloc", not(has_extern_crate_alloc)), feature(alloc))] +#![cfg(feature = "std")] +extern crate core; extern crate generic_array; use generic_array::typenum::Unsigned; @@ -12,29 +15,20 @@ use core::marker::PhantomData; pub struct Error; /// A trait which can support a stateful, RFC5116 authenticated encryption -/// scheme. +/// scheme with a fixed-size nonce. pub trait Aead { /// The key size in a new method. - type KeyLength: ArrayLength + Unsigned; - /// The maximum length a plaintext can be. - type PlaintextMax: ArrayLength + Unsigned; - /// The maximum length a ciphertext can be. - type CiphertextMax: ArrayLength + Unsigned; - /// The maximum length of the associated data. - type AssociatedDataMax: ArrayLength + Unsigned; - /// The minimum length of the nonce. - type NonceMin: ArrayLength + Unsigned; + type KeySize: ArrayLength + Unsigned; + /// The length of a nonce. + type NonceSize: ArrayLength + Unsigned; /// The maximum length of the nonce. - type NonceMax: ArrayLength + Unsigned; - - /// An actual type for the nonce - type Nonce; - - /// Retrieve the size of the buffer required for plaintext of a given size. - fn ciphertext_len(&self, plaintext_used: usize) -> usize; + type TagSize: ArrayLength + Unsigned; + /// The amount of suffix padding, in bytes, which needs to be appended to + /// a plaintext to accommodate this cipher's output. + type CiphertextOverhead: ArrayLength + Unsigned; /// Construct a new stateful instance for the given key. - fn for_key(key: GenericArray) -> Self; + fn for_key(key: GenericArray) -> Self; /// Perform an in-place encryption of the given plaintext, which is built /// from the first plaintext_used bytes of the pre-populated plaintext @@ -46,7 +40,7 @@ pub trait Aead { fn encrypt<'in_out, AdItem: AsRef<[u8]>, AdIter: Iterator>( &mut self, additional_data: AdIter, - nonce: &mut Self::Nonce, + nonce: &mut GenericArray, plaintext: &'in_out mut [u8], plaintext_used: usize, ) -> Result<&'in_out mut [u8], Error>; @@ -57,7 +51,7 @@ pub trait Aead { fn decrypt<'in_out, AdItem: AsRef<[u8]>, AdIter: Iterator>( &mut self, additional_data: AdIter, - nonce: &Self::Nonce, + nonce: &GenericArray, ciphertext: &'in_out mut [u8], ) -> Result<&'in_out mut [u8], Error>; } @@ -66,29 +60,20 @@ pub trait Aead { /// scheme. This is the standard RFC algorithm. pub trait StatelessAead { /// The key size in a new method. - type KeyLength: ArrayLength + Unsigned; - /// The maximum length a plaintext can be. - type PlaintextMax: ArrayLength + Unsigned; - /// The maximum length a ciphertext can be. - type CiphertextMax: ArrayLength + Unsigned; - /// The maximum length of the associated data. - type AssociatedDataMax: ArrayLength + Unsigned; - /// The minimum length of the nonce. - type NonceMin: ArrayLength + Unsigned; + type KeySize: ArrayLength + Unsigned; + /// The length of a nonce. + type NonceSize: ArrayLength + Unsigned; /// The maximum length of the nonce. - type NonceMax: ArrayLength + Unsigned; - - /// An actual type indicating the nonce - type Nonce; - - /// Retrieve the size of the buffer required for plaintext of a given size. - fn ciphertext_len(plaintext_used: usize) -> usize; + type TagSize: ArrayLength + Unsigned; + /// The amount of suffix padding, in bytes, which needs to be + /// appended to a plaintext to accomodate this cipher's output. + type CiphertextOverhead: ArrayLength + Unsigned; /// Encrypts the given plaintext into a new ciphertext object and the nonce fn encrypt<'in_out, AdItem: AsRef<[u8]>, AdIter: Iterator>( - key: &GenericArray, + key: &GenericArray, additional_data: AdIter, - nonce: &mut Self::Nonce, + nonce: &mut GenericArray, plaintext: &'in_out mut [u8], plaintext_used: usize, ) -> Result<&'in_out mut [u8], Error>; @@ -96,34 +81,27 @@ pub trait StatelessAead { /// Authenticates the ciphertext, nonce, and additional data, then /// decrypts the ciphertext contents into plaintext. fn decrypt<'in_out, AdItem: AsRef<[u8]>, AdIter: Iterator>( - key: &GenericArray, + key: &GenericArray, additional_data: AdIter, - nonce: &Self::Nonce, + nonce: &GenericArray, ciphertext: &'in_out mut [u8], ) -> Result<&'in_out mut [u8], Error>; } -/// A wrapper structure to allow using a stateless AEAD from the stateful +/// A wrapper structure to allow use of a stateless AEAD through the stateful /// interface. pub struct Stateful { - key: GenericArray, + key: GenericArray, _aead: PhantomData Algo> } impl Aead for Stateful { - type KeyLength = Algo::KeyLength; - type PlaintextMax = Algo::PlaintextMax; - type CiphertextMax = Algo::CiphertextMax; - type AssociatedDataMax = Algo::AssociatedDataMax; - type NonceMin = Algo::NonceMin; - type NonceMax = Algo::NonceMax; - type Nonce = Algo::Nonce; - - fn ciphertext_len(&self, plaintext_used: usize) -> usize { - Algo::ciphertext_len(plaintext_used) - } + type KeySize = Algo::KeySize; + type NonceSize = Algo::NonceSize; + type TagSize = Algo::TagSize; + type CiphertextOverhead = Algo::CiphertextOverhead; - fn for_key(key: GenericArray) -> Self { + fn for_key(key: GenericArray) -> Self { Self { key, _aead: PhantomData::default(), @@ -133,7 +111,7 @@ impl Aead for Stateful { fn encrypt<'in_out, AdItem: AsRef<[u8]>, AdIter: Iterator>( &mut self, additional_data: AdIter, - nonce: &mut Self::Nonce, + nonce: &mut GenericArray, plaintext: &'in_out mut [u8], plaintext_used: usize, ) -> Result<&'in_out mut [u8], Error> { @@ -143,11 +121,123 @@ impl Aead for Stateful { fn decrypt<'in_out, AdItem: AsRef<[u8]>, AdIter: Iterator>( &mut self, additional_data: AdIter, - nonce: &Self::Nonce, + nonce: &GenericArray, ciphertext: &'in_out mut [u8], ) -> Result<&'in_out mut [u8], Error> { Algo::decrypt(&self.key, additional_data, nonce, ciphertext) } } +#[cfg(any(feature = "alloc", all(feature = "std", has_extern_crate_alloc)))] +extern crate alloc; + +#[cfg(any(feature = "alloc", all(feature = "std", has_extern_crate_alloc)))] +use alloc::vec::Vec; +#[cfg(all(feature = "std", not(any(feature = "alloc", has_extern_crate_alloc))))] +use std::vec::Vec; + +#[cfg(any(feature = "alloc", feature = "std"))] +/// Users who wish to use vectors instead of mutable byte slices should +/// utilize this API. +pub trait AeadVec { + fn encrypt_vec, AdIter: Iterator>( + &mut self, + additional_data: AdIter, + nonce: &mut GenericArray, + plaintext: Vec + ) -> Result, Error>; + + fn decrypt_vec, AdIter: Iterator>( + &mut self, + additional_data: AdIter, + nonce: &GenericArray, + ciphertext: Vec + ) -> Result, Error>; +} + +#[cfg(any(feature = "alloc", feature = "std"))] +/// When built with the `alloc` or `std` features, AEAD algorithms can operate +/// on vectors instead of simply byte slices. This functionality is +/// automatically provided for all algorithms. +impl AeadVec for Algo { + fn encrypt_vec, AdIter: Iterator>( + &mut self, + additional_data: AdIter, + nonce: &mut GenericArray, + plaintext: Vec + ) -> Result, Error> { + let used = plaintext.len(); + let required_len = used + Algo::CiphertextOverhead::to_usize(); + let mut retval = plaintext; + retval.resize(required_len, 0); + + let truncate_to = { + self.encrypt(additional_data, nonce, retval.as_mut_slice(), used)?.len() + }; + retval.truncate(truncate_to); + + Ok(retval) + } + + fn decrypt_vec, AdIter: Iterator>( + &mut self, + additional_data: AdIter, + nonce: &GenericArray, + ciphertext: Vec + ) -> Result, Error> { + let mut retval = ciphertext; + Ok(Vec::from(self.decrypt(additional_data, nonce, retval.as_mut_slice())?)) + } +} + + +#[cfg(any(feature = "alloc", feature = "std"))] +pub trait StatelessAeadVec { + fn encrypt_vec, AdIter: Iterator>( + key: &GenericArray, + additional_data: AdIter, + nonce: &mut GenericArray, + plaintext: Vec + ) -> Result, Error>; + fn decrypt_vec, AdIter: Iterator>( + key: &GenericArray, + additional_data: AdIter, + nonce: &GenericArray, + ciphertext: Vec + ) -> Result, Error>; +} + +#[cfg(any(feature = "alloc", feature = "std"))] +/// When built with the `alloc` or `std` features, stateless AEAD algorithms +/// can operate on vectors instead of simply byte slices. +impl StatelessAeadVec for Algo { + fn encrypt_vec, AdIter: Iterator>( + key: &GenericArray, + additional_data: AdIter, + nonce: &mut GenericArray, + plaintext: Vec + ) -> Result, Error> { + let used = plaintext.len(); + let required_len = used + Algo::CiphertextOverhead::to_usize(); + let mut retval = plaintext; + retval.resize(required_len, 0); + + let truncate_to = { + Algo::encrypt(key, additional_data, nonce, retval.as_mut_slice(), used)?.len() + }; + retval.truncate(truncate_to); + + Ok(retval) + } + + fn decrypt_vec, AdIter: Iterator>( + key: &GenericArray, + additional_data: AdIter, + nonce: &GenericArray, + ciphertext: Vec + ) -> Result, Error> { + let mut retval = ciphertext; + Ok(Vec::from(Algo::decrypt(key, additional_data, nonce, retval.as_mut_slice())?)) + } +} From ee8a730b3f5b0fc1fa39aef54cc5a65090c34f8d Mon Sep 17 00:00:00 2001 From: James Cape Date: Wed, 7 Aug 2019 13:26:40 -0700 Subject: [PATCH 07/17] Fix no_std selection. --- aead/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aead/src/lib.rs b/aead/src/lib.rs index d7c8cc694..d0ebd37a2 100644 --- a/aead/src/lib.rs +++ b/aead/src/lib.rs @@ -1,6 +1,6 @@ //! A set of traits designed to support authenticated encryption. -#![cfg_attr(not(any(feature = "std", feature = "alloc")), no_std)] +#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(all(feature = "alloc", not(has_extern_crate_alloc)), feature(alloc))] #![cfg(feature = "std")] From 9c1665c25483ef53921209270f4a7ff0f3b0d1c0 Mon Sep 17 00:00:00 2001 From: James Cape Date: Wed, 7 Aug 2019 13:53:46 -0700 Subject: [PATCH 08/17] Address PR conversation. --- aead/src/lib.rs | 91 ++++++++++++++++++++++++------------------------- 1 file changed, 45 insertions(+), 46 deletions(-) diff --git a/aead/src/lib.rs b/aead/src/lib.rs index d0ebd37a2..6972e570b 100644 --- a/aead/src/lib.rs +++ b/aead/src/lib.rs @@ -1,12 +1,19 @@ //! A set of traits designed to support authenticated encryption. #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(all(feature = "alloc", not(has_extern_crate_alloc)), feature(alloc))] -#![cfg(feature = "std")] +#![cfg(feature = "alloc")] +extern crate alloc; + +#[cfg(feature = "std")] extern crate core; extern crate generic_array; +#[cfg(any(feature = "alloc", all(feature = "std", has_extern_crate_alloc)))] +use alloc::vec::Vec; +#[cfg(all(feature = "std", not(any(feature = "alloc", has_extern_crate_alloc))))] +use std::vec::Vec; + use generic_array::typenum::Unsigned; use generic_array::{GenericArray, ArrayLength}; use core::marker::PhantomData; @@ -28,7 +35,7 @@ pub trait Aead { type CiphertextOverhead: ArrayLength + Unsigned; /// Construct a new stateful instance for the given key. - fn for_key(key: GenericArray) -> Self; + fn new(key: GenericArray) -> Self; /// Perform an in-place encryption of the given plaintext, which is built /// from the first plaintext_used bytes of the pre-populated plaintext @@ -37,9 +44,9 @@ pub trait Aead { /// Implementers are responsible for shifting any existing contents of the /// plaintext, if necessary, and returning a slice trimmed to the /// algorithm-specific ciphertext. - fn encrypt<'in_out, AdItem: AsRef<[u8]>, AdIter: Iterator>( + fn encrypt_in_place<'in_out>( &mut self, - additional_data: AdIter, + additional_data: &[u8], nonce: &mut GenericArray, plaintext: &'in_out mut [u8], plaintext_used: usize, @@ -48,9 +55,9 @@ pub trait Aead { /// Perform an in-place decryption of the given ciphertext, as constructed /// by the algorithm's `encrypt()` method, and returns a slice of the /// plaintext. - fn decrypt<'in_out, AdItem: AsRef<[u8]>, AdIter: Iterator>( + fn decrypt_in_place<'in_out>( &mut self, - additional_data: AdIter, + additional_data: &[u8], nonce: &GenericArray, ciphertext: &'in_out mut [u8], ) -> Result<&'in_out mut [u8], Error>; @@ -70,9 +77,9 @@ pub trait StatelessAead { type CiphertextOverhead: ArrayLength + Unsigned; /// Encrypts the given plaintext into a new ciphertext object and the nonce - fn encrypt<'in_out, AdItem: AsRef<[u8]>, AdIter: Iterator>( + fn encrypt_in_place<'in_out>( key: &GenericArray, - additional_data: AdIter, + additional_data: &[u8], nonce: &mut GenericArray, plaintext: &'in_out mut [u8], plaintext_used: usize, @@ -80,9 +87,9 @@ pub trait StatelessAead { /// Authenticates the ciphertext, nonce, and additional data, then /// decrypts the ciphertext contents into plaintext. - fn decrypt<'in_out, AdItem: AsRef<[u8]>, AdIter: Iterator>( + fn decrypt_in_place<'in_out>( key: &GenericArray, - additional_data: AdIter, + additional_data: &[u8], nonce: &GenericArray, ciphertext: &'in_out mut [u8], ) -> Result<&'in_out mut [u8], Error>; @@ -101,55 +108,47 @@ impl Aead for Stateful { type TagSize = Algo::TagSize; type CiphertextOverhead = Algo::CiphertextOverhead; - fn for_key(key: GenericArray) -> Self { + fn new(key: GenericArray) -> Self { Self { key, _aead: PhantomData::default(), } } - fn encrypt<'in_out, AdItem: AsRef<[u8]>, AdIter: Iterator>( + fn encrypt_in_place<'in_out>( &mut self, - additional_data: AdIter, + additional_data: &[u8], nonce: &mut GenericArray, plaintext: &'in_out mut [u8], plaintext_used: usize, ) -> Result<&'in_out mut [u8], Error> { - Algo::encrypt(&self.key, additional_data, nonce, plaintext, plaintext_used) + Algo::encrypt_in_place(&self.key, additional_data, nonce, plaintext, plaintext_used) } - fn decrypt<'in_out, AdItem: AsRef<[u8]>, AdIter: Iterator>( + fn decrypt_in_place<'in_out>( &mut self, - additional_data: AdIter, + additional_data: &[u8], nonce: &GenericArray, ciphertext: &'in_out mut [u8], ) -> Result<&'in_out mut [u8], Error> { - Algo::decrypt(&self.key, additional_data, nonce, ciphertext) + Algo::decrypt_in_place(&self.key, additional_data, nonce, ciphertext) } } -#[cfg(any(feature = "alloc", all(feature = "std", has_extern_crate_alloc)))] -extern crate alloc; - -#[cfg(any(feature = "alloc", all(feature = "std", has_extern_crate_alloc)))] -use alloc::vec::Vec; -#[cfg(all(feature = "std", not(any(feature = "alloc", has_extern_crate_alloc))))] -use std::vec::Vec; - #[cfg(any(feature = "alloc", feature = "std"))] /// Users who wish to use vectors instead of mutable byte slices should /// utilize this API. pub trait AeadVec { - fn encrypt_vec, AdIter: Iterator>( + fn encrypt( &mut self, - additional_data: AdIter, + additional_data: &[u8], nonce: &mut GenericArray, plaintext: Vec ) -> Result, Error>; - fn decrypt_vec, AdIter: Iterator>( + fn decrypt, AdIter: Iterator>( &mut self, - additional_data: AdIter, + additional_data: &[u8], nonce: &GenericArray, ciphertext: Vec ) -> Result, Error>; @@ -160,9 +159,9 @@ pub trait AeadVec { /// on vectors instead of simply byte slices. This functionality is /// automatically provided for all algorithms. impl AeadVec for Algo { - fn encrypt_vec, AdIter: Iterator>( + fn encrypt( &mut self, - additional_data: AdIter, + additional_data: &[u8], nonce: &mut GenericArray, plaintext: Vec ) -> Result, Error> { @@ -172,37 +171,37 @@ impl AeadVec for Algo { retval.resize(required_len, 0); let truncate_to = { - self.encrypt(additional_data, nonce, retval.as_mut_slice(), used)?.len() + self.encrypt_in_place(additional_data, nonce, retval.as_mut_slice(), used)?.len() }; retval.truncate(truncate_to); Ok(retval) } - fn decrypt_vec, AdIter: Iterator>( + fn decrypt( &mut self, - additional_data: AdIter, + additional_data: &[u8], nonce: &GenericArray, ciphertext: Vec ) -> Result, Error> { let mut retval = ciphertext; - Ok(Vec::from(self.decrypt(additional_data, nonce, retval.as_mut_slice())?)) + Ok(Vec::from(self.decrypt_in_place(additional_data, nonce, retval.as_mut_slice())?)) } } #[cfg(any(feature = "alloc", feature = "std"))] pub trait StatelessAeadVec { - fn encrypt_vec, AdIter: Iterator>( + fn encrypt( key: &GenericArray, - additional_data: AdIter, + additional_data: &[u8], nonce: &mut GenericArray, plaintext: Vec ) -> Result, Error>; - fn decrypt_vec, AdIter: Iterator>( + fn decrypt, AdIter: Iterator>( key: &GenericArray, - additional_data: AdIter, + additional_data: &[u8], nonce: &GenericArray, ciphertext: Vec ) -> Result, Error>; @@ -212,9 +211,9 @@ pub trait StatelessAeadVec { /// When built with the `alloc` or `std` features, stateless AEAD algorithms /// can operate on vectors instead of simply byte slices. impl StatelessAeadVec for Algo { - fn encrypt_vec, AdIter: Iterator>( + fn encrypt( key: &GenericArray, - additional_data: AdIter, + additional_data: &[u8], nonce: &mut GenericArray, plaintext: Vec ) -> Result, Error> { @@ -224,20 +223,20 @@ impl StatelessAeadVec for Algo { retval.resize(required_len, 0); let truncate_to = { - Algo::encrypt(key, additional_data, nonce, retval.as_mut_slice(), used)?.len() + Algo::encrypt_in_place(key, additional_data, nonce, retval.as_mut_slice(), used)?.len() }; retval.truncate(truncate_to); Ok(retval) } - fn decrypt_vec, AdIter: Iterator>( + fn decrypt( key: &GenericArray, - additional_data: AdIter, + additional_data: &[u8], nonce: &GenericArray, ciphertext: Vec ) -> Result, Error> { let mut retval = ciphertext; - Ok(Vec::from(Algo::decrypt(key, additional_data, nonce, retval.as_mut_slice())?)) + Ok(Vec::from(Algo::decrypt_in_place(key, additional_data, nonce, retval.as_mut_slice())?)) } } From f266526ec64f03b1271ae8163e1b9c4f29d3ddbc Mon Sep 17 00:00:00 2001 From: James Cape Date: Wed, 7 Aug 2019 15:08:03 -0700 Subject: [PATCH 09/17] More PR conversations - Remove Unsigned from associated type bounds. - Update copyright. - Move the _vec methods into the "core" trait. - Go back to encrypt/decrypt from _in_place. - Nonces given to encrypt() are immutable. --- aead/LICENSE-MIT | 3 +- aead/src/lib.rs | 232 ++++++++++++++++++++--------------------------- 2 files changed, 101 insertions(+), 134 deletions(-) diff --git a/aead/LICENSE-MIT b/aead/LICENSE-MIT index 8dcb85b30..88e64ca7b 100644 --- a/aead/LICENSE-MIT +++ b/aead/LICENSE-MIT @@ -1,4 +1,5 @@ -Copyright (c) 2017 Artyom Pavlov +Copyright (c) 2019 The RustCrypto Project Developers +Copyright (c) 2019 MobileCoin, LLC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated diff --git a/aead/src/lib.rs b/aead/src/lib.rs index 6972e570b..9077233cf 100644 --- a/aead/src/lib.rs +++ b/aead/src/lib.rs @@ -25,14 +25,14 @@ pub struct Error; /// scheme with a fixed-size nonce. pub trait Aead { /// The key size in a new method. - type KeySize: ArrayLength + Unsigned; + type KeySize: ArrayLength; /// The length of a nonce. - type NonceSize: ArrayLength + Unsigned; + type NonceSize: ArrayLength; /// The maximum length of the nonce. - type TagSize: ArrayLength + Unsigned; + type TagSize: ArrayLength; /// The amount of suffix padding, in bytes, which needs to be appended to /// a plaintext to accommodate this cipher's output. - type CiphertextOverhead: ArrayLength + Unsigned; + type CiphertextOverhead: ArrayLength; /// Construct a new stateful instance for the given key. fn new(key: GenericArray) -> Self; @@ -44,55 +44,127 @@ pub trait Aead { /// Implementers are responsible for shifting any existing contents of the /// plaintext, if necessary, and returning a slice trimmed to the /// algorithm-specific ciphertext. - fn encrypt_in_place<'in_out>( + fn encrypt<'in_out>( &mut self, additional_data: &[u8], - nonce: &mut GenericArray, + nonce: &GenericArray, plaintext: &'in_out mut [u8], plaintext_used: usize, - ) -> Result<&'in_out mut [u8], Error>; + ) -> Result<&'in_out [u8], Error>; /// Perform an in-place decryption of the given ciphertext, as constructed - /// by the algorithm's `encrypt()` method, and returns a slice of the - /// plaintext. - fn decrypt_in_place<'in_out>( + /// by the algorithm's `encrypt_vec()` method, and returns a slice + /// containing the plaintext. + fn decrypt<'in_out>( &mut self, additional_data: &[u8], nonce: &GenericArray, ciphertext: &'in_out mut [u8], - ) -> Result<&'in_out mut [u8], Error>; + ) -> Result<&'in_out [u8], Error>; + + #[cfg(any(feature = "alloc", feature = "std"))] + /// Consume a plaintext vector, encrypt it in-place, and return the + /// resulting ciphertext. + /// + /// A default implementation is provided which should be sufficient for + /// most cases. + fn encrypt_vec( + &mut self, + additional_data: &[u8], + nonce: &GenericArray, + plaintext: Vec + ) -> Result, Error> { + let used = plaintext.len(); + let required_len = used + Self::CiphertextOverhead::to_usize(); + let mut retval = plaintext; + retval.resize(required_len, 0); + + let truncate_to = { + self.encrypt(additional_data, nonce, retval.as_mut_slice(), used)?.len() + }; + retval.truncate(truncate_to); + + Ok(retval) + } + + #[cfg(any(feature = "alloc", feature = "std"))] + /// Consume a ciphertext vector, decrypt it in-place, and return a copy in + /// a new vector. + /// + /// A sub-optimal default implementation is provided, but AEAD implementers + /// are welcome to provide more optimized versions as desired. + fn decrypt_vec( + &mut self, + additional_data: &[u8], + nonce: &GenericArray, + ciphertext: Vec + ) -> Result, Error> { + let mut retval = ciphertext; + Ok(Vec::from(self.decrypt(additional_data, nonce, retval.as_mut_slice())?)) + } } /// A trait which can support a stateless RFC5116 authenticated encryption /// scheme. This is the standard RFC algorithm. pub trait StatelessAead { /// The key size in a new method. - type KeySize: ArrayLength + Unsigned; + type KeySize: ArrayLength; /// The length of a nonce. - type NonceSize: ArrayLength + Unsigned; + type NonceSize: ArrayLength; /// The maximum length of the nonce. - type TagSize: ArrayLength + Unsigned; + type TagSize: ArrayLength; /// The amount of suffix padding, in bytes, which needs to be /// appended to a plaintext to accomodate this cipher's output. - type CiphertextOverhead: ArrayLength + Unsigned; + type CiphertextOverhead: ArrayLength; /// Encrypts the given plaintext into a new ciphertext object and the nonce - fn encrypt_in_place<'in_out>( + fn encrypt<'in_out>( key: &GenericArray, additional_data: &[u8], - nonce: &mut GenericArray, + nonce: &GenericArray, plaintext: &'in_out mut [u8], plaintext_used: usize, - ) -> Result<&'in_out mut [u8], Error>; + ) -> Result<&'in_out [u8], Error>; /// Authenticates the ciphertext, nonce, and additional data, then /// decrypts the ciphertext contents into plaintext. - fn decrypt_in_place<'in_out>( + fn decrypt<'in_out>( key: &GenericArray, additional_data: &[u8], nonce: &GenericArray, ciphertext: &'in_out mut [u8], - ) -> Result<&'in_out mut [u8], Error>; + ) -> Result<&'in_out [u8], Error>; + + #[cfg(any(feature = "alloc", feature = "std"))] + fn encrypt_vec( + key: &GenericArray, + additional_data: &[u8], + nonce: &GenericArray, + plaintext: Vec + ) -> Result, Error> { + let used = plaintext.len(); + let required_len = used + Self::CiphertextOverhead::to_usize(); + let mut retval = plaintext; + retval.resize(required_len, 0); + + let truncate_to = { + Self::encrypt(key, additional_data, nonce, retval.as_mut_slice(), used)?.len() + }; + retval.truncate(truncate_to); + + Ok(retval) + } + + #[cfg(any(feature = "alloc", feature = "std"))] + fn decrypt_vec( + key: &GenericArray, + additional_data: &[u8], + nonce: &GenericArray, + ciphertext: Vec + ) -> Result, Error> { + let mut retval = ciphertext; + Ok(Vec::from(Self::decrypt(key, additional_data, nonce, retval.as_mut_slice())?)) + } } /// A wrapper structure to allow use of a stateless AEAD through the stateful @@ -115,128 +187,22 @@ impl Aead for Stateful { } } - fn encrypt_in_place<'in_out>( + fn encrypt<'in_out>( &mut self, additional_data: &[u8], - nonce: &mut GenericArray, + nonce: &GenericArray, plaintext: &'in_out mut [u8], plaintext_used: usize, - ) -> Result<&'in_out mut [u8], Error> { - Algo::encrypt_in_place(&self.key, additional_data, nonce, plaintext, plaintext_used) + ) -> Result<&'in_out [u8], Error> { + Algo::encrypt(&self.key, additional_data, nonce, plaintext, plaintext_used) } - fn decrypt_in_place<'in_out>( + fn decrypt<'in_out>( &mut self, additional_data: &[u8], nonce: &GenericArray, ciphertext: &'in_out mut [u8], - ) -> Result<&'in_out mut [u8], Error> { - Algo::decrypt_in_place(&self.key, additional_data, nonce, ciphertext) - } -} - -#[cfg(any(feature = "alloc", feature = "std"))] -/// Users who wish to use vectors instead of mutable byte slices should -/// utilize this API. -pub trait AeadVec { - fn encrypt( - &mut self, - additional_data: &[u8], - nonce: &mut GenericArray, - plaintext: Vec - ) -> Result, Error>; - - fn decrypt, AdIter: Iterator>( - &mut self, - additional_data: &[u8], - nonce: &GenericArray, - ciphertext: Vec - ) -> Result, Error>; -} - -#[cfg(any(feature = "alloc", feature = "std"))] -/// When built with the `alloc` or `std` features, AEAD algorithms can operate -/// on vectors instead of simply byte slices. This functionality is -/// automatically provided for all algorithms. -impl AeadVec for Algo { - fn encrypt( - &mut self, - additional_data: &[u8], - nonce: &mut GenericArray, - plaintext: Vec - ) -> Result, Error> { - let used = plaintext.len(); - let required_len = used + Algo::CiphertextOverhead::to_usize(); - let mut retval = plaintext; - retval.resize(required_len, 0); - - let truncate_to = { - self.encrypt_in_place(additional_data, nonce, retval.as_mut_slice(), used)?.len() - }; - retval.truncate(truncate_to); - - Ok(retval) - } - - fn decrypt( - &mut self, - additional_data: &[u8], - nonce: &GenericArray, - ciphertext: Vec - ) -> Result, Error> { - let mut retval = ciphertext; - Ok(Vec::from(self.decrypt_in_place(additional_data, nonce, retval.as_mut_slice())?)) - } -} - - -#[cfg(any(feature = "alloc", feature = "std"))] -pub trait StatelessAeadVec { - fn encrypt( - key: &GenericArray, - additional_data: &[u8], - nonce: &mut GenericArray, - plaintext: Vec - ) -> Result, Error>; - - fn decrypt, AdIter: Iterator>( - key: &GenericArray, - additional_data: &[u8], - nonce: &GenericArray, - ciphertext: Vec - ) -> Result, Error>; -} - -#[cfg(any(feature = "alloc", feature = "std"))] -/// When built with the `alloc` or `std` features, stateless AEAD algorithms -/// can operate on vectors instead of simply byte slices. -impl StatelessAeadVec for Algo { - fn encrypt( - key: &GenericArray, - additional_data: &[u8], - nonce: &mut GenericArray, - plaintext: Vec - ) -> Result, Error> { - let used = plaintext.len(); - let required_len = used + Algo::CiphertextOverhead::to_usize(); - let mut retval = plaintext; - retval.resize(required_len, 0); - - let truncate_to = { - Algo::encrypt_in_place(key, additional_data, nonce, retval.as_mut_slice(), used)?.len() - }; - retval.truncate(truncate_to); - - Ok(retval) - } - - fn decrypt( - key: &GenericArray, - additional_data: &[u8], - nonce: &GenericArray, - ciphertext: Vec - ) -> Result, Error> { - let mut retval = ciphertext; - Ok(Vec::from(Algo::decrypt_in_place(key, additional_data, nonce, retval.as_mut_slice())?)) + ) -> Result<&'in_out [u8], Error> { + Algo::decrypt(&self.key, additional_data, nonce, ciphertext) } } From a52b2cf5d1b1a52ba4a6fdfdc1cbb4958b569ec0 Mon Sep 17 00:00:00 2001 From: James Cape Date: Mon, 12 Aug 2019 15:24:37 -0700 Subject: [PATCH 10/17] And now without the in-place API. --- aead/src/lib.rs | 111 ++++++++---------------------------------------- 1 file changed, 18 insertions(+), 93 deletions(-) diff --git a/aead/src/lib.rs b/aead/src/lib.rs index 9077233cf..59d0782f1 100644 --- a/aead/src/lib.rs +++ b/aead/src/lib.rs @@ -14,7 +14,6 @@ use alloc::vec::Vec; #[cfg(all(feature = "std", not(any(feature = "alloc", has_extern_crate_alloc))))] use std::vec::Vec; -use generic_array::typenum::Unsigned; use generic_array::{GenericArray, ArrayLength}; use core::marker::PhantomData; @@ -37,71 +36,25 @@ pub trait Aead { /// Construct a new stateful instance for the given key. fn new(key: GenericArray) -> Self; - /// Perform an in-place encryption of the given plaintext, which is built - /// from the first plaintext_used bytes of the pre-populated plaintext - /// buffer. - /// - /// Implementers are responsible for shifting any existing contents of the - /// plaintext, if necessary, and returning a slice trimmed to the - /// algorithm-specific ciphertext. - fn encrypt<'in_out>( - &mut self, - additional_data: &[u8], - nonce: &GenericArray, - plaintext: &'in_out mut [u8], - plaintext_used: usize, - ) -> Result<&'in_out [u8], Error>; - - /// Perform an in-place decryption of the given ciphertext, as constructed - /// by the algorithm's `encrypt_vec()` method, and returns a slice - /// containing the plaintext. - fn decrypt<'in_out>( - &mut self, - additional_data: &[u8], - nonce: &GenericArray, - ciphertext: &'in_out mut [u8], - ) -> Result<&'in_out [u8], Error>; - #[cfg(any(feature = "alloc", feature = "std"))] /// Consume a plaintext vector, encrypt it in-place, and return the /// resulting ciphertext. - /// - /// A default implementation is provided which should be sufficient for - /// most cases. fn encrypt_vec( &mut self, additional_data: &[u8], nonce: &GenericArray, plaintext: Vec - ) -> Result, Error> { - let used = plaintext.len(); - let required_len = used + Self::CiphertextOverhead::to_usize(); - let mut retval = plaintext; - retval.resize(required_len, 0); - - let truncate_to = { - self.encrypt(additional_data, nonce, retval.as_mut_slice(), used)?.len() - }; - retval.truncate(truncate_to); - - Ok(retval) - } + ) -> Result, Error>; #[cfg(any(feature = "alloc", feature = "std"))] /// Consume a ciphertext vector, decrypt it in-place, and return a copy in /// a new vector. - /// - /// A sub-optimal default implementation is provided, but AEAD implementers - /// are welcome to provide more optimized versions as desired. fn decrypt_vec( &mut self, additional_data: &[u8], nonce: &GenericArray, ciphertext: Vec - ) -> Result, Error> { - let mut retval = ciphertext; - Ok(Vec::from(self.decrypt(additional_data, nonce, retval.as_mut_slice())?)) - } + ) -> Result, Error>; } /// A trait which can support a stateless RFC5116 authenticated encryption @@ -117,43 +70,13 @@ pub trait StatelessAead { /// appended to a plaintext to accomodate this cipher's output. type CiphertextOverhead: ArrayLength; - /// Encrypts the given plaintext into a new ciphertext object and the nonce - fn encrypt<'in_out>( - key: &GenericArray, - additional_data: &[u8], - nonce: &GenericArray, - plaintext: &'in_out mut [u8], - plaintext_used: usize, - ) -> Result<&'in_out [u8], Error>; - - /// Authenticates the ciphertext, nonce, and additional data, then - /// decrypts the ciphertext contents into plaintext. - fn decrypt<'in_out>( - key: &GenericArray, - additional_data: &[u8], - nonce: &GenericArray, - ciphertext: &'in_out mut [u8], - ) -> Result<&'in_out [u8], Error>; - #[cfg(any(feature = "alloc", feature = "std"))] fn encrypt_vec( key: &GenericArray, additional_data: &[u8], nonce: &GenericArray, plaintext: Vec - ) -> Result, Error> { - let used = plaintext.len(); - let required_len = used + Self::CiphertextOverhead::to_usize(); - let mut retval = plaintext; - retval.resize(required_len, 0); - - let truncate_to = { - Self::encrypt(key, additional_data, nonce, retval.as_mut_slice(), used)?.len() - }; - retval.truncate(truncate_to); - - Ok(retval) - } + ) -> Result, Error>; #[cfg(any(feature = "alloc", feature = "std"))] fn decrypt_vec( @@ -161,10 +84,7 @@ pub trait StatelessAead { additional_data: &[u8], nonce: &GenericArray, ciphertext: Vec - ) -> Result, Error> { - let mut retval = ciphertext; - Ok(Vec::from(Self::decrypt(key, additional_data, nonce, retval.as_mut_slice())?)) - } + ) -> Result, Error>; } /// A wrapper structure to allow use of a stateless AEAD through the stateful @@ -187,22 +107,27 @@ impl Aead for Stateful { } } - fn encrypt<'in_out>( + #[cfg(any(feature = "alloc", feature = "std"))] + /// Consume a plaintext vector, encrypt it in-place, and return the + /// resulting ciphertext. + fn encrypt_vec( &mut self, additional_data: &[u8], nonce: &GenericArray, - plaintext: &'in_out mut [u8], - plaintext_used: usize, - ) -> Result<&'in_out [u8], Error> { - Algo::encrypt(&self.key, additional_data, nonce, plaintext, plaintext_used) + plaintext: Vec + ) -> Result, Error> { + Algo::encrypt_vec(&self.key, additional_data, nonce, plaintext) } - fn decrypt<'in_out>( + #[cfg(any(feature = "alloc", feature = "std"))] + /// Consume a ciphertext vector, decrypt it in-place, and return a copy in + /// a new vector. + fn decrypt_vec( &mut self, additional_data: &[u8], nonce: &GenericArray, - ciphertext: &'in_out mut [u8], - ) -> Result<&'in_out [u8], Error> { - Algo::decrypt(&self.key, additional_data, nonce, ciphertext) + ciphertext: Vec + ) -> Result, Error> { + Algo::decrypt_vec(&self.key, additional_data, nonce, ciphertext) } } From 68bbb398a5becc246b1df244d71c3337e4de53d2 Mon Sep 17 00:00:00 2001 From: James Cape Date: Tue, 13 Aug 2019 11:53:16 -0700 Subject: [PATCH 11/17] Stateful Stateless - Split out NewAead and the KeySize type. - encrypt_vec and encrypt_to_vec. --- aead/src/lib.rs | 124 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 91 insertions(+), 33 deletions(-) diff --git a/aead/src/lib.rs b/aead/src/lib.rs index 59d0782f1..d3a30a7f3 100644 --- a/aead/src/lib.rs +++ b/aead/src/lib.rs @@ -15,16 +15,23 @@ use alloc::vec::Vec; use std::vec::Vec; use generic_array::{GenericArray, ArrayLength}; -use core::marker::PhantomData; #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct Error; +/// A trait which can be used to create a new RFC5116 authenticated encryption +/// scheme. +pub trait NewAead { + /// The size of the key array required by this algorithm. + type KeySize: ArrayLength; + + /// Construct a new stateful instance for the given key. + fn new(key: GenericArray) -> Self; +} + /// A trait which can support a stateful, RFC5116 authenticated encryption /// scheme with a fixed-size nonce. pub trait Aead { - /// The key size in a new method. - type KeySize: ArrayLength; /// The length of a nonce. type NonceSize: ArrayLength; /// The maximum length of the nonce. @@ -33,12 +40,32 @@ pub trait Aead { /// a plaintext to accommodate this cipher's output. type CiphertextOverhead: ArrayLength; - /// Construct a new stateful instance for the given key. - fn new(key: GenericArray) -> Self; + #[cfg(any(feature = "alloc", feature = "std"))] + /// Encrypt the given plaintext and return the ciphertext into a vector. + fn encrypt_to_vec( + &mut self, + additional_data: &[u8], + nonce: &GenericArray, + plaintext: &[u8] + ) -> Result, Error> { + self.encrypt_vec(additional_data, nonce, Vec::from(plaintext)) + } + + #[cfg(any(feature = "alloc", feature = "std"))] + /// Decrypt the given ciphertext, and return the plaintext as a vector of + /// bytes. + fn decrypt_to_vec( + &mut self, + additional_data: &[u8], + nonce: &GenericArray, + ciphertext: &[u8] + ) -> Result, Error> { + self.decrypt_vec(additional_data, nonce, Vec::from(ciphertext)) + } #[cfg(any(feature = "alloc", feature = "std"))] - /// Consume a plaintext vector, encrypt it in-place, and return the - /// resulting ciphertext. + /// Consume a plaintext vector, encrypt it, and return the resulting + /// ciphertext as a vector. fn encrypt_vec( &mut self, additional_data: &[u8], @@ -47,8 +74,8 @@ pub trait Aead { ) -> Result, Error>; #[cfg(any(feature = "alloc", feature = "std"))] - /// Consume a ciphertext vector, decrypt it in-place, and return a copy in - /// a new vector. + /// Consume a ciphertext vector, decrypt it, and return the resulting + /// plaintext as a vector of bytes. fn decrypt_vec( &mut self, additional_data: &[u8], @@ -60,8 +87,6 @@ pub trait Aead { /// A trait which can support a stateless RFC5116 authenticated encryption /// scheme. This is the standard RFC algorithm. pub trait StatelessAead { - /// The key size in a new method. - type KeySize: ArrayLength; /// The length of a nonce. type NonceSize: ArrayLength; /// The maximum length of the nonce. @@ -71,63 +96,96 @@ pub trait StatelessAead { type CiphertextOverhead: ArrayLength; #[cfg(any(feature = "alloc", feature = "std"))] + fn encrypt_to_vec(&self, + additional_data: &[u8], + nonce: &GenericArray, + plaintext: &[u8] + ) -> Result, Error> { + self.encrypt_vec(additional_data, nonce, Vec::from(plaintext)) + } + + #[cfg(any(feature = "alloc", feature = "std"))] + fn decrypt_to_vec(&self, + additional_data: &[u8], + nonce: &GenericArray, + ciphertext: &[u8] + ) -> Result, Error> { + self.decrypt_vec(additional_data, nonce, Vec::from(ciphertext)) + } + + #[cfg(any(feature = "alloc", feature = "std"))] + /// Consume a plaintext vector, encrypt it, and return the resulting + /// ciphertext as a vector. fn encrypt_vec( - key: &GenericArray, + &self, additional_data: &[u8], nonce: &GenericArray, plaintext: Vec ) -> Result, Error>; #[cfg(any(feature = "alloc", feature = "std"))] + /// Consume a ciphertext vector, decrypt it, and return the resulting + /// plaintext as a vector of bytes. fn decrypt_vec( - key: &GenericArray, + &self, additional_data: &[u8], nonce: &GenericArray, ciphertext: Vec ) -> Result, Error>; } -/// A wrapper structure to allow use of a stateless AEAD through the stateful -/// interface. -pub struct Stateful { - key: GenericArray, - _aead: PhantomData Algo> -} - -impl Aead for Stateful { - type KeySize = Algo::KeySize; +/// A blanket implementation of the Stateful AEAD interface for Stateless +/// AEAD implementations. +impl Aead for Algo { type NonceSize = Algo::NonceSize; type TagSize = Algo::TagSize; type CiphertextOverhead = Algo::CiphertextOverhead; - fn new(key: GenericArray) -> Self { - Self { - key, - _aead: PhantomData::default(), - } + #[cfg(any(feature = "alloc", feature = "std"))] + /// Consume a plaintext vector, encrypt it, and return the resulting + /// ciphertext as a vector. + fn encrypt_to_vec( + &mut self, + additional_data: &[u8], + nonce: &GenericArray, + plaintext: &[u8] + ) -> Result, Error> { + ::encrypt_to_vec(self, additional_data, nonce, plaintext) + } + + #[cfg(any(feature = "alloc", feature = "std"))] + /// Consume a ciphertext vector, decrypt it, and return the resulting + /// plaintext as a vector of bytes. + fn decrypt_to_vec( + &mut self, + additional_data: &[u8], + nonce: &GenericArray, + ciphertext: &[u8] + ) -> Result, Error> { + ::decrypt_to_vec(self, additional_data, nonce, ciphertext) } #[cfg(any(feature = "alloc", feature = "std"))] - /// Consume a plaintext vector, encrypt it in-place, and return the - /// resulting ciphertext. + /// Consume a plaintext vector, encrypt it, and return the resulting + /// ciphertext as a vector. fn encrypt_vec( &mut self, additional_data: &[u8], nonce: &GenericArray, plaintext: Vec ) -> Result, Error> { - Algo::encrypt_vec(&self.key, additional_data, nonce, plaintext) + ::encrypt_vec(self, additional_data, nonce, plaintext) } #[cfg(any(feature = "alloc", feature = "std"))] - /// Consume a ciphertext vector, decrypt it in-place, and return a copy in - /// a new vector. + /// Consume a ciphertext vector, decrypt it, and return the resulting + /// plaintext as a vector of bytes. fn decrypt_vec( &mut self, additional_data: &[u8], nonce: &GenericArray, ciphertext: Vec ) -> Result, Error> { - Algo::decrypt_vec(&self.key, additional_data, nonce, ciphertext) + ::decrypt_vec(self, additional_data, nonce, ciphertext) } } From 301598d09eab111304098e9e36fa12d71dbaa5cb Mon Sep 17 00:00:00 2001 From: James Cape Date: Tue, 13 Aug 2019 12:14:22 -0700 Subject: [PATCH 12/17] Use CiphertextOverhead --- aead/src/lib.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/aead/src/lib.rs b/aead/src/lib.rs index d3a30a7f3..1421ce115 100644 --- a/aead/src/lib.rs +++ b/aead/src/lib.rs @@ -15,6 +15,7 @@ use alloc::vec::Vec; use std::vec::Vec; use generic_array::{GenericArray, ArrayLength}; +use generic_array::typenum::Unsigned; #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct Error; @@ -38,7 +39,7 @@ pub trait Aead { type TagSize: ArrayLength; /// The amount of suffix padding, in bytes, which needs to be appended to /// a plaintext to accommodate this cipher's output. - type CiphertextOverhead: ArrayLength; + type CiphertextOverhead: ArrayLength + Unsigned; #[cfg(any(feature = "alloc", feature = "std"))] /// Encrypt the given plaintext and return the ciphertext into a vector. @@ -48,7 +49,9 @@ pub trait Aead { nonce: &GenericArray, plaintext: &[u8] ) -> Result, Error> { - self.encrypt_vec(additional_data, nonce, Vec::from(plaintext)) + let mut pt_vec = Vec::with_capacity(plaintext.len() + Self::CiphertextOverhead::to_usize()); + pt_vec.extend(plaintext); + self.encrypt_vec(additional_data, nonce, pt_vec) } #[cfg(any(feature = "alloc", feature = "std"))] From 5a0376a114dc802a3e7b8a8859342e39c1aeb2c4 Mon Sep 17 00:00:00 2001 From: James Cape Date: Tue, 13 Aug 2019 12:16:22 -0700 Subject: [PATCH 13/17] Update CiphertextOverhead comments, do stateless. --- aead/src/lib.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/aead/src/lib.rs b/aead/src/lib.rs index 1421ce115..3223b326c 100644 --- a/aead/src/lib.rs +++ b/aead/src/lib.rs @@ -37,8 +37,8 @@ pub trait Aead { type NonceSize: ArrayLength; /// The maximum length of the nonce. type TagSize: ArrayLength; - /// The amount of suffix padding, in bytes, which needs to be appended to - /// a plaintext to accommodate this cipher's output. + /// The upper bound amount of additional space required to support a + /// ciphertext vs. a plaintext. type CiphertextOverhead: ArrayLength + Unsigned; #[cfg(any(feature = "alloc", feature = "std"))] @@ -94,9 +94,9 @@ pub trait StatelessAead { type NonceSize: ArrayLength; /// The maximum length of the nonce. type TagSize: ArrayLength; - /// The amount of suffix padding, in bytes, which needs to be - /// appended to a plaintext to accomodate this cipher's output. - type CiphertextOverhead: ArrayLength; + /// The upper bound amount of additional space required to support a + /// ciphertext vs. a plaintext. + type CiphertextOverhead: ArrayLength + Unsigned; #[cfg(any(feature = "alloc", feature = "std"))] fn encrypt_to_vec(&self, @@ -104,7 +104,9 @@ pub trait StatelessAead { nonce: &GenericArray, plaintext: &[u8] ) -> Result, Error> { - self.encrypt_vec(additional_data, nonce, Vec::from(plaintext)) + let mut pt_vec = Vec::with_capacity(plaintext.len() + Self::CiphertextOverhead::to_usize()); + pt_vec.extend(plaintext); + self.encrypt_vec(additional_data, nonce, pt_vec) } #[cfg(any(feature = "alloc", feature = "std"))] From caa23261c5aa98d1e83d207b44a3e1080f394cfa Mon Sep 17 00:00:00 2001 From: James Cape Date: Tue, 13 Aug 2019 12:20:58 -0700 Subject: [PATCH 14/17] rustdoc comments. --- aead/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/aead/src/lib.rs b/aead/src/lib.rs index 3223b326c..82d49ffd7 100644 --- a/aead/src/lib.rs +++ b/aead/src/lib.rs @@ -99,6 +99,8 @@ pub trait StatelessAead { type CiphertextOverhead: ArrayLength + Unsigned; #[cfg(any(feature = "alloc", feature = "std"))] + /// Encrypt the given plaintext slice, and return the resulting ciphertext + /// as a vector of bytes. fn encrypt_to_vec(&self, additional_data: &[u8], nonce: &GenericArray, @@ -110,6 +112,8 @@ pub trait StatelessAead { } #[cfg(any(feature = "alloc", feature = "std"))] + /// Decrypt the given ciphertext, and return the resulting plaintext as a + /// vector of bytes. fn decrypt_to_vec(&self, additional_data: &[u8], nonce: &GenericArray, From 5261a04e312b2b7648e1bb837a7172a6b918f7a2 Mon Sep 17 00:00:00 2001 From: James Cape Date: Fri, 16 Aug 2019 13:51:19 -0700 Subject: [PATCH 15/17] Latest requests. --- .gitignore | 1 - aead/Cargo.toml | 5 +- aead/src/lib.rs | 139 +++++++++++------------------------------------- build_std.sh | 2 +- 4 files changed, 33 insertions(+), 114 deletions(-) diff --git a/.gitignore b/.gitignore index 37af649ab..a4048e8bb 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,4 @@ target/ */target/ */*/target/ Cargo.lock -.idea diff --git a/aead/Cargo.toml b/aead/Cargo.toml index 85978c519..295b4f5f6 100644 --- a/aead/Cargo.toml +++ b/aead/Cargo.toml @@ -2,13 +2,12 @@ name = "aead" version = "0.1.0" authors = ["James Cape "] +edition = "2018" description = """ -The RFC5116 AEAD API, as a trait. +Traits for Authenticated Encryption with Associated Data (AEAD) algorithms """ [features] -std = [] -dev = [] alloc = [] [dependencies] diff --git a/aead/src/lib.rs b/aead/src/lib.rs index 82d49ffd7..9bac08541 100644 --- a/aead/src/lib.rs +++ b/aead/src/lib.rs @@ -1,18 +1,12 @@ //! A set of traits designed to support authenticated encryption. -#![cfg_attr(not(feature = "std"), no_std)] +#![no_std] -#![cfg(feature = "alloc")] +#[cfg(feature = "alloc")] extern crate alloc; -#[cfg(feature = "std")] -extern crate core; -extern crate generic_array; - -#[cfg(any(feature = "alloc", all(feature = "std", has_extern_crate_alloc)))] +#[cfg(feature = "alloc")] use alloc::vec::Vec; -#[cfg(all(feature = "std", not(any(feature = "alloc", has_extern_crate_alloc))))] -use std::vec::Vec; use generic_array::{GenericArray, ArrayLength}; use generic_array::typenum::Unsigned; @@ -41,49 +35,24 @@ pub trait Aead { /// ciphertext vs. a plaintext. type CiphertextOverhead: ArrayLength + Unsigned; - #[cfg(any(feature = "alloc", feature = "std"))] - /// Encrypt the given plaintext and return the ciphertext into a vector. - fn encrypt_to_vec( + #[cfg(feature = "alloc")] + /// Encrypt the given plaintext slice, and return the resulting ciphertext + /// as a vector of bytes. + fn encrypt( &mut self, additional_data: &[u8], nonce: &GenericArray, plaintext: &[u8] - ) -> Result, Error> { - let mut pt_vec = Vec::with_capacity(plaintext.len() + Self::CiphertextOverhead::to_usize()); - pt_vec.extend(plaintext); - self.encrypt_vec(additional_data, nonce, pt_vec) - } - - #[cfg(any(feature = "alloc", feature = "std"))] - /// Decrypt the given ciphertext, and return the plaintext as a vector of - /// bytes. - fn decrypt_to_vec( - &mut self, - additional_data: &[u8], - nonce: &GenericArray, - ciphertext: &[u8] - ) -> Result, Error> { - self.decrypt_vec(additional_data, nonce, Vec::from(ciphertext)) - } - - #[cfg(any(feature = "alloc", feature = "std"))] - /// Consume a plaintext vector, encrypt it, and return the resulting - /// ciphertext as a vector. - fn encrypt_vec( - &mut self, - additional_data: &[u8], - nonce: &GenericArray, - plaintext: Vec ) -> Result, Error>; - #[cfg(any(feature = "alloc", feature = "std"))] - /// Consume a ciphertext vector, decrypt it, and return the resulting - /// plaintext as a vector of bytes. - fn decrypt_vec( + #[cfg(feature = "alloc")] + /// Decrypt the given ciphertext slice, and return the resulting plaintext + /// as a vector of bytes. + fn decrypt( &mut self, additional_data: &[u8], nonce: &GenericArray, - ciphertext: Vec + ciphertext: &[u8] ) -> Result, Error>; } @@ -98,48 +67,24 @@ pub trait StatelessAead { /// ciphertext vs. a plaintext. type CiphertextOverhead: ArrayLength + Unsigned; - #[cfg(any(feature = "alloc", feature = "std"))] + #[cfg(feature = "alloc")] /// Encrypt the given plaintext slice, and return the resulting ciphertext /// as a vector of bytes. - fn encrypt_to_vec(&self, - additional_data: &[u8], - nonce: &GenericArray, - plaintext: &[u8] - ) -> Result, Error> { - let mut pt_vec = Vec::with_capacity(plaintext.len() + Self::CiphertextOverhead::to_usize()); - pt_vec.extend(plaintext); - self.encrypt_vec(additional_data, nonce, pt_vec) - } - - #[cfg(any(feature = "alloc", feature = "std"))] - /// Decrypt the given ciphertext, and return the resulting plaintext as a - /// vector of bytes. - fn decrypt_to_vec(&self, - additional_data: &[u8], - nonce: &GenericArray, - ciphertext: &[u8] - ) -> Result, Error> { - self.decrypt_vec(additional_data, nonce, Vec::from(ciphertext)) - } - - #[cfg(any(feature = "alloc", feature = "std"))] - /// Consume a plaintext vector, encrypt it, and return the resulting - /// ciphertext as a vector. - fn encrypt_vec( + fn encrypt( &self, additional_data: &[u8], nonce: &GenericArray, - plaintext: Vec + plaintext: &[u8] ) -> Result, Error>; - #[cfg(any(feature = "alloc", feature = "std"))] - /// Consume a ciphertext vector, decrypt it, and return the resulting - /// plaintext as a vector of bytes. - fn decrypt_vec( + #[cfg(feature = "alloc")] + /// Decrypt the given ciphertext slice, and return the resulting plaintext + /// as a vector of bytes. + fn decrypt( &self, additional_data: &[u8], nonce: &GenericArray, - ciphertext: Vec + ciphertext: &[u8] ) -> Result, Error>; } @@ -150,51 +95,27 @@ impl Aead for Algo { type TagSize = Algo::TagSize; type CiphertextOverhead = Algo::CiphertextOverhead; - #[cfg(any(feature = "alloc", feature = "std"))] - /// Consume a plaintext vector, encrypt it, and return the resulting - /// ciphertext as a vector. - fn encrypt_to_vec( + #[cfg(feature = "alloc")] + /// Encrypt the given plaintext slice, and return the resulting ciphertext + /// as a vector of bytes. + fn encrypt( &mut self, additional_data: &[u8], nonce: &GenericArray, plaintext: &[u8] ) -> Result, Error> { - ::encrypt_to_vec(self, additional_data, nonce, plaintext) + ::encrypt(self, additional_data, nonce, plaintext) } - #[cfg(any(feature = "alloc", feature = "std"))] - /// Consume a ciphertext vector, decrypt it, and return the resulting - /// plaintext as a vector of bytes. - fn decrypt_to_vec( + #[cfg(feature = "alloc")] + /// Decrypt the given ciphertext slice, and return the resulting plaintext + /// as a vector of bytes. + fn decrypt( &mut self, additional_data: &[u8], nonce: &GenericArray, ciphertext: &[u8] ) -> Result, Error> { - ::decrypt_to_vec(self, additional_data, nonce, ciphertext) - } - - #[cfg(any(feature = "alloc", feature = "std"))] - /// Consume a plaintext vector, encrypt it, and return the resulting - /// ciphertext as a vector. - fn encrypt_vec( - &mut self, - additional_data: &[u8], - nonce: &GenericArray, - plaintext: Vec - ) -> Result, Error> { - ::encrypt_vec(self, additional_data, nonce, plaintext) - } - - #[cfg(any(feature = "alloc", feature = "std"))] - /// Consume a ciphertext vector, decrypt it, and return the resulting - /// plaintext as a vector of bytes. - fn decrypt_vec( - &mut self, - additional_data: &[u8], - nonce: &GenericArray, - ciphertext: Vec - ) -> Result, Error> { - ::decrypt_vec(self, additional_data, nonce, ciphertext) + ::decrypt(self, additional_data, nonce, ciphertext) } } diff --git a/build_std.sh b/build_std.sh index d9a48e64a..7fd3877a5 100755 --- a/build_std.sh +++ b/build_std.sh @@ -13,7 +13,7 @@ for DIR in $DIRS; do fi cd $DIR echo Building $DIR - cargo build --features std,dev || { + cargo build --all-features || { echo $DIR failed exit 1 } From 79f378ce8575c59d148a3dc8299ecec63c27c04d Mon Sep 17 00:00:00 2001 From: James Cape Date: Fri, 16 Aug 2019 13:58:30 -0700 Subject: [PATCH 16/17] Remove alloc feature. --- aead/Cargo.toml | 3 --- aead/src/lib.rs | 9 --------- 2 files changed, 12 deletions(-) diff --git a/aead/Cargo.toml b/aead/Cargo.toml index 295b4f5f6..66ca8e122 100644 --- a/aead/Cargo.toml +++ b/aead/Cargo.toml @@ -7,8 +7,5 @@ description = """ Traits for Authenticated Encryption with Associated Data (AEAD) algorithms """ -[features] -alloc = [] - [dependencies] generic-array = { version = "0.12", default-features = false } diff --git a/aead/src/lib.rs b/aead/src/lib.rs index 9bac08541..a42072e40 100644 --- a/aead/src/lib.rs +++ b/aead/src/lib.rs @@ -2,12 +2,9 @@ #![no_std] -#[cfg(feature = "alloc")] extern crate alloc; -#[cfg(feature = "alloc")] use alloc::vec::Vec; - use generic_array::{GenericArray, ArrayLength}; use generic_array::typenum::Unsigned; @@ -35,7 +32,6 @@ pub trait Aead { /// ciphertext vs. a plaintext. type CiphertextOverhead: ArrayLength + Unsigned; - #[cfg(feature = "alloc")] /// Encrypt the given plaintext slice, and return the resulting ciphertext /// as a vector of bytes. fn encrypt( @@ -45,7 +41,6 @@ pub trait Aead { plaintext: &[u8] ) -> Result, Error>; - #[cfg(feature = "alloc")] /// Decrypt the given ciphertext slice, and return the resulting plaintext /// as a vector of bytes. fn decrypt( @@ -67,7 +62,6 @@ pub trait StatelessAead { /// ciphertext vs. a plaintext. type CiphertextOverhead: ArrayLength + Unsigned; - #[cfg(feature = "alloc")] /// Encrypt the given plaintext slice, and return the resulting ciphertext /// as a vector of bytes. fn encrypt( @@ -77,7 +71,6 @@ pub trait StatelessAead { plaintext: &[u8] ) -> Result, Error>; - #[cfg(feature = "alloc")] /// Decrypt the given ciphertext slice, and return the resulting plaintext /// as a vector of bytes. fn decrypt( @@ -95,7 +88,6 @@ impl Aead for Algo { type TagSize = Algo::TagSize; type CiphertextOverhead = Algo::CiphertextOverhead; - #[cfg(feature = "alloc")] /// Encrypt the given plaintext slice, and return the resulting ciphertext /// as a vector of bytes. fn encrypt( @@ -107,7 +99,6 @@ impl Aead for Algo { ::encrypt(self, additional_data, nonce, plaintext) } - #[cfg(feature = "alloc")] /// Decrypt the given ciphertext slice, and return the resulting plaintext /// as a vector of bytes. fn decrypt( From 46fd26d848da70db821bced2c208d5e928c867d4 Mon Sep 17 00:00:00 2001 From: James Cape Date: Mon, 19 Aug 2019 12:20:13 -0700 Subject: [PATCH 17/17] Travis adjustments, pub use generic_array. --- .travis.yml | 6 ++++-- aead/src/lib.rs | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 59c9afd83..d32ccf978 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,9 @@ sudo: required matrix: include: - rust: 1.21.0 - script: cargo test --verbose --all --release + script: cargo test --verbose --all --exclude aead --release + - rust: 1.36.0 + script: cargo test --verbose --package aead --release - rust: stable script: cargo test --verbose --all --release - rust: nightly @@ -23,7 +25,7 @@ matrix: # tests if crates truly can be built without std - env: TARGET=thumbv7em-none-eabi rust: nightly - script: xargo build --no-default-features --verbose --target $TARGET + script: xargo build --exclude aead --no-default-features --verbose --target $TARGET install: - cargo install xargo || true - rustup target install armv7-unknown-linux-gnueabihf diff --git a/aead/src/lib.rs b/aead/src/lib.rs index a42072e40..856819b6b 100644 --- a/aead/src/lib.rs +++ b/aead/src/lib.rs @@ -4,9 +4,10 @@ extern crate alloc; +pub use generic_array; + use alloc::vec::Vec; -use generic_array::{GenericArray, ArrayLength}; -use generic_array::typenum::Unsigned; +use generic_array::{GenericArray, ArrayLength, typenum::Unsigned}; #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct Error;