libaacs | branch: master | Janusz Dziemidowicz <rrapt...@nails.eu.org> | Sat Sep 7 01:16:14 2013 +0200| [7c8c7b43dfa85e5dc34bba11b200e0fb968a2004] | committer: npzacs
Retrieve bus encryption flags from drive and content certificate For bus encryption to be active it must be enabled both by the drive and the disc. Drive certificate contains Bus Encryption Capable (BEC) flag in the least significant bit in the second byte of the certificate. Content certificate contains Bus Encryption Enabled (BEE) flag in the most significant bit in the second byte of the certificate. Retrieve both bits so it is now possible to check if bus encryption is active (it will not be active if the disc does not enable it, even on bus encryption drive; most discs currently do not enable it). > http://git.videolan.org/gitweb.cgi/libaacs.git/?a=commit;h=7c8c7b43dfa85e5dc34bba11b200e0fb968a2004 --- src/libaacs/aacs.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/libaacs/mmc.c | 17 ++++++++++--- src/libaacs/mmc.h | 1 + 3 files changed, 82 insertions(+), 3 deletions(-) diff --git a/src/libaacs/aacs.c b/src/libaacs/aacs.c index 3a455e4..3f841e1 100644 --- a/src/libaacs/aacs.c +++ b/src/libaacs/aacs.c @@ -65,6 +65,10 @@ struct aacs { /* title -> CPS unit mappings */ uint32_t num_titles; uint16_t *cps_units; /* [0] = first play ; [1] = top menu ; [2] = title 1 ... */ + + /* bus encryption */ + int bee; /* bus encryption enabled flag in content certificate */ + int bec; /* bus encryption capable flag in drive certificate */ }; static const uint8_t empty_key[] = "\x00\x00\x00\x00\x00\x00\x00\x00" @@ -441,6 +445,22 @@ static AACS_FILE_H *_open_unit_key_file(const char *path) return fp; } +static AACS_FILE_H *_open_content_certificate_file(const char *path) +{ + AACS_FILE_H *fp; + char *f_name; + + f_name = str_printf("%s/AACS/Content000.cer", path); + fp = file_open(f_name, "rb"); + + if (!fp) { + DEBUG(DBG_AACS | DBG_CRIT, "Error opening content certificate file %s\n", f_name); + } + + X_FREE(f_name); + return fp; +} + /* Function that collects keys from keydb config entry */ static void _find_config_entry(AACS *aacs, title_entry_list *ce, uint8_t *mk, uint8_t *vuk) @@ -639,6 +659,50 @@ static int _calc_title_hash(const char *path, uint8_t *title_hash) return result; } +static int _get_bus_encryption_enabled(const char *path) +{ + AACS_FILE_H *fp = NULL; + uint8_t buf[2]; + int bee = 0; + + fp = _open_content_certificate_file(path); + if (!fp) { + DEBUG(DBG_AACS | DBG_CRIT, "Unable to open content certificate\n"); + return 0; + } + + if (file_read(fp, buf, 2) == 2) { + bee = (buf[1] & 0x80) >> 7; + DEBUG(DBG_AACS, "Bus Encryption Enabled flag in content certificate: %d\n", bee); + } else { + DEBUG(DBG_AACS | DBG_CRIT, "Failed to read Bus Encryption Enabled flag from content certificate file\n"); + } + + file_close(fp); + return bee; +} + +static int _get_bus_encryption_capable(const char *path) +{ + MMC* mmc = NULL; + uint8_t drive_cert[92]; + int bec = 0; + + if (!(mmc = mmc_open(path))) { + return 0; + } + + if (mmc_read_drive_cert(mmc, drive_cert) == MMC_SUCCESS) { + bec = drive_cert[1] & 1; + DEBUG(DBG_AACS, "Bus Encryption Capable flag in drive certificate: %d\n", bec); + } else { + DEBUG(DBG_AACS | DBG_CRIT, "Unable to read drive certificate\n"); + } + + mmc_close(mmc); + return bec; +} + static int _verify_ts(uint8_t *buf, size_t size) { uint8_t *ptr; @@ -751,6 +815,9 @@ AACS *aacs_open2(const char *path, const char *configfile_path, int *error_code) DEBUG(DBG_AACS, "Starting AACS waterfall...\n"); *error_code = _calc_uks(aacs, configfile_path); + aacs->bee = _get_bus_encryption_enabled(path); + aacs->bec = _get_bus_encryption_capable(path); + if (*error_code == AACS_SUCCESS) { DEBUG(DBG_AACS, "AACS initialized!\n"); } else { diff --git a/src/libaacs/mmc.c b/src/libaacs/mmc.c index 41b1fd2..5afbdae 100644 --- a/src/libaacs/mmc.c +++ b/src/libaacs/mmc.c @@ -469,8 +469,8 @@ static int _mmc_send_host_cert(MMC *mmc, uint8_t agid, return _mmc_send_key(mmc, agid, 0x01, buf, 116); } -static int _mmc_read_drive_cert(MMC *mmc, uint8_t agid, uint8_t *drive_nonce, - uint8_t *drive_cert) +static int _mmc_read_drive_cert_challenge(MMC *mmc, uint8_t agid, uint8_t *drive_nonce, + uint8_t *drive_cert) { uint8_t buf[116]; memset(buf, 0, sizeof(buf)); @@ -1044,7 +1044,7 @@ static int _mmc_aacs_auth(MMC *mmc, const uint8_t *host_priv_key, const uint8_t } // receive mmc cert + nonce - if (!_mmc_read_drive_cert(mmc, agid, dn, dc)) { + if (!_mmc_read_drive_cert_challenge(mmc, agid, dn, dc)) { DEBUG(DBG_MMC | DBG_CRIT, "Drive doesn't give its certificate\n"); return MMC_ERROR; @@ -1223,6 +1223,17 @@ int mmc_read_data_keys(MMC *mmc, const uint8_t *host_priv_key, const uint8_t *ho return MMC_ERROR; } +int mmc_read_drive_cert(MMC *mmc, uint8_t *drive_cert) +{ + uint8_t buf[116]; + + if (_mmc_report_key(mmc, 0, 0, 0, 0x38, buf, 116)) { + memcpy(drive_cert, buf + 4, 92); + return MMC_SUCCESS; + } + return MMC_ERROR; +} + uint8_t *mmc_read_mkb(MMC *mmc, int address, int *size) { uint8_t agid = 0; diff --git a/src/libaacs/mmc.h b/src/libaacs/mmc.h index 57419dc..2bae638 100644 --- a/src/libaacs/mmc.h +++ b/src/libaacs/mmc.h @@ -37,6 +37,7 @@ AACS_PRIVATE int mmc_read_vid(MMC *mmc, const uint8_t *host_priv_key, const uin uint8_t *vid, uint8_t *pmsn); AACS_PRIVATE int mmc_read_data_keys(MMC *mmc, const uint8_t *host_priv_key, const uint8_t *host_cert, uint8_t *read_data_key, uint8_t *write_data_key); +AACS_PRIVATE int mmc_read_drive_cert(MMC *mmc, uint8_t *drive_cert); /* read partial MKB */ AACS_PRIVATE uint8_t *mmc_read_mkb(MMC *mmc, int address, int *size); _______________________________________________ libaacs-devel mailing list libaacs-devel@videolan.org https://mailman.videolan.org/listinfo/libaacs-devel