omadrm/drmengine/dm/src/Oma1DcfCreator.cpp
author hgs
Thu, 14 Oct 2010 13:45:23 +0300
changeset 84 b09186059647
parent 23 493788a4a8a4
permissions -rw-r--r--
201039_02

/*
* Copyright (c) 2002-2010 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:  Implementation of the DRM access functions that are available
*                to authenticated clients.
*
*/


// INCLUDE FILES

#include <e32base.h>
#include <e32std.h>
#include <e32math.h>
#include <e32test.h>
#include <f32file.h>
#include <s32file.h>
#include <s32mem.h>
#include <apmstd.h>
#include <symmetric.h>
#include "Oma1DcfCreator.h"
#include "DRMRightsClient.h"
#include "DrmPermission.h"
#include "DrmConstraint.h"
#include "DRMCommon.h"
#include "DrmKeyStorage.h"


// EXTERNAL DATA STRUCTURES

// EXTERNAL FUNCTION PROTOTYPES

// CONSTANTS

static const TInt KMaxEncryptionSize = 2048;

// MACROS

// LOCAL CONSTANTS AND MACROS

_LIT8(KLDContentURI, "ldf:31415926535@localhost");
_LIT8(KLDFHeader, "Encryption-Method:AES128CBC;padding=RFC2630\x0d\x0a");

// ============================= LOCAL FUNCTIONS ===============================

// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// COma1DcfCreator::COma1DcfCreator
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
EXPORT_C COma1DcfCreator::COma1DcfCreator(void)
    {
    iEncryptionStream = NULL;
    iEncryptionBuffer = NULL;
    }

// -----------------------------------------------------------------------------
// COma1DcfCreator::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
EXPORT_C void COma1DcfCreator::ConstructL()
    {
    iEncryptionBuffer = HBufC8::NewL(KMaxEncryptionSize);
    }

// -----------------------------------------------------------------------------
// COma1DcfCreator::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
EXPORT_C COma1DcfCreator* COma1DcfCreator::NewL()
    {
    COma1DcfCreator* self = new (ELeave) COma1DcfCreator();
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop();

    return self;
    }


// Destructor
EXPORT_C COma1DcfCreator::~COma1DcfCreator()
    {
    delete iEncryptionBuffer;
    iRdb.Close();
    }

// ================= MEMBER FUNCTIONS =======================

// -----------------------------------------------------------------------------
// COma1DcfCreator::
//
// -----------------------------------------------------------------------------
EXPORT_C void COma1DcfCreator::EncryptInitializeL(
    RWriteStream& anOutput,
    const TDesC8& aMIMEType,
    CDRMRights* aRightsObject)
    {
    const TUint KVersion = 1;
    CDRMPermission *rights = CDRMPermission::NewLC();
    TInt err = 0;
    TDRMUniqueID id = 0;
    TBuf8<KDCFKeySize> key;
    TPtrC8 uri(0, 0);

    User::LeaveIfError(iRdb.Connect());
    iBytesWritten = 0;

    // generate rights
    if (aRightsObject)
        {
        uri.Set(aRightsObject->GetAsset().iUid->Des());
        err = iRdb.InitializeKey(uri);
        if (err == KErrCANoRights)
            {
            key.SetLength(KDCFKeySize);
            iRdb.GetRandomDataL(key);
            User::LeaveIfError(iRdb.AddRecord(key, aRightsObject->GetPermission(),
                uri, id));
            User::LeaveIfError(iRdb.InitializeKey(uri));
            }
        else
            {
            User::LeaveIfError(err);
            }
        }
    else
        {
        uri.Set(KLDContentURI);
        err = iRdb.InitializeKey(uri);
        if (err == KErrCANoRights)
            {
            rights->iAvailableRights = ERightsAll;
            rights->iTopLevel->iActiveConstraints = EConstraintNone;
            rights->iPlay->iActiveConstraints = EConstraintNone;
            rights->iDisplay->iActiveConstraints = EConstraintNone;
            rights->iPrint->iActiveConstraints = EConstraintNone;
            rights->iExecute->iActiveConstraints = EConstraintNone;
            rights->iUniqueID = 0;
            key.SetLength(KDCFKeySize);
            iRdb.GetRandomDataL(key);
            User::LeaveIfError(iRdb.AddRecord(key, *rights, uri, id));
            User::LeaveIfError(iRdb.InitializeKey(uri));
            }
        else
            {
            User::LeaveIfError(err);
            }
        }

    iIv.SetLength(KDCFKeySize);
    iRdb.GetRandomDataL(iIv);

    iEncryptionStream = &anOutput;

    anOutput.WriteUint8L(KVersion);
    anOutput.WriteUint8L(aMIMEType.Length());
    anOutput.WriteUint8L(uri.Length());
    anOutput.WriteL(aMIMEType);
    anOutput.WriteL(uri);
    anOutput.WriteUint8L(KLDFHeader().Size());
    anOutput.WriteUint8L(0);
    anOutput.WriteL(KLDFHeader);
    anOutput.WriteL(iIv);
    anOutput.CommitL();
    iBytesWritten += 3 + aMIMEType.Size() + 2 + KLDFHeader().Size() +
        iIv.Size();

    CleanupStack::PopAndDestroy(); // rights
    }

// -----------------------------------------------------------------------------
// COma1DcfCreator::EncryptUpdateL
// update the encryption
// -----------------------------------------------------------------------------
EXPORT_C void COma1DcfCreator::EncryptUpdateL(const TDesC8& aMessageData)
    {
    TInt i;
    TInt n;
    TInt size;
    TPtr8 ptr(iEncryptionBuffer->Des());
    TPtrC8 data;

    data.Set(aMessageData);
    if (iRemainder.Size() > 0 && iRemainder.Size() + data.Size() >= KDCFKeySize)
        {
        ptr.Copy(iRemainder);
        n = Min(KDCFKeySize - iRemainder.Size(), data.Size());
        ptr.Append(data.Left(n));
        iRdb.Encrypt(iIv, ptr);
        iEncryptionStream->WriteL(ptr);
        iBytesWritten += ptr.Size();
        iIv.Copy(ptr.Right(KDCFKeySize));
        data.Set(data.Right(data.Size() - n));
        iRemainder.SetLength(0);
        }

    size = data.Size();
    for (i = 0; size > KDCFKeySize; i += KMaxEncryptionSize)
        {
        n = Min(KMaxEncryptionSize, ((size / KDCFKeySize) * KDCFKeySize));
        ptr.Copy(data.Mid(i, n));
        iRdb.Encrypt(iIv, ptr);
        iEncryptionStream->WriteL(ptr);
        iBytesWritten += ptr.Size();
        iIv.Copy(ptr.Right(KDCFKeySize));
        size -= n;
        }
    iRemainder.Append(data.Right(size));
    }


// -----------------------------------------------------------------------------
// COma1DcfCreator::EncryptFinalizeL
// finalize the encryption
// -----------------------------------------------------------------------------
EXPORT_C void COma1DcfCreator::EncryptFinalizeL()
    {
    TPtr8 ptr(iEncryptionBuffer->Des());

    ptr.Copy(iRemainder);
    iRdb.Encrypt(iIv, ptr, ETrue);
    iEncryptionStream->WriteL(ptr);
    iEncryptionStream->CommitL();

    iBytesWritten += ptr.Size();
    iRdb.Close();
    }

// -----------------------------------------------------------------------------
// COma1DcfCreator::EncryptContent
// Encrypt plain content to a DCF. Replaces the input buffer with the plain
// content with the DCF.
// -----------------------------------------------------------------------------
EXPORT_C void COma1DcfCreator::EncryptContentL(
    HBufC8*& aContent,
    const TDesC8& aMIMEType,
    CDRMRights* aRightsObject)
    {
    RMemWriteStream output;
    TAny* buffer;
    TInt size;

    size = aContent->Length() +
        aMIMEType.Length() +
        KLDContentURI().Length() +
        KLDFHeader().Length() + 256;
    buffer = User::Alloc(size);
    User::LeaveIfNull(buffer);
    CleanupStack::PushL(buffer);
    output.Open(buffer, size);
    CleanupClosePushL(output);
    EncryptInitializeL(output, aMIMEType, aRightsObject);
    EncryptUpdateL(*aContent);
    EncryptFinalizeL();
    delete aContent;
    aContent = HBufC8::NewMax(size);
    User::LeaveIfNull(aContent);
    size = iBytesWritten;
    *aContent = TPtr8(static_cast<TUint8*>(buffer), size, size);
    CleanupStack::PopAndDestroy(2); // output, buffer
    }

// -----------------------------------------------------------------------------
// COma1DcfCreator::EncryptFileL
// Turn a plain content file into a DCF.
// -----------------------------------------------------------------------------
EXPORT_C void COma1DcfCreator::EncryptFileL(
    const TDesC& aFileName,
    const TDesC& aDCFFileName,
    const TDesC8& aMIMEType,
    CDRMRights* aRightsObject)
    {
    TInt r = KErrNone;
    RFs fs;
    RFile input;
    RFileWriteStream output;
    HBufC8* buf = HBufC8::NewLC(8000);
    TPtr8 buffer(const_cast<TUint8*>(buf->Ptr()),0,8000);


    User::LeaveIfError(fs.Connect());
    CleanupClosePushL(fs);

    r = input.Open(fs, aFileName, EFileRead|EFileShareReadersOrWriters);
    if(r == KErrInUse)
        {
        r = input.Open(fs, aFileName, EFileRead | EFileShareAny);

        if(r == KErrInUse)
            {
            User::LeaveIfError(input.Open(fs, aFileName, EFileRead |
                                                         EFileShareReadersOnly));
            r = KErrNone;
            }
        }

    User::LeaveIfError( r );

    CleanupClosePushL(input);

    User::LeaveIfError(output.Replace(fs, aDCFFileName, EFileWrite));
    CleanupClosePushL(output);


    EncryptInitializeL(output, aMIMEType, aRightsObject);


    do
        {
        input.Read(buffer, buffer.MaxSize());
        if (buffer.Size() > 0)
            {

            EncryptUpdateL(buffer);

            }
        }
    while (buffer.Size() > 0);

    EncryptFinalizeL();

    CleanupStack::PopAndDestroy(4); // output, input, fs, buf
    }

// -----------------------------------------------------------------------------
// COma1DcfCreator::EncryptContentToFile
// Encrypt plain content to a DCF and stores it in a file.
// -----------------------------------------------------------------------------
EXPORT_C void COma1DcfCreator::EncryptContentToFileL(
    const TDesC8& aContent,
    const TDesC& aFileName,
    const TDesC8& aMIMEType,
    CDRMRights* aRightsObject)
    {
    RFs fs;
    RFileWriteStream output;

    User::LeaveIfError(fs.Connect());
    CleanupClosePushL(fs);
    fs.Delete(aFileName);
    User::LeaveIfError(output.Create(fs, aFileName, EFileWrite));
    CleanupClosePushL(output);
    EncryptInitializeL(output, aMIMEType, aRightsObject);
    EncryptUpdateL(aContent);
    EncryptFinalizeL();
    CleanupStack::PopAndDestroy(2); // output, fs
    }

// End of File