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

Code before:
            };
            let min_pin_length_output = if min_pin_length {
                Some(storage::min_pin_length(env)? as u64)
            } else {
                None
            };
            let cred_protect_output = extensions.cred_protect.and(cred_protect_policy);
            let extensions_output = cbor_map_options! {
                "credBlob" => cred_blob_output,
                "credProtect" => cred_protect_output,
                "hmac-secret" => hmac_secret_output,
                "minPinLength" => min_pin_length_output,
            };
            cbor_write(extensions_output, &mut auth_data)?;
        }

        let mut signature_data = auth_data.clone();
        signature_data.extend(client_data_hash);

        let attestation_id = if env.customization().use_batch_attestation() {
            Some(attestation_store::Id::Batch)
        } else if ep_att {
            Some(attestation_store::Id::Enterprise)
        } else {
            None
        };
        let (signature, x5c) = match attestation_id {
            Some(id) => {
                let Attestation {
                    private_key,
                    certificate,
                } = env
                    .attestation_store()
                    .get(&id)?
                    .ok_or(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR)?;
                let attestation_key = crypto::ecdsa::SecKey::from_bytes(&private_key).unwrap();
                (
                    attestation_key
                        .sign_rfc6979::<Sha256>(&signature_data)
                        .to_asn1_der(),
                    Some(vec![certificate]),
                )
            }
            None => (private_key.sign_and_encode(env, &signature_data)?, None),
        };
        let attestation_statement = PackedAttestationStatement {
            alg: SignatureAlgorithm::ES256 as i64,
            sig: signature,
            x5c,
            ecdaa_key_id: None,
        };

Review comment (bug):
Just noticed that the order is wrong. Enterprise attestation has priority. For all other occasions, it depends on the security key's customization.

Code after:
            } else {
                None
            };
            let min_pin_length_output = if min_pin_length {
                Some(storage::min_pin_length(env)? as u64)
            } else {
                None
            };
            let cred_protect_output = extensions.cred_protect.and(cred_protect_policy);
            let extensions_output = cbor_map_options! {
                "credBlob" => cred_blob_output,
                "credProtect" => cred_protect_output,
                "hmac-secret" => hmac_secret_output,
                "minPinLength" => min_pin_length_output,
            };
            cbor_write(extensions_output, &mut auth_data)?;
        }

        let mut signature_data = auth_data.clone();
        signature_data.extend(client_data_hash);

        let attestation_id = if ep_att {
            Some(attestation_store::Id::Enterprise)
        } else if env.customization().use_batch_attestation() {
            Some(attestation_store::Id::Batch)
        } else {
            None
        };
        let (signature, x5c) = match attestation_id {
            Some(id) => {
                let Attestation {
                    private_key,
                    certificate,
                } = env
                    .attestation_store()
                    .get(&id)?
                    .ok_or(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR)?;
                let attestation_key = crypto::ecdsa::SecKey::from_bytes(&private_key).unwrap();
                (
                    attestation_key
                        .sign_rfc6979::<Sha256>(&signature_data)
                        .to_asn1_der(),
                    Some(vec![certificate]),
                )
            }
            None => (private_key.sign_and_encode(env, &signature_data)?, None),
        };
        let attestation_statement = PackedAttestationStatement {
            alg: SignatureAlgorithm::ES256 as i64,
            sig: signature,
            x5c,