Repository: google/OpenSK
File: src/ctap/storage.rs (Rust)

Code before:

    fn init(&mut self, rng: &mut impl Rng256) {
        if self.store.find_one(&Key::MasterKeys).is_none() {
            let master_encryption_key = rng.gen_uniform_u8x32();
            let master_hmac_key = rng.gen_uniform_u8x32();
            let mut master_keys = Vec::with_capacity(64);
            master_keys.extend_from_slice(&master_encryption_key);
            master_keys.extend_from_slice(&master_hmac_key);
            self.store
                .insert(StoreEntry {
                    tag: MASTER_KEYS,
                    data: &master_keys,
                    sensitive: true,
                })
                .unwrap();
        }
        if self.store.find_one(&Key::PinRetries).is_none() {
            self.store
                .insert(StoreEntry {
                    tag: PIN_RETRIES,
                    data: &[MAX_PIN_RETRIES],
                    sensitive: false,
                })
                .unwrap();
        }
        if self.store.find_one(&Key::AttestationPrivateKey).is_none() {
            self.store
                .insert(StoreEntry {
                    tag: ATTESTATION_PRIVATE_KEY,
                    data: key_material::ATTESTATION_PRIVATE_KEY,
                    sensitive: false,
                })
                .unwrap();
        }
        if self.store.find_one(&Key::AttestationCertificate).is_none() {
            self.store
                .insert(StoreEntry {
                    tag: ATTESTATION_CERTIFICATE,
                    data: key_material::ATTESTATION_CERTIFICATE,
                    sensitive: false,
                })
                .unwrap();
        }
        if self.store.find_one(&Key::Aaguid).is_none() {
            self.store
                .insert(StoreEntry {
                    tag: AAGUID,
                    data: key_material::AAGUID,
                    sensitive: false,
                })
                .unwrap();

Review comment (performance):
I introduced `USE_BATCH_ATTESTATION` for users to have a choice. Batch attestation can be a privacy concern, and some relying parties might not require it. If we want to replace the boolean flag `USE_BATCH_ATTESTATION` with "exists in the persistent store", we could add that here. This is more of an open question which is cleaner.

Code after:
        }
        if self.store.find_one(&Key::PinRetries).is_none() {
            self.store
                .insert(StoreEntry {
                    tag: PIN_RETRIES,
                    data: &[MAX_PIN_RETRIES],
                    sensitive: false,
                })
                .unwrap();
        }
        // The following 3 entries are meant to be written by vendor-specific commands.
        if USE_BATCH_ATTESTATION {
            if self.store.find_one(&Key::AttestationPrivateKey).is_none() {
                self.set_attestation_private_key(key_material::ATTESTATION_PRIVATE_KEY)
                    .unwrap();
            }
            if self.store.find_one(&Key::AttestationCertificate).is_none() {
                self.set_attestation_certificate(key_material::ATTESTATION_CERTIFICATE)
                    .unwrap();
            }
        }
        if self.store.find_one(&Key::Aaguid).is_none() {
            self.set_aaguid(key_material::AAGUID).unwrap();
        }
    }

    pub fn find_credential(
        &self,
        rp_id: &str,
        credential_id: &[u8],
        check_cred_protect: bool,
    ) -> Option<PublicKeyCredentialSource> {
        let key = Key::Credential {
            rp_id: Some(rp_id.into()),
            credential_id: Some(credential_id.into()),
            user_handle: None,
        };
        let (_, entry) = self.store.find_one(&key)?;
        debug_assert_eq!(entry.tag, TAG_CREDENTIAL);
        let result = deserialize_credential(entry.data);
        debug_assert!(result.is_some());
        if check_cred_protect
            && result.as_ref().map_or(false, |cred| {
                cred.cred_protect_policy
                    == Some(CredentialProtectionPolicy::UserVerificationRequired)
            })
        {
            None
        } else {
            result
        }