Restrict Sha256 to be used sequentially

Also remove useless HashBlockSize64Bytes bound.
This commit is contained in:
Julien Cretin
2022-01-17 11:45:58 +01:00
committed by Julien Cretin
parent ca2ea2007e
commit ce08f82d68
4 changed files with 21 additions and 12 deletions

View File

@@ -18,7 +18,7 @@ use super::ec::int256::Int256;
use super::ec::point::PointP256; use super::ec::point::PointP256;
use super::hmac::hmac_256; use super::hmac::hmac_256;
use super::rng256::Rng256; use super::rng256::Rng256;
use super::{Hash256, HashBlockSize64Bytes}; use super::Hash256;
use alloc::vec; use alloc::vec;
use alloc::vec::Vec; use alloc::vec::Vec;
#[cfg(feature = "std")] #[cfg(feature = "std")]
@@ -82,7 +82,7 @@ impl SecKey {
/// Creates a deterministic ECDSA signature based on RFC 6979. /// Creates a deterministic ECDSA signature based on RFC 6979.
pub fn sign_rfc6979<H>(&self, msg: &[u8]) -> Signature pub fn sign_rfc6979<H>(&self, msg: &[u8]) -> Signature
where where
H: Hash256 + HashBlockSize64Bytes, H: Hash256,
{ {
let m = ExponentP256::modn(Int256::from_bin(&H::hash(msg))); let m = ExponentP256::modn(Int256::from_bin(&H::hash(msg)));
@@ -131,7 +131,7 @@ impl SecKey {
#[cfg(test)] #[cfg(test)]
pub fn get_k_rfc6979<H>(&self, msg: &[u8]) -> NonZeroExponentP256 pub fn get_k_rfc6979<H>(&self, msg: &[u8]) -> NonZeroExponentP256
where where
H: Hash256 + HashBlockSize64Bytes, H: Hash256,
{ {
let m = ExponentP256::modn(Int256::from_bin(&H::hash(msg))); let m = ExponentP256::modn(Int256::from_bin(&H::hash(msg)));
@@ -288,7 +288,7 @@ impl PubKey {
struct Rfc6979<H> struct Rfc6979<H>
where where
H: Hash256 + HashBlockSize64Bytes, H: Hash256,
{ {
k: [u8; 32], k: [u8; 32],
v: [u8; 32], v: [u8; 32],
@@ -297,7 +297,7 @@ where
impl<H> Rfc6979<H> impl<H> Rfc6979<H>
where where
H: Hash256 + HashBlockSize64Bytes, H: Hash256,
{ {
pub fn new(sk: &SecKey, msg: &[u8]) -> Rfc6979<H> { pub fn new(sk: &SecKey, msg: &[u8]) -> Rfc6979<H> {
let h1 = H::hash(msg); let h1 = H::hash(msg);

View File

@@ -13,7 +13,7 @@
// limitations under the License. // limitations under the License.
use super::hmac::hmac_256; use super::hmac::hmac_256;
use super::{Hash256, HashBlockSize64Bytes}; use super::Hash256;
const HASH_SIZE: usize = 32; const HASH_SIZE: usize = 32;
@@ -28,7 +28,7 @@ const HASH_SIZE: usize = 32;
/// default block of zeros and the output length l as 32. /// default block of zeros and the output length l as 32.
pub fn hkdf_empty_salt_256<H>(ikm: &[u8], info: &[u8]) -> [u8; HASH_SIZE] pub fn hkdf_empty_salt_256<H>(ikm: &[u8], info: &[u8]) -> [u8; HASH_SIZE]
where where
H: Hash256 + HashBlockSize64Bytes, H: Hash256,
{ {
// Salt is a zero block here. // Salt is a zero block here.
let prk = hmac_256::<H>(&[0; HASH_SIZE], ikm); let prk = hmac_256::<H>(&[0; HASH_SIZE], ikm);
@@ -55,7 +55,7 @@ where
#[cfg(test)] #[cfg(test)]
pub fn hkdf<H>(salt: &[u8], ikm: &[u8], l: u8, info: &[u8]) -> Vec<u8> pub fn hkdf<H>(salt: &[u8], ikm: &[u8], l: u8, info: &[u8]) -> Vec<u8>
where where
H: Hash256 + HashBlockSize64Bytes, H: Hash256,
{ {
let prk = if salt.is_empty() { let prk = if salt.is_empty() {
hmac_256::<H>(&[0; HASH_SIZE], ikm) hmac_256::<H>(&[0; HASH_SIZE], ikm)

View File

@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use super::{Hash256, HashBlockSize64Bytes}; use super::Hash256;
use arrayref::array_ref; use arrayref::array_ref;
use subtle::ConstantTimeEq; use subtle::ConstantTimeEq;
@@ -21,7 +21,7 @@ const HASH_SIZE: usize = 32;
pub fn verify_hmac_256<H>(key: &[u8], contents: &[u8], mac: &[u8; HASH_SIZE]) -> bool pub fn verify_hmac_256<H>(key: &[u8], contents: &[u8], mac: &[u8; HASH_SIZE]) -> bool
where where
H: Hash256 + HashBlockSize64Bytes, H: Hash256,
{ {
let expected_mac = hmac_256::<H>(key, contents); let expected_mac = hmac_256::<H>(key, contents);
bool::from(expected_mac.ct_eq(mac)) bool::from(expected_mac.ct_eq(mac))
@@ -31,7 +31,7 @@ where
// against the pin ¯\_(ツ)_/¯ // against the pin ¯\_(ツ)_/¯
pub fn verify_hmac_256_first_128bits<H>(key: &[u8], contents: &[u8], pin: &[u8; 16]) -> bool pub fn verify_hmac_256_first_128bits<H>(key: &[u8], contents: &[u8], pin: &[u8; 16]) -> bool
where where
H: Hash256 + HashBlockSize64Bytes, H: Hash256,
{ {
let expected_mac = hmac_256::<H>(key, contents); let expected_mac = hmac_256::<H>(key, contents);
bool::from(array_ref![expected_mac, 0, 16].ct_eq(pin)) bool::from(array_ref![expected_mac, 0, 16].ct_eq(pin))
@@ -39,7 +39,7 @@ where
pub fn hmac_256<H>(key: &[u8], contents: &[u8]) -> [u8; HASH_SIZE] pub fn hmac_256<H>(key: &[u8], contents: &[u8]) -> [u8; HASH_SIZE]
where where
H: Hash256 + HashBlockSize64Bytes, H: Hash256,
{ {
let mut ipad: [u8; BLOCK_SIZE] = [0x36; BLOCK_SIZE]; let mut ipad: [u8; BLOCK_SIZE] = [0x36; BLOCK_SIZE];
let mut opad: [u8; BLOCK_SIZE] = [0x5c; BLOCK_SIZE]; let mut opad: [u8; BLOCK_SIZE] = [0x5c; BLOCK_SIZE];

View File

@@ -15,10 +15,17 @@
use super::{Hash256, HashBlockSize64Bytes}; use super::{Hash256, HashBlockSize64Bytes};
use arrayref::{array_mut_ref, array_ref}; use arrayref::{array_mut_ref, array_ref};
use byteorder::{BigEndian, ByteOrder}; use byteorder::{BigEndian, ByteOrder};
use core::cell::Cell;
use core::num::Wrapping; use core::num::Wrapping;
const BLOCK_SIZE: usize = 64; const BLOCK_SIZE: usize = 64;
// To be able to support hardware cryptography, we want to make sure we never compute multiple
// sha256 in parallel. (Note that almost all usage of Sha256 is through Hash256::hash which is
// statically correct. There's only 2 low-level usages in the `hmac::hmac_256` and those are
// sequential.) This variable tracks whether `new` was called but `finalize` wasn't called yet.
const BUSY: Cell<bool> = Cell::new(false);
pub struct Sha256 { pub struct Sha256 {
state: [Wrapping<u32>; 8], state: [Wrapping<u32>; 8],
block: [u8; BLOCK_SIZE], block: [u8; BLOCK_SIZE],
@@ -27,6 +34,7 @@ pub struct Sha256 {
impl Hash256 for Sha256 { impl Hash256 for Sha256 {
fn new() -> Self { fn new() -> Self {
assert!(!BUSY.replace(true));
Sha256 { Sha256 {
state: Sha256::H, state: Sha256::H,
block: [0; BLOCK_SIZE], block: [0; BLOCK_SIZE],
@@ -93,6 +101,7 @@ impl Hash256 for Sha256 {
for i in 0..8 { for i in 0..8 {
BigEndian::write_u32(array_mut_ref![result, 4 * i, 4], self.state[i].0); BigEndian::write_u32(array_mut_ref![result, 4 * i, 4], self.state[i].0);
} }
BUSY.set(false);
result result
} }
} }