Commit a41a6d3d authored by Simona-Marinela Prodea's avatar Simona-Marinela Prodea Committed by Jean-Baptiste Kempf

DCP: read encrypted DCP with KDM files

Uses libgcrypt
Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>
parent c7e0dfcc
......@@ -9,12 +9,16 @@ AM_CPPFLAGS += -I$(srcdir)/access
libattachment_plugin_la_SOURCES = access/attachment.c
access_LTLIBRARIES += libattachment_plugin.la
libdcp_plugin_la_SOURCES = access/dcp/dcpparser.h access/dcp/dcp.cpp access/dcp/dcpparser.cpp
libdcp_plugin_la_SOURCES = access/dcp/dcpparser.h access/dcp/dcp.cpp access/dcp/dcpparser.cpp access/dcp/dcpdecrypt.cpp
if HAVE_ASDCP
libdcp_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) $(ASDCP_CFLAGS)
libdcp_plugin_la_LIBADD = $(AM_LIBADD) $(ASDCP_LIBS)
if HAVE_GCRYPT
libdcp_plugin_la_CPPFLAGS += $(GCRYPT_CFLAGS)
libdcp_plugin_la_LIBADD += $(GCRYPT_LIBS)
access_LTLIBRARIES += libdcp_plugin.la
endif
endif
libfilesystem_plugin_la_SOURCES = access/fs.h access/file.c access/directory.c access/fs.c
libfilesystem_plugin_la_CPPFLAGS = $(AM_CPPFLAGS)
......
......@@ -41,6 +41,8 @@
#endif
#define __STDC_CONSTANT_MACROS 1
#define KDM_HELP_TEXT "KDM file"
#define KDM_HELP_LONG_TEXT "Path to Key Delivery Message XML file"
/* VLC core API headers */
#include <vlc_common.h>
......@@ -72,6 +74,7 @@ static void Close( vlc_object_t * );
vlc_module_begin()
set_shortname( N_( "DCP" ) )
add_shortcut( "dcp" )
add_loadfile( "kdm", "", KDM_HELP_TEXT, KDM_HELP_LONG_TEXT, false )
set_description( N_( "Digital Cinema Package module" ) )
set_capability( "access_demux", 0 )
set_category( CAT_INPUT )
......@@ -604,6 +607,7 @@ static int Demux( demux_t *p_demux )
block_t *p_video_frame = NULL, *p_audio_frame = NULL;
PCM::FrameBuffer AudioFrameBuff( p_sys->i_audio_buffer);
AESDecContext video_aes_ctx, audio_aes_ctx;
/* swaping video reels */
if ( p_sys->frame_no == p_sys->p_dcp->video_reels[p_sys->i_video_reel].i_absolute_end )
......@@ -632,6 +636,20 @@ static int Demux( demux_t *p_demux )
}
/* video frame */
/* initialize AES context, if reel is encrypted */
if( p_sys &&
p_sys->p_dcp &&
p_sys->p_dcp->video_reels.size() > p_sys->i_video_reel &&
p_sys->p_dcp->video_reels[p_sys->i_video_reel].p_key )
{
if( ! ASDCP_SUCCESS( video_aes_ctx.InitKey( p_sys->p_dcp->video_reels[p_sys->i_video_reel].p_key->getKey() ) ) )
{
msg_Err( p_demux, "ASDCP failed to initialize AES key" );
goto error;
}
}
switch( p_sys->PictureEssType )
{
case ESS_JPEG_2000:
......@@ -646,13 +664,13 @@ static int Demux( demux_t *p_demux )
goto error_asdcp;
if ( p_sys->PictureEssType == ESS_JPEG_2000_S ) {
if ( ! ASDCP_SUCCESS(
p_sys->v_videoReader[p_sys->i_video_reel].p_PicMXFSReader->ReadFrame(nextFrame, JP2K::SP_LEFT, PicFrameBuff, 0, 0)) ) {
p_sys->v_videoReader[p_sys->i_video_reel].p_PicMXFSReader->ReadFrame(nextFrame, JP2K::SP_LEFT, PicFrameBuff, &video_aes_ctx, 0)) ) {
PicFrameBuff.SetData(0,0);
goto error_asdcp;
}
} else {
if ( ! ASDCP_SUCCESS(
p_sys->v_videoReader[p_sys->i_video_reel].p_PicMXFReader->ReadFrame(nextFrame, PicFrameBuff, 0, 0)) ) {
p_sys->v_videoReader[p_sys->i_video_reel].p_PicMXFReader->ReadFrame(nextFrame, PicFrameBuff, &video_aes_ctx, 0)) ) {
PicFrameBuff.SetData(0,0);
goto error_asdcp;
}
......@@ -670,7 +688,7 @@ static int Demux( demux_t *p_demux )
goto error_asdcp;
if ( ! ASDCP_SUCCESS(
p_sys->v_videoReader[p_sys->i_video_reel].p_VideoMXFReader->ReadFrame(p_sys->frame_no + p_sys->p_dcp->video_reels[p_sys->i_video_reel].i_correction, VideoFrameBuff, 0, 0)) ) {
p_sys->v_videoReader[p_sys->i_video_reel].p_VideoMXFReader->ReadFrame(p_sys->frame_no + p_sys->p_dcp->video_reels[p_sys->i_video_reel].i_correction, VideoFrameBuff, &video_aes_ctx, 0)) ) {
VideoFrameBuff.SetData(0,0);
goto error_asdcp;
}
......@@ -690,13 +708,27 @@ static int Demux( demux_t *p_demux )
if ( ( p_audio_frame = block_Alloc( p_sys->i_audio_buffer )) == NULL ) {
goto error;
}
/* initialize AES context, if reel is encrypted */
if( p_sys &&
p_sys->p_dcp &&
p_sys->p_dcp->audio_reels.size() > p_sys->i_audio_reel &&
p_sys->p_dcp->audio_reels[p_sys->i_audio_reel].p_key )
{
if( ! ASDCP_SUCCESS( audio_aes_ctx.InitKey( p_sys->p_dcp->audio_reels[p_sys->i_audio_reel].p_key->getKey() ) ) )
{
msg_Err( p_demux, "ASDCP failed to initialize AES key" );
goto error;
}
}
if ( ! ASDCP_SUCCESS(
AudioFrameBuff.SetData(p_audio_frame->p_buffer, p_sys->i_audio_buffer)) ) {
goto error_asdcp;
}
if ( ! ASDCP_SUCCESS(
p_sys->v_audioReader[p_sys->i_audio_reel].p_AudioMXFReader->ReadFrame(p_sys->frame_no + p_sys->p_dcp->audio_reels[p_sys->i_audio_reel].i_correction, AudioFrameBuff, 0, 0)) ) {
p_sys->v_audioReader[p_sys->i_audio_reel].p_AudioMXFReader->ReadFrame(p_sys->frame_no + p_sys->p_dcp->audio_reels[p_sys->i_audio_reel].i_correction, AudioFrameBuff, &audio_aes_ctx, 0)) ) {
AudioFrameBuff.SetData(0,0);
goto error_asdcp;
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -8,6 +8,7 @@
* Anthony Giniers
* Ludovic Hoareau
* Loukmane Dessai
* Simona-Marinela Prodea <simona dot marinela dot prodea at gmail dot com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
......@@ -42,6 +43,10 @@
#include <vlc_demux.h>
#include <vlc_plugin.h>
/* gcrypt headers */
#include <gcrypt.h>
#include <vlc_gcrypt.h>
#include <iostream>
#include <string>
#include <list>
......@@ -67,7 +72,8 @@ typedef enum {
class Asset;
class AssetList: public std::list<Asset *> {};
class PKL;
class AESKey;
class AESKeyList: public std::list<AESKey *> {};
/* This struct stores useful information about an MXF for demux() */
struct info_reel
......@@ -77,6 +83,7 @@ struct info_reel
int i_duration;
int i_correction; /* entrypoint - sum of previous durations */
uint32_t i_absolute_end; /* correction + duration */
AESKey * p_key;
};
/* This struct stores the most important information about the DCP */
......@@ -86,12 +93,13 @@ struct dcp_t
vector<PKL *> pkls;
AssetList *p_asset_list;
AESKeyList *p_key_list;
vector<info_reel> audio_reels;
vector<info_reel> video_reels;
dcp_t():
p_asset_list(NULL) {};
p_asset_list(NULL), p_key_list(NULL) {};
~dcp_t( ) {
vlc_delete_all(pkls);
......@@ -100,6 +108,10 @@ struct dcp_t
delete(p_asset_list);
}
if ( p_key_list != NULL ) {
vlc_delete_all(*p_key_list);
delete(p_key_list);
}
}
};
......@@ -117,6 +129,9 @@ public:
virtual int Parse() = 0;
static int ReadNextNode( xml_reader_t *p_xmlReader, string& s_node );
static int ReadEndNode( xml_reader_t *p_xmlReader, string s_node, int i_type, string &s_value );
bool IsCPL() { return type == XML_CPL; }
protected:
demux_t *p_demux;
......@@ -164,6 +179,7 @@ public:
else
this->s_annotation = this->s_annotation + "--" + p_string;
};
void setKeyId(string p_string) { this->s_key_id = p_string; };
void setPackingList(bool p_bool) { this->s_path = p_bool; };
void setEntryPoint(int i_val) { this->i_entry_point = i_val; };
void setDuration (int i_val) { this->i_duration = i_val; };
......@@ -172,6 +188,7 @@ public:
string getPath() const { return this->s_path; };
string getType() const { return this->s_type; };
string getOriginalFilename() const { return this->s_original_filename; };
string getKeyId() const { return this->s_key_id; }
int getEntryPoint() const { return this->i_entry_point; };
int getDuration() const { return this->i_duration; };
int getIntrinsicDuration() const { return this->i_intrisic_duration; };
......@@ -181,6 +198,8 @@ public:
int Parse( xml_reader_t *p_xmlReader, string node, int type);
int ParsePKL( xml_reader_t *p_xmlReader);
static AESKey * getAESKeyById( AESKeyList* , const string s_id );
// TODO: remove
void Dump();
......@@ -315,4 +334,76 @@ private:
int ParseAssetList (xml_reader_t *p_xmlReader, const string p_node, int p_type);
};
class KDM : public XmlFile {
public:
KDM( demux_t * p_demux, string s_path, dcp_t *_p_dcp )
: XmlFile( p_demux, s_path ), p_dcp(_p_dcp) {}
virtual int Parse();
private:
dcp_t *p_dcp;
int ParsePrivate( const string s_node, int i_type );
};
class AESKey
{
public:
AESKey( demux_t *demux ): p_demux( demux ) { }
virtual ~AESKey() {};
const string getKeyId() { return this->s_key_id; };
const unsigned char * getKey() { return this->ps_key; };
int Parse( xml_reader_t *p_xml_reader, string s_node, int i_type );
private:
demux_t *p_demux;
string s_key_id;
unsigned char ps_key[16];
int decryptRSA( string s_cipher_text_b64 );
int extractInfo( unsigned char * ps_plain_text, bool smpte );
};
class RSAKey
{
public:
RSAKey( demux_t *demux ):
priv_key( NULL ), p_demux( demux ) { }
virtual ~RSAKey() { gcry_sexp_release( priv_key ); }
/* some ASN.1 tags. */
enum
{
TAG_INTEGER = 2,
TAG_SEQUENCE = 16,
};
/* ASN.1 Parser object. */
struct tag_info
{
int class_; /* Object class. */
unsigned long tag; /* The tag of the object. */
unsigned long length; /* Length of the values. */
int nhdr; /* Length of the header (TL). */
unsigned int ndef:1; /* The object has an indefinite length. */
unsigned int cons:1; /* This is a constructed object. */
};
int setPath();
int readPEM();
int readDER( unsigned char const *ps_data_der, size_t length );
int parseTag( unsigned char const **buffer, size_t *buflen, struct tag_info *ti);
gcry_sexp_t priv_key;
private:
demux_t *p_demux;
string s_path;
};
#endif /* _DCPPARSER_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment