[KCC] Add generate_kem_keypair and generate_binding_keypair FFIs#633
[KCC] Add generate_kem_keypair and generate_binding_keypair FFIs#633meetrajvala wants to merge 1 commit intogoogle:mainfrom
Conversation
atulpatildbz
left a comment
There was a problem hiding this comment.
On-going review. Will continue tomorrow. Meanwhile you can start working on these comments.
| #[derive(ZeroizeOnDrop)] | ||
| pub struct Vault { | ||
| mmap: MmapMut, | ||
| } |
There was a problem hiding this comment.
MmapMut doesn't implement Zeroize it seems. https://docs.rs/memmap2/latest/memmap2/struct.MmapMut.html#trait-implementations
Implement Drop manually to zero the mmap contents via self.mmap[..].zeroize() before unmapping.
| let name_cstr = CString::new(name) | ||
| .map_err(|_| IoError::new(std::io::ErrorKind::InvalidInput, "Invalid name"))?; | ||
| let fd = unsafe { | ||
| libc::syscall(libc::SYS_memfd_create, name_cstr.as_ptr(), MFD_CLOEXEC | MFD_SECRET) |
There was a problem hiding this comment.
MFD_SECRET isn't a valid flag for memfd_create. https://man7.org/linux/man-pages/man2/memfd_create.2.html
- Call the actual
memfd_secretsyscall . (man page reference) - Use
ftruncateto set the size. - Use
mmapto write the data (sincememfd_secretfds don't supportwrite()).
There was a problem hiding this comment.
Yeah I think I wrote MFD_SECRET in my doc. It should be MFD_NOEXEC_SEAL instead. We should add it to prevent this memory from ever being executable.
There was a problem hiding this comment.
Regarding using ftruncate, while it is a valid method. A memory write() should have similar effects. As the man-page mentions:
The initial size of the file is set to 0. Following the call, the
file size should be set using ftruncate(2). (Alternatively, the
file may be populated by calls to write(2) or similar.)
So I think the file.write_all(data)?; below should be good enough to set the file size.
Regarding write() not being supported, I am not sure why that will be. Unless we add F_SEAL_WRITE we should be able to write to the fd location similar to memfd backed files.
|
|
||
| // From <linux/memfd.h> | ||
| const MFD_CLOEXEC: u32 = 0x0001; | ||
| const MFD_SECRET: u32 = 0x0008; |
There was a problem hiding this comment.
in linux/memfd.h 0x0008 points to MFD_NOEXEC_SEAL
LMK if i'm missing something
NilanjanDaw
left a comment
There was a problem hiding this comment.
Thanks for working on this, added some initial comments.
| } | ||
|
|
||
| pub struct KeyManager { | ||
| pub binding_keys: KeyRegistry, |
There was a problem hiding this comment.
As discussed today, we need to separate these out into individual Key Management Agents, one for the Workload daemon, and the other for the Key Protection Service.
| let meta = KeyMetadata { | ||
| id: key_id, | ||
| created_at: Instant::now(), | ||
| delete_after: Some(Instant::now() + Duration::from_secs(3600)), |
There was a problem hiding this comment.
The binding key lifespan is a parameter passed down from the orchestration layer.
| pub fn generate_binding_keypair(&self) -> (KeyHandle, Vec<u8>) { | ||
| clear_stack_on_return(2, || { | ||
| let key_id = Uuid::new_v4(); | ||
| let (pub_key, mut priv_key) = hpke::Kem::X25519HkdfSha256.generate_keypair(); |
There was a problem hiding this comment.
Even though for initial phases, we will exclusively support X25519, we need to make these configurable. The KemAlgorithm will be passed as parameter indicating the DHKEM algorithm to use for the request.
| algo: HpkeAlgorithm { | ||
| kem: KemAlgorithm::DhKemX25519HkdfSha256, | ||
| kdf: KdfAlgorithm::HkdfSha256, | ||
| aead: AeadAlgorithm::Aes256Gcm, | ||
| }, |
There was a problem hiding this comment.
Again the exact algorithm chain should be passed from the orchestration layer and not hardcoded here.
| Binding { algo: HpkeAlgorithm, binding_public_key: Vec<u8> }, | ||
| Sek { algo: SigningAlgorithm, verifying_key: Vec<u8> }, | ||
| } | ||
|
|
There was a problem hiding this comment.
I would prefer defining the Algorithms below as a common protobuf definition and not in rust. And then use Prost to have a Rust binding for those protos. That would allow us to have a common definition between both the orchestration and the custody core components.
| #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
| #[repr(u32)] | ||
| pub enum KemAlgorithm { | ||
| DhKemX25519HkdfSha256 = 1, |
There was a problem hiding this comment.
For each of these, we should have a default unknown definition, like KEM_ALGORITHM_UNSPECIFIED to prevent accidental values from being set.
| let name_cstr = CString::new(name) | ||
| .map_err(|_| IoError::new(std::io::ErrorKind::InvalidInput, "Invalid name"))?; | ||
| let fd = unsafe { | ||
| libc::syscall(libc::SYS_memfd_create, name_cstr.as_ptr(), MFD_CLOEXEC | MFD_SECRET) |
There was a problem hiding this comment.
Yeah I think I wrote MFD_SECRET in my doc. It should be MFD_NOEXEC_SEAL instead. We should add it to prevent this memory from ever being executable.
|
|
||
| pub fn generate_kem_keypair(&self, binding_pub_key: &[u8]) -> (KeyHandle, Vec<u8>) { | ||
| clear_stack_on_return(2, || { | ||
| let key_id = Uuid::new_v4(); |
There was a problem hiding this comment.
The KEM keys and the Binding keys will share the same UUID. When creating the binding keys, a new UUID will be generated and returned back to the orchestration layer. This same UUID will be passed back to the generate_kem_keypair FFI. So when the KEM keys are generated, these keys are mapped to the same UUID and not a new one. This way we can look up the correct KEM key <-> Binding Key pair during the "decap and seal" and subsequent "open" operation.
| @@ -0,0 +1,14 @@ | |||
|
|
|||
| use thiserror::Error; | |||
|
|
|||
There was a problem hiding this comment.
I think we should move this to a protobuf file, to ensure a single definition across the orchestration and custody core layers.
|
|
||
| let reaper_handle = Some(thread::spawn(move || { | ||
| while !stop_clone.load(Ordering::Relaxed) { | ||
| thread::sleep(Duration::from_secs(10)); |
There was a problem hiding this comment.
Let's make this configurable?
No description provided.