openpgp_card/ocard/data/
kdf_do.rs

1// SPDX-FileCopyrightText: 2024 Heiko Schaefer <heiko@schaefer.name>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4use std::convert::TryFrom;
5
6use crate::ocard::data::KdfDo;
7use crate::ocard::tags::Tags;
8use crate::ocard::tlv::tag::Tag;
9use crate::ocard::tlv::value::Value;
10use crate::ocard::tlv::Tlv;
11use crate::Error;
12
13impl TryFrom<&[u8]> for KdfDo {
14    type Error = Error;
15    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
16        let tlv = Tlv::new(Tags::KdfDo, Value::from(value, true)?);
17
18        if let Some(Value::S(data)) = tlv.find(Tag::from([0x81])) {
19            let kdf_algo: u8 = if data.len() == 1 {
20                data[0]
21            } else {
22                return Err(Error::ParseError(
23                    "couldn't parse kdf algorithm field in KDF DO".to_string(),
24                ));
25            };
26
27            let hash_algo: Option<u8> = tlv.find(Tag::from([0x82])).and_then(|v| match v {
28                Value::S(data) => {
29                    if data.len() == 1 {
30                        Some(data[0])
31                    } else {
32                        None
33                    }
34                }
35                _ => None,
36            });
37
38            let iter_count: Option<u32> = tlv.find(Tag::from([0x83])).and_then(|v| match v {
39                Value::S(data) => match &data[..] {
40                    [a, b, c, d] => Some(u32::from_be_bytes([*a, *b, *c, *d])),
41                    _ => None,
42                },
43                _ => None,
44            });
45
46            let salt_pw1: Option<Vec<u8>> = tlv.find(Tag::from([0x84])).and_then(|v| match v {
47                Value::S(data) => Some(data.to_vec()),
48                _ => None,
49            });
50
51            let salt_rc: Option<Vec<u8>> = tlv.find(Tag::from([0x85])).and_then(|v| match v {
52                Value::S(data) => Some(data.to_vec()),
53                _ => None,
54            });
55
56            let salt_pw3: Option<Vec<u8>> = tlv.find(Tag::from([0x86])).and_then(|v| match v {
57                Value::S(data) => Some(data.to_vec()),
58                _ => None,
59            });
60
61            let initial_hash_pw1: Option<Vec<u8>> =
62                tlv.find(Tag::from([0x87])).and_then(|v| match v {
63                    Value::S(data) => Some(data.to_vec()),
64                    _ => None,
65                });
66
67            let initial_hash_pw3: Option<Vec<u8>> =
68                tlv.find(Tag::from([0x88])).and_then(|v| match v {
69                    Value::S(data) => Some(data.to_vec()),
70                    _ => None,
71                });
72
73            Ok(Self {
74                kdf_algo,
75                hash_algo,
76                iter_count,
77                salt_pw1,
78                salt_rc,
79                salt_pw3,
80                initial_hash_pw1,
81                initial_hash_pw3,
82            })
83        } else {
84            Err(Error::ParseError("couldn't parse KDF DO".to_string()))
85        }
86    }
87}
88
89impl KdfDo {
90    pub fn kdf_algo(&self) -> u8 {
91        self.kdf_algo
92    }
93
94    pub fn hash_algo(&self) -> Option<u8> {
95        self.hash_algo
96    }
97
98    pub fn iter_count(&self) -> Option<u32> {
99        self.iter_count
100    }
101
102    pub fn salt_pw1(&self) -> Option<&[u8]> {
103        self.salt_pw1.as_deref()
104    }
105
106    pub fn salt_rc(&self) -> Option<&[u8]> {
107        self.salt_rc.as_deref()
108    }
109
110    pub fn salt_pw3(&self) -> Option<&[u8]> {
111        self.salt_pw3.as_deref()
112    }
113
114    pub fn initial_hash_pw1(&self) -> Option<&[u8]> {
115        self.initial_hash_pw1.as_deref()
116    }
117
118    pub fn initial_hash_pw3(&self) -> Option<&[u8]> {
119        self.initial_hash_pw3.as_deref()
120    }
121}