From cb25a130797370e2801cecc34740764c6d2d264b Mon Sep 17 00:00:00 2001 From: Vesselin Bontchev <vesselin.bontc...@yandex.com> Date: Sat, 1 Jan 2000 09:00:00 +0000 Subject: [PATCH v3] Add support for playing Audible AAXC (.aaxc) files
The AAXC container format is the same as the (already supported) Audible AAX format but it uses a different encryption scheme. Note: audible_key and audible_iv values are variable (per file) and are externally fed. It is possible to extend https://github.com/mkb79/Audible to derive the audible_key and audible_key values. Relevant code: def decrypt_voucher(deviceSerialNumber, customerId, deviceType, asin, voucher): buf = (deviceType + deviceSerialNumber + customerId + asin).encode("ascii") digest = hashlib.sha256(buf).digest() key = digest[0:16] iv = digest[16:] # decrypt "voucher" using AES in CBC mode with no padding cipher = AES.new(key, AES.MODE_CBC, iv) plaintext = cipher.decrypt(voucher).rstrip(b"\x00") return json.loads(plaintext) The decrypted "voucher" has the required audible_key and audible_iv values. Signed-off-by: Vesselin Bontchev <vesselin.bontc...@yandex.com> --- libavformat/isom.h | 4 ++++ libavformat/mov.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/libavformat/isom.h b/libavformat/isom.h index 4943b80ccf..6f7de09155 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -285,6 +285,10 @@ typedef struct MOVContext { int activation_bytes_size; void *audible_fixed_key; int audible_fixed_key_size; + void *audible_key; + int audible_key_size; + void *audible_iv; + int audible_iv_size; struct AVAES *aes_decrypt; uint8_t *decryption_key; int decryption_key_len; diff --git a/libavformat/mov.c b/libavformat/mov.c index 0c4e468dd4..d31653eb6e 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1085,6 +1085,39 @@ fail: return ret; } +static int mov_aaxc_crypto(MOVContext *c) +{ + int ret = 0; + + /* verify audible_key */ + if (c->audible_key_size != 16) { + av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_key value needs to be 16 bytes!\n"); + ret = AVERROR(EINVAL); + goto fail; + } + + /* verify audible_iv */ + if (c->audible_iv_size != 16) { + av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_iv value needs to be 16 bytes!\n"); + ret = AVERROR(EINVAL); + goto fail; + } + + c->aes_decrypt = av_aes_alloc(); + if (!c->aes_decrypt) { + ret = AVERROR(ENOMEM); + goto fail; + } + + memcpy(c->file_key, c->audible_key, 16); + memcpy(c->file_iv, c->audible_iv, 16); + c->aax_mode = 1; + +fail: + + return ret; +} + // Audible AAX (and AAX+) bytestream decryption static int aax_filter(uint8_t *input, int size, MOVContext *c) { @@ -1133,6 +1166,11 @@ static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom) av_dict_set(&c->fc->metadata, "compatible_brands", comp_brands_str, AV_DICT_DONT_STRDUP_VAL); + // Logic for handling Audible's .aaxc files + if (!strcmp(type, "aaxc")) { + mov_aaxc_crypto(c); + } + return 0; } @@ -8073,6 +8111,10 @@ static const AVOption mov_options[] = { AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS }, { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM }, + { "audible_key", "AES-128 Key for Audible AAXC files", OFFSET(audible_key), + AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM }, + { "audible_iv", "AES-128 IV for Audible AAXC files", OFFSET(audible_iv), + AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM }, { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files! "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key), AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"}, -- 2.26.0
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".