libaacs | branch: master | npzacs <[email protected]> | Thu Aug 16 14:55:44 2018 
+0300| [9571186cd51a38f14aa1c54482a7c394d03f37d2] | committer: npzacs

content_cert: parse AACS2 content certificate

> http://git.videolan.org/gitweb.cgi/libaacs.git/?a=commit;h=9571186cd51a38f14aa1c54482a7c394d03f37d2
---

 src/libaacs/content_cert.c | 47 +++++++++++++++++++++++++++++++++++++++-------
 src/libaacs/content_cert.h |  9 ++++++++-
 2 files changed, 48 insertions(+), 8 deletions(-)

diff --git a/src/libaacs/content_cert.c b/src/libaacs/content_cert.c
index 0f901f8..aec303f 100644
--- a/src/libaacs/content_cert.c
+++ b/src/libaacs/content_cert.c
@@ -32,15 +32,36 @@
 #include <stdint.h>
 #include <string.h>
 
+/*
+ * AACS2 format specific data:
+ *
+ * XXX this needs to be verified from other sources / discs.
+ *
+ * offset 26: 34 0-bytes, unknown
+ * offset 60: BD-J root certificate hash, SHA256 (32 bytes)
+ * offset 92: 34 0-bytes
+ * offset 126: num CPS units (uint16)
+ * offset 128: .cci file hashes, SHA256 (32 bytes * num_cps_unit)
+ */
+
 CONTENT_CERT *cc_parse(const void *data, size_t len)
 {
     const uint8_t *p = data;
+    size_t signature_size;
 
-    if (len < 87) {
-        BD_DEBUG(DBG_AACS | DBG_CRIT, "Invalid content certificate (length %zd 
< 87)\n", len);
+    if (len < 26) {
+        BD_DEBUG(DBG_AACS | DBG_CRIT, "Invalid content certificate (length %zu 
< 26)\n", len);
         return NULL;
     }
-    if (p[0] != 0) {
+
+    switch (p[0]) {
+    case 0x00: /* AACS 1 */
+        signature_size = 40;
+        break;
+    case 0x10: /* AACS 2 */
+        signature_size = 64;
+        break;
+    default:
         BD_DEBUG(DBG_AACS | DBG_CRIT, "Invalid content certificate type 
0x%02x\n", p[0]);
         return NULL;
     }
@@ -52,9 +73,9 @@ CONTENT_CERT *cc_parse(const void *data, size_t len)
 
     size_t cert_data_len = 26 + length_format_specific + num_digest*8;
 
-    if (len < cert_data_len + 40) {
-        BD_DEBUG(DBG_AACS | DBG_CRIT, "Invalid content certificate (length %zd 
< %zd)\n",
-                 len, cert_data_len + 40);
+    if (len < cert_data_len + signature_size) {
+        BD_DEBUG(DBG_AACS | DBG_CRIT, "Invalid content certificate (length %zu 
< %zu)\n",
+                 len, cert_data_len + signature_size);
         return NULL;
     }
 
@@ -71,7 +92,19 @@ CONTENT_CERT *cc_parse(const void *data, size_t len)
     if (c) {
         c->bus_encryption_enabled_flag = p[1] >> 7;
         memcpy(c->cc_id,              p + 14, 6);
-        memcpy(c->bdj_root_cert_hash, p + 46, 20);
+
+        /* aacs1 and aacs2 format specific data is different. */
+        if (p[0] == 0) {
+            if (length_format_specific >= 40) {
+                memcpy(c->bdj_root_cert_hash, p + 46, 20);
+            }
+        } else {
+            c->aacs2 = 1;
+            // XXX this needs to be verified from other sources / discs.
+            if (length_format_specific >= 66) {
+                memcpy(c->bdj_root_cert_hash, p + 60, 32);
+            }
+        }
     }
     return c;
 }
diff --git a/src/libaacs/content_cert.h b/src/libaacs/content_cert.h
index 2a8949c..03cc0e4 100644
--- a/src/libaacs/content_cert.h
+++ b/src/libaacs/content_cert.h
@@ -31,7 +31,14 @@ struct content_cert {
     uint8_t bus_encryption_enabled_flag;
 
     uint8_t cc_id[6];
-    uint8_t bdj_root_cert_hash[20];
+
+    /*
+     * BD-J root certificte hash
+     * aacs1: SHA1   (20 bytes)
+     * aacs2: SHA256 (32 bytes)
+     */
+    uint8_t aacs2; /* 0 - aacs1, 1 - aacs2 */
+    uint8_t bdj_root_cert_hash[32];
 };
 
 

_______________________________________________
libaacs-devel mailing list
[email protected]
https://mailman.videolan.org/listinfo/libaacs-devel

Reply via email to