1use crate::{
20 cbor::value::Value,
21 common::AsCborValue,
22 iana,
23 util::{cbor_type_error, ValueTryAs},
24 Algorithm, CoseError, ProtectedHeader, Result,
25};
26use alloc::{vec, vec::Vec};
27use core::convert::TryInto;
28
29#[cfg(test)]
30mod tests;
31
32#[derive(Clone, Debug, Eq, PartialEq)]
34pub enum Nonce {
35 Bytes(Vec<u8>),
36 Integer(i64),
37}
38
39#[derive(Clone, Debug, Default, Eq, PartialEq)]
49pub struct PartyInfo {
50 pub identity: Option<Vec<u8>>,
51 pub nonce: Option<Nonce>,
52 pub other: Option<Vec<u8>>,
53}
54
55impl crate::CborSerializable for PartyInfo {}
56
57impl AsCborValue for PartyInfo {
58 fn from_cbor_value(value: Value) -> Result<Self> {
59 let mut a = value.try_as_array()?;
60 if a.len() != 3 {
61 return Err(CoseError::UnexpectedItem("array", "array with 3 items"));
62 }
63
64 Ok(Self {
66 other: match a.remove(2) {
67 Value::Null => None,
68 Value::Bytes(b) => Some(b),
69 v => return cbor_type_error(&v, "bstr / nil"),
70 },
71 nonce: match a.remove(1) {
72 Value::Null => None,
73 Value::Bytes(b) => Some(Nonce::Bytes(b)),
74 Value::Integer(u) => Some(Nonce::Integer(u.try_into()?)),
75 v => return cbor_type_error(&v, "bstr / int / nil"),
76 },
77 identity: match a.remove(0) {
78 Value::Null => None,
79 Value::Bytes(b) => Some(b),
80 v => return cbor_type_error(&v, "bstr / nil"),
81 },
82 })
83 }
84
85 fn to_cbor_value(self) -> Result<Value> {
86 Ok(Value::Array(vec![
87 match self.identity {
88 None => Value::Null,
89 Some(b) => Value::Bytes(b),
90 },
91 match self.nonce {
92 None => Value::Null,
93 Some(Nonce::Bytes(b)) => Value::Bytes(b),
94 Some(Nonce::Integer(i)) => Value::from(i),
95 },
96 match self.other {
97 None => Value::Null,
98 Some(b) => Value::Bytes(b),
99 },
100 ]))
101 }
102}
103
104#[derive(Debug, Default)]
106pub struct PartyInfoBuilder(PartyInfo);
107
108impl PartyInfoBuilder {
109 builder! {PartyInfo}
110 builder_set_optional! {identity: Vec<u8>}
111 builder_set_optional! {nonce: Nonce}
112 builder_set_optional! {other: Vec<u8>}
113}
114
115#[derive(Clone, Debug, Default, PartialEq)]
125pub struct SuppPubInfo {
126 pub key_data_length: u64,
127 pub protected: ProtectedHeader,
128 pub other: Option<Vec<u8>>,
129}
130
131impl crate::CborSerializable for SuppPubInfo {}
132
133impl AsCborValue for SuppPubInfo {
134 fn from_cbor_value(value: Value) -> Result<Self> {
135 let mut a = value.try_as_array()?;
136 if a.len() != 2 && a.len() != 3 {
137 return Err(CoseError::UnexpectedItem(
138 "array",
139 "array with 2 or 3 items",
140 ));
141 }
142
143 Ok(Self {
145 other: {
146 if a.len() == 3 {
147 Some(a.remove(2).try_as_bytes()?)
148 } else {
149 None
150 }
151 },
152 protected: ProtectedHeader::from_cbor_bstr(a.remove(1))?,
153 key_data_length: a.remove(0).try_as_integer()?.try_into()?,
154 })
155 }
156
157 fn to_cbor_value(self) -> Result<Value> {
158 let mut v = vec![
159 Value::from(self.key_data_length),
160 self.protected.cbor_bstr()?,
161 ];
162 if let Some(other) = self.other {
163 v.push(Value::Bytes(other));
164 }
165 Ok(Value::Array(v))
166 }
167}
168
169#[derive(Debug, Default)]
171pub struct SuppPubInfoBuilder(SuppPubInfo);
172
173impl SuppPubInfoBuilder {
174 builder! {SuppPubInfo}
175 builder_set! {key_data_length: u64}
176 builder_set_protected! {protected}
177 builder_set_optional! {other: Vec<u8>}
178}
179
180#[derive(Clone, Debug, Default, PartialEq)]
195pub struct CoseKdfContext {
196 algorithm_id: Algorithm,
197 party_u_info: PartyInfo,
198 party_v_info: PartyInfo,
199 supp_pub_info: SuppPubInfo,
200 supp_priv_info: Vec<Vec<u8>>,
201}
202
203impl crate::CborSerializable for CoseKdfContext {}
204
205impl AsCborValue for CoseKdfContext {
206 fn from_cbor_value(value: Value) -> Result<Self> {
207 let mut a = value.try_as_array()?;
208 if a.len() < 4 {
209 return Err(CoseError::UnexpectedItem(
210 "array",
211 "array with at least 4 items",
212 ));
213 }
214
215 let mut supp_priv_info = Vec::with_capacity(a.len() - 4);
217 for i in (4..a.len()).rev() {
218 supp_priv_info.push(a.remove(i).try_as_bytes()?);
219 }
220 supp_priv_info.reverse();
221
222 Ok(Self {
223 supp_priv_info,
224 supp_pub_info: SuppPubInfo::from_cbor_value(a.remove(3))?,
225 party_v_info: PartyInfo::from_cbor_value(a.remove(2))?,
226 party_u_info: PartyInfo::from_cbor_value(a.remove(1))?,
227 algorithm_id: Algorithm::from_cbor_value(a.remove(0))?,
228 })
229 }
230
231 fn to_cbor_value(self) -> Result<Value> {
232 let mut v = vec![
233 self.algorithm_id.to_cbor_value()?,
234 self.party_u_info.to_cbor_value()?,
235 self.party_v_info.to_cbor_value()?,
236 self.supp_pub_info.to_cbor_value()?,
237 ];
238 for supp_priv_info in self.supp_priv_info {
239 v.push(Value::Bytes(supp_priv_info));
240 }
241 Ok(Value::Array(v))
242 }
243}
244
245#[derive(Debug, Default)]
247pub struct CoseKdfContextBuilder(CoseKdfContext);
248
249impl CoseKdfContextBuilder {
250 builder! {CoseKdfContext}
251 builder_set! {party_u_info: PartyInfo}
252 builder_set! {party_v_info: PartyInfo}
253 builder_set! {supp_pub_info: SuppPubInfo}
254
255 #[must_use]
257 pub fn algorithm(mut self, alg: iana::Algorithm) -> Self {
258 self.0.algorithm_id = Algorithm::Assigned(alg);
259 self
260 }
261
262 #[must_use]
264 pub fn add_supp_priv_info(mut self, supp_priv_info: Vec<u8>) -> Self {
265 self.0.supp_priv_info.push(supp_priv_info);
266 self
267 }
268}