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

Code before:
}

// We serialize credentials for the persistent storage using CBOR maps. Each field of a credential
// is associated with a unique tag, implemented with a CBOR unsigned key.
enum PublicKeyCredentialSourceField {
    CredentialId = 0,
    PrivateKey = 1,
    RpId = 2,
    UserHandle = 3,
    OtherUi = 4,
    CredRandom = 5,
    // When a field is removed, its tag should be reserved and not used for new fields. We document
    // those reserved tags below.
    // Reserved tags: none.
}

impl From<PublicKeyCredentialSourceField> for cbor::KeyType {
    fn from(field: PublicKeyCredentialSourceField) -> cbor::KeyType {
        (field as u64).into()
    }
}

impl From<PublicKeyCredentialSource> for cbor::Value {
    fn from(credential: PublicKeyCredentialSource) -> cbor::Value {
        use PublicKeyCredentialSourceField::*;
        let mut private_key = [0; 32];
        credential.private_key.to_bytes(&mut private_key);
        cbor_map_options! {
            CredentialId => Some(credential.credential_id),
            PrivateKey => Some(private_key.to_vec()),
            RpId => Some(credential.rp_id),
            UserHandle => Some(credential.user_handle),
            OtherUi => credential.other_ui,
            CredRandom => credential.cred_random
        }
    }
}

impl TryFrom<&cbor::Value> for PublicKeyCredentialSource {
    type Error = Ctap2StatusCode;

    fn try_from(cbor_value: &cbor::Value) -> Result<Self, Ctap2StatusCode> {
        use PublicKeyCredentialSourceField::*;
        let map = read_map(cbor_value)?;
        let credential_id = read_byte_string(ok_or_missing(map.get(&CredentialId.into()))?)?;
        let private_key = read_byte_string(ok_or_missing(map.get(&PrivateKey.into()))?)?;
        if private_key.len() != 32 {
            return Err(Ctap2StatusCode::CTAP2_ERR_INVALID_CBOR);
        }
        let private_key = ecdsa::SecKey::from_bytes(array_ref!(private_key, 0, 32))
            .ok_or(Ctap2StatusCode::CTAP2_ERR_INVALID_CBOR)?;

Review comment (suggestion):
I find the previous expression `0u8` more readable, as it makes it clear that we have 32 **bytes** and not potentially some other integer type.

Code after:
}

// We serialize credentials for the persistent storage using CBOR maps. Each field of a credential
// is associated with a unique tag, implemented with a CBOR unsigned key.
enum PublicKeyCredentialSourceField {
    CredentialId = 0,
    PrivateKey = 1,
    RpId = 2,
    UserHandle = 3,
    OtherUi = 4,
    CredRandom = 5,
    // When a field is removed, its tag should be reserved and not used for new fields. We document
    // those reserved tags below.
    // Reserved tags: none.
}

impl From<PublicKeyCredentialSourceField> for cbor::KeyType {
    fn from(field: PublicKeyCredentialSourceField) -> cbor::KeyType {
        (field as u64).into()
    }
}

impl From<PublicKeyCredentialSource> for cbor::Value {
    fn from(credential: PublicKeyCredentialSource) -> cbor::Value {
        use PublicKeyCredentialSourceField::*;
        let mut private_key = [0u8; 32];
        credential.private_key.to_bytes(&mut private_key);
        cbor_map_options! {
            CredentialId => Some(credential.credential_id),
            PrivateKey => Some(private_key.to_vec()),
            RpId => Some(credential.rp_id),
            UserHandle => Some(credential.user_handle),
            OtherUi => credential.other_ui,
            CredRandom => credential.cred_random
        }
    }
}

impl TryFrom<cbor::Value> for PublicKeyCredentialSource {
    type Error = Ctap2StatusCode;

    fn try_from(cbor_value: cbor::Value) -> Result<Self, Ctap2StatusCode> {
        use PublicKeyCredentialSourceField::*;
        let mut map = extract_map(cbor_value)?;
        let credential_id = extract_byte_string(ok_or_missing(map.remove(&CredentialId.into()))?)?;
        let private_key = extract_byte_string(ok_or_missing(map.remove(&PrivateKey.into()))?)?;
        if private_key.len() != 32 {
            return Err(Ctap2StatusCode::CTAP2_ERR_INVALID_CBOR);
        }
        let private_key = ecdsa::SecKey::from_bytes(array_ref!(private_key, 0, 32))
            .ok_or(Ctap2StatusCode::CTAP2_ERR_INVALID_CBOR)?;