Skip to content

Commit bbfaab3

Browse files
Merge branch 'release/0.1.2alpha' of ssh://git.bouncycastle.org/bc-rust into merge-pr-43
2 parents 935c5c0 + 4035351 commit bbfaab3

23 files changed

Lines changed: 255 additions & 341 deletions

File tree

alpha_0.1.2_release_notes.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
preventing exposure of stale data in oversized output buffers or on early error returns.
4848
* Reworked the way KeyMaterial hazardous operations work; instead of a stateful .allow_hazardous_operations() /
4949
.drop_hazardous_operations(), it now uses a closure-based do_hazardous_operations(). Github issue #39.
50+
* Renamed KeyMaterial::KeyType's and deleted KeyMaterial::concatenate in order to give a better intuition and
51+
FIPS-alignment.
5052
* Github issues resolved:
5153
* #6: https://github.com/bcgit/bc-rust/issues/6, thanks to Q. T. Felix (github: @Quant-TheodoreFelix)
5254
* #10: https://github.com/bcgit/bc-rust/issues/10, thanks to Nicola Tuveri (github: @romen)

crypto/core-test-framework/src/kdf.rs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -59,31 +59,31 @@ impl TestFrameworkKDF {
5959
assert_eq!(zeroized_key.key_type(), KeyType::Zeroized);
6060
let out_key = H::default().derive_key(&zeroized_key, &[0u8; 10]).unwrap();
6161
// since we've done some computation, the result will not actually be zeroized, even if all input key material was zeroized.
62-
assert_eq!(out_key.key_type(), KeyType::BytesLowEntropy);
62+
assert_eq!(out_key.key_type(), KeyType::Unknown);
6363
assert_eq!(out_key.security_strength(), SecurityStrength::None);
6464

6565
// BytesLowEntropy -> BytesLowEntropy
6666
let low_entropy_key =
67-
KeyMaterial256::from_bytes_as_type(&[1u8; 16], KeyType::BytesLowEntropy).unwrap();
68-
assert_eq!(low_entropy_key.key_type(), KeyType::BytesLowEntropy);
67+
KeyMaterial256::from_bytes_as_type(&[1u8; 16], KeyType::Unknown).unwrap();
68+
assert_eq!(low_entropy_key.key_type(), KeyType::Unknown);
6969
let out_key = H::default().derive_key(&low_entropy_key, &[0u8; 10]).unwrap();
70-
assert_eq!(out_key.key_type(), KeyType::BytesLowEntropy);
70+
assert_eq!(out_key.key_type(), KeyType::Unknown);
7171
assert_eq!(out_key.security_strength(), SecurityStrength::None);
7272

7373
// BytesFullEntropy -> BytesLowEntropy if not enough to fill the hash block
7474
let low_entropy_key =
75-
KeyMaterial256::from_bytes_as_type(&[1u8; 6], KeyType::BytesFullEntropy).unwrap();
76-
assert_eq!(low_entropy_key.key_type(), KeyType::BytesFullEntropy);
75+
KeyMaterial256::from_bytes_as_type(&[1u8; 6], KeyType::CryptographicRandom).unwrap();
76+
assert_eq!(low_entropy_key.key_type(), KeyType::CryptographicRandom);
7777
let out_key = H::default().derive_key(&low_entropy_key, &[0u8; 10]).unwrap();
78-
assert_eq!(out_key.key_type(), KeyType::BytesLowEntropy);
78+
assert_eq!(out_key.key_type(), KeyType::Unknown);
7979
assert_eq!(out_key.security_strength(), SecurityStrength::None);
8080

8181
// BytesFullEntropy -> BytesFullEntropy
8282
let full_entropy_key =
83-
KeyMaterial512::from_bytes_as_type(&[1u8; 64], KeyType::BytesFullEntropy).unwrap();
84-
assert_eq!(full_entropy_key.key_type(), KeyType::BytesFullEntropy);
83+
KeyMaterial512::from_bytes_as_type(&[1u8; 64], KeyType::CryptographicRandom).unwrap();
84+
assert_eq!(full_entropy_key.key_type(), KeyType::CryptographicRandom);
8585
let out_key = H::default().derive_key(&full_entropy_key, &[0u8; 10]).unwrap();
86-
assert_eq!(out_key.key_type(), KeyType::BytesFullEntropy);
86+
assert_eq!(out_key.key_type(), KeyType::CryptographicRandom);
8787
assert!(out_key.security_strength() > SecurityStrength::None);
8888
}
8989

@@ -141,35 +141,35 @@ impl TestFrameworkKDF {
141141
assert_eq!(zeroized_key.security_strength(), SecurityStrength::None);
142142
let keys = [&zeroized_key, &zeroized_key];
143143
let out_key = H::default().derive_key_from_multiple(&keys, &[0u8; 10]).unwrap();
144-
assert_eq!(out_key.key_type(), KeyType::BytesLowEntropy);
144+
assert_eq!(out_key.key_type(), KeyType::Unknown);
145145
assert_eq!(out_key.security_strength(), SecurityStrength::None);
146146

147147
// BytesLowEntropy -> BytesLowEntropy
148148
let low_entropy_key =
149-
KeyMaterial256::from_bytes_as_type(&[1u8; 16], KeyType::BytesLowEntropy).unwrap();
150-
assert_eq!(low_entropy_key.key_type(), KeyType::BytesLowEntropy);
149+
KeyMaterial256::from_bytes_as_type(&[1u8; 16], KeyType::Unknown).unwrap();
150+
assert_eq!(low_entropy_key.key_type(), KeyType::Unknown);
151151
let keys = [&zeroized_key, &low_entropy_key];
152152
let out_key = H::default().derive_key_from_multiple(&keys, &[0u8; 10]).unwrap();
153-
assert_eq!(out_key.key_type(), KeyType::BytesLowEntropy);
153+
assert_eq!(out_key.key_type(), KeyType::Unknown);
154154
assert_eq!(out_key.security_strength(), SecurityStrength::None);
155155

156156
// BytesFullEntropy -> BytesLowEntropy if not enough to fill the hash block
157157
let low_entropy_key =
158-
KeyMaterial256::from_bytes_as_type(&[1u8; 6], KeyType::BytesFullEntropy).unwrap();
159-
assert_eq!(low_entropy_key.key_type(), KeyType::BytesFullEntropy);
158+
KeyMaterial256::from_bytes_as_type(&[1u8; 6], KeyType::CryptographicRandom).unwrap();
159+
assert_eq!(low_entropy_key.key_type(), KeyType::CryptographicRandom);
160160
let keys = [&zeroized_key, &low_entropy_key];
161161
let out_key = H::default().derive_key_from_multiple(&keys, &[0u8; 10]).unwrap();
162-
assert_eq!(out_key.key_type(), KeyType::BytesLowEntropy);
162+
assert_eq!(out_key.key_type(), KeyType::Unknown);
163163
assert_eq!(out_key.security_strength(), SecurityStrength::None);
164164

165165
// BytesFullEntropy -> BytesFullEntropy
166166
let zeroized64_key = KeyMaterial512::new();
167167
let full_entropy_key =
168-
KeyMaterial512::from_bytes_as_type(&[1u8; 64], KeyType::BytesFullEntropy).unwrap();
169-
assert_eq!(full_entropy_key.key_type(), KeyType::BytesFullEntropy);
168+
KeyMaterial512::from_bytes_as_type(&[1u8; 64], KeyType::CryptographicRandom).unwrap();
169+
assert_eq!(full_entropy_key.key_type(), KeyType::CryptographicRandom);
170170
let keys = [&zeroized64_key, &full_entropy_key];
171171
let out_key = H::default().derive_key_from_multiple(&keys, &[0u8; 10]).unwrap();
172-
assert_eq!(out_key.key_type(), KeyType::BytesFullEntropy);
172+
assert_eq!(out_key.key_type(), KeyType::CryptographicRandom);
173173
assert!(out_key.security_strength() > SecurityStrength::None);
174174
}
175175
}

crypto/core/src/key_material.rs

Lines changed: 34 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,13 @@ pub trait KeyMaterialTrait: KeyMaterialInternalTrait {
8585
///
8686
/// let key_bytes = [0u8; 16];
8787
/// let mut key = KeyMaterial256::new();
88-
/// let res = key.set_bytes_as_type(&key_bytes, KeyType::BytesLowEntropy);
88+
/// let res = key.set_bytes_as_type(&key_bytes, KeyType::Unknown);
8989
/// match res {
9090
/// Err(KeyMaterialError::ActingOnZeroizedKey) => {
9191
/// // Either figure out why your passed an all-zero key,
9292
/// // or set the key type manually, if that's what you intended.
9393
/// do_hazardous_operations(&mut key, |key| {
94-
/// key.set_key_type(KeyType::BytesLowEntropy)
94+
/// key.set_key_type(KeyType::Unknown)
9595
/// }).unwrap(); // probably you should do something more elegant than .unwrap in your code ;)
9696
/// },
9797
/// Err(_) => { /* figure out what else went wrong */ },
@@ -103,7 +103,7 @@ pub trait KeyMaterialTrait: KeyMaterialInternalTrait {
103103
/// Since this zeroizes and resets the key material, this is considered a dangerous conversion.
104104
///
105105
/// Will set the [SecurityStrength] automatically according to the following rules:
106-
/// * If [KeyType] is [KeyType::Zeroized] or [KeyType::BytesLowEntropy] then it will be [SecurityStrength::None].
106+
/// * If [KeyType] is [KeyType::Zeroized] or [KeyType::Unknown] then it will be [SecurityStrength::None].
107107
/// * Otherwise it will set it based on the length of the provided source bytes.
108108
fn set_bytes_as_type(
109109
&mut self,
@@ -160,7 +160,7 @@ pub trait KeyMaterialTrait: KeyMaterialInternalTrait {
160160
///
161161
/// # 🚨 Hazardous Operation🚨
162162
/// Inside a [do_hazardous_operations] closure this will set the key to any [KeyType].
163-
/// Outside such a closure, only "safe" conversions are permitted: a [KeyType::BytesFullEntropy]
163+
/// Outside such a closure, only "safe" conversions are permitted: a [KeyType::CryptographicRandom]
164164
/// key may be converted to any type, and any type may be converted to itself (a no-op).
165165
/// A hazardous conversion attempted outside a [do_hazardous_operations] closure returns
166166
/// [KeyMaterialError::HazardousOperationNotPermitted], and converting a [KeyType::Zeroized] key
@@ -202,18 +202,6 @@ pub trait KeyMaterialTrait: KeyMaterialInternalTrait {
202202
/// hold a different key, potentially of a different length.
203203
fn zeroize(&mut self);
204204

205-
/// Adds the other KeyMaterial into this one, assuming there is space.
206-
///
207-
/// Throws [KeyMaterialError::InvalidLength] if this object does not have enough space to add the other one.
208-
///
209-
/// The resulting [KeyType] and security strength will be the lesser of the two keys.
210-
/// In other words, concatenating two 128-bit full entropy keys generated at a 128-bit DRBG security level
211-
/// will result in a 256-bit full entropy key still at the 128-bit DRBG security level.
212-
/// Concatenating a full entropy key with a low entropy key will result in a low entropy key.
213-
///
214-
/// Returns the new key_len.
215-
fn concatenate(&mut self, other: &dyn KeyMaterialTrait) -> Result<usize, KeyMaterialError>;
216-
217205
/// Perform a constant-time comparison between the two key material buffers,
218206
/// ignoring differences in capacity, [KeyType], [SecurityStrength], etc.
219207
fn equals(&self, other: &dyn KeyMaterialTrait) -> bool;
@@ -238,11 +226,18 @@ pub enum KeyType {
238226
/// The KeyMaterial is zeroized and MUST NOT be used for any cryptographic operation in this state.
239227
Zeroized,
240228

241-
/// The KeyMaterial contains data of low or unknown entropy.
242-
BytesLowEntropy,
229+
/// The KeyMaterial contains non-zero data of unknown key type.
230+
/// A KeyMaterial of key type Unknown will always have a [SecurityStrength] of [SecurityStrength::None].
231+
///
232+
/// This is the default KeyType for data loaded via [KeyMaterial::from_bytes].
233+
/// Promotion from Unknown to any other key type is considered to be a hazardous operation
234+
/// and must be done within a [do_hazardous_operations] closure.
235+
/// If you want to import key material directly into a known key type, use [KeyMaterial::from_bytes_as_type],
236+
/// which does not require a hazardous operations closure.
237+
Unknown,
243238

244-
/// The KeyMaterial contains data of full entropy and can be safely converted to any other full-entropy key type.
245-
BytesFullEntropy,
239+
/// The KeyMaterial contains data of full entropy and can be safely converted to any other key type.
240+
CryptographicRandom,
246241

247242
/// A seed for asymmetric private keys, RNGs, and other seed-based cryptographic objects.
248243
Seed,
@@ -283,16 +278,16 @@ impl<const KEY_LEN: usize> KeyMaterial<KEY_LEN> {
283278
})?;
284279

285280
key.key_len = KEY_LEN;
286-
key.key_type = KeyType::BytesFullEntropy;
281+
key.key_type = KeyType::CryptographicRandom;
287282
key.security_strength = rng.security_strength();
288283
Ok(key)
289284
}
290285

291286
/// Constructor.
292-
/// Loads the provided data into a new KeyMaterial of type [KeyType::BytesLowEntropy].
287+
/// Loads the provided data into a new KeyMaterial of type [KeyType::Unknown].
293288
/// It will detect if you give it all-zero source data and set the key type to [KeyType::Zeroized] instead.
294289
pub fn from_bytes(source: &[u8]) -> Result<Self, KeyMaterialError> {
295-
Self::from_bytes_as_type(source, KeyType::BytesLowEntropy)
290+
Self::from_bytes_as_type(source, KeyType::Unknown)
296291
}
297292

298293
/// Constructor.
@@ -302,7 +297,7 @@ impl<const KEY_LEN: usize> KeyMaterial<KEY_LEN> {
302297
/// It will detect if you give it all-zero source data and set the key type to [KeyType::Zeroized] instead.
303298
///
304299
/// Will set the [SecurityStrength] automatically according to the following rules:
305-
/// * If [KeyType] is [KeyType::Zeroized] or [KeyType::BytesLowEntropy] then it will be [SecurityStrength::None].
300+
/// * If [KeyType] is [KeyType::Zeroized] or [KeyType::Unknown] then it will be [SecurityStrength::None].
306301
/// * Otherwise it will set it based on the length of the provided source bytes.
307302
pub fn from_bytes_as_type(source: &[u8], key_type: KeyType) -> Result<Self, KeyMaterialError> {
308303
let mut key_material = Self::default();
@@ -359,7 +354,7 @@ impl<const KEY_LEN: usize> KeyMaterialTrait for KeyMaterial<KEY_LEN> {
359354
self.key_type = new_key_type;
360355

361356
do_hazardous_operations(self, |s| {
362-
if new_key_type <= KeyType::BytesLowEntropy {
357+
if new_key_type <= KeyType::Unknown {
363358
s.set_security_strength(SecurityStrength::None)?;
364359
} else {
365360
s.set_security_strength(SecurityStrength::from_bits(source.len() * 8))?;
@@ -435,12 +430,12 @@ impl<const KEY_LEN: usize> KeyMaterialTrait for KeyMaterial<KEY_LEN> {
435430
KeyType::Zeroized => {
436431
return Err(KeyMaterialError::ActingOnZeroizedKey);
437432
}
438-
KeyType::BytesFullEntropy => {
433+
KeyType::CryptographicRandom => {
439434
// raw full entropy can be safely converted to anything.
440435
self.key_type = key_type;
441436
}
442-
KeyType::BytesLowEntropy => match key_type {
443-
KeyType::BytesLowEntropy => { /* No change */ }
437+
KeyType::Unknown => match key_type {
438+
KeyType::Unknown => { /* No change */ }
444439
_ => {
445440
return Err(KeyMaterialError::HazardousOperationNotPermitted);
446441
}
@@ -482,7 +477,7 @@ impl<const KEY_LEN: usize> KeyMaterialTrait for KeyMaterial<KEY_LEN> {
482477
return Err(KeyMaterialError::HazardousOperationNotPermitted);
483478
};
484479

485-
if self.key_type <= KeyType::BytesLowEntropy && strength > SecurityStrength::None {
480+
if self.key_type <= KeyType::Unknown && strength > SecurityStrength::None {
486481
return Err(KeyMaterialError::SecurityStrength(
487482
"BytesLowEntropy keys cannot have a security strength other than None.",
488483
));
@@ -525,11 +520,11 @@ impl<const KEY_LEN: usize> KeyMaterialTrait for KeyMaterial<KEY_LEN> {
525520
}
526521
fn is_full_entropy(&self) -> bool {
527522
match self.key_type {
528-
KeyType::BytesFullEntropy
523+
KeyType::CryptographicRandom
529524
| KeyType::Seed
530525
| KeyType::MACKey
531526
| KeyType::SymmetricCipherKey => true,
532-
KeyType::Zeroized | KeyType::BytesLowEntropy => false,
527+
KeyType::Zeroized | KeyType::Unknown => false,
533528
}
534529
}
535530

@@ -539,18 +534,6 @@ impl<const KEY_LEN: usize> KeyMaterialTrait for KeyMaterial<KEY_LEN> {
539534
self.key_type = KeyType::Zeroized;
540535
}
541536

542-
fn concatenate(&mut self, other: &dyn KeyMaterialTrait) -> Result<usize, KeyMaterialError> {
543-
let new_key_len = self.key_len() + other.key_len();
544-
if self.key_len() + other.key_len() > KEY_LEN {
545-
return Err(KeyMaterialError::InputDataLongerThanKeyCapacity);
546-
}
547-
self.buf[self.key_len..new_key_len].copy_from_slice(other.ref_to_bytes());
548-
self.key_len += other.key_len();
549-
self.key_type = min(&self.key_type, &other.key_type()).clone();
550-
self.security_strength = min(&self.security_strength, &other.security_strength()).clone();
551-
Ok(self.key_len())
552-
}
553-
554537
fn equals(&self, other: &dyn KeyMaterialTrait) -> bool {
555538
if self.key_len() != other.key_len() {
556539
return false;
@@ -561,7 +544,7 @@ impl<const KEY_LEN: usize> KeyMaterialTrait for KeyMaterial<KEY_LEN> {
561544

562545
/// Checks for equality of the key data (using a constant-time comparison), but does not check that
563546
/// the two keys have the same type.
564-
/// Therefore, for example, two keys loaded from the same bytes, one with type [KeyType::BytesLowEntropy] and
547+
/// Therefore, for example, two keys loaded from the same bytes, one with type [KeyType::Unknown] and
565548
/// the other with [KeyType::MACKey] will be considered equal.
566549
impl<const KEY_LEN: usize> PartialEq for KeyMaterial<KEY_LEN> {
567550
fn eq(&self, other: &Self) -> bool {
@@ -582,18 +565,18 @@ impl PartialOrd for KeyType {
582565
KeyType::Zeroized => Some(Ordering::Equal),
583566
_ => Some(Ordering::Less),
584567
},
585-
KeyType::BytesLowEntropy => match other {
568+
KeyType::Unknown => match other {
586569
KeyType::Zeroized => Some(Ordering::Greater),
587-
KeyType::BytesLowEntropy => Some(Ordering::Equal),
570+
KeyType::Unknown => Some(Ordering::Equal),
588571
_ => Some(Ordering::Less),
589572
},
590-
KeyType::BytesFullEntropy => match other {
591-
KeyType::Zeroized | KeyType::BytesLowEntropy => Some(Ordering::Greater),
592-
KeyType::BytesFullEntropy => Some(Ordering::Equal),
573+
KeyType::CryptographicRandom => match other {
574+
KeyType::Zeroized | KeyType::Unknown => Some(Ordering::Greater),
575+
KeyType::CryptographicRandom => Some(Ordering::Equal),
593576
_ => Some(Ordering::Less),
594577
},
595578
KeyType::Seed | KeyType::MACKey | KeyType::SymmetricCipherKey => match other {
596-
KeyType::Zeroized | KeyType::BytesLowEntropy | KeyType::BytesFullEntropy => {
579+
KeyType::Zeroized | KeyType::Unknown | KeyType::CryptographicRandom => {
597580
Some(Ordering::Greater)
598581
}
599582
KeyType::Seed | KeyType::MACKey | KeyType::SymmetricCipherKey => {
@@ -736,7 +719,7 @@ impl<const KEY_LEN: usize> KeyMaterialInternalTrait for KeyMaterial<KEY_LEN> {
736719
/// // In this example, we initialize a KeyMateriol512 (64 bytes) with only 32 bytes of input.
737720
/// let mut key = KeyMaterial512::from_bytes_as_type(
738721
/// &[1u8; 32],
739-
/// KeyType::BytesFullEntropy
722+
/// KeyType::CryptographicRandom
740723
/// ).unwrap();
741724
/// assert_eq!(key.key_len(), 32);
742725
///

crypto/core/src/traits.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,14 +98,14 @@ pub trait KDF: Default {
9898
///
9999
/// ex.:
100100
///
101-
/// * [KeyType::BytesLowEntropy] -> [KeyType::BytesLowEntropy])
102-
/// * [KeyType::BytesFullEntropy] -> [KeyType::BytesFullEntropy])
101+
/// * [KeyType::Unknown] -> [KeyType::Unknown])
102+
/// * [KeyType::CryptographicRandom] -> [KeyType::CryptographicRandom])
103103
/// * [KeyType::SymmetricCipherKey] -> [KeyType::SymmetricCipherKey])
104104
///
105-
/// If provided with an input key, even if it is [KeyType::BytesFullEntropy], but that
105+
/// If provided with an input key, even if it is [KeyType::CryptographicRandom], but that
106106
/// contains less key material than the internal block size of the KDF, then the KDF
107107
/// will not be considered properly seeded, and the output [KeyMaterial] will be set to
108-
/// [KeyType::BytesLowEntropy] -- for example, seeding SHA3-256 with a [KeyMaterial] containing
108+
/// [KeyType::Unknown] -- for example, seeding SHA3-256 with a [KeyMaterial] containing
109109
/// only 128 bits of key material.
110110
///
111111
/// An implement can, and in most cases SHOULD, return a [HashError] if provided
@@ -152,9 +152,9 @@ pub trait KDF: Default {
152152
///
153153
/// Implementations can, and in most cases SHOULD, return a [KeyMaterial] of the same type as the
154154
/// strongest key, and SHOULD throw a [HashError] if all input keys are zeroized.
155-
/// For example output a [KeyType::BytesFullEntropy] key whenever any one of
156-
/// the input keys is a [KeyType::BytesFullEntropy] key.
157-
/// As another example, combining a [KeyType::BytesLowEntropy] key with a [KeyType::MACKey] key
155+
/// For example output a [KeyType::CryptographicRandom] key whenever any one of
156+
/// the input keys is a [KeyType::CryptographicRandom] key.
157+
/// As another example, combining a [KeyType::Unknown] key with a [KeyType::MACKey] key
158158
/// should return a [KeyType::MACKey].
159159
///
160160
/// Output length: this function will create a KeyMaterial populated with the default output length

0 commit comments

Comments
 (0)