sl@0: /* sl@0: * Copyright (c) 2002-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 sl@0: #include sl@0: #include sl@0: #include "pkcs5kdf.h" sl@0: #include "pbencryptor.h" sl@0: #include "pbe.h" sl@0: #include sl@0: #include "pbesymmetricfactory.h" sl@0: sl@0: EXPORT_C CPBEncryptSet* CPBEncryptSet::NewL(const TPBPassword& aPassword) sl@0: { sl@0: CPBEncryptSet* self = NewLC(aPassword); sl@0: CleanupStack::Pop(); sl@0: return self; sl@0: } sl@0: sl@0: EXPORT_C CPBEncryptSet* CPBEncryptSet::NewLC(const TPBPassword& aPassword) sl@0: { sl@0: CPBEncryptSet* self = new(ELeave) CPBEncryptSet; sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aPassword.Password()); sl@0: return self; sl@0: } sl@0: sl@0: EXPORT_C CPBEncryptSet* CPBEncryptSet::NewL(const TPBPassword& aPassword, sl@0: const TPBECipher aCipher) sl@0: { sl@0: CPBEncryptSet* self = NewLC(aPassword, aCipher); sl@0: CleanupStack::Pop(); sl@0: return self; sl@0: } sl@0: sl@0: EXPORT_C CPBEncryptSet* CPBEncryptSet::NewLC(const TPBPassword& aPassword, sl@0: const TPBECipher aCipher) sl@0: { sl@0: CPBEncryptSet* self = new(ELeave) CPBEncryptSet; sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aPassword.Password(), aCipher); sl@0: return self; sl@0: } sl@0: sl@0: EXPORT_C CPBEncryptSet* CPBEncryptSet::NewL(const TPBPassword& aPassword, sl@0: const CPBEncryptParms& aParms) sl@0: { sl@0: CPBEncryptSet* self = NewLC(aPassword, aParms); sl@0: CleanupStack::Pop(); sl@0: return self; sl@0: } sl@0: sl@0: EXPORT_C CPBEncryptSet* CPBEncryptSet::NewLC(const TPBPassword& aPassword, sl@0: const CPBEncryptParms& aParms) sl@0: { sl@0: CPBEncryptSet* self = new(ELeave) CPBEncryptSet; sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aPassword.Password(), aParms); sl@0: return self; sl@0: } sl@0: sl@0: EXPORT_C CPBEncryptSet* CPBEncryptSet::NewL(const CPBEncryptionData& aData, sl@0: const TDesC8& aEncryptedKey, const TPBPassword& aPassword) sl@0: { sl@0: CPBEncryptSet* self = NewLC(aData, aEncryptedKey, aPassword); sl@0: CleanupStack::Pop(); sl@0: return self; sl@0: } sl@0: sl@0: EXPORT_C CPBEncryptSet* CPBEncryptSet::NewLC(const CPBEncryptionData& aData, sl@0: const TDesC8& aEncryptedKey, const TPBPassword& aPassword) sl@0: { sl@0: CPBEncryptSet* self = new(ELeave) CPBEncryptSet; sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aData, aEncryptedKey, aPassword); sl@0: return self; sl@0: } sl@0: sl@0: void CPBEncryptSet::ConstructL(const TDesC8& aPassword) sl@0: { sl@0: CPBEncryptElement::ConstructL(aPassword); sl@0: ConstructMasterKeyL(); sl@0: } sl@0: sl@0: void CPBEncryptSet::ConstructL(const TDesC8& aPassword, sl@0: const TPBECipher aCipher) sl@0: { sl@0: CPBEncryptElement::ConstructL(aPassword, aCipher); sl@0: ConstructMasterKeyL(); sl@0: } sl@0: sl@0: void CPBEncryptSet::ConstructL(const TDesC8& aPassword, sl@0: const CPBEncryptParms& aParms) sl@0: { sl@0: CPBEncryptElement::ConstructL(aPassword, aParms); sl@0: ConstructMasterKeyL(); sl@0: } sl@0: sl@0: void CPBEncryptSet::ConstructMasterKeyL(void) sl@0: { sl@0: TBuf8 masterKey(KAESKeyBytes256); sl@0: TRandom::RandomL(masterKey); sl@0: iEncryptedMasterKey = HBufC8::NewL(KAESKeyBytes256); sl@0: EncryptMasterKeyL(masterKey); sl@0: } sl@0: sl@0: void CPBEncryptSet::ConstructL(const CPBEncryptionData& aData, sl@0: const TDesC8& aEncryptedMasterKey, const TPBPassword& aPassword) sl@0: { sl@0: CPBEncryptElement::ConstructL(aData, aPassword); sl@0: iEncryptedMasterKey = aEncryptedMasterKey.AllocL(); sl@0: } sl@0: sl@0: EXPORT_C void CPBEncryptSet::ChangePasswordL(const TPBPassword& aNewPassword) sl@0: { sl@0: //1) Decrypt master key with old encrypt key sl@0: TBuf8 masterKey; sl@0: DecryptMasterKeyL(masterKey); sl@0: sl@0: //2) create new encrypt parms sl@0: sl@0: TBuf8 authSalt(KPBEMaxSaltBytes); sl@0: TRandom::RandomL(authSalt); sl@0: sl@0: //3) create a totally new CPBEncryptionData representing the new password sl@0: CPBEncryptionData* newData = CPBEncryptionData::NewL( sl@0: aNewPassword.Password(), authSalt, iData->EncryptParms()); sl@0: sl@0: delete iData; sl@0: iData = newData; sl@0: sl@0: // regenerate the password using a maximum length salt. sl@0: CPBEncryptParms& epNonConst = sl@0: const_cast(iData->EncryptParms()); sl@0: epNonConst.ResizeSaltL(KPBEMaxSaltBytes); sl@0: sl@0: TPtr8 iEncryptKeyBuf(iEncryptKey->Des()); sl@0: iEncryptKeyBuf.SetLength(PBE::GetKeyBytes(iData->EncryptParms().Cipher())); sl@0: sl@0: iData->EncryptParms().DeriveKeyL(aNewPassword.Password(), iEncryptKeyBuf); sl@0: sl@0: //4) Encrypt master key with new encrypt key sl@0: EncryptMasterKeyL(masterKey); sl@0: } sl@0: sl@0: EXPORT_C const TDesC8& CPBEncryptSet::EncryptedMasterKey(void) const sl@0: { sl@0: return *iEncryptedMasterKey; sl@0: } sl@0: sl@0: CPBEncryptor* CPBEncryptSet::NewEncryptLC(void) const sl@0: { sl@0: CPBEncryptor* encryptor = NewEncryptL(); sl@0: CleanupStack::PushL(encryptor); sl@0: return encryptor; sl@0: } sl@0: sl@0: CPBEncryptor* CPBEncryptSet::NewEncryptL(void) const sl@0: { sl@0: TBuf8 masterKey; sl@0: DecryptMasterKeyL(masterKey); sl@0: sl@0: CPBEncryptor* encryptor = 0; sl@0: //make sure the masterkey we pass is exactly the right length for the cipher sl@0: encryptor = CPBEncryptorSet::NewL(iData->EncryptParms().Cipher(), sl@0: masterKey.Left(PBE::GetKeyBytes(iData->EncryptParms().Cipher()))); sl@0: return encryptor; sl@0: } sl@0: sl@0: CPBDecryptor* CPBEncryptSet::NewDecryptLC(void) const sl@0: { sl@0: CPBDecryptor* decryptor = NewDecryptL(); sl@0: CleanupStack::PushL(decryptor); sl@0: return decryptor; sl@0: } sl@0: sl@0: CPBDecryptor* CPBEncryptSet::NewDecryptL(void) const sl@0: { sl@0: TBuf8 masterKey; sl@0: DecryptMasterKeyL(masterKey); sl@0: sl@0: CPBDecryptor* decryptor = 0; sl@0: //make sure the masterkey we pass is exactly the right length for the cipher sl@0: decryptor = CPBDecryptorSet::NewL(iData->EncryptParms().Cipher(), sl@0: masterKey.Left(PBE::GetKeyBytes(iData->EncryptParms().Cipher()))); sl@0: return decryptor; sl@0: } sl@0: sl@0: void CPBEncryptSet::DecryptMasterKeyL(TDes8& aMasterKey) const sl@0: { sl@0: CPBDecryptorElement* decryptor = CPBDecryptorElement::NewLC( sl@0: iData->EncryptParms().Cipher(), *iEncryptKey, iData->EncryptParms().IV()); sl@0: aMasterKey.SetLength(0); sl@0: decryptor->Process(*iEncryptedMasterKey, aMasterKey); sl@0: CleanupStack::PopAndDestroy(decryptor); sl@0: } sl@0: sl@0: void CPBEncryptSet::EncryptMasterKeyL(const TDesC8& aMasterKey) sl@0: { sl@0: CPBEncryptorElement* encryptor = CPBEncryptorElement::NewLC( sl@0: iData->EncryptParms().Cipher(), *iEncryptKey, iData->EncryptParms().IV()); sl@0: TPtr8 encryptedMasterKeyBuf(iEncryptedMasterKey->Des()); sl@0: encryptedMasterKeyBuf.SetLength(0); sl@0: encryptor->Process(aMasterKey, encryptedMasterKeyBuf); sl@0: CleanupStack::PopAndDestroy(encryptor); sl@0: } sl@0: sl@0: CPBEncryptSet::CPBEncryptSet() sl@0: { sl@0: } sl@0: sl@0: CPBEncryptSet::~CPBEncryptSet() sl@0: { sl@0: delete iEncryptedMasterKey; sl@0: } sl@0: sl@0: // Warning: This function is only valid BEFORE you call NewEncryptL sl@0: // After creating the cipher, ask it about itself, not me! sl@0: // This is _very_ dodgy as I assume all sorts of things about the encryptor. sl@0: // 1) That it uses SSLv3 or similar style padding sl@0: // 2) That it stores the IV for that stream at the front. sl@0: // This is here for specific application that requires this and aren't able to sl@0: // actually construct the cipher and ask it. In almost all other cases you sl@0: // should construct the cipher and ask it. sl@0: TInt CPBEncryptSet::MaxCiphertextLength(TInt aPlaintextLength) const sl@0: { sl@0: TUint blocksize = PBE::GetBlockBytes(iData->EncryptParms().Cipher()); sl@0: TUint padding = blocksize - aPlaintextLength % blocksize; sl@0: //totallength = blocksize of iv hidden at beginning + inputLength + padding sl@0: return blocksize + aPlaintextLength + padding; sl@0: } sl@0: sl@0: // Warning: This function is only valid BEFORE you call NewDecryptL sl@0: // After creating the cipher, ask it about itself, not me! sl@0: TInt CPBEncryptSet::MaxPlaintextLength(TInt aCiphertextLength) const sl@0: { sl@0: /*It's impossible to determine anything about how much padding will be sl@0: * removed. So we'll return a max length that is longer than will ever sl@0: * happen by at most a blocksize - 1. sl@0: */ sl@0: //In all cases SSLv3 padding has at least one byte of padding. sl@0: TUint blocksize = PBE::GetBlockBytes(iData->EncryptParms().Cipher()); sl@0: //totallength = inputlength - iv hidden at beginning - 1 byte of padding sl@0: return aCiphertextLength - blocksize - 1; sl@0: } sl@0: