sl@0: /* sl@0: * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of the License "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * sl@0: */ sl@0: sl@0: sl@0: #include "pkcs7encrypteddataobject.h" sl@0: sl@0: /** The last character in the PKCS7 EncryptedData OID */ sl@0: const TInt KPkcs7EncryptedData = 6; sl@0: sl@0: EXPORT_C CPKCS7EncryptedDataObject* CPKCS7EncryptedDataObject::NewL(const CPKCS7ContentInfo& aContentInfo) sl@0: { sl@0: CPKCS7EncryptedDataObject* self = new (ELeave) CPKCS7EncryptedDataObject(); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aContentInfo); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: CPKCS7EncryptedDataObject::CPKCS7EncryptedDataObject(void) sl@0: { sl@0: } sl@0: sl@0: CPKCS7EncryptedDataObject::~CPKCS7EncryptedDataObject() sl@0: { sl@0: delete iEncryptParams; sl@0: } sl@0: sl@0: EXPORT_C TInt CPKCS7EncryptedDataObject::Version() const sl@0: { sl@0: return iVersion; sl@0: } sl@0: sl@0: EXPORT_C CPKCS7EncryptedDataObject::TContentType CPKCS7EncryptedDataObject::ContentType() const sl@0: { sl@0: return iContentType; sl@0: } sl@0: sl@0: EXPORT_C const TDesC8& CPKCS7EncryptedDataObject::EncryptedContentInfoData() const sl@0: { sl@0: return iEncryptedContent; sl@0: } sl@0: sl@0: EXPORT_C const CPBEncryptParms& CPKCS7EncryptedDataObject::EncryptParams() const sl@0: { sl@0: return *iEncryptParams; sl@0: } sl@0: sl@0: CPBEncryptParms* CPKCS7EncryptedDataObject::DecodeContentEncryptionAlgorithmL(const TDesC8& aBinaryData) const sl@0: { sl@0: TASN1DecGeneric seqGen(aBinaryData); sl@0: seqGen.InitL(); sl@0: if (seqGen.Tag() != EASN1Sequence || seqGen.Class() != EUniversal) sl@0: { sl@0: User::Leave(KErrArgument); sl@0: } sl@0: sl@0: TPtrC8 theContent(seqGen.Encoding()); sl@0: CPBEncryptParms* encryptParams = TASN1DecPKCS5::DecodeDERL(theContent); sl@0: return encryptParams; sl@0: } sl@0: sl@0: EXPORT_C HBufC8* CPKCS7EncryptedDataObject::DecryptDataL(const TDesC& aPassword) const sl@0: { sl@0: CPBEncryptElement* encryptElement; sl@0: HBufC8* pkcs12Pwd = PKCS12KDF::GeneratePasswordLC(aPassword); sl@0: if(iEncryptParams->Kdf() == CPBEncryptParms::EKdfPkcs12) sl@0: { sl@0: TPtrC8 iv = iEncryptParams->IV(); sl@0: HBufC8* ivValue = HBufC8::NewMaxLC(iv.Length()); sl@0: TPtr8 encryptKeyBuf = ivValue->Des(); sl@0: sl@0: switch(iEncryptParams->Cipher()) sl@0: { sl@0: case ECipherARC4_128: sl@0: case ECipherARC4_40: sl@0: { sl@0: //derive only key it is unnecessary to derive an IV for RC4 sl@0: break; sl@0: } sl@0: case ECipher3DES_CBC: sl@0: case ECipher2Key3DES_CBC: sl@0: case ECipherRC2_CBC_128_16: sl@0: case ECipherRC2_CBC_40_5: sl@0: { sl@0: PKCS12KDF::DeriveKeyL(encryptKeyBuf, PKCS12KDF::EIDByteIV, *pkcs12Pwd, iEncryptParams->Salt(), iEncryptParams->Iterations()); sl@0: iEncryptParams->SetIV(encryptKeyBuf); sl@0: break; sl@0: } sl@0: default: sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: break; sl@0: } sl@0: } sl@0: CleanupStack::PopAndDestroy(ivValue); sl@0: // Create the decryptor sl@0: encryptElement = CPBEncryptElement::NewLC(*pkcs12Pwd, *iEncryptParams); sl@0: } sl@0: else sl@0: { sl@0: TPBPassword password(aPassword); sl@0: // Create the decryptor sl@0: encryptElement = CPBEncryptElement::NewLC(password.Password(), *iEncryptParams); sl@0: } sl@0: sl@0: CPBDecryptor* decryptor = encryptElement->NewDecryptLC(); sl@0: sl@0: TPtrC8 encryptedKey(iEncryptedContent); sl@0: TUint encryptLength = encryptedKey.Length(); sl@0: TUint maxDecryptLength = decryptor->MaxOutputLength(encryptLength); sl@0: sl@0: if ( maxDecryptLength <= 0 ) sl@0: { sl@0: User::Leave(KErrGeneral); sl@0: } sl@0: sl@0: HBufC8* decryptedContent = HBufC8::NewLC(maxDecryptLength); sl@0: TPtr8 dcDes(decryptedContent->Des()); sl@0: decryptor->Process(encryptedKey, dcDes); sl@0: CleanupStack::Pop(decryptedContent); sl@0: CleanupStack::PopAndDestroy(3, pkcs12Pwd); // pkcs12Pwd, encryptElement, decryptor sl@0: return decryptedContent; sl@0: } sl@0: sl@0: void CPKCS7EncryptedDataObject::ConstructL(const CPKCS7ContentInfo& aContentInfo) sl@0: { sl@0: if(aContentInfo.ContentType() != KPkcs7EncryptedData) sl@0: { sl@0: User::Leave(KErrArgument); sl@0: } sl@0: sl@0: // EncryptedData SEQUENCE sl@0: TASN1DecGeneric decGen(aContentInfo.ContentData()); sl@0: decGen.InitL(); sl@0: if(decGen.Tag() != EASN1Sequence || decGen.Class() != EUniversal) sl@0: { sl@0: User::Leave(KErrArgument); sl@0: } sl@0: TASN1DecSequence seq1; sl@0: CArrayPtrFlat* EncryptedDataContents = seq1.DecodeDERLC(decGen); sl@0: sl@0: // Both version and encryptedContentInfo should be present sl@0: if (EncryptedDataContents->Count() != 2) sl@0: { sl@0: User::Leave(KErrArgument); sl@0: } sl@0: sl@0: // VERSION sl@0: // version is the syntax version number. It shall be 0 for this version of the standard sl@0: const TASN1DecGeneric* EncryptedDataContentsAt0 = EncryptedDataContents->At(0); sl@0: if(EncryptedDataContentsAt0->Tag() != EASN1Integer || EncryptedDataContentsAt0->Class() != EUniversal) sl@0: { sl@0: User::Leave(KErrArgument); sl@0: } sl@0: sl@0: TASN1DecInteger intDecoder; sl@0: iVersion = intDecoder.DecodeDERShortL(*EncryptedDataContentsAt0); sl@0: if (iVersion != 0) sl@0: { sl@0: User::Leave(KErrArgument); sl@0: } sl@0: sl@0: // ENCRYPTED CONTENT INFO a SEQUENCE sl@0: const TASN1DecGeneric* EncryptedDataContentsAt1 = EncryptedDataContents->At(1); sl@0: if (EncryptedDataContentsAt1->Tag() != EASN1Sequence || EncryptedDataContentsAt1->Class() != EUniversal) sl@0: { sl@0: User::Leave(KErrArgument); sl@0: } sl@0: TASN1DecSequence seq2; sl@0: CArrayPtrFlat* EncryptedContentInfo = seq2.DecodeDERLC(*EncryptedDataContentsAt1); sl@0: sl@0: // CONTENT TYPE IDENTIFIED BY AN OBJECT IDENTIFIER sl@0: // Gets the oid sl@0: TASN1DecObjectIdentifier ContentTypeoidDec; sl@0: HBufC* contentType = ContentTypeoidDec.DecodeDERL(*EncryptedContentInfo->At(0)); sl@0: if(contentType->Compare(KPkcs7DataOID()) == 0) sl@0: { sl@0: iContentType = EPkcs7Data; sl@0: } sl@0: else sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: delete contentType; sl@0: // CONTENT ENCRYPTION ALGORITHM sl@0: // Get the Cipher used and the encoded params in it sl@0: iEncryptParams = DecodeContentEncryptionAlgorithmL(EncryptedContentInfo->At(1)->Encoding()); sl@0: sl@0: // ENCRYPTED CONTENT sl@0: // This is an OPTIONAL field sl@0: TInt encryptedContentInfoCount = EncryptedContentInfo->Count(); sl@0: if(encryptedContentInfoCount == 3) sl@0: { sl@0: TASN1DecGeneric decOctetString(*EncryptedContentInfo->At(2)); sl@0: decOctetString.InitL(); sl@0: iEncryptedContent.Set(decOctetString.GetContentDER()); sl@0: } sl@0: else if(encryptedContentInfoCount > 3 || encryptedContentInfoCount < 2) sl@0: { sl@0: User::Leave(KErrArgument); sl@0: } sl@0: else if(encryptedContentInfoCount == 2) sl@0: { sl@0: iEncryptedContent.Set(KNullDesC8()); sl@0: } sl@0: sl@0: CleanupStack::PopAndDestroy(2, EncryptedDataContents); //EncryptedDataContents, EncryptedContentInfo sl@0: } sl@0: