1use crate::{
4 binary_format::{self, device::PRD_SCALAR_SIZE},
5 certificate::CertificateChain,
6 crypto::ecc_p256::{FromBytes, Keypair, ToUntaggedBytes, SCALAR_SIZE},
7};
8use binrw::{BinRead, BinWrite};
9use p256::ecdsa::SigningKey;
10use p256::elliptic_curve::PrimeField;
11use rand::{thread_rng, Rng};
12use std::{
13 fs::File,
14 io::{Cursor, Read},
15 path::Path,
16};
17
18#[derive(Debug, Clone)]
20pub struct Device {
21 group_key: Option<SigningKey>,
22 encryption_key: Keypair,
23 signing_key: SigningKey,
24 cert_chain: CertificateChain,
25}
26
27impl Device {
28 pub fn new(
30 group_key: Option<SigningKey>,
31 encryption_key: Keypair,
32 signing_key: SigningKey,
33 cert_chain: CertificateChain,
34 ) -> Self {
35 Self {
36 group_key,
37 encryption_key,
38 signing_key,
39 cert_chain,
40 }
41 }
42
43 pub fn from_bytes(bytes: &[u8]) -> Result<Self, crate::Error> {
45 let device = binary_format::device::Device::read(&mut Cursor::new(bytes))?;
46
47 let group_key = match &device.inner {
48 binary_format::device::DeviceInner::V2(_) => None,
49 binary_format::device::DeviceInner::V3(v3) => Some(&v3.group_key),
50 };
51
52 let group_key = match group_key {
53 Some(group_key) => Some(SigningKey::from_slice(&group_key[..SCALAR_SIZE])?),
54 None => None,
55 };
56
57 let encryption_key = match &device.inner {
58 binary_format::device::DeviceInner::V2(v2) => &v2.encryption_key,
59 binary_format::device::DeviceInner::V3(v3) => &v3.encryption_key,
60 };
61
62 let signing_key = match &device.inner {
63 binary_format::device::DeviceInner::V2(v2) => &v2.signing_key,
64 binary_format::device::DeviceInner::V3(v3) => &v3.signing_key,
65 };
66
67 let encryption_key = Keypair::from_bytes(&encryption_key[..SCALAR_SIZE])?;
68 let signing_key = SigningKey::from_slice(&signing_key[..SCALAR_SIZE])?;
69
70 let group_certificate = match device.inner {
71 binary_format::device::DeviceInner::V2(v2) => v2.group_certificate,
72 binary_format::device::DeviceInner::V3(v3) => v3.group_certificate,
73 };
74
75 let cert_chain = CertificateChain::from_vec(group_certificate)?;
76
77 Ok(Self {
78 group_key,
79 encryption_key,
80 signing_key,
81 cert_chain,
82 })
83 }
84
85 pub fn from_prd(path: impl AsRef<Path>) -> Result<Self, crate::Error> {
91 let mut file = File::open(path)?;
92 let mut bytes = Vec::<u8>::new();
93 file.read_to_end(&mut bytes)?;
94
95 Self::from_bytes(&bytes)
96 }
97
98 pub fn signing_key(&self) -> &SigningKey {
100 &self.signing_key
101 }
102
103 pub fn encryption_key(&self) -> &Keypair {
105 &self.encryption_key
106 }
107
108 pub fn group_certificate(&self) -> &[u8] {
110 self.cert_chain.raw()
111 }
112
113 pub fn group_key(&self) -> Option<&SigningKey> {
115 self.group_key.as_ref()
116 }
117
118 pub fn name(&self) -> Result<String, crate::Error> {
120 self.cert_chain.name()
121 }
122
123 pub fn security_level(&self) -> Result<u32, crate::Error> {
125 self.cert_chain.security_level()
126 }
127
128 pub fn verify(&self) -> Result<(), crate::Error> {
130 let public_signing_key = self
131 .signing_key
132 .verifying_key()
133 .as_affine()
134 .to_untagged_bytes();
135
136 let public_encryption_key = self
137 .encryption_key
138 .public()
139 .as_element()
140 .to_untagged_bytes();
141
142 if *public_signing_key != *self.cert_chain.public_signing_key()? {
143 return Err(crate::Error::PublicKeyMismatchError("signing key"));
144 }
145
146 if *public_encryption_key != *self.cert_chain.public_encryption_key()? {
147 return Err(crate::Error::PublicKeyMismatchError("encryption key"));
148 }
149
150 if let Some(group_key) = self.group_key() {
151 let group_key = group_key.verifying_key().as_affine().to_untagged_bytes();
152
153 if *group_key != *self.cert_chain.public_group_key()? {
154 return Err(crate::Error::PublicKeyMismatchError("group key"));
155 }
156 }
157
158 self.cert_chain.verify_signatures()
159 }
160
161 pub fn provision(
163 cert_chain: CertificateChain,
164 group_key: SigningKey,
165 ) -> Result<Self, crate::Error> {
166 let mut rng = thread_rng();
167
168 let client_id = rng.gen::<[u8; 16]>();
169 let cert_id = rng.gen::<[u8; 16]>();
170
171 let encryption_key = Keypair::generate(&mut rng);
172 let signing_key = SigningKey::random(&mut rng);
173
174 let public_encryption_key = encryption_key
175 .public()
176 .as_element()
177 .to_untagged_bytes()
178 .to_vec();
179
180 let public_signing_key = signing_key
181 .verifying_key()
182 .as_affine()
183 .to_untagged_bytes()
184 .to_vec();
185
186 let cert_chain = cert_chain.provision(
187 cert_id,
188 client_id,
189 public_signing_key,
190 public_encryption_key,
191 &group_key,
192 )?;
193
194 cert_chain.verify_signatures()?;
195
196 Ok(Self {
197 group_key: Some(group_key),
198 encryption_key,
199 signing_key,
200 cert_chain,
201 })
202 }
203
204 pub fn reprovision(self) -> Result<Self, crate::Error> {
206 let Device {
207 cert_chain,
208 group_key,
209 ..
210 } = self;
211
212 let group_key = group_key.ok_or(crate::Error::GroupKeyMissingError)?;
213
214 Self::provision(cert_chain, group_key)
215 }
216
217 pub fn provision_from_files(
220 group_cert_path: impl AsRef<Path>,
221 group_key_path: impl AsRef<Path>,
222 ) -> Result<Self, crate::Error> {
223 let mut file = File::open(group_cert_path)?;
224 let mut bytes = Vec::<u8>::new();
225 file.read_to_end(&mut bytes)?;
226
227 let cert_chain = CertificateChain::from_bytes(&bytes)?;
228
229 file = File::open(group_key_path)?;
230 bytes.clear();
231 file.read_to_end(&mut bytes)?;
232
233 let group_key = SigningKey::from_slice(bytes.get(..SCALAR_SIZE).ok_or(
234 crate::Error::SliceOutOfBoundsError("group_key", bytes.len()),
235 )?)?;
236
237 Self::provision(cert_chain, group_key)
238 }
239
240 pub fn write_to_file(&self, path: impl AsRef<Path>) -> Result<(), crate::Error> {
242 let mut group_key = [0u8; PRD_SCALAR_SIZE];
243 let mut encryption_key = [0u8; PRD_SCALAR_SIZE];
244 let mut signing_key = [0u8; PRD_SCALAR_SIZE];
245
246 group_key[..SCALAR_SIZE].copy_from_slice(
247 &self
248 .group_key
249 .as_ref()
250 .ok_or(crate::Error::GroupKeyMissingError)?
251 .to_bytes(),
252 );
253
254 encryption_key[..SCALAR_SIZE]
255 .copy_from_slice(&self.encryption_key.secret().expose_scalar().to_repr());
256 signing_key[..SCALAR_SIZE].copy_from_slice(&self.signing_key.to_bytes());
257
258 let group_certificate = self.group_certificate().to_vec();
259 let group_certificate_length = u32::try_from(group_certificate.len()).unwrap();
260
261 let device = binary_format::device::Device {
262 version: 3,
263 inner: binary_format::device::DeviceInner::V3(binary_format::device::DeviceV3 {
264 group_key,
265 encryption_key,
266 signing_key,
267 group_certificate_length,
268 group_certificate,
269 }),
270 };
271
272 let mut file = File::create(path)?;
273 device.write(&mut file)?;
274
275 Ok(())
276 }
277}
278
279impl TryFrom<&[u8]> for Device {
280 type Error = crate::Error;
281
282 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
283 Self::from_bytes(value)
284 }
285}