ykoath_protocol/
select.rs1use crate::{Algorithm, Error, YubiKey};
2
3#[derive(Clone, Copy, Debug)]
4pub struct Response<'a> {
5 pub version: &'a [u8],
6 pub name: &'a [u8],
7 pub inner: Option<Inner<'a>>,
8}
9
10#[derive(Clone, Copy, Debug)]
11pub struct Inner<'a> {
12 pub challenge: &'a [u8],
13 pub algorithm: Algorithm,
14}
15
16impl YubiKey {
17 #[tracing::instrument(err, ret, skip(buf))]
18 pub fn select<'a>(&self, buf: &'a mut Vec<u8>) -> Result<Response<'a>, Error> {
19 #[allow(clippy::redundant_locals)]
21 let buf = buf;
22 buf.clear();
23 buf.extend_from_slice(&[0x00, 0xa4, 0x04, 0x00]);
24 buf.push(0x00);
25 buf.extend_from_slice(&[0xa0, 0x00, 0x00, 0x05, 0x27, 0x21, 0x01]);
26 let mut response = self.transmit(buf)?;
27 let (_, version) = Self::pop(&mut response, &[0x79])?;
28 let (_, name) = Self::pop(&mut response, &[0x71])?;
29 let inner = if response.is_empty() {
30 None
31 } else {
32 let (_, challenge) = Self::pop(&mut response, &[0x74])?;
33 let (_, algorithm) = Self::pop(&mut response, &[0x7b])?;
34 let algorithm = match algorithm {
35 [v] => Algorithm::try_from(*v)?,
36 _ => Err(Error::UnexpectedValue(algorithm.len().try_into()?))?,
37 };
38 Some(Inner {
39 challenge,
40 algorithm,
41 })
42 };
43 let response = Response {
44 version,
45 name,
46 inner,
47 };
48 Ok(response)
49 }
50}