1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/cryptoplugins/cryptospiplugins/source/softwarecrypto/desimpl.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,249 @@
1.4 +/*
1.5 +* Copyright (c) 2006-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 "desimpl.h"
1.23 +
1.24 +#include "destables.h"
1.25 +#include "common/inlines.h"
1.26 +#include "des.inl"
1.27 +#include "pluginconfig.h"
1.28 +#include "symmetriccipherimpl.h"
1.29 +#include <cryptostrength.h>
1.30 +
1.31 +
1.32 +// bit 0 is left-most in byte
1.33 +static const TInt bytebit[] = {0200,0100,040,020,010,04,02,01};
1.34 +
1.35 +using namespace SoftwareCrypto;
1.36 +
1.37 +/* CDesImpl */
1.38 +CDesImpl::CDesImpl(
1.39 + TUint8 aBlockBytes,
1.40 + TUid aCryptoMode,
1.41 + TUid aOperationMode,
1.42 + TUid aPadding) :
1.43 + CSymmetricBlockCipherImpl(aBlockBytes, aCryptoMode, aOperationMode, aPadding)
1.44 + {
1.45 + }
1.46 +
1.47 +CDesImpl* CDesImpl::NewL(const CKey& aKey, TUid aCryptoMode, TUid aOperationMode, TUid aPadding)
1.48 + {
1.49 + CDesImpl* self = CDesImpl::NewLC(aKey, aCryptoMode, aOperationMode, aPadding);
1.50 + CleanupStack::Pop(self);
1.51 + return self;
1.52 + }
1.53 +
1.54 +CDesImpl* CDesImpl::NewLC(const CKey& aKey, TUid aCryptoMode, TUid aOperationMode, TUid aPadding)
1.55 + {
1.56 + CDesImpl* self = new(ELeave) CDesImpl(KDesBlockBytes, aCryptoMode, aOperationMode, aPadding);
1.57 + CleanupStack::PushL(self);
1.58 + self->ConstructL(aKey);
1.59 +
1.60 + const TDesC8& keyContent = aKey.GetTDesC8L(KSymmetricKeyParameterUid);
1.61 + TCrypto::IsSymmetricWeakEnoughL(BytesToBits(keyContent.Size()) - keyContent.Size());
1.62 + return self;
1.63 + }
1.64 +
1.65 +CDesImpl::~CDesImpl()
1.66 + {
1.67 + // make sure key information isn't visible to other processes if the
1.68 + // page is reused.
1.69 + Mem::FillZ(&iK, sizeof(iK));
1.70 + }
1.71 +
1.72 +void CDesImpl::ConstructL(const CKey& aKey)
1.73 + {
1.74 + CSymmetricBlockCipherImpl::ConstructL(aKey);
1.75 + SetKeySchedule();
1.76 + }
1.77 +
1.78 +CExtendedCharacteristics* CDesImpl::CreateExtendedCharacteristicsL()
1.79 + {
1.80 + // All Symbian software plug-ins have unlimited concurrency, cannot be reserved
1.81 + // for exclusive use and are not CERTIFIED to be standards compliant.
1.82 + return CExtendedCharacteristics::NewL(KMaxTInt, EFalse);
1.83 + }
1.84 +
1.85 +const CExtendedCharacteristics* CDesImpl::GetExtendedCharacteristicsL()
1.86 + {
1.87 + return CDesImpl::CreateExtendedCharacteristicsL();
1.88 + }
1.89 +
1.90 +TUid CDesImpl::ImplementationUid() const
1.91 + {
1.92 + return KCryptoPluginDesUid;
1.93 + }
1.94 +
1.95 +TBool CDesImpl::IsValidKeyLength(TInt aKeyBytes) const
1.96 + {
1.97 + return (aKeyBytes == KDesKeyBytes);
1.98 + }
1.99 +
1.100 +TInt CDesImpl::GetKeyStrength() const
1.101 + {
1.102 + // parity bits are excluded
1.103 + return BytesToBits(KDesKeyBytes - 8);
1.104 + }
1.105 +
1.106 +void CDesImpl::TransformEncrypt(
1.107 + TUint8* aBuffer,
1.108 + TUint aNumBlocks)
1.109 + {
1.110 + for (TInt i = 0; i < aNumBlocks; ++i)
1.111 + {
1.112 + ModeEncryptStart(aBuffer);
1.113 + TUint32 l, r;
1.114 + // Split the block into 2 word-sized big endian portions
1.115 + GetBlockBigEndian(aBuffer, l, r);
1.116 + IPerm(l,r);
1.117 + DoTransform(l, r, iK);
1.118 + FPerm(l,r);
1.119 +
1.120 + // Put the portions back into the block as little endian
1.121 + PutBlockBigEndian(aBuffer, r, l);
1.122 +
1.123 + ModeEncryptEnd(aBuffer);
1.124 + aBuffer += KDesBlockBytes;
1.125 + }
1.126 + }
1.127 +
1.128 +void CDesImpl::TransformDecrypt(
1.129 + TUint8* aBuffer,
1.130 + TUint aNumBlocks)
1.131 + {
1.132 + for (TInt i = 0; i < aNumBlocks; ++i)
1.133 + {
1.134 + ModeDecryptStart(aBuffer);
1.135 +
1.136 + TUint32 l, r;
1.137 + // Split the block into 2 word-sized big endian portions
1.138 + GetBlockBigEndian(aBuffer, l, r);
1.139 +
1.140 + IPerm(l,r);
1.141 + DoTransform(l, r, iK);
1.142 + FPerm(l,r);
1.143 +
1.144 + // Put the portions back into the block as little endian
1.145 + PutBlockBigEndian(aBuffer, r, l);
1.146 +
1.147 + ModeDecryptEnd(aBuffer);
1.148 + aBuffer += KDesBlockBytes;
1.149 + }
1.150 + }
1.151 +
1.152 +void CDesImpl::SetKeySchedule()
1.153 + {
1.154 + if (iCryptoMode.iUid == KCryptoModeEncrypt)
1.155 + {
1.156 + SetEncryptKeySchedule(*iKey, iK);
1.157 + }
1.158 + else
1.159 + {
1.160 + ASSERT(iCryptoMode.iUid == KCryptoModeDecrypt);
1.161 + SetDecryptKeySchedule(*iKey, iK);
1.162 + }
1.163 + }
1.164 +
1.165 +void CDesImpl::DoTransform(TUint32& l, TUint32& r, const TUint32* aKeySchedule)
1.166 + {
1.167 + TInt i = 0;
1.168 + for (; i<8; i++)
1.169 + {
1.170 + TUint32 work = rotrFixed(r, 4U) ^ aKeySchedule[4*i+0];
1.171 + l ^= DES_TABLE::sbox[6][(work) & 0x3f]
1.172 + ^ DES_TABLE::sbox[4][(work >> 8) & 0x3f]
1.173 + ^ DES_TABLE::sbox[2][(work >> 16) & 0x3f]
1.174 + ^ DES_TABLE::sbox[0][(work >> 24) & 0x3f];
1.175 + work = r ^ aKeySchedule[4*i+1];
1.176 + l ^= DES_TABLE::sbox[7][(work) & 0x3f]
1.177 + ^ DES_TABLE::sbox[5][(work >> 8) & 0x3f]
1.178 + ^ DES_TABLE::sbox[3][(work >> 16) & 0x3f]
1.179 + ^ DES_TABLE::sbox[1][(work >> 24) & 0x3f];
1.180 +
1.181 + work = rotrFixed(l, 4U) ^ aKeySchedule[4*i+2];
1.182 + r ^= DES_TABLE::sbox[6][(work) & 0x3f]
1.183 + ^ DES_TABLE::sbox[4][(work >> 8) & 0x3f]
1.184 + ^ DES_TABLE::sbox[2][(work >> 16) & 0x3f]
1.185 + ^ DES_TABLE::sbox[0][(work >> 24) & 0x3f];
1.186 + work = l ^ aKeySchedule[4*i+3];
1.187 + r ^= DES_TABLE::sbox[7][(work) & 0x3f]
1.188 + ^ DES_TABLE::sbox[5][(work >> 8) & 0x3f]
1.189 + ^ DES_TABLE::sbox[3][(work >> 16) & 0x3f]
1.190 + ^ DES_TABLE::sbox[1][(work >> 24) & 0x3f];
1.191 + }
1.192 + }
1.193 +
1.194 +void CDesImpl::SetEncryptKeySchedule(const TDesC8& aKey, TUint32* aKeySchedule)
1.195 + {
1.196 + TInt i=0, j=0, l=0, m=0;
1.197 +
1.198 +// Form a byte array from aKey, taking endianess into account (little->big)
1.199 + TUint8 key[8]; // For big endian byte array
1.200 + Mem::Copy(&key, &aKey[0], 8);
1.201 +
1.202 + TUint8 buffer[56+56+8];
1.203 + TUint8* const pc1m = &buffer[0]; /* place to modify pc1 into */
1.204 + TUint8* const pcr = pc1m + 56; /* place to rotate pc1 into */
1.205 + TUint8* const ks = pcr + 56;
1.206 +
1.207 + for (j=0; j<56; j++)
1.208 + {/* convert pc1 to bits of key */
1.209 + l = DES_TABLE::pc1[j]-1; /* integer bit location */
1.210 + m = l & 07; /* find bit */
1.211 + pc1m[j]=(key[l>>3] & /* find which key byte l is in */
1.212 + bytebit[m]) /* and which bit of that byte */
1.213 + ? (TUint8)1 : (TUint8)0; /* and store 1-bit result */
1.214 + }
1.215 +
1.216 + for (i=0; i<16; i++)
1.217 + {/* key chunk for each iteration */
1.218 + Mem::FillZ(ks,8); /* Clear key schedule */
1.219 + for (j=0; j<56; j++)
1.220 + /* rotate pc1 the right amount */
1.221 + pcr[j] = pc1m[(l=j+DES_TABLE::totrot[i])<(j<28? 28 : 56) ? l: l-28];
1.222 +
1.223 + /* rotate left and right halves independently */
1.224 +
1.225 + for (j=0; j<48; j++)
1.226 + {/* select bits individually */
1.227 + /* check bit that goes to ks[j] */
1.228 + if (pcr[DES_TABLE::pc2[j]-1])
1.229 + {/* mask it in if it's there */
1.230 + l= j % 6;
1.231 + ks[j/6] |= bytebit[l] >> 2;
1.232 + }
1.233 + }
1.234 +
1.235 + /* Now convert to odd/even interleaved form for use in F */
1.236 + (*(aKeySchedule+(2*i))) = ((TUint32)ks[0] << 24)
1.237 + | ((TUint32)ks[2] << 16)
1.238 + | ((TUint32)ks[4] << 8)
1.239 + | ((TUint32)ks[6]);
1.240 +
1.241 + (*(aKeySchedule+(2*i+1))) = ((TUint32)ks[1] << 24)
1.242 + | ((TUint32)ks[3] << 16)
1.243 + | ((TUint32)ks[5] << 8)
1.244 + | ((TUint32)ks[7]);
1.245 + }
1.246 + }
1.247 +
1.248 +void CDesImpl::SetDecryptKeySchedule(const TDesC8& aKey, TUint32* aKeySchedule)
1.249 + {
1.250 + SetEncryptKeySchedule(aKey, aKeySchedule);
1.251 + ReverseKeySchedule(aKeySchedule);
1.252 + }