summaryrefslogtreecommitdiff
path: root/asdcplib/src/AS_DCP_MXF.cpp
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2016-01-16 15:58:56 +0000
committerCarl Hetherington <cth@carlh.net>2016-01-16 15:58:56 +0000
commite04eced93da1907e803c065a953ffe0d6540e1cb (patch)
treecab897dea7c1a50c141ff948ff21e401038d0c07 /asdcplib/src/AS_DCP_MXF.cpp
parent485794f8322b090a22da841961025b19642e42a2 (diff)
Use asdclib-cth rather than in-tree copy.
Diffstat (limited to 'asdcplib/src/AS_DCP_MXF.cpp')
-rwxr-xr-xasdcplib/src/AS_DCP_MXF.cpp542
1 files changed, 0 insertions, 542 deletions
diff --git a/asdcplib/src/AS_DCP_MXF.cpp b/asdcplib/src/AS_DCP_MXF.cpp
deleted file mode 100755
index da5232f..0000000
--- a/asdcplib/src/AS_DCP_MXF.cpp
+++ /dev/null
@@ -1,542 +0,0 @@
-/*
-Copyright (c) 2004-2009, John Hurst
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-3. The name of the author may not be used to endorse or promote products
- derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-/*! \file AS_DCP_MXF.cpp
- \version $Id: AS_DCP_MXF.cpp,v 1.31 2009/08/04 18:43:10 jhurst Exp $
- \brief AS-DCP library, misc classes and subroutines
-*/
-
-#include <KM_fileio.h>
-#include <KM_xml.h>
-#include "AS_DCP_internal.h"
-#include "JP2K.h"
-#include "MPEG.h"
-#include "Wav.h"
-#include <iostream>
-#include <iomanip>
-
-
-//------------------------------------------------------------------------------------------
-// misc subroutines
-
-
-//
-std::ostream&
-ASDCP::operator << (std::ostream& strm, const WriterInfo& Info)
-{
- char str_buf[40];
-
- strm << " ProductUUID: " << UUID(Info.ProductUUID).EncodeHex(str_buf, 40) << std::endl;
- strm << " ProductVersion: " << Info.ProductVersion << std::endl;
- strm << " CompanyName: " << Info.CompanyName << std::endl;
- strm << " ProductName: " << Info.ProductName << std::endl;
- strm << " EncryptedEssence: " << (Info.EncryptedEssence ? "Yes" : "No") << std::endl;
-
- if ( Info.EncryptedEssence )
- {
- strm << " HMAC: " << (Info.UsesHMAC ? "Yes" : "No") << std::endl;
- strm << " ContextID: " << UUID(Info.ContextID).EncodeHex(str_buf, 40) << std::endl;
- strm << "CryptographicKeyID: " << UUID(Info.CryptographicKeyID).EncodeHex(str_buf, 40) << std::endl;
- }
-
- strm << " AssetUUID: " << UUID(Info.AssetUUID).EncodeHex(str_buf, 40) << std::endl;
- strm << " Label Set Type: " << (Info.LabelSetType == LS_MXF_SMPTE ? "SMPTE" :
- (Info.LabelSetType == LS_MXF_INTEROP ? "MXF Interop" :
- "Unknown")) << std::endl;
- return strm;
-}
-
-//
-void
-ASDCP::WriterInfoDump(const WriterInfo& Info, FILE* stream)
-{
- if ( stream == 0 )
- stream = stderr;
-
- char str_buf[40];
-
- fprintf(stream," ProductUUID: %s\n", UUID(Info.ProductUUID).EncodeHex(str_buf, 40));
- fprintf(stream,"\
- ProductVersion: %s\n\
- CompanyName: %s\n\
- ProductName: %s\n\
- EncryptedEssence: %s\n",
- Info.ProductVersion.c_str(),
- Info.CompanyName.c_str(),
- Info.ProductName.c_str(),
- ( Info.EncryptedEssence ? "Yes" : "No" )
- );
-
- if ( Info.EncryptedEssence )
- {
- fprintf(stream, " HMAC: %s\n", ( Info.UsesHMAC ? "Yes" : "No"));
- fprintf(stream, " ContextID: %s\n", UUID(Info.ContextID).EncodeHex(str_buf, 40));
- fprintf(stream, "CryptographicKeyID: %s\n", UUID(Info.CryptographicKeyID).EncodeHex(str_buf, 40));
- }
-
- fprintf(stream," AssetUUID: %s\n", UUID(Info.AssetUUID).EncodeHex(str_buf, 40));
- fprintf(stream," Label Set Type: %s\n", ( Info.LabelSetType == LS_MXF_SMPTE ? "SMPTE" :
- ( Info.LabelSetType == LS_MXF_INTEROP ? "MXF Interop" :
- "Unknown" ) ));
-}
-
-//
-Result_t
-ASDCP::MD_to_WriterInfo(Identification* InfoObj, WriterInfo& Info)
-{
- ASDCP_TEST_NULL(InfoObj);
- char tmp_str[IdentBufferLen];
-
- Info.ProductName = "Unknown Product";
- Info.ProductVersion = "Unknown Version";
- Info.CompanyName = "Unknown Company";
- memset(Info.ProductUUID, 0, UUIDlen);
-
- InfoObj->ProductName.EncodeString(tmp_str, IdentBufferLen);
- if ( *tmp_str ) Info.ProductName = tmp_str;
-
- InfoObj->VersionString.EncodeString(tmp_str, IdentBufferLen);
- if ( *tmp_str ) Info.ProductVersion = tmp_str;
-
- InfoObj->CompanyName.EncodeString(tmp_str, IdentBufferLen);
- if ( *tmp_str ) Info.CompanyName = tmp_str;
-
- memcpy(Info.ProductUUID, InfoObj->ProductUID.Value(), UUIDlen);
-
- return RESULT_OK;
-}
-
-
-//
-Result_t
-ASDCP::MD_to_CryptoInfo(CryptographicContext* InfoObj, WriterInfo& Info, const Dictionary& Dict)
-{
- ASDCP_TEST_NULL(InfoObj);
-
- Info.EncryptedEssence = true;
- memcpy(Info.ContextID, InfoObj->ContextID.Value(), UUIDlen);
- memcpy(Info.CryptographicKeyID, InfoObj->CryptographicKeyID.Value(), UUIDlen);
-
- UL MIC_SHA1(Dict.ul(MDD_MICAlgorithm_HMAC_SHA1));
- UL MIC_NONE(Dict.ul(MDD_MICAlgorithm_NONE));
-
- if ( InfoObj->MICAlgorithm == MIC_SHA1 )
- Info.UsesHMAC = true;
-
- else if ( InfoObj->MICAlgorithm == MIC_NONE )
- Info.UsesHMAC = false;
-
- else
- {
- DefaultLogSink().Error("Unexpected MICAlgorithm UL.\n");
- return RESULT_FORMAT;
- }
-
- return RESULT_OK;
-}
-
-//
-//
-ASDCP::Result_t
-ASDCP::EssenceType(const char* filename, EssenceType_t& type)
-{
- const Dictionary* m_Dict = &DefaultCompositeDict();
- assert(m_Dict);
-
- ASDCP_TEST_NULL_STR(filename);
- Kumu::FileReader Reader;
- OPAtomHeader TestHeader(m_Dict);
-
- Result_t result = Reader.OpenRead(filename);
-
- if ( ASDCP_SUCCESS(result) )
- result = TestHeader.InitFromFile(Reader); // test UL and OP
-
- if ( ASDCP_SUCCESS(result) )
- {
- type = ESS_UNKNOWN;
- if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(RGBAEssenceDescriptor))) )
- {
- if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(StereoscopicPictureSubDescriptor))) )
- type = ESS_JPEG_2000_S;
- else
- type = ESS_JPEG_2000;
- }
- else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(WaveAudioDescriptor))) )
- type = ESS_PCM_24b_48k;
- else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(MPEG2VideoDescriptor))) )
- type = ESS_MPEG2_VES;
- else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(TimedTextDescriptor))) )
- type = ESS_TIMED_TEXT;
- }
-
- return result;
-}
-
-//
-ASDCP::Result_t
-ASDCP::RawEssenceType(const char* filename, EssenceType_t& type)
-{
- ASDCP_TEST_NULL_STR(filename);
- type = ESS_UNKNOWN;
- ASDCP::FrameBuffer FB;
- Kumu::FileReader Reader;
- ASDCP::Wav::SimpleWaveHeader WavHeader;
- ASDCP::AIFF::SimpleAIFFHeader AIFFHeader;
- Kumu::XMLElement TmpElement("Tmp");
-
- ui32_t data_offset;
- ui32_t read_count;
- Result_t result = FB.Capacity(Wav::MaxWavHeader); // using Wav max because everything else is much smaller
-
- if ( Kumu::PathIsFile(filename) )
- {
- result = Reader.OpenRead(filename);
-
- if ( ASDCP_SUCCESS(result) )
- {
- result = Reader.Read(FB.Data(), FB.Capacity(), &read_count);
- Reader.Close();
- }
-
- if ( ASDCP_SUCCESS(result) )
- {
- const byte_t* p = FB.RoData();
- FB.Size(read_count);
-
- ui32_t i = 0;
- while ( p[i] == 0 ) i++;
-
- if ( i > 1 && p[i] == 1 && (p[i+1] == ASDCP::MPEG2::SEQ_START || p[i+1] == ASDCP::MPEG2::PIC_START) )
- {
- type = ESS_MPEG2_VES;
- }
- else if ( memcmp(FB.RoData(), ASDCP::JP2K::Magic, sizeof(ASDCP::JP2K::Magic)) == 0 )
- {
- type = ESS_JPEG_2000;
- }
- else if ( ASDCP_SUCCESS(WavHeader.ReadFromBuffer(FB.RoData(), read_count, &data_offset)) )
- {
- switch ( WavHeader.samplespersec )
- {
- case 48000: type = ESS_PCM_24b_48k; break;
- case 96000: type = ESS_PCM_24b_96k; break;
- default:
- return RESULT_FORMAT;
- }
- }
- else if ( ASDCP_SUCCESS(AIFFHeader.ReadFromBuffer(FB.RoData(), read_count, &data_offset)) )
- {
- type = ESS_PCM_24b_48k;
- }
- else if ( Kumu::StringIsXML((const char*)FB.RoData(), FB.Size()) )
- {
- type = ESS_TIMED_TEXT;
- }
- }
- }
- else if ( Kumu::PathIsDirectory(filename) )
- {
- char next_file[Kumu::MaxFilePath];
- Kumu::DirScanner Scanner;
- Result_t result = Scanner.Open(filename);
-
- if ( ASDCP_SUCCESS(result) )
- {
- while ( ASDCP_SUCCESS(Scanner.GetNext(next_file)) )
- {
- if ( next_file[0] == '.' ) // no hidden files or internal links
- continue;
-
- std::string Str(filename);
- Str += "/";
- Str += next_file;
- result = Reader.OpenRead(Str.c_str());
-
- if ( ASDCP_SUCCESS(result) )
- {
- result = Reader.Read(FB.Data(), FB.Capacity(), &read_count);
- Reader.Close();
- }
-
- if ( ASDCP_SUCCESS(result) )
- {
- if ( memcmp(FB.RoData(), ASDCP::JP2K::Magic, sizeof(ASDCP::JP2K::Magic)) == 0 )
- {
- type = ESS_JPEG_2000;
- }
- else if ( ASDCP_SUCCESS(WavHeader.ReadFromBuffer(FB.RoData(), read_count, &data_offset)) )
- {
- switch ( WavHeader.samplespersec )
- {
- case 48000: type = ESS_PCM_24b_48k; break;
- case 96000: type = ESS_PCM_24b_96k; break;
- default:
- return RESULT_FORMAT;
- }
- }
- }
-
- break;
- }
- }
- }
-
- return result;
-}
-
-//
-Result_t
-ASDCP::EncryptFrameBuffer(const ASDCP::FrameBuffer& FBin, ASDCP::FrameBuffer& FBout, AESEncContext* Ctx)
-{
- ASDCP_TEST_NULL(Ctx);
- FBout.Size(0);
-
- // size the buffer
- Result_t result = FBout.Capacity(calc_esv_length(FBin.Size(), FBin.PlaintextOffset()));
-
- // write the IV
- byte_t* p = FBout.Data();
-
- // write the IV to the frame buffer
- Ctx->GetIVec(p);
- p += CBC_BLOCK_SIZE;
-
-
- // encrypt the check value to the frame buffer
- if ( ASDCP_SUCCESS(result) )
- {
- result = Ctx->EncryptBlock(ESV_CheckValue, p, CBC_BLOCK_SIZE);
- p += CBC_BLOCK_SIZE;
- }
-
- // write optional plaintext region
- if ( FBin.PlaintextOffset() > 0 )
- {
- assert(FBin.PlaintextOffset() <= FBin.Size());
- memcpy(p, FBin.RoData(), FBin.PlaintextOffset());
- p += FBin.PlaintextOffset();
- }
-
- ui32_t ct_size = FBin.Size() - FBin.PlaintextOffset();
- ui32_t diff = ct_size % CBC_BLOCK_SIZE;
- ui32_t block_size = ct_size - diff;
- assert((block_size % CBC_BLOCK_SIZE) == 0);
-
- // encrypt the ciphertext region essence data
- if ( ASDCP_SUCCESS(result) )
- {
- result = Ctx->EncryptBlock(FBin.RoData() + FBin.PlaintextOffset(), p, block_size);
- p += block_size;
- }
-
- // construct and encrypt the padding
- if ( ASDCP_SUCCESS(result) )
- {
- byte_t the_last_block[CBC_BLOCK_SIZE];
-
- if ( diff > 0 )
- memcpy(the_last_block, FBin.RoData() + FBin.PlaintextOffset() + block_size, diff);
-
- for (ui32_t i = 0; diff < CBC_BLOCK_SIZE; diff++, i++ )
- the_last_block[diff] = i;
-
- result = Ctx->EncryptBlock(the_last_block, p, CBC_BLOCK_SIZE);
- }
-
- if ( ASDCP_SUCCESS(result) )
- FBout.Size(calc_esv_length(FBin.Size(), FBin.PlaintextOffset()));
-
- return result;
-}
-
-//
-Result_t
-ASDCP::DecryptFrameBuffer(const ASDCP::FrameBuffer& FBin, ASDCP::FrameBuffer& FBout, AESDecContext* Ctx)
-{
- ASDCP_TEST_NULL(Ctx);
- assert(FBout.Capacity() >= FBin.SourceLength());
-
- ui32_t ct_size = FBin.SourceLength() - FBin.PlaintextOffset();
- ui32_t diff = ct_size % CBC_BLOCK_SIZE;
- ui32_t block_size = ct_size - diff;
- assert(block_size);
- assert((block_size % CBC_BLOCK_SIZE) == 0);
-
- const byte_t* buf = FBin.RoData();
-
- // get ivec
- Ctx->SetIVec(buf);
- buf += CBC_BLOCK_SIZE;
-
- // decrypt and test check value
- byte_t CheckValue[CBC_BLOCK_SIZE];
- Result_t result = Ctx->DecryptBlock(buf, CheckValue, CBC_BLOCK_SIZE);
- buf += CBC_BLOCK_SIZE;
-
- if ( memcmp(CheckValue, ESV_CheckValue, CBC_BLOCK_SIZE) != 0 )
- return RESULT_CHECKFAIL;
-
- // copy plaintext region
- if ( FBin.PlaintextOffset() > 0 )
- {
- memcpy(FBout.Data(), buf, FBin.PlaintextOffset());
- buf += FBin.PlaintextOffset();
- }
-
- // decrypt all but last block
- if ( ASDCP_SUCCESS(result) )
- {
- result = Ctx->DecryptBlock(buf, FBout.Data() + FBin.PlaintextOffset(), block_size);
- buf += block_size;
- }
-
- // decrypt last block
- if ( ASDCP_SUCCESS(result) )
- {
- byte_t the_last_block[CBC_BLOCK_SIZE];
- result = Ctx->DecryptBlock(buf, the_last_block, CBC_BLOCK_SIZE);
-
- if ( the_last_block[diff] != 0 )
- {
- DefaultLogSink().Error("Unexpected non-zero padding value.\n");
- return RESULT_FORMAT;
- }
-
- if ( diff > 0 )
- memcpy(FBout.Data() + FBin.PlaintextOffset() + block_size, the_last_block, diff);
- }
-
- if ( ASDCP_SUCCESS(result) )
- FBout.Size(FBin.SourceLength());
-
- return result;
-}
-
-
-//
-Result_t
-ASDCP::IntegrityPack::CalcValues(const ASDCP::FrameBuffer& FB, byte_t* AssetID,
- ui32_t sequence, HMACContext* HMAC)
-{
- ASDCP_TEST_NULL(AssetID);
- ASDCP_TEST_NULL(HMAC);
- byte_t* p = Data;
- HMAC->Reset();
-
- static byte_t ber_4[MXF_BER_LENGTH] = {0x83, 0, 0, 0};
-
- // update HMAC with essence data
- HMAC->Update(FB.RoData(), FB.Size());
-
- // track file ID length
- memcpy(p, ber_4, MXF_BER_LENGTH);
- *(p+3) = UUIDlen;;
- p += MXF_BER_LENGTH;
-
- // track file ID
- memcpy(p, AssetID, UUIDlen);
- p += UUIDlen;
-
- // sequence length
- memcpy(p, ber_4, MXF_BER_LENGTH);
- *(p+3) = sizeof(ui64_t);
- p += MXF_BER_LENGTH;
-
- // sequence number
- Kumu::i2p<ui64_t>(KM_i64_BE(sequence), p);
- p += sizeof(ui64_t);
-
- // HMAC length
- memcpy(p, ber_4, MXF_BER_LENGTH);
- *(p+3) = HMAC_SIZE;
- p += MXF_BER_LENGTH;
-
- // update HMAC with intpack values
- HMAC->Update(Data, klv_intpack_size - HMAC_SIZE);
-
- // finish & write HMAC
- HMAC->Finalize();
- HMAC->GetHMACValue(p);
-
- assert(p + HMAC_SIZE == Data + klv_intpack_size);
-
- return RESULT_OK;
-}
-
-
-Result_t
-ASDCP::IntegrityPack::TestValues(const ASDCP::FrameBuffer& FB, byte_t* AssetID,
- ui32_t sequence, HMACContext* HMAC)
-{
- ASDCP_TEST_NULL(AssetID);
- ASDCP_TEST_NULL(HMAC);
-
- // find the start of the intpack
- byte_t* p = (byte_t*)FB.RoData() + ( FB.Size() - klv_intpack_size );
-
- // test the AssetID length
- if ( ! Kumu::read_test_BER(&p, UUIDlen) )
- return RESULT_HMACFAIL;
-
- // test the AssetID
- if ( memcmp(p, AssetID, UUIDlen) != 0 )
- {
- DefaultLogSink().Error("IntegrityPack failure: AssetID mismatch.\n");
- return RESULT_HMACFAIL;
- }
- p += UUIDlen;
-
- // test the sequence length
- if ( ! Kumu::read_test_BER(&p, sizeof(ui64_t)) )
- return RESULT_HMACFAIL;
-
- ui32_t test_sequence = (ui32_t)KM_i64_BE(Kumu::cp2i<ui64_t>(p));
-
- // test the sequence value
- if ( test_sequence != sequence )
- {
- DefaultLogSink().Error("IntegrityPack failure: sequence is %u, expecting %u.\n", test_sequence, sequence);
- return RESULT_HMACFAIL;
- }
-
- p += sizeof(ui64_t);
-
- // test the HMAC length
- if ( ! Kumu::read_test_BER(&p, HMAC_SIZE) )
- return RESULT_HMACFAIL;
-
- // test the HMAC
- HMAC->Reset();
- HMAC->Update(FB.RoData(), FB.Size() - HMAC_SIZE);
- HMAC->Finalize();
-
- return HMAC->TestHMACValue(p);
-}
-
-//
-// end AS_DCP_MXF.cpp
-//