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