omadrm/drmengine/keystorage/src/DrmStdKeyStorage.cpp
changeset 0 95b198f216e5
child 12 8a03a285ab14
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omadrm/drmengine/keystorage/src/DrmStdKeyStorage.cpp	Thu Dec 17 08:52:27 2009 +0200
@@ -0,0 +1,1178 @@
+/*
+* Copyright (c) 2002-2004 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:  OMA DRM 2.0 Key Storage
+*
+*/
+
+
+// INCLUDE FILES
+#include <e32std.h>
+#include <asymmetric.h>
+#include <symmetric.h>
+#include <hash.h>
+#include <asn1dec.h>
+#include <x509cert.h>
+#include <etelmm.h>
+#include <mmtsy_names.h>
+
+#ifdef RD_MULTIPLE_DRIVE
+#include <DriveInfo.h>
+#endif
+
+#include "DrmKeyStorage.h"
+#include "DrmStdKeyStorage.h"
+
+#ifdef _DEBUG
+#define LOGGING
+#endif
+
+#ifdef LOGGING
+_LIT(KLogDir, "DRM");
+_LIT(KLogName, "KeyStorage.log");
+#include "flogger.h"
+#define LOG(string) \
+    RFileLogger::Write(KLogDir, KLogName, \
+        EFileLoggingModeAppend, string);
+#define LOGHEX(buffer) \
+    RFileLogger::HexDump(KLogDir, KLogName, \
+        EFileLoggingModeAppend, _S(""), _S(""), \
+        buffer.Ptr(), buffer.Length());
+#else
+#define LOG(string)
+#define LOGHEX(buffer)       
+#endif
+
+#pragma message("Compiling DRM Std KeyStorage..")
+
+
+// LOCAL CONSTANTS AND MACROS
+
+const TInt KKeyLength = 128;
+const TInt KWaitingTime = 2000000; // 2 sec
+
+#ifdef RD_MULTIPLE_DRIVE
+_LIT(KKeyStoragePath, "%c:\\private\\101F51F2\\PKI\\");
+_LIT(KRomKeyStoragePath, "%c:\\private\\101F51F2\\PKI\\");
+
+#else
+_LIT(KKeyStoragePath, "c:\\private\\101F51F2\\PKI\\");
+_LIT(KRomKeyStoragePath, "z:\\private\\101F51F2\\PKI\\");
+#endif
+
+_LIT(KDeviceKeyFileName, "DevicePrivateKey.der");
+_LIT(KDeviceCertFileName, "DeviceCert.der");
+_LIT(KSingingCertFmt, "SigningCert%02d.der");
+_LIT(KSingingCertPattern, "SigningCert*");
+_LIT8(KDefaultKey, "0000000000000000");
+
+#ifdef RD_MULTIPLE_DRIVE
+_LIT(KSerialNumberFile, "%c:\\private\\101F51F2\\rdbserial.dat");
+_LIT(KUdtCertFileName, "%c:\\private\\101F51F2\\PKI\\UdtCertificate.der");
+#else
+_LIT(KSerialNumberFile, "c:\\private\\101F51F2\\rdbserial.dat");
+_LIT(KUdtCertFileName, "z:\\private\\101F51F2\\PKI\\UdtCertificate.der");
+#endif
+
+_LIT(KCmla, "CMLA");
+_LIT(KPadding, "\x0");
+
+NONSHARABLE_STRUCT( TUnloadModule )
+    {
+    RTelServer* iServer;
+    const TDesC* iName;
+    };
+
+
+// ============================ LOCAL FUNCTIONS ================================
+LOCAL_C void DoUnloadPhoneModule( TAny* aAny );
+
+LOCAL_C void WriteFileL(RFs& aFs, const TDesC& aName, const TDesC8& aData)
+    {
+    RFile file;
+    
+    User::LeaveIfError(file.Replace(aFs, aName, EFileWrite));
+    User::LeaveIfError(file.Write(aData));
+    file.Close();
+    }
+    
+LOCAL_C void ReadFileL(RFs& aFs, const TDesC& aName, HBufC8*& aContent)
+    {   
+    RFile file;
+    TInt size = 0;
+    
+    User::LeaveIfError(file.Open(aFs, aName, EFileRead));
+    CleanupClosePushL(file);
+    User::LeaveIfError(file.Size(size));
+    aContent = HBufC8::NewLC(size);
+    TPtr8 ptr(aContent->Des());
+    User::LeaveIfError(file.Read(ptr, size));
+    CleanupStack::Pop(); //aContent
+    CleanupStack::PopAndDestroy(); // file
+    }
+
+HBufC8* I2OSPL(
+    RInteger& aInt, TInt& aKeySize )
+    {
+    HBufC8* integer = aInt.BufferLC();
+    if (integer->Length() < aKeySize)
+        {
+        HBufC8* r = HBufC8::NewLC(aKeySize);
+        TPtr8 ptr(r->Des());
+        for(TInt i = integer->Length(); i < aKeySize; i++)
+            {
+            ptr.Append(KPadding());
+            }
+        ptr.Append(*integer);
+        CleanupStack::Pop(r);
+        CleanupStack::PopAndDestroy(integer);
+        return r;
+        }
+    else
+        {
+        CleanupStack::Pop(integer);
+        return integer;
+        }
+    }
+
+RInteger OS2IPL(
+    const TDesC8& aOctetStream)
+    {
+    RInteger r;
+    TInt i;
+    
+    r = RInteger::NewL(0);
+    for (i = 0; i < aOctetStream.Length(); i++)
+        {
+        r *= 256;
+        r += aOctetStream[i];
+        }
+    return r;
+    }
+
+void DoUnloadPhoneModule( TAny* aAny )
+    {
+    __ASSERT_DEBUG( aAny, User::Invariant() );
+    TUnloadModule* module = ( TUnloadModule* ) aAny;
+    module->iServer->UnloadPhoneModule( *( module->iName ) );
+    }
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage* CDrmStdKeyStorage::NewL
+// 
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CDrmStdKeyStorage* CDrmStdKeyStorage::NewL(RLibrary aLibrary)
+    {
+    CDrmStdKeyStorage* self = new (ELeave) CDrmStdKeyStorage(aLibrary);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop();
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::CDrmStdKeyStorage
+// 
+// -----------------------------------------------------------------------------
+//    
+CDrmStdKeyStorage::CDrmStdKeyStorage(RLibrary aLibrary):
+    iFileMan(NULL),
+    iRootSelected(EFalse),
+    iKey(NULL),
+    iImei(NULL),
+    iLibrary(aLibrary)
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::ConstructL
+// 
+// -----------------------------------------------------------------------------
+//   
+void CDrmStdKeyStorage::ConstructL()
+    {
+   
+    LOG(_L("CDrmStdKeyStorage::ConstructL ->"));
+    User::LeaveIfError(iFs.Connect());
+    iFileMan = CFileMan::NewL(iFs);
+
+#ifdef __DRM_OMA2 
+	SelectDefaultRootL();
+#endif
+
+    iDeviceSpecificKey.Copy(KDefaultKey);
+
+    LOG(_L("CDrmStdKeyStorage::ConstructL <-"));
+    }
+
+// -----------------------------------------------------------------------------
+// MDrmKeyStorage::~MDrmKeyStorage
+// 
+// -----------------------------------------------------------------------------
+//
+
+MDrmKeyStorage::~MDrmKeyStorage()
+    {
+    }
+// -----------------------------------------------------------------------------
+// DrmStdKeyStorage::~CDrmStdKeyStorage
+// 
+// -----------------------------------------------------------------------------
+//
+
+CDrmStdKeyStorage::~CDrmStdKeyStorage()
+    {
+    LOG(_L("CDrmStdKeyStorage::~CDrmStdKeyStorage ->"));
+    delete iFileMan;
+    delete iKey;
+    delete iImei; iImei = NULL;
+    iFs.Close();
+    //iLibrary.Close();
+    LOG(_L("CDrmStdKeyStorage::~CDrmStdKeyStorage <-"));
+    }
+
+// -----------------------------------------------------------------------------
+// DrmStdKeyStorage::ModulusSize
+// 
+// -----------------------------------------------------------------------------
+//
+    
+TInt CDrmStdKeyStorage::ModulusSize()
+    {
+    LOG(_L("CDrmStdKeyStorage::ModulusSize ->"));
+
+    if(iKey == NULL)
+        {
+        return KErrGeneral;
+        }
+    LOG(_L("CDrmStdKeyStorage::ModulusSize <-"));
+    return iKey->N().BitCount();
+    }
+
+// -----------------------------------------------------------------------------
+// DrmStdKeyStorage::SelectTrustedRootL
+// 
+// -----------------------------------------------------------------------------
+//
+void CDrmStdKeyStorage::SelectTrustedRootL(
+    const TDesC8& aRootKeyHash)
+    {
+    TFileName fileName;
+    TEntry entry;
+    TInt i;
+    
+    LOG(_L("CDrmStdKeyStorage::SelectTrustedRootL ->"));
+    LOG(aRootKeyHash);
+    if (aRootKeyHash.Length() != 0)
+        {
+        
+#ifndef RD_MULTIPLE_DRIVE
+        
+        fileName.Copy(KKeyStoragePath);
+    
+#else //RD_MULTIPLE_DRIVE
+    
+        TFileName tempPath;
+        TInt driveNumber( -1 );
+        TChar driveLetter;
+        DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
+    	iFs.DriveToChar( driveNumber, driveLetter );
+    
+    	tempPath.Format( KKeyStoragePath, (TUint)driveLetter );
+        
+        fileName.Copy(tempPath);
+    
+#endif
+        
+        for (i = 0; i < SHA1_HASH; i++)
+            {
+            fileName.AppendNumFixedWidth(aRootKeyHash[i], EHex, 2);
+            }
+        fileName.Append('\\');
+        if (iFs.Entry(fileName, entry) != KErrNone)
+            {
+            
+#ifndef RD_MULTIPLE_DRIVE
+            
+            fileName.Copy(KRomKeyStoragePath);
+    
+#else //RD_MULTIPLE_DRIVE
+    
+            DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRom, driveNumber );
+    	    iFs.DriveToChar( driveNumber, driveLetter );
+    	    
+    	    tempPath.Format( KRomKeyStoragePath, (TUint)driveLetter );
+            
+            fileName.Copy(tempPath);
+    
+#endif
+            
+            for (i = 0; i < SHA1_HASH; i++)
+                {
+                fileName.AppendNumFixedWidth(aRootKeyHash[i], EHex, 2);
+                }
+            fileName.Append('\\');
+            // check that the path exists
+            User::LeaveIfError(iFs.Entry(fileName, entry));
+            }
+        User::LeaveIfError(iFs.SetSessionPath(fileName));
+        InitializeKeyL();
+        CheckRootForCmlaL();
+        iRootSelected = ETrue;  
+        }
+    else
+        {
+        SelectDefaultRootL();
+        }
+    LOG(_L("CDrmStdKeyStorage::SelectTrustedRootL <-"));
+    }
+    
+// -----------------------------------------------------------------------------
+// DrmStdKeyStorage::SelectDefaultRootL
+// 
+// -----------------------------------------------------------------------------
+//
+void CDrmStdKeyStorage::SelectDefaultRootL()
+    {
+    CDir* dir = NULL;
+    TFileName dirName;
+    TBool found = EFalse;
+    
+    LOG(_L("CDrmStdKeyStorage::SelectDefaultRootL ->"));
+    
+#ifndef RD_MULTIPLE_DRIVE
+    
+    if (iFs.GetDir(KKeyStoragePath, KEntryAttDir, ESortByName, dir) == KErrNone)
+    
+#else //RD_MULTIPLE_DRIVE
+    
+    TFileName tempPath;
+    TInt driveNumber( -1 );
+    TChar driveLetter;
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+    
+    tempPath.Format( KKeyStoragePath, (TUint)driveLetter );
+    
+    if (iFs.GetDir(tempPath, KEntryAttDir, ESortByName, dir) == KErrNone)
+    
+#endif
+    
+        {
+        __UHEAP_MARK;
+        LOG(_L("  Checking keys on C:"));
+        CleanupStack::PushL(dir);
+        if (dir->Count() >= 1)
+            {
+            
+#ifndef RD_MULTIPLE_DRIVE
+            
+            dirName.Copy(KKeyStoragePath);
+    
+#else //RD_MULTIPLE_DRIVE
+    
+            dirName.Copy(tempPath);
+    
+#endif
+            
+            dirName.Append((*dir)[0].iName);
+            dirName.Append('\\');
+            User::LeaveIfError(iFs.SetSessionPath(dirName));
+            found = ETrue;
+            }
+        CleanupStack::PopAndDestroy(dir);
+        __UHEAP_MARKEND;
+        }
+    
+#ifndef RD_MULTIPLE_DRIVE
+
+    if (!found && iFs.GetDir(KRomKeyStoragePath, KEntryAttDir, ESortByName, dir) == KErrNone)
+    
+#else //RD_MULTIPLE_DRIVE
+    
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRom, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+    
+    tempPath.Format( KRomKeyStoragePath, (TUint)driveLetter );
+    
+    if (!found && iFs.GetDir(tempPath, KEntryAttDir, ESortByName, dir) == KErrNone)
+    
+#endif
+        {
+    	LOG(_L("  Checking keys on Z:"));
+        CleanupStack::PushL(dir);
+        if (dir->Count() < 1)
+            {
+            User::Leave(KErrGeneral);
+            }
+        
+#ifndef RD_MULTIPLE_DRIVE
+        
+        dirName.Copy(KRomKeyStoragePath);
+        
+#else //RD_MULTIPLE_DRIVE
+    
+        dirName.Copy(tempPath);
+        
+#endif
+        
+        dirName.Append((*dir)[0].iName);
+        dirName.Append('\\');
+        User::LeaveIfError(iFs.SetSessionPath(dirName));
+        CleanupStack::PopAndDestroy(dir);
+        found = ETrue;
+        }
+    if (!found)
+        {
+        User::Leave(KErrGeneral); 
+        }
+    InitializeKeyL();
+    CheckRootForCmlaL();
+    iRootSelected = ETrue;
+    LOG(_L("CDrmStdKeyStorage::SelectDefaultRootL <-"));
+    }
+    
+TBool CDrmStdKeyStorage::SelectedRootIsCmla()
+    {
+    return iRootIsCmla;
+    }
+
+// -----------------------------------------------------------------------------
+// DrmStdKeyStorage::GetTrustedRootsL
+// 
+// -----------------------------------------------------------------------------
+//
+    
+void CDrmStdKeyStorage::GetTrustedRootsL(
+    RPointerArray<HBufC8>& aRootList)
+    {
+    CDir* dir = NULL;
+    TInt i;
+    TInt j;
+    TBuf8<SHA1_HASH> hash;
+    TEntry entry;
+    TUint8 c;
+    TInt r = KErrNone;
+    
+    LOG(_L("CDrmStdKeyStorage::GetTrustedRootsL ->"));
+    aRootList.ResetAndDestroy();
+    
+#ifndef RD_MULTIPLE_DRIVE
+    
+    if (iFs.GetDir(KKeyStoragePath, KEntryAttDir, ESortByName, dir) == KErrNone)
+    
+#else //RD_MULTIPLE_DRIVE
+    
+    TFileName tempPath;
+    TInt driveNumber( -1 );
+    TChar driveLetter;
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+    
+    tempPath.Format( KKeyStoragePath, (TUint)driveLetter );
+    
+    if (iFs.GetDir(tempPath, KEntryAttDir, ESortByName, dir) == KErrNone)
+    
+#endif
+        {
+        LOG(_L("  Getting roots on C:"));
+        CleanupStack::PushL(dir);
+        for (i = 0; i < dir->Count(); i++)
+            {
+            entry = (*dir)[i];
+            hash.SetLength(0);
+            LOG(entry.iName);
+            r = KErrNone;
+            for (j = 0; r == KErrNone && j < SHA1_HASH; j++)
+                {
+                TLex lex(entry.iName.Mid(j * 2, 2));
+                r = lex.Val(c, EHex);
+                hash.Append(c);
+                }
+            if (r == KErrNone)
+                {
+                aRootList.Append(hash.AllocL());
+                }
+            }
+        CleanupStack::PopAndDestroy(dir);
+        }
+    
+#ifndef RD_MULTIPLE_DRIVE
+    
+    if (iFs.GetDir(KRomKeyStoragePath, KEntryAttDir, ESortByName, dir) == KErrNone)
+    
+#else //RD_MULTIPLE_DRIVE
+    
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRom, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+    
+    tempPath.Format( KRomKeyStoragePath, (TUint)driveLetter );
+    
+    if (iFs.GetDir(tempPath, KEntryAttDir, ESortByName, dir) == KErrNone)
+    
+#endif
+        {
+        LOG(_L("  Getting roots on Z:"));
+        CleanupStack::PushL(dir);
+        for (i = 0; i < dir->Count(); i++)
+            {
+            LOG(entry.iName);
+            entry = (*dir)[i];
+            hash.SetLength(0);
+            r = KErrNone;
+            for (j = 0; r == KErrNone && j < SHA1_HASH; j++)
+                {
+                TLex lex(entry.iName.Mid(j * 2, 2));
+                r = lex.Val(c, EHex);
+                hash.Append(c);
+                }
+            if (r == KErrNone)
+                {
+                aRootList.Append(hash.AllocL());
+                }
+            }
+        CleanupStack::PopAndDestroy(dir);
+        }
+    LOG(_L("CDrmStdKeyStorage::GetTrustedRootsL <-"));
+    }
+
+// -----------------------------------------------------------------------------
+// DrmStdKeyStorage::GetCertificateChainL
+// 
+// -----------------------------------------------------------------------------
+//
+void CDrmStdKeyStorage::GetCertificateChainL(
+    RPointerArray<HBufC8>& aCertChain)
+    {
+    TFileName fileName;
+    TInt i;
+    CDir* dir = NULL;
+    HBufC8* cert = NULL;
+    
+    LOG(_L("CDrmStdKeyStorage::GetCertificateChainL ->"));
+    if (!iRootSelected)
+        {
+        User::Leave(KErrGeneral);
+        }
+    aCertChain.ResetAndDestroy();
+    ReadFileL(iFs, KDeviceCertFileName, cert);
+    aCertChain.Append(cert);
+    iFs.GetDir(KSingingCertPattern, KEntryAttNormal, ESortByName, dir);
+    CleanupStack::PushL(dir);
+    for (i = 0; i < dir->Count(); i++)
+        {
+        ReadFileL(iFs, (*dir)[i].iName, cert);
+        aCertChain.AppendL(cert);
+        }
+    CleanupStack::PopAndDestroy(); // dir
+    LOG(_L("CDrmStdKeyStorage::GetCertificateChainL <-"));
+    }
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::RsaSignL
+// -----------------------------------------------------------------------------
+//
+HBufC8* CDrmStdKeyStorage::RsaSignL(
+    const TDesC8& aInput)
+    {
+    return ModularExponentiateWithKeyL(aInput);
+    }
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::RsaDecryptL
+// -----------------------------------------------------------------------------
+//
+HBufC8* CDrmStdKeyStorage::RsaDecryptL(
+    const TDesC8& aInput)
+    {
+    return ModularExponentiateWithKeyL(aInput);
+    }
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::ImportDataL
+// -----------------------------------------------------------------------------
+//
+void CDrmStdKeyStorage::ImportDataL(
+    const TDesC8& aPrivateKey,
+    const RArray<TPtrC8>& aCertificateChain)
+    {
+    TInt i;
+    TInt n;
+    HBufC8* publicKey = NULL;
+    CX509Certificate* cert = NULL;
+    CSHA1* hasher = NULL;
+    TBuf8<SHA1_HASH> publicKeyHash;
+    TFileName fileName;
+    
+    LOG(_L("CDrmStdKeyStorage::ImportDataL ->"));
+    n = aCertificateChain.Count();
+    cert = CX509Certificate::NewLC(aCertificateChain[n - 1]);
+    publicKey = cert->DataElementEncoding(
+        CX509Certificate::ESubjectPublicKeyInfo)->AllocL();
+    CleanupStack::PushL(publicKey);
+    hasher = CSHA1::NewL();
+    CleanupStack::PushL(hasher);
+    hasher->Update(*publicKey);
+    publicKeyHash.Copy(hasher->Final());
+    
+#ifndef RD_MULTIPLE_DRIVE
+    
+    fileName.Copy(KKeyStoragePath);
+    
+#else //RD_MULTIPLE_DRIVE
+    
+    TInt driveNumber( -1 );
+    TChar driveLetter;
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+    
+    TFileName keyStorageDir;
+    keyStorageDir.Format( KKeyStoragePath, (TUint)driveLetter );
+    
+    fileName.Copy(keyStorageDir);
+    
+#endif
+    
+    for (i = 0; i < SHA1_HASH; i++)
+        {
+        fileName.AppendNumFixedWidth(publicKeyHash[i], EHex, 2);
+        }
+    fileName.Append('\\');
+    iFileMan->Delete(fileName, CFileMan::ERecurse);
+    iFs.MkDirAll(fileName);
+    iFs.SetSessionPath(fileName);
+    WriteFileL(iFs, KDeviceKeyFileName, aPrivateKey);
+    fileName.Copy(fileName);
+    WriteFileL(iFs, KDeviceCertFileName, aCertificateChain[0]);
+    for (i = 1; i < n; i++)
+        {
+        fileName.SetLength(0);
+        fileName.AppendFormat(KSingingCertFmt, i - 1);
+        WriteFileL(iFs, fileName, aCertificateChain[i]);
+        }
+    CleanupStack::PopAndDestroy(3); // hasher, publicKey, cert
+    LOG(_L("CDrmStdKeyStorage::ImportDataL <-"));
+    }
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::GetDeviceSpecificKeyL
+// -----------------------------------------------------------------------------
+//
+void CDrmStdKeyStorage::GetDeviceSpecificKeyL(
+    TBuf8<KDeviceSpecificKeyLength>& aKey)
+    {
+    
+    HBufC8* key = NULL;
+    TInt n;    
+    CSHA1* hasher = NULL;  
+    TBuf8<SHA1_HASH> hash;
+    
+    if (iDeviceSpecificKey.Compare(KDefaultKey) == 0)
+        {
+        
+        GetImeiL();
+        
+        HBufC8* buf = HBufC8::NewLC( iImei->Size() + sizeof(VID_DEFAULT) );
+        TPtr8 ptr( buf->Des() );
+        ptr.Copy( *iImei );
+        ptr.Append(VID_DEFAULT);
+
+        hasher = CSHA1::NewL();
+        CleanupStack::PushL(hasher);
+        hasher->Update(ptr);
+        hash.Copy(hasher->Final());
+        key=hash.AllocL();
+        CleanupStack::PopAndDestroy(2,buf); // hasher,buf;
+
+        n = Min(key->Length(), KDeviceSpecificKeyLength);
+        iDeviceSpecificKey.Copy(key->Right(n));
+        delete key;
+        n = KDeviceSpecificKeyLength - n;
+        while (n > 0)
+            {
+            iDeviceSpecificKey.Append(0);
+            n--;
+            }
+        }
+    
+    aKey.Copy(iDeviceSpecificKey);
+    }
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::InitializeKeyL
+// -----------------------------------------------------------------------------
+//
+void CDrmStdKeyStorage::InitializeKeyL()
+    {
+    HBufC8* key = NULL;
+    TASN1DecInteger encInt;
+    TInt pos = 0;
+
+    LOG(_L("CDrmStdKeyStorage::InitializeKeyL ->"));
+    delete iKey;
+    iKey = NULL;
+    ReadFileL(iFs, KDeviceKeyFileName, key);
+    CleanupStack::PushL(key);
+    TASN1DecGeneric gen(*key);
+    gen.InitL();
+    pos += gen.LengthDERHeader();
+    if (gen.Tag() != EASN1Sequence)
+        {
+        User::Leave(KErrArgument);
+        }
+    encInt.DecodeDERShortL(*key, pos); // version
+    RInteger modulus = encInt.DecodeDERLongL(*key, pos);
+    CleanupStack::PushL(modulus);
+    RInteger publicExponent = encInt.DecodeDERLongL(*key, pos);
+    CleanupStack::PushL(publicExponent);
+    RInteger privateExponent = encInt.DecodeDERLongL(*key, pos);
+    CleanupStack::PushL(privateExponent);
+    iKey = CRSAPrivateKeyStandard::NewL(modulus, privateExponent);
+    CleanupStack::Pop(); // privateExponent
+    CleanupStack::PopAndDestroy();// publicExponent
+    CleanupStack::Pop(); // modulus
+    CleanupStack::PopAndDestroy(); // key
+    LOG(_L("CDrmStdKeyStorage::InitializeKeyL <-"));
+    }
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::ModularExponentiateWithKeyL
+// -----------------------------------------------------------------------------
+//
+HBufC8* CDrmStdKeyStorage::ModularExponentiateWithKeyL(
+    const TDesC8& aInput)
+    {
+    RInteger result;
+    RInteger input;
+    HBufC8* output;
+    TInt keyLength = KKeyLength;
+    
+    LOG(_L("CDrmStdKeyStorage::ModularExponentiateWithKeyL ->"));
+    input = OS2IPL(aInput);
+    CleanupClosePushL(input);
+    result = TInteger::ModularExponentiateL(input,iKey->D(), iKey->N());
+    CleanupClosePushL(result);
+    output = I2OSPL(result,  keyLength);
+    CleanupStack::PopAndDestroy(2); // result, input
+    LOG(_L("CDrmStdKeyStorage::ModularExponentiateWithKeyL <-"));
+    return output;
+    }
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::CheckRootForCmlaL
+// -----------------------------------------------------------------------------
+//
+void CDrmStdKeyStorage::CheckRootForCmlaL()
+    {
+    CDir* dir = NULL;
+    HBufC8* buffer = NULL;
+    HBufC* name = NULL;
+    CX509Certificate* cert = NULL;
+    
+    LOG(_L("CDrmStdKeyStorage::CheckRootForCmlaL ->"));
+    __UHEAP_MARK;
+    iFs.GetDir(KSingingCertPattern, KEntryAttNormal, ESortByName, dir);
+    CleanupStack::PushL(dir);
+    ReadFileL(iFs, (*dir)[dir->Count() - 1].iName, buffer);
+    CleanupStack::PushL(buffer);
+    cert = CX509Certificate::NewL(*buffer);
+    CleanupStack::PushL(cert);
+    name = cert->SubjectName().DisplayNameL();
+    CleanupStack::PushL(name);
+    if (name->Find(KCmla) != KErrNotFound)
+        {
+        iRootIsCmla = ETrue;
+        }
+    else
+        {
+        iRootIsCmla = EFalse;
+        }
+    CleanupStack::PopAndDestroy(4); // name, cert, buffer, dir
+    LOG(_L("CDrmStdKeyStorage::CheckRootForCmlaL <-"));
+    __UHEAP_MARKEND;
+    }
+    
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::GetRdbSerialNumberL
+// -----------------------------------------------------------------------------
+//
+void CDrmStdKeyStorage::GetRdbSerialNumberL(
+    TBuf8<KRdbSerialNumberLength>& aSerialNumber)
+    {
+    HBufC8* buffer = NULL;
+    TUint att;
+    
+#ifndef RD_MULTIPLE_DRIVE
+
+    if (iFs.Att(KSerialNumberFile, att) != KErrNone)
+    
+#else //RD_MULTIPLE_DRIVE
+    
+    TInt driveNumber( -1 );
+    TChar driveLetter;
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+    
+    TFileName serialNoFile;
+    serialNoFile.Format( KSerialNumberFile, (TUint)driveLetter );
+    
+    if (iFs.Att(serialNoFile, att) != KErrNone)
+    
+#endif
+        {
+        GenerateNewRdbSerialNumberL();
+        }
+    
+#ifndef RD_MULTIPLE_DRIVE
+
+    ReadFileL(iFs, KSerialNumberFile, buffer);
+    
+#else //RD_MULTIPLE_DRIVE
+    
+    ReadFileL(iFs, serialNoFile, buffer);
+    
+#endif
+    
+    aSerialNumber.Copy(*buffer);
+    delete buffer;
+    }
+    
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::GenerateNewRdbSerialNumberL
+// -----------------------------------------------------------------------------
+//
+void CDrmStdKeyStorage::GenerateNewRdbSerialNumberL()
+    {
+    TBuf8<KRdbSerialNumberLength> serialNumber;
+    TPtr8 random( const_cast<TUint8*>(serialNumber.Ptr()),
+                  KRdbSerialNumberLength,
+                  KRdbSerialNumberLength );
+    
+    RandomDataGetL(random,KRdbSerialNumberLength);
+    
+#ifndef RD_MULTIPLE_DRIVE
+    
+    WriteFileL(iFs, KSerialNumberFile, random);
+    
+#else //RD_MULTIPLE_DRIVE
+    
+    TInt driveNumber( -1 );
+    TChar driveLetter;
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+    
+    TFileName serialNoFile;
+    serialNoFile.Format( KSerialNumberFile, (TUint)driveLetter );
+    
+    WriteFileL(iFs, serialNoFile, random);
+    
+#endif
+    
+    }
+    
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::UdtEncryptL
+// -----------------------------------------------------------------------------
+//
+HBufC8* CDrmStdKeyStorage::UdtEncryptL(
+    const TDesC8& aInput)
+    {
+    HBufC8* buffer = NULL;
+    HBufC8* output = HBufC8::NewMaxLC( 256 );
+    CX509Certificate* cert = NULL;
+    CRSAPublicKey* key = NULL;
+    TX509KeyFactory factory;
+    CRSAPKCS1v15Encryptor* encryptor = NULL;
+    TPtr8 result(const_cast<TUint8*>(output->Ptr()), 0, 256);
+    
+#ifndef RD_MULTIPLE_DRIVE
+    
+    ReadFileL(iFs, KUdtCertFileName, buffer);
+    
+#else //RD_MULTIPLE_DRIVE
+    
+    TInt driveNumber( -1 );
+    TChar driveLetter;
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRom, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+    
+    TFileName udtCertFile;
+    udtCertFile.Format( KUdtCertFileName, (TUint)driveLetter );
+    
+    ReadFileL(iFs, udtCertFile, buffer);
+    
+#endif
+    
+    CleanupStack::PushL(buffer);
+    cert = CX509Certificate::NewL(*buffer);
+    CleanupStack::PushL(cert);
+    key = factory.RSAPublicKeyL(cert->PublicKey().KeyData());
+    CleanupStack::PushL(key);
+       
+    encryptor = CRSAPKCS1v15Encryptor::NewLC(*key);
+    encryptor->EncryptL(aInput, result);
+
+    CleanupStack::PopAndDestroy(4); // encryptor, key, cert, buffer
+    CleanupStack::Pop();// output
+    return output;
+    };
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::GetRootCertificatesL
+// -----------------------------------------------------------------------------
+//
+void CDrmStdKeyStorage::GetRootCertificatesL(
+          RPointerArray<HBufC8>& aRootCerts)
+    {
+    CDir* dir = NULL;
+    CDir* rootCerts = NULL;
+    TFileName dirName;
+    HBufC8* cert = NULL;
+    TInt i = 0;
+    TBuf<256> path;
+
+    iFs.SessionPath( path );
+
+#ifndef RD_MULTIPLE_DRIVE
+
+    if (iFs.GetDir(KKeyStoragePath, KEntryAttDir, ESortByName, dir) == KErrNone)
+    
+#else //RD_MULTIPLE_DRIVE
+    
+    TFileName tempPath;
+    TInt driveNumber( -1 );
+    TChar driveLetter;
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+    
+    tempPath.Format( KKeyStoragePath, (TUint)driveLetter );
+    
+    if (iFs.GetDir(tempPath, KEntryAttDir, ESortByName, dir) == KErrNone)
+    
+#endif
+        {
+        CleanupStack::PushL(dir);
+        for(i = 0; i < dir->Count(); i++)
+            {
+            if ((*dir)[i].IsDir())
+                {
+                
+#ifndef RD_MULTIPLE_DRIVE
+                
+                dirName.Copy(KKeyStoragePath);
+    
+#else //RD_MULTIPLE_DRIVE
+    
+                dirName.Copy(tempPath);
+    
+#endif
+                
+                dirName.Append((*dir)[i].iName);
+                dirName.Append('\\');
+                User::LeaveIfError(iFs.SetSessionPath(dirName));
+                User::LeaveIfError(iFs.GetDir(KSingingCertPattern, KEntryAttNormal, ESortByName, rootCerts));
+                CleanupStack::PushL(rootCerts);
+                ReadFileL(iFs, (*rootCerts)[rootCerts->Count() - 1].iName, cert);
+                CleanupStack::PushL(cert);
+                aRootCerts.AppendL(cert);
+                CleanupStack::Pop(cert);
+                CleanupStack::PopAndDestroy(); // rootCerts
+                }
+            }
+        CleanupStack::PopAndDestroy(dir);
+        }
+    
+#ifndef RD_MULTIPLE_DRIVE
+
+    if (iFs.GetDir(KRomKeyStoragePath, KEntryAttDir, ESortByName, dir) == KErrNone)
+    
+#else //RD_MULTIPLE_DRIVE
+    
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRom, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+    
+    tempPath.Format( KRomKeyStoragePath, (TUint)driveLetter );
+    
+    if (iFs.GetDir(tempPath, KEntryAttDir, ESortByName, dir) == KErrNone)
+    
+#endif
+        {
+        CleanupStack::PushL(dir);
+        for(i = 0; i < dir->Count(); i++)
+            {
+            if ((*dir)[i].IsDir())
+                {
+                
+#ifndef RD_MULTIPLE_DRIVE
+                
+                dirName.Copy(KRomKeyStoragePath);
+    
+#else //RD_MULTIPLE_DRIVE
+    
+                dirName.Copy(tempPath);
+    
+#endif
+                
+                dirName.Append((*dir)[i].iName);
+                dirName.Append('\\');
+                User::LeaveIfError(iFs.SetSessionPath(dirName));
+                User::LeaveIfError(iFs.GetDir(KSingingCertPattern, KEntryAttNormal, ESortByName, rootCerts));
+                CleanupStack::PushL(rootCerts);
+                ReadFileL(iFs, (*rootCerts)[rootCerts->Count() - 1].iName, cert);
+                CleanupStack::PushL(cert);
+                aRootCerts.AppendL(cert);
+                CleanupStack::Pop(cert);
+                CleanupStack::PopAndDestroy(); // rootCerts
+                }
+            }
+        CleanupStack::PopAndDestroy(dir);
+        }
+    iFs.SetSessionPath( path );
+    }
+    
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::GetIMEIL
+// -----------------------------------------------------------------------------
+//
+const TDesC& CDrmStdKeyStorage::GetImeiL()
+    {
+    if ( iImei )
+        {
+        return *iImei;
+        }
+
+#if (defined __WINS__ || defined WINSCW)
+    // Default IMEI used for emulator   
+    _LIT( KDefaultSerialNumber, "123456789123456789" );
+    iImei = KDefaultSerialNumber().AllocL();
+        
+    return *iImei;
+#else
+ 
+    TInt error( KErrNone );
+    TInt count( 0 );
+    TInt count2( 0 );
+    TUint32 caps( 0 );
+    TBool found (EFalse);
+    
+    RTelServer etelServer;
+    RMobilePhone phone;
+    
+    TUint KMaxImeiTries = 5;
+    
+    for ( TUint8 i = 0; i < KMaxImeiTries; ++i )
+        {
+        error = etelServer.Connect();
+        if ( error )
+            {
+            User::After( TTimeIntervalMicroSeconds32( KWaitingTime ) );
+            }
+        else 
+            {
+            break;
+            }
+        }
+    
+    User::LeaveIfError( error );
+    CleanupClosePushL( etelServer );
+    
+    User::LeaveIfError( etelServer.LoadPhoneModule( KMmTsyModuleName ) );  
+    
+    TUnloadModule unload;
+    unload.iServer = &etelServer;
+    unload.iName = &KMmTsyModuleName;
+    
+    TCleanupItem item( DoUnloadPhoneModule, &unload );
+    CleanupStack::PushL( item );
+    User::LeaveIfError( etelServer.EnumeratePhones( count ) );
+        
+    for ( count2 = 0; count2 < count && !found; ++count2 )
+        {
+        RTelServer::TPhoneInfo phoneInfo;
+        User::LeaveIfError( etelServer.GetTsyName( count2, phoneInfo.iName ) );
+        
+        if ( phoneInfo.iName.CompareF(KMmTsyModuleName()) == 0 )   
+           {
+            User::LeaveIfError( etelServer.GetPhoneInfo( count2, phoneInfo ) );
+            User::LeaveIfError( phone.Open( etelServer, phoneInfo.iName ) );
+            CleanupClosePushL( phone );
+            found = ETrue;
+            }
+        }
+
+    if ( !found )
+        {
+        // Not found.
+        User::Leave( KErrNotFound );
+        }
+   
+    User::LeaveIfError( phone.GetIdentityCaps( caps ) );
+    if (!( caps & RMobilePhone::KCapsGetSerialNumber ))
+        {
+         User::Leave( KErrNotFound );
+        }
+        
+    RMobilePhone::TMobilePhoneIdentityV1 id;
+    TRequestStatus status;
+    
+    phone.GetPhoneId( status, id );
+       
+    User::WaitForRequest( status );
+        
+    User::LeaveIfError( status.Int() );
+        
+    iImei = id.iSerialNumber.AllocL();
+        
+    CleanupStack::PopAndDestroy( 3 ); // phone, item, etelServer
+        
+    HBufC8* buf = HBufC8::NewL( iImei->Size() );
+    TPtr8 ptr( buf->Des() );
+    ptr.Copy( *iImei );
+        
+    LOG(_L("IMEI:"));
+    LOGHEX(ptr);
+    delete buf;
+    
+    return *iImei;
+#endif /* __WINS__ , WINSCW */ 
+       
+    }
+    
+    
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::RandomDataGetL
+// -----------------------------------------------------------------------------
+//
+    
+void CDrmStdKeyStorage::RandomDataGetL( TDes8& aData, const TInt aLength )
+    {
+    if ( aLength <= 0 )
+        {
+         User::Leave(KErrArgument);
+        }
+
+    TInt size = aData.MaxSize();
+
+    if( size < aLength )
+        {
+        User::Leave(KErrOverflow);
+        }
+
+    TRandom::Random( aData );
+    }
+
+// end of file