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 "des.h" sl@0: #include "destables.h" sl@0: #include "../common/inlines.h" sl@0: #include "des.inl" sl@0: #include sl@0: sl@0: const TInt KDESBlockBytes = 8; sl@0: const TInt KDESKeyBytes = 8; sl@0: sl@0: // bit 0 is left-most in byte sl@0: static const TInt bytebit[] = {0200,0100,040,020,010,04,02,01}; sl@0: sl@0: void CDES::Transform(TDes8& aBlock) sl@0: { sl@0: assert(aBlock.Size() == KDESBlockBytes); sl@0: sl@0: TUint32 l, r; sl@0: // Split the block into 2 word-sized big endian portions sl@0: GetBlockBigEndian((TUint8*)&aBlock[0], l, r); sl@0: sl@0: IPerm(l,r); sl@0: sl@0: CDES::DoTransform(l, r, iK1); sl@0: sl@0: FPerm(l,r); sl@0: sl@0: // Put the portions back into the block as little endian sl@0: PutBlockBigEndian((TUint8*)&aBlock[0], r, l); sl@0: } sl@0: sl@0: void CDES::DoTransform(TUint32& l, TUint32& r, const TUint32* aKey) sl@0: { sl@0: TInt i = 0; sl@0: for (; i<8; i++) sl@0: { sl@0: TUint32 work = rotrFixed(r, 4U) ^ aKey[4*i+0]; sl@0: l ^= DES_TABLE::sbox[6][(work) & 0x3f] sl@0: ^ DES_TABLE::sbox[4][(work >> 8) & 0x3f] sl@0: ^ DES_TABLE::sbox[2][(work >> 16) & 0x3f] sl@0: ^ DES_TABLE::sbox[0][(work >> 24) & 0x3f]; sl@0: work = r ^ aKey[4*i+1]; sl@0: l ^= DES_TABLE::sbox[7][(work) & 0x3f] sl@0: ^ DES_TABLE::sbox[5][(work >> 8) & 0x3f] sl@0: ^ DES_TABLE::sbox[3][(work >> 16) & 0x3f] sl@0: ^ DES_TABLE::sbox[1][(work >> 24) & 0x3f]; sl@0: sl@0: work = rotrFixed(l, 4U) ^ aKey[4*i+2]; sl@0: r ^= DES_TABLE::sbox[6][(work) & 0x3f] sl@0: ^ DES_TABLE::sbox[4][(work >> 8) & 0x3f] sl@0: ^ DES_TABLE::sbox[2][(work >> 16) & 0x3f] sl@0: ^ DES_TABLE::sbox[0][(work >> 24) & 0x3f]; sl@0: work = l ^ aKey[4*i+3]; sl@0: r ^= DES_TABLE::sbox[7][(work) & 0x3f] sl@0: ^ DES_TABLE::sbox[5][(work >> 8) & 0x3f] sl@0: ^ DES_TABLE::sbox[3][(work >> 16) & 0x3f] sl@0: ^ DES_TABLE::sbox[1][(work >> 24) & 0x3f]; sl@0: } sl@0: } sl@0: sl@0: sl@0: TInt CDES::BlockSize() const sl@0: { sl@0: return KDESBlockBytes; sl@0: } sl@0: sl@0: TInt CDES::KeySize() const sl@0: { sl@0: return KDESKeyBytes; sl@0: } sl@0: sl@0: CDES::~CDES() sl@0: { sl@0: delete iKey; sl@0: } sl@0: sl@0: void CDES::ConstructL(const TDesC8& aKey, TBool /*aCheckWeakKey*/) sl@0: { sl@0: assert(aKey.Size() == KDESKeyBytes); sl@0: sl@0: iKey = aKey.AllocL(); sl@0: SetKey(aKey, iK1); sl@0: } sl@0: sl@0: CDES::CDES() sl@0: { sl@0: } sl@0: sl@0: typedef TUint8 TKeyDES[KDESKeyBytes]; sl@0: const TInt KKnownWeakKeysCount = 16; sl@0: const TKeyDES weak_keys[KKnownWeakKeysCount] = sl@0: { sl@0: /* weak keys */ sl@0: {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, sl@0: {0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE}, sl@0: {0x1E,0x1E,0x1E,0x1E,0x0E,0x0E,0x0E,0x0E}, sl@0: {0xE0,0xE0,0xE0,0xE0,0xF0,0xF0,0xF0,0xF0}, sl@0: {0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE}, sl@0: {0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00}, sl@0: {0x1E,0xE0,0x1E,0xE0,0x0E,0xF0,0x0E,0xF0}, sl@0: {0xE0,0x1E,0xE0,0x1E,0xF0,0x0E,0xF0,0x0E}, sl@0: {0x00,0xE0,0x00,0xE0,0x00,0xF0,0x00,0xF0}, sl@0: {0xE0,0x00,0xE0,0x00,0xF0,0x00,0xF0,0x00}, sl@0: {0x1E,0xFE,0x1E,0xFE,0x0E,0xFE,0x0E,0xFE}, sl@0: {0xFE,0x1E,0xFE,0x1E,0xFE,0x0E,0xFE,0x0E}, sl@0: {0x00,0x1E,0x00,0x1E,0x00,0x0E,0x00,0x0E}, sl@0: {0x1E,0x00,0x1E,0x00,0x0E,0x00,0x0E,0x00}, sl@0: {0xE0,0xFE,0xE0,0xFE,0xF0,0xFE,0xF0,0xFE}, sl@0: {0xFE,0xE0,0xFE,0xE0,0xFE,0xF0,0xFE,0xF0} sl@0: }; sl@0: sl@0: void CDES::SetKey(const TDesC8& aKey, TUint32* aKeyBuffer) sl@0: { sl@0: TInt i=0, j=0, l=0, m=0; sl@0: sl@0: // Form a byte array from aKey, taking endianess into account (little->big) sl@0: TUint8 key[8]; // For big endian byte array sl@0: Mem::Copy(&key, &aKey[0], 8); sl@0: sl@0: TUint8 buffer[56+56+8]; sl@0: TUint8* const pc1m = &buffer[0]; /* place to modify pc1 into */ sl@0: TUint8* const pcr = pc1m + 56; /* place to rotate pc1 into */ sl@0: TUint8* const ks = pcr + 56; sl@0: sl@0: for (j=0; j<56; j++) sl@0: {/* convert pc1 to bits of key */ sl@0: l = DES_TABLE::pc1[j]-1; /* integer bit location */ sl@0: m = l & 07; /* find bit */ sl@0: pc1m[j]=(key[l>>3] & /* find which key byte l is in */ sl@0: bytebit[m]) /* and which bit of that byte */ sl@0: ? (TUint8)1 : (TUint8)0; /* and store 1-bit result */ sl@0: } sl@0: sl@0: for (i=0; i<16; i++) sl@0: {/* key chunk for each iteration */ sl@0: Mem::FillZ(ks,8); /* Clear key schedule */ sl@0: for (j=0; j<56; j++) sl@0: /* rotate pc1 the right amount */ sl@0: pcr[j] = pc1m[(l=j+DES_TABLE::totrot[i])<(j<28? 28 : 56) ? l: l-28]; sl@0: sl@0: /* rotate left and right halves independently */ sl@0: sl@0: for (j=0; j<48; j++) sl@0: {/* select bits individually */ sl@0: /* check bit that goes to ks[j] */ sl@0: if (pcr[DES_TABLE::pc2[j]-1]) sl@0: {/* mask it in if it's there */ sl@0: l= j % 6; sl@0: ks[j/6] |= bytebit[l] >> 2; sl@0: } sl@0: } sl@0: sl@0: /* Now convert to odd/even interleaved form for use in F */ sl@0: (*(aKeyBuffer+(2*i))) = ((TUint32)ks[0] << 24) sl@0: | ((TUint32)ks[2] << 16) sl@0: | ((TUint32)ks[4] << 8) sl@0: | ((TUint32)ks[6]); sl@0: sl@0: (*(aKeyBuffer+(2*i+1))) = ((TUint32)ks[1] << 24) sl@0: | ((TUint32)ks[3] << 16) sl@0: | ((TUint32)ks[5] << 8) sl@0: | ((TUint32)ks[7]); sl@0: } sl@0: } sl@0: sl@0: void CDES::Reset() sl@0: { sl@0: SetKey(*iKey, iK1); sl@0: } sl@0: sl@0: sl@0: /* CDESEncryptor */ sl@0: sl@0: EXPORT_C CDESEncryptor* CDESEncryptor::NewL(const TDesC8& aKey, sl@0: TBool aCheckWeakKey) sl@0: { sl@0: CDESEncryptor* me = CDESEncryptor::NewLC(aKey, aCheckWeakKey); sl@0: CleanupStack::Pop(me); sl@0: return (me); sl@0: } sl@0: sl@0: EXPORT_C CDESEncryptor* CDESEncryptor::NewLC(const TDesC8& aKey, sl@0: TBool aCheckWeakKey) sl@0: { sl@0: CDESEncryptor* me = new (ELeave) CDESEncryptor(); sl@0: CleanupStack::PushL(me); sl@0: me->ConstructL(aKey, aCheckWeakKey); sl@0: // DES only used 7 bits out of every key byte sl@0: TCrypto::IsSymmetricWeakEnoughL(BytesToBits(aKey.Size()) - aKey.Size()); sl@0: return (me); sl@0: } sl@0: sl@0: CDESEncryptor::CDESEncryptor() sl@0: { sl@0: } sl@0: sl@0: /* CDESDecryptor */ sl@0: sl@0: EXPORT_C CDESDecryptor* CDESDecryptor::NewL(const TDesC8& aKey, sl@0: TBool aCheckWeakKey) sl@0: { sl@0: CDESDecryptor* me = CDESDecryptor::NewLC(aKey, aCheckWeakKey); sl@0: CleanupStack::Pop(me); sl@0: return (me); sl@0: } sl@0: sl@0: EXPORT_C CDESDecryptor* CDESDecryptor::NewLC(const TDesC8& aKey, sl@0: TBool aCheckWeakKey) sl@0: { sl@0: CDESDecryptor* me = new (ELeave) CDESDecryptor(); sl@0: CleanupStack::PushL(me); sl@0: me->ConstructL(aKey, aCheckWeakKey); sl@0: // DES only used 7 bits out of every key byte sl@0: TCrypto::IsSymmetricWeakEnoughL(BytesToBits(aKey.Size()) - aKey.Size()); sl@0: return (me); sl@0: } sl@0: sl@0: sl@0: CDESDecryptor::CDESDecryptor() sl@0: { sl@0: } sl@0: sl@0: void CDESDecryptor::SetKey(const TDesC8& aKey, TUint32* aKeyBuffer) sl@0: { sl@0: CDES::SetKey(aKey, aKeyBuffer); sl@0: sl@0: ReverseKeySchedule(iK1); sl@0: } sl@0: sl@0: EXPORT_C TBool CDES::IsWeakKey(const TDesC8& aKey) sl@0: { sl@0: TKeyDES key; sl@0: TInt index = 0; sl@0: //Reset parity bits sl@0: for(; index < KDESKeyBytes; index++) sl@0: { sl@0: key[index] = aKey[index] & 0xFE; sl@0: } sl@0: sl@0: TBool weak = EFalse; sl@0: //Compare key with potential weak keys without parity sl@0: for (index=0; index < KKnownWeakKeysCount; index++) sl@0: { sl@0: if (Mem::Compare(weak_keys[index], KDESKeyBytes, &key[0], KDESKeyBytes)==0) sl@0: { sl@0: weak = ETrue; sl@0: break; sl@0: } sl@0: } sl@0: return weak; sl@0: } sl@0: