cryptoservices/asnpkcs/source/asnpkcs5.cpp
changeset 8 35751d3474b7
parent 0 2c201484c85f
--- a/cryptoservices/asnpkcs/source/asnpkcs5.cpp	Tue Jul 21 01:04:32 2009 +0100
+++ b/cryptoservices/asnpkcs/source/asnpkcs5.cpp	Thu Sep 10 14:01:51 2009 +0300
@@ -1,496 +1,504 @@
-/*
-* Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
-* All rights reserved.
-* This component and the accompanying materials are made available
-* under the terms of the License "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: 
-*
-*/
-
-
-#include <asn1enc.h>
-#include <asn1dec.h>
-#include <pbedata.h>
-#include <rc2.h>
-
-#include "asnpkcs.h"
-
-_LIT(Kpkcs5PBES2, "1.2.840.113549.1.5.13");
-_LIT(Kpkcs5PBKDF2, "1.2.840.113549.1.5.12");
-_LIT(KDESCBC, "1.3.14.3.2.7");
-_LIT(K3DESCBC, "1.2.840.113549.3.7");
-_LIT(KRC2CBC, "1.2.840.113549.3.2");
-
-// pbe12Algorithm Ids
-_LIT(KPbeWithSHA1And128BitRC4, "1.2.840.113549.1.12.1.1");
-_LIT(KPbeWithSHA1And40BitRC4, "1.2.840.113549.1.12.1.2");
-_LIT(KPbeWithSHA1And3_KeyTripleDES_CBC, "1.2.840.113549.1.12.1.3");
-_LIT(KPbeWithSHA1And2_KeyTripleDES_CBC, "1.2.840.113549.1.12.1.4");
-_LIT(KPbeWithSHA1And128BitRC2_CBC, "1.2.840.113549.1.12.1.5");
-_LIT(KPbeWithSHA1And40BitRC2_CBC, "1.2.840.113549.1.12.1.6");
-//The size of the Initialization vector
-const TInt KIvSize = 8;
-
-
-/*
-* //For RC2
-* SEQUENCE
-* 	OID -- pkcs5PBES2
-*	SEQUENCE
-*		SEQUENCE
-*		OID -- pkcs5PBKDF2
-*		SEQUENCE
-*			OCTET STRING -- salt
-*			INTEGER -- iteration count
-*			INTEGER -- effective key length in octets
-* 	SEQUENCE
-*		OID -- algorithm id (rc2)
-*		SEQUENCE
-*			INTEGER -- RC2 parameter version 58 = 128, 160 = 40
-*			OCTET STRING -- iv
-*
-* //For DES and 3DES
-* SEQUENCE
-* 	OID -- pkcs5PBES2
-*	SEQUENCE
-*		SEQUENCE
-*		OID -- pkcs5PBKDF2
-*		SEQUENCE
-*			OCTET STRING -- salt
-*			INTEGER -- iteration count
-* 	SEQUENCE
-*		OID -- algorithm id (des, 3des)
-*		OCTET STRING -- iv
-*/
-
-EXPORT_C CASN1EncSequence* TASN1EncPKCS5::EncodeDERL(const CPBEncryptParms& aParms)
-	{
-	CASN1EncSequence* seq = CASN1EncSequence::NewLC();
-	CASN1EncObjectIdentifier* pbes2 = CASN1EncObjectIdentifier::NewLC(Kpkcs5PBES2);
-	seq->AddChildL(pbes2);
-	CleanupStack::Pop(pbes2);
-
-	CASN1EncSequence* seq1 = CASN1EncSequence::NewLC();
-	seq->AddChildL(seq1);
-	CleanupStack::Pop(seq1);
-
-	CASN1EncSequence* seq2 = CASN1EncSequence::NewLC();
-	seq1->AddChildL(seq2);
-	CleanupStack::Pop(seq2);
-
-	CASN1EncObjectIdentifier* pbkdf2 = CASN1EncObjectIdentifier::NewLC(Kpkcs5PBKDF2);
-	seq2->AddChildL(pbkdf2);
-	CleanupStack::Pop(pbkdf2);
-
-	CASN1EncSequence* seq3 = CASN1EncSequence::NewLC();
-	seq2->AddChildL(seq3);
-	CleanupStack::Pop(seq3);
-
-	CASN1EncOctetString* salt = CASN1EncOctetString::NewLC(aParms.Salt());
-	seq3->AddChildL(salt);
-	CleanupStack::Pop(salt);
-
-	CASN1EncInt* iterations = CASN1EncInt::NewLC(aParms.Iterations());
-	seq3->AddChildL(iterations);
-	CleanupStack::Pop(iterations);
-
-	CASN1EncInt* keysize = 0;
-	switch(aParms.Cipher())
-		{
-		case ECipherDES_CBC:
-		case ECipher3DES_CBC: 
-			break;
-		case ECipherRC2_CBC_40:
- 			keysize = CASN1EncInt::NewLC(KSSLCompatibilityBits/8);  // effective key length in *octets*
-			seq3->AddChildL(keysize);
-			CleanupStack::Pop(keysize);
-			break;
-		case ECipherRC2_CBC_128:
- 			keysize = CASN1EncInt::NewLC(KSSLCompatibilityBits/8);  // effective key length in *octets*
-			seq3->AddChildL(keysize);
-			CleanupStack::Pop(keysize);
-			break;
-		case ECipherRC2_CBC_40_16:
- 			keysize = CASN1EncInt::NewLC(KPkcs8CompatibilityBits/8);  // effective key length in *octets*
-			seq3->AddChildL(keysize);
-			CleanupStack::Pop(keysize);
-			break;
-		case ECipherRC2_CBC_128_16:
- 			keysize = CASN1EncInt::NewLC(KPkcs8CompatibilityBits/8);  // effective key length in *octets*
-			seq3->AddChildL(keysize);
-			CleanupStack::Pop(keysize);
-			break;
-		default:
-			User::Leave(KErrNotSupported);
-			break;
-		}
-
-	CASN1EncSequence* seq4 = CASN1EncSequence::NewLC();
-	seq1->AddChildL(seq4);
-	CleanupStack::Pop(seq4);
-
-	CASN1EncObjectIdentifier* algid = 0;
-	switch(aParms.Cipher())
-		{
-		case ECipherDES_CBC:
-			algid = CASN1EncObjectIdentifier::NewLC(KDESCBC);
-			break;
-		case ECipher3DES_CBC:
-			algid = CASN1EncObjectIdentifier::NewLC(K3DESCBC);
-			break;
-		case ECipherRC2_CBC_40:
-		case ECipherRC2_CBC_128:
-		case ECipherRC2_CBC_40_16:
-		case ECipherRC2_CBC_128_16:
-			algid = CASN1EncObjectIdentifier::NewLC(KRC2CBC);
-			break;
-		default:
-			User::Leave(KErrNotSupported);
-			break;
-		}
-	seq4->AddChildL(algid);
-	CleanupStack::Pop(algid);
-
-	CASN1EncSequence* seq5 = 0;
-	CASN1EncInt* keysize1 = 0;
-	CASN1EncOctetString* iv = 0;
-	switch(aParms.Cipher())
-		{
-		case ECipherDES_CBC:
-		case ECipher3DES_CBC:
-			iv = CASN1EncOctetString::NewLC(aParms.IV());
-			seq4->AddChildL(iv);
-			CleanupStack::Pop(iv);
-			break;
-		case ECipherRC2_CBC_40:
-		case ECipherRC2_CBC_40_16:
-			seq5 = CASN1EncSequence::NewLC();
-			seq4->AddChildL(seq5);
-			CleanupStack::Pop(seq5);
-
-			keysize1 = CASN1EncInt::NewLC(160); //encoding for 40 bit
-			seq5->AddChildL(keysize1);
-			CleanupStack::Pop(keysize1);
-
-			iv = CASN1EncOctetString::NewLC(aParms.IV());
-			seq5->AddChildL(iv);
-			CleanupStack::Pop(iv);
-			break;
-		case ECipherRC2_CBC_128:
-		case ECipherRC2_CBC_128_16:
-			seq5 = CASN1EncSequence::NewLC();
-			seq4->AddChildL(seq5);
-			CleanupStack::Pop(seq5);
-			
-			keysize1 = CASN1EncInt::NewLC(58); //encoding for 128 bit
-			seq5->AddChildL(keysize1);
-			CleanupStack::Pop(keysize1);
-
-			iv = CASN1EncOctetString::NewLC(aParms.IV());
-			seq5->AddChildL(iv);
-			CleanupStack::Pop(iv);
-			break;
-		default:
-			User::Leave(KErrNotSupported);
-			break;
-		}
-	CleanupStack::Pop(seq);
-	return seq;
-	}
-
-EXPORT_C CPBEncryptParms* TASN1DecPKCS5::DecodeDERL(const TDesC8& aBinaryData)
-	{
-	TASN1DecGeneric seqGen(aBinaryData);
-	seqGen.InitL();
-	if (seqGen.Tag() != EASN1Sequence)
-		{
-		User::Leave(KErrArgument);
-		}
-	
-	//Decode the Algorithm Identifier Sequence
-	TASN1DecSequence seq;
-	CArrayPtrFlat<TASN1DecGeneric>* seqContents = seq.DecodeDERLC(seqGen);
-
-	//PbeAlgorithm Id
-	if (seqContents->At(0)->Tag() != EASN1ObjectIdentifier)
-		{
-		User::Leave(KErrArgument);
-		}	
-	CPBEncryptParms* params = NULL;	
-	TASN1DecObjectIdentifier oid;
-	HBufC* oiddes = oid.DecodeDERL(*(seqContents->At(0)));
-	CleanupStack::PushL(oiddes);
-	//Algorithm Id is a pkcs-12Pbe Algorithm Id.
-	if(*oiddes != Kpkcs5PBES2)
-		{
-		// Initialise to impossible value
-		TPBECipher cipher = (TPBECipher) -1; 
-		// Pbe12Algorithm Ids
-		if(*oiddes == KPbeWithSHA1And128BitRC4)
-			{
-			cipher = ECipherARC4_128;
-			}
-		else if(*oiddes == KPbeWithSHA1And40BitRC4)
-			{
-			cipher = ECipherARC4_40;
-			}
-		else if(*oiddes == KPbeWithSHA1And3_KeyTripleDES_CBC)
-			{
-			cipher = ECipher3DES_CBC;
-			}
-		else if(*oiddes == KPbeWithSHA1And2_KeyTripleDES_CBC)
-			{
-			cipher = ECipher2Key3DES_CBC;
-			}
-		else if(*oiddes == KPbeWithSHA1And128BitRC2_CBC)
-			{
-			cipher = ECipherRC2_CBC_128_16; 
-			}
-		else if(*oiddes == KPbeWithSHA1And40BitRC2_CBC)
-			{
-			cipher = ECipherRC2_CBC_40_5; 
-			}
-	    else
-        	{
-        	User::Leave(KErrNotSupported);
-        	}	 
-        
-        TInt seqContentsCount = seqContents->Count();
-		
-		//All pkcs-12Pbe algorithms require the Algorithm Parameters.
-		//Algorithm Parameters are not OPTIONAL for pkcs-12Pbe algorithms.
-		
-		//seqContentsCount should be equal to 2.That is, the Algorithm Id 
-		//and associated Algorithm Parameters have to be present.
-		if(seqContentsCount != 2)
-			{
-			User::Leave(KErrArgument);	
-			}
-		//This if statement checks if the pkcs-12PbeParams Sequence is present in the 
-		//AlgorithmIdentifier Sequence Since pkcs-12PbeParams are OPTIONAL
-		else 
-			{
-			//Set the Initialization vector size to 8 bytes.
-			TBuf8<KIvSize> iv(KIvSize);
-			// Initialized to NULL, if salt is not present.
-			TPtrC8 salt;
-			TInt iterations; 
-
-			const TASN1DecGeneric* seqContentsAt1 = seqContents->At(1);
-			if (seqContentsAt1->Tag() != EASN1Sequence || seqContentsAt1->Class() != EUniversal)
-				{
-				User::Leave(KErrArgument);
-				}
-				
-			CArrayPtrFlat<TASN1DecGeneric>* seq1Contents = seq.DecodeDERLC(*seqContentsAt1);
-			const TASN1DecGeneric* seq1ContentsAt0 = seq1Contents->At(0);
-			if (seq1ContentsAt0->Tag() != EASN1OctetString || seq1ContentsAt0->Class() != EUniversal)
-				{
-				User::Leave(KErrArgument);
-				}
-			salt.Set(seq1ContentsAt0->GetContentDER());
-			const TASN1DecGeneric* seq1ContentsAt1 = seq1Contents->At(1);
-			if (seq1ContentsAt1->Tag() != EASN1Integer || seq1ContentsAt1->Class() != EUniversal)
-				{
-				User::Leave(KErrArgument);
-				}
-			TASN1DecInteger integer;
-			iterations = integer.DecodeDERShortL(*seq1ContentsAt1);
-			if (iterations <= 0)
-				{
-				User::Leave(KErrArgument);
-				}
-			params = CPBEncryptParms::NewL(cipher, salt, iv, iterations);
-			params->SetKdf(CPBEncryptParms::EKdfPkcs12);
-			CleanupStack::PopAndDestroy(seq1Contents);
-			}
-		}
-	//Algorithm Id is a pkcs-5Pbe Algorithm Id.
-   	 else if (*oiddes == Kpkcs5PBES2)
-    	{
-    	if (seqContents->At(1)->Tag() != EASN1Sequence)
-			{
-			User::Leave(KErrArgument);
-			}
-		CArrayPtrFlat<TASN1DecGeneric>* seq1Contents = seq.DecodeDERLC(*(seqContents->At(1)));
-
-		if (seq1Contents->At(0)->Tag() != EASN1Sequence)
-			{
-			User::Leave(KErrArgument);
-			}
-		CArrayPtrFlat<TASN1DecGeneric>* seq2Contents = seq.DecodeDERLC(*(seq1Contents->At(0)));
-
-		if (seq2Contents->At(0)->Tag() != EASN1ObjectIdentifier)
-			{
-			User::Leave(KErrArgument);
-			}
-		HBufC* oid1des = oid.DecodeDERL(*(seq2Contents->At(0)));
-		CleanupStack::PushL(oid1des);
-		
-		if(*oid1des != Kpkcs5PBKDF2)
-			{
-			User::Leave(KErrNotSupported);
-			}
-		if (seq2Contents->At(1)->Tag() != EASN1Sequence)
-			{
-			User::Leave(KErrArgument);
-			}
-		CArrayPtrFlat<TASN1DecGeneric>* seq3Contents = seq.DecodeDERLC(*(seq2Contents->At(1)));
-
-		if (seq3Contents->At(0)->Tag() != EASN1OctetString)
-			{
-			User::Leave(KErrArgument);
-			}
-		TASN1DecOctetString octet;
-		HBufC8* salt = octet.DecodeDERL(*(seq3Contents->At(0)));
-		CleanupStack::PushL(salt);
-		
-		if (seq3Contents->At(1)->Tag() != EASN1Integer)
-			{
-			User::Leave(KErrArgument);
-			}
-		TASN1DecInteger integer;
-		TInt iterations = integer.DecodeDERShortL(*(seq3Contents->At(1)));
-
-		if (seq1Contents->At(1)->Tag() != EASN1Sequence)
-			{
-			User::Leave(KErrArgument);
-			}
-		CArrayPtrFlat<TASN1DecGeneric>* seq4Contents = seq.DecodeDERLC(*(seq1Contents->At(1)));
-	
-		TPBECipher cipher = (TPBECipher) -1; // Initialise to impossible value
-		if (seq4Contents->At(0)->Tag() != EASN1ObjectIdentifier)
-			{
-			User::Leave(KErrArgument);
-			}
-		HBufC* oid2des = oid.DecodeDERL(*(seq4Contents->At(0)));
-		CleanupStack::PushL(oid2des);
-		
-		CArrayPtrFlat<TASN1DecGeneric>* seq5Contents = 0; 
-
-		if(*oid2des == K3DESCBC)
-			{
-			cipher = ECipher3DES_CBC;
-		CleanupStack::PushL(seq5Contents);
-			}
-		else if(*oid2des == KDESCBC)
-			{
-			cipher = ECipherDES_CBC;
-		CleanupStack::PushL(seq5Contents);
-			}
-		else if(*oid2des == KRC2CBC)
-			{
-			// RC2 has an additional parameter, the effective key lenght in octets.
-			if (seq3Contents->At(2)->Tag() != EASN1Integer)
-				{
-				User::Leave(KErrArgument);
-				}		
-			TInt effectiveKeyLength =  integer.DecodeDERShortL(*(seq3Contents->At(2)));
-
-			if (seq4Contents->At(1)->Tag() != EASN1Sequence)
-				{
-				User::Leave(KErrArgument);
-				}
-			seq5Contents = seq.DecodeDERLC(*(seq4Contents->At(1)));
-			if (seq5Contents->At(0)->Tag() != EASN1Integer)
-				{
-				User::Leave(KErrArgument);
-				}
-			TInt keysize = integer.DecodeDERShortL(*(seq5Contents->At(0)));
-			switch(keysize)
-				{
-				// These values come from the PKCS#5 v2 specs
-				case 160:
-					if (effectiveKeyLength == 16)
-						{
-						cipher = ECipherRC2_CBC_40_16;					
-						}
-					else 
-						{
-						if (effectiveKeyLength == 128)
-							{
-							cipher = ECipherRC2_CBC_40;
-							}
-						else 
-							{
-							User::Leave(KErrNotSupported); // Unsupported effective key length!						
-							}
-						}
-					break;
-				case 58:
-					if (effectiveKeyLength == 16)
-						{
-						cipher = ECipherRC2_CBC_128_16;					
-						}
-					else 
-						{
-						if (effectiveKeyLength == 128)
-							{
-							cipher = ECipherRC2_CBC_128;
-							}
-						else 
-							{
-							User::Leave(KErrNotSupported); // Unsupported effective key length!						
-							}
-						}			
-					break;
-				case 120:
-					//would be RC_CBC_64 but we don't support that
-				default:
-					User::Leave(KErrNotSupported);
-					break;
-				}
-			}
-		else 
-			{
-			User::Leave(KErrNotSupported);
-			}	
-
-		HBufC8* iv = 0;
-		switch(cipher)
-			{
-			case ECipher3DES_CBC:
-			case ECipherDES_CBC:
-				if (seq4Contents->At(1)->Tag() != EASN1OctetString)
-					{
-					User::Leave(KErrArgument);
-					}
-				iv = octet.DecodeDERL(*(seq4Contents->At(1)));	
-			CleanupStack::PushL(iv);
-				break;
-			case ECipherRC2_CBC_40:
-			case ECipherRC2_CBC_128:
-			case ECipherRC2_CBC_40_16:
-			case ECipherRC2_CBC_128_16:	
-				if (seq5Contents->At(1)->Tag() != EASN1OctetString)
-					{
-					User::Leave(KErrArgument);
-					}
-				iv = octet.DecodeDERL(*(seq5Contents->At(1)));
-			CleanupStack::PushL(iv);
-				break;
-			default:
-				User::Leave(KErrNotSupported);
-				break;
-			}
-
-		params = CPBEncryptParms::NewL(cipher, *salt, *iv,
-		iterations);
-	CleanupStack::PopAndDestroy(9); //iv, seq5contents, oid2des, seq4Contents,
-	//salt, seq3Contents, oid1des, seq2Contents, seq1Contents
-    	}
-	else
-		{
-		User::Leave(KErrNotSupported);
-		}
-	CleanupStack::PopAndDestroy(2, seqContents);
-	return params;
-	}
+/*
+* Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "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: 
+*
+*/
+
+
+#include <asn1enc.h>
+#include <asn1dec.h>
+#include <pbedata.h>
+#include <rc2.h>
+
+#include "asnpkcs.h"
+
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+
+/** OpenSSL PKCS8 Effective Key Length Compatibility.*/
+const TUint KPkcs8CompatibilityBits = 128;
+
+#endif
+
+
+_LIT(Kpkcs5PBES2, "1.2.840.113549.1.5.13");
+_LIT(Kpkcs5PBKDF2, "1.2.840.113549.1.5.12");
+_LIT(KDESCBC, "1.3.14.3.2.7");
+_LIT(K3DESCBC, "1.2.840.113549.3.7");
+_LIT(KRC2CBC, "1.2.840.113549.3.2");
+
+// pbe12Algorithm Ids
+_LIT(KPbeWithSHA1And128BitRC4, "1.2.840.113549.1.12.1.1");
+_LIT(KPbeWithSHA1And40BitRC4, "1.2.840.113549.1.12.1.2");
+_LIT(KPbeWithSHA1And3_KeyTripleDES_CBC, "1.2.840.113549.1.12.1.3");
+_LIT(KPbeWithSHA1And2_KeyTripleDES_CBC, "1.2.840.113549.1.12.1.4");
+_LIT(KPbeWithSHA1And128BitRC2_CBC, "1.2.840.113549.1.12.1.5");
+_LIT(KPbeWithSHA1And40BitRC2_CBC, "1.2.840.113549.1.12.1.6");
+//The size of the Initialization vector
+const TInt KIvSize = 8;
+
+
+/*
+* //For RC2
+* SEQUENCE
+* 	OID -- pkcs5PBES2
+*	SEQUENCE
+*		SEQUENCE
+*		OID -- pkcs5PBKDF2
+*		SEQUENCE
+*			OCTET STRING -- salt
+*			INTEGER -- iteration count
+*			INTEGER -- effective key length in octets
+* 	SEQUENCE
+*		OID -- algorithm id (rc2)
+*		SEQUENCE
+*			INTEGER -- RC2 parameter version 58 = 128, 160 = 40
+*			OCTET STRING -- iv
+*
+* //For DES and 3DES
+* SEQUENCE
+* 	OID -- pkcs5PBES2
+*	SEQUENCE
+*		SEQUENCE
+*		OID -- pkcs5PBKDF2
+*		SEQUENCE
+*			OCTET STRING -- salt
+*			INTEGER -- iteration count
+* 	SEQUENCE
+*		OID -- algorithm id (des, 3des)
+*		OCTET STRING -- iv
+*/
+
+EXPORT_C CASN1EncSequence* TASN1EncPKCS5::EncodeDERL(const CPBEncryptParms& aParms)
+	{
+	CASN1EncSequence* seq = CASN1EncSequence::NewLC();
+	CASN1EncObjectIdentifier* pbes2 = CASN1EncObjectIdentifier::NewLC(Kpkcs5PBES2);
+	seq->AddChildL(pbes2);
+	CleanupStack::Pop(pbes2);
+
+	CASN1EncSequence* seq1 = CASN1EncSequence::NewLC();
+	seq->AddChildL(seq1);
+	CleanupStack::Pop(seq1);
+
+	CASN1EncSequence* seq2 = CASN1EncSequence::NewLC();
+	seq1->AddChildL(seq2);
+	CleanupStack::Pop(seq2);
+
+	CASN1EncObjectIdentifier* pbkdf2 = CASN1EncObjectIdentifier::NewLC(Kpkcs5PBKDF2);
+	seq2->AddChildL(pbkdf2);
+	CleanupStack::Pop(pbkdf2);
+
+	CASN1EncSequence* seq3 = CASN1EncSequence::NewLC();
+	seq2->AddChildL(seq3);
+	CleanupStack::Pop(seq3);
+
+	CASN1EncOctetString* salt = CASN1EncOctetString::NewLC(aParms.Salt());
+	seq3->AddChildL(salt);
+	CleanupStack::Pop(salt);
+
+	CASN1EncInt* iterations = CASN1EncInt::NewLC(aParms.Iterations());
+	seq3->AddChildL(iterations);
+	CleanupStack::Pop(iterations);
+
+	CASN1EncInt* keysize = 0;
+	switch(aParms.Cipher())
+		{
+		case ECipherDES_CBC:
+		case ECipher3DES_CBC: 
+			break;
+		case ECipherRC2_CBC_40:
+ 			keysize = CASN1EncInt::NewLC(KSSLCompatibilityBits/8);  // effective key length in *octets*
+			seq3->AddChildL(keysize);
+			CleanupStack::Pop(keysize);
+			break;
+		case ECipherRC2_CBC_128:
+ 			keysize = CASN1EncInt::NewLC(KSSLCompatibilityBits/8);  // effective key length in *octets*
+			seq3->AddChildL(keysize);
+			CleanupStack::Pop(keysize);
+			break;
+		case ECipherRC2_CBC_40_16:
+ 			keysize = CASN1EncInt::NewLC(KPkcs8CompatibilityBits/8);  // effective key length in *octets*
+			seq3->AddChildL(keysize);
+			CleanupStack::Pop(keysize);
+			break;
+		case ECipherRC2_CBC_128_16:
+ 			keysize = CASN1EncInt::NewLC(KPkcs8CompatibilityBits/8);  // effective key length in *octets*
+			seq3->AddChildL(keysize);
+			CleanupStack::Pop(keysize);
+			break;
+		default:
+			User::Leave(KErrNotSupported);
+			break;
+		}
+
+	CASN1EncSequence* seq4 = CASN1EncSequence::NewLC();
+	seq1->AddChildL(seq4);
+	CleanupStack::Pop(seq4);
+
+	CASN1EncObjectIdentifier* algid = 0;
+	switch(aParms.Cipher())
+		{
+		case ECipherDES_CBC:
+			algid = CASN1EncObjectIdentifier::NewLC(KDESCBC);
+			break;
+		case ECipher3DES_CBC:
+			algid = CASN1EncObjectIdentifier::NewLC(K3DESCBC);
+			break;
+		case ECipherRC2_CBC_40:
+		case ECipherRC2_CBC_128:
+		case ECipherRC2_CBC_40_16:
+		case ECipherRC2_CBC_128_16:
+			algid = CASN1EncObjectIdentifier::NewLC(KRC2CBC);
+			break;
+		default:
+			User::Leave(KErrNotSupported);
+			break;
+		}
+	seq4->AddChildL(algid);
+	CleanupStack::Pop(algid);
+
+	CASN1EncSequence* seq5 = 0;
+	CASN1EncInt* keysize1 = 0;
+	CASN1EncOctetString* iv = 0;
+	switch(aParms.Cipher())
+		{
+		case ECipherDES_CBC:
+		case ECipher3DES_CBC:
+			iv = CASN1EncOctetString::NewLC(aParms.IV());
+			seq4->AddChildL(iv);
+			CleanupStack::Pop(iv);
+			break;
+		case ECipherRC2_CBC_40:
+		case ECipherRC2_CBC_40_16:
+			seq5 = CASN1EncSequence::NewLC();
+			seq4->AddChildL(seq5);
+			CleanupStack::Pop(seq5);
+
+			keysize1 = CASN1EncInt::NewLC(160); //encoding for 40 bit
+			seq5->AddChildL(keysize1);
+			CleanupStack::Pop(keysize1);
+
+			iv = CASN1EncOctetString::NewLC(aParms.IV());
+			seq5->AddChildL(iv);
+			CleanupStack::Pop(iv);
+			break;
+		case ECipherRC2_CBC_128:
+		case ECipherRC2_CBC_128_16:
+			seq5 = CASN1EncSequence::NewLC();
+			seq4->AddChildL(seq5);
+			CleanupStack::Pop(seq5);
+			
+			keysize1 = CASN1EncInt::NewLC(58); //encoding for 128 bit
+			seq5->AddChildL(keysize1);
+			CleanupStack::Pop(keysize1);
+
+			iv = CASN1EncOctetString::NewLC(aParms.IV());
+			seq5->AddChildL(iv);
+			CleanupStack::Pop(iv);
+			break;
+		default:
+			User::Leave(KErrNotSupported);
+			break;
+		}
+	CleanupStack::Pop(seq);
+	return seq;
+	}
+
+EXPORT_C CPBEncryptParms* TASN1DecPKCS5::DecodeDERL(const TDesC8& aBinaryData)
+	{
+	TASN1DecGeneric seqGen(aBinaryData);
+	seqGen.InitL();
+	if (seqGen.Tag() != EASN1Sequence)
+		{
+		User::Leave(KErrArgument);
+		}
+	
+	//Decode the Algorithm Identifier Sequence
+	TASN1DecSequence seq;
+	CArrayPtrFlat<TASN1DecGeneric>* seqContents = seq.DecodeDERLC(seqGen);
+
+	//PbeAlgorithm Id
+	if (seqContents->At(0)->Tag() != EASN1ObjectIdentifier)
+		{
+		User::Leave(KErrArgument);
+		}	
+	CPBEncryptParms* params = NULL;	
+	TASN1DecObjectIdentifier oid;
+	HBufC* oiddes = oid.DecodeDERL(*(seqContents->At(0)));
+	CleanupStack::PushL(oiddes);
+	//Algorithm Id is a pkcs-12Pbe Algorithm Id.
+	if(*oiddes != Kpkcs5PBES2)
+		{
+		// Initialise to impossible value
+		TPBECipher cipher = (TPBECipher) -1; 
+		// Pbe12Algorithm Ids
+		if(*oiddes == KPbeWithSHA1And128BitRC4)
+			{
+			cipher = ECipherARC4_128;
+			}
+		else if(*oiddes == KPbeWithSHA1And40BitRC4)
+			{
+			cipher = ECipherARC4_40;
+			}
+		else if(*oiddes == KPbeWithSHA1And3_KeyTripleDES_CBC)
+			{
+			cipher = ECipher3DES_CBC;
+			}
+		else if(*oiddes == KPbeWithSHA1And2_KeyTripleDES_CBC)
+			{
+			cipher = ECipher2Key3DES_CBC;
+			}
+		else if(*oiddes == KPbeWithSHA1And128BitRC2_CBC)
+			{
+			cipher = ECipherRC2_CBC_128_16; 
+			}
+		else if(*oiddes == KPbeWithSHA1And40BitRC2_CBC)
+			{
+			cipher = ECipherRC2_CBC_40_5; 
+			}
+	    else
+        	{
+        	User::Leave(KErrNotSupported);
+        	}	 
+        
+        TInt seqContentsCount = seqContents->Count();
+		
+		//All pkcs-12Pbe algorithms require the Algorithm Parameters.
+		//Algorithm Parameters are not OPTIONAL for pkcs-12Pbe algorithms.
+		
+		//seqContentsCount should be equal to 2.That is, the Algorithm Id 
+		//and associated Algorithm Parameters have to be present.
+		if(seqContentsCount != 2)
+			{
+			User::Leave(KErrArgument);	
+			}
+		//This if statement checks if the pkcs-12PbeParams Sequence is present in the 
+		//AlgorithmIdentifier Sequence Since pkcs-12PbeParams are OPTIONAL
+		else 
+			{
+			//Set the Initialization vector size to 8 bytes.
+			TBuf8<KIvSize> iv(KIvSize);
+			// Initialized to NULL, if salt is not present.
+			TPtrC8 salt;
+			TInt iterations; 
+
+			const TASN1DecGeneric* seqContentsAt1 = seqContents->At(1);
+			if (seqContentsAt1->Tag() != EASN1Sequence || seqContentsAt1->Class() != EUniversal)
+				{
+				User::Leave(KErrArgument);
+				}
+				
+			CArrayPtrFlat<TASN1DecGeneric>* seq1Contents = seq.DecodeDERLC(*seqContentsAt1);
+			const TASN1DecGeneric* seq1ContentsAt0 = seq1Contents->At(0);
+			if (seq1ContentsAt0->Tag() != EASN1OctetString || seq1ContentsAt0->Class() != EUniversal)
+				{
+				User::Leave(KErrArgument);
+				}
+			salt.Set(seq1ContentsAt0->GetContentDER());
+			const TASN1DecGeneric* seq1ContentsAt1 = seq1Contents->At(1);
+			if (seq1ContentsAt1->Tag() != EASN1Integer || seq1ContentsAt1->Class() != EUniversal)
+				{
+				User::Leave(KErrArgument);
+				}
+			TASN1DecInteger integer;
+			iterations = integer.DecodeDERShortL(*seq1ContentsAt1);
+			if (iterations <= 0)
+				{
+				User::Leave(KErrArgument);
+				}
+			params = CPBEncryptParms::NewL(cipher, salt, iv, iterations);
+			params->SetKdf(CPBEncryptParms::EKdfPkcs12);
+			CleanupStack::PopAndDestroy(seq1Contents);
+			}
+		}
+	//Algorithm Id is a pkcs-5Pbe Algorithm Id.
+   	 else if (*oiddes == Kpkcs5PBES2)
+    	{
+    	if (seqContents->At(1)->Tag() != EASN1Sequence)
+			{
+			User::Leave(KErrArgument);
+			}
+		CArrayPtrFlat<TASN1DecGeneric>* seq1Contents = seq.DecodeDERLC(*(seqContents->At(1)));
+
+		if (seq1Contents->At(0)->Tag() != EASN1Sequence)
+			{
+			User::Leave(KErrArgument);
+			}
+		CArrayPtrFlat<TASN1DecGeneric>* seq2Contents = seq.DecodeDERLC(*(seq1Contents->At(0)));
+
+		if (seq2Contents->At(0)->Tag() != EASN1ObjectIdentifier)
+			{
+			User::Leave(KErrArgument);
+			}
+		HBufC* oid1des = oid.DecodeDERL(*(seq2Contents->At(0)));
+		CleanupStack::PushL(oid1des);
+		
+		if(*oid1des != Kpkcs5PBKDF2)
+			{
+			User::Leave(KErrNotSupported);
+			}
+		if (seq2Contents->At(1)->Tag() != EASN1Sequence)
+			{
+			User::Leave(KErrArgument);
+			}
+		CArrayPtrFlat<TASN1DecGeneric>* seq3Contents = seq.DecodeDERLC(*(seq2Contents->At(1)));
+
+		if (seq3Contents->At(0)->Tag() != EASN1OctetString)
+			{
+			User::Leave(KErrArgument);
+			}
+		TASN1DecOctetString octet;
+		HBufC8* salt = octet.DecodeDERL(*(seq3Contents->At(0)));
+		CleanupStack::PushL(salt);
+		
+		if (seq3Contents->At(1)->Tag() != EASN1Integer)
+			{
+			User::Leave(KErrArgument);
+			}
+		TASN1DecInteger integer;
+		TInt iterations = integer.DecodeDERShortL(*(seq3Contents->At(1)));
+
+		if (seq1Contents->At(1)->Tag() != EASN1Sequence)
+			{
+			User::Leave(KErrArgument);
+			}
+		CArrayPtrFlat<TASN1DecGeneric>* seq4Contents = seq.DecodeDERLC(*(seq1Contents->At(1)));
+	
+		TPBECipher cipher = (TPBECipher) -1; // Initialise to impossible value
+		if (seq4Contents->At(0)->Tag() != EASN1ObjectIdentifier)
+			{
+			User::Leave(KErrArgument);
+			}
+		HBufC* oid2des = oid.DecodeDERL(*(seq4Contents->At(0)));
+		CleanupStack::PushL(oid2des);
+		
+		CArrayPtrFlat<TASN1DecGeneric>* seq5Contents = 0; 
+
+		if(*oid2des == K3DESCBC)
+			{
+			cipher = ECipher3DES_CBC;
+		CleanupStack::PushL(seq5Contents);
+			}
+		else if(*oid2des == KDESCBC)
+			{
+			cipher = ECipherDES_CBC;
+		CleanupStack::PushL(seq5Contents);
+			}
+		else if(*oid2des == KRC2CBC)
+			{
+			// RC2 has an additional parameter, the effective key lenght in octets.
+			if (seq3Contents->At(2)->Tag() != EASN1Integer)
+				{
+				User::Leave(KErrArgument);
+				}		
+			TInt effectiveKeyLength =  integer.DecodeDERShortL(*(seq3Contents->At(2)));
+
+			if (seq4Contents->At(1)->Tag() != EASN1Sequence)
+				{
+				User::Leave(KErrArgument);
+				}
+			seq5Contents = seq.DecodeDERLC(*(seq4Contents->At(1)));
+			if (seq5Contents->At(0)->Tag() != EASN1Integer)
+				{
+				User::Leave(KErrArgument);
+				}
+			TInt keysize = integer.DecodeDERShortL(*(seq5Contents->At(0)));
+			switch(keysize)
+				{
+				// These values come from the PKCS#5 v2 specs
+				case 160:
+					if (effectiveKeyLength == 16)
+						{
+						cipher = ECipherRC2_CBC_40_16;					
+						}
+					else 
+						{
+						if (effectiveKeyLength == 128)
+							{
+							cipher = ECipherRC2_CBC_40;
+							}
+						else 
+							{
+							User::Leave(KErrNotSupported); // Unsupported effective key length!						
+							}
+						}
+					break;
+				case 58:
+					if (effectiveKeyLength == 16)
+						{
+						cipher = ECipherRC2_CBC_128_16;					
+						}
+					else 
+						{
+						if (effectiveKeyLength == 128)
+							{
+							cipher = ECipherRC2_CBC_128;
+							}
+						else 
+							{
+							User::Leave(KErrNotSupported); // Unsupported effective key length!						
+							}
+						}			
+					break;
+				case 120:
+					//would be RC_CBC_64 but we don't support that
+				default:
+					User::Leave(KErrNotSupported);
+					break;
+				}
+			}
+		else 
+			{
+			User::Leave(KErrNotSupported);
+			}	
+
+		HBufC8* iv = 0;
+		switch(cipher)
+			{
+			case ECipher3DES_CBC:
+			case ECipherDES_CBC:
+				if (seq4Contents->At(1)->Tag() != EASN1OctetString)
+					{
+					User::Leave(KErrArgument);
+					}
+				iv = octet.DecodeDERL(*(seq4Contents->At(1)));	
+			CleanupStack::PushL(iv);
+				break;
+			case ECipherRC2_CBC_40:
+			case ECipherRC2_CBC_128:
+			case ECipherRC2_CBC_40_16:
+			case ECipherRC2_CBC_128_16:	
+				if (seq5Contents->At(1)->Tag() != EASN1OctetString)
+					{
+					User::Leave(KErrArgument);
+					}
+				iv = octet.DecodeDERL(*(seq5Contents->At(1)));
+			CleanupStack::PushL(iv);
+				break;
+			default:
+				User::Leave(KErrNotSupported);
+				break;
+			}
+
+		params = CPBEncryptParms::NewL(cipher, *salt, *iv,
+		iterations);
+	CleanupStack::PopAndDestroy(9); //iv, seq5contents, oid2des, seq4Contents,
+	//salt, seq3Contents, oid1des, seq2Contents, seq1Contents
+    	}
+	else
+		{
+		User::Leave(KErrNotSupported);
+		}
+	CleanupStack::PopAndDestroy(2, seqContents);
+	return params;
+	}