Skip to content
Snippets Groups Projects
Commit a726ac41 authored by François Cartegnie's avatar François Cartegnie :fingers_crossed:
Browse files

demux: adaptive: move decryption to base classes

parent 4e6e6ce0
No related branches found
No related tags found
No related merge requests found
......@@ -23,6 +23,8 @@
#endif
#include "CommonEncryption.hpp"
#include "Keyring.hpp"
#include "../SharedResources.hpp"
#include <vlc_common.h>
......@@ -44,12 +46,13 @@ CommonEncryptionSession::CommonEncryptionSession()
ctx = NULL;
}
CommonEncryptionSession::~CommonEncryptionSession()
{
close();
}
bool CommonEncryptionSession::start(const CommonEncryption &enc)
bool CommonEncryptionSession::start(SharedResources *res, const CommonEncryption &enc)
{
if(ctx)
close();
......@@ -57,11 +60,18 @@ bool CommonEncryptionSession::start(const CommonEncryption &enc)
#ifdef HAVE_GCRYPT
if(encryption.method == CommonEncryption::Method::AES_128)
{
if(key.empty())
{
if(!encryption.uri.empty())
key = res->getKeyring()->getKey(res->getAuthStorage(), encryption.uri);
if(key.size() != 16)
return false;
}
vlc_gcrypt_init();
gcry_cipher_hd_t handle;
if( gcry_cipher_open(&handle, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0) ||
encryption.key.size() != 16 ||
gcry_cipher_setkey(handle, &encryption.key[0], 16) ||
gcry_cipher_setkey(handle, &key[0], 16) ||
gcry_cipher_setiv(handle, &encryption.iv[0], 16) )
{
gcry_cipher_close(handle);
......
......@@ -21,9 +21,12 @@
#define COMMONENCRYPTION_H
#include <vector>
#include <string>
namespace adaptive
{
class SharedResources;
namespace encryption
{
class CommonEncryption
......@@ -36,7 +39,7 @@ namespace adaptive
AES_128,
AES_SAMPLE,
} method;
std::vector<unsigned char> key;
std::string uri;
std::vector<unsigned char> iv;
};
......@@ -46,11 +49,12 @@ namespace adaptive
CommonEncryptionSession();
~CommonEncryptionSession();
bool start(const CommonEncryption &);
bool start(SharedResources *, const CommonEncryption &);
void close();
size_t decrypt(void *, size_t, bool);
private:
std::vector<unsigned char> key;
CommonEncryption encryption;
void *ctx;
};
......
......@@ -53,6 +53,7 @@ KeyringKey Keyring::getKey(AuthStorage *auth, const std::string &uri)
if(it == keys.end())
{
/* Pretty bad inside the lock */
msg_Dbg(obj, "Retrieving AES key %s", uri.c_str());
block_t *p_block = Retrieve::HTTP(obj, auth, uri);
if(p_block)
{
......
......@@ -67,7 +67,22 @@ void ISegment::onChunkDownload(block_t **, SegmentChunk *, BaseRepresentation *)
}
SegmentChunk* ISegment::toChunk(SharedResources *, AbstractConnectionManager *connManager,
bool ISegment::prepareChunk(SharedResources *res, SegmentChunk *chunk, BaseRepresentation *)
{
if(encryption.method != CommonEncryption::Method::NONE)
{
CommonEncryptionSession *encryptionSession = new CommonEncryptionSession();
if(!encryptionSession->start(res, encryption))
{
delete encryptionSession;
return false;
}
chunk->setEncryptionSession(encryptionSession);
}
return true;
}
SegmentChunk* ISegment::toChunk(SharedResources *res, AbstractConnectionManager *connManager,
size_t index, BaseRepresentation *rep)
{
const std::string url = getUrlSegment().toString(index, rep);
......@@ -79,8 +94,13 @@ SegmentChunk* ISegment::toChunk(SharedResources *, AbstractConnectionManager *co
source->setBytesRange(BytesRange(startByte, endByte));
SegmentChunk *chunk = new (std::nothrow) SegmentChunk(this, source, rep);
if( chunk )
if(chunk)
{
if(!prepareChunk(res, chunk, rep))
{
delete chunk;
return NULL;
}
connManager->start(source);
return chunk;
}
......@@ -163,6 +183,11 @@ int ISegment::compare(ISegment *other) const
return 0;
}
void ISegment::setEncryption(CommonEncryption &e)
{
encryption = e;
}
int ISegment::getClassId() const
{
return classId;
......
......@@ -30,6 +30,7 @@
#include <vector>
#include "ICanonicalUrl.hpp"
#include "../http/Chunk.h"
#include "../encryption/CommonEncryption.hpp"
#include "../tools/Properties.hpp"
#include "Time.hpp"
......@@ -49,6 +50,7 @@ namespace adaptive
class SegmentChunk;
using namespace http;
using namespace encryption;
class ISegment : public ICanonicalUrl
{
......@@ -72,6 +74,7 @@ namespace adaptive
virtual void debug (vlc_object_t *,int = 0) const;
virtual bool contains (size_t byte) const;
virtual int compare (ISegment *) const;
void setEncryption (CommonEncryption &);
int getClassId () const;
Property<stime_t> startTime;
Property<stime_t> duration;
......@@ -80,9 +83,15 @@ namespace adaptive
static const int CLASSID_ISEGMENT = 0;
/* callbacks */
virtual void onChunkDownload (block_t **, SegmentChunk *, BaseRepresentation *);
virtual void onChunkDownload (block_t **,
SegmentChunk *,
BaseRepresentation *);
protected:
virtual bool prepareChunk (SharedResources *,
SegmentChunk *,
BaseRepresentation *);
CommonEncryption encryption;
size_t startByte;
size_t endByte;
std::string debugName;
......
......@@ -24,9 +24,14 @@
#include "SegmentChunk.hpp"
#include "Segment.h"
#include "BaseRepresentation.h"
#include "../encryption/CommonEncryption.hpp"
#include <vlc_block.h>
#include <cassert>
using namespace adaptive::playlist;
using namespace adaptive::encryption;
using namespace adaptive;
SegmentChunk::SegmentChunk(ISegment *segment_, AbstractChunkSource *source,
......@@ -37,16 +42,35 @@ SegmentChunk::SegmentChunk(ISegment *segment_, AbstractChunkSource *source,
segment->chunksuse.Set(segment->chunksuse.Get() + 1);
rep = rep_;
discontinuity = segment_->discontinuity;
encryptionSession = NULL;
}
SegmentChunk::~SegmentChunk()
{
assert(segment->chunksuse.Get() > 0);
segment->chunksuse.Set(segment->chunksuse.Get() - 1);
delete encryptionSession;
}
bool SegmentChunk::decrypt(block_t **pp_block)
{
block_t *p_block = *pp_block;
if(encryptionSession)
{
bool b_last = isEmpty();
p_block->i_buffer = encryptionSession->decrypt(p_block->p_buffer,
p_block->i_buffer, b_last);
if(b_last)
encryptionSession->close();
}
return true;
}
void SegmentChunk::onDownload(block_t **pp_block)
{
decrypt(pp_block);
segment->onChunkDownload(pp_block, this, rep);
}
......@@ -58,3 +82,8 @@ StreamFormat SegmentChunk::getStreamFormat() const
return StreamFormat();
}
void SegmentChunk::setEncryptionSession(CommonEncryptionSession *s)
{
delete encryptionSession;
encryptionSession = s;
}
......@@ -27,10 +27,15 @@
namespace adaptive
{
namespace encryption
{
class CommonEncryptionSession;
}
namespace playlist
{
using namespace http;
using namespace encryption;
class BaseRepresentation;
class ISegment;
......@@ -40,13 +45,16 @@ namespace adaptive
public:
SegmentChunk(ISegment *segment, AbstractChunkSource *, BaseRepresentation *);
virtual ~SegmentChunk();
void setEncryptionSession(CommonEncryptionSession *);
StreamFormat getStreamFormat() const;
bool discontinuity;
protected:
bool decrypt(block_t **);
virtual void onDownload(block_t **); // reimpl
ISegment *segment;
BaseRepresentation *rep;
CommonEncryptionSession *encryptionSession;
};
}
......
......@@ -24,10 +24,7 @@
#include "HLSSegment.hpp"
#include "../adaptive/playlist/SegmentChunk.hpp"
#include "../adaptive/playlist/BaseRepresentation.h"
#include "../adaptive/encryption/CommonEncryption.hpp"
#include <vlc_common.h>
#include <vlc_block.h>
using namespace hls::playlist;
......@@ -42,47 +39,23 @@ HLSSegment::~HLSSegment()
{
}
void HLSSegment::onChunkDownload(block_t **pp_block, SegmentChunk *chunk, BaseRepresentation *)
bool HLSSegment::prepareChunk(SharedResources *res, SegmentChunk *chunk, BaseRepresentation *rep)
{
block_t *p_block = *pp_block;
#ifndef HAVE_GCRYPT
(void)chunk;
#else
if(encryption.method == CommonEncryption::Method::AES_128)
{
if (encryption.iv.size() != 16)
{
uint64_t sequence = getSequenceNumber() - Segment::SEQUENCE_FIRST;
encryption.iv.clear();
encryption.iv.resize(16);
encryption.iv[15] = (getSequenceNumber() - Segment::SEQUENCE_FIRST) & 0xff;
encryption.iv[14] = ((getSequenceNumber() - Segment::SEQUENCE_FIRST) >> 8)& 0xff;
encryption.iv[13] = ((getSequenceNumber() - Segment::SEQUENCE_FIRST) >> 16)& 0xff;
encryption.iv[12] = ((getSequenceNumber() - Segment::SEQUENCE_FIRST) >> 24)& 0xff;
}
block_t *p_block = *pp_block;
/* first bytes */
if(chunk->getBytesRead() == p_block->i_buffer)
{
if(!encryptSession.start(encryption))
{
p_block->i_buffer = 0;
return;
}
encryption.iv[15] = (sequence >> 0) & 0xff;
encryption.iv[14] = (sequence >> 8) & 0xff;
encryption.iv[13] = (sequence >> 16) & 0xff;
encryption.iv[12] = (sequence >> 24) & 0xff;
}
bool b_last = chunk->isEmpty();
p_block->i_buffer = encryptSession.decrypt(p_block->p_buffer, p_block->i_buffer, b_last);
if(b_last)
encryptSession.close();
}
else
#endif
if(encryption.method != CommonEncryption::Method::NONE)
{
p_block->i_buffer = 0;
}
return Segment::prepareChunk(res, chunk, rep);
}
vlc_tick_t HLSSegment::getUTCTime() const
......@@ -90,11 +63,6 @@ vlc_tick_t HLSSegment::getUTCTime() const
return utcTime;
}
void HLSSegment::setEncryption(CommonEncryption &enc)
{
encryption = enc;
}
int HLSSegment::compare(ISegment *segment) const
{
HLSSegment *hlssegment = dynamic_cast<HLSSegment *>(segment);
......
......@@ -27,6 +27,7 @@ namespace hls
{
namespace playlist
{
using namespace adaptive;
using namespace adaptive::playlist;
using namespace adaptive::encryption;
......@@ -37,16 +38,13 @@ namespace hls
public:
HLSSegment( ICanonicalUrl *parent, uint64_t sequence );
virtual ~HLSSegment();
void setEncryption(CommonEncryption &);
vlc_tick_t getUTCTime() const;
virtual int compare(ISegment *) const; /* reimpl */
protected:
vlc_tick_t utcTime;
virtual void onChunkDownload(block_t **, SegmentChunk *, BaseRepresentation *); /* reimpl */
CommonEncryption encryption;
CommonEncryptionSession encryptSession;
virtual bool prepareChunk(SharedResources *, SegmentChunk *,
BaseRepresentation *); /* reimpl */
};
}
}
......
......@@ -316,7 +316,7 @@ void M3U8Parser::parseSegments(vlc_object_t *, Representation *rep, const std::l
keytag->getAttributeByName("URI") )
{
encryption.method = CommonEncryption::Method::AES_128;
encryption.key.clear();
encryption.uri.clear();
Url keyurl(keytag->getAttributeByName("URI")->quotedString());
if(!keyurl.hasScheme())
......@@ -324,11 +324,8 @@ void M3U8Parser::parseSegments(vlc_object_t *, Representation *rep, const std::l
keyurl.prepend(Helper::getDirectoryPath(rep->getPlaylistUrl().toString()).append("/"));
}
M3U8 *m3u8 = dynamic_cast<M3U8 *>(rep->getPlaylist());
if(likely(m3u8))
encryption.key = resources->getKeyring()->getKey(
resources->getAuthStorage(),
keyurl.toString());
encryption.uri = keyurl.toString();
if(keytag->getAttributeByName("IV"))
{
encryption.iv.clear();
......@@ -339,7 +336,7 @@ void M3U8Parser::parseSegments(vlc_object_t *, Representation *rep, const std::l
{
/* unsupported or invalid */
encryption.method = CommonEncryption::Method::NONE;
encryption.key.clear();
encryption.uri.clear();
encryption.iv.clear();
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment