omadrm/drmengine/drmcrypto/src/OmaCrypto.cpp
changeset 0 95b198f216e5
equal deleted inserted replaced
-1:000000000000 0:95b198f216e5
       
     1 /*
       
     2 * Copyright (c) 2002-2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  OMA DRM 2.x Crypto Algorithms
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include <e32std.h>
       
    22 #include <asymmetric.h>
       
    23 #include <symmetric.h>
       
    24 #include <hash.h>
       
    25 #include "OmaCrypto.h"
       
    26 #include "DrmKeyStorage.h"
       
    27 
       
    28 #ifdef _DEBUG
       
    29 #define LOGGING
       
    30 #endif
       
    31 
       
    32 #ifdef LOGGING
       
    33 _LIT(KLogDir, "DRM");
       
    34 _LIT(KLogName, "Crypto.log");
       
    35 #include "flogger.h"
       
    36 #define LOG(string) \
       
    37     RFileLogger::Write(KLogDir, KLogName, \
       
    38         EFileLoggingModeAppend, string);
       
    39 #define LOGHEX(buffer) \
       
    40     RFileLogger::HexDump(KLogDir, KLogName, \
       
    41         EFileLoggingModeAppend, _S(""), _S(""), \
       
    42         buffer.Ptr(), buffer.Length());
       
    43 #define LOGFMT(string, value) \
       
    44     RFileLogger::WriteFormat(KLogDir, KLogName, \
       
    45         EFileLoggingModeAppend, string, value);
       
    46 #else
       
    47 #define LOG
       
    48 #define LOGHEX
       
    49 #define LOGFMT
       
    50 #endif
       
    51 
       
    52 // LOCAL CONSTANTS AND MACROS
       
    53 
       
    54 _LIT8(KWrapIv, "\xA6\xA6\xA6\xA6\xA6\xA6\xA6\xA6");
       
    55 
       
    56 // LOCAL FUNCTION PROTOTYPES
       
    57 LOCAL_C void DeleteObject( TAny* aObject );
       
    58 
       
    59 // FORWARD DECLARATIONS
       
    60 
       
    61 // ============================= LOCAL FUNCTIONS ===============================
       
    62 
       
    63 // ----------------------------------------------------------------------------
       
    64 // DeleteObject
       
    65 // Deletes the file by TFileName presented by aHandle
       
    66 // ----------------------------------------------------------------------------
       
    67 //
       
    68 LOCAL_C void DeleteObject( TAny* aObject )
       
    69     {
       
    70     __ASSERT_DEBUG( aObject, User::Panic( _L( "DeleteObject" ), KErrArgument ) );
       
    71     MDrmKeyStorage* object = reinterpret_cast< MDrmKeyStorage* >( aObject );
       
    72     delete object;
       
    73     object = NULL;
       
    74     }
       
    75 
       
    76 
       
    77 // ============================ MEMBER FUNCTIONS ===============================
       
    78 
       
    79 // -----------------------------------------------------------------------------
       
    80 // OmaCrypto::
       
    81 //
       
    82 // -----------------------------------------------------------------------------
       
    83 //
       
    84 EXPORT_C void OmaCrypto::WriteUint32ToBlock(
       
    85     TUint32 aInt,
       
    86     TDes8& aBlock,
       
    87     TInt aOffset)
       
    88     {
       
    89     aBlock[aOffset] =  (aInt & 0xff000000) >> 24;
       
    90     aBlock[aOffset + 1] = (aInt & 0x00ff0000) >> 16;
       
    91     aBlock[aOffset + 2] = (aInt & 0x0000ff00) >> 8;
       
    92     aBlock[aOffset + 3] = (aInt & 0x000000ff);
       
    93     }
       
    94 
       
    95 // -----------------------------------------------------------------------------
       
    96 // OmaCrypto::
       
    97 //
       
    98 // -----------------------------------------------------------------------------
       
    99 //
       
   100 EXPORT_C HBufC8* OmaCrypto::RsaDecryptL(
       
   101     MDrmKeyStorage* aKeyStorage,
       
   102     const TDesC8& aInput)
       
   103     {
       
   104     return aKeyStorage->RsaDecryptL(aInput);
       
   105     }
       
   106 
       
   107 // -----------------------------------------------------------------------------
       
   108 // OmaCrypto::
       
   109 //
       
   110 // -----------------------------------------------------------------------------
       
   111 //
       
   112 EXPORT_C HBufC8* OmaCrypto::RsaEncryptL(
       
   113     CRSAPublicKey* aKey,
       
   114     const TDesC8& aInput)
       
   115     {
       
   116     RInteger result;
       
   117     RInteger input;
       
   118     HBufC8* output;
       
   119 
       
   120     input = OS2IPL(aInput);
       
   121     CleanupClosePushL(input);
       
   122     result = TInteger::ModularExponentiateL(input, aKey->E(), aKey->N());
       
   123     CleanupClosePushL(result);
       
   124     output = I2OSPL(result);
       
   125 
       
   126 #ifdef LOGGING
       
   127     HBufC8* buffer = NULL;
       
   128     LOG(_L8("RsaEncryptL"));
       
   129     LOG(_L8("Input"));
       
   130     LOGHEX(aInput);
       
   131     buffer = aKey->E().BufferLC();
       
   132     LOG(_L8("E"));
       
   133     LOGHEX((*buffer));
       
   134     CleanupStack::PopAndDestroy(buffer);
       
   135     buffer = aKey->N().BufferLC();
       
   136     LOG(_L8("N"));
       
   137     LOGHEX((*buffer));
       
   138     CleanupStack::PopAndDestroy(buffer);
       
   139     LOG(_L8("Result"));
       
   140     LOGHEX((*output));
       
   141 #endif
       
   142 
       
   143     CleanupStack::PopAndDestroy(2); // result, input
       
   144     return output;
       
   145     }
       
   146 
       
   147 // -----------------------------------------------------------------------------
       
   148 // OmaCrypto::
       
   149 //
       
   150 // -----------------------------------------------------------------------------
       
   151 //
       
   152 EXPORT_C HBufC8* OmaCrypto::RsaVerifyL(
       
   153     CRSAPublicKey* aKey,
       
   154     const TDesC8& aInput)
       
   155     {
       
   156     RInteger result;
       
   157     RInteger input;
       
   158     HBufC8* output;
       
   159 
       
   160     input = OS2IPL(aInput);
       
   161     CleanupClosePushL(input);
       
   162     result = TInteger::ModularExponentiateL(input, aKey->E(), aKey->N());
       
   163     CleanupClosePushL(result);
       
   164     output = I2OSPL(result);
       
   165     CleanupStack::PopAndDestroy(2); // result, input
       
   166     return output;
       
   167     }
       
   168 
       
   169 // -----------------------------------------------------------------------------
       
   170 // OmaCrypto::
       
   171 //
       
   172 // -----------------------------------------------------------------------------
       
   173 //
       
   174 EXPORT_C HBufC8* OmaCrypto::RsaKemKwsEncryptL(
       
   175     CRSAPublicKey* aKey,
       
   176     const TDesC8& aRek,
       
   177     const TDesC8& aMac)
       
   178     {
       
   179     HBufC8* C1 = NULL;
       
   180     HBufC8* C2 = NULL;
       
   181     HBufC8* C;
       
   182     TPtr8 c(0, 0);
       
   183     TBuf8<128> Z;
       
   184     TBuf8<KKeySize + KMacSize> keyAndMac;
       
   185     HBufC8* kek = NULL;
       
   186     const TUint8 KFirstBitMask( 0x7f );
       
   187 
       
   188     Z.SetLength(128);
       
   189     MDrmKeyStorage* storage = DrmKeyStorageNewL();
       
   190     TCleanupItem storageCleanup( DeleteObject, storage );
       
   191     CleanupStack::PushL(storageCleanup);
       
   192     storage->RandomDataGetL(Z,Z.Size());
       
   193     CleanupStack::PopAndDestroy( storage );
       
   194 
       
   195     Z[0] &= KFirstBitMask;
       
   196 
       
   197 #ifdef LOGGING
       
   198     LOG(_L("RsaKemKwsEncryptL"));
       
   199     LOG(_L("random Z"));
       
   200     LOGHEX(Z);
       
   201 #endif
       
   202     C1 = RsaEncryptL(aKey, Z);
       
   203     CleanupStack::PushL(C1);
       
   204     kek = KdfL(Z, KNullDesC8, KKeySize);
       
   205     CleanupStack::PushL(kek);
       
   206     keyAndMac.Copy(aMac);
       
   207     keyAndMac.Append(aRek);
       
   208     C2 = AesWrapL(*kek, keyAndMac);
       
   209     CleanupStack::PushL(C2);
       
   210     C = HBufC8::NewL(C1->Length() + C2->Length());
       
   211     c.Set(C->Des());
       
   212     c.Copy(*C1);
       
   213     c.Append(*C2);
       
   214 
       
   215 #ifdef LOGGING
       
   216     LOG(_L("RsaKemKwsEncryptL"));
       
   217     LOG(_L("Z"));
       
   218     LOGHEX(Z);
       
   219     LOG(_L("C1"));
       
   220     LOGHEX((*C1));
       
   221     LOG(_L("C2"));
       
   222     LOGHEX((*C2));
       
   223 #endif
       
   224 
       
   225     CleanupStack::PopAndDestroy(3); // C2, kek, C1
       
   226     return C;
       
   227     }
       
   228 
       
   229 // -----------------------------------------------------------------------------
       
   230 // OmaCrypto::
       
   231 //
       
   232 // -----------------------------------------------------------------------------
       
   233 //
       
   234 EXPORT_C void OmaCrypto::RsaKemKwsDecryptL(
       
   235     MDrmKeyStorage* aKeyStorage,
       
   236     const TDesC8& aInput,
       
   237     TDes8& aRek,
       
   238     TDes8& aMac)
       
   239     {
       
   240     HBufC8* C1 = NULL;
       
   241     HBufC8* C2 = NULL;
       
   242     HBufC8* Z = NULL;
       
   243     HBufC8* keyAndMac = NULL;
       
   244     HBufC8* kek = NULL;
       
   245 
       
   246     C1 = aInput.Left(aInput.Length() - KWrappedKeySize).AllocL();
       
   247     CleanupStack::PushL(C1);
       
   248     C2 = aInput.Right(KWrappedKeySize).AllocL();
       
   249     CleanupStack::PushL(C2);
       
   250     Z = aKeyStorage->RsaDecryptL(*C1);
       
   251     CleanupStack::PushL(Z);
       
   252     kek = KdfL(*Z, KNullDesC8, KKeySize);
       
   253     CleanupStack::PushL(kek);
       
   254     keyAndMac = AesUnwrapL(*kek, *C2);
       
   255     aMac.Copy(keyAndMac->Left(KKeySize));
       
   256     aRek.Copy(keyAndMac->Right(KMacSize));
       
   257 
       
   258 #ifdef LOGGING
       
   259     LOG(_L("RsaKemKwsDecryptL"));
       
   260     LOG(_L("Z"));
       
   261     LOGHEX((*Z));
       
   262     LOG(_L("C1"));
       
   263     LOGHEX((*C1));
       
   264     LOG(_L("C2"));
       
   265     LOGHEX((*C2));
       
   266     LOG(_L("REK + MAC"));
       
   267     LOGHEX((*keyAndMac));
       
   268     LOG(_L("KEK"));
       
   269     LOGHEX((*kek));
       
   270 #endif
       
   271 
       
   272     delete keyAndMac;
       
   273     CleanupStack::PopAndDestroy(4); // kek, Z, C2, C1
       
   274     }
       
   275 
       
   276 // -----------------------------------------------------------------------------
       
   277 // OmaCrypto::
       
   278 //
       
   279 // -----------------------------------------------------------------------------
       
   280 //
       
   281 EXPORT_C HBufC8* OmaCrypto::KdfL(
       
   282     const TDesC8& aInput,
       
   283     const TDesC8& aOtherData,
       
   284     TInt aKLen)
       
   285     {
       
   286     TUint32 d;
       
   287     CSHA1* h = NULL;
       
   288     TBuf8<sizeof(d)> c;
       
   289     HBufC8* t = NULL;
       
   290     HBufC8* r = NULL;
       
   291     TPtr8 T(0, 0);
       
   292 
       
   293     h = CSHA1::NewL();
       
   294     CleanupStack::PushL(h);
       
   295     t = HBufC8::NewL(aKLen + SHA1_HASH);
       
   296     CleanupStack::PushL(t);
       
   297     T.Set(t->Des());
       
   298     c.SetLength(sizeof(d));
       
   299     d = 1;
       
   300     do
       
   301         {
       
   302         WriteUint32ToBlock(d, c, 0);
       
   303         h->Hash(aInput);
       
   304         h->Hash(c);
       
   305         if (aOtherData.Length() > 0)
       
   306             {
       
   307             h->Hash(aOtherData);
       
   308             }
       
   309         T.Append(h->Final());
       
   310         d++;
       
   311         }
       
   312     while (d < SHA1_HASH / aKLen);
       
   313     r = t->Left(aKLen).AllocL();
       
   314     CleanupStack::PopAndDestroy(2); // Tbuf, h
       
   315     return r;
       
   316     }
       
   317 
       
   318 // -----------------------------------------------------------------------------
       
   319 // OmaCrypto::
       
   320 //
       
   321 // -----------------------------------------------------------------------------
       
   322 //
       
   323 EXPORT_C HBufC8* OmaCrypto::I2OSPL(
       
   324     RInteger& aInt)
       
   325     {
       
   326     HBufC8* r = aInt.BufferLC();
       
   327     CleanupStack::Pop(r);
       
   328     return r;
       
   329     }
       
   330 
       
   331 // -----------------------------------------------------------------------------
       
   332 // OmaCrypto::
       
   333 //
       
   334 // -----------------------------------------------------------------------------
       
   335 //
       
   336 EXPORT_C RInteger OmaCrypto::OS2IPL(
       
   337     const TDesC8& aOctetStream)
       
   338     {
       
   339     RInteger r;
       
   340     TInt i;
       
   341 
       
   342     r = RInteger::NewL(0);
       
   343     for (i = 0; i < aOctetStream.Length(); i++)
       
   344         {
       
   345         r *= 256;
       
   346         r += aOctetStream[i];
       
   347         }
       
   348     return r;
       
   349     }
       
   350 
       
   351 // -----------------------------------------------------------------------------
       
   352 // OmaCrypto::
       
   353 //
       
   354 // -----------------------------------------------------------------------------
       
   355 //
       
   356 EXPORT_C HBufC8* OmaCrypto::AesWrapL(
       
   357     const TDesC8& aKey,
       
   358     const TDesC8& aInput)
       
   359     {
       
   360     HBufC8* ret = NULL;
       
   361     TBuf8<KWrapBlockSize> A;
       
   362     TBuf8<2 * KWrapBlockSize> B;
       
   363     TInt i;
       
   364     TInt j;
       
   365     TPtr8 R(0, 0);
       
   366     TPtr8 Rn(0, 0);
       
   367     TInt t;
       
   368     TInt n;
       
   369     CAESEncryptor* e;
       
   370 
       
   371     e = CAESEncryptor::NewL(aKey);
       
   372     User::LeaveIfNull(e);
       
   373     CleanupStack::PushL(e);
       
   374     n = aInput.Length() / KWrapBlockSize;
       
   375     ret = HBufC8::NewMax((n + 1) * KWrapBlockSize);
       
   376     User::LeaveIfNull(ret);
       
   377     R.Set(ret->Des());
       
   378     A.Copy(KWrapIv);
       
   379     R.Copy(A);
       
   380     R.Append(aInput);
       
   381     for (j = 0; j <= 5; j++)
       
   382         {
       
   383         for (i = 1; i <= n; i++)
       
   384             {
       
   385             t = (n * j) + i;
       
   386             Rn.Set(const_cast<TUint8*>(R.Ptr()) + KWrapBlockSize * i,
       
   387                 KWrapBlockSize, KWrapBlockSize);
       
   388             B.Copy(A);
       
   389             B.Append(Rn);
       
   390             e->Transform(B);
       
   391             A.Copy(B.Left(KWrapBlockSize));
       
   392             A[KWrapBlockSize - 1] ^= t;
       
   393             Rn.Copy(B.Right(KWrapBlockSize));
       
   394             }
       
   395         }
       
   396     Rn.Set(const_cast<TUint8*>(R.Ptr()), KWrapBlockSize, KWrapBlockSize);
       
   397     Rn.Copy(A);
       
   398     CleanupStack::PopAndDestroy(); // e
       
   399     return ret;
       
   400     }
       
   401 
       
   402 // -----------------------------------------------------------------------------
       
   403 // OmaCrypto::
       
   404 //
       
   405 // -----------------------------------------------------------------------------
       
   406 //
       
   407 EXPORT_C HBufC8* OmaCrypto::AesUnwrapL(
       
   408     const TDesC8& aKey,
       
   409     const TDesC8& aInput)
       
   410     {
       
   411     HBufC8* ret = NULL;
       
   412     TBuf8<KWrapBlockSize> A;
       
   413     TBuf8<2 * KWrapBlockSize> B;
       
   414     TInt i;
       
   415     TInt j;
       
   416     TPtr8 R(0, 0);
       
   417     TPtr8 Rn(0, 0);
       
   418     TInt t;
       
   419     TInt n;
       
   420     CAESDecryptor* d;
       
   421 
       
   422     d = CAESDecryptor::NewL(aKey);
       
   423     User::LeaveIfNull(d);
       
   424     CleanupStack::PushL(d);
       
   425     n = (aInput.Length() / KWrapBlockSize) - 1;
       
   426     ret = HBufC8::NewMax((n + 1) * KWrapBlockSize);
       
   427     User::LeaveIfNull(ret);
       
   428     R.Set(ret->Des());
       
   429     A.Copy(aInput.Left(KWrapBlockSize));
       
   430     R.Copy(aInput);
       
   431     for (j = 5; j >= 0; j--)
       
   432         {
       
   433         for (i = n; i >= 1; i--)
       
   434             {
       
   435             t = (n * j) + i;
       
   436             Rn.Set(const_cast<TUint8*>(R.Ptr()) + KWrapBlockSize * i,
       
   437                 KWrapBlockSize, KWrapBlockSize);
       
   438             A[KWrapBlockSize - 1] ^= t;
       
   439             B.Copy(A);
       
   440             B.Append(Rn);
       
   441             d->Transform(B);
       
   442             A.Copy(B.Left(KWrapBlockSize));
       
   443             Rn.Copy(B.Right(KWrapBlockSize));
       
   444             }
       
   445         }
       
   446     R.Delete(0, KWrapBlockSize);
       
   447     CleanupStack::PopAndDestroy(); // e
       
   448 
       
   449 #ifdef LOGGING
       
   450     LOG(_L("OmaCrypto::AesUnwrapL"));
       
   451     LOG(_L("Key:"));
       
   452     LOGHEX(aKey);
       
   453     LOG(_L("Input:"));
       
   454     LOGHEX(aInput);
       
   455     LOG(_L("Ret:"));
       
   456     LOGHEX((*ret));
       
   457 #endif
       
   458 
       
   459     return ret;
       
   460     }
       
   461 
       
   462 // -----------------------------------------------------------------------------
       
   463 // OmaCrypto::
       
   464 //
       
   465 // -----------------------------------------------------------------------------
       
   466 //
       
   467 EXPORT_C HBufC8* OmaCrypto::Mgf1L(
       
   468     const TDesC8& aMfgSeed,
       
   469     TInt aMaskLen)
       
   470     {
       
   471     TUint32 c;
       
   472     CSHA1* h = NULL;
       
   473     TBuf8<4> counter;
       
   474     HBufC8* t = NULL;
       
   475     TPtr8 T(0, 0);
       
   476     TInt n;
       
   477 
       
   478     n = aMaskLen / SHA1_HASH + (aMaskLen % SHA1_HASH ? 1 : 0);
       
   479     h = CSHA1::NewL();
       
   480     CleanupStack::PushL(h);
       
   481     t = HBufC8::NewL(aMaskLen + 2 * SHA1_HASH + 1);
       
   482     CleanupStack::PushL(t);
       
   483     T.Set(t->Des());
       
   484     counter.SetLength(4);
       
   485     c = 0;
       
   486     do
       
   487         {
       
   488         WriteUint32ToBlock(c, counter, 0);
       
   489         h->Hash(aMfgSeed);
       
   490         h->Hash(counter);
       
   491         T.Append(h->Final());
       
   492         c++;
       
   493         }
       
   494     while (c < n);
       
   495     T.SetLength(aMaskLen);
       
   496     CleanupStack::Pop(); // t
       
   497     CleanupStack::PopAndDestroy(); // h
       
   498     return t;
       
   499     }
       
   500 
       
   501 // -----------------------------------------------------------------------------
       
   502 // OmaCrypto::RsaPssSignHashL
       
   503 // Sign a hash (not a message!) using RSASSA-PSS.
       
   504 // NOTE: The implementation is only correct for a private key modulus divisible
       
   505 // by eight!
       
   506 // -----------------------------------------------------------------------------
       
   507 //
       
   508 EXPORT_C HBufC8* OmaCrypto::RsaPssSignHashL(
       
   509     MDrmKeyStorage* aKeyStorage,
       
   510     const TDesC8& aMHash)
       
   511     {
       
   512     CSHA1* hasher = NULL;
       
   513     HBufC8* em = NULL;
       
   514     HBufC8* S = NULL;
       
   515     TPtr8 EM(0, 0);
       
   516     TInt modBits;
       
   517     TInt emLen;
       
   518     TBuf8<KPssSaltLength> salt;
       
   519     TBuf8<SHA1_HASH> H;
       
   520     _LIT8(KMNullVector, "\0\0\0\0\0\0\0\0");
       
   521     HBufC8* db = NULL;
       
   522     TPtr8 DB(0, 0);
       
   523     HBufC8* dbMask = NULL;
       
   524     TInt i;
       
   525 
       
   526     modBits = aKeyStorage->ModulusSize();
       
   527 
       
   528     if( modBits < 0)
       
   529         {
       
   530         User::LeaveIfError( modBits );
       
   531         }
       
   532     emLen = modBits / 8;
       
   533     hasher = CSHA1::NewL();
       
   534     CleanupStack::PushL(hasher);
       
   535 
       
   536     salt.SetLength(KPssSaltLength);
       
   537 
       
   538     aKeyStorage->RandomDataGetL(salt,salt.Size());
       
   539 
       
   540 #ifdef LOGGING
       
   541     LOG(_L("RsaKemKwsEncryptL"));
       
   542     LOG(_L("salt"));
       
   543     LOGHEX(salt);
       
   544 #endif
       
   545 
       
   546     hasher->Hash(KMNullVector);
       
   547     hasher->Hash(aMHash);
       
   548     hasher->Hash(salt);
       
   549     H.Copy(hasher->Final());
       
   550 
       
   551     db = HBufC8::NewL(emLen - SHA1_HASH - 1);
       
   552     CleanupStack::PushL(db);
       
   553     DB.Set(db->Des());
       
   554     DB.FillZ(emLen - KPssSaltLength - SHA1_HASH - 2);
       
   555     DB.Append(0x01);
       
   556     DB.Append(salt);
       
   557 
       
   558     dbMask = Mgf1L(H, emLen - SHA1_HASH - 1);
       
   559     CleanupStack::PushL(dbMask);
       
   560 
       
   561     for (i = 0; i < emLen - SHA1_HASH - 1; i++)
       
   562         {
       
   563         DB[i] = DB[i] ^ (*dbMask)[i];
       
   564         }
       
   565 
       
   566     em = HBufC8::NewL(emLen);
       
   567     CleanupStack::PushL(em);
       
   568     EM.Set(em->Des());
       
   569     EM.Copy(DB);
       
   570     EM[0] &= 0x7f;
       
   571     EM.Append(H);
       
   572     EM.Append(0xbc);
       
   573     S = aKeyStorage->RsaSignL(EM);
       
   574 
       
   575     CleanupStack::PopAndDestroy(4); // em, dbMask, db, hasher
       
   576     return S;
       
   577     }
       
   578 
       
   579 // -----------------------------------------------------------------------------
       
   580 // OmaCrypto::
       
   581 //
       
   582 // -----------------------------------------------------------------------------
       
   583 //
       
   584 EXPORT_C TBool OmaCrypto::RsaPssVerifyHashL(
       
   585     CRSAPublicKey* aKey,
       
   586     const TDesC8& aSignature,
       
   587     const TDesC8& aMHash)
       
   588     {
       
   589     TBool r = EFalse;
       
   590     CSHA1* hasher = NULL;
       
   591     HBufC8* EM = NULL;
       
   592     TInt emLen;
       
   593     TBuf8<KPssSaltLength> salt;
       
   594     TBuf8<SHA1_HASH> H;
       
   595     _LIT8(KMNullVector, "\0\0\0\0\0\0\0\0");
       
   596     HBufC8* db = NULL;
       
   597     TPtr8 DB(0, 0);
       
   598     HBufC8* dbMask = NULL;
       
   599     TInt i;
       
   600 
       
   601     EM = RsaVerifyL(aKey, aSignature);
       
   602     CleanupStack::PushL(EM);
       
   603     emLen = EM->Size();
       
   604 
       
   605     hasher = CSHA1::NewL();
       
   606     CleanupStack::PushL(hasher);
       
   607 
       
   608     db = EM->Left(emLen - SHA1_HASH - 1).AllocL();
       
   609     CleanupStack::PushL(db);
       
   610     DB.Set(db->Des());
       
   611     H.Copy(EM->Mid(emLen - SHA1_HASH - 1, SHA1_HASH));
       
   612 
       
   613     dbMask = Mgf1L(H, emLen - SHA1_HASH - 1);
       
   614     CleanupStack::PushL(dbMask);
       
   615 
       
   616     for (i = 0; i < emLen - SHA1_HASH - 1; i++)
       
   617         {
       
   618         DB[i] = DB[i] ^ (*dbMask)[i];
       
   619         }
       
   620 
       
   621     salt.Copy(DB.Right(KPssSaltLength));
       
   622 
       
   623     hasher->Hash(KMNullVector);
       
   624     hasher->Hash(aMHash);
       
   625     hasher->Hash(salt);
       
   626     if (hasher->Final().Compare(H) == 0)
       
   627         {
       
   628         r = ETrue;
       
   629         }
       
   630 
       
   631     CleanupStack::PopAndDestroy(4); // dbMask, db, hasher, EM
       
   632     return r;
       
   633     }
       
   634 
       
   635 //  End of File