diff -r 675a964f4eb5 -r 35751d3474b7 cryptoservices/asnpkcs/source/asnpkcs5.cpp --- 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 -#include -#include -#include - -#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* 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 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* 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* seq1Contents = seq.DecodeDERLC(*(seqContents->At(1))); - - if (seq1Contents->At(0)->Tag() != EASN1Sequence) - { - User::Leave(KErrArgument); - } - CArrayPtrFlat* 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* 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* 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* 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 +#include +#include +#include + +#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* 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 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* 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* seq1Contents = seq.DecodeDERLC(*(seqContents->At(1))); + + if (seq1Contents->At(0)->Tag() != EASN1Sequence) + { + User::Leave(KErrArgument); + } + CArrayPtrFlat* 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* 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* 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* 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; + }