summaryrefslogtreecommitdiffstats
path: root/vendor/orion/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/orion/src/util')
-rw-r--r--vendor/orion/src/util/endianness.rs371
-rw-r--r--vendor/orion/src/util/mod.rs186
-rw-r--r--vendor/orion/src/util/u32x4.rs98
-rw-r--r--vendor/orion/src/util/u64x4.rs114
4 files changed, 769 insertions, 0 deletions
diff --git a/vendor/orion/src/util/endianness.rs b/vendor/orion/src/util/endianness.rs
new file mode 100644
index 0000000..b8d0d92
--- /dev/null
+++ b/vendor/orion/src/util/endianness.rs
@@ -0,0 +1,371 @@
+// MIT License
+
+// Copyright (c) 2019-2023 The orion Developers
+
+// 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.
+
+use core::convert::TryInto;
+use core::mem;
+
+macro_rules! impl_store_into {
+ ($type_alias:ty, $conv_function:ident, $func_name:ident) => {
+ /// Store bytes in `src` in `dst`.
+ pub fn $func_name(src: &[$type_alias], dst: &mut [u8]) {
+ let type_alias_len = mem::size_of::<$type_alias>();
+ // The length of src must be evenly divisible with the length of dst,
+ // making sure .chunks_exact() leaves no remainder.
+ assert_eq!(mem::size_of_val(src), dst.len());
+
+ for (src_elem, dst_chunk) in src.iter().zip(dst.chunks_exact_mut(type_alias_len)) {
+ dst_chunk.copy_from_slice(&src_elem.$conv_function());
+ }
+ }
+ };
+}
+
+macro_rules! impl_load_into {
+ ($type_alias:ty, $type_alias_expr:ident, $conv_function:ident, $func_name:ident) => {
+ /// Load bytes in `src` into `dst`.
+ pub fn $func_name(src: &[u8], dst: &mut [$type_alias]) {
+ let type_alias_len = mem::size_of::<$type_alias>();
+ // The length of src must be evenly divisible with the length of dst,
+ // making sure .chunks_exact() leaves no remainder.
+ assert_eq!(mem::size_of_val(dst), src.len());
+
+ for (src_chunk, dst_elem) in src.chunks_exact(type_alias_len).zip(dst.iter_mut()) {
+ // The above assert and this debug assert should prove that .unwrap()
+ // cannot panic using TryInto.
+ debug_assert_eq!(src_chunk.len(), type_alias_len);
+ *dst_elem = $type_alias_expr::$conv_function(src_chunk.try_into().unwrap());
+ }
+ }
+ };
+}
+
+macro_rules! impl_load {
+ ($type_alias:ty, $type_alias_expr:ident, $conv_function:ident, $func_name:ident) => {
+ /// Convert bytes in `src` to a given primitive.
+ pub fn $func_name(src: &[u8]) -> $type_alias {
+ // Satisfying this assert should prove that using TryInto
+ // cannot panic.
+ assert_eq!(mem::size_of::<$type_alias>(), src.len());
+ $type_alias_expr::$conv_function(src.try_into().unwrap())
+ }
+ };
+}
+
+impl_load!(u32, u32, from_le_bytes, load_u32_le);
+
+#[cfg(test)]
+impl_load_into!(u32, u32, from_le_bytes, load_u32_into_le);
+
+impl_load_into!(u64, u64, from_le_bytes, load_u64_into_le);
+
+impl_store_into!(u32, to_le_bytes, store_u32_into_le);
+
+#[cfg(any(feature = "safe_api", feature = "alloc", test))]
+impl_store_into!(u64, to_le_bytes, store_u64_into_le);
+
+// Testing public functions in the module.
+#[cfg(test)]
+mod public {
+ use super::*;
+
+ macro_rules! test_empty_src_panic {
+ ($test_name:ident, $src_val:expr, $dst_val:expr, $func_to_test:expr) => {
+ #[test]
+ #[should_panic]
+ fn $test_name() {
+ let mut dst_load = $dst_val;
+ $func_to_test($src_val, &mut dst_load);
+ }
+ };
+ }
+
+ macro_rules! test_dst_length_panic {
+ ($test_name:ident, $src_val:expr, $dst_val:expr, $func_to_test:expr) => {
+ #[test]
+ #[should_panic]
+ fn $test_name() {
+ let mut dst_load = $dst_val;
+ $func_to_test($src_val, &mut dst_load);
+ }
+ };
+ }
+
+ macro_rules! test_dst_length_ok {
+ ($test_name:ident, $src_val:expr, $dst_val:expr, $func_to_test:expr) => {
+ #[test]
+ fn $test_name() {
+ let mut dst_load = $dst_val;
+ $func_to_test($src_val, &mut dst_load);
+ }
+ };
+ }
+
+ test_empty_src_panic! {test_panic_empty_load_u32_le, &[0u8; 0], [0u32; 4], load_u32_into_le}
+ test_empty_src_panic! {test_panic_empty_load_u64_le, &[0u8; 0], [0u64; 4], load_u64_into_le}
+
+ test_empty_src_panic! {test_panic_empty_store_u32_le, &[0u32; 0], [0u8; 24], store_u32_into_le}
+ test_empty_src_panic! {test_panic_empty_store_u64_le, &[0u64; 0], [0u8; 24], store_u64_into_le}
+
+ // -1 too low
+ test_dst_length_panic! {test_dst_length_load_u32_le_low, &[0u8; 64], [0u32; 15], load_u32_into_le}
+ test_dst_length_panic! {test_dst_length_load_u64_le_low, &[0u8; 64], [0u64; 7], load_u64_into_le}
+
+ test_dst_length_panic! {test_dst_length_store_u32_le_low, &[0u32; 15], [0u8; 64], store_u32_into_le}
+ test_dst_length_panic! {test_dst_length_store_u64_le_low, &[0u64; 7], [0u8; 64], store_u64_into_le}
+
+ // +1 too high
+ test_dst_length_panic! {test_dst_length_load_u32_le_high, &[0u8; 64], [0u32; 17], load_u32_into_le}
+ test_dst_length_panic! {test_dst_length_load_u64_le_high, &[0u8; 64], [0u64; 9], load_u64_into_le}
+
+ test_dst_length_panic! {test_dst_length_store_u32_le_high, &[0u32; 17], [0u8; 64], store_u32_into_le}
+ test_dst_length_panic! {test_dst_length_store_u64_le_high, &[0u64; 9], [0u8; 64], store_u64_into_le}
+
+ // Ok
+ test_dst_length_ok! {test_dst_length_load_u32_le_ok, &[0u8; 64], [0u32; 16], load_u32_into_le}
+ test_dst_length_ok! {test_dst_length_load_u64_le_ok, &[0u8; 64], [0u64; 8], load_u64_into_le}
+
+ test_dst_length_ok! {test_dst_length_store_u32_le_ok, &[0u32; 16], [0u8; 64], store_u32_into_le}
+ test_dst_length_ok! {test_dst_length_store_u64_le_ok, &[0u64; 8], [0u8; 64], store_u64_into_le}
+
+ #[test]
+ #[should_panic]
+ fn test_load_single_src_high() {
+ load_u32_le(&[0u8; 5]);
+ }
+
+ #[test]
+ #[should_panic]
+ fn test_load_single_src_low() {
+ load_u32_le(&[0u8; 3]);
+ }
+
+ #[test]
+ fn test_load_single_src_ok() {
+ load_u32_le(&[0u8; 4]);
+ }
+
+ #[test]
+ fn test_results_store_and_load_u32_into_le() {
+ let input_0: [u32; 2] = [777190791, 1465409568];
+ let input_1: [u32; 4] = [3418616323, 2289579672, 172726903, 1048927929];
+ let input_2: [u32; 6] = [
+ 84693101, 443297962, 3962861724, 3081916164, 4167874952, 3982893227,
+ ];
+ let input_3: [u32; 8] = [
+ 2761719494, 242571916, 3097304063, 3924274282, 1553851098, 3673278295, 3531531406,
+ 2347852690,
+ ];
+
+ let expected_0: [u8; 8] = [135, 253, 82, 46, 32, 96, 88, 87];
+ let expected_1: [u8; 16] = [
+ 3, 242, 195, 203, 152, 54, 120, 136, 119, 154, 75, 10, 185, 94, 133, 62,
+ ];
+ let expected_2: [u8; 24] = [
+ 109, 80, 12, 5, 170, 48, 108, 26, 156, 120, 52, 236, 4, 79, 178, 183, 136, 185, 108,
+ 248, 171, 32, 102, 237,
+ ];
+ let expected_3: [u8; 32] = [
+ 198, 126, 156, 164, 140, 90, 117, 14, 255, 27, 157, 184, 106, 172, 231, 233, 218, 226,
+ 157, 92, 87, 199, 241, 218, 142, 228, 126, 210, 146, 99, 241, 139,
+ ];
+
+ let mut actual_bytes_0 = [0u8; 8];
+ let mut actual_bytes_1 = [0u8; 16];
+ let mut actual_bytes_2 = [0u8; 24];
+ let mut actual_bytes_3 = [0u8; 32];
+
+ store_u32_into_le(&input_0, &mut actual_bytes_0);
+ store_u32_into_le(&input_1, &mut actual_bytes_1);
+ store_u32_into_le(&input_2, &mut actual_bytes_2);
+ store_u32_into_le(&input_3, &mut actual_bytes_3);
+
+ assert_eq!(actual_bytes_0, expected_0);
+ assert_eq!(actual_bytes_1, expected_1);
+ assert_eq!(actual_bytes_2, expected_2);
+ assert_eq!(actual_bytes_3, expected_3);
+
+ let mut actual_nums_0 = [0u32; 2];
+ let mut actual_nums_1 = [0u32; 4];
+ let mut actual_nums_2 = [0u32; 6];
+ let mut actual_nums_3 = [0u32; 8];
+
+ load_u32_into_le(&actual_bytes_0, &mut actual_nums_0);
+ load_u32_into_le(&actual_bytes_1, &mut actual_nums_1);
+ load_u32_into_le(&actual_bytes_2, &mut actual_nums_2);
+ load_u32_into_le(&actual_bytes_3, &mut actual_nums_3);
+
+ assert_eq!(actual_nums_0, input_0);
+ assert_eq!(actual_nums_1, input_1);
+ assert_eq!(actual_nums_2, input_2);
+ assert_eq!(actual_nums_3, input_3);
+ }
+
+ #[test]
+ fn test_results_store_and_load_u64_into_le() {
+ let input_0: [u64; 2] = [3449173576222258260, 2574723713182514848];
+ let input_1: [u64; 4] = [
+ 18418572897904167042,
+ 8576666536239673655,
+ 11410394363908906546,
+ 7465319841649779999,
+ ];
+ let input_2: [u64; 6] = [
+ 9356732802025012686,
+ 185726711773006573,
+ 11478604380402216982,
+ 11229612629557120299,
+ 2892361689551487626,
+ 11014300370630005317,
+ ];
+ let input_3: [u64; 8] = [
+ 9519534723912119720,
+ 6001603601558183532,
+ 8164850737304360888,
+ 571607234094878696,
+ 4752095875230140457,
+ 13190954815003641110,
+ 16657196750477544576,
+ 10329042493888204415,
+ ];
+
+ let expected_0: [u8; 16] = [
+ 84, 52, 100, 211, 23, 237, 221, 47, 160, 190, 4, 95, 147, 65, 187, 35,
+ ];
+ let expected_1: [u8; 32] = [
+ 130, 8, 55, 1, 119, 234, 155, 255, 55, 177, 139, 9, 198, 112, 6, 119, 50, 222, 232, 23,
+ 56, 221, 89, 158, 31, 229, 53, 208, 215, 36, 154, 103,
+ ];
+ let expected_2: [u8; 48] = [
+ 206, 61, 242, 202, 232, 202, 217, 129, 237, 10, 136, 216, 117, 213, 147, 2, 22, 240,
+ 29, 35, 222, 49, 76, 159, 43, 13, 254, 133, 48, 153, 215, 155, 138, 66, 170, 219, 161,
+ 187, 35, 40, 69, 210, 218, 176, 212, 167, 218, 152,
+ ];
+ let expected_3: [u8; 64] = [
+ 168, 53, 199, 13, 101, 46, 28, 132, 108, 158, 148, 129, 173, 250, 73, 83, 184, 215, 28,
+ 129, 124, 96, 79, 113, 232, 207, 68, 59, 192, 193, 238, 7, 41, 8, 177, 85, 5, 214, 242,
+ 65, 22, 69, 133, 252, 131, 175, 15, 183, 128, 76, 1, 226, 48, 64, 42, 231, 127, 14, 31,
+ 46, 108, 33, 88, 143,
+ ];
+
+ let mut actual_bytes_0 = [0u8; 16];
+ let mut actual_bytes_1 = [0u8; 32];
+ let mut actual_bytes_2 = [0u8; 48];
+ let mut actual_bytes_3 = [0u8; 64];
+
+ store_u64_into_le(&input_0, &mut actual_bytes_0);
+ store_u64_into_le(&input_1, &mut actual_bytes_1);
+ store_u64_into_le(&input_2, &mut actual_bytes_2);
+ store_u64_into_le(&input_3, &mut actual_bytes_3);
+
+ assert_eq!(actual_bytes_0, expected_0);
+ assert_eq!(actual_bytes_1, expected_1);
+ assert_eq!(actual_bytes_2.as_ref(), expected_2.as_ref());
+ assert_eq!(actual_bytes_3.as_ref(), expected_3.as_ref());
+
+ let mut actual_nums_0 = [0u64; 2];
+ let mut actual_nums_1 = [0u64; 4];
+ let mut actual_nums_2 = [0u64; 6];
+ let mut actual_nums_3 = [0u64; 8];
+
+ load_u64_into_le(&actual_bytes_0, &mut actual_nums_0);
+ load_u64_into_le(&actual_bytes_1, &mut actual_nums_1);
+ load_u64_into_le(&actual_bytes_2, &mut actual_nums_2);
+ load_u64_into_le(&actual_bytes_3, &mut actual_nums_3);
+
+ assert_eq!(actual_nums_0, input_0);
+ assert_eq!(actual_nums_1, input_1);
+ assert_eq!(actual_nums_2, input_2);
+ assert_eq!(actual_nums_3, input_3);
+ }
+
+ #[test]
+ fn test_results_load_u32() {
+ let input_0: [u8; 4] = [203, 12, 195, 63];
+ let expected_0: u32 = 1069747403;
+
+ assert_eq!(load_u32_le(&input_0), expected_0);
+ }
+
+ #[quickcheck]
+ #[cfg(feature = "safe_api")]
+ /// Load and store should not change the result.
+ fn prop_load_store_u32_le(src: Vec<u8>) -> bool {
+ if !src.is_empty() && src.len() % 4 == 0 {
+ let mut dst_load = vec![0u32; src.len() / 4];
+ load_u32_into_le(&src[..], &mut dst_load);
+ // Test that loading a single also is working correctly
+ dst_load[0] = load_u32_le(&src[..4]);
+ let mut dst_store = src.clone();
+ store_u32_into_le(&dst_load[..], &mut dst_store);
+
+ dst_store == src
+ } else {
+ // Otherwise above functions panic.
+ true
+ }
+ }
+
+ #[quickcheck]
+ #[cfg(feature = "safe_api")]
+ /// Load and store should not change the result.
+ fn prop_load_store_u64_le(src: Vec<u8>) -> bool {
+ if !src.is_empty() && src.len() % 8 == 0 {
+ let mut dst_load = vec![0u64; src.len() / 8];
+ load_u64_into_le(&src[..], &mut dst_load);
+ let mut dst_store = src.clone();
+ store_u64_into_le(&dst_load[..], &mut dst_store);
+
+ dst_store == src
+ } else {
+ // Otherwise above functions panic.
+ true
+ }
+ }
+
+ #[quickcheck]
+ #[cfg(feature = "safe_api")]
+ /// Store and load should not change the result.
+ fn prop_store_load_u32_le(src: Vec<u32>) -> bool {
+ let mut dst_store = vec![0u8; src.len() * 4];
+ store_u32_into_le(&src[..], &mut dst_store);
+ let mut dst_load = src.clone();
+ load_u32_into_le(&dst_store[..], &mut dst_load);
+ if dst_store.len() >= 4 {
+ // Test that loading a single also is working correctly
+ dst_load[0] = load_u32_le(&dst_store[..4]);
+ }
+
+ dst_load == src
+ }
+
+ #[quickcheck]
+ #[cfg(feature = "safe_api")]
+ /// Store and load should not change the result.
+ fn prop_store_load_u64_le(src: Vec<u64>) -> bool {
+ let mut dst_store = vec![0u8; src.len() * 8];
+ store_u64_into_le(&src[..], &mut dst_store);
+ let mut dst_load = src.clone();
+ load_u64_into_le(&dst_store[..], &mut dst_load);
+
+ dst_load == src
+ }
+}
diff --git a/vendor/orion/src/util/mod.rs b/vendor/orion/src/util/mod.rs
new file mode 100644
index 0000000..27fc291
--- /dev/null
+++ b/vendor/orion/src/util/mod.rs
@@ -0,0 +1,186 @@
+// MIT License
+
+// Copyright (c) 2018-2023 The orion Developers
+
+// 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.
+
+use crate::errors;
+use subtle::ConstantTimeEq;
+
+/// xor_slices!(src, destination): XOR $src into $destination slice.
+/// Uses iter() and .zip(), so it short-circuits on the slice that has
+/// the smallest length.
+macro_rules! xor_slices {
+ ($src:expr, $destination:expr) => {
+ for (inplace, _src_elem) in $destination.iter_mut().zip($src.iter()) {
+ *inplace ^= _src_elem;
+ }
+ };
+}
+
+pub(crate) mod endianness;
+pub(crate) mod u32x4;
+pub(crate) mod u64x4;
+
+#[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."]
+#[cfg(feature = "safe_api")]
+/// Generate random bytes using a CSPRNG. Not available in `no_std` context.
+///
+/// # About:
+/// This function can be used to generate cryptographic keys, salts or other
+/// values that rely on strong randomness. Please note that most keys and other
+/// types used throughout Orion, implement their own `generate()` function and
+/// it is strongly preferred to use those, compared to [`secure_rand_bytes()`].
+///
+/// This uses [`getrandom`].
+///
+/// # Parameters:
+/// - `dst`: Destination buffer for the randomly generated bytes. The amount of
+/// bytes to be generated is
+/// implied by the length of `dst`.
+///
+/// # Errors:
+/// An error will be returned if:
+/// - `dst` is empty.
+///
+/// # Panics:
+/// A panic will occur if:
+/// - Failure to generate random bytes securely.
+/// - The platform is not supported by [`getrandom`].
+///
+/// # Example:
+/// ```rust
+/// use orion::util;
+///
+/// let mut salt = [0u8; 64];
+/// util::secure_rand_bytes(&mut salt)?;
+/// # Ok::<(), orion::errors::UnknownCryptoError>(())
+/// ```
+/// [`getrandom`]: https://github.com/rust-random/getrandom
+pub fn secure_rand_bytes(dst: &mut [u8]) -> Result<(), errors::UnknownCryptoError> {
+ if dst.is_empty() {
+ return Err(errors::UnknownCryptoError);
+ }
+
+ getrandom::getrandom(dst).unwrap();
+
+ Ok(())
+}
+
+#[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."]
+/// Compare two equal length slices in constant time.
+///
+/// # About:
+/// Compare two equal length slices, in constant time, using the
+/// [subtle](https://github.com/dalek-cryptography/subtle) crate.
+///
+/// # Parameters:
+/// - `a`: The first slice used in the comparison.
+/// - `b`: The second slice used in the comparison.
+///
+/// # Errors:
+/// An error will be returned if:
+/// - `a` and `b` do not have the same length.
+/// - `a` is not equal to `b`.
+///
+/// # Example:
+/// ```rust
+/// # #[cfg(feature = "safe_api")] {
+/// use orion::util;
+///
+/// let mut rnd_bytes = [0u8; 64];
+/// assert!(util::secure_cmp(&rnd_bytes, &[0u8; 64]).is_ok());
+///
+/// util::secure_rand_bytes(&mut rnd_bytes)?;
+/// assert!(util::secure_cmp(&rnd_bytes, &[0u8; 64]).is_err());
+/// # }
+/// # Ok::<(), orion::errors::UnknownCryptoError>(())
+/// ```
+pub fn secure_cmp(a: &[u8], b: &[u8]) -> Result<(), errors::UnknownCryptoError> {
+ if a.ct_eq(b).into() {
+ Ok(())
+ } else {
+ Err(errors::UnknownCryptoError)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[cfg(feature = "safe_api")]
+ #[test]
+ fn rand_key_len_ok() {
+ let mut dst = [0u8; 64];
+ secure_rand_bytes(&mut dst).unwrap();
+ }
+
+ #[cfg(feature = "safe_api")]
+ #[test]
+ fn rand_key_len_error() {
+ let mut dst = [0u8; 0];
+ assert!(secure_rand_bytes(&mut dst).is_err());
+
+ let err = secure_rand_bytes(&mut dst).unwrap_err();
+ assert_eq!(err, errors::UnknownCryptoError);
+ }
+
+ #[test]
+ fn test_ct_eq_ok() {
+ let buf_1 = [0x06; 10];
+ let buf_2 = [0x06; 10];
+
+ assert!(secure_cmp(&buf_1, &buf_2).is_ok());
+ assert!(secure_cmp(&buf_2, &buf_1).is_ok());
+ }
+
+ #[test]
+ fn test_ct_eq_diff_len() {
+ let buf_1 = [0x06; 10];
+ let buf_2 = [0x06; 5];
+
+ assert!(secure_cmp(&buf_1, &buf_2).is_err());
+ assert!(secure_cmp(&buf_2, &buf_1).is_err());
+ }
+
+ #[test]
+ fn test_ct_ne() {
+ let buf_1 = [0x06; 10];
+ let buf_2 = [0x76; 10];
+
+ assert!(secure_cmp(&buf_1, &buf_2).is_err());
+ assert!(secure_cmp(&buf_2, &buf_1).is_err());
+ }
+
+ #[test]
+ fn test_ct_ne_reg() {
+ assert!(secure_cmp(&[0], &[0, 1]).is_err());
+ assert!(secure_cmp(&[0, 1], &[0]).is_err());
+ }
+
+ #[quickcheck]
+ #[cfg(feature = "safe_api")]
+ fn prop_secure_cmp(a: Vec<u8>, b: Vec<u8>) -> bool {
+ if a == b {
+ secure_cmp(&a, &b).is_ok()
+ } else {
+ secure_cmp(&a, &b).is_err()
+ }
+ }
+}
diff --git a/vendor/orion/src/util/u32x4.rs b/vendor/orion/src/util/u32x4.rs
new file mode 100644
index 0000000..c1ff1bc
--- /dev/null
+++ b/vendor/orion/src/util/u32x4.rs
@@ -0,0 +1,98 @@
+// MIT License
+
+// Copyright (c) 2019-2023 The orion Developers
+
+// 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.
+
+#[derive(Clone, Copy)]
+pub(crate) struct U32x4(
+ pub(crate) u32,
+ pub(crate) u32,
+ pub(crate) u32,
+ pub(crate) u32,
+);
+
+impl core::ops::BitXor for U32x4 {
+ type Output = Self;
+
+ #[must_use]
+ fn bitxor(self, _rhs: Self) -> Self::Output {
+ Self(
+ self.0 ^ _rhs.0,
+ self.1 ^ _rhs.1,
+ self.2 ^ _rhs.2,
+ self.3 ^ _rhs.3,
+ )
+ }
+}
+
+impl zeroize::Zeroize for U32x4 {
+ fn zeroize(&mut self) {
+ self.0.zeroize();
+ self.1.zeroize();
+ self.2.zeroize();
+ self.3.zeroize();
+ }
+}
+
+impl U32x4 {
+ #[must_use]
+ pub(crate) const fn wrapping_add(self, _rhs: Self) -> Self {
+ Self(
+ self.0.wrapping_add(_rhs.0),
+ self.1.wrapping_add(_rhs.1),
+ self.2.wrapping_add(_rhs.2),
+ self.3.wrapping_add(_rhs.3),
+ )
+ }
+
+ #[must_use]
+ pub(crate) const fn shl_1(self) -> Self {
+ Self(self.1, self.2, self.3, self.0)
+ }
+
+ #[must_use]
+ pub(crate) const fn shl_2(self) -> Self {
+ Self(self.2, self.3, self.0, self.1)
+ }
+
+ #[must_use]
+ pub(crate) const fn shl_3(self) -> Self {
+ Self(self.3, self.0, self.1, self.2)
+ }
+
+ #[must_use]
+ pub(crate) const fn rotate_left(self, n: u32) -> Self {
+ Self(
+ self.0.rotate_left(n),
+ self.1.rotate_left(n),
+ self.2.rotate_left(n),
+ self.3.rotate_left(n),
+ )
+ }
+
+ pub(crate) fn store_into_le(&self, slice_in: &mut [u8]) {
+ debug_assert_eq!(slice_in.len(), core::mem::size_of::<u32>() * 4);
+ let mut iter = slice_in.chunks_exact_mut(core::mem::size_of::<u32>());
+ iter.next().unwrap().copy_from_slice(&self.0.to_le_bytes());
+ iter.next().unwrap().copy_from_slice(&self.1.to_le_bytes());
+ iter.next().unwrap().copy_from_slice(&self.2.to_le_bytes());
+ iter.next().unwrap().copy_from_slice(&self.3.to_le_bytes());
+ }
+}
diff --git a/vendor/orion/src/util/u64x4.rs b/vendor/orion/src/util/u64x4.rs
new file mode 100644
index 0000000..bc181c4
--- /dev/null
+++ b/vendor/orion/src/util/u64x4.rs
@@ -0,0 +1,114 @@
+// MIT License
+
+// Copyright (c) 2019-2023 The orion Developers
+
+// 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.
+
+#[derive(Clone, Copy, Default)]
+pub(crate) struct U64x4(
+ pub(crate) u64,
+ pub(crate) u64,
+ pub(crate) u64,
+ pub(crate) u64,
+);
+
+impl core::ops::BitXor for U64x4 {
+ type Output = Self;
+
+ #[must_use]
+ fn bitxor(self, _rhs: Self) -> Self::Output {
+ Self(
+ self.0 ^ _rhs.0,
+ self.1 ^ _rhs.1,
+ self.2 ^ _rhs.2,
+ self.3 ^ _rhs.3,
+ )
+ }
+}
+
+impl core::ops::BitXorAssign for U64x4 {
+ fn bitxor_assign(&mut self, _rhs: Self) {
+ self.0 ^= _rhs.0;
+ self.1 ^= _rhs.1;
+ self.2 ^= _rhs.2;
+ self.3 ^= _rhs.3;
+ }
+}
+
+impl zeroize::Zeroize for U64x4 {
+ fn zeroize(&mut self) {
+ self.0.zeroize();
+ self.1.zeroize();
+ self.2.zeroize();
+ self.3.zeroize();
+ }
+}
+
+#[cfg(test)]
+impl PartialEq<U64x4> for U64x4 {
+ fn eq(&self, other: &Self) -> bool {
+ self.0 == other.0 && self.1 == other.1 && self.2 == other.2 && self.3 == other.3
+ }
+}
+
+impl U64x4 {
+ #[must_use]
+ pub(crate) const fn wrapping_add(self, _rhs: Self) -> Self {
+ Self(
+ self.0.wrapping_add(_rhs.0),
+ self.1.wrapping_add(_rhs.1),
+ self.2.wrapping_add(_rhs.2),
+ self.3.wrapping_add(_rhs.3),
+ )
+ }
+
+ #[must_use]
+ pub(crate) const fn shl_1(self) -> Self {
+ Self(self.1, self.2, self.3, self.0)
+ }
+
+ #[must_use]
+ pub(crate) const fn shl_2(self) -> Self {
+ Self(self.2, self.3, self.0, self.1)
+ }
+
+ #[must_use]
+ pub(crate) const fn shl_3(self) -> Self {
+ Self(self.3, self.0, self.1, self.2)
+ }
+
+ #[must_use]
+ pub(crate) const fn rotate_right(self, n: u32) -> Self {
+ Self(
+ self.0.rotate_right(n),
+ self.1.rotate_right(n),
+ self.2.rotate_right(n),
+ self.3.rotate_right(n),
+ )
+ }
+
+ pub(crate) fn store_into_le(self, slice_in: &mut [u8]) {
+ debug_assert_eq!(slice_in.len(), core::mem::size_of::<u64>() * 4);
+ let mut iter = slice_in.chunks_exact_mut(core::mem::size_of::<u64>());
+ iter.next().unwrap().copy_from_slice(&self.0.to_le_bytes());
+ iter.next().unwrap().copy_from_slice(&self.1.to_le_bytes());
+ iter.next().unwrap().copy_from_slice(&self.2.to_le_bytes());
+ iter.next().unwrap().copy_from_slice(&self.3.to_le_bytes());
+ }
+}