examples-features/ctap: Add support for locate_credentials

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
diff --git a/examples-features/ctap.rs b/examples-features/ctap.rs
index f0eb32c..bc1329d 100644
--- a/examples-features/ctap.rs
+++ b/examples-features/ctap.rs
@@ -234,6 +234,32 @@
         seed_buffer.read_bytes(&mut temp_buffer[..]);
         temp_buffer
     }
+
+    /// Generates a Credential from a CredentialId and checks that the Id is valid
+    fn checked_generate_hmac_cred(
+        &mut self,
+        rp_id: &str,
+        credential_id: &[u8],
+    ) -> Option<HmacKeyCredential> {
+        if credential_id.len() != 40 {
+            return None;
+        }
+
+        let received_mac = &credential_id[..32];
+
+        let seed_buffer = self.generate_key_seed(rp_id, &credential_id[32..40].try_into().unwrap());
+
+        let credential =
+            HmacKeyCredential::new(&seed_buffer, credential_id[32..].try_into().unwrap());
+
+        let generated_mac = &credential.0[..32];
+
+        if generated_mac == received_mac {
+            Some(credential)
+        } else {
+            None
+        }
+    }
 }
 
 impl AuthenticatorPlatform for CtapPlatform {
@@ -265,15 +291,27 @@
 
     fn locate_credentials(
         &mut self,
-        _rp_id: &str,
+        rp_id: &str,
         list: Option<CredentialDescriptorList>,
     ) -> (u16, Self::CredentialIterator) {
         match list {
             None => (0, HmacCredentialQueue::new()),
-            Some(_list) => {
-                let result = HmacCredentialQueue::new();
+            Some(list) => {
+                let mut result = HmacCredentialQueue::new();
 
-                // TODO Add location
+                for descriptor in list {
+                    match self.checked_generate_hmac_cred(rp_id, descriptor.get_id()) {
+                        None => (),
+                        Some(credential) => {
+                            match result.push(credential, 0) {
+                                Ok(()) => (),
+                                // NOTE: We just truncate if we don't have enough space to store all
+                                // fitting credentials
+                                Err(()) => break,
+                            }
+                        }
+                    }
+                }
 
                 (result.len() as u16, result)
             }