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