os/security/crypto/weakcryptospi/source/pbe/pbe.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /*
     2 * Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     4 * This component and the accompanying materials are made available
     5 * under the terms of the License "Eclipse Public License v1.0"
     6 * which accompanies this distribution, and is available
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
     8 *
     9 * Initial Contributors:
    10 * Nokia Corporation - initial contribution.
    11 *
    12 * Contributors:
    13 *
    14 * Description: 
    15 *
    16 */
    17 
    18 
    19 #include <e32std.h>
    20 #include <random.h>
    21 #include <cryptostrength.h>
    22 #include <securityerr.h>
    23 #include <pbedata.h>
    24 #include "pkcs5kdf.h"
    25 #include "pbe.h"
    26 #include <pbencryptor.h>
    27 #include "pbesymmetricfactory.h"
    28 
    29 EXPORT_C CPBEncryptElement* CPBEncryptElement::NewL(const TPBPassword& aPassword)
    30 	{
    31 	CPBEncryptElement* self = NewLC(aPassword);
    32 	CleanupStack::Pop();
    33 	return self;
    34 	}
    35 
    36 EXPORT_C CPBEncryptElement* CPBEncryptElement::NewLC(const TPBPassword& aPassword)
    37 	{
    38 	CPBEncryptElement* self = new(ELeave) CPBEncryptElement;
    39 	CleanupStack::PushL(self);
    40 	self->ConstructL(aPassword.Password());
    41 	return self;
    42 	}
    43 
    44 EXPORT_C CPBEncryptElement* CPBEncryptElement::NewL(const TPBPassword& aPassword, 
    45 	const TPBECipher aCipher)
    46 	{
    47 	CPBEncryptElement* self = NewLC(aPassword, aCipher);
    48 	CleanupStack::Pop();
    49 	return self;
    50 	}
    51 
    52 EXPORT_C CPBEncryptElement* CPBEncryptElement::NewLC(const TPBPassword& aPassword, 
    53 	const TPBECipher aCipher)
    54 	{
    55 	CPBEncryptElement* self = new(ELeave) CPBEncryptElement;
    56 	CleanupStack::PushL(self);
    57 	self->ConstructL(aPassword.Password(), aCipher);
    58 	return self;
    59 	}
    60 
    61 EXPORT_C CPBEncryptElement* CPBEncryptElement::NewL(const TPBPassword& aPassword, 
    62 	const CPBEncryptParms& aParms)
    63 	{
    64 	CPBEncryptElement* self = NewLC(aPassword, aParms);
    65 	CleanupStack::Pop();
    66 	return self;
    67 	}
    68 
    69 EXPORT_C CPBEncryptElement* CPBEncryptElement::NewLC(const TPBPassword& aPassword, 
    70 	const CPBEncryptParms& aParms)
    71 	{
    72 	CPBEncryptElement* self = new(ELeave) CPBEncryptElement;
    73 	CleanupStack::PushL(self);
    74 	self->ConstructL(aPassword.Password(), aParms);
    75 	return self;
    76 	}
    77 
    78 EXPORT_C CPBEncryptElement* CPBEncryptElement::NewL(
    79 	const CPBEncryptionData& aData, const TPBPassword& aPassword)
    80 	{
    81 	CPBEncryptElement* self = CPBEncryptElement::NewLC(aData, aPassword);
    82 	CleanupStack::Pop();
    83 	return self;
    84 	}
    85 
    86 EXPORT_C CPBEncryptElement* CPBEncryptElement::NewLC(
    87 	const CPBEncryptionData& aData, const TPBPassword& aPassword)
    88 	{
    89 	CPBEncryptElement* self = new(ELeave) CPBEncryptElement;
    90 	CleanupStack::PushL(self);
    91 	self->ConstructL(aData, aPassword);
    92 	return self;
    93 	}
    94 
    95 CPBEncryptElement::CPBEncryptElement(void) 
    96 	{
    97 	}
    98 
    99 CPBEncryptElement::~CPBEncryptElement(void)
   100 	{
   101 	delete iData;
   102 	delete iEncryptKey;
   103 	}
   104 
   105 void CPBEncryptElement::ConstructL(const TDesC8& aPassword)
   106 	{
   107 	// Construct based on cryptography strength
   108 	if (TCrypto::Strength() == TCrypto::EStrong)
   109 		{
   110 		ConstructL(aPassword, KPBEDefaultStrongCipher);
   111 		}
   112 	else
   113 		{
   114 		ConstructL(aPassword, KPBEDefaultWeakCipher);
   115 		}
   116 	}
   117 
   118 void CPBEncryptElement::ConstructL(const TDesC8& aPassword, TPBECipher aCipher)
   119 	{
   120 	TBuf8<KPBEMaxCipherIVBytes> iv(KPBEMaxCipherIVBytes);
   121 	iv.SetLength(PBE::GetBlockBytes(aCipher));
   122 	TRandom::RandomL(iv);
   123 
   124 	TBuf8<KPBEDefaultSaltBytes> encryptSalt(KPBEDefaultSaltBytes);
   125 	TRandom::RandomL(encryptSalt);
   126 
   127 	TBuf8<KPBEDefaultSaltBytes> authSalt(KPBEDefaultSaltBytes);
   128 	TRandom::RandomL(authSalt);
   129 
   130 	iData = CPBEncryptionData::NewL(aPassword, aCipher, authSalt, encryptSalt,
   131 		iv, KDefaultIterations);
   132 
   133 	MakeEncryptKeyL(PBE::GetKeyBytes(aCipher), aPassword);
   134 	}
   135 
   136 void CPBEncryptElement::ConstructL(const CPBEncryptionData& aData, 
   137 	const TPBPassword& aPassword)
   138 	{
   139 	iData = CPBEncryptionData::NewL(aData);
   140 	if(!AuthenticateL(aPassword))
   141 		{
   142 		User::Leave(KErrBadPassphrase);
   143 		}
   144 	}
   145 
   146 void CPBEncryptElement::ConstructL(const TDesC8& aPassword,
   147 	const CPBEncryptParms& aParms)
   148 	{
   149 	TUint keySize = PBE::GetKeyBytes(aParms.Cipher());
   150 
   151 	TBuf8<KPBEDefaultSaltBytes> authSalt(KPBEDefaultSaltBytes);
   152 	TRandom::RandomL(authSalt);
   153 
   154 	//Recreate parms with given data and create a totally new auth
   155 	iData = CPBEncryptionData::NewL(aPassword, authSalt, aParms);
   156 	MakeEncryptKeyL(keySize, aPassword);
   157 	}
   158 
   159 const CPBEncryptionData& CPBEncryptElement::EncryptionData(void) const
   160 	{
   161 	return *iData;
   162 	}
   163 
   164 CPBEncryptor* CPBEncryptElement::NewEncryptL() const 
   165 	{
   166 	CPBEncryptor* encryptor = NewEncryptLC();
   167 	CleanupStack::Pop();
   168 	return encryptor;
   169 	}
   170 
   171 CPBEncryptor* CPBEncryptElement::NewEncryptLC() const
   172 	{
   173 	CPBEncryptor* encryptor = CPBEncryptorElement::NewLC( 
   174 		iData->EncryptParms().Cipher(), *iEncryptKey, 
   175 		iData->EncryptParms().IV());
   176 	return encryptor;
   177 	}
   178 
   179 TBool CPBEncryptElement::AuthenticateL(const TPBPassword& aPassword)
   180 	{
   181 	TBool retval = EFalse;
   182 
   183 	//create a new auth to test against the existing one
   184 	//therefore we use the same key size, and salt as the current one
   185 	CPBAuthData* auth = CPBAuthData::NewLC(aPassword.Password(),
   186 		iData->AuthData().Salt(), iData->AuthData().Key().Size(),
   187 		iData->AuthData().Iterations());
   188 	if(*auth==iData->AuthData())
   189 		{
   190 		//We've got a valid password, regenerate the key so they can decrypt
   191 		//stuff.  We don't the change the length of iEncryptKey as we assume the
   192 		//previous key size is appropriate for the new one
   193 		MakeEncryptKeyL(PBE::GetKeyBytes(iData->EncryptParms().Cipher()),
   194 			aPassword.Password());
   195 		retval = ETrue;
   196 		}
   197 	CleanupStack::PopAndDestroy(auth);
   198 	return retval;
   199 	}
   200 
   201 CPBDecryptor* CPBEncryptElement::NewDecryptL() const
   202 	{
   203 	CPBDecryptor* decryptor = NewDecryptLC();
   204 	CleanupStack::Pop();
   205 	return decryptor;
   206 	}
   207 
   208 CPBDecryptor* CPBEncryptElement::NewDecryptLC() const
   209 	{
   210 	CPBDecryptor* decryptor = CPBDecryptorElement::NewLC(
   211 		iData->EncryptParms().Cipher(), *iEncryptKey,
   212 		iData->EncryptParms().IV());
   213 	return decryptor;
   214 	}
   215 
   216 // Warning: This function is only valid BEFORE you call NewEncryptL
   217 // After creating the cipher, ask it about itself, not me!
   218 // This is _very_ dodgy as I assume all sorts of things about the encryptor.
   219 // 1) That it uses SSLv3 or similar style padding
   220 // 2) That it stores the IV for that stream at the front.
   221 // This is here for specific application that requires this and aren't able to
   222 // actually construct the cipher and ask it.  In almost all other cases you
   223 // should construct the cipher and ask it.
   224 TInt CPBEncryptElement::MaxCiphertextLength(TInt aPlaintextLength) const
   225 	{
   226 	TUint blocksize = PBE::GetBlockBytes(iData->EncryptParms().Cipher());
   227 	TUint padding = blocksize - aPlaintextLength % blocksize;
   228 	//len = inputLength + padding
   229 	return aPlaintextLength + padding;
   230 	}
   231 
   232 // Warning: This function is only valid BEFORE you call NewDecryptL
   233 // After creating the cipher, ask it about itself, not me!
   234 TInt CPBEncryptElement::MaxPlaintextLength(TInt aCiphertextLength) const
   235 	{
   236 	/*It's impossible to determine anything about how much padding will be
   237 	 * removed.  So we'll return a max length that is longer than will
   238 	 * ever happen by at most a blocksize - 1.
   239 	 */
   240 	//totallength = inputlength - 1 byte of padding min
   241 	return aCiphertextLength - 1;
   242 	}
   243 
   244 void CPBEncryptElement::MakeEncryptKeyL(TUint aKeySize, const TDesC8& aPassword)
   245 	{
   246 	iEncryptKey = HBufC8::NewMaxL(aKeySize);
   247 	TPtr8 encryptKeyBuf = iEncryptKey->Des();
   248 	iData->EncryptParms().DeriveKeyL(aPassword, encryptKeyBuf);
   249 	}
   250 
   251 EXPORT_C TPBPassword::TPBPassword(const TDesC8& aPassword)
   252 	{
   253 	iPassword.Set(aPassword);
   254 	}
   255 
   256 EXPORT_C TPBPassword::TPBPassword(const TDesC16& aPassword)
   257 	{
   258 	iPassword.Set(reinterpret_cast<const TUint8*>(aPassword.Ptr()), aPassword.Size());
   259 	}
   260 
   261 EXPORT_C const TDesC8& TPBPassword::Password(void) const
   262 	{
   263 	return iPassword;
   264 	}
   265 
   266