1use crate::{
4 binary_format::{
5 bcert::{
6 Attribute, BCertChainHeader, DrmBCertDeviceInfo, DrmBCertFeatureInfo,
7 DrmBCertKeyInfoInner, PreprocessWrite,
8 },
9 StructTag,
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}
39
40impl Certificate {
41 fn new(bcert: BCert) -> Self {
42 Self { parsed: bcert }
43 }
44
45 fn from_bytes(bytes: &[u8]) -> Result<Self, binrw::Error> {
46 Self::from_vec(bytes.to_vec())
47 }
48
49 fn from_vec(vec: Vec<u8>) -> Result<Self, binrw::Error> {
50 let parsed = BCert::read(&mut Cursor::new(&vec))?;
51
52 Ok(Self { parsed })
53 }
54
55 fn find_attribute(&self, tag: u16) -> Option<&Attribute> {
56 self.parsed.attributes.iter().find(|a| a.tag == tag)
57 }
58
59 fn find_key_by_usage(&self, usage: u32) -> Option<&[u8]> {
60 let attribute = self.find_attribute(DrmBCertKeyInfo::TAG)?;
61
62 let cert_info = match &attribute.inner {
63 AttributeInner::DrmBCertKeyInfo(inner) => Some(inner),
64 _ => 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(1)
76 }
77
78 fn public_encryption_key(&self) -> Option<&[u8]> {
79 self.find_key_by_usage(2)
80 }
81
82 fn issuer_key(&self) -> Option<&[u8]> {
83 self.find_key_by_usage(6)
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
100 let sig_info = match &attribute.inner {
101 AttributeInner::DrmBCertSignatureInfo(inner) => Some(inner),
102 _ => None,
103 }
104 .ok_or(crate::Error::BinaryObjectNotFoundError(
105 "DrmBCertSignatureInfo",
106 ))?;
107
108 if public_key != sig_info.signature_key {
109 return Err(crate::Error::PublicKeyMismatchError("BCert"));
110 }
111
112 ecc_p256::verify(
113 &VerifyingKey::from_bytes(&sig_info.signature_key)?,
114 cert_bytes,
115 &sig_info.signature,
116 )
117 .map_err(|e| e.into())
118 }
119
120 fn new_leaf(
121 cert_id: [u8; 16],
122 client_id: [u8; 16],
123 security_level: u32,
124 manufacturer_info: Attribute,
125 public_signing_key: Vec<u8>,
126 public_encryption_key: Vec<u8>,
127 group_key: &SigningKey,
128 ) -> Result<Self, crate::Error> {
129 let public_group_key = group_key
130 .verifying_key()
131 .as_affine()
132 .to_untagged_bytes()
133 .to_vec();
134
135 let attributes = vec![
136 Attribute {
137 flags: 1,
138 inner: AttributeInner::DrmBCertBasicInfo(DrmBCertBasicInfo {
139 cert_id,
140 security_level,
141 cert_type: 2,
142 public_key_digest: sha256::hash(&public_signing_key).try_into().unwrap(),
143 expiration_date: u32::MAX,
144 client_id,
145 ..Default::default()
146 }),
147 ..Default::default()
148 },
149 Attribute {
150 flags: 1,
151 inner: AttributeInner::DrmBCertDeviceInfo(DrmBCertDeviceInfo {
152 max_license: 10240,
153 max_header: 15360,
154 max_chain_depth: 2,
155 }),
156 ..Default::default()
157 },
158 Attribute {
159 flags: 1,
160 inner: AttributeInner::DrmBCertFeatureInfo(DrmBCertFeatureInfo {
161 features: vec![4, 9, 13],
162 ..Default::default()
163 }),
164 ..Default::default()
165 },
166 Attribute {
167 flags: 1,
168 inner: AttributeInner::DrmBCertKeyInfo(DrmBCertKeyInfo {
169 cert_keys: vec![
170 DrmBCertKeyInfoInner {
171 type_: 1,
172 key: public_signing_key,
173 usages: vec![1],
174 ..Default::default()
175 },
176 DrmBCertKeyInfoInner {
177 type_: 1,
178 key: public_encryption_key,
179 usages: vec![2],
180 ..Default::default()
181 },
182 ],
183 ..Default::default()
184 }),
185 ..Default::default()
186 },
187 manufacturer_info,
188 Attribute {
189 flags: 1,
190 inner: AttributeInner::DrmBCertSignatureInfo(DrmBCertSignatureInfo {
191 signature_type: 1,
192 signature: vec![0u8; SIGNATURE_SIZE],
193 signature_key: public_group_key,
194 ..Default::default()
195 }),
196 ..Default::default()
197 },
198 ];
199
200 let mut cert = BCert {
201 version: 1,
202 attributes,
203 ..Default::default()
204 };
205
206 let mut raw = Vec::<u8>::new();
207 cert.preprocess_write();
208 cert.write(&mut Cursor::new(&mut raw))?;
209
210 let signature = ecc_p256::sign(
211 group_key,
212 raw.get(0..usize::try_from(cert.certificate_length)?)
213 .ok_or(crate::Error::SliceOutOfBoundsError("cert.raw", raw.len()))?,
214 );
215
216 assert!(signature.len() == SIGNATURE_SIZE);
217
218 if let AttributeInner::DrmBCertSignatureInfo(inner) =
219 &mut cert.attributes.last_mut().unwrap().inner
220 {
221 inner.signature.copy_from_slice(&signature)
222 }
223
224 raw.clear();
225 cert.write(&mut Cursor::new(&mut raw))?;
226
227 Ok(Self { parsed: cert })
228 }
229}
230
231impl TryFrom<&[u8]> for Certificate {
232 type Error = binrw::Error;
233
234 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
235 Self::from_bytes(value)
236 }
237}
238
239impl TryFrom<Vec<u8>> for Certificate {
240 type Error = binrw::Error;
241
242 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
243 Self::from_vec(value)
244 }
245}
246
247impl From<BCert> for Certificate {
248 fn from(value: BCert) -> Self {
249 Self::new(value)
250 }
251}
252
253impl From<Certificate> for BCert {
254 fn from(value: Certificate) -> Self {
255 value.parsed
256 }
257}
258
259#[derive(Clone)]
261pub struct CertificateChain {
262 header: BCertChainHeader,
263 certificates: Vec<Certificate>,
264 raw: Vec<u8>,
265}
266
267impl std::fmt::Debug for CertificateChain {
268 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
269 f.debug_struct("CertificateChain")
270 .field("header", &self.header)
271 .field("certificates", &self.certificates)
272 .finish()
273 }
274}
275
276impl CertificateChain {
277 pub fn from_bytes(bytes: &[u8]) -> Result<Self, binrw::Error> {
279 Self::from_vec(bytes.to_vec())
280 }
281
282 pub fn from_vec(vec: Vec<u8>) -> Result<Self, binrw::Error> {
284 let parsed = BCertChain::read(&mut Cursor::new(&vec))?;
285
286 let header = parsed.header;
287 let certificates = parsed
288 .certificates
289 .into_iter()
290 .map(Certificate::from)
291 .collect();
292
293 Ok(Self {
294 header,
295 certificates,
296 raw: vec,
297 })
298 }
299
300 pub fn raw(&self) -> &[u8] {
302 &self.raw
303 }
304
305 pub fn security_level(&self) -> Result<u32, crate::Error> {
307 let first_cert = self
308 .certificates
309 .first()
310 .ok_or(crate::Error::CertificateMissingError)?;
311
312 let attribute = first_cert
313 .find_attribute(DrmBCertBasicInfo::TAG)
314 .ok_or(crate::Error::BinaryObjectNotFoundError("DrmBCertBasicInfo"))?;
315
316 match &attribute.inner {
317 AttributeInner::DrmBCertBasicInfo(inner) => Ok(inner.security_level),
318 _ => Err(crate::Error::BinaryObjectNotFoundError("DrmBCertBasicInfo")),
319 }
320 }
321
322 pub fn public_signing_key(&self) -> Result<&[u8], crate::Error> {
324 self.certificates
325 .first()
326 .ok_or(crate::Error::CertificateMissingError)?
327 .public_signing_key()
328 .ok_or(crate::Error::BinaryObjectNotFoundError(
329 "DrmBCertKeyInfo.signing_key",
330 ))
331 }
332
333 pub fn public_encryption_key(&self) -> Result<&[u8], crate::Error> {
335 self.certificates
336 .first()
337 .ok_or(crate::Error::CertificateMissingError)?
338 .public_encryption_key()
339 .ok_or(crate::Error::BinaryObjectNotFoundError(
340 "DrmBCertKeyInfo.encryption_key",
341 ))
342 }
343
344 pub fn public_group_key(&self) -> Result<&[u8], crate::Error> {
346 self.certificates
347 .first()
348 .ok_or(crate::Error::CertificateMissingError)?
349 .public_group_key()
350 .ok_or(crate::Error::BinaryObjectNotFoundError(
351 "DrmBCertSignatureInfo.public_group_key",
352 ))
353 }
354
355 pub fn name(&self) -> Result<String, crate::Error> {
357 let attribute = self
358 .certificates
359 .iter()
360 .filter_map(|c| c.find_attribute(DrmBCertManufacturerInfo::TAG))
361 .next()
362 .ok_or(crate::Error::BinaryObjectNotFoundError(
363 "DrmBCertManufacturerInfo",
364 ))?;
365
366 match &attribute.inner {
367 AttributeInner::DrmBCertManufacturerInfo(inner) => {
368 let manufacturer = inner.manufacturer_name.to_string();
369 let model_name = inner.model_name.to_string();
370 let model_number = inner.model_number.to_string();
371
372 Ok(format!("{manufacturer} {model_name} {model_number}"))
373 }
374 _ => Err(crate::Error::BinaryObjectNotFoundError(
375 "DrmBCertManufacturerInfo",
376 )),
377 }
378 }
379
380 pub fn verify_signatures(&self) -> Result<(), crate::Error> {
382 if self.certificates.is_empty() {
383 return Err(crate::Error::CertificateMissingError);
384 }
385
386 let mut issuer_key = ROOT_ISSUER_KEY;
387
388 for i in (0..self.certificates.len()).rev() {
389 let cert = &self.certificates[i];
390 cert.verify_signature(&issuer_key, self.cert_bytes(i)?)?;
391
392 match cert.issuer_key() {
393 Some(key) => issuer_key.copy_from_slice(key),
394 None => {
395 if i != 0 {
396 return Err(crate::Error::CertificateVerificationError(i));
397 }
398 }
399 }
400 }
401
402 Ok(())
403 }
404
405 pub fn provision(
407 mut self,
408 cert_id: [u8; 16],
409 client_id: [u8; 16],
410 public_signing_key: Vec<u8>,
411 public_encryption_key: Vec<u8>,
412 group_key: &SigningKey,
413 ) -> Result<Self, crate::Error> {
414 let public_group_key = group_key.verifying_key().as_affine().to_untagged_bytes();
415
416 self.certificates = self
417 .certificates
418 .into_iter()
419 .skip_while(|c| {
420 c.issuer_key()
421 .map(|c| *c != *public_group_key)
422 .unwrap_or(true)
423 })
424 .collect();
425
426 if self.certificates.is_empty() {
427 return Err(crate::Error::PublicKeyMismatchError("group key"));
428 }
429
430 let first_cert = self
431 .certificates
432 .first()
433 .ok_or(crate::Error::CertificateMissingError)?;
434
435 let manufacturer_info = first_cert
436 .find_attribute(DrmBCertManufacturerInfo::TAG)
437 .ok_or(crate::Error::BinaryObjectNotFoundError(
438 "DrmBCertManufacturerInfo",
439 ))
440 .cloned()?;
441
442 let security_level = self.security_level()?;
443
444 let new_leaf = Certificate::new_leaf(
445 cert_id,
446 client_id,
447 security_level,
448 manufacturer_info,
449 public_signing_key,
450 public_encryption_key,
451 group_key,
452 )?;
453
454 self.certificates.insert(0, new_leaf);
455
456 let mut bcertchain = BCertChain {
457 header: self.header,
458 certificates: self.certificates.into_iter().map(BCert::from).collect(),
459 };
460
461 self.raw.clear();
462 let mut raw = self.raw;
463 bcertchain.preprocess_write();
464 bcertchain.write(&mut Cursor::new(&mut raw))?;
465
466 let header = bcertchain.header;
467 let certificates = bcertchain
468 .certificates
469 .into_iter()
470 .map(Certificate::from)
471 .collect();
472
473 Ok(Self {
474 header,
475 certificates,
476 raw,
477 })
478 }
479
480 fn cert_bytes(&self, n: usize) -> Result<&[u8], crate::Error> {
481 let mut offset: usize = 20; let Some(cert) = self.certificates.get(n) else {
484 return Err(crate::Error::CertificateMissingError);
485 };
486
487 for i in 0..n {
488 offset += usize::try_from(self.certificates[i].parsed.total_length)?;
489 }
490
491 let cert_end = offset + usize::try_from(cert.parsed.certificate_length)?;
492
493 self.raw
494 .get(offset..cert_end)
495 .ok_or(crate::Error::SliceOutOfBoundsError("cert.raw", cert_end))
496 }
497}
498
499impl TryFrom<&[u8]> for CertificateChain {
500 type Error = binrw::Error;
501
502 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
503 Self::from_bytes(value)
504 }
505}
506
507impl TryFrom<Vec<u8>> for CertificateChain {
508 type Error = binrw::Error;
509
510 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
511 Self::from_vec(value)
512 }
513}