Background
In google/go-tpm-tools#990, two related issues were identified and addressed in the Key Custody Core / keymanager components:
-
Slice index out of bounds in CGO bindings
In both key_protection_service/key_custody_core/kps_key_custody_core_cgo.go (GenerateKEMKeypair) and workload_service/key_custody_core/ws_key_custody_core_cgo.go (GenerateBindingKeypair), proto.Marshal(algo) can produce an empty byte slice if an empty HpkeAlgorithm struct is passed.
Attempting to pass (*C.uint8_t)(unsafe.Pointer(&algoBytes[0])) panics with a runtime slice bounds out of range error when len(algoBytes) == 0.
Proposed Fix: Check for empty slice prior to the CGO call:
if len(algoBytes) == 0 {
return uuid.Nil, nil, fmt.Errorf("no algorithm provided")
}
-
Simplify SecretBox::new in km_common/src/crypto/secret_box.rs
Currently, SecretBox::new branches on data.capacity() > data.len():
pub fn new(mut data: Vec<u8>) -> Self {
let boxed: Box<[u8]> = if data.capacity() > data.len() {
let b = Box::from(data.as_slice());
data.zeroize();
b
} else {
data.into_boxed_slice()
};
Self(secrecy::SecretBox::new(boxed))
}
As noted during code review on PR #990, branching on capacity() > len() introduces unnecessary branch duplication. Unconditional copy-then-zeroize is correct and consistent for both cases, avoiding any edge cases with reallocation or freed memory:
pub fn new(mut data: Vec<u8>) -> Self {
let boxed: Box<[u8]> = data.as_slice().into();
data.zeroize();
Self(secrecy::SecretBox::new(boxed))
}
Affected Files
key_protection_service/key_custody_core/kps_key_custody_core_cgo.go
workload_service/key_custody_core/ws_key_custody_core_cgo.go
km_common/src/crypto/secret_box.rs
Background
In google/go-tpm-tools#990, two related issues were identified and addressed in the Key Custody Core / keymanager components:
Slice index out of bounds in CGO bindings
In both
key_protection_service/key_custody_core/kps_key_custody_core_cgo.go(GenerateKEMKeypair) andworkload_service/key_custody_core/ws_key_custody_core_cgo.go(GenerateBindingKeypair),proto.Marshal(algo)can produce an empty byte slice if an emptyHpkeAlgorithmstruct is passed.Attempting to pass
(*C.uint8_t)(unsafe.Pointer(&algoBytes[0]))panics with a runtime slice bounds out of range error whenlen(algoBytes) == 0.Proposed Fix: Check for empty slice prior to the CGO call:
Simplify
SecretBox::newinkm_common/src/crypto/secret_box.rsCurrently,
SecretBox::newbranches ondata.capacity() > data.len():As noted during code review on PR #990, branching on
capacity() > len()introduces unnecessary branch duplication. Unconditional copy-then-zeroize is correct and consistent for both cases, avoiding any edge cases with reallocation or freed memory:Affected Files
key_protection_service/key_custody_core/kps_key_custody_core_cgo.goworkload_service/key_custody_core/ws_key_custody_core_cgo.gokm_common/src/crypto/secret_box.rs