crypto: Implement ConstTimeEq
Implement ConstTimeEq using TEE_MemCompare.
Test: make ta + unit test
Change-Id: I88521607186aff294d3023578d95f33f36164f0e
diff --git a/src/crypto.rs b/src/crypto.rs
index ef7b691..c3fe217 100644
--- a/src/crypto.rs
+++ b/src/crypto.rs
@@ -19,6 +19,7 @@
use kmr_common::vec_try;
pub mod clock;
+pub mod eq;
pub mod sha;
#[cfg(feature = "dev")]
diff --git a/src/crypto/eq.rs b/src/crypto/eq.rs
new file mode 100644
index 0000000..3a43ae1
--- /dev/null
+++ b/src/crypto/eq.rs
@@ -0,0 +1,41 @@
+//
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use core::ffi::c_void;
+use kmr_common::crypto;
+use optee_utee_sys;
+
+pub struct Eq;
+
+impl crypto::ConstTimeEq for Eq {
+ fn eq(&self, left: &[u8], right: &[u8]) -> bool {
+ if left.len() != right.len() {
+ return false;
+ }
+
+ // OP-TEE implementation of TEE_MemCompare uses consttime_memcmp,
+ // which is constant-time.
+ // SAFETY: both buffers are valid and equal length.
+ let res = unsafe {
+ optee_utee_sys::TEE_MemCompare(
+ left.as_ptr() as *const c_void,
+ right.as_ptr() as *const c_void,
+ left.len() as usize,
+ )
+ };
+
+ res == 0
+ }
+}
diff --git a/src/crypto/tests.rs b/src/crypto/tests.rs
index 49ac694..86a2cb0 100644
--- a/src/crypto/tests.rs
+++ b/src/crypto/tests.rs
@@ -14,7 +14,7 @@
// limitations under the License.
use hex;
-use kmr_common::crypto::{MonotonicClock, Sha256};
+use kmr_common::crypto::{ConstTimeEq, MonotonicClock, Sha256};
use log::info;
/// Test basic hardware-backed key derivation functionality.
@@ -38,6 +38,31 @@
info!("test_clock: Success");
}
+/// Test basic [`ConstTimeEq`] functionality. Does not test the key constant-time property though.
+pub fn test_eq<E: ConstTimeEq>(comparator: E) {
+ let b0 = [];
+ let b1 = [0u8, 1u8, 2u8];
+ let b2 = [1u8, 1u8, 2u8];
+ let b3 = [0u8, 1u8, 3u8];
+ let b4 = [0u8, 1u8, 2u8, 3u8];
+ let b5 = [42; 4096];
+ let mut b6 = [42; 4096];
+ b6[4095] = 43;
+ assert!(comparator.eq(&b0, &b0));
+ assert!(comparator.eq(&b5, &b5));
+ assert!(comparator.ne(&b0, &b1));
+ assert!(comparator.ne(&b0, &b2));
+ assert!(comparator.ne(&b0, &b3));
+ assert!(comparator.ne(&b0, &b4));
+ assert!(comparator.ne(&b0, &b5));
+ assert!(comparator.eq(&b1, &b1));
+ assert!(comparator.ne(&b1, &b2));
+ assert!(comparator.ne(&b1, &b3));
+ assert!(comparator.ne(&b5, &b4));
+ assert!(comparator.ne(&b5, &b6));
+ info!("test_eq: Success");
+}
+
/// Test basic SHA-256 functionality.
pub fn test_sha256<S: Sha256>(sha256: S) {
struct TestCase {
@@ -68,6 +93,8 @@
test_clock(crate::crypto::clock::Clock);
+ test_eq(crate::crypto::eq::Eq);
+
test_sha256(crate::crypto::sha::Sha256 {});
info!("crypto::tests::run: Done");
diff --git a/src/main.rs b/src/main.rs
index c7f4aeb..2f0619d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -72,7 +72,7 @@
kmr_common::crypto::Implementation {
rng: Box::new(kmr_common::crypto::NoOpRng),
clock: Some(Box::new(crypto::clock::Clock)),
- compare: Box::new(kmr_common::crypto::InsecureEq),
+ compare: Box::new(crypto::eq::Eq),
aes: Box::new(kmr_common::crypto::NoOpAes),
des: Box::new(kmr_common::crypto::NoOpDes),
hmac: Box::new(kmr_common::crypto::NoOpHmac),