Petri Hintukainen pushed to branch master at VideoLAN / libaacs


Commits:
33c95654 by John Doe at 2020-06-21T02:26:15+03:00
Fix unit key parsing for AACS 2.x discs (when there are multiple unit keys)

- - - - -


3 changed files:

- src/libaacs/aacs.c
- src/libaacs/unit_key.c
- src/libaacs/unit_key.h


Changes:

=====================================
src/libaacs/aacs.c
=====================================
@@ -982,10 +982,11 @@ static int _calc_title_hash(AACS *aacs)
     size_t   size;
     char     str[48];
     int      result = AACS_SUCCESS;
+    int      aacs2 = aacs->cc ? aacs->cc->aacs2 : 0;
 
     size = _read_file(aacs, "AACS" DIR_SEP "Unit_Key_RO.inf", &data);
     if (size > 2048) {
-        aacs->uk = uk_parse(data, size);
+        aacs->uk = uk_parse(data, size, aacs2);
     }
 
     /* failed, try backup */
@@ -993,7 +994,7 @@ static int _calc_title_hash(AACS *aacs)
         X_FREE(data);
         size = _read_file(aacs, "AACS" DIR_SEP "DUPLICATE" DIR_SEP 
"Unit_Key_RO.inf", &data);
         if (size > 2048) {
-            aacs->uk = uk_parse(data, size);
+            aacs->uk = uk_parse(data, size, aacs2);
         }
     }
 
@@ -1233,6 +1234,8 @@ int aacs_open_device(AACS *aacs, const char *path, const 
char *configfile_path)
 
     aacs->path = path ? str_dup(path) : NULL;
 
+    aacs->cc = _read_cc_any(aacs);
+
     error_code = _calc_title_hash(aacs);
     if (error_code != AACS_SUCCESS) {
         return error_code;
@@ -1246,8 +1249,6 @@ int aacs_open_device(AACS *aacs, const char *path, const 
char *configfile_path)
         BD_DEBUG(DBG_AACS, "Failed to initialize AACS!\n");
     }
 
-    aacs->cc = _read_cc_any(aacs);
-
     aacs->bee = _get_bus_encryption_enabled(aacs);
     aacs->bec = _get_bus_encryption_capable(aacs, path);
 


=====================================
src/libaacs/unit_key.c
=====================================
@@ -143,8 +143,9 @@ static int _assign_titles(AACS_UK *uk, const uint8_t *p, 
size_t size)
     return 0;
 }
 
-static int _parse_uks(AACS_UK *uk, const uint8_t *p, size_t size)
+static int _parse_uks(AACS_UK *uk, const uint8_t *p, size_t size, int aacs2)
 {
+    const uint8_t empty_key[16] = {0};
     uint32_t uk_pos;
     unsigned int i;
 
@@ -173,6 +174,17 @@ static int _parse_uks(AACS_UK *uk, const uint8_t *p, 
size_t size)
         return -1;
     }
 
+    if (aacs2 && uk->num_uk > 1) {
+        /* do some sanity checks ... */
+        if (!memcmp(empty_key, p + 48 + 48 + 16, 16)) {
+            BD_DEBUG(DBG_UK | DBG_CRIT, "AACS2 unit key not found from 
expected location ?\n");
+            aacs2 = 0;
+        } else if (size < uk_pos + 64 * uk->num_uk + 16) {
+            BD_DEBUG(DBG_UK | DBG_CRIT, "Unexpected EOF (AACS2 unit key data 
truncated)\n");
+            return -1;
+        }
+    }
+
     /* alloc storage for keys */
 
     uk->enc_uk = calloc(uk->num_uk, sizeof(AACS_UK));
@@ -181,19 +193,29 @@ static int _parse_uks(AACS_UK *uk, const uint8_t *p, 
size_t size)
         return -1;
     }
 
-    BD_DEBUG(DBG_UK, "%d CPS unit keys\n", uk->num_uk);
+    BD_DEBUG(DBG_UK, "%d CPS unit keys (AACS%d)\n", uk->num_uk, aacs2 ? 2 : 1);
 
     /* get encrypted keys */
 
     for (i = 0; i < uk->num_uk; i++) {
         uk_pos += 48;
         memcpy(uk->enc_uk[i].key, p + uk_pos, 16);
+
+        if (!memcmp(empty_key, uk->enc_uk[i].key, 16)) {
+            BD_DEBUG(DBG_UK | DBG_CRIT, "WARNING: Unit key %d is empty!\n", 
i+1);
+        }
+
+        /* XXX there seems to be nothing in this file that could be used to 
detect this ... */
+        if (aacs2) {
+            /* skip unknown */
+            uk_pos += 16;
+        }
     }
 
     return 0;
 }
 
-static int _parse(AACS_UK *uk, const uint8_t *data, size_t len)
+static int _parse(AACS_UK *uk, const uint8_t *data, size_t len, int aacs2)
 {
     int result;
 
@@ -201,7 +223,7 @@ static int _parse(AACS_UK *uk, const uint8_t *data, size_t 
len)
         return -1;
     }
 
-    result = _parse_uks(uk, data, len);
+    result = _parse_uks(uk, data, len, aacs2);
 
     /* not fatal, just speeds up things ... */
     _assign_titles(uk, data, len);
@@ -209,7 +231,7 @@ static int _parse(AACS_UK *uk, const uint8_t *data, size_t 
len)
     return result;
 }
 
-AACS_UK *uk_parse(const void *data, size_t len)
+AACS_UK *uk_parse(const void *data, size_t len, int aacs2)
 {
     AACS_UK *uk = calloc(1, sizeof(*uk));
 
@@ -217,7 +239,7 @@ AACS_UK *uk_parse(const void *data, size_t len)
         return NULL;
     }
 
-    if (_parse(uk, data, len) < 0) {
+    if (_parse(uk, data, len, aacs2) < 0) {
         BD_DEBUG(DBG_UK | DBG_CRIT, "Corrupt unit key file 
(AACS/Unit_Key_RO.inf)\n");
         X_FREE(uk);
     }


=====================================
src/libaacs/unit_key.h
=====================================
@@ -50,7 +50,7 @@ struct aacs_uk {
     uint16_t  *title_cps_unit;  /* map title to CPS unit (key index) */
 };
 
-BD_PRIVATE AACS_UK *uk_parse(const void *data, size_t len);
+BD_PRIVATE AACS_UK *uk_parse(const void *data, size_t len, int aacs2);
 BD_PRIVATE void     uk_free(AACS_UK **);
 
 #endif /* AACS_UK_H_ */



View it on GitLab: 
https://code.videolan.org/videolan/libaacs/-/commit/33c95654d6147d6de6d97fb57d8b0ea2f3d47b43

-- 
View it on GitLab: 
https://code.videolan.org/videolan/libaacs/-/commit/33c95654d6147d6de6d97fb57d8b0ea2f3d47b43
You're receiving this email because of your account on code.videolan.org.


_______________________________________________
libaacs-devel mailing list
libaacs-devel@videolan.org
https://mailman.videolan.org/listinfo/libaacs-devel

Reply via email to