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
