1use crate::{
4 binary_format::{
5 bcert::{
6 Attribute, BCertChainHeader, DrmBCertDeviceInfo, DrmBCertFeatureInfo,
7 DrmBCertKeyInfoInner, PreprocessWrite,
8 },
9 StructTag, ValueAndRaw,
10 },
11 crypto::{
12 ecc_p256::{FromBytes, ToUntaggedBytes, SIGNATURE_SIZE},
13 sha256,
14 },
15};
16use binrw::{BinRead, BinWrite};
17use p256::ecdsa::{SigningKey, VerifyingKey};
18use std::io::Cursor;
19
20use crate::{
21 binary_format::bcert::{
22 AttributeInner, BCert, BCertChain, DrmBCertBasicInfo, DrmBCertKeyInfo,
23 DrmBCertManufacturerInfo, DrmBCertSignatureInfo,
24 },
25 crypto::ecc_p256,
26};
27
28const ROOT_ISSUER_KEY: [u8; 64] = [
29 0x86, 0x4d, 0x61, 0xcf, 0xf2, 0x25, 0x6e, 0x42, 0x2c, 0x56, 0x8b, 0x3c, 0x28, 0x00, 0x1c, 0xfb,
30 0x3e, 0x15, 0x27, 0x65, 0x85, 0x84, 0xba, 0x05, 0x21, 0xb7, 0x9b, 0x18, 0x28, 0xd9, 0x36, 0xde,
31 0x1d, 0x82, 0x6a, 0x8f, 0xc3, 0xe6, 0xe7, 0xfa, 0x7a, 0x90, 0xd5, 0xca, 0x29, 0x46, 0xf1, 0xf6,
32 0x4a, 0x2e, 0xfb, 0x9f, 0x5d, 0xcf, 0xfe, 0x7e, 0x43, 0x4e, 0xb4, 0x42, 0x93, 0xfa, 0xc5, 0xab,
33];
34
35#[derive(Debug, Clone)]
36struct Certificate {
37 parsed: BCert,
38 raw: Vec<u8>,
39}
40
41impl Certificate {
42 fn new(bcert: BCert, raw: Vec<u8>) -> Self {
43 Self { parsed: bcert, raw }
44 }
45
46 fn into_bcert_and_raw(self) -> (BCert, Vec<u8>) {
47 (self.parsed, self.raw)
48 }
49
50 fn from_bytes(bytes: &[u8]) -> Result<Self, binrw::Error> {
51 Self::from_vec(bytes.to_vec())
52 }
53
54 fn from_vec(vec: Vec<u8>) -> Result<Self, binrw::Error> {
55 let parsed = BCert::read(&mut Cursor::new(&vec))?;
56
57 Ok(Self { parsed, raw: vec })
58 }
59
60 fn find_attribute(&self, tag: u16) -> Option<&Attribute> {
61 self.parsed.attributes.iter().find(|a| a.tag == tag)
62 }
63
64 fn find_key_by_usage(&self, usage: u32) -> Option<&[u8]> {
65 let attribute = self.find_attribute(DrmBCertKeyInfo::TAG)?;
66
67 let cert_info = match &attribute.inner {
68 AttributeInner::DrmBCertKeyInfo(inner) => Some(inner),
69 _ => None,
70 }?;
71
72 cert_info
73 .cert_keys
74 .iter()
75 .find(|c| c.usages.contains(&usage))
76 .map(|c| c.key.as_slice())
77 }
78
79 fn public_signing_key(&self) -> Option<&[u8]> {
80 self.find_key_by_usage(1)
81 }
82
83 fn public_encryption_key(&self) -> Option<&[u8]> {
84 self.find_key_by_usage(2)
85 }
86
87 fn issuer_key(&self) -> Option<&[u8]> {
88 self.find_key_by_usage(6)
89 }
90
91 fn public_group_key(&self) -> Option<&[u8]> {
92 let attribute = self.find_attribute(DrmBCertSignatureInfo::TAG)?;
93
94 match &attribute.inner {
95 AttributeInner::DrmBCertSignatureInfo(inner) => Some(&inner.signature_key),
96 _ => None,
97 }
98 }
99
100 fn verify_signature(&self, public_key: &[u8]) -> Result<(), crate::Error> {
101 let attribute = self.find_attribute(DrmBCertSignatureInfo::TAG).ok_or(
102 crate::Error::BinaryObjectNotFoundError("DrmBCertSignatureInfo"),
103 )?;
104
105 let sig_info = match &attribute.inner {
106 AttributeInner::DrmBCertSignatureInfo(inner) => Some(inner),
107 _ => None,
108 }
109 .ok_or(crate::Error::BinaryObjectNotFoundError(
110 "DrmBCertSignatureInfo",
111 ))?;
112
113 if public_key != sig_info.signature_key {
114 return Err(crate::Error::PublicKeyMismatchError("BCert"));
115 }
116
117 let msg_end = self.raw.len() - usize::try_from(attribute.length)?;
118
119 ecc_p256::verify(
120 &VerifyingKey::from_bytes(&sig_info.signature_key)?,
121 self.raw
122 .get(..msg_end)
123 .ok_or(crate::Error::SliceOutOfBoundsError(
124 "cert.raw",
125 self.raw.len(),
126 ))?,
127 &sig_info.signature,
128 )
129 .map_err(|e| e.into())
130 }
131
132 fn new_leaf(
133 cert_id: [u8; 16],
134 client_id: [u8; 16],
135 security_level: u32,
136 manufacturer_info: Attribute,
137 public_signing_key: Vec<u8>,
138 public_encryption_key: Vec<u8>,
139 group_key: &SigningKey,
140 ) -> Result<Self, crate::Error> {
141 let public_group_key = group_key
142 .verifying_key()
143 .as_affine()
144 .to_untagged_bytes()
145 .to_vec();
146
147 let attributes = vec![
148 Attribute {
149 flags: 1,
150 inner: AttributeInner::DrmBCertBasicInfo(DrmBCertBasicInfo {
151 cert_id,
152 security_level,
153 cert_type: 2,
154 public_key_digest: sha256::hash(&public_signing_key).try_into().unwrap(),
155 expiration_date: u32::MAX,
156 client_id,
157 ..Default::default()
158 }),
159 ..Default::default()
160 },
161 Attribute {
162 flags: 1,
163 inner: AttributeInner::DrmBCertDeviceInfo(DrmBCertDeviceInfo {
164 max_license: 10240,
165 max_header: 15360,
166 max_chain_depth: 2,
167 }),
168 ..Default::default()
169 },
170 Attribute {
171 flags: 1,
172 inner: AttributeInner::DrmBCertFeatureInfo(DrmBCertFeatureInfo {
173 features: vec![4, 9, 13],
174 ..Default::default()
175 }),
176 ..Default::default()
177 },
178 Attribute {
179 flags: 1,
180 inner: AttributeInner::DrmBCertKeyInfo(DrmBCertKeyInfo {
181 cert_keys: vec![
182 DrmBCertKeyInfoInner {
183 type_: 1,
184 key: public_signing_key,
185 usages: vec![1],
186 ..Default::default()
187 },
188 DrmBCertKeyInfoInner {
189 type_: 1,
190 key: public_encryption_key,
191 usages: vec![2],
192 ..Default::default()
193 },
194 ],
195 ..Default::default()
196 }),
197 ..Default::default()
198 },
199 manufacturer_info,
200 Attribute {
201 flags: 1,
202 inner: AttributeInner::DrmBCertSignatureInfo(DrmBCertSignatureInfo {
203 signature_type: 1,
204 signature: vec![0u8; SIGNATURE_SIZE],
205 signature_key: public_group_key,
206 ..Default::default()
207 }),
208 ..Default::default()
209 },
210 ];
211
212 let mut cert = BCert {
213 version: 1,
214 attributes,
215 ..Default::default()
216 };
217
218 let mut raw = Vec::<u8>::new();
219 cert.preprocess_write();
220 cert.write(&mut Cursor::new(&mut raw))?;
221
222 let signature = ecc_p256::sign(
223 group_key,
224 raw.get(0..usize::try_from(cert.certificate_length)?)
225 .ok_or(crate::Error::SliceOutOfBoundsError("cert.raw", raw.len()))?,
226 );
227
228 assert!(signature.len() == SIGNATURE_SIZE);
229
230 if let AttributeInner::DrmBCertSignatureInfo(inner) =
231 &mut cert.attributes.last_mut().unwrap().inner
232 {
233 inner.signature.copy_from_slice(&signature)
234 }
235
236 raw.clear();
237 cert.write(&mut Cursor::new(&mut raw))?;
238
239 Ok(Self { parsed: cert, raw })
240 }
241}
242
243impl TryFrom<&[u8]> for Certificate {
244 type Error = binrw::Error;
245
246 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
247 Self::from_bytes(value)
248 }
249}
250
251impl TryFrom<Vec<u8>> for Certificate {
252 type Error = binrw::Error;
253
254 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
255 Self::from_vec(value)
256 }
257}
258
259impl From<ValueAndRaw<BCert>> for Certificate {
260 fn from(value: ValueAndRaw<BCert>) -> Self {
261 let (val, raw) = value.into_value_and_raw();
262 Self::new(val, raw)
263 }
264}
265
266impl From<Certificate> for ValueAndRaw<BCert> {
267 fn from(value: Certificate) -> Self {
268 Self::from(value.into_bcert_and_raw())
269 }
270}
271
272#[derive(Debug, Clone)]
274pub struct CertificateChain {
275 header: BCertChainHeader,
276 certificates: Vec<Certificate>,
277 raw: Vec<u8>,
278}
279
280impl CertificateChain {
281 pub fn from_bytes(bytes: &[u8]) -> Result<Self, binrw::Error> {
283 Self::from_vec(bytes.to_vec())
284 }
285
286 pub fn from_vec(vec: Vec<u8>) -> Result<Self, binrw::Error> {
288 let parsed = BCertChain::read(&mut Cursor::new(&vec))?;
289
290 let header = parsed.header;
291 let certificates = parsed
292 .certificates
293 .into_iter()
294 .map(Certificate::from)
295 .collect();
296
297 Ok(Self {
298 header,
299 certificates,
300 raw: vec,
301 })
302 }
303
304 pub fn raw(&self) -> &[u8] {
306 &self.raw
307 }
308
309 pub fn security_level(&self) -> Result<u32, crate::Error> {
311 let first_cert = self
312 .certificates
313 .first()
314 .ok_or(crate::Error::CertificateMissingError)?;
315
316 let attribute = first_cert
317 .find_attribute(DrmBCertBasicInfo::TAG)
318 .ok_or(crate::Error::BinaryObjectNotFoundError("DrmBCertBasicInfo"))?;
319
320 match &attribute.inner {
321 AttributeInner::DrmBCertBasicInfo(inner) => Ok(inner.security_level),
322 _ => Err(crate::Error::BinaryObjectNotFoundError("DrmBCertBasicInfo")),
323 }
324 }
325
326 pub fn public_signing_key(&self) -> Result<&[u8], crate::Error> {
328 self.certificates
329 .first()
330 .ok_or(crate::Error::CertificateMissingError)?
331 .public_signing_key()
332 .ok_or(crate::Error::BinaryObjectNotFoundError(
333 "DrmBCertKeyInfo.signing_key",
334 ))
335 }
336
337 pub fn public_encryption_key(&self) -> Result<&[u8], crate::Error> {
339 self.certificates
340 .first()
341 .ok_or(crate::Error::CertificateMissingError)?
342 .public_encryption_key()
343 .ok_or(crate::Error::BinaryObjectNotFoundError(
344 "DrmBCertKeyInfo.encryption_key",
345 ))
346 }
347
348 pub fn public_group_key(&self) -> Result<&[u8], crate::Error> {
350 self.certificates
351 .first()
352 .ok_or(crate::Error::CertificateMissingError)?
353 .public_group_key()
354 .ok_or(crate::Error::BinaryObjectNotFoundError(
355 "DrmBCertSignatureInfo.public_group_key",
356 ))
357 }
358
359 pub fn name(&self) -> Result<String, crate::Error> {
361 fn from_null_terminated_string(s: Vec<u8>) -> String {
362 let s = s.into_iter().take_while(|c| *c != b'\x00').collect();
363 String::from_utf8(s)
364 .inspect_err(|e| log::error!("Failed to create utf8 string: {e:?}"))
365 .unwrap_or_default()
366 }
367
368 let first_cert = self
369 .certificates
370 .first()
371 .ok_or(crate::Error::CertificateMissingError)?;
372
373 let attribute = first_cert
374 .find_attribute(DrmBCertManufacturerInfo::TAG)
375 .ok_or(crate::Error::BinaryObjectNotFoundError(
376 "DrmBCertManufacturerInfo",
377 ))?;
378
379 match &attribute.inner {
380 AttributeInner::DrmBCertManufacturerInfo(inner) => {
381 let manufacturer = from_null_terminated_string(inner.manufacturer_name.clone());
382 let model_name = from_null_terminated_string(inner.model_name.clone());
383 let model_number = from_null_terminated_string(inner.model_number.clone());
384
385 Ok(format!("{manufacturer} {model_name} {model_number}"))
386 }
387 _ => Err(crate::Error::BinaryObjectNotFoundError(
388 "DrmBCertManufacturerInfo",
389 )),
390 }
391 }
392
393 pub fn verify_signatures(&self) -> Result<(), crate::Error> {
395 if self.certificates.is_empty() {
396 return Err(crate::Error::CertificateMissingError);
397 }
398
399 let mut issuer_key = ROOT_ISSUER_KEY;
400
401 for i in (0..self.certificates.len()).rev() {
402 let cert = &self.certificates[i];
403 cert.verify_signature(&issuer_key)?;
404
405 match cert.issuer_key() {
406 Some(key) => issuer_key.copy_from_slice(key),
407 None => {
408 if i != 0 {
409 return Err(crate::Error::CertificateVerificationError(i));
410 }
411 }
412 }
413 }
414
415 Ok(())
416 }
417
418 pub fn provision(
420 mut self,
421 cert_id: [u8; 16],
422 client_id: [u8; 16],
423 public_signing_key: Vec<u8>,
424 public_encryption_key: Vec<u8>,
425 group_key: &SigningKey,
426 ) -> Result<Self, crate::Error> {
427 let public_group_key = group_key.verifying_key().as_affine().to_untagged_bytes();
428
429 self.certificates = self
430 .certificates
431 .into_iter()
432 .skip_while(|c| {
433 c.issuer_key()
434 .map(|c| *c != *public_group_key)
435 .unwrap_or(true)
436 })
437 .collect();
438
439 if self.certificates.is_empty() {
440 return Err(crate::Error::PublicKeyMismatchError("group key"));
441 }
442
443 let first_cert = self
444 .certificates
445 .first()
446 .ok_or(crate::Error::CertificateMissingError)?;
447
448 let manufacturer_info = first_cert
449 .find_attribute(DrmBCertManufacturerInfo::TAG)
450 .ok_or(crate::Error::BinaryObjectNotFoundError(
451 "DrmBCertManufacturerInfo",
452 ))
453 .cloned()?;
454
455 let security_level = self.security_level()?;
456
457 let new_leaf = Certificate::new_leaf(
458 cert_id,
459 client_id,
460 security_level,
461 manufacturer_info,
462 public_signing_key,
463 public_encryption_key,
464 group_key,
465 )?;
466
467 self.certificates.insert(0, new_leaf);
468
469 let mut bcertchain = BCertChain {
470 header: self.header,
471 certificates: self
472 .certificates
473 .into_iter()
474 .map(ValueAndRaw::<BCert>::from)
475 .collect(),
476 };
477
478 bcertchain
479 .certificates
480 .iter_mut()
481 .for_each(|c| c.use_raw = true);
482
483 self.raw.clear();
484 let mut raw = self.raw;
485 bcertchain.preprocess_write();
486 bcertchain.write(&mut Cursor::new(&mut raw))?;
487
488 let header = bcertchain.header;
489 let certificates = bcertchain
490 .certificates
491 .into_iter()
492 .map(Certificate::from)
493 .collect();
494
495 Ok(Self {
496 header,
497 certificates,
498 raw,
499 })
500 }
501}
502
503impl TryFrom<&[u8]> for CertificateChain {
504 type Error = binrw::Error;
505
506 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
507 Self::from_bytes(value)
508 }
509}
510
511impl TryFrom<Vec<u8>> for CertificateChain {
512 type Error = binrw::Error;
513
514 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
515 Self::from_vec(value)
516 }
517}