📄 mp4drm.cpp
字号:
\param drm input, DRM manager. \param conID input-output, content identifier. \param xmlDoc input, XML document. \param logger input-output, message logger. If constructor fails, it throws MPEG4DRMPluginException. */ AES128CBCOMAMPEG4SinfDRMEncryptor(IDRMEncManager* drm, std::string& conID, DRMPlugin::IXMLElement* xmlDoc, DRMLogger& logger): encryptor(0), contentID(), rightsHost(), silentHdr(), previewHdr(), contentURLHdr(), contentVerHdr(), contentLocHdr(), pTextLen(0) { if (xmlDoc == 0) { logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::ctor: zero XML file."); throw MPEG4DRMPluginException(); } encryptor = drm->CreateAES128CBCEnc(conID, xmlDoc, logger); if (encryptor == 0) { logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::ctor: zero encryptor."); throw MPEG4DRMPluginException(); } contentID = conID; try { rightsHost = xmlDoc->GetChildStrValue("RightsHostInfo"); } catch (XMLException) { delete encryptor; logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::ctor: missing data in XML file."); throw MPEG4DRMPluginException(); } try { silentHdr = xmlDoc->GetChildStrValue("SilentHeader"); } catch (XMLException) { } try { previewHdr = xmlDoc->GetChildStrValue("PreviewHeader"); } catch (XMLException) { } try { contentURLHdr = xmlDoc->GetChildStrValue("ContentURLHeader"); } catch (XMLException) { } try { contentVerHdr = xmlDoc->GetChildStrValue("ContentVersionHeader"); } catch (XMLException) { } try { contentLocHdr = xmlDoc->GetChildStrValue("ContentLocationHeader"); } catch (XMLException) { } } virtual ~AES128CBCOMAMPEG4SinfDRMEncryptor() { if (encryptor != 0) delete encryptor; } /*! \brief Encrypt sample sampleBuffer. Returns encrypted sample in encSampleData. \param sampleBuffer input, sample to be encrypted. \param sampleSize input, size of input sample. \param encSampleData output, encrypted sample. \param encSampleLen output, size of encrypted sample. \param logger input-output, message logger. \return Boolean indicating success or failure. In case of failure, logger's log will contain error message. */ virtual bool EncryptSample(ByteT* sampleBuffer, UInt32T sampleSize, ByteT** encSampleData, UInt32T* encSampleLen, DRMLogger& logger) { // Get next IV. ByteT* iv; UInt32T ivLen; if (encryptor->NextIV(&iv, &ivLen, logger) == false) { return false; } // Encrypt sample. ByteT* enc; UInt32T encLen; // Encrypt sample. if (encryptor->Encrypt(sampleBuffer, sampleSize, &enc, &encLen, logger) == false) { if (iv != NULL) { free(iv); } return false; } /* Allocate memory (1 byte for selective encryption + 1 for iv length + 1 for counter length + size of the IV + size of the encrypted block). */ *encSampleData = (ByteT*)malloc(3 + ivLen + encLen); if (*encSampleData == NULL) { if (iv != NULL) { free(iv); } if (enc != NULL) { free(enc); } logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::EncryptSample: memory allocation error."); return false; } *encSampleLen = 3 + ivLen + encLen; ByteT* tmp = *encSampleData; // Add AU header. // Selective encryption indicator. // *tmp++ = (contentInfo.GetSelectiveEncryption() == true? 0x80: 0); *tmp++ = 0x80; // Counter length. *tmp++ = 0; // IV length. *tmp++ = (ByteT)ivLen; memcpy(tmp, iv, ivLen); tmp += ivLen; memcpy(tmp, enc, encLen); if (iv != NULL) { free(iv); } if (enc != NULL) { free(enc); } pTextLen += sampleSize; return true; } /*! \brief Add drm information into sinf atom. Caller must take care that given sinf atom really coresponds to sample description atom which refers to encrypted samples. \param originalFormat input, 4CC code of the original data format. \param sinf input-output, sinf atom where to add drm information. \param logger input-output, message logger. \return Boolean indicating success or failure. In case of failure, logger's log will contain error message. */ virtual bool Finish(UInt32T originalFormat, MP4Atom* sinf, DRMLogger& logger) { MP4Atom* frma = sinf->FindChildAtom("frma"); if (frma == 0) { logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::Finish: no original format atom."); return false; } MP4Property* data_format = 0; frma->FindProperty("frma.data-format", &data_format, 0); if (data_format == 0) { logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::Finish: frma->SetDataFormat() error."); return false; } ((MP4Integer32Property*)data_format)->SetValue(originalFormat); MP4Atom* schm = sinf->CreateAtom("schm"); if (schm == 0) { logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::Finish: could not create scheme type atom."); return false; } sinf->AddChildAtom(schm); schm->Generate(); MP4Property* scheme_type = 0; schm->FindProperty("schm.scheme_type", &scheme_type, 0); if (scheme_type == 0) { logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::Finish: schm->SetSchemeCode() error."); return false; } ((MP4Integer32Property*)scheme_type)->SetValue(('o' << 24) | ('d' << 16) | ('k' << 8) | 'm'); MP4Property* scheme_version = 0; schm->FindProperty("schm.scheme_version", &scheme_version, 0); if (scheme_version == 0) { logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::Finish: schm->SetSchemeVersion() error."); return false; } ((MP4Integer32Property*)scheme_version)->SetValue(0x0200); MP4Atom* schi = sinf->CreateAtom("schi"); if (schi == 0) { logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::Finish: could not create scheme information atom."); return false; } sinf->AddChildAtom(schi); schi->Generate(); MP4Atom* odkm = schi->CreateAtom("odkm"); if (odkm == 0) { logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::Finish: could not create OMA drm atom."); return false; } schi->AddChildAtom(odkm); odkm->Generate(); MP4Atom* ohdr = odkm->FindChildAtom("ohdr"); if (ohdr == 0) { logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::Finish: could not create OMA drm headers atom."); return false; } MP4Property* version = 0; ohdr->FindProperty("ohdr.version", &version, 0); if (version == 0) { logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::Finish: ohdr->SetAtomVersion() error."); return false; } ((MP4Integer8Property*)version)->SetValue(0); MP4Property* flags = 0; ohdr->FindProperty("ohdr.flags", &flags, 0); if (flags == 0) { logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::Finish: ohdr->SetAtomFlags() error."); return false; } ((MP4Integer24Property*)flags)->SetValue(0); MP4Property* EncryptionMethod = 0; ohdr->FindProperty("ohdr.EncryptionMethod", &EncryptionMethod, 0); if (EncryptionMethod == 0) { logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::Finish: ohdr->SetEncryptionMethod() error."); return false; } ((MP4Integer8Property*)EncryptionMethod)->SetValue(1); MP4Property* EncryptionPadding = 0; ohdr->FindProperty("ohdr.EncryptionPadding", &EncryptionPadding, 0); if (EncryptionPadding == 0) { logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::Finish: ohdr->SetEncryptionPadding() error."); return false; } ((MP4Integer8Property*)EncryptionPadding)->SetValue(1); MP4Property* PlaintextLength = 0; ohdr->FindProperty("ohdr.PlaintextLength", &PlaintextLength, 0); if (PlaintextLength == 0) { logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::Finish: ohdr->SetPlaintextLength() error."); return false; } ((MP4Integer64Property*)PlaintextLength)->SetValue(pTextLen); MP4Property* ContentID = 0; ohdr->FindProperty("ohdr.ContentID", &ContentID, 0); if (ContentID == 0) { logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::Finish: ohdr->SetContentIdentifier() error."); return false; } ((MP4StringProperty*)ContentID)->SetFixedLength(strlen(contentID.data())); ((MP4StringProperty*)ContentID)->SetValue(contentID.data()); MP4Property* ContentIDLength = 0; ohdr->FindProperty("ohdr.ContentIDLength", &ContentIDLength, 0); if (ContentIDLength == 0) { logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::Finish: ohdr->SetContentIdentifier() error."); return false; } ((MP4Integer16Property*)ContentIDLength)->SetValue(strlen(contentID.data())); MP4Property* RightsIssuerURL = 0; ohdr->FindProperty("ohdr.RightsIssuerURL", &RightsIssuerURL, 0); if (RightsIssuerURL == 0) { logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::Finish: ohdr->SetRightsIssuerURL() error."); return false; } ((MP4StringProperty*)RightsIssuerURL)->SetFixedLength(strlen(rightsHost.data())); ((MP4StringProperty*)RightsIssuerURL)->SetValue(rightsHost.data()); MP4Property* RightsIssuerURLLength = 0; ohdr->FindProperty("ohdr.RightsIssuerURLLength", &RightsIssuerURLLength, 0); if (RightsIssuerURLLength == 0) { logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::Finish: ohdr->SetRightsIssuerURL() error."); return false; } ((MP4Integer16Property*)RightsIssuerURLLength)->SetValue(strlen(rightsHost.data())); unsigned int len = 0; unsigned int tmpLen; tmpLen = silentHdr.size(); len += (tmpLen > 0? tmpLen + 1: 0); tmpLen = previewHdr.size(); len += (tmpLen > 0? tmpLen + 1: 0); tmpLen = contentURLHdr.size(); len += (tmpLen > 0? tmpLen + 1: 0); tmpLen = contentVerHdr.size(); len += (tmpLen > 0? tmpLen + 1: 0); tmpLen = contentLocHdr.size(); len += (tmpLen > 0? tmpLen + 1: 0); ByteT* pValue = (ByteT*)malloc(len); if (pValue == NULL) { logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::Finish: memory allocation error."); return false; } unsigned int pos = 0; tmpLen = silentHdr.size(); if (tmpLen > 0) { memcpy(pValue + pos, silentHdr.data(), tmpLen + 1); pos += (tmpLen + 1); } tmpLen = previewHdr.size(); if (tmpLen > 0) { memcpy(pValue + pos, previewHdr.data(), tmpLen + 1); pos += (tmpLen + 1); } tmpLen = contentURLHdr.size(); if (tmpLen > 0) { memcpy(pValue + pos, contentURLHdr.data(), tmpLen + 1); pos += (tmpLen + 1); } tmpLen = contentVerHdr.size(); if (tmpLen > 0) { memcpy(pValue + pos, contentVerHdr.data(), tmpLen + 1); pos += (tmpLen + 1); } tmpLen = contentLocHdr.size(); if (tmpLen > 0) { memcpy(pValue + pos, contentLocHdr.data(), tmpLen + 1); pos += (tmpLen + 1); } MP4Property* TextualHeaders = 0; ohdr->FindProperty("ohdr.TextualHeaders", &TextualHeaders, 0); if (TextualHeaders == 0) { logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::Finish: ohdr->SetTextualHeaders() error."); return false; } ((MP4BytesProperty*)TextualHeaders)->SetValue((u_int8_t*)pValue, len); MP4Property* TextualHeadersLength = 0; ohdr->FindProperty("ohdr.TextualHeadersLength", &TextualHeadersLength, 0); if (TextualHeadersLength == 0) { logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::Finish: ohdr->SetTextualHeaders() error."); return false; } ((MP4Integer16Property*)TextualHeadersLength)->SetValue(len); if (pValue != 0) { free(pValue); } odkm->FindProperty("odkm.version", &version, 0); if (version == 0) { logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::Finish: odkm->SetAtomVersion() error."); return false; } ((MP4Integer8Property*)version)->SetValue(0); odkm->FindProperty("odkm.flags", &flags, 0); if (flags == 0) { logger.UpdateLog("AES128CBCOMAMPEG4SinfDRMEncryptor::Finish: odkm->SetAtomFlags() error."); return false; } ((MP4Integer24Property*)flags)->SetValue(0); return true; }private: AES128CBCEncryptor* encryptor; std::string contentID; std::string rightsHost; std::string silentHdr; std::string previewHdr; std::string contentURLHdr; std::string contentVerHdr; std::string contentLocHdr; UInt64T pTextLen;};/*! \brief Encrypts MP4 data using AES128CTR encryptor according to OMA specifications with Sinf signalling. Encrypts samples and adds information for decryption to MP4 stream.*/class AES128CTROMAMPEG4SinfDRMEncryptor: public IMPEG4SinfDRMEncryptor {public: /*! \brief Constructor. Mandatory tags in the XML file are:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -