examples-features/ctap: Add support for creating credentials
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
diff --git a/examples-features/ctap.rs b/examples-features/ctap.rs
index 9715af9..176c5c5 100644
--- a/examples-features/ctap.rs
+++ b/examples-features/ctap.rs
@@ -5,6 +5,7 @@
use core::alloc::Layout;
use core::cell::Cell;
+use core::convert::TryInto;
use core::fmt::{self, Debug, Error, Formatter};
use core::time::Duration;
use ctap2_authenticator::credentials::{RpCredential, UserCredential};
@@ -17,12 +18,12 @@
};
use generic_array::GenericArray;
use libtock::ctap::{CtapRecvBuffer, CtapSendBuffer};
-use libtock::hmac::HmacDriverFactory;
+use libtock::hmac::{HmacDataBuffer, HmacDestBuffer, HmacDriverFactory, HmacKeyBuffer};
use libtock::println;
use libtock::result::TockResult;
use libtock::syscalls;
use p256::elliptic_curve::ff::PrimeField;
-use p256::Scalar;
+use p256::{Scalar, SecretKey};
use subtle::{Choice, ConditionallySelectable};
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
@@ -194,6 +195,46 @@
}
}
+impl CtapPlatform {
+ fn generate_key_seed(
+ &mut self,
+ rp_id: &str,
+ nonce: &[u8; 8],
+ ) -> [u8; libtock::hmac::DEST_BUFFER_SIZE] {
+ let hmac_driver = self.hmac.init_driver().unwrap();
+
+ let mut key_buffer = HmacKeyBuffer::default();
+ for (i, d) in rp_id.as_bytes().iter().enumerate() {
+ key_buffer[i] = *d;
+ }
+ let _key_buffer = hmac_driver.init_key_buffer(&mut key_buffer).unwrap();
+
+ let mut data_buffer = HmacDataBuffer::default();
+ for (i, d) in nonce.iter().enumerate() {
+ data_buffer[i] = *d;
+ }
+ let _data_buffer = hmac_driver.init_data_buffer(&mut data_buffer).unwrap();
+
+ let mut seed_buffer = HmacDestBuffer::default();
+ let seed_buffer = hmac_driver.init_dest_buffer(&mut seed_buffer).unwrap();
+
+ let mut callback = |_result, _digest| {};
+
+ let _subscription = hmac_driver.subscribe(&mut callback).unwrap();
+
+ hmac_driver.run().unwrap();
+
+ // Yield waiting for the HMAC callback
+ unsafe {
+ syscalls::raw::yieldk();
+ }
+
+ let mut temp_buffer = [0; libtock::hmac::DEST_BUFFER_SIZE];
+ seed_buffer.read_bytes(&mut temp_buffer[..]);
+ temp_buffer
+ }
+}
+
impl AuthenticatorPlatform for CtapPlatform {
const AAGUID: [u8; 16] = [
0xf8, 0xa0, 0x11, 0xf3, 0x8c, 0x0a, 0x4d, 0x15, 0x80, 0x06, 0x17, 0x11, 0x1f, 0x9e, 0xdc,
@@ -240,10 +281,32 @@
fn create_credential(
&mut self,
- _rp: RpCredential<&[u8], &str>,
+ rp: RpCredential<&[u8], &str>,
_user: UserCredential<&[u8], &str>,
) -> (Self::CredentialId, PublicKey<Self::PublicKeyBuffer>, u32) {
- unimplemented!()
+ println!("create_credential");
+ let rp_id = core::str::from_utf8(rp.rp_id()).unwrap();
+ // This nonce is static!!!!
+ // This is really bad cryptowise, let's print a warning
+ // TODO: Convert this to generate a nonce from Tock's TRNG
+ println!("WARNING!!! The nonce is static, this key is insecure");
+ println!("WARNING!!! Do not use this anywhere important");
+ let nonce = [0; 8];
+
+ let seed_buffer = self.generate_key_seed(rp_id, &nonce);
+
+ let credential = HmacKeyCredential::new(&seed_buffer, nonce.try_into().unwrap());
+
+ let secret_key = SecretKey::from_bytes(&seed_buffer[0..32]).unwrap();
+
+ let pub_key = p256::EncodedPoint::from_secret_key(&secret_key, false);
+
+ let x: [u8; 32] = pub_key.as_bytes()[1..33].try_into().unwrap();
+ let y: [u8; 32] = pub_key.as_bytes()[33..].try_into().unwrap();
+
+ let ret_key = PublicKey::nistp256(x, y);
+
+ (credential, ret_key, 0)
}
fn attest(