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