1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/crypto/weakcrypto/source/pbe/pbe.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,266 @@
1.4 +/*
1.5 +* Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of the License "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description:
1.18 +*
1.19 +*/
1.20 +
1.21 +
1.22 +#include <e32std.h>
1.23 +#include <random.h>
1.24 +#include <cryptostrength.h>
1.25 +#include <securityerr.h>
1.26 +#include <pbedata.h>
1.27 +#include "pkcs5kdf.h"
1.28 +#include "pbe.h"
1.29 +#include "pbencryptor.h"
1.30 +#include "pbesymmetricfactory.h"
1.31 +
1.32 +EXPORT_C CPBEncryptElement* CPBEncryptElement::NewL(const TPBPassword& aPassword)
1.33 + {
1.34 + CPBEncryptElement* self = NewLC(aPassword);
1.35 + CleanupStack::Pop();
1.36 + return self;
1.37 + }
1.38 +
1.39 +EXPORT_C CPBEncryptElement* CPBEncryptElement::NewLC(const TPBPassword& aPassword)
1.40 + {
1.41 + CPBEncryptElement* self = new(ELeave) CPBEncryptElement;
1.42 + CleanupStack::PushL(self);
1.43 + self->ConstructL(aPassword.Password());
1.44 + return self;
1.45 + }
1.46 +
1.47 +EXPORT_C CPBEncryptElement* CPBEncryptElement::NewL(const TPBPassword& aPassword,
1.48 + const TPBECipher aCipher)
1.49 + {
1.50 + CPBEncryptElement* self = NewLC(aPassword, aCipher);
1.51 + CleanupStack::Pop();
1.52 + return self;
1.53 + }
1.54 +
1.55 +EXPORT_C CPBEncryptElement* CPBEncryptElement::NewLC(const TPBPassword& aPassword,
1.56 + const TPBECipher aCipher)
1.57 + {
1.58 + CPBEncryptElement* self = new(ELeave) CPBEncryptElement;
1.59 + CleanupStack::PushL(self);
1.60 + self->ConstructL(aPassword.Password(), aCipher);
1.61 + return self;
1.62 + }
1.63 +
1.64 +EXPORT_C CPBEncryptElement* CPBEncryptElement::NewL(const TPBPassword& aPassword,
1.65 + const CPBEncryptParms& aParms)
1.66 + {
1.67 + CPBEncryptElement* self = NewLC(aPassword, aParms);
1.68 + CleanupStack::Pop();
1.69 + return self;
1.70 + }
1.71 +
1.72 +EXPORT_C CPBEncryptElement* CPBEncryptElement::NewLC(const TPBPassword& aPassword,
1.73 + const CPBEncryptParms& aParms)
1.74 + {
1.75 + CPBEncryptElement* self = new(ELeave) CPBEncryptElement;
1.76 + CleanupStack::PushL(self);
1.77 + self->ConstructL(aPassword.Password(), aParms);
1.78 + return self;
1.79 + }
1.80 +
1.81 +EXPORT_C CPBEncryptElement* CPBEncryptElement::NewL(
1.82 + const CPBEncryptionData& aData, const TPBPassword& aPassword)
1.83 + {
1.84 + CPBEncryptElement* self = CPBEncryptElement::NewLC(aData, aPassword);
1.85 + CleanupStack::Pop();
1.86 + return self;
1.87 + }
1.88 +
1.89 +EXPORT_C CPBEncryptElement* CPBEncryptElement::NewLC(
1.90 + const CPBEncryptionData& aData, const TPBPassword& aPassword)
1.91 + {
1.92 + CPBEncryptElement* self = new(ELeave) CPBEncryptElement;
1.93 + CleanupStack::PushL(self);
1.94 + self->ConstructL(aData, aPassword);
1.95 + return self;
1.96 + }
1.97 +
1.98 +CPBEncryptElement::CPBEncryptElement(void)
1.99 + {
1.100 + }
1.101 +
1.102 +CPBEncryptElement::~CPBEncryptElement(void)
1.103 + {
1.104 + delete iData;
1.105 + delete iEncryptKey;
1.106 + }
1.107 +
1.108 +void CPBEncryptElement::ConstructL(const TDesC8& aPassword)
1.109 + {
1.110 + // Construct based on cryptography strength
1.111 + if (TCrypto::Strength() == TCrypto::EStrong)
1.112 + {
1.113 + ConstructL(aPassword, KPBEDefaultStrongCipher);
1.114 + }
1.115 + else
1.116 + {
1.117 + ConstructL(aPassword, KPBEDefaultWeakCipher);
1.118 + }
1.119 + }
1.120 +
1.121 +void CPBEncryptElement::ConstructL(const TDesC8& aPassword, TPBECipher aCipher)
1.122 + {
1.123 + TBuf8<KPBEMaxCipherIVBytes> iv(KPBEMaxCipherIVBytes);
1.124 + iv.SetLength(PBE::GetBlockBytes(aCipher));
1.125 + TRandom::RandomL(iv);
1.126 +
1.127 + TBuf8<KPBEDefaultSaltBytes> encryptSalt(KPBEDefaultSaltBytes);
1.128 + TRandom::RandomL(encryptSalt);
1.129 +
1.130 + TBuf8<KPBEDefaultSaltBytes> authSalt(KPBEDefaultSaltBytes);
1.131 + TRandom::RandomL(authSalt);
1.132 +
1.133 + iData = CPBEncryptionData::NewL(aPassword, aCipher, authSalt, encryptSalt,
1.134 + iv, KDefaultIterations);
1.135 +
1.136 + MakeEncryptKeyL(PBE::GetKeyBytes(aCipher), aPassword);
1.137 + }
1.138 +
1.139 +void CPBEncryptElement::ConstructL(const CPBEncryptionData& aData,
1.140 + const TPBPassword& aPassword)
1.141 + {
1.142 + iData = CPBEncryptionData::NewL(aData);
1.143 + if(!AuthenticateL(aPassword))
1.144 + {
1.145 + User::Leave(KErrBadPassphrase);
1.146 + }
1.147 + }
1.148 +
1.149 +void CPBEncryptElement::ConstructL(const TDesC8& aPassword,
1.150 + const CPBEncryptParms& aParms)
1.151 + {
1.152 + TUint keySize = PBE::GetKeyBytes(aParms.Cipher());
1.153 +
1.154 + TBuf8<KPBEDefaultSaltBytes> authSalt(KPBEDefaultSaltBytes);
1.155 + TRandom::RandomL(authSalt);
1.156 +
1.157 + //Recreate parms with given data and create a totally new auth
1.158 + iData = CPBEncryptionData::NewL(aPassword, authSalt, aParms);
1.159 + MakeEncryptKeyL(keySize, aPassword);
1.160 + }
1.161 +
1.162 +const CPBEncryptionData& CPBEncryptElement::EncryptionData(void) const
1.163 + {
1.164 + return *iData;
1.165 + }
1.166 +
1.167 +CPBEncryptor* CPBEncryptElement::NewEncryptL() const
1.168 + {
1.169 + CPBEncryptor* encryptor = NewEncryptLC();
1.170 + CleanupStack::Pop();
1.171 + return encryptor;
1.172 + }
1.173 +
1.174 +CPBEncryptor* CPBEncryptElement::NewEncryptLC() const
1.175 + {
1.176 + CPBEncryptor* encryptor = CPBEncryptorElement::NewLC(
1.177 + iData->EncryptParms().Cipher(), *iEncryptKey,
1.178 + iData->EncryptParms().IV());
1.179 + return encryptor;
1.180 + }
1.181 +
1.182 +TBool CPBEncryptElement::AuthenticateL(const TPBPassword& aPassword)
1.183 + {
1.184 + TBool retval = EFalse;
1.185 +
1.186 + //create a new auth to test against the existing one
1.187 + //therefore we use the same key size, and salt as the current one
1.188 + CPBAuthData* auth = CPBAuthData::NewLC(aPassword.Password(),
1.189 + iData->AuthData().Salt(), iData->AuthData().Key().Size(),
1.190 + iData->AuthData().Iterations());
1.191 + if(*auth==iData->AuthData())
1.192 + {
1.193 + //We've got a valid password, regenerate the key so they can decrypt
1.194 + //stuff. We don't the change the length of iEncryptKey as we assume the
1.195 + //previous key size is appropriate for the new one
1.196 + MakeEncryptKeyL(PBE::GetKeyBytes(iData->EncryptParms().Cipher()),
1.197 + aPassword.Password());
1.198 + retval = ETrue;
1.199 + }
1.200 + CleanupStack::PopAndDestroy(auth);
1.201 + return retval;
1.202 + }
1.203 +
1.204 +CPBDecryptor* CPBEncryptElement::NewDecryptL() const
1.205 + {
1.206 + CPBDecryptor* decryptor = NewDecryptLC();
1.207 + CleanupStack::Pop();
1.208 + return decryptor;
1.209 + }
1.210 +
1.211 +CPBDecryptor* CPBEncryptElement::NewDecryptLC() const
1.212 + {
1.213 + CPBDecryptor* decryptor = CPBDecryptorElement::NewLC(
1.214 + iData->EncryptParms().Cipher(), *iEncryptKey,
1.215 + iData->EncryptParms().IV());
1.216 + return decryptor;
1.217 + }
1.218 +
1.219 +// Warning: This function is only valid BEFORE you call NewEncryptL
1.220 +// After creating the cipher, ask it about itself, not me!
1.221 +// This is _very_ dodgy as I assume all sorts of things about the encryptor.
1.222 +// 1) That it uses SSLv3 or similar style padding
1.223 +// 2) That it stores the IV for that stream at the front.
1.224 +// This is here for specific application that requires this and aren't able to
1.225 +// actually construct the cipher and ask it. In almost all other cases you
1.226 +// should construct the cipher and ask it.
1.227 +TInt CPBEncryptElement::MaxCiphertextLength(TInt aPlaintextLength) const
1.228 + {
1.229 + TUint blocksize = PBE::GetBlockBytes(iData->EncryptParms().Cipher());
1.230 + TUint padding = blocksize - aPlaintextLength % blocksize;
1.231 + //len = inputLength + padding
1.232 + return aPlaintextLength + padding;
1.233 + }
1.234 +
1.235 +// Warning: This function is only valid BEFORE you call NewDecryptL
1.236 +// After creating the cipher, ask it about itself, not me!
1.237 +TInt CPBEncryptElement::MaxPlaintextLength(TInt aCiphertextLength) const
1.238 + {
1.239 + /*It's impossible to determine anything about how much padding will be
1.240 + * removed. So we'll return a max length that is longer than will
1.241 + * ever happen by at most a blocksize - 1.
1.242 + */
1.243 + //totallength = inputlength - 1 byte of padding min
1.244 + return aCiphertextLength - 1;
1.245 + }
1.246 +
1.247 +void CPBEncryptElement::MakeEncryptKeyL(TUint aKeySize, const TDesC8& aPassword)
1.248 + {
1.249 + iEncryptKey = HBufC8::NewMaxL(aKeySize);
1.250 + TPtr8 encryptKeyBuf = iEncryptKey->Des();
1.251 + iData->EncryptParms().DeriveKeyL(aPassword, encryptKeyBuf);
1.252 + }
1.253 +
1.254 +EXPORT_C TPBPassword::TPBPassword(const TDesC8& aPassword)
1.255 + {
1.256 + iPassword.Set(aPassword);
1.257 + }
1.258 +
1.259 +EXPORT_C TPBPassword::TPBPassword(const TDesC16& aPassword)
1.260 + {
1.261 + iPassword.Set(reinterpret_cast<const TUint8*>(aPassword.Ptr()), aPassword.Size());
1.262 + }
1.263 +
1.264 +EXPORT_C const TDesC8& TPBPassword::Password(void) const
1.265 + {
1.266 + return iPassword;
1.267 + }
1.268 +
1.269 +