libaacs | branch: master | npzacs <npz...@gmail.com> | Tue Oct 8 09:57:07 2013 +0300| [08d869c8122ae4c6a73c8e7d8aed60bdacba339b] | committer: npzacs
Added aacs_get_device_binding_id() and aacs_get_device_nonce() > http://git.videolan.org/gitweb.cgi/libaacs.git/?a=commit;h=08d869c8122ae4c6a73c8e7d8aed60bdacba339b --- ChangeLog | 1 + src/examples/aacs_info.c | 2 ++ src/file/keydbcfg.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++ src/file/keydbcfg.h | 3 +++ src/libaacs/aacs.c | 29 ++++++++++++++++++++++++ src/libaacs/aacs.h | 4 ++++ 6 files changed, 94 insertions(+) diff --git a/ChangeLog b/ChangeLog index fa0a2d2..8e7c0f9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + - Added aacs_get_device_binding_id() and aacs_get_device_nonce() - Fixed reading PMSN - Dropped support for compile-time PATCHED_DRIVE flag. - Bus encryption support diff --git a/src/examples/aacs_info.c b/src/examples/aacs_info.c index 8f8d6d4..8970fd8 100644 --- a/src/examples/aacs_info.c +++ b/src/examples/aacs_info.c @@ -112,6 +112,7 @@ int main (int argc, char **argv) const uint8_t *id = aacs_get_disc_id(aacs); const uint8_t *pmsn = aacs_get_pmsn(aacs); const int bec = aacs_get_bus_encryption(aacs); + const uint8_t *binding_id = aacs_get_device_binding_id(aacs); printf("Disc ID: %s\n", id ? _hex2str(id, 20) : "???"); printf("VID : %s\n", vid ? _hex2str(vid, 16) : "???"); printf("MKBv : %d\n", aacs_get_mkb_version(aacs)); @@ -119,6 +120,7 @@ int main (int argc, char **argv) printf("Bus encryption:\n"); printf(" Device support: %s\n", (bec & AACS_BUS_ENCRYPTION_CAPABLE) ? "yes" : "no"); printf(" Enabled in media: %s\n", (bec & AACS_BUS_ENCRYPTION_ENABLED) ? "yes" : "no"); + printf("Device binding ID: %s\n", binding_id ? _hex2str(binding_id, 16) : "???"); aacs_close(aacs); diff --git a/src/file/keydbcfg.c b/src/file/keydbcfg.c index 8d93d1f..ddac497 100644 --- a/src/file/keydbcfg.c +++ b/src/file/keydbcfg.c @@ -550,6 +550,61 @@ void *cache_get_or_update(const char *type, const void *data, uint32_t *len, uin return cache_data; } +int config_save(const char *name, const void *data, uint32_t len) +{ + char *path = NULL; + FILE *fp = _open_cfg_file_user(name, &path, "w"); + int result = 0; + + if (fp) { + if (fwrite(&len, 1, 4, fp) == 4 && + fwrite(data, 1, len, fp) == len) { + DEBUG(DBG_FILE, "Wrote %d bytes to %s\n", len + 4, path); + result = 1; + + } else { + DEBUG(DBG_FILE | DBG_CRIT, "Error writing to %s\n", path); + } + + fclose(fp); + } + + X_FREE(path); + + return result; +} + +int config_get(const char *name, uint32_t *len, void *buf) +{ + char *path = NULL; + FILE *fp = _open_cfg_file_user(name, &path, "r"); + int result = 0; + uint32_t size = *len; + + *len = 0; + + if (fp) { + DEBUG(DBG_FILE, "Reading %s\n", path); + + if (fread(len, 1, 4, fp) == 4 && (size <= *len) && + (!buf || fread(buf, 1, *len, fp) == *len)) { + + DEBUG(DBG_FILE, "Read %d bytes from %s\n", 4 + (buf ? *len : 0), path); + result = 1; + + } else { + DEBUG(DBG_FILE | DBG_CRIT, "Error reading from %s\n", path); + } + + fclose(fp); + } + + X_FREE(path); + + return result; +} + + static char *_find_config_file(void) { static const char cfg_file_name[] = CFG_FILE_NAME; diff --git a/src/file/keydbcfg.h b/src/file/keydbcfg.h index 08677ec..7afc0e8 100644 --- a/src/file/keydbcfg.h +++ b/src/file/keydbcfg.h @@ -131,4 +131,7 @@ AACS_PRIVATE int cache_remove(const char *name); AACS_PRIVATE void *cache_get_or_update(const char *type, const void *data, uint32_t *len, uint32_t version); +AACS_PRIVATE int config_get(const char *name, uint32_t *len, void *buf); /* use buf=NULL to get size */ +AACS_PRIVATE int config_save(const char *name, const void *data, uint32_t len); + #endif diff --git a/src/libaacs/aacs.c b/src/libaacs/aacs.c index 0ae51b4..e8f5812 100644 --- a/src/libaacs/aacs.c +++ b/src/libaacs/aacs.c @@ -70,6 +70,10 @@ struct aacs { int bee; /* bus encryption enabled flag in content certificate */ int bec; /* bus encryption capable flag in drive certificate */ uint8_t read_data_key[16]; + + /* AACS Online (BD-J) */ + uint8_t device_nonce[16]; + uint8_t device_binding_id[16]; }; static const uint8_t empty_key[] = "\x00\x00\x00\x00\x00\x00\x00\x00" @@ -1056,6 +1060,31 @@ const uint8_t *aacs_get_pmsn(AACS *aacs) return aacs->pmsn; } +const uint8_t *aacs_get_device_binding_id(AACS *aacs) +{ + /* Device binding ID is used to encrypt online content. + * It needs to be cached so that downloaded content can be played later. + */ + static const char config_file_name[] = "device_binding_id"; + uint32_t len = sizeof(aacs->device_binding_id); + + DEBUG(DBG_AACS, "reading device binding id\n"); + if (!config_get(config_file_name, &len, aacs->device_binding_id) || len != sizeof(aacs->device_binding_id)) { + DEBUG(DBG_AACS, "creating device binding id\n"); + crypto_create_nonce(aacs->device_binding_id, sizeof(aacs->device_binding_id)); + config_save(config_file_name, aacs->device_binding_id, sizeof(aacs->device_binding_id)); + } + + return aacs->device_binding_id; +} + +const uint8_t *aacs_get_device_nonce(AACS *aacs) +{ + DEBUG(DBG_AACS, "creating device nonce\n"); + crypto_create_nonce(aacs->device_nonce, sizeof(aacs->device_nonce)); + return aacs->device_nonce; +} + static AACS_RL_ENTRY *_get_rl(const char *type, int *num_records, int *mkbv) { uint32_t len, version; diff --git a/src/libaacs/aacs.h b/src/libaacs/aacs.h index 1f36b1a..8d51f31 100644 --- a/src/libaacs/aacs.h +++ b/src/libaacs/aacs.h @@ -52,6 +52,10 @@ AACS_PUBLIC const uint8_t *aacs_get_disc_id(AACS *aacs); AACS_PUBLIC const uint8_t *aacs_get_vid(AACS *aacs); /* may fail even if disc can be decrypted */ AACS_PUBLIC const uint8_t *aacs_get_pmsn(AACS *aacs); /* may fail even if disc can be decrypted */ +/* AACS Online */ +AACS_PUBLIC const uint8_t *aacs_get_device_binding_id(AACS *aacs); +AACS_PUBLIC const uint8_t *aacs_get_device_nonce(AACS *aacs); + /* revocation lists */ typedef struct { uint16_t range; _______________________________________________ libaacs-devel mailing list libaacs-devel@videolan.org https://mailman.videolan.org/listinfo/libaacs-devel