diff -r 000000000000 -r 2c201484c85f cryptoservices/certificateandkeymgmt/pkcs7/pkcs7encrypteddataobject.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cryptoservices/certificateandkeymgmt/pkcs7/pkcs7encrypteddataobject.cpp Wed Jul 08 11:25:26 2009 +0100 @@ -0,0 +1,222 @@ +/* +* Copyright (c) 2005-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 "pkcs7encrypteddataobject.h" + +/** The last character in the PKCS7 EncryptedData OID */ +const TInt KPkcs7EncryptedData = 6; + +EXPORT_C CPKCS7EncryptedDataObject* CPKCS7EncryptedDataObject::NewL(const CPKCS7ContentInfo& aContentInfo) + { + CPKCS7EncryptedDataObject* self = new (ELeave) CPKCS7EncryptedDataObject(); + CleanupStack::PushL(self); + self->ConstructL(aContentInfo); + CleanupStack::Pop(self); + return self; + } + +CPKCS7EncryptedDataObject::CPKCS7EncryptedDataObject(void) + { + } + +CPKCS7EncryptedDataObject::~CPKCS7EncryptedDataObject() + { + delete iEncryptParams; + } + +EXPORT_C TInt CPKCS7EncryptedDataObject::Version() const + { + return iVersion; + } + +EXPORT_C CPKCS7EncryptedDataObject::TContentType CPKCS7EncryptedDataObject::ContentType() const + { + return iContentType; + } + +EXPORT_C const TDesC8& CPKCS7EncryptedDataObject::EncryptedContentInfoData() const + { + return iEncryptedContent; + } + +EXPORT_C const CPBEncryptParms& CPKCS7EncryptedDataObject::EncryptParams() const + { + return *iEncryptParams; + } + +CPBEncryptParms* CPKCS7EncryptedDataObject::DecodeContentEncryptionAlgorithmL(const TDesC8& aBinaryData) const + { + TASN1DecGeneric seqGen(aBinaryData); + seqGen.InitL(); + if (seqGen.Tag() != EASN1Sequence || seqGen.Class() != EUniversal) + { + User::Leave(KErrArgument); + } + + TPtrC8 theContent(seqGen.Encoding()); + CPBEncryptParms* encryptParams = TASN1DecPKCS5::DecodeDERL(theContent); + return encryptParams; + } + +EXPORT_C HBufC8* CPKCS7EncryptedDataObject::DecryptDataL(const TDesC& aPassword) const + { + CPBEncryptElement* encryptElement; + HBufC8* pkcs12Pwd = PKCS12KDF::GeneratePasswordLC(aPassword); + if(iEncryptParams->Kdf() == CPBEncryptParms::EKdfPkcs12) + { + TPtrC8 iv = iEncryptParams->IV(); + HBufC8* ivValue = HBufC8::NewMaxLC(iv.Length()); + TPtr8 encryptKeyBuf = ivValue->Des(); + + switch(iEncryptParams->Cipher()) + { + case ECipherARC4_128: + case ECipherARC4_40: + { + //derive only key it is unnecessary to derive an IV for RC4 + break; + } + case ECipher3DES_CBC: + case ECipher2Key3DES_CBC: + case ECipherRC2_CBC_128_16: + case ECipherRC2_CBC_40_5: + { + PKCS12KDF::DeriveKeyL(encryptKeyBuf, PKCS12KDF::EIDByteIV, *pkcs12Pwd, iEncryptParams->Salt(), iEncryptParams->Iterations()); + iEncryptParams->SetIV(encryptKeyBuf); + break; + } + default: + { + User::Leave(KErrNotSupported); + break; + } + } + CleanupStack::PopAndDestroy(ivValue); + // Create the decryptor + encryptElement = CPBEncryptElement::NewLC(*pkcs12Pwd, *iEncryptParams); + } + else + { + TPBPassword password(aPassword); + // Create the decryptor + encryptElement = CPBEncryptElement::NewLC(password.Password(), *iEncryptParams); + } + + CPBDecryptor* decryptor = encryptElement->NewDecryptLC(); + + TPtrC8 encryptedKey(iEncryptedContent); + TUint encryptLength = encryptedKey.Length(); + TUint maxDecryptLength = decryptor->MaxOutputLength(encryptLength); + + if ( maxDecryptLength <= 0 ) + { + User::Leave(KErrGeneral); + } + + HBufC8* decryptedContent = HBufC8::NewLC(maxDecryptLength); + TPtr8 dcDes(decryptedContent->Des()); + decryptor->Process(encryptedKey, dcDes); + CleanupStack::Pop(decryptedContent); + CleanupStack::PopAndDestroy(3, pkcs12Pwd); // pkcs12Pwd, encryptElement, decryptor + return decryptedContent; + } + + void CPKCS7EncryptedDataObject::ConstructL(const CPKCS7ContentInfo& aContentInfo) + { + if(aContentInfo.ContentType() != KPkcs7EncryptedData) + { + User::Leave(KErrArgument); + } + + // EncryptedData SEQUENCE + TASN1DecGeneric decGen(aContentInfo.ContentData()); + decGen.InitL(); + if(decGen.Tag() != EASN1Sequence || decGen.Class() != EUniversal) + { + User::Leave(KErrArgument); + } + TASN1DecSequence seq1; + CArrayPtrFlat* EncryptedDataContents = seq1.DecodeDERLC(decGen); + + // Both version and encryptedContentInfo should be present + if (EncryptedDataContents->Count() != 2) + { + User::Leave(KErrArgument); + } + + // VERSION + // version is the syntax version number. It shall be 0 for this version of the standard + const TASN1DecGeneric* EncryptedDataContentsAt0 = EncryptedDataContents->At(0); + if(EncryptedDataContentsAt0->Tag() != EASN1Integer || EncryptedDataContentsAt0->Class() != EUniversal) + { + User::Leave(KErrArgument); + } + + TASN1DecInteger intDecoder; + iVersion = intDecoder.DecodeDERShortL(*EncryptedDataContentsAt0); + if (iVersion != 0) + { + User::Leave(KErrArgument); + } + + // ENCRYPTED CONTENT INFO a SEQUENCE + const TASN1DecGeneric* EncryptedDataContentsAt1 = EncryptedDataContents->At(1); + if (EncryptedDataContentsAt1->Tag() != EASN1Sequence || EncryptedDataContentsAt1->Class() != EUniversal) + { + User::Leave(KErrArgument); + } + TASN1DecSequence seq2; + CArrayPtrFlat* EncryptedContentInfo = seq2.DecodeDERLC(*EncryptedDataContentsAt1); + + // CONTENT TYPE IDENTIFIED BY AN OBJECT IDENTIFIER + // Gets the oid + TASN1DecObjectIdentifier ContentTypeoidDec; + HBufC* contentType = ContentTypeoidDec.DecodeDERL(*EncryptedContentInfo->At(0)); + if(contentType->Compare(KPkcs7DataOID()) == 0) + { + iContentType = EPkcs7Data; + } + else + { + User::Leave(KErrNotSupported); + } + delete contentType; + // CONTENT ENCRYPTION ALGORITHM + // Get the Cipher used and the encoded params in it + iEncryptParams = DecodeContentEncryptionAlgorithmL(EncryptedContentInfo->At(1)->Encoding()); + + // ENCRYPTED CONTENT + // This is an OPTIONAL field + TInt encryptedContentInfoCount = EncryptedContentInfo->Count(); + if(encryptedContentInfoCount == 3) + { + TASN1DecGeneric decOctetString(*EncryptedContentInfo->At(2)); + decOctetString.InitL(); + iEncryptedContent.Set(decOctetString.GetContentDER()); + } + else if(encryptedContentInfoCount > 3 || encryptedContentInfoCount < 2) + { + User::Leave(KErrArgument); + } + else if(encryptedContentInfoCount == 2) + { + iEncryptedContent.Set(KNullDesC8()); + } + + CleanupStack::PopAndDestroy(2, EncryptedDataContents); //EncryptedDataContents, EncryptedContentInfo + }