зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1257726
- Update to latest upstream version of nestegg. r=kinetik
Bring in updated nestegg library, the newly exposed encryption functionality will be used to enable WebM EME. MozReview-Commit-ID: Hv6hSFjlS5c --HG-- extra : rebase_source : c759a702c205111d65aa2002564559210c662d5f
This commit is contained in:
Родитель
c6bd7cd3df
Коммит
85f8335784
|
@ -5,4 +5,4 @@ Makefile.in build files for the Mozilla build system.
|
|||
|
||||
The nestegg git repository is: git://github.com/kinetiknz/nestegg.git
|
||||
|
||||
The git commit ID used was d493c8a7abd05c6911cd546fd6b5c82b366f5203.
|
||||
The git commit ID used was 3bc788d4de8f11a1e6b625047f49b9d35dce824f.
|
||||
|
|
|
@ -89,6 +89,13 @@ extern "C" {
|
|||
#define NESTEGG_LOG_ERROR 1000 /**< Error level log message. */
|
||||
#define NESTEGG_LOG_CRITICAL 10000 /**< Critical level log message. */
|
||||
|
||||
#define NESTEGG_ENCODING_COMPRESSION 0 /**< Content encoding type is compression. */
|
||||
#define NESTEGG_ENCODING_ENCRYPTION 1 /**< Content encoding type is encryption. */
|
||||
|
||||
#define NESTEGG_PACKET_HAS_SIGNAL_BYTE_FALSE 0 /**< Packet does not have signal byte */
|
||||
#define NESTEGG_PACKET_HAS_SIGNAL_BYTE_UNENCRYPTED 1 /**< Packet has signal byte and is unencrypted */
|
||||
#define NESTEGG_PACKET_HAS_SIGNAL_BYTE_ENCRYPTED 2 /**< Packet has signal byte and is encrypted */
|
||||
|
||||
#define NESTEGG_PACKET_HAS_KEYFRAME_FALSE 0 /**< Packet contains only keyframes. */
|
||||
#define NESTEGG_PACKET_HAS_KEYFRAME_TRUE 1 /**< Packet does not contain any keyframes */
|
||||
#define NESTEGG_PACKET_HAS_KEYFRAME_UNKNOWN 2 /**< Packet may or may not contain keyframes */
|
||||
|
@ -288,6 +295,28 @@ int nestegg_track_video_params(nestegg * context, unsigned int track,
|
|||
int nestegg_track_audio_params(nestegg * context, unsigned int track,
|
||||
nestegg_audio_params * params);
|
||||
|
||||
/** Query the encoding status for @a track. If a track has multiple encodings
|
||||
the first will be returned.
|
||||
@param context Stream context initialized by #nestegg_init.
|
||||
@param track Zero based track number.
|
||||
@retval #NESTEGG_ENCODING_COMPRESSION The track is compressed, but not encrypted.
|
||||
@retval #NESTEGG_ENCODING_ENCRYPTION The track is encrypted and compressed.
|
||||
@retval -1 Error. */
|
||||
int nestegg_track_encoding(nestegg * context, unsigned int track);
|
||||
|
||||
/** Query the ContentEncKeyId for @a track. Will return an error if the track
|
||||
in not encrypted, or is not recognized.
|
||||
@param context Stream context initialized by #nestegg_init.
|
||||
@param track Zero based track number.
|
||||
@param content_enc_key_id Storage for queried id. The content encryption key used.
|
||||
Owned by nestegg and will be freed separately.
|
||||
@param content_enc_key_id_length Length of the queried ContentEncKeyId in bytes.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_track_content_enc_key_id(nestegg * context, unsigned int track,
|
||||
unsigned char const ** content_enc_key_id,
|
||||
size_t * content_enc_key_id_length);
|
||||
|
||||
/** Query the default frame duration for @a track. For a video track, this
|
||||
is typically the inverse of the video frame rate.
|
||||
@param context Stream context initialized by #nestegg_init.
|
||||
|
@ -387,6 +416,29 @@ int nestegg_packet_additional_data(nestegg_packet * packet, unsigned int id,
|
|||
int nestegg_packet_discard_padding(nestegg_packet * packet,
|
||||
int64_t * discard_padding);
|
||||
|
||||
/** Query if a packet is encrypted.
|
||||
@param packet Packet initialized by #nestegg_read_packet.
|
||||
@retval #NESTEGG_PACKET_HAS_SIGNAL_BYTE_FALSE No signal byte, encryption
|
||||
information not read from packet.
|
||||
@retval #NESTEGG_PACKET_HAS_SIGNAL_BYTE_UNENCRYPTED Encrypted bit not
|
||||
set, encryption information not read from packet.
|
||||
@retval #NESTEGG_PACKET_HAS_SIGNAL_BYTE_ENCRYPTED Encrypted bit set,
|
||||
encryption infomation read from packet.
|
||||
@retval -1 Error.*/
|
||||
int nestegg_packet_encryption(nestegg_packet * packet);
|
||||
|
||||
/** Query the IV for an encrypted packet. Expects a packet from an encrypted
|
||||
track, and will return error if given a packet that has no signal btye.
|
||||
@param packet Packet initialized by #nestegg_read_packet.
|
||||
@param iv Storage for queried iv.
|
||||
@param length Length of returned iv, may be 0.
|
||||
The data is owned by the #nestegg_packet packet.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error.
|
||||
*/
|
||||
int nestegg_packet_iv(nestegg_packet * packet, unsigned char const ** iv,
|
||||
size_t * length);
|
||||
|
||||
/** Returns reference_block given packet
|
||||
@param packet Packet initialized by #nestegg_read_packet.
|
||||
@param reference_block pointer to store reference block in.
|
||||
|
|
|
@ -12,97 +12,109 @@
|
|||
#include "nestegg/nestegg.h"
|
||||
|
||||
/* EBML Elements */
|
||||
#define ID_EBML 0x1a45dfa3
|
||||
#define ID_EBML_VERSION 0x4286
|
||||
#define ID_EBML_READ_VERSION 0x42f7
|
||||
#define ID_EBML_MAX_ID_LENGTH 0x42f2
|
||||
#define ID_EBML_MAX_SIZE_LENGTH 0x42f3
|
||||
#define ID_DOCTYPE 0x4282
|
||||
#define ID_DOCTYPE_VERSION 0x4287
|
||||
#define ID_DOCTYPE_READ_VERSION 0x4285
|
||||
#define ID_EBML 0x1a45dfa3
|
||||
#define ID_EBML_VERSION 0x4286
|
||||
#define ID_EBML_READ_VERSION 0x42f7
|
||||
#define ID_EBML_MAX_ID_LENGTH 0x42f2
|
||||
#define ID_EBML_MAX_SIZE_LENGTH 0x42f3
|
||||
#define ID_DOCTYPE 0x4282
|
||||
#define ID_DOCTYPE_VERSION 0x4287
|
||||
#define ID_DOCTYPE_READ_VERSION 0x4285
|
||||
|
||||
/* Global Elements */
|
||||
#define ID_VOID 0xec
|
||||
#define ID_CRC32 0xbf
|
||||
#define ID_VOID 0xec
|
||||
#define ID_CRC32 0xbf
|
||||
|
||||
/* WebM Elements */
|
||||
#define ID_SEGMENT 0x18538067
|
||||
#define ID_SEGMENT 0x18538067
|
||||
|
||||
/* Seek Head Elements */
|
||||
#define ID_SEEK_HEAD 0x114d9b74
|
||||
#define ID_SEEK 0x4dbb
|
||||
#define ID_SEEK_ID 0x53ab
|
||||
#define ID_SEEK_POSITION 0x53ac
|
||||
#define ID_SEEK_HEAD 0x114d9b74
|
||||
#define ID_SEEK 0x4dbb
|
||||
#define ID_SEEK_ID 0x53ab
|
||||
#define ID_SEEK_POSITION 0x53ac
|
||||
|
||||
/* Info Elements */
|
||||
#define ID_INFO 0x1549a966
|
||||
#define ID_TIMECODE_SCALE 0x2ad7b1
|
||||
#define ID_DURATION 0x4489
|
||||
#define ID_INFO 0x1549a966
|
||||
#define ID_TIMECODE_SCALE 0x2ad7b1
|
||||
#define ID_DURATION 0x4489
|
||||
|
||||
/* Cluster Elements */
|
||||
#define ID_CLUSTER 0x1f43b675
|
||||
#define ID_TIMECODE 0xe7
|
||||
#define ID_BLOCK_GROUP 0xa0
|
||||
#define ID_SIMPLE_BLOCK 0xa3
|
||||
#define ID_CLUSTER 0x1f43b675
|
||||
#define ID_TIMECODE 0xe7
|
||||
#define ID_BLOCK_GROUP 0xa0
|
||||
#define ID_SIMPLE_BLOCK 0xa3
|
||||
|
||||
/* BlockGroup Elements */
|
||||
#define ID_BLOCK 0xa1
|
||||
#define ID_BLOCK_ADDITIONS 0x75a1
|
||||
#define ID_BLOCK_DURATION 0x9b
|
||||
#define ID_REFERENCE_BLOCK 0xfb
|
||||
#define ID_DISCARD_PADDING 0x75a2
|
||||
#define ID_BLOCK 0xa1
|
||||
#define ID_BLOCK_ADDITIONS 0x75a1
|
||||
#define ID_BLOCK_DURATION 0x9b
|
||||
#define ID_REFERENCE_BLOCK 0xfb
|
||||
#define ID_DISCARD_PADDING 0x75a2
|
||||
|
||||
/* BlockAdditions Elements */
|
||||
#define ID_BLOCK_MORE 0xa6
|
||||
#define ID_BLOCK_MORE 0xa6
|
||||
|
||||
/* BlockMore Elements */
|
||||
#define ID_BLOCK_ADD_ID 0xee
|
||||
#define ID_BLOCK_ADDITIONAL 0xa5
|
||||
#define ID_BLOCK_ADD_ID 0xee
|
||||
#define ID_BLOCK_ADDITIONAL 0xa5
|
||||
|
||||
/* Tracks Elements */
|
||||
#define ID_TRACKS 0x1654ae6b
|
||||
#define ID_TRACK_ENTRY 0xae
|
||||
#define ID_TRACK_NUMBER 0xd7
|
||||
#define ID_TRACK_UID 0x73c5
|
||||
#define ID_TRACK_TYPE 0x83
|
||||
#define ID_FLAG_ENABLED 0xb9
|
||||
#define ID_FLAG_DEFAULT 0x88
|
||||
#define ID_FLAG_LACING 0x9c
|
||||
#define ID_TRACK_TIMECODE_SCALE 0x23314f
|
||||
#define ID_LANGUAGE 0x22b59c
|
||||
#define ID_CODEC_ID 0x86
|
||||
#define ID_CODEC_PRIVATE 0x63a2
|
||||
#define ID_CODEC_DELAY 0x56aa
|
||||
#define ID_SEEK_PREROLL 0x56bb
|
||||
#define ID_DEFAULT_DURATION 0x23e383
|
||||
#define ID_TRACKS 0x1654ae6b
|
||||
#define ID_TRACK_ENTRY 0xae
|
||||
#define ID_TRACK_NUMBER 0xd7
|
||||
#define ID_TRACK_UID 0x73c5
|
||||
#define ID_TRACK_TYPE 0x83
|
||||
#define ID_FLAG_ENABLED 0xb9
|
||||
#define ID_FLAG_DEFAULT 0x88
|
||||
#define ID_FLAG_LACING 0x9c
|
||||
#define ID_TRACK_TIMECODE_SCALE 0x23314f
|
||||
#define ID_LANGUAGE 0x22b59c
|
||||
#define ID_CODEC_ID 0x86
|
||||
#define ID_CODEC_PRIVATE 0x63a2
|
||||
#define ID_CODEC_DELAY 0x56aa
|
||||
#define ID_SEEK_PREROLL 0x56bb
|
||||
#define ID_DEFAULT_DURATION 0x23e383
|
||||
|
||||
/* Video Elements */
|
||||
#define ID_VIDEO 0xe0
|
||||
#define ID_STEREO_MODE 0x53b8
|
||||
#define ID_ALPHA_MODE 0x53c0
|
||||
#define ID_PIXEL_WIDTH 0xb0
|
||||
#define ID_PIXEL_HEIGHT 0xba
|
||||
#define ID_PIXEL_CROP_BOTTOM 0x54aa
|
||||
#define ID_PIXEL_CROP_TOP 0x54bb
|
||||
#define ID_PIXEL_CROP_LEFT 0x54cc
|
||||
#define ID_PIXEL_CROP_RIGHT 0x54dd
|
||||
#define ID_DISPLAY_WIDTH 0x54b0
|
||||
#define ID_DISPLAY_HEIGHT 0x54ba
|
||||
#define ID_VIDEO 0xe0
|
||||
#define ID_STEREO_MODE 0x53b8
|
||||
#define ID_ALPHA_MODE 0x53c0
|
||||
#define ID_PIXEL_WIDTH 0xb0
|
||||
#define ID_PIXEL_HEIGHT 0xba
|
||||
#define ID_PIXEL_CROP_BOTTOM 0x54aa
|
||||
#define ID_PIXEL_CROP_TOP 0x54bb
|
||||
#define ID_PIXEL_CROP_LEFT 0x54cc
|
||||
#define ID_PIXEL_CROP_RIGHT 0x54dd
|
||||
#define ID_DISPLAY_WIDTH 0x54b0
|
||||
#define ID_DISPLAY_HEIGHT 0x54ba
|
||||
|
||||
/* Audio Elements */
|
||||
#define ID_AUDIO 0xe1
|
||||
#define ID_SAMPLING_FREQUENCY 0xb5
|
||||
#define ID_CHANNELS 0x9f
|
||||
#define ID_BIT_DEPTH 0x6264
|
||||
#define ID_AUDIO 0xe1
|
||||
#define ID_SAMPLING_FREQUENCY 0xb5
|
||||
#define ID_CHANNELS 0x9f
|
||||
#define ID_BIT_DEPTH 0x6264
|
||||
|
||||
/* Cues Elements */
|
||||
#define ID_CUES 0x1c53bb6b
|
||||
#define ID_CUE_POINT 0xbb
|
||||
#define ID_CUE_TIME 0xb3
|
||||
#define ID_CUE_TRACK_POSITIONS 0xb7
|
||||
#define ID_CUE_TRACK 0xf7
|
||||
#define ID_CUE_CLUSTER_POSITION 0xf1
|
||||
#define ID_CUE_BLOCK_NUMBER 0x5378
|
||||
#define ID_CUES 0x1c53bb6b
|
||||
#define ID_CUE_POINT 0xbb
|
||||
#define ID_CUE_TIME 0xb3
|
||||
#define ID_CUE_TRACK_POSITIONS 0xb7
|
||||
#define ID_CUE_TRACK 0xf7
|
||||
#define ID_CUE_CLUSTER_POSITION 0xf1
|
||||
#define ID_CUE_BLOCK_NUMBER 0x5378
|
||||
|
||||
/* Encoding Elements */
|
||||
#define ID_CONTENT_ENCODINGS 0x6d80
|
||||
#define ID_CONTENT_ENCODING 0x6240
|
||||
#define ID_CONTENT_ENCODING_TYPE 0x5033
|
||||
|
||||
/* Encryption Elements */
|
||||
#define ID_CONTENT_ENCRYPTION 0x5035
|
||||
#define ID_CONTENT_ENC_ALGO 0x47e1
|
||||
#define ID_CONTENT_ENC_KEY_ID 0x47e2
|
||||
#define ID_CONTENT_ENC_AES_SETTINGS 0x47e7
|
||||
#define ID_AES_SETTINGS_CIPHER_MODE 0x47e8
|
||||
|
||||
/* EBML Types */
|
||||
enum ebml_type_enum {
|
||||
|
@ -114,36 +126,48 @@ enum ebml_type_enum {
|
|||
TYPE_BINARY
|
||||
};
|
||||
|
||||
#define LIMIT_STRING (1 << 20)
|
||||
#define LIMIT_BINARY (1 << 24)
|
||||
#define LIMIT_BLOCK (1 << 30)
|
||||
#define LIMIT_FRAME (1 << 28)
|
||||
#define LIMIT_STRING (1 << 20)
|
||||
#define LIMIT_BINARY (1 << 24)
|
||||
#define LIMIT_BLOCK (1 << 30)
|
||||
#define LIMIT_FRAME (1 << 28)
|
||||
|
||||
/* Field Flags */
|
||||
#define DESC_FLAG_NONE 0
|
||||
#define DESC_FLAG_MULTI (1 << 0)
|
||||
#define DESC_FLAG_SUSPEND (1 << 1)
|
||||
#define DESC_FLAG_OFFSET (1 << 2)
|
||||
#define DESC_FLAG_NONE 0
|
||||
#define DESC_FLAG_MULTI (1 << 0)
|
||||
#define DESC_FLAG_SUSPEND (1 << 1)
|
||||
#define DESC_FLAG_OFFSET (1 << 2)
|
||||
|
||||
/* Block Header Flags */
|
||||
#define SIMPLE_BLOCK_FLAGS_KEYFRAME (1 << 7)
|
||||
#define BLOCK_FLAGS_LACING 6
|
||||
|
||||
/* Lacing Constants */
|
||||
#define LACING_NONE 0
|
||||
#define LACING_XIPH 1
|
||||
#define LACING_FIXED 2
|
||||
#define LACING_EBML 3
|
||||
#define LACING_NONE 0
|
||||
#define LACING_XIPH 1
|
||||
#define LACING_FIXED 2
|
||||
#define LACING_EBML 3
|
||||
|
||||
/* Track Types */
|
||||
#define TRACK_TYPE_VIDEO 1
|
||||
#define TRACK_TYPE_AUDIO 2
|
||||
#define TRACK_TYPE_VIDEO 1
|
||||
#define TRACK_TYPE_AUDIO 2
|
||||
|
||||
/* Track IDs */
|
||||
#define TRACK_ID_VP8 "V_VP8"
|
||||
#define TRACK_ID_VP9 "V_VP9"
|
||||
#define TRACK_ID_VORBIS "A_VORBIS"
|
||||
#define TRACK_ID_OPUS "A_OPUS"
|
||||
#define TRACK_ID_VP8 "V_VP8"
|
||||
#define TRACK_ID_VP9 "V_VP9"
|
||||
#define TRACK_ID_VORBIS "A_VORBIS"
|
||||
#define TRACK_ID_OPUS "A_OPUS"
|
||||
|
||||
/* Track Encryption */
|
||||
#define CONTENT_ENC_ALGO_AES 5
|
||||
#define AES_SETTINGS_CIPHER_CTR 1
|
||||
|
||||
/* Packet Encryption */
|
||||
#define SIGNAL_BYTE_SIZE 1
|
||||
#define IV_SIZE 8
|
||||
|
||||
/* Signal Byte */
|
||||
#define PACKET_ENCRYPTED 1
|
||||
#define ENCRYPTED_BIT_MASK (1 << 0)
|
||||
|
||||
enum vint_mask {
|
||||
MASK_NONE,
|
||||
|
@ -223,6 +247,25 @@ struct audio {
|
|||
struct ebml_type bit_depth;
|
||||
};
|
||||
|
||||
struct content_enc_aes_settings {
|
||||
struct ebml_type aes_settings_cipher_mode;
|
||||
};
|
||||
|
||||
struct content_encryption {
|
||||
struct ebml_type content_enc_algo;
|
||||
struct ebml_type content_enc_key_id;
|
||||
struct ebml_list content_enc_aes_settings;
|
||||
};
|
||||
|
||||
struct content_encoding {
|
||||
struct ebml_type content_encoding_type;
|
||||
struct ebml_list content_encryption;
|
||||
};
|
||||
|
||||
struct content_encodings {
|
||||
struct ebml_list content_encoding;
|
||||
};
|
||||
|
||||
struct track_entry {
|
||||
struct ebml_type number;
|
||||
struct ebml_type uid;
|
||||
|
@ -239,6 +282,7 @@ struct track_entry {
|
|||
struct ebml_type default_duration;
|
||||
struct video video;
|
||||
struct audio audio;
|
||||
struct content_encodings content_encodings;
|
||||
};
|
||||
|
||||
struct tracks {
|
||||
|
@ -285,9 +329,16 @@ struct saved_state {
|
|||
int last_valid;
|
||||
};
|
||||
|
||||
struct frame_encryption {
|
||||
unsigned char * iv;
|
||||
size_t length;
|
||||
uint8_t signal_byte;
|
||||
};
|
||||
|
||||
struct frame {
|
||||
unsigned char * data;
|
||||
size_t length;
|
||||
struct frame_encryption * frame_encryption;
|
||||
struct frame * next;
|
||||
};
|
||||
|
||||
|
@ -409,6 +460,29 @@ static struct ebml_element_desc ne_audio_elements[] = {
|
|||
E_LAST
|
||||
};
|
||||
|
||||
static struct ebml_element_desc ne_content_enc_aes_settings_elements[] = {
|
||||
E_FIELD(ID_AES_SETTINGS_CIPHER_MODE, TYPE_UINT, struct content_enc_aes_settings, aes_settings_cipher_mode),
|
||||
E_LAST
|
||||
};
|
||||
|
||||
static struct ebml_element_desc ne_content_encryption_elements[] = {
|
||||
E_FIELD(ID_CONTENT_ENC_ALGO, TYPE_UINT, struct content_encryption, content_enc_algo),
|
||||
E_FIELD(ID_CONTENT_ENC_KEY_ID, TYPE_BINARY, struct content_encryption, content_enc_key_id),
|
||||
E_MASTER(ID_CONTENT_ENC_AES_SETTINGS, TYPE_MASTER, struct content_encryption, content_enc_aes_settings),
|
||||
E_LAST
|
||||
};
|
||||
|
||||
static struct ebml_element_desc ne_content_encoding_elements[] = {
|
||||
E_FIELD(ID_CONTENT_ENCODING_TYPE, TYPE_UINT, struct content_encoding, content_encoding_type),
|
||||
E_MASTER(ID_CONTENT_ENCRYPTION, TYPE_MASTER, struct content_encoding, content_encryption),
|
||||
E_LAST
|
||||
};
|
||||
|
||||
static struct ebml_element_desc ne_content_encodings_elements[] = {
|
||||
E_MASTER(ID_CONTENT_ENCODING, TYPE_MASTER, struct content_encodings, content_encoding),
|
||||
E_LAST
|
||||
};
|
||||
|
||||
static struct ebml_element_desc ne_track_entry_elements[] = {
|
||||
E_FIELD(ID_TRACK_NUMBER, TYPE_UINT, struct track_entry, number),
|
||||
E_FIELD(ID_TRACK_UID, TYPE_UINT, struct track_entry, uid),
|
||||
|
@ -425,6 +499,7 @@ static struct ebml_element_desc ne_track_entry_elements[] = {
|
|||
E_FIELD(ID_DEFAULT_DURATION, TYPE_UINT, struct track_entry, default_duration),
|
||||
E_SINGLE_MASTER(ID_VIDEO, TYPE_MASTER, struct track_entry, video),
|
||||
E_SINGLE_MASTER(ID_AUDIO, TYPE_MASTER, struct track_entry, audio),
|
||||
E_SINGLE_MASTER(ID_CONTENT_ENCODINGS, TYPE_MASTER, struct track_entry, content_encodings),
|
||||
E_LAST
|
||||
};
|
||||
|
||||
|
@ -1072,6 +1147,55 @@ ne_parse(nestegg * ctx, struct ebml_element_desc * top_level, int64_t max_offset
|
|||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
ne_read_block_encryption(nestegg * ctx, struct track_entry const * entry,
|
||||
uint64_t * encoding_type, uint64_t * encryption_algo,
|
||||
uint64_t * encryption_mode)
|
||||
{
|
||||
struct content_encoding * encoding;
|
||||
struct content_encryption * encryption;
|
||||
struct content_enc_aes_settings * aes_settings;
|
||||
|
||||
*encoding_type = 0;
|
||||
if (entry->content_encodings.content_encoding.head) {
|
||||
encoding = entry->content_encodings.content_encoding.head->data;
|
||||
if (ne_get_uint(encoding->content_encoding_type, encoding_type) != 0)
|
||||
return -1;
|
||||
|
||||
if (*encoding_type == NESTEGG_ENCODING_ENCRYPTION) {
|
||||
/* Metadata states content is encrypted */
|
||||
if (!encoding->content_encryption.head)
|
||||
return -1;
|
||||
|
||||
encryption = encoding->content_encryption.head->data;
|
||||
if (ne_get_uint(encryption->content_enc_algo, encryption_algo) != 0) {
|
||||
ctx->log(ctx, NESTEGG_LOG_ERROR, "No ContentEncAlgo element found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*encryption_algo != CONTENT_ENC_ALGO_AES) {
|
||||
ctx->log(ctx, NESTEGG_LOG_ERROR, "Disallowed ContentEncAlgo used");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!encryption->content_enc_aes_settings.head) {
|
||||
ctx->log(ctx, NESTEGG_LOG_ERROR, "No ContentEncAESSettings element found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
aes_settings = encryption->content_enc_aes_settings.head->data;
|
||||
*encryption_mode = AES_SETTINGS_CIPHER_CTR;
|
||||
ne_get_uint(aes_settings->aes_settings_cipher_mode, encryption_mode);
|
||||
|
||||
if (*encryption_mode != AES_SETTINGS_CIPHER_CTR) {
|
||||
ctx->log(ctx, NESTEGG_LOG_ERROR, "Disallowed AESSettingsCipherMode used");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
ne_read_xiph_lace_value(nestegg_io * io, uint64_t * value, size_t * consumed)
|
||||
{
|
||||
|
@ -1224,10 +1348,11 @@ ne_read_block(nestegg * ctx, uint64_t block_id, uint64_t block_size, nestegg_pac
|
|||
struct frame * f, * last;
|
||||
struct track_entry * entry;
|
||||
double track_scale;
|
||||
uint64_t track_number, length, frame_sizes[256], cluster_tc, flags, frames, tc_scale, total;
|
||||
uint64_t track_number, length, frame_sizes[256], cluster_tc, flags, frames, tc_scale, total,
|
||||
encoding_type, encryption_algo, encryption_mode;
|
||||
unsigned int i, lacing, track;
|
||||
uint8_t keyframe = NESTEGG_PACKET_HAS_KEYFRAME_UNKNOWN;
|
||||
size_t consumed = 0;
|
||||
uint8_t signal_byte, keyframe = NESTEGG_PACKET_HAS_KEYFRAME_UNKNOWN;
|
||||
size_t consumed = 0, data_size, encryption_size;
|
||||
|
||||
*data = NULL;
|
||||
|
||||
|
@ -1324,6 +1449,16 @@ ne_read_block(nestegg * ctx, uint64_t block_id, uint64_t block_size, nestegg_pac
|
|||
if (!entry)
|
||||
return -1;
|
||||
|
||||
r = ne_read_block_encryption(ctx, entry, &encoding_type, &encryption_algo, &encryption_mode);
|
||||
if (r != 1)
|
||||
return r;
|
||||
|
||||
/* Encryption does not support lacing */
|
||||
if (lacing != LACING_NONE && encoding_type == NESTEGG_ENCODING_ENCRYPTION) {
|
||||
ctx->log(ctx, NESTEGG_LOG_ERROR, "Encrypted blocks may not also be laced");
|
||||
return -1;
|
||||
}
|
||||
|
||||
track_scale = 1.0;
|
||||
|
||||
tc_scale = ne_get_timecode_scale(ctx);
|
||||
|
@ -1357,15 +1492,64 @@ ne_read_block(nestegg * ctx, uint64_t block_id, uint64_t block_size, nestegg_pac
|
|||
nestegg_free_packet(pkt);
|
||||
return -1;
|
||||
}
|
||||
f->data = ne_alloc(frame_sizes[i]);
|
||||
/* Parse encryption */
|
||||
if (encoding_type == NESTEGG_ENCODING_ENCRYPTION) {
|
||||
r = ne_io_read(ctx->io, &signal_byte, SIGNAL_BYTE_SIZE);
|
||||
if (r != 1) {
|
||||
free(f);
|
||||
nestegg_free_packet(pkt);
|
||||
return r;
|
||||
}
|
||||
f->frame_encryption = ne_alloc(sizeof(*f->frame_encryption));
|
||||
if (!f->frame_encryption) {
|
||||
free(f);
|
||||
nestegg_free_packet(pkt);
|
||||
return -1;
|
||||
}
|
||||
f->frame_encryption->signal_byte = signal_byte;
|
||||
if ((signal_byte & ENCRYPTED_BIT_MASK) == PACKET_ENCRYPTED) {
|
||||
f->frame_encryption->iv = ne_alloc(IV_SIZE);
|
||||
if (!f->frame_encryption->iv) {
|
||||
free(f->frame_encryption);
|
||||
free(f);
|
||||
nestegg_free_packet(pkt);
|
||||
return -1;
|
||||
}
|
||||
r = ne_io_read(ctx->io, f->frame_encryption->iv, IV_SIZE);
|
||||
if (r != 1) {
|
||||
free(f->frame_encryption);
|
||||
free(f);
|
||||
nestegg_free_packet(pkt);
|
||||
return r;
|
||||
}
|
||||
f->frame_encryption->length = IV_SIZE;
|
||||
encryption_size = SIGNAL_BYTE_SIZE + IV_SIZE;
|
||||
} else {
|
||||
f->frame_encryption->iv = NULL;
|
||||
f->frame_encryption->length = 0;
|
||||
encryption_size = SIGNAL_BYTE_SIZE;
|
||||
}
|
||||
} else {
|
||||
f->frame_encryption = NULL;
|
||||
encryption_size = 0;
|
||||
}
|
||||
data_size = frame_sizes[i] - encryption_size;
|
||||
/* Encryption parsed */
|
||||
f->data = ne_alloc(data_size);
|
||||
if (!f->data) {
|
||||
if (f->frame_encryption)
|
||||
free(f->frame_encryption->iv);
|
||||
free(f->frame_encryption);
|
||||
free(f);
|
||||
nestegg_free_packet(pkt);
|
||||
return -1;
|
||||
}
|
||||
f->length = frame_sizes[i];
|
||||
r = ne_io_read(ctx->io, f->data, frame_sizes[i]);
|
||||
f->length = data_size;
|
||||
r = ne_io_read(ctx->io, f->data, data_size);
|
||||
if (r != 1) {
|
||||
if (f->frame_encryption)
|
||||
free(f->frame_encryption->iv);
|
||||
free(f->frame_encryption);
|
||||
free(f->data);
|
||||
free(f);
|
||||
nestegg_free_packet(pkt);
|
||||
|
@ -2301,6 +2485,108 @@ nestegg_track_audio_params(nestegg * ctx, unsigned int track,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nestegg_track_encoding(nestegg * ctx, unsigned int track)
|
||||
{
|
||||
struct track_entry * entry;
|
||||
struct content_encoding * encoding;
|
||||
uint64_t encoding_value;
|
||||
|
||||
entry = ne_find_track_entry(ctx, track);
|
||||
if (!entry) {
|
||||
ctx->log(ctx, NESTEGG_LOG_ERROR, "No track entry found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!entry->content_encodings.content_encoding.head) {
|
||||
/* Default encoding is compression */
|
||||
return NESTEGG_ENCODING_COMPRESSION;
|
||||
}
|
||||
|
||||
encoding = entry->content_encodings.content_encoding.head->data;
|
||||
|
||||
encoding_value = NESTEGG_ENCODING_COMPRESSION;
|
||||
ne_get_uint(encoding->content_encoding_type, &encoding_value);
|
||||
if (encoding_value != NESTEGG_ENCODING_COMPRESSION && encoding_value != NESTEGG_ENCODING_ENCRYPTION) {
|
||||
ctx->log(ctx, NESTEGG_LOG_ERROR, "Invalid ContentEncoding element found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return encoding_value;
|
||||
}
|
||||
|
||||
int
|
||||
nestegg_track_content_enc_key_id(nestegg * ctx, unsigned int track, unsigned char const ** content_enc_key_id,
|
||||
size_t * content_enc_key_id_length)
|
||||
{
|
||||
struct track_entry * entry;
|
||||
struct content_encoding * encoding;
|
||||
struct content_encryption * encryption;
|
||||
struct content_enc_aes_settings * aes_settings;
|
||||
struct nestegg_encryption_params;
|
||||
uint64_t value;
|
||||
struct ebml_binary enc_key_id;
|
||||
|
||||
entry = ne_find_track_entry(ctx, track);
|
||||
if (!entry) {
|
||||
ctx->log(ctx, NESTEGG_LOG_ERROR, "No track entry found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!entry->content_encodings.content_encoding.head) {
|
||||
ctx->log(ctx, NESTEGG_LOG_ERROR, "No ContentEncoding element found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
encoding = entry->content_encodings.content_encoding.head->data;
|
||||
|
||||
value = 0;
|
||||
ne_get_uint(encoding->content_encoding_type, &value);
|
||||
if (value != NESTEGG_ENCODING_ENCRYPTION) {
|
||||
ctx->log(ctx, NESTEGG_LOG_ERROR, "Disallowed ContentEncodingType found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!encoding->content_encryption.head) {
|
||||
ctx->log(ctx, NESTEGG_LOG_ERROR, "No ContentEncryption element found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
encryption = encoding->content_encryption.head->data;
|
||||
|
||||
value = 0;
|
||||
ne_get_uint(encryption->content_enc_algo, &value);
|
||||
|
||||
if (value != CONTENT_ENC_ALGO_AES) {
|
||||
ctx->log(ctx, NESTEGG_LOG_ERROR, "Disallowed ContentEncAlgo found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!encryption->content_enc_aes_settings.head) {
|
||||
ctx->log(ctx, NESTEGG_LOG_ERROR, "No ContentEncAesSettings element found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
aes_settings = encryption->content_enc_aes_settings.head->data;
|
||||
value = AES_SETTINGS_CIPHER_CTR;
|
||||
ne_get_uint(aes_settings->aes_settings_cipher_mode, &value);
|
||||
|
||||
if (value != AES_SETTINGS_CIPHER_CTR) {
|
||||
ctx->log(ctx, NESTEGG_LOG_ERROR, "Disallowed AESSettingCipherMode used");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ne_get_binary(encryption->content_enc_key_id, &enc_key_id) != 0) {
|
||||
ctx->log(ctx, NESTEGG_LOG_ERROR, "Could not retrieve track ContentEncKeyId");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*content_enc_key_id = enc_key_id.data;
|
||||
*content_enc_key_id_length = enc_key_id.length;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nestegg_track_default_duration(nestegg * ctx, unsigned int track,
|
||||
uint64_t * duration)
|
||||
|
@ -2476,6 +2762,10 @@ nestegg_free_packet(nestegg_packet * pkt)
|
|||
while (pkt->frame) {
|
||||
frame = pkt->frame;
|
||||
pkt->frame = frame->next;
|
||||
if (frame->frame_encryption) {
|
||||
free(frame->frame_encryption->iv);
|
||||
}
|
||||
free(frame->frame_encryption);
|
||||
free(frame->data);
|
||||
free(frame);
|
||||
}
|
||||
|
@ -2596,6 +2886,50 @@ nestegg_packet_additional_data(nestegg_packet * pkt, unsigned int id,
|
|||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
nestegg_packet_encryption(nestegg_packet * pkt)
|
||||
{
|
||||
struct frame * f = pkt->frame;
|
||||
unsigned char encrypted_bit;
|
||||
|
||||
if (!f->frame_encryption)
|
||||
return NESTEGG_PACKET_HAS_SIGNAL_BYTE_FALSE;
|
||||
|
||||
/* Should never have parsed blocks with both encryption and lacing */
|
||||
assert(f->next == NULL);
|
||||
|
||||
encrypted_bit = f->frame_encryption->signal_byte & ENCRYPTED_BIT_MASK;
|
||||
|
||||
if (encrypted_bit != PACKET_ENCRYPTED)
|
||||
return NESTEGG_PACKET_HAS_SIGNAL_BYTE_UNENCRYPTED;
|
||||
|
||||
return NESTEGG_PACKET_HAS_SIGNAL_BYTE_ENCRYPTED;
|
||||
}
|
||||
|
||||
int
|
||||
nestegg_packet_iv(nestegg_packet * pkt, unsigned char const ** iv, size_t * length)
|
||||
{
|
||||
struct frame * f = pkt->frame;
|
||||
unsigned char encrypted_bit;
|
||||
|
||||
*iv = NULL;
|
||||
*length = 0;
|
||||
if (!f->frame_encryption)
|
||||
return -1;
|
||||
|
||||
/* Should never have parsed blocks with both encryption and lacing */
|
||||
assert(f->next == NULL);
|
||||
|
||||
encrypted_bit = f->frame_encryption->signal_byte & ENCRYPTED_BIT_MASK;
|
||||
|
||||
if (encrypted_bit != PACKET_ENCRYPTED)
|
||||
return 0;
|
||||
|
||||
*iv = f->frame_encryption->iv;
|
||||
*length = f->frame_encryption->length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nestegg_has_cues(nestegg * ctx)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче