summaryrefslogtreecommitdiffstats
path: root/vendor/rfc6979/src/lib.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:41 +0000
commit10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 (patch)
treebdffd5d80c26cf4a7a518281a204be1ace85b4c1 /vendor/rfc6979/src/lib.rs
parentReleasing progress-linux version 1.70.0+dfsg1-9~progress7.99u1. (diff)
downloadrustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.tar.xz
rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.zip
Merging upstream version 1.70.0+dfsg2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/rfc6979/src/lib.rs')
-rw-r--r--vendor/rfc6979/src/lib.rs141
1 files changed, 141 insertions, 0 deletions
diff --git a/vendor/rfc6979/src/lib.rs b/vendor/rfc6979/src/lib.rs
new file mode 100644
index 000000000..32df1e652
--- /dev/null
+++ b/vendor/rfc6979/src/lib.rs
@@ -0,0 +1,141 @@
+#![doc = include_str!("../README.md")]
+
+//! ## Usage
+//!
+//! See also: the documentation for the [`generate_k`] function.
+//!
+//! ```
+//! use crypto_bigint::{ArrayEncoding, U256};
+//! use sha2::{Digest, Sha256};
+//!
+//! // NIST P-256 field modulus
+//! const NIST_P256_MODULUS: U256 =
+//! U256::from_be_hex("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551");
+//!
+//! // Public key for RFC6979 NIST P256/SHA256 test case
+//! const RFC6979_KEY: U256 =
+//! U256::from_be_hex("C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721");
+//!
+//! // Test message for RFC6979 NIST P256/SHA256 test case
+//! const RFC6979_MSG: &[u8; 6] = b"sample";
+//!
+//! // Expected K for RFC6979 NIST P256/SHA256 test case
+//! const RFC6979_EXPECTED_K: U256 =
+//! U256::from_be_hex("A6E3C57DD01ABE90086538398355DD4C3B17AA873382B0F24D6129493D8AAD60");
+//!
+//! let h = Sha256::digest(RFC6979_MSG);
+//! let aad = b"";
+//! let k = rfc6979::generate_k::<Sha256, U256>(&RFC6979_KEY, &NIST_P256_MODULUS, &h, aad);
+//! assert_eq!(&k.to_be_byte_array(), &RFC6979_EXPECTED_K.to_be_byte_array());
+//! ```
+
+#![no_std]
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![forbid(unsafe_code, clippy::unwrap_used)]
+#![warn(missing_docs, rust_2018_idioms)]
+#![doc(
+ html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
+ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg"
+)]
+
+use crypto_bigint::{ArrayEncoding, ByteArray, Integer};
+use hmac::{
+ digest::{
+ core_api::BlockSizeUser, generic_array::GenericArray, Digest, FixedOutput,
+ FixedOutputReset, Mac,
+ },
+ SimpleHmac,
+};
+use zeroize::{Zeroize, Zeroizing};
+
+/// Deterministically generate ephemeral scalar `k`.
+///
+/// Accepts the following parameters and inputs:
+///
+/// - `x`: secret key
+/// - `n`: field modulus
+/// - `h`: hash/digest of input message: must be reduced modulo `n` in advance
+/// - `data`: additional associated data, e.g. CSRNG output used as added entropy
+#[inline]
+pub fn generate_k<D, I>(x: &I, n: &I, h: &ByteArray<I>, data: &[u8]) -> Zeroizing<I>
+where
+ D: Digest + BlockSizeUser + FixedOutput<OutputSize = I::ByteSize> + FixedOutputReset,
+ I: ArrayEncoding + Integer + Zeroize,
+{
+ let mut x = x.to_be_byte_array();
+ let mut hmac_drbg = HmacDrbg::<D>::new(&x, h, data);
+ x.zeroize();
+
+ loop {
+ let mut bytes = ByteArray::<I>::default();
+ hmac_drbg.fill_bytes(&mut bytes);
+ let k = I::from_be_byte_array(bytes);
+
+ if (!k.is_zero() & k.ct_lt(n)).into() {
+ return Zeroizing::new(k);
+ }
+ }
+}
+
+/// Internal implementation of `HMAC_DRBG` as described in NIST SP800-90A.
+///
+/// <https://csrc.nist.gov/publications/detail/sp/800-90a/rev-1/final>
+///
+/// This is a HMAC-based deterministic random bit generator used compute a
+/// deterministic ephemeral scalar `k`.
+pub struct HmacDrbg<D>
+where
+ D: Digest + BlockSizeUser + FixedOutputReset,
+{
+ /// HMAC key `K` (see RFC 6979 Section 3.2.c)
+ k: SimpleHmac<D>,
+
+ /// Chaining value `V` (see RFC 6979 Section 3.2.c)
+ v: GenericArray<u8, D::OutputSize>,
+}
+
+impl<D> HmacDrbg<D>
+where
+ D: Digest + BlockSizeUser + FixedOutputReset,
+{
+ /// Initialize `HMAC_DRBG`
+ pub fn new(entropy_input: &[u8], nonce: &[u8], additional_data: &[u8]) -> Self {
+ let mut k = SimpleHmac::new(&Default::default());
+ let mut v = GenericArray::default();
+
+ for b in &mut v {
+ *b = 0x01;
+ }
+
+ for i in 0..=1 {
+ k.update(&v);
+ k.update(&[i]);
+ k.update(entropy_input);
+ k.update(nonce);
+ k.update(additional_data);
+ k = SimpleHmac::new_from_slice(&k.finalize().into_bytes()).expect("HMAC error");
+
+ // Steps 3.2.e,g: v = HMAC_k(v)
+ k.update(&v);
+ v = k.finalize_reset().into_bytes();
+ }
+
+ Self { k, v }
+ }
+
+ /// Write the next `HMAC_DRBG` output to the given byte slice.
+ pub fn fill_bytes(&mut self, out: &mut [u8]) {
+ for out_chunk in out.chunks_mut(self.v.len()) {
+ self.k.update(&self.v);
+ self.v = self.k.finalize_reset().into_bytes();
+ out_chunk.copy_from_slice(&self.v[..out_chunk.len()]);
+ }
+
+ self.k.update(&self.v);
+ self.k.update(&[0x00]);
+ self.k =
+ SimpleHmac::new_from_slice(&self.k.finalize_reset().into_bytes()).expect("HMAC error");
+ self.k.update(&self.v);
+ self.v = self.k.finalize_reset().into_bytes();
+ }
+}