ctap_types/ctap2/
large_blobs.rs

1use crate::sizes::LARGE_BLOB_MAX_FRAGMENT_LENGTH;
2use crate::Bytes;
3use serde_indexed::{DeserializeIndexed, SerializeIndexed};
4
5// See: https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#largeBlobsRW
6#[derive(Clone, Debug, Eq, PartialEq, SerializeIndexed, DeserializeIndexed)]
7#[non_exhaustive]
8#[serde_indexed(offset = 1)]
9pub struct Request<'a> {
10    // 0x01
11    #[serde(skip_serializing_if = "Option::is_none")]
12    pub get: Option<u32>,
13    // 0x02
14    #[serde(skip_serializing_if = "Option::is_none")]
15    pub set: Option<&'a serde_bytes::Bytes>,
16    // 0x03
17    pub offset: u32,
18    // 0x04
19    #[serde(skip_serializing_if = "Option::is_none")]
20    pub length: Option<u32>,
21    // 0x05
22    #[serde(skip_serializing_if = "Option::is_none")]
23    pub pin_uv_auth_param: Option<&'a serde_bytes::Bytes>,
24    // 0x06
25    #[serde(skip_serializing_if = "Option::is_none")]
26    pub pin_uv_auth_protocol: Option<u32>,
27}
28
29#[derive(Clone, Debug, Default, Eq, PartialEq, SerializeIndexed, DeserializeIndexed)]
30#[non_exhaustive]
31#[serde_indexed(offset = 1)]
32pub struct Response {
33    // 0x01
34    #[serde(skip_serializing_if = "Option::is_none")]
35    pub config: Option<Bytes<LARGE_BLOB_MAX_FRAGMENT_LENGTH>>,
36}
37
38#[cfg(test)]
39mod tests {
40    use super::*;
41    use serde_test::{assert_de_tokens, assert_ser_tokens, Token};
42
43    const FRAGMENT: &[u8] = &[0xaf; 255];
44    const PIN_AUTH: &[u8] = &[0xad; 32];
45
46    #[test]
47    fn test_de_request_get() {
48        let request = Request {
49            get: Some(255),
50            set: None,
51            offset: 0,
52            length: None,
53            pin_uv_auth_param: None,
54            pin_uv_auth_protocol: None,
55        };
56        assert_de_tokens(
57            &request,
58            &[
59                Token::Map { len: Some(2) },
60                // 0x01: get
61                Token::U64(0x01),
62                Token::U32(255),
63                // 0x03: offset
64                Token::U64(0x03),
65                Token::U32(0),
66                Token::MapEnd,
67            ],
68        );
69    }
70
71    #[test]
72    fn test_de_request_set() {
73        let request = Request {
74            get: None,
75            set: Some(serde_bytes::Bytes::new(FRAGMENT)),
76            offset: 0,
77            length: Some(255),
78            pin_uv_auth_param: Some(serde_bytes::Bytes::new(PIN_AUTH)),
79            pin_uv_auth_protocol: Some(1),
80        };
81        assert_de_tokens(
82            &request,
83            &[
84                Token::Map { len: Some(5) },
85                // 0x02: set
86                Token::U64(0x02),
87                Token::BorrowedBytes(FRAGMENT),
88                // 0x03: offset
89                Token::U64(0x03),
90                Token::U32(0),
91                // 0x04: length
92                Token::U64(0x04),
93                Token::U32(255),
94                // 0x05: pinUvAuthParam
95                Token::U64(0x05),
96                Token::BorrowedBytes(PIN_AUTH),
97                // 0x06: pinUvAuthProtocol
98                Token::U64(0x06),
99                Token::U32(1),
100                Token::MapEnd,
101            ],
102        );
103    }
104
105    #[test]
106    fn test_ser_response() {
107        let response = Response {
108            config: Some(Bytes::from_slice(&[]).unwrap()),
109            ..Default::default()
110        };
111        assert_ser_tokens(
112            &response,
113            &[
114                Token::Map { len: Some(1) },
115                // 0x01: config
116                Token::U64(0x01),
117                Token::Some,
118                Token::BorrowedBytes(&[]),
119                Token::MapEnd,
120            ],
121        );
122    }
123}