Skip to content

Commit 92442a5

Browse files
committed
fix codebase to use secretbox, tighten security
1 parent 14d53e1 commit 92442a5

File tree

5 files changed

+122
-251
lines changed

5 files changed

+122
-251
lines changed

keymanager/key_protection_service/key_custody_core/src/lib.rs

Lines changed: 57 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -171,28 +171,40 @@ pub unsafe extern "C" fn key_manager_decap_and_seal(
171171
aad: *const u8,
172172
aad_len: usize,
173173
out_encapsulated_key: *mut u8,
174-
out_encapsulated_key_len: *mut usize,
174+
out_encapsulated_key_len: usize,
175175
out_ciphertext: *mut u8,
176-
out_ciphertext_len: *mut usize,
176+
out_ciphertext_len: usize,
177177
) -> i32 {
178178
if uuid_bytes.is_null()
179179
|| encapsulated_key.is_null()
180180
|| encapsulated_key_len == 0
181181
|| out_encapsulated_key.is_null()
182-
|| out_encapsulated_key_len.is_null()
182+
|| out_encapsulated_key_len == 0
183183
|| out_ciphertext.is_null()
184-
|| out_ciphertext_len.is_null()
184+
|| out_ciphertext_len == 0
185185
{
186186
return -1;
187187
}
188188

189-
let uuid = unsafe {
190-
let mut bytes = [0u8; 16];
191-
std::ptr::copy_nonoverlapping(uuid_bytes, bytes.as_mut_ptr(), 16);
192-
Uuid::from_bytes(bytes)
189+
// Convert to Safe Types
190+
let uuid = unsafe { std::slice::from_raw_parts(uuid_bytes, 16) };
191+
let enc_key_slice = unsafe { slice::from_raw_parts(encapsulated_key, encapsulated_key_len) };
192+
let aad_slice = if !aad.is_null() && aad_len > 0 {
193+
unsafe { slice::from_raw_parts(aad, aad_len) }
194+
} else {
195+
&[]
196+
};
197+
let out_encapsulated_key =
198+
unsafe { slice::from_raw_parts_mut(out_encapsulated_key, out_encapsulated_key_len) };
199+
let out_ciphertext = unsafe { slice::from_raw_parts_mut(out_ciphertext, out_ciphertext_len) };
200+
201+
let uuid_val = match Uuid::from_slice(uuid) {
202+
Ok(u) => u,
203+
Err(_) => return -1,
193204
};
194205

195-
let key_record = match KEY_REGISTRY.get_key(&uuid) {
206+
// Get key record from registry
207+
let key_record = match KEY_REGISTRY.get_key(&uuid_val) {
196208
Some(record) => record,
197209
None => return -1,
198210
};
@@ -208,61 +220,39 @@ pub unsafe extern "C" fn key_manager_decap_and_seal(
208220

209221
let _kem_algo = match km_common::algorithms::KemAlgorithm::try_from(hpke_algo.kem) {
210222
Ok(k) => k,
211-
Err(_) => return -1,
223+
Err(_) => return -1, // Invalid KEM algorithm
212224
};
213225

214-
let enc_key_slice = unsafe { slice::from_raw_parts(encapsulated_key, encapsulated_key_len) };
215-
216-
// Convert Vault bytes to SecretBox for active usage
217-
let secret =
218-
km_common::crypto::secret_box::SecretBox::new(key_record.private_key.as_bytes().to_vec());
219-
let priv_key = km_common::crypto::PrivateKey::from_secret(secret);
226+
let priv_key = key_record.get_private_key();
220227

221228
// Decapsulate
222-
let mut shared_secret = match km_common::crypto::decaps(&priv_key, enc_key_slice) {
229+
let shared_secret = match km_common::crypto::decaps(&priv_key, enc_key_slice) {
223230
Ok(s) => s,
224231
Err(_) => return -3,
225232
};
226233

227-
let aad_slice = if !aad.is_null() && aad_len > 0 {
228-
unsafe { slice::from_raw_parts(aad, aad_len) }
229-
} else {
230-
&[]
231-
};
232-
233234
// Seal
234-
let (new_enc_key, sealed_ciphertext) = match km_common::crypto::hpke_seal(
235+
let (enc_key, sealed_ciphertext) = match km_common::crypto::hpke_seal(
235236
binding_public_key,
236237
&shared_secret,
237238
aad_slice,
238239
hpke_algo,
239240
) {
240241
Ok(res) => res,
241242
Err(_) => {
242-
shared_secret.zeroize();
243243
return -4;
244244
}
245245
};
246-
shared_secret.zeroize();
247246

248247
// Copy outputs
249-
unsafe {
250-
let enc_len_req = new_enc_key.len();
251-
let ct_len_req = sealed_ciphertext.len();
252-
let enc_len_avail = *out_encapsulated_key_len;
253-
let ct_len_avail = *out_ciphertext_len;
254-
255-
if enc_len_avail < enc_len_req || ct_len_avail < ct_len_req {
256-
return -2;
257-
}
258-
259-
std::ptr::copy_nonoverlapping(new_enc_key.as_ptr(), out_encapsulated_key, enc_len_req);
260-
*out_encapsulated_key_len = enc_len_req;
248+
let enc_len_req = enc_key.len();
249+
let ct_len_req = sealed_ciphertext.len();
261250

262-
std::ptr::copy_nonoverlapping(sealed_ciphertext.as_ptr(), out_ciphertext, ct_len_req);
263-
*out_ciphertext_len = ct_len_req;
251+
if out_encapsulated_key_len != enc_len_req || out_ciphertext_len != ct_len_req {
252+
return -2;
264253
}
265-
254+
out_encapsulated_key.copy_from_slice(enc_key.as_slice());
255+
out_ciphertext.copy_from_slice(sealed_ciphertext.as_slice());
266256
0
267257
}
268258

@@ -485,14 +475,14 @@ mod tests {
485475
// 2. Generate KEM key in registry
486476
let mut uuid_bytes = [0u8; 16];
487477
let mut kem_pubkey_bytes = [0u8; 32];
488-
let mut kem_pubkey_len = 32;
478+
let kem_pubkey_len = 32;
489479
let algo = HpkeAlgorithm {
490480
kem: KemAlgorithm::DhkemX25519HkdfSha256 as i32,
491481
kdf: KdfAlgorithm::HkdfSha256 as i32,
492482
aead: AeadAlgorithm::Aes256Gcm as i32,
493483
};
494484

495-
let result = unsafe {
485+
unsafe {
496486
key_manager_generate_kem_keypair(
497487
algo,
498488
binding_pk.as_bytes().as_ptr(),
@@ -515,9 +505,9 @@ mod tests {
515505

516506
// Step 3: Call `decap_and_seal`.
517507
let mut out_enc_key = [0u8; 32];
518-
let mut out_enc_key_len = 32;
508+
let out_enc_key_len = 32;
519509
let mut out_ct = [0u8; 48]; // 32 bytes secret + 16 tag
520-
let mut out_ct_len = 48;
510+
let out_ct_len = 48;
521511

522512
let result = unsafe {
523513
key_manager_decap_and_seal(
@@ -527,9 +517,9 @@ mod tests {
527517
aad.as_ptr(),
528518
aad.len(),
529519
out_enc_key.as_mut_ptr(),
530-
&mut out_enc_key_len,
520+
out_enc_key_len,
531521
out_ct.as_mut_ptr(),
532-
&mut out_ct_len,
522+
out_ct_len,
533523
)
534524
};
535525

@@ -545,10 +535,7 @@ mod tests {
545535
// 5. Verify the recovered secret matches what decaps would produce
546536
let key_record = KEY_REGISTRY.get_key(&Uuid::from_bytes(uuid_bytes)).unwrap();
547537

548-
let secret = km_common::crypto::secret_box::SecretBox::new(
549-
key_record.private_key.as_bytes().to_vec(),
550-
);
551-
let priv_key = km_common::crypto::PrivateKey::from_secret(secret);
538+
let priv_key = key_record.get_private_key();
552539

553540
let expected_shared_secret =
554541
km_common::crypto::decaps(&priv_key, &client_enc).expect("decaps failed");
@@ -574,9 +561,9 @@ mod tests {
574561
#[test]
575562
fn test_decap_and_seal_invalid_uuid() {
576563
let mut out_enc_key = [0u8; 32];
577-
let mut out_enc_key_len = 32;
564+
let out_enc_key_len = 32;
578565
let mut out_ct = [0u8; 48];
579-
let mut out_ct_len = 48;
566+
let out_ct_len = 48;
580567

581568
let result = unsafe {
582569
key_manager_decap_and_seal(
@@ -586,9 +573,9 @@ mod tests {
586573
std::ptr::null(),
587574
0,
588575
out_enc_key.as_mut_ptr(),
589-
&mut out_enc_key_len,
576+
out_enc_key_len,
590577
out_ct.as_mut_ptr(),
591-
&mut out_ct_len,
578+
out_ct_len,
592579
)
593580
};
594581

@@ -598,7 +585,7 @@ mod tests {
598585
#[test]
599586
fn test_decap_and_seal_null_args() {
600587
let mut out_enc_key = [0u8; 32];
601-
let mut out_enc_key_len = 32;
588+
let out_enc_key_len = 32;
602589

603590
let result = unsafe {
604591
key_manager_decap_and_seal(
@@ -608,9 +595,9 @@ mod tests {
608595
std::ptr::null(),
609596
0,
610597
out_enc_key.as_mut_ptr(),
611-
&mut out_enc_key_len,
612-
std::ptr::null_mut(),
598+
out_enc_key_len,
613599
std::ptr::null_mut(),
600+
0,
614601
)
615602
};
616603

@@ -626,7 +613,7 @@ mod tests {
626613
// 2. Generate KEM key
627614
let mut uuid_bytes = [0u8; 16];
628615
let mut kem_pubkey_bytes = [0u8; 32];
629-
let mut kem_pubkey_len = 32;
616+
let kem_pubkey_len = 32;
630617
let algo = HpkeAlgorithm {
631618
kem: KemAlgorithm::DhkemX25519HkdfSha256 as i32,
632619
kdf: KdfAlgorithm::HkdfSha256 as i32,
@@ -640,16 +627,16 @@ mod tests {
640627
3600,
641628
uuid_bytes.as_mut_ptr(),
642629
kem_pubkey_bytes.as_mut_ptr(),
643-
&mut kem_pubkey_len,
630+
kem_pubkey_len,
644631
)
645632
};
646633
assert_eq!(res, 0);
647634

648635
// 3. Call with invalid encapsulated key (wrong length for X25519)
649636
let mut out_enc_key = [0u8; 32];
650-
let mut out_enc_key_len = 32;
637+
let out_enc_key_len = 32;
651638
let mut out_ct = [0u8; 48];
652-
let mut out_ct_len = 48;
639+
let out_ct_len = 48;
653640

654641
let result = unsafe {
655642
key_manager_decap_and_seal(
@@ -659,9 +646,9 @@ mod tests {
659646
std::ptr::null(),
660647
0,
661648
out_enc_key.as_mut_ptr(),
662-
&mut out_enc_key_len,
649+
out_enc_key_len,
663650
out_ct.as_mut_ptr(),
664-
&mut out_ct_len,
651+
out_ct_len,
665652
)
666653
};
667654

@@ -677,7 +664,7 @@ mod tests {
677664
// 2. Generate KEM key
678665
let mut uuid_bytes = [0u8; 16];
679666
let mut kem_pubkey_bytes = [0u8; 32];
680-
let mut kem_pubkey_len = 32;
667+
let kem_pubkey_len = 32;
681668
let algo = HpkeAlgorithm {
682669
kem: KemAlgorithm::DhkemX25519HkdfSha256 as i32,
683670
kdf: KdfAlgorithm::HkdfSha256 as i32,
@@ -691,7 +678,7 @@ mod tests {
691678
3600,
692679
uuid_bytes.as_mut_ptr(),
693680
kem_pubkey_bytes.as_mut_ptr(),
694-
&mut kem_pubkey_len,
681+
kem_pubkey_len,
695682
);
696683
}
697684

@@ -703,9 +690,9 @@ mod tests {
703690

704691
// 4. Call with small output buffers
705692
let mut out_enc_key = [0u8; 31]; // Small
706-
let mut out_enc_key_len = 31;
693+
let out_enc_key_len = 31;
707694
let mut out_ct = [0u8; 47]; // Small
708-
let mut out_ct_len = 47;
695+
let out_ct_len = 47;
709696

710697
let result = unsafe {
711698
key_manager_decap_and_seal(
@@ -715,9 +702,9 @@ mod tests {
715702
std::ptr::null(),
716703
0,
717704
out_enc_key.as_mut_ptr(),
718-
&mut out_enc_key_len,
705+
out_enc_key_len,
719706
out_ct.as_mut_ptr(),
720-
&mut out_ct_len,
707+
out_ct_len,
721708
)
722709
};
723710

keymanager/km_common/src/crypto.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
use crate::algorithms::{AeadAlgorithm, HpkeAlgorithm, KdfAlgorithm, KemAlgorithm};
22
pub mod secret_box;
33
use crate::crypto::secret_box::SecretBox;
4-
use bssl_crypto::hkdf;
54
#[cfg(any(test, feature = "test-utils"))]
6-
use bssl_crypto::{aead, aead::Aead};
5+
use bssl_crypto::{aead, aead::Aead, hkdf};
76
use clear_on_drop::clear_stack_on_return;
87
use thiserror::Error;
98

@@ -93,6 +92,12 @@ pub enum PrivateKey {
9392
X25519(X25519PrivateKey),
9493
}
9594

95+
impl From<SecretBox> for PrivateKey {
96+
fn from(secret: SecretBox) -> Self {
97+
PrivateKey::X25519(X25519PrivateKey(secret))
98+
}
99+
}
100+
96101
impl From<PrivateKey> for SecretBox {
97102
fn from(key: PrivateKey) -> SecretBox {
98103
match key {

keymanager/km_common/src/key_types.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub struct KeyMetadata {
4747
pub struct KeyRecord {
4848
pub meta: KeyMetadata,
4949
/// memfd_secrets backed secret key-material
50-
pub private_key: Vault,
50+
private_key: Vault,
5151
}
5252

5353
pub type KeyHandle = Uuid;
@@ -102,6 +102,11 @@ impl KeyRegistry {
102102
}
103103

104104
impl KeyRecord {
105+
/// Returns the private key material.
106+
pub fn get_private_key(&self) -> crypto::PrivateKey {
107+
crypto::PrivateKey::from(self.private_key.get_secret())
108+
}
109+
105110
/// Creates a new long-term Binding key.
106111
pub fn create_binding_key(
107112
algo: HpkeAlgorithm,

0 commit comments

Comments
 (0)