--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pkiutilities/PKCS12/CrPkcs12/Src/crpkcs12.cpp Tue Jan 26 15:20:08 2010 +0200
@@ -0,0 +1,2243 @@
+/*
+* Copyright (c) 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: This file contains the implementation of CCrPKCS12 class.
+*
+*/
+
+
+
+// INCLUDE FILES
+#include "crpkcs12.h"
+#include <crdefs.h> // CCrDefines
+#include <e32std.h>
+#include <x509certext.h>
+
+const TInt KX509Version3 = 3;
+
+// -----------------------------------------------------------------------------
+// CPKCS12SyncWrapper
+// Constructor
+// -----------------------------------------------------------------------------
+//
+CCrPKCS12::CPKCS12SyncWrapper::CPKCS12SyncWrapper(): CActive( EPriorityStandard )
+ {
+ CActiveScheduler::Add( this );
+ }
+
+// -----------------------------------------------------------------------------
+// CPKCS12SyncWrapper
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CCrPKCS12::CPKCS12SyncWrapper::~CPKCS12SyncWrapper()
+ {
+ if (iSecDlg)
+ {
+ iSecDlg->Release();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CPKCS12SyncWrapper
+// EnterPassword wrapper function.
+// -----------------------------------------------------------------------------
+//
+TInt CCrPKCS12::CPKCS12SyncWrapper::EnterPasswordL(const TPINParams& aPINParams, TBool aRetry, TPINValue& aPINValue)
+ {
+ iSecDlg = SecurityDialogFactory::CreateL();
+ iSecDlg->EnterPIN(aPINParams, aRetry, aPINValue, iStatus);
+ return SetActiveAndWait();
+ }
+
+// -----------------------------------------------------------------------------
+// CPKCS12SyncWrapper::SetActiveAndWait
+//
+// -----------------------------------------------------------------------------
+//
+TInt CCrPKCS12::CPKCS12SyncWrapper::SetActiveAndWait()
+ {
+ SetActive();
+ iWait.Start();
+ return iStatus.Int();
+ }
+
+// -----------------------------------------------------------------------------
+// CPKCS12SyncWrapper::DoCancel
+//
+// -----------------------------------------------------------------------------
+//
+void CCrPKCS12::CPKCS12SyncWrapper::DoCancel()
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CPKCS12SyncWrapper::RunL
+//
+// -----------------------------------------------------------------------------
+//
+void CCrPKCS12::CPKCS12SyncWrapper::RunL()
+ {
+ iWait.AsyncStop();
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12
+// Constructor
+// This function constructs CCrPKCS12 object
+// Return Values: None
+// -----------------------------------------------------------------------------
+CCrPKCS12::CCrPKCS12():iIter(1), iPrivateKeyIdArray(1), iSafeBagsCount(0)
+ {
+ // Default iteration count is 1.
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::ConstructL
+// This function initializes CCrPKCS12 object's member objects.
+// Parameters: None
+// Return Values: None
+// -----------------------------------------------------------------------------
+void CCrPKCS12::ConstructL()
+ {
+ iberSet = CCrBerSet::NewL( 1 );
+ iUserCertificates = CX509CertificateSet::NewL( 1 );
+ iCACertificates = CX509CertificateSet::NewL( 1 );
+ iUserCertificateBuffer = new (ELeave) CArrayPtrFlat<TDesC8>(1);
+ iCACertificateBuffer = new (ELeave) CArrayPtrFlat<TDesC8>(1);
+ iPKCS8PrivateKeyArray = new (ELeave) CArrayPtrFlat<HBufC8>(1);
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12
+// Destructor
+// This function destructs CCrPKCS12 object
+// Return Values: None
+// -----------------------------------------------------------------------------
+CCrPKCS12::~CCrPKCS12()
+ {
+ delete iberSet;
+ delete iUserCertificates;
+ delete iCACertificates;
+
+ if (iUserCertificateBuffer)
+ {
+ iUserCertificateBuffer->ResetAndDestroy();
+ delete iUserCertificateBuffer;
+ }
+ if (iCACertificateBuffer)
+ {
+ iCACertificateBuffer->ResetAndDestroy();
+ delete iCACertificateBuffer;
+ }
+ delete iMac;
+ delete iSalt;
+ delete iPassWord;
+ delete iContentInfo;
+ delete iBags;
+ delete iDecryptionKey;
+
+ if (iPKCS8PrivateKeyArray)
+ {
+ iPKCS8PrivateKeyArray->ResetAndDestroy();
+ delete iPKCS8PrivateKeyArray;
+ }
+ iPrivateKeyIdArray.ResetAndDestroy();
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::NewLC
+// This function implements the two-phase construction of CCrPKCS12
+// class. The function uses standard constructor to reserve memory
+// for pkcs12-object, stores a pointer to the object into clean up
+// stack, and returns the pointer to the object.
+// Parameters: None.
+// Return Values: CCrPKCS12* Pointer to the CCrPKCS12 object.
+// -----------------------------------------------------------------------------
+CCrPKCS12* CCrPKCS12::NewLC()
+ {
+ CCrPKCS12* self = new ( ELeave ) CCrPKCS12();
+ CleanupStack::PushL( self );
+
+ self->ConstructL();
+
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::NewL
+// This function implements the two-phase construction of CCrPKCS12
+// class. The function reserves memory for pkcs12-object and
+// returns pointer to that object. This function uses NewLC to create
+// the object and store it to cleanup stack. Finally the object is popped
+// from clean up stack.
+// Parameters: None.
+// Return Values: CCrPKCS12* Pointer to the CCrPKCS12 object.
+// -----------------------------------------------------------------------------
+CCrPKCS12* CCrPKCS12::NewL()
+ {
+ CCrPKCS12* self = NewLC();
+ CleanupStack::Pop();
+
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::Open
+// Opens pkcs12-file from location given in parameter afilePath,
+// then it makes a CCrBer::berSet from it. Then it starts testing
+// berObjects from berSet. When it comes long enough, needed
+// information can be get and stored to CCrPKCS12-Class' members.
+// Parameters: CCrData& aPkcs12File PKCS #12 file.
+// TBuf<48> aPassWord password.
+// Returns: TCrStatus Value of error.
+// -----------------------------------------------------------------------------
+TCrStatus CCrPKCS12::OpenL(CCrData& aPkcs12File,
+ const TDesC16& aPassword)
+ {
+ TCrStatus status = KCrOK;
+ TInt errData = KErrNone;
+
+ if (!iberSet)
+ {
+ User::Leave(KErrGeneral);
+ }
+
+ // Number of extracted BER objects.
+ TInt numberOfBerObjects = 0;
+ // make berSet, set of berObjects
+ TRAP( errData,numberOfBerObjects = iberSet->OpenL( &aPkcs12File,KOpenAllLevels ));
+ if ( errData < KErrNone )
+ {
+ return KCrPkcs12 | KCrBerLibraryError;
+ }
+ // number of ber objects must be > 0.
+ if (numberOfBerObjects < 1)
+ {
+ return KCrPkcs12 | KCrNotValidPkcs12Object;
+ }
+
+ iObjectNum = KFirstObject;
+
+ // Now we have the first object
+ iberObject = iberSet->At( iObjectNum );
+
+ // File opened successfully, let's start testing berObjects.
+
+ // 1. Test, is berObject Sequence?
+ if ( !iberObject->IsSeqOrSet( iberObject->Type() ) )
+ {
+ return KCrPkcs12 | KCrNotValidPkcs12Object;
+ }
+
+ iObjectNum++;
+ if (numberOfBerObjects < iObjectNum)
+ {
+ return KCrPkcs12 | KCrNotValidPkcs12Object;
+ }
+ iberObject = iberSet->At(iObjectNum );
+
+ // 2. Test, is an integer?
+ if ( iberObject->Type() != KBerInteger )
+ {
+ return KCrPkcs12 | KCrNotValidPkcs12Object;
+ }
+
+ TInt version = 0;
+ TRAP( errData,version = iberObject->GetIntegerL() );
+ if ( errData < KErrNone )
+ {
+ return KCrPkcs12 | KCrBerLibraryError;
+ }
+
+ // 3. Test, is version 3?
+ if ( version != KVersion3 )
+ {
+ return KCrPkcs12 | KCrNotValidPkcs12Object;
+ }
+
+ // Is there still ber objects?
+ iObjectNum++;
+ if (numberOfBerObjects < iObjectNum)
+ {
+ return KCrPkcs12 | KCrNotValidPkcs12Object;
+ }
+ iberObject = iberSet->At(iObjectNum );
+
+ // 4. Test, is Seq?
+ if ( !iberObject->IsSeqOrSet( iberObject->Type() ) )
+ {
+ return KCrPkcs12 | KCrNotValidPkcs12Object;
+ }
+
+ // Remember where we are.
+ TInt place = iObjectNum;
+
+ // Is there still ber objects?
+ iObjectNum++;
+ if (numberOfBerObjects < iObjectNum)
+ {
+ return KCrPkcs12 | KCrNotValidPkcs12Object;
+ }
+
+ iberObject = iberSet->At(iObjectNum );
+
+ CCrData* contentInfo = NULL;
+ TRAP (errData, contentInfo = CCrData::NewL(EFalse));
+ if (errData < KErrNone)
+ {
+ delete contentInfo;
+ contentInfo = NULL;
+ return KCrPkcs12 | KCrNoMemory;
+ }
+
+ if ( !ReadContentInfo(*contentInfo ) )
+ {
+ delete contentInfo;
+ contentInfo = NULL;
+ return KCrPkcs12 | KCrNotPasswordBasedEncryption;
+ }
+
+ iberObject = iberSet->At( place );
+
+ iObjectNum += JumpNextObjectAtSameLevel();
+
+ iObjectNum++;
+ if (numberOfBerObjects < iObjectNum)
+ {
+ delete contentInfo;
+ contentInfo = NULL;
+ return KCrPkcs12 | KCrNotValidPkcs12Object;
+ }
+ iberObject = iberSet->At( iObjectNum );
+
+ // 5. Test, is Seq?
+ if ( !iberObject->IsSeqOrSet( iberObject->Type() ) )
+ {
+ delete contentInfo;
+ contentInfo = NULL;
+ return KCrPkcs12 | KCrNotValidPkcs12Object;
+ }
+
+ iObjectNum++;
+ if (numberOfBerObjects < iObjectNum)
+ {
+ delete contentInfo;
+ contentInfo = NULL;
+ return KCrPkcs12 | KCrNotValidPkcs12Object;
+ }
+ iberObject = iberSet->At(iObjectNum );
+
+ // 6. Test, is Seq?
+ if ( !iberObject->IsSeqOrSet( iberObject->Type() ) )
+ {
+ delete contentInfo;
+ contentInfo = NULL;
+ return KCrPkcs12 | KCrNotValidPkcs12Object;
+ }
+
+ iObjectNum++;
+ if (numberOfBerObjects < iObjectNum)
+ {
+ delete contentInfo;
+ contentInfo = NULL;
+ return KCrPkcs12 | KCrNotValidPkcs12Object;
+ }
+ iberObject = iberSet->At(iObjectNum );
+
+ // 6. Test, is Seq?
+ if ( iberObject->IsSeqOrSet( iberObject->Type() ) )
+ {
+ iObjectNum++;
+ if (numberOfBerObjects < iObjectNum)
+ {
+ delete contentInfo;
+ contentInfo = NULL;
+ return KCrPkcs12 | KCrNotValidPkcs12Object;
+ }
+ iberObject = iberSet->At(iObjectNum );
+ }
+
+ // 7. Test, is OID?
+ if ( iberObject->Type() != KBerOid)
+ {
+ delete contentInfo;
+ contentInfo = NULL;
+ return KCrPkcs12 | KCrNotValidPkcs12Object;
+ }
+
+ HBufC* oid = NULL;
+
+ TRAP(errData, oid = iberObject->GetOidL() );
+
+ if ( errData < KErrNone )
+ {
+ delete contentInfo;
+ contentInfo = NULL;
+ return KCrPkcs12 | KCrBerLibraryError;
+ }
+
+ // 8. What is used HMAC-algorithm??
+ if ( *oid == KCrSha1 )
+ {
+ iHMACalgorithm = ECrSHA1;
+ }
+ else if ( *oid == KCrMD5 )
+ {
+ iHMACalgorithm = ECrMD5;
+ }
+ else
+ {
+ delete oid;
+ oid = NULL;
+ delete contentInfo;
+ contentInfo = NULL;
+ return KCrPkcs12 | KCrNotSupportedHMACalgorithm;
+ }
+
+ delete oid;
+ oid = NULL;
+
+ iObjectNum++;
+ if (numberOfBerObjects < iObjectNum)
+ {
+ delete contentInfo;
+ contentInfo = NULL;
+ return KCrPkcs12 | KCrNotValidPkcs12Object;
+ }
+
+ iberObject = iberSet->At(iObjectNum);
+
+ // If Octet String, read mac // Case in Outlook
+ if (iberObject->Type() == KBerOctetString)
+ {
+ }
+ else
+ {
+ // 9. Test, is Null Tag?
+ if ( iberObject->Type() != KBerNull )
+ {
+ delete contentInfo;
+ contentInfo = NULL;
+ return KCrPkcs12 | KCrNotValidPkcs12Object;
+ }
+
+ iObjectNum++;
+ if (numberOfBerObjects < iObjectNum)
+ {
+ delete contentInfo;
+ contentInfo = NULL;
+ return KCrPkcs12 | KCrNotValidPkcs12Object;
+ }
+ iberObject = iberSet->At(iObjectNum);
+
+ // If Octet String, read mac
+ if ( iberObject->Type() != KBerOctetString )
+ {
+ delete contentInfo;
+ contentInfo = NULL;
+ return EFalse;
+ }
+ }
+
+ // This is where needed data can be get
+ TRAP( errData,iMac = iberObject->GetOctetStringL() );
+
+ if ( errData < KErrNone )
+ {
+ delete contentInfo;
+ contentInfo = NULL;
+ return KCrPkcs12 | KCrBerLibraryError;
+ }
+
+ iObjectNum++;
+ if (numberOfBerObjects < iObjectNum)
+ {
+ delete contentInfo;
+ contentInfo = NULL;
+ return KCrPkcs12 | KCrNotValidPkcs12Object;
+ }
+ iberObject = iberSet->At(iObjectNum );
+
+ // If Octet String, read salt, if OctetString can be found,
+ // validate of this file is OK.
+ if ( iberObject->Type() != KBerOctetString )
+ {
+ delete contentInfo;
+ contentInfo = NULL;
+ return KCrPkcs12 | KCrNotValidPkcs12Object;
+ }
+
+ TRAP( errData,iSalt = iberObject->GetOctetStringL() );
+ if ( errData < KErrNone )
+ {
+ delete contentInfo;
+ contentInfo = NULL;
+ return KCrPkcs12 | KCrBerLibraryError;
+ }
+
+ // Here's optional integer value
+ if ( iberSet->Count() > ++iObjectNum )
+ {
+ iberObject = iberSet->At( iObjectNum );
+
+ // If here is an integer, then read the number of iterations,
+ // otherwise leave DEFAULT value ( = 1, given in constructor).
+ if ( iberObject->Type() == KBerInteger )
+ {
+ TRAP( errData,iIter = iberObject->GetIntegerL() );
+
+ if ( errData < KErrNone )
+ {
+ delete contentInfo;
+ contentInfo = NULL;
+ return KCrPkcs12 | KCrBerLibraryError;
+ }
+ }
+ }
+
+
+ // Verify Mac.
+ TBool result = EFalse;
+ TRAP(errData, result = VerifyMacL(aPassword));
+ if ( errData < KErrNone )
+ {
+ delete contentInfo;
+ contentInfo = NULL;
+ return KCrPkcs12 | KCrWrongPassWordOrCorruptedFile;
+ }
+ if ( result)
+ {
+ // If password was OK, open ContentInfo
+ if ( !UnpackContentInfo(*contentInfo))
+ {
+ delete contentInfo;
+ contentInfo = NULL;
+ return KCrPkcs12 | KCrNotPasswordBasedEncryption;
+ }
+
+ delete contentInfo;
+ contentInfo = NULL;
+
+ iSafeBagsCount = DecodeSafeBagsL();
+
+ if ( !iSafeBagsCount )
+ {
+ return KCrPkcs12 | KCrNotPasswordBasedEncryption;
+ }
+ }
+ // If macs weren't the same, password was wrong
+ else
+ {
+ delete contentInfo;
+ contentInfo = NULL;
+ return KCrPkcs12 | KCrWrongPassWordOrCorruptedFile;
+ }
+
+ return status;
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::ReadContentInfo
+// Reads ContentInfo.
+// Parameters:
+// Return Values:
+// -----------------------------------------------------------------------------
+TBool CCrPKCS12::ReadContentInfo( CCrData& aContentInfo )
+ {
+ // If this object isn't OID, or if it isn't type pkcs7Data, return EFalse
+ if ( iberObject->Type() != KBerOid )
+ {
+ return EFalse;
+ }
+
+ HBufC* oid = NULL;
+ TInt errData = KErrNone;
+
+ TRAP( errData,oid = iberObject->GetOidL());
+ if ( errData < KErrNone )
+ {
+ delete oid;
+ oid = NULL;
+ return EFalse;
+ }
+
+ if ( *oid != Kpkcs7Data )
+ {
+ delete oid;
+ oid = NULL;
+ return EFalse;
+ }
+
+ delete oid;
+ oid = NULL;
+
+ iberObject = iberSet->At( ++iObjectNum );
+
+ if ( iberObject->Type() != KBerImplicitConstructed )
+ {
+ return EFalse;
+ }
+
+ // Now, let's open Constructed data.
+ iberObject = iberSet->At( ++iObjectNum );
+
+ // Outlook or Netscape
+ if (iberObject->Type() == KBerConstructedBit + KBerOctetString ||
+ iberObject->Type() == KBerOctetString)
+ {
+ // Outlook
+ if (iberObject->Type() == KBerOctetString )
+ {
+ TRAP (errData, iberObject->GetOctetStringL(aContentInfo));
+ if (errData < KErrNone)
+ {
+ return EFalse;
+ }
+ }
+ // Netscape
+ else // iberObject->Type() == KBerConstructedBit + KBerOctetString
+ {
+ TRAP(errData,iberObject->OpenConstructedEncodingL(aContentInfo));
+ if ( errData < KErrNone )
+ {
+ return EFalse;
+ }
+ }
+
+ // Size of contentData
+ TInt size = 0;
+ aContentInfo.Seek( ESeekCurrent,size );
+
+ // ContentInfo's size -> Buffer's allocated size
+ TRAP( errData,iContentInfo = HBufC8::NewL( size ) );
+ if ( errData < KErrNone )
+ {
+ return EFalse;
+ }
+
+ // Make pointer to iContentInfo
+ TPtr8 pContentInfo = iContentInfo->Des();
+
+ // Copy readed ContentInfo to aContentInfo (parameter)
+ aContentInfo.Read( pContentInfo );
+
+ // Go back to start
+ size = 0;
+ aContentInfo.Seek( ESeekStart,size );
+ return ETrue;
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::UnpackContentInfo
+// This function unpacks ContentInfo. First, it tests from what level
+// SafeContents begin and after that it goes through ContentData.
+// All sequences, that begin at that level, are tested (via OID) and
+// Unpacked.
+// Parameters: CCrData& aContentData. CCrData containing ContentInfo.
+// Return Values: TBool If OK, returns ETrue and if not, EFalse
+// -----------------------------------------------------------------------------
+TBool CCrPKCS12::UnpackContentInfo( CCrData& aContentData )
+ {
+ TInt objectNum = KFirstObject;
+ TInt count = 0;
+ TInt errData = KErrNone;
+ HBufC* oid = NULL;
+
+ CCrBerSet* set = NULL;
+
+ TRAP( errData,set = CCrBerSet::NewL( 1 ) );
+
+ if ( errData < KErrNone )
+ {
+ delete set;
+ set = NULL;
+ return EFalse;
+ }
+
+ // make berSet, set of berObjects
+ TRAP( errData,set->OpenL( &aContentData,KOpenAllLevels ) );
+
+ if ( errData < KErrNone )
+ {
+ delete set;
+ set = NULL;
+ return EFalse;
+ }
+
+ count = set->Count();
+
+ CCrBer* object = set->At( objectNum );
+
+ // 1. Test, is seq?
+ if ( !object->IsSeqOrSet( object->Type() ) )
+ {
+ delete set;
+ set = NULL;
+ return EFalse;
+ }
+
+ object = set->At( ++objectNum );
+
+ TInt i(0);
+ for (i = objectNum ; i < count ; i++)
+ {
+ // If there exists object, then check
+ //this object
+ if ( i < count )
+ {
+ object = set->At( i );
+ }
+
+ // Next check type of SafeContent
+ if ( object->Type() == KBerOid )
+ {
+ // Get object identifier
+ TRAP( errData, oid = object->GetOidL() );
+
+ if( errData < KErrNone )
+ {
+ delete set;
+ set = NULL;
+ return EFalse;
+ }
+
+ if ( *oid == Kpkcs7Data )
+ {
+ // Unpack PKCS #7 data
+ object = set->At( ++i );
+
+ // Case it's just an octetstring
+ // NOT TESTED!
+ if ( object->Type() != KBerImplicitConstructed &&
+ object->Type() == KBerOctetString )
+ {
+ HBufC8* pkcs7Data = NULL;
+
+ TRAP( errData, pkcs7Data = object->GetOctetStringL() );
+ if ( errData < KErrNone )
+ {
+ delete oid;
+ oid = NULL;
+ delete set;
+ set = NULL;
+ return EFalse;
+ }
+ // Riddance from warnings
+ if ( pkcs7Data == NULL ) { delete pkcs7Data; }
+
+ }
+ else
+ {
+ object = set->At( ++i );
+
+ if ( (object->Type() ==
+ (KBerConstructedBit + KBerOctetString)) ||
+ (object->Type() == KBerOctetString))
+ {
+ CCrData* pkcs7Data = NULL;
+ TRAP (errData, pkcs7Data = CCrData::NewL(EFalse));
+ if (errData < KErrNone)
+ {
+ delete pkcs7Data;
+ pkcs7Data = NULL;
+ delete oid;
+ oid = NULL;
+ delete set;
+ set = NULL;
+ return EFalse;
+ }
+
+ // Netscape
+ if (object->Type() ==
+ (KBerConstructedBit + KBerOctetString))
+ {
+
+ TRAP( errData,
+ object->OpenConstructedEncodingL(*pkcs7Data));
+ if ( errData < KErrNone )
+ {
+ delete pkcs7Data;
+ pkcs7Data = NULL;
+ delete oid;
+ oid = NULL;
+ delete set;
+ set = NULL;
+ return EFalse;
+ }
+ }
+ // Outlook
+ else if (object->Type() == KBerOctetString)
+ {
+ TRAP (errData, object->GetOctetStringL(*pkcs7Data));
+ if ( errData < KErrNone )
+ {
+ delete pkcs7Data;
+ pkcs7Data = NULL;
+ delete oid;
+ oid = NULL;
+ delete set;
+ set = NULL;
+ return EFalse;
+ }
+ }
+
+ else
+ {
+ delete pkcs7Data;
+ pkcs7Data = NULL;
+ delete oid;
+ oid = NULL;
+ delete set;
+ set = NULL;
+ return EFalse;
+ }
+
+ TBool result = EFalse;
+ TRAP (errData, result = UnpackPkcs7DataL(*pkcs7Data));
+ if ( !result || errData < KErrNone )
+ {
+ delete pkcs7Data;
+ pkcs7Data = NULL;
+ delete oid;
+ oid = NULL;
+ delete set;
+ set = NULL;
+ return EFalse;
+ }
+ delete pkcs7Data;
+ pkcs7Data = NULL;
+ }
+ }
+ }
+ else if ( *oid == Kpkcs7EncryptedData )
+ {
+ TInt currentPlace = 0;
+ // Mark, where we are now
+ aContentData.Seek( ESeekCurrent,currentPlace );
+
+ // Unpack PKCS #7 encrypted Data
+ TBool result = EFalse;
+ TRAP(errData, result = UnpackPkcs7EncryptedDataL( aContentData ) );
+ if (!result || errData < KErrNone)
+ {
+ delete oid;
+ oid = NULL;
+ delete set;
+ set = NULL;
+ return EFalse;
+ }
+
+ // Go back where we were and continue
+ aContentData.Seek( ESeekStart,currentPlace );
+ }
+ delete oid;
+ oid = NULL;
+ }
+ }
+ if( i < count )
+ {
+ object = set->At( i );
+ }
+
+ delete set;
+ set = NULL;
+ // Now iBags contains all SafeBags.
+ return ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::UnpackPkcs7DataL
+// Unpacks Pkcs7Data.
+// Parameters: CCrData& aPkcs7Data
+// Return Values: TBool If OK, returns ETrue and if not, EFalse
+// -----------------------------------------------------------------------------
+TBool CCrPKCS12::UnpackPkcs7DataL( CCrData& aPkcs7Data )
+ {
+ TInt size = 0;
+
+ // Size fo aPkcs7Data
+ aPkcs7Data.Seek( ESeekCurrent,size );
+ // Add this bag to iBags
+
+ // Allocate needed amount of memory for iBags
+ // If iBags-buffer is NULL
+ if ( iBags == NULL)
+ {
+ iBags = HBufC8::NewL( size );
+ }
+ // If iBags isn't NULL
+ else
+ {
+ // Re-allocated space for iBags is
+ // size of the current iBags buffer + size of aPkcs7Dat
+ iBags = iBags->ReAllocL(iBags->Size() + size);
+ }
+ // Append aPkcs7Data to iBags
+ TPtr8 pBags = iBags->Des();
+ HBufC8* tempBuf = HBufC8::NewLC(size);
+ TPtr8 tempPtr = tempBuf->Des();
+ aPkcs7Data.Read(tempPtr);
+ pBags.Append(tempPtr);
+ CleanupStack::PopAndDestroy(); // tempBuf
+
+ return ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::UnpackPkcs7EncryptedDataL
+// Unpacks Pkcs7EncryptedData.
+// Parameters: CCrData& aPkcs7EncryptedData
+// Return Values: TBool If OK, returns ETrue and if not, EFalse
+// -----------------------------------------------------------------------------
+TBool CCrPKCS12::UnpackPkcs7EncryptedDataL( CCrData& aPkcs7EncryptedData )
+ {
+ TInt objectNum = KFirstObject;
+ //TInt count = 0;
+ HBufC* oid = NULL;
+ HBufC8* pkcs7EncryptedDataBuf = NULL;
+ CCrBerSet* set = NULL;
+ CCrBer* object;
+
+ TInt numberOfItemsInCStack = 0;
+
+ set = CCrBerSet::NewL(1);
+ CleanupStack::PushL(set);
+ numberOfItemsInCStack++;
+
+ // make berSet, set of berObjects
+ set->OpenL( &aPkcs7EncryptedData,KOpenAllLevels );
+
+ //count = set->Count();
+
+ // Now we should have a sequence here
+ object = set->At( ++objectNum );
+
+ // 1. Test, is seq?
+ if ( !object->IsSeqOrSet( object->Type() ) )
+ {
+ CleanupStack::PopAndDestroy(numberOfItemsInCStack); // set
+ numberOfItemsInCStack = 0;
+ return EFalse;
+ }
+
+ object = set->At( ++objectNum );
+
+ // 2. Test, is integer?
+ if ( object->Type() != KBerInteger )
+ {
+ CleanupStack::PopAndDestroy(numberOfItemsInCStack); // set
+ numberOfItemsInCStack = 0;
+ return EFalse;
+ }
+
+ // 3. Test, is version 1?
+ if ( object->GetIntegerL() != KEdVer0 )
+ {
+ CleanupStack::PopAndDestroy(numberOfItemsInCStack); // set
+ numberOfItemsInCStack = 0;
+ return EFalse;
+ }
+
+ object = set->At( ++objectNum );
+
+ // 4. Test, is seq?
+ if ( !object->IsSeqOrSet( object->Type() ) )
+ {
+ CleanupStack::PopAndDestroy(numberOfItemsInCStack); // set
+ numberOfItemsInCStack = 0;
+ return EFalse;
+ }
+
+ object = set->At( ++objectNum );
+
+ // 5. Test, is OID?
+ if ( object->Type() != KBerOid )
+ {
+ CleanupStack::PopAndDestroy(numberOfItemsInCStack); // set
+ numberOfItemsInCStack = 0;
+ return EFalse;
+ }
+
+ // Get OID.
+ oid = object->GetOidL();
+ CleanupStack::PushL(oid);
+ numberOfItemsInCStack++; // 2 set + oid
+ // Is it pkcs7Data?
+ if ( *oid != Kpkcs7Data )
+ {
+ CleanupStack::PopAndDestroy(numberOfItemsInCStack); // set + oid
+ numberOfItemsInCStack = 0;
+ return EFalse;
+ }
+
+ CleanupStack::PopAndDestroy(); // oid
+ numberOfItemsInCStack--; // 1
+
+ object = set->At( ++objectNum );
+
+ // 6. Test, is seq?
+ if ( !object->IsSeqOrSet( object->Type() ) )
+ {
+ CleanupStack::PopAndDestroy(numberOfItemsInCStack); // set
+ numberOfItemsInCStack = 0;
+ return EFalse;
+ }
+
+ object = set->At( ++objectNum );
+
+ // Here should be encryption algorithm
+ if ( object->Type() != KBerOid )
+ {
+ CleanupStack::PopAndDestroy(numberOfItemsInCStack); // set
+ numberOfItemsInCStack = 0;
+ return EFalse;
+ }
+
+ // Get used encryption algorithm
+ TInt algorithm = 0;
+
+ oid = object->GetOidL();
+ CleanupStack::PushL(oid);
+ numberOfItemsInCStack++; // 2 set + oid
+
+ algorithm = GetAlgorithmL( oid );
+ CleanupStack::PopAndDestroy(); // oid
+ numberOfItemsInCStack--; // 1
+
+ object = set->At( ++objectNum );
+
+ // 7. Test, is seq?
+ if ( !object->IsSeqOrSet(object->Type()))
+ {
+ CleanupStack::PopAndDestroy(numberOfItemsInCStack); // set
+ numberOfItemsInCStack = 0;
+ return EFalse;
+ }
+
+ object = set->At( ++objectNum );
+
+ // Here should be salt
+ if ( object->Type() != KBerOctetString )
+ {
+ CleanupStack::PopAndDestroy(numberOfItemsInCStack); // set
+ numberOfItemsInCStack = 0;
+ return EFalse;
+ }
+
+ HBufC8* salt = NULL;
+ salt = object->GetOctetStringL();
+ CleanupStack::PushL(salt);
+ numberOfItemsInCStack++; // 2 set + salt
+
+ object = set->At( ++objectNum );
+
+ // Here should be an iteration count
+ if ( object->Type() != KBerInteger)
+ {
+ CleanupStack::PopAndDestroy(numberOfItemsInCStack); // set + salt
+ numberOfItemsInCStack = 0;
+ return EFalse;
+ }
+
+ // By default, iteration count is set to 1
+ TInt iter = 1;
+ iter = object->GetIntegerL();
+
+ // Next we have encrypted data
+
+ object = set->At( ++objectNum );
+
+ // If it's an octet string, read it.
+ if (object->Type() == KBerOctetString)
+ {
+ pkcs7EncryptedDataBuf = object->GetOctetStringL();
+ }
+
+ // If it's an Outlook's KBerImplicit, read it.
+ if (object->Type() == KBerImplicit)
+ {
+ pkcs7EncryptedDataBuf = object->GetContentStringLC();
+ numberOfItemsInCStack++;
+ }
+
+ TBool stop = EFalse;
+
+ if (object->Type() == KBerImplicitConstructed )
+ {
+ object = set->At( ++objectNum );
+
+ for (TInt i = objectNum ; i < set->Count() && !stop ; i++)
+ {
+ if ( object->Type() == KBerOctetString )
+ {
+ // First octet string into buffer...
+ if ( i == objectNum )
+ {
+ pkcs7EncryptedDataBuf = object->GetOctetStringL();
+ CleanupStack::PushL(pkcs7EncryptedDataBuf);
+ numberOfItemsInCStack++;
+ }
+ // ...and rest of octet strings.
+ // New object's content is added to the
+ // pkcs7EncryptedDataBuf
+ else
+ {
+ object = set->At( i );
+
+ // Re-allocate buffer
+ __ASSERT_DEBUG(pkcs7EncryptedDataBuf, User::Invariant());
+ TInt currentSize = pkcs7EncryptedDataBuf->Size();
+ CleanupStack::Pop(); // pkcs7EncryptedDataBuf
+ numberOfItemsInCStack--;
+
+ pkcs7EncryptedDataBuf = pkcs7EncryptedDataBuf->ReAllocL(currentSize + object->ContentLen());
+ CleanupStack::PushL(pkcs7EncryptedDataBuf);
+ numberOfItemsInCStack++;
+
+ // Get new OctetString
+ HBufC8* octetString = NULL;
+ octetString = object->GetOctetStringL();
+ TPtr8 pOctetString = octetString->Des();
+
+ // Copy it into buffer
+ TPtr8 pPkcs7EncryptedData = pkcs7EncryptedDataBuf->Des();
+ pPkcs7EncryptedData.Append( pOctetString );
+
+ // Delete OctetString
+ delete octetString;
+ octetString = NULL;
+ }
+ }
+ else if ( object->Type() == KBerEndOfContent )
+ {
+ stop = ETrue;
+ }
+ }
+ }
+ // OK, now we have buffer to be decrypted, used algorithm, salt and
+ // an iteration count. Next we decrypt buffer and append it to iBags.
+
+ DecryptPkcs7EncryptedDataL( pkcs7EncryptedDataBuf,salt,iter,algorithm );
+
+ CleanupStack::PopAndDestroy(numberOfItemsInCStack);
+ numberOfItemsInCStack = 0;
+
+ return ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::DecryptPkcs7EncryptedDataL
+// Decrypts Pkcs7EncryptedData and adds it to iBags.
+// Parameters:
+// Return Values: TBool If OK, returns ETrue and if not, EFalse
+// -----------------------------------------------------------------------------
+TBool CCrPKCS12::DecryptPkcs7EncryptedDataL( HBufC8* aPkcs7EncryptedData,
+ HBufC8* aSalt,
+ TInt aIter,
+ TInt aAlgorithm)
+ {
+ HBufC8* certificates = HBufC8::NewLC(aPkcs7EncryptedData->Length());
+ TPtr8 ptrCertificates = certificates->Des();
+ DecryptDataL(*aPkcs7EncryptedData, *aSalt, aIter, aAlgorithm, ptrCertificates);
+
+ if (iBags)
+ {
+ iBags = iBags->ReAllocL(iBags->Size() + ptrCertificates.Size());
+ }
+ else
+ {
+ iBags = HBufC8::NewL(ptrCertificates.Size());
+ }
+
+ TPtr8 pIBag = iBags->Des();
+ pIBag.Append(ptrCertificates);
+
+ CleanupStack::PopAndDestroy(certificates);
+ return ETrue;
+ }
+// -----------------------------------------------------------------------------
+// CCrPKCS12::DecodeSafeBagsL
+// Decodes SafeBags and if needed, also decrypts them.
+// Parameters:
+// Return Values: TBool If OK, returns ETrue and if not, EFalse
+// -----------------------------------------------------------------------------
+TInt CCrPKCS12::DecodeSafeBagsL()
+ {
+ TInt numberOfItemsInCStack = 0;
+ TInt bagCount = 0;
+
+ CCrData* safeBags = CCrData::NewLC(EFalse);
+ ++numberOfItemsInCStack;
+
+ TPtr8 piBags = iBags->Des();
+ safeBags->Write( piBags );
+
+ // Go back to start
+ TInt start = 0;
+ safeBags->Seek( ESeekStart,start );
+
+ CCrBerSet* set = NULL;
+ CCrBer* object = NULL;
+
+ set = CCrBerSet::NewLC( 1 );
+ ++numberOfItemsInCStack;
+
+ set->OpenL( safeBags,KOpenAllLevels );
+
+ TInt count = set->Count();
+
+ // We have to check first only for a private key, because we need
+ // it's LocalKeyId, so we can identify a corresponding certificate.
+ TInt i(0);
+ for (i = 0 ; i < count ; i++)
+ {
+ object = set->At( i );
+
+ if ( object->Type() == KBerOid )
+ {
+
+ HBufC* oid = object->GetOidL();
+ CleanupStack::PushL(oid);
+
+ if ( *oid == Kpkcs8ShroudedKeyBag )
+ {
+ bagCount++;
+ DecryptShroudedKeybagL( * safeBags );
+ }
+
+ if ( *oid == KkeyBag )
+ {
+ bagCount++;
+
+ ExtractKeybagL( * safeBags );
+ }
+
+ CleanupStack::PopAndDestroy(oid);
+ oid = NULL;
+ }
+ }
+
+ // And now for certificates.
+ for (i = 0 ; i < count ; i++)
+ {
+ object = set->At( i );
+
+ if ( object->Type() == KBerOid )
+ {
+ HBufC* oid = object->GetOidL();
+ CleanupStack::PushL(oid);
+
+ if ( *oid == KcertBag )
+ {
+ bagCount++;
+ DecodeCertBagL( * safeBags );
+ }
+
+ CleanupStack::PopAndDestroy(oid);
+ oid = NULL;
+ }
+ }
+
+ CleanupStack::PopAndDestroy(numberOfItemsInCStack, safeBags);
+
+ // Return amount fo safebags
+ return bagCount;
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::ExtractKeybagL
+// Extract Keybag.
+// Parameters:
+// Return Values:
+// -----------------------------------------------------------------------------
+void CCrPKCS12::ExtractKeybagL( CCrData& aSafeBag )
+ {
+ TInt numberOfItemsinCStack = 0;
+ CCrBerSet* set = NULL;
+
+ set = CCrBerSet::NewLC( 1 );
+ ++numberOfItemsinCStack;
+
+ CCrBer* object = NULL;
+ TInt objectNum = KFirstObject;
+
+ set->OpenL( &aSafeBag,KOpenAllLevels );
+
+ object = set->At( objectNum );
+
+ if ( object->Type() != KBerImplicitConstructed )
+ {
+ User::Leave( KErrArgument );
+ }
+
+ HBufC8* PKCS8PrivateKey = object->GetOctetStringL();
+ iPKCS8PrivateKeyArray->AppendL( PKCS8PrivateKey );
+
+ if ( ++objectNum < set->Count() )
+ {
+ object = set->At( objectNum );
+ iPrivateKeyIdArray.Append( GetLocalKeyId( aSafeBag ) );
+ }
+
+ CleanupStack::PopAndDestroy( numberOfItemsinCStack, set );
+
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::DecryptShroudedKeybagL
+// DecryptShroudedKeybag.
+// Parameters:
+// Return Values:
+// -----------------------------------------------------------------------------
+void CCrPKCS12::DecryptShroudedKeybagL( CCrData& aSafeBag )
+ {
+ TInt numberOfItemsinCStack = 0;
+ CCrBerSet* set = NULL;
+ TInt errData = KErrNone;
+
+ set = CCrBerSet::NewLC( 1 );
+ ++numberOfItemsinCStack;
+
+ CCrBer* object = NULL;
+ TInt objectNum = KFirstObject;
+
+ set->OpenL( &aSafeBag,KOpenAllLevels );
+
+ object = set->At( objectNum );
+
+ // This one needs first to be decrypted, first we open SafeBag and
+ // then we decrypt encyrpted PrivateKey
+
+ // Decryption Starts
+ // -----------------
+ if ( object->Type() != KBerImplicitConstructed )
+ {
+ User::Leave(KErrArgument);
+ }
+
+ object = set->At( ++objectNum );
+
+ if ( !object->IsSeqOrSet( object->Type() ) )
+ {
+ User::Leave(KErrArgument);
+ }
+
+ object = set->At( ++objectNum );
+
+ if ( !object->IsSeqOrSet( object->Type() ) )
+ {
+ User::Leave(KErrArgument);
+ }
+
+ object = set->At( ++objectNum );
+
+ if ( object->Type() != KBerOid)
+ {
+ User::Leave(KErrArgument);
+ }
+
+ // Algorithm
+ HBufC* oid = object->GetOidL();
+ CleanupStack::PushL(oid);
+
+ TInt algorithm = GetAlgorithmL( oid );
+
+ CleanupStack::PopAndDestroy(oid);
+ oid = NULL;
+
+ object = set->At( ++objectNum );
+
+ if (!object->IsSeqOrSet(object->Type()))
+ {
+ User::Leave(KErrArgument);
+ }
+
+ object = set->At( ++objectNum );
+
+ if ( object->Type() != KBerOctetString )
+ {
+ User::Leave(KErrArgument);
+ }
+
+ // Salt
+ HBufC8* salt = object->GetOctetStringL();
+ CleanupStack::PushL(salt);
+ ++numberOfItemsinCStack;
+
+ object = set->At( ++objectNum );
+
+ if ( object->Type() != KBerInteger)
+ {
+ User::Leave(KErrArgument);
+ }
+
+ // Iterations
+ TInt iter = 1;
+ iter = object->GetIntegerL();
+
+ object = set->At( ++objectNum );
+
+ if ( object->Type() != KBerOctetString )
+ {
+ User::Leave(KErrArgument);
+ }
+
+ // EncryptedData
+ HBufC8* encryptedPrivateKeyInfo = object->GetOctetStringL();
+ CleanupStack::PushL(encryptedPrivateKeyInfo);
+ ++numberOfItemsinCStack;
+
+ if ( errData < KErrNone )
+ {
+ User::Leave(KErrArgument);
+ }
+
+ // Decrypt
+ if ( !DecryptPrivateKeyL( encryptedPrivateKeyInfo,
+ salt,
+ iter,
+ algorithm ) )
+ {
+ User::Leave(KErrArgument);
+ }
+
+ // Decryption Ends
+ // ---------------
+
+ if ( ++objectNum < set->Count() )
+ {
+ object = set->At( objectNum );
+ iPrivateKeyIdArray.Append(GetLocalKeyId( aSafeBag ));
+ }
+
+ CleanupStack::PopAndDestroy(numberOfItemsinCStack, set);
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::GetLocalKeyId
+// Gets pkcs12-SafeBag-attribute LocalKeyId
+// Parameters: CCrData& aBagData SafeBag
+// Return Values: TBool
+// -----------------------------------------------------------------------------
+HBufC8* CCrPKCS12::GetLocalKeyId( CCrData& aBagData )
+ {
+ CCrBerSet* set = NULL;
+ CCrBer* object;
+ TInt errData = KErrNone;
+
+ TRAP( errData,set = CCrBerSet::NewL( 1 ) );
+
+ if ( errData < KErrNone )
+ {
+ return NULL;
+ }
+
+ TInt objectNum = KFirstObject;
+
+ TRAP( errData,set->OpenL( &aBagData,KOpenAllLevels ) );
+
+ if ( errData < KErrNone )
+ {
+ delete set;
+ set = NULL;
+ return NULL;
+ }
+
+ TInt count = set->Count();
+
+ // If there are attributes,
+ if( count > 0 )
+ {
+ // continue,
+ object = set->At( KFirstObject );
+ }
+ else
+ {
+ // otherwise go away.
+ delete set;
+ set = NULL;
+ return NULL;
+ }
+
+ // Attributes begin
+ if ( !object->IsSeqOrSet( object->Type() ) )
+ {
+ delete set;
+ set = NULL;
+ return NULL;
+ }
+
+ // Some applications seem to put an empty set in the
+ // place of LocalKeyId. If so, give up.
+ if (object->ContentLen() == 0)
+ {
+ delete set;
+ set = NULL;
+ return NULL;
+ }
+
+ // If there are more ber-objects left,
+ if ( count > ++objectNum )
+ {
+ // get next,
+ object = set->At( objectNum );
+ }
+ else
+ {
+ // otherwise give up.
+ delete set;
+ set = NULL;
+ return NULL;
+ }
+
+ // First attribute
+ if ( !object->IsSeqOrSet( object->Type() ) )
+ {
+ delete set;
+ set = NULL;
+ return NULL;
+ }
+
+ // Remember, at what level we are
+ TUint level = object->Level();
+ TBool stop = EFalse;
+
+ object = set->At( ++objectNum );
+
+ for( TInt i = objectNum ; i < count && !stop; i++ )
+ {
+ object = set->At( i );
+
+ if ( object->Level() < level )
+ {
+ stop = ETrue;
+ }
+
+ // What is it?
+ if ( object->Type() == KBerOid )
+ {
+ HBufC* oid = NULL;
+
+ TRAP( errData,oid = object->GetOidL() );
+
+ if ( errData < KErrNone )
+ {
+ delete set;
+ set = NULL;
+ return NULL;
+ }
+
+ if ( *oid == Kpkcs9LocalKeyId )
+ {
+ /// BEGIN OF WORKAROUND ///
+ /* There is a major error in this library which causes that in certain
+ situations the localKeyId attribute is found for certificate even though
+ it is not specified in the file. This happens when for example private key buffer
+ is right after CA certificate buffer in bag data. After the CA certificate is parsed then
+ the module starts searching for localKeyId and it founds it from the private key buffer.
+ This buffer contains localKeyId and thus CA certificate is wrongly identified to be
+ user certificate. A proper solution would be somehow limit the searching to correct ASN.1 sets
+ but there's no time for that now. This is a ugly quick fix for this problem:
+ Zero the localKeyId oid so that it is used only once. */
+
+ CCrData* data = object->Data();
+ TInt start = object->ContentBegin();
+ TInt len = object->ContentLen();
+ data->Zero(start, len);
+
+ // END OF WORKAROUND ///
+ i += 2;
+
+ if ( count > i )
+ {
+ object = set->At( i );
+ HBufC8* buf = NULL;
+
+ // Now we can read LocalKeyId
+ TRAP( errData,buf = object->GetOctetStringL() );
+
+ if ( errData < KErrNone )
+ {
+ delete set;
+ set = NULL;
+ return NULL;
+ }
+
+ stop = ETrue;
+ delete set;
+ set = NULL;
+ delete oid;
+ oid = NULL;
+ return buf;
+ }
+ }
+ delete oid;
+ oid = NULL;
+ }
+ }
+
+ delete set;
+ set = NULL;
+ return NULL;
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::DecodeCertBagL
+// DecodeCertBag.
+// Parameters:
+// Return Values: TBool
+// -----------------------------------------------------------------------------
+void CCrPKCS12::DecodeCertBagL( CCrData& aSafeBags )
+ {
+ TInt numberOfItemsinCStack = 0;
+ CCrBerSet* set = NULL;
+
+ set = CCrBerSet::NewLC( 1 );
+ ++numberOfItemsinCStack;
+
+
+ CCrBer* object;
+ TInt objectNum = KFirstObject;
+
+ set->OpenL( &aSafeBags,KOpenAllLevels );
+
+ object = set->At( objectNum );
+
+ // CertificateBags are decrypted at this phase and they just need
+ // to be decoded from a certificate bag and added to certificate set.
+ // LocalKeyId is used to check if certificate is user's.
+
+ // Decoding starts
+ // -----------------
+ if ( object->Type() != KBerImplicitConstructed )
+ {
+ User::Leave(KErrArgument);
+ }
+
+ object = set->At( ++objectNum );
+
+ if ( !object->IsSeqOrSet( object->Type() ) )
+ {
+ User::Leave(KErrArgument);
+ }
+
+ object = set->At( ++objectNum );
+
+ if ( object->Type() != KBerOid )
+ {
+ User::Leave(KErrArgument);
+ }
+
+ // Algorithm
+ HBufC* oid = NULL;
+
+ oid = object->GetOidL();
+ CleanupStack::PushL(oid);
+
+ if ( *oid != Kx509certificate )
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+ CleanupStack::PopAndDestroy(oid);
+ oid = NULL;
+
+ object = set->At( ++objectNum );
+
+ if ( object->Type() != KBerImplicitConstructed )
+ {
+ User::Leave(KErrArgument);
+ }
+
+ object = set->At( ++objectNum );
+
+ if ( object->Type() != KBerOctetString )
+ {
+ User::Leave(KErrArgument);
+ }
+
+ HBufC8* x509certificate = object->GetOctetStringL();
+ CleanupStack::PushL(x509certificate);
+ ++numberOfItemsinCStack;
+
+ // For identifying certificate's type.
+ HBufC8* localKeyId = NULL;
+
+ if ( ++objectNum < set->Count() )
+ {
+ object = set->At( objectNum );
+ localKeyId = GetLocalKeyId( aSafeBags );
+ }
+ TBool isCA = EFalse;
+ CX509Certificate* cert = CX509Certificate::NewLC( *x509certificate );
+
+
+ // Check certificate version
+ if ( cert->Version() != KX509Version3 )
+ {
+ isCA = cert->IsSelfSignedL();
+ }
+ else
+ {
+ // X509 v3 certificate. Check basicConstrains
+ const CX509CertExtension* certExt = cert->Extension( KBasicConstraints );
+ if ( certExt )
+ {
+ CX509BasicConstraintsExt* basic = CX509BasicConstraintsExt::NewLC( certExt->Data() );
+ isCA = basic->IsCA();
+ CleanupStack::PopAndDestroy( basic ); //basic
+ }
+ else
+ {
+ isCA = cert->IsSelfSignedL();
+ }
+ }
+
+
+ CleanupStack::PopAndDestroy( cert );
+
+ if( localKeyId == NULL || isCA )
+ {
+ if ( localKeyId )
+ {
+ delete localKeyId;
+ localKeyId = NULL;
+ }
+ // Add to CAcertificates;
+ PutCertsIntoSetL( iCACertificates, iCACertificateBuffer, x509certificate );
+ // Do not delete x509certificate in this case
+ CleanupStack::Pop(x509certificate);
+ --numberOfItemsinCStack;
+ }
+ else
+ {
+ CleanupStack::PushL(localKeyId);
+ ++numberOfItemsinCStack;
+ for (TInt i = 0; i < iPrivateKeyIdArray.Count(); ++i)
+ {
+ if (*localKeyId == *(iPrivateKeyIdArray[i]))
+ {
+ PutCertsIntoSetL( iUserCertificates,iUserCertificateBuffer, x509certificate );
+ CleanupStack::PopAndDestroy(localKeyId);
+ --numberOfItemsinCStack;
+ // Do not delete x509certificate in this case
+ CleanupStack::Pop(x509certificate);
+ --numberOfItemsinCStack;
+ break;
+ }
+ }
+ }
+ /*else
+ {
+ delete x509certificate;
+ x509certificate = NULL;
+ }
+*/
+
+ CleanupStack::PopAndDestroy(numberOfItemsinCStack, set);
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::DecryptDataL
+// -----------------------------------------------------------------------------
+void CCrPKCS12::DecryptDataL( const TDesC8& aEncryptedData,
+ const TDesC8& aSalt,
+ TInt aIter,
+ TInt aAlgorithm,
+ TDes8& aDecryptedData )
+ {
+ HBufC8* keyBuf = NULL;
+ TBuf8<8> iv;
+ TInt keySize = 0;
+ TInt numberOfItemsinCStack = 0;
+
+ CCrCrypto* crypto = CCrCrypto::NewLC();
+ ++numberOfItemsinCStack;
+
+ switch(aAlgorithm)
+ {
+ case ECrKpbeWithSHAAnd128BitRC2_CBC:
+ {
+ keySize = K128BitRC2KeySize;
+ break;
+ }
+ case ECrKpbeWithSHAAnd40BitRC2_CBC:
+ {
+ keySize = K40BitRC2KeySize;
+ break;
+ }
+ case ECrpbeWithSHAAnd3_KeyTripleDES_CBC:
+ {
+ // We need 3 keys for triple DES.
+ keySize = 3 * KDesKeySize;
+ break;
+ }
+ case ECrpbeWithSHAAnd2_KeyTripleDES_CBC:
+ {
+ keySize = 2 * KDesKeySize;
+ break;
+ }
+ default:
+ {
+ User::Leave(KErrNotSupported);
+ }
+ }
+ keyBuf = HBufC8::NewLC(keySize);
+ ++numberOfItemsinCStack;
+ TPtr8 keyPtr = keyBuf->Des();
+ // Get key.
+ crypto->DeriveKeyPKCS12L(*iPassWord,
+ aSalt,
+ aIter,
+ ECrSHA1,
+ KId1,
+ keySize,
+ keyPtr);
+
+ // Get IV
+ crypto->DeriveKeyPKCS12L(*iPassWord,
+ aSalt,
+ aIter,
+ ECrSHA1,
+ KId2,
+ iv.MaxSize(),
+ iv);
+
+
+ switch(aAlgorithm)
+ {
+ case ECrKpbeWithSHAAnd128BitRC2_CBC:
+ {
+ crypto->InitCryptRC2L(*keyBuf, iv, EFalse, 8*K128BitRC2KeySize);
+ break;
+ }
+ case ECrKpbeWithSHAAnd40BitRC2_CBC:
+ {
+ crypto->InitCryptRC2L(*keyBuf, iv, EFalse, 40);
+ break;
+ }
+ case ECrpbeWithSHAAnd3_KeyTripleDES_CBC:
+ {
+ crypto->InitCrypt3DESL(
+ keyPtr.Left(KDesKeySize), keyPtr.Mid(KDesKeySize, KDesKeySize),
+ keyPtr.Right(KDesKeySize), iv, EFalse);
+ break;
+ }
+ case ECrpbeWithSHAAnd2_KeyTripleDES_CBC:
+ {
+ crypto->InitCrypt3DESL(
+ keyPtr.Left(KDesKeySize), keyPtr.Right(KDesKeySize),
+ keyPtr.Left(KDesKeySize), iv, EFalse);
+ break;
+ }
+ default:
+ {
+ User::Leave(KErrNotSupported);
+ }
+ }
+ crypto->ProcessL(aEncryptedData, aDecryptedData);
+ crypto->FinalCryptL(aDecryptedData);
+ CleanupStack::PopAndDestroy(numberOfItemsinCStack, crypto);
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::DecryptPrivateKey
+// DecryptPrivateKey.
+// Parameters:
+// Return Values:
+// -----------------------------------------------------------------------------
+
+TBool CCrPKCS12::DecryptPrivateKeyL( HBufC8* aEncryptedPrivateKey,
+ HBufC8* aSalt,
+ TInt aIter,
+ TInt aAlgorithm )
+ {
+ TBool returnValue = ETrue;
+ HBufC8* privateKey = HBufC8::NewLC(aEncryptedPrivateKey->Length());
+ TPtr8 privateKeyPtr = privateKey->Des();
+ TPtr8 paEncryptedPrivateKey = aEncryptedPrivateKey->Des();
+ TPtr8 paSalt = aSalt->Des();
+
+ DecryptDataL(*aEncryptedPrivateKey, *aSalt, aIter, aAlgorithm, privateKeyPtr);
+
+ HBufC8* PKCS8PrivateKey = HBufC8::NewL(privateKey->Length());
+ PKCS8PrivateKey->Des().Copy(*privateKey);
+ iPKCS8PrivateKeyArray->AppendL(PKCS8PrivateKey);
+
+ CleanupStack::PopAndDestroy(privateKey);
+ return returnValue;
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::VerifyMacFromEightBytePassword
+// This function generates double byte pasword from given eight byte
+// password and calls VerifyMac.
+// Parameters: aPassWord password given to open function
+// Return Values: TBool If OK, returns ETrue and if not, EFalse
+// -----------------------------------------------------------------------------
+TBool CCrPKCS12::VerifyMacFromEightBytePassword(const TDesC8& aPassWord)
+ {
+ TInt errData = KErrNone;
+
+ // Alloc Space for password in pkcs12-format. Needed space is
+ // 2 * aPassWord + 2
+ if (iPassWord == NULL)
+ {
+ TRAP( errData,iPassWord = HBufC8::NewL( (2 * aPassWord.Length()) + 2) );
+
+ if ( errData < KErrNone )
+ {
+ return EFalse;
+ }
+ }
+
+ // Pointer to allocated pkcs12PassWord
+ TPtr8 aPkcs12PassWord = iPassWord->Des();
+
+ // Make sure password is empty.
+ aPkcs12PassWord = _L8("");
+
+ // Append 0x00 between characters
+ for( TInt i = 0 ; i < aPassWord.Length() ; i++ )
+ {
+ aPkcs12PassWord.Append(0x00);
+ aPkcs12PassWord.Append(aPassWord[i]);
+ }
+
+ // Append last 0x00 0x00
+ aPkcs12PassWord.Append(0x00);
+ aPkcs12PassWord.Append(0x00);
+
+ TBool result = EFalse;
+ TRAP(errData, result = VerifyMacL(aPkcs12PassWord));
+ if ( errData < KErrNone )
+ {
+ return EFalse;
+ }
+ return result;
+ }
+// -----------------------------------------------------------------------------
+// CCrPKCS12::VerifyMacL
+// Verifies Mac. This function generates mac with password given to
+// open function above, salt and iteration count, It uses crypto-
+// library to do that. Generated mac is compared with iMac (mac within
+// pkcs12 file) and if they are the same, password was OK and if they
+// weren't the same, password was wrong, or file is corrupted.
+// Parameters: aPassWord password given to open function
+// Return Values: TBool If OK, returns ETrue and if not, EFalse
+// -----------------------------------------------------------------------------
+TBool CCrPKCS12::VerifyMacL(const TDesC8& aPassWord)
+ {
+ TPtr8 pContentInfo = iContentInfo->Des();
+
+ // Key to be derivated
+ iDecryptionKey = HBufC8::NewL( iMac->Length() );
+ TPtr8 pDecryptionKey = iDecryptionKey->Des();
+
+ TInt numberOfItemsInCStack = 0;
+ // Mac to be calculated
+ HBufC8* mac = HBufC8::NewLC( iMac->Length() );
+ numberOfItemsInCStack++;
+ TPtr8 pMac = mac->Des();
+
+ CCrCrypto* crypto = CCrCrypto::NewLC();
+ numberOfItemsInCStack++;
+
+ if ( iHMACalgorithm == ECrSHA1 )
+ {
+ crypto->DeriveKeyPKCS12L(aPassWord,
+ *iSalt,
+ iIter,
+ ECrSHA1,
+ KId3,
+ iMac->Length(),
+ pDecryptionKey);
+
+ // Initialize HMAC SHA-1 algorithm
+ crypto->InitDigestHMACL( pDecryptionKey,ECrSHA1 );
+ }
+ else
+ {
+ CleanupStack::PopAndDestroy(numberOfItemsInCStack);
+ return EFalse;
+ }
+
+ // Process data (filedata)
+ crypto->ProcessL( pContentInfo, pMac);
+
+ // Final digest algorithm
+ crypto->FinalDigest( pMac );
+
+ if ( pMac == *iMac )
+ {
+ CleanupStack::PopAndDestroy(numberOfItemsInCStack);
+ return ETrue;
+ }
+ else
+ {
+ CleanupStack::PopAndDestroy(numberOfItemsInCStack);
+ return EFalse;
+ }
+ }
+
+TBool CCrPKCS12::VerifyMacL(const TDesC16& aPassWord)
+ {
+ TUint8 halfCharacter;
+ TUint16 character;
+
+ // Alloc Space for password in pkcs12-format. Needed space is
+ // 2 * aPassWord + 2
+ if (iPassWord == NULL)
+ {
+ iPassWord = HBufC8::NewL( (2 * aPassWord.Length()) + 2);
+ }
+
+ // Pointer to allocated pkcs12PassWord
+ TPtr8 pPkcs12PassWord = iPassWord->Des();
+
+ // Make sure password is empty.
+ pPkcs12PassWord = _L8("");
+
+ // Divide characters into bytes and append them.
+ for (TInt i = 0; i < aPassWord.Length(); i++)
+ {
+ character = aPassWord[i];
+
+ halfCharacter = (TUint8) (character >> 8);
+ pPkcs12PassWord.Append(halfCharacter);
+
+ halfCharacter = (TUint8) (character & 0xFF);
+ pPkcs12PassWord.Append(halfCharacter);
+ }
+
+ // Append last 0x00 0x00
+ pPkcs12PassWord.Append(0x00);
+ pPkcs12PassWord.Append(0x00);
+
+ return VerifyMacL(pPkcs12PassWord);
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::JumpNextObjectAtSameLevel
+// Returns integer value of how many objects shoud be jumped to get
+// next object at same level. Works, when CCrBer-library works with
+// definite values correctly.
+// Parameters: None.
+// Return Values: TUint Next object's index-number at same level
+// -----------------------------------------------------------------------------
+TUint CCrPKCS12::JumpNextObjectAtSameLevel()
+ {
+ TUint levelAt = iberObject->Level();
+ TUint jumps = 1;
+
+ TUint index_to = iObjectNum + 1;
+
+ iberObject = iberSet->At( index_to );
+
+ while( iberObject->Level() != levelAt )
+ {
+ jumps++;
+ index_to++;
+ iberObject = iberSet->At( index_to );
+ }
+
+ return jumps;
+ }
+// -----------------------------------------------------------------------------
+// CCrPKCS12::GetAlgorithm
+// This function identifies algorithm and returns integer about what
+// algorithm was. Algorithm is identified via ObjectIdentifier.
+// For example, in case if aBuf = "1.2.840.113549.1.12.1.2",
+// (pbeWithSHAAnd40BitRC4) function returns 2.
+// Parameters: aBuf buffer containing ObjectIdentifier
+// Return Values: TUint Last number of an algorithm
+// -----------------------------------------------------------------------------
+TUint CCrPKCS12::GetAlgorithmL( HBufC* aBuf )
+ {
+ // What is the algorithm?
+ TUint algorithm = 0;
+
+ if ( *aBuf == KpbeWithSHAAnd128BitRC4 )
+ {
+ algorithm = ECrpbeWithSHAAnd128BitRC4;
+ }
+ else if ( *aBuf == KpbeWithSHAAnd40BitRC4 )
+ {
+ algorithm = ECrpbeWithSHAAnd40BitRC4;
+ }
+ else if ( *aBuf == KpbeWithSHAAnd3_KeyTripleDES_CBC )
+ {
+ algorithm = ECrpbeWithSHAAnd3_KeyTripleDES_CBC;
+ }
+ else if ( *aBuf == KpbeWithSHAAnd2_KeyTripleDES_CBC )
+ {
+ algorithm = ECrpbeWithSHAAnd2_KeyTripleDES_CBC;
+ }
+ else if ( *aBuf == KpbeWithSHAAnd128BitRC2_CBC )
+ {
+ algorithm = ECrKpbeWithSHAAnd128BitRC2_CBC;
+ }
+ else if ( *aBuf == KpbeWithSHAAnd40BitRC2_CBC )
+ {
+ algorithm = ECrKpbeWithSHAAnd40BitRC2_CBC;
+ }
+ else
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+ return algorithm;
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::PutCertsIntoSet
+// This function puts all certificates into set given at parameter.
+// DecodeCertsL calls this functiuon.
+// Parameters: *set Set, where certificates will be put into
+// Return Values: TInt Value of error
+// -----------------------------------------------------------------------------
+void CCrPKCS12::PutCertsIntoSetL( CX509CertificateSet* aSet,
+ CArrayPtrFlat<TDesC8>* aBufSet,
+ HBufC8* aX509certificate )
+ {
+ // Pointer to certificate given at third parameter
+ TPtr8 paX509certificate = aX509certificate->Des();
+
+ // Add certificate to CertificateSet given at first parameter
+ aSet->DecodeCertsL( paX509certificate );
+
+ // Add certificate to CertificateSet given at second parameter
+ aBufSet->AppendL(aX509certificate);
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::GetPrivateKeys
+// -----------------------------------------------------------------------------
+const CArrayPtrFlat<HBufC8>& CCrPKCS12::PrivateKeys() const
+ {
+ return *iPKCS8PrivateKeyArray;
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::GetUserCertificates
+// This function returns CX509CertificateSet, set of CX509Certificates,
+// that are defined in certman. These certificates are user certificates.
+// All certificates from X509Certificates are tested and if certificate
+// isn't CA Certificate and if KeyUsage don't mach to one given at
+// parameter, it is removed from set. After that, UserCertificates
+// (type CX509CertificateSet *) are returned to caller.
+// Parameters: TKeyUsage aKeyUsage.
+// Return Values: CX509CertificateSet* Pointer to the CX509CertificateSet.
+// -----------------------------------------------------------------------------
+const CX509CertificateSet& CCrPKCS12::UserCertificates() const
+ {
+ return *iUserCertificates;
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::GetUserCertificateBuffer
+// This function returns CX509CertificateSet, set of CX509Certificates,
+// that are defined in certman. These certificates are user certificates.
+// All certificates from X509Certificates are tested and if certificate
+// isn't CA Certificate and if KeyUsage don't mach to one given at
+// parameter, it is removed from set. After that, UserCertificateBuffer
+// (type CArrayPtrFlat<TDes>* ) are returned to caller.
+// Parameters: TKeyUsage aKeyUsage.
+// Return Values: CArrayPtrFlat<TDesC8>* Pointer to a buffer.
+// -----------------------------------------------------------------------------
+const CArrayPtrFlat<TDesC8>& CCrPKCS12::UserCertificateBuffer() const
+
+ {
+ return *iUserCertificateBuffer;
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::GetCACertificates
+// This function returns CX509CertificateSet, set of CX509Certificates,
+// that are defined in certman. These certificates are CA certificates.
+// All certificates from X509Certificates are tested and if certificate
+// isn't CA Certificate, it is removed from set. After that,
+// CACertificates (type CX509CertificateSet *) are returned to caller.
+// Parameters: none.
+// Return Values: CX509CertificateSet* Pointer to the CX509CertificateSet.
+// -----------------------------------------------------------------------------
+const CX509CertificateSet& CCrPKCS12::CACertificates() const
+ {
+ return *iCACertificates;
+ }
+// -----------------------------------------------------------------------------
+// CCrPKCS12::GetCACertificateBuffer
+// This function returns CX509CertificateSet, set of CX509Certificates,
+// that are defined in certman. These certificates are CA certificates.
+// All certificates from X509Certificates are tested and if certificate
+// isn't CA Certificate, it is removed from set. After that,
+// CACertificates (type CArrayPtrFlat<TDesC8>*) are returned to caller.
+// Parameters: none.
+// Return Values: CArrayPtrFlat<TDesC8>* Pointer to the CX509CertificateSet.
+// -----------------------------------------------------------------------------
+const CArrayPtrFlat<TDesC8>& CCrPKCS12::CACertificateBuffer() const
+ {
+ return *iCACertificateBuffer;
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::GetIter
+// This function returns the number of iterations
+// Parameters: none
+// Returns: TUint Number of iterations.
+// -----------------------------------------------------------------------------
+
+TUint CCrPKCS12::Iter()
+ {
+ return iIter;
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::GetMac
+// This function returns the mac
+// Parameters: none
+// Returns: HBufC8* Pointer to mac.
+// -----------------------------------------------------------------------------
+HBufC8* CCrPKCS12::Mac()
+ {
+ return iMac;
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::GetSalt
+// This function returns the salt
+// Parameters: none
+// Returns: HBufC8* Pointer to salt.
+// -----------------------------------------------------------------------------
+HBufC8* CCrPKCS12::Salt()
+ {
+ return iSalt;
+ }
+
+// -----------------------------------------------------------------------------
+// CCrPKCS12::GetSafeBagsCount
+// This function returns number of SafeBags
+// Parameters: none
+// Returns: TInt Number of SafeBags
+// -----------------------------------------------------------------------------
+TUint CCrPKCS12::SafeBagsCount()
+ {
+ return iSafeBagsCount;
+ }
+// EOF