--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/networksecurity/ipsec/ipsec6/src/sa_crypt.cpp Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,1012 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// sa_crypt.cpp - IPv6/IPv4 IPSEC interface to crypto libraries
+// IPsec interface to cryptographic libraries -- the implementation.
+//
+
+
+
+/**
+ @file sa_crypt.cpp
+*/
+#include "ext_hdr.h"
+#include <networking/pfkeyv2.h>
+#include "sa_spec.h"
+#include "sa_crypt.h"
+#include <networking/ipsecerr.h>
+#include "ipseccrypto.h"
+#include "keys.h"
+#include "cryptospidef.h"
+#ifdef SYMBIAN_IPSEC_VOIP_SUPPORT
+#include "cryptomacapi.h"
+#endif //SYMBIAN_IPSEC_VOIP_SUPPORT
+
+class TLibraryPtr
+ /**
+ * Description of installed cryptographic library.
+ */
+ {
+public:
+ TLibraryPtr() : iLibrary(NULL), iName(KNullDesC), iAlgs(NULL), iNum(0) {}
+ TLibraryPtr(CProtocolCrypto* aLibrary, const TDesC &aName, TAlgorithmDesc *algs, TUint aNum)
+ : iLibrary(aLibrary), iName(aName), iAlgs(algs), iNum(aNum) {}
+
+ CProtocolCrypto* iLibrary; //< Library (protocol) instance
+ TProtocolName iName; //< Symbolic name of the library
+ TAlgorithmDesc *iAlgs; //< Supported Algorithms descriptions
+ TUint iNum; //< Number of Algorithms
+ };
+
+
+class CLibraryList : public CArrayFixFlat<TLibraryPtr>
+ /**
+ * List of installed libraries.
+ * Implemented as an array of TLibraryPtr, each of which
+ * describes one cryptographi library.
+ */
+ {
+public:
+ CLibraryList() : CArrayFixFlat<TLibraryPtr>(2) {}
+ ~CLibraryList();
+ void AddL(CProtocolCrypto* aLibrary);
+ TUint Lookup(const TAlgorithmMap &aMap, TLibraryPtr **aLib);
+ };
+
+
+void CLibraryList::AddL(CProtocolCrypto* aLibrary)
+ /**
+ * Add a cryptographic library to the list.
+ *
+ * Find out the list of algoritms supported by this library (AlgorithmList()), and
+ * if there are some, then add this library to the list of available libaries.
+ *
+ * @param aLibrary The crypto protocol.
+ * @leave error if library cannot be added.
+ */
+ {
+ TAlgorithmDesc *algs = NULL;
+ TServerProtocolDesc desc;
+
+ aLibrary->Identify(&desc);
+ TUint num = aLibrary->AlgorithmList(algs);
+ //coverity[leave_without_push]
+ LOG(Log::Printf(_L("Registering crypto library: %S with %d algorithms"), &desc.iName, num));
+ if (algs)
+ {
+ CleanupStack::PushL(algs);
+ TLibraryPtr ptr(aLibrary, desc.iName, algs, num);
+ AppendL(ptr);
+ CleanupStack::Pop();
+ aLibrary->Open();
+#ifdef _LOG
+ for (TInt i = 0; i < num; ++i)
+ {
+ const TAlgorithmDesc &a = algs[i];
+ if (a.iAlgType == EAlgorithmClass_Digest)
+ {
+ Log::Printf(_L("\tDigest %S block=%d"), &a.iName, a.iBlock);
+ }
+ else if (a.iAlgType == EAlgorithmClass_Cipher)
+ {
+ Log::Printf(_L("\tCipher %S block=%d, IV=%d key min=%d max=%d"),
+ &a.iName, a.iBlock, a.iVector, a.iMinBits, a.iMaxBits);
+ }
+#ifdef SYMBIAN_IPSEC_VOIP_SUPPORT
+ else if (a.iAlgType == EAlgorithmClass_Mac)
+ {
+ Log::Printf(_L("\tMac %S block=%d, IV=%d key min=%d max=%d"),
+ &a.iName, a.iBlock, a.iVector, a.iMinBits, a.iMaxBits);
+
+ }
+#endif // SYMBIAN_IPSEC_VOIP_SUPPORT
+ else
+ {
+ Log::Printf(_L("\tUnknown %S block=%d, IV=%d key min=%d max=%d"),
+ &a.iName, a.iBlock, a.iVector, a.iMinBits, a.iMaxBits);
+ }
+ }
+#endif
+ }
+ }
+
+CLibraryList::~CLibraryList()
+ /**
+ * Desctructor.
+ *
+ * Resease resources and Close() the crypto protocol modules.
+ */
+ {
+ TInt i, n;
+ n = Count();
+ TLibraryPtr *lib;
+
+ for (i = 0; i < n; i++)
+ {
+ lib = &operator[](i);
+ delete[] lib->iAlgs;
+ if (lib->iLibrary)
+ lib->iLibrary->Close();
+ }
+ }
+
+
+TUint CLibraryList::Lookup(const TAlgorithmMap &aMap, TLibraryPtr **aLib)
+ {
+ /**
+ * Lookup a library that implements the specified algorithm.
+ *
+ * If the map entry specifies a specific library, then only that
+ * library is examined for a match of algorithm name.
+ *
+ * The algorithm search is based on algorithm name (not on number).
+ *
+ * @param aMap The algorithm to find.
+ * @retval The library that implements it.
+ */
+ TInt i, n;
+ n = Count();
+ TLibraryPtr *lib;
+
+ for (i = 0; i < n; i++)
+ {
+ lib = &operator[](i);
+ if (aMap.iLibrary.Length() == 0 ||
+ aMap.iLibrary == lib->iName)
+ {
+ //
+ // Search Algorithms within this library
+ //
+ for (TUint j = 0; j < lib->iNum; ++j)
+ {
+ if (lib->iAlgs[j].iName == aMap.iAlgorithm)
+ {
+ *aLib = lib;
+ return j;
+ }
+ }
+ }
+ }
+ // Requested algorithm is not available! This is configuration
+ // error, because Security Policy should not request algorithms
+ // that are not installed.
+ *aLib = NULL;
+ return 0;
+ }
+
+CIpsecCryptoManager::CIpsecCryptoManager()
+ /**
+ * Constructor.
+ *
+ * Only called from CIpsecCryptoManager::NewL().
+ */
+ {
+ }
+
+CIpsecCryptoManager* CIpsecCryptoManager::NewL()
+ /**
+ * Return instance of crypto library manager.
+ *
+ * @return Cryptographic libarary manager.
+ */
+ {
+ CIpsecCryptoManager *self = new (ELeave) CIpsecCryptoManager();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+void CIpsecCryptoManager::ConstructL()
+ /**
+ * Construction.
+ *
+ * The construction creates initial library list (empty) and algorithm map
+ * (initialised with the default mapping). The default mapping uses the standard
+ * algorithm number symbols defined in the standard <networking/pfkeyv2.h> as follows:
+ * @code
+ * // Algorithm Bits Library Name
+ * SADB_AALG_MD5HMAC, 96, KNullDesC, KIpsecName_MD5
+ * SADB_AALG_SHA1HMAC, 96, KNullDesC, KIpsecName_SHA1
+ * SADB_EALG_DESCBC, 64, KNullDesC, KIpsecName_DES_CBC
+ * SADB_EALG_3DESCBC, 64, KNullDesC, KIpsecName_3DES_CBC
+ * SADB_EALG_NULL , 0, KNullDesC, KNullDesC
+ * SADB_X_AALG_AES_XCBC_MAC, 128, KNullDesC, KIpsecName_AES_XCBC_MAC
+ * @endcode
+ *
+ * @leave error if not enough memory.
+ */
+ {
+ iLibraryList = new (ELeave) CLibraryList;
+ iAlgorithmList = new (ELeave) CAlgorithmList;
+
+ // Default mapping IPSEC algorithm numbers to engines:
+ // Should read these mappings from some ini file. For test purposes,
+ // the following mappings are now hard coded (library = "" => use
+ // whichever defines the algorithm first).
+ iAlgorithmList->AddL(EAlgorithmClass_Digest, SADB_AALG_MD5HMAC , 96, KNullDesC, KIpsecName_MD5);
+ iAlgorithmList->AddL(EAlgorithmClass_Digest, SADB_AALG_SHA1HMAC , 96, KNullDesC, KIpsecName_SHA1);
+ iAlgorithmList->AddL(EAlgorithmClass_Cipher, SADB_EALG_DESCBC , 64, KNullDesC, KIpsecName_DES_CBC);
+ iAlgorithmList->AddL(EAlgorithmClass_Cipher, SADB_EALG_3DESCBC , 64, KNullDesC, KIpsecName_3DES_CBC);
+ iAlgorithmList->AddL(EAlgorithmClass_Cipher, SADB_EALG_AESCBC , 64, KNullDesC, KIpsecName_AES_CBC);
+#ifdef SYMBIAN_IPSEC_VOIP_SUPPORT
+ iAlgorithmList->AddL(EAlgorithmClass_Mac, SADB_AALG_AES_XCBC_MAC , 128,KNullDesC,KIpsecName_AES_XCBC_MAC );
+#endif //SYMBIAN_IPSEC_VOIP_SUPPORT
+#ifdef SYMBIAN_CRYPTOSPI
+ iAlgorithmList->AddL(EAlgorithmClass_Cipher, SADB_EALG_AESCTR , 64, KNullDesC, KIpsecName_AES_CTR);
+#endif //SYMBIAN_CRYPTOSPI
+ iAlgorithmList->AddL(EAlgorithmClass_Cipher, SADB_EALG_NULL , 0, KNullDesC, KNullDesC);
+
+ }
+
+CIpsecCryptoManager::~CIpsecCryptoManager()
+ /**
+ * Descructor.
+ *
+ * Delete algorithm mapping and library list.
+ */
+ {
+ delete iLibraryList;
+ delete iAlgorithmList;
+ }
+
+void CIpsecCryptoManager::SetAlgorithms(CAlgorithmList*& aList)
+ /**
+ * Update the algorithm map with a new mapping table.
+ *
+ * Replace the current algorithm list with a the new list, take ownership
+ * of the structure and place NULL into aList.
+ *
+ * Algorithm mapping cannot be set to NULL using this method.
+ *
+ * @param aList The algorithm list (must be non-NULL)
+ */
+ {
+ if (aList)
+ {
+ // Replace old with new
+ delete iAlgorithmList;
+ iAlgorithmList = aList;
+ aList = NULL;
+ }
+#ifdef _LOG
+ if (iAlgorithmList)
+ {
+ const TInt N = iAlgorithmList->Count();
+ for (TInt i = 0; i < N; ++i)
+ {
+ const TAlgorithmMap &map = (*iAlgorithmList)[i];
+ _LIT(KEncr, "ENCR");
+ _LIT(KAuth, "AUTH");
+ Log::Printf(_L("\tAlgorithmMap %S %d (bits=%d) maps to %S.%S"),
+ map.iClass == EAlgorithmClass_Digest ? &KAuth() : &KEncr(),
+ map.iId, map.iBits,
+ &map.iLibrary, &map.iAlgorithm);
+ }
+ }
+ else
+ {
+ Log::Printf(_L("\tAlgorithmMap does not exist"));
+ }
+#endif
+ }
+
+void CIpsecCryptoManager::AddLibraryL(CProtocolCrypto *aLibrary)
+ /**
+ * Add a cryptographic library to the list.
+ *
+ * Add a cryptographic library packaged as a protocol into the
+ * list of installed libraries. The CLibraryList::AddL() does
+ * the major work.
+ *
+ * @param aLibrary The crypto protocol.
+ */
+ {
+ iLibraryList->AddL(aLibrary);
+ }
+
+
+CArrayFixFlat<struct sadb_alg> *CIpsecCryptoManager::SupportedAlgorithms
+ (TInt &aNumAuth, TInt &aNumEncrypt)
+ /**
+ * Ask the supported algorithms of a library.
+ *
+ * This function has a very specialized use: return supported
+ * algorithms, when a PFKEY reply to the REGISTER message is generated
+ * (CProtocolKey::ExecRegister). The format of the return value is tailored
+ * for that purpose.
+ *
+ * Return a dynamically alloated (heap) array of 'sadb_alg'
+ * descriptions. The first aNumAuth descriptors are authentication
+ * algorithms, and the tail aNumEncrypt are encryption
+ * algorithms.
+ *
+ * @retval aNumAuth Count of authentication algorithms
+ * @retval aNumEncrypt Count of cipher algorithms
+ * return Algorithm descriptions
+ *
+ * The return is guaranteed to be non-NULL, if aNumAuth + aNumEncrypt > 0.
+ */
+ {
+ CArrayFixFlat<struct sadb_alg> *algs;
+ TInt n;
+
+ aNumAuth = 0;
+ aNumEncrypt = 0;
+
+ if (iAlgorithmList == NULL ||
+ iLibraryList == NULL ||
+ (n = iAlgorithmList->Count()) == 0)
+ return NULL; // No algorithms supported!
+ //
+ // Allocate all the space that is needed
+ //
+ // Sets 'aNumEncrypt' in case the heap allocations
+ // fail (a NULL return with non-zero count is used
+ // to indicate Memory Allocation error).
+ aNumEncrypt = n;
+ algs = new CArrayFixFlat<struct sadb_alg>(n);
+ if (!algs)
+ return NULL;
+ TRAPD(left, algs->ResizeL(n));
+ if (left)
+ {
+ delete algs;
+ return NULL;
+ }
+ aNumEncrypt = 0;
+ //
+ // -- All requred heap space has now been allocated --
+ // (The space is contigous in memory)
+ struct sadb_alg *auth = algs->Back(0);
+ struct sadb_alg *encrypt = algs->End(0);
+
+ for (TInt i = 0; i < n; ++i)
+ {
+ struct sadb_alg *alg;
+ TAlgorithmMap &p = iAlgorithmList->At(i);
+ if (p.iAlgorithm.Length() == 0 && p.iClass == EAlgorithmClass_Cipher )
+ {
+ // The NULL encryption is indicated by empty string in the
+ // algorithm name. NULL encryption is supported, if the
+ // mapping has such entry configured...
+ alg = encrypt - ++aNumEncrypt;
+ alg->sadb_alg_id = (TUint8)p.iId;
+ alg->sadb_alg_ivlen = 0;
+ alg->sadb_alg_minbits = 0;
+ alg->sadb_alg_maxbits = 0;
+ alg->sadb_alg_reserved = 0;
+ continue;
+ }
+ TLibraryPtr *lib;
+ TInt j = iLibraryList->Lookup(p, &lib);
+ if (lib != NULL)
+ {
+ // A matching library instance and algorithm
+ // located, fill in the algorithm description.
+ if (p.iClass == EAlgorithmClass_Digest)
+ {
+ alg = auth + aNumAuth++;
+ alg->sadb_alg_ivlen = 0;
+ }
+ else if (p.iClass == EAlgorithmClass_Cipher)
+ {
+ alg = encrypt - ++aNumEncrypt;
+ alg->sadb_alg_ivlen = (TUint8)lib->iAlgs[j].iVector;
+ }
+#ifdef SYMBIAN_IPSEC_VOIP_SUPPORT
+ else if (p.iClass == EAlgorithmClass_Mac )
+ {
+ alg = auth + aNumAuth++;
+ alg->sadb_alg_ivlen = 0;
+ }
+#endif //SYMBIAN_IPSEC_VOIP_SUPPORT
+ else
+ continue; // Some unknown algorithm class, that
+ // cannot be used by this implementation.
+ alg->sadb_alg_id = (TUint8)p.iId;
+ alg->sadb_alg_minbits = (TUint16)lib->iAlgs[j].iMinBits;
+ alg->sadb_alg_maxbits = (TUint16)lib->iAlgs[j].iMaxBits;
+ alg->sadb_alg_reserved = 0;
+ }
+ }
+ return algs;
+ }
+
+class CAuthenticationHmac : public CAuthenticationBase
+ /**
+ * HMAC authentication.
+ *
+ * Implement the (RFC-2104) HMAC based keyed authentication as used by IPsec.
+ */
+ {
+ friend class CIpsecCryptoManager;
+public:
+ virtual void Init();
+ virtual void Update(const TDesC8& aMessage);
+ virtual const TDesC8 &Final(TInt aSize);
+ virtual TInt Compare(const TDesC8& aDigest);
+ virtual TInt BlockSize() const {return iBlockSize;}
+ //
+ // Return the number of bytes defined by the algorithm
+ // map, not the real digest length of the algorithm.
+ virtual TInt DigestSize() const {return (iBits + 7) / 8;}
+protected:
+ static CAuthenticationHmac* NewL(const TLibraryPtr &lib, TUint anIndex, const TDesC8 &aKey, TInt aBits);
+ void ConstructL(const TLibraryPtr &lib, TUint anIndex, const TDesC8 &aKey, TInt aBits);
+ virtual ~CAuthenticationHmac();
+private:
+ CAuthenticationHmac();
+protected:
+ HBufC8 *iHmac_ipad; //< Precomputed HMAC input pad
+ HBufC8 *iHmac_opad; //< Precomputed HMAC output pad
+ HBufC8 *iTemp; //< Working space (at least native digest size)
+ TInt iBlockSize; //< The blocksize in bytes
+ TInt iDigestSize; //< The digest size in bytes
+ TInt iBits; //< Number of bits used from the digest.
+ CMessageDigestCrypto *iDigest;//< The raw message digest engine
+ };
+
+
+CAuthenticationHmac::CAuthenticationHmac()
+ /**
+ * Constructor.
+ */
+ {
+ }
+
+CAuthenticationHmac* CAuthenticationHmac::NewL(const TLibraryPtr &aLib, TUint anIndex, const TDesC8 &aKey, TInt aBits)
+ /**
+ * Create HMAC authentication engine.
+ *
+ * @param aLib The library to use for the digest engine
+ * @param anIndex The digest algorithm number in library
+ * @param aKey The authentication key
+ * @param aBits The number of bits used from the digets.
+ */
+ {
+ CAuthenticationHmac *self = new (ELeave) CAuthenticationHmac();
+ CleanupStack::PushL(self);
+ self->ConstructL(aLib, anIndex, aKey, aBits);
+ CleanupStack::Pop(); // self
+ return self;
+ }
+
+void CAuthenticationHmac::ConstructL(const TLibraryPtr &aLib, TUint anIndex, const TDesC8 &aKey, TInt aBits)
+ {
+ /**
+ * Setup HMAC processing using the specified digest.
+ *
+ * @param aLib The library to use for the digest engine
+ * @param anIndex The digest algorithm number in library
+ * @param aKey The authentication key
+ * @param aBits The number of bits used from the digets.
+ */
+ iDigest = aLib.iLibrary->MessageDigest(anIndex);
+ iBlockSize = aLib.iAlgs[anIndex].iBlock;
+ iDigestSize = aLib.iAlgs[anIndex].iVector;
+ iBits = aBits;
+
+ iHmac_ipad = HBufC8::NewMaxL(iBlockSize);
+ iHmac_opad = HBufC8::NewMaxL(iBlockSize);
+ iTemp = HBufC8::NewMaxL(iDigestSize);
+ TPtr8 ipad(iHmac_ipad->Des());
+ TPtr8 opad(iHmac_opad->Des());
+ if (aKey.Length() > iBlockSize)
+ {
+ iDigest->Init();
+ iDigest->Update(aKey);
+ iDigest->Final(ipad);
+ ipad.SetLength(iDigestSize);
+ }
+ else
+ ipad = aKey;
+
+ opad.SetLength(iBlockSize);
+ int i;
+ for (i = 0; i < ipad.Length(); ++i)
+ {
+ opad[i] = (TUint8)(ipad[i] ^ 0x5c);
+ ipad[i] ^= 0x36;
+ }
+ ipad.SetLength(iBlockSize);
+ for ( ;i < iBlockSize; ++i)
+ {
+ ipad[i] = 0x36;
+ opad[i] = 0x5c;
+ }
+ }
+
+
+CAuthenticationHmac::~CAuthenticationHmac()
+ /**
+ * Destructor.
+ *
+ * Clear the memory areas containing the key information, before
+ * releasing the memory.
+ */
+ {
+ if (iHmac_ipad)
+ {
+ iHmac_ipad->Des().FillZ();
+ delete iHmac_ipad;
+ }
+ if (iHmac_opad)
+ {
+ iHmac_opad->Des().FillZ();
+ delete iHmac_opad;
+ }
+ if (iTemp)
+ {
+ iTemp->Des().FillZ();
+ delete iTemp;
+ }
+ delete iDigest;
+ }
+
+void CAuthenticationHmac::Init()
+ /**
+ * Initialize authentication for a packet.
+ *
+ * Reset digest enginge and feed the input (HMAC) pad to it.
+ */
+ {
+ iDigest->Init(); // Initialize Digest engine
+ iDigest->Update(*iHmac_ipad); // Feed in the precomputed input pad
+ };
+
+void CAuthenticationHmac::Update(const TDesC8& aMessage)
+ /**
+ * Feed data to the digest.
+ *
+ * @param aMessage The data.
+ */
+ {
+ iDigest->Update(aMessage); // Feed actual payload material
+ }
+
+const TDesC8 &CAuthenticationHmac::Final(TInt aSize)
+ /**
+ * Finish the digest computation and return ICV.
+ *
+ * @param aSize The length of the ICV (bytes).
+ * @return The computed ICV
+ */
+ {
+ TPtr8 ptr = iTemp->Des();
+ ptr.SetLength(iDigestSize); // Ensure correct length! [also in *iTemp!]
+ iDigest->Final(ptr); // Get Current Digest Value
+ iDigest->Init(); // Initialize Digest Engine
+ iDigest->Update(*iHmac_opad); // Feed in the precomputed output pad
+ iDigest->Update(ptr); // Merge with digest from the first phase
+ iDigest->Final(ptr); // and produce the final digest value.
+
+ if (ptr.Length() > aSize) // The caller may want a trucated value
+ ptr.SetLength(aSize); // [This changes also *iTemp length!]
+ return *iTemp;
+ }
+
+TInt CAuthenticationHmac::Compare(const TDesC8 &aDigest)
+ /**
+ * Finish the digets computation and compare with ICV.
+ *
+ * @param aDigest The ICV to match
+ * @return comparison result (= 0, match, != 0, no match).
+ */
+ {
+ TPtr8 ptr = iTemp->Des();
+ ptr.SetLength(iDigestSize); // Ensure correct length!
+ iDigest->Final(ptr); // Get Current Digest Value
+ iDigest->Init(); // Initialize Digest Engine
+ iDigest->Update(*iHmac_opad); // Feed in the precomputed output pad
+ iDigest->Update(ptr); // Merge with digest from the first phase
+ iDigest->Final(ptr); // and produce the final digest value.
+ // The caller may want a tructated value
+ ptr.SetLength(aDigest.Length());
+ return aDigest.Compare(ptr);
+ }
+
+
+class CEncryptionCipher : public CEncryptionBase
+ /**
+ * IPsec Cipher class using externally given algorithm.
+ *
+ * Acts as an intermediate between the IPsec and the raw external
+ * cryptographic algorithm.
+ */
+ {
+ friend class CIpsecCryptoManager;
+public:
+ virtual void EncryptL(const TDesC8& anIV); // Reset encryption engine
+ virtual void DecryptL(const TDesC8& anIV); // Reset encryption engine
+ virtual void UpdateL(TDes8& aBuf, TDes8& aBufOut); // Encrypt/decrypt a block
+ virtual void UpdateFinalL(TDes8& aBuf, TDes8& aBufOut); // Encrypt/decrypt the last block
+ virtual TInt BlockSize() const {return iBlockSize; } // Fetch the block size of the algorithm under consideration
+ virtual TInt GetOutputLength(TInt aInputLen); // Fetch the encrypt/decrypt output length of given block from crypto
+ virtual TInt GetFinalOutputLength(TInt aInputLen); // Fetch the encrypt/decrypt output length of final block from crypto
+ virtual TInt IVSize() const {return iIVSize;} // Fetch the IVSize of the algorithm under consideration
+ virtual void Reset(); // Reset the encryptor/decryptor state at the crypto layer
+protected:
+ static CEncryptionCipher* NewL(const TLibraryPtr &aLib, TUint anIndex, const TDesC8 &aKey, TInt aBits);
+ void ConstructL(const TLibraryPtr &aLib, TUint anIndex, const TDesC8 &aKey, TInt aBits);
+ virtual ~CEncryptionCipher();
+ TInt iBlockSize; //< The blocksize in bytes
+ TInt iIVSize; //< The IV size in bytes
+ TInt iBits; //< Number of bits used from the IV
+ CryptoSpi::CSymmetricCipher *iEncrypt; //< The raw encryption engine
+ };
+
+CEncryptionCipher*
+CEncryptionCipher::NewL(const TLibraryPtr &aLib, TUint anIndex, const TDesC8 &aKey, TInt aBits)
+ /**
+ * Construct cipher engine.
+ *
+ * @param aLib The library to use.
+ * @param anIndex The algorithm number in library.
+ * @param aKey The encryption key to be used in the encryption/decryption operation
+ * @param aBits The IV length.
+ */
+ {
+ CEncryptionCipher *self = new (ELeave) CEncryptionCipher();
+ CleanupStack::PushL(self);
+ self->ConstructL(aLib, anIndex, aKey, aBits);
+ CleanupStack::Pop(); // self
+ return self;
+ }
+
+void CEncryptionCipher::ConstructL(const TLibraryPtr &aLib, TUint anIndex, const TDesC8 &aKey, TInt aBits)
+ {
+ iEncrypt = aLib.iLibrary->SymmetricCipherL(anIndex, aKey);
+ iBlockSize = aLib.iAlgs[anIndex].iBlock;
+ iIVSize = aLib.iAlgs[anIndex].iVector;
+ iBits = aBits;
+ }
+
+CEncryptionCipher::~CEncryptionCipher()
+ /**
+ * Destructor.
+ */
+ {
+ delete iEncrypt;
+ }
+
+void CEncryptionCipher::EncryptL(const TDesC8& anIV)
+ /**
+ * Start cipher in encryption mode.
+ *
+ * @param anIV The IV to start with.
+ */
+ {
+ iEncrypt->SetCryptoModeL(CryptoSpi::KCryptoModeEncryptUid);
+ iEncrypt->SetIvL(anIV);
+ }
+
+void CEncryptionCipher::DecryptL(const TDesC8& anIV)
+ /**
+ * Start cipher in decryption mode.
+ *
+ * @param anIV The IV to start with.
+ */
+ {
+ iEncrypt->SetCryptoModeL(CryptoSpi::KCryptoModeDecryptUid);
+ iEncrypt->SetIvL(anIV);
+ }
+
+TInt CEncryptionCipher::GetOutputLength(TInt aInputLen)
+ /**
+ * Determine output length for the given input length
+ *
+ *@param aInputLen Length of the input data
+ */
+ {
+ return iEncrypt->MaxOutputLength(aInputLen);
+ }
+
+TInt CEncryptionCipher::GetFinalOutputLength(TInt aInputLen)
+ /**
+ * Determine output length for the given input length
+ *
+ *@param aInputLen Length of the input data
+ */
+ {
+ return iEncrypt->MaxFinalOutputLength(aInputLen);
+ }
+
+void CEncryptionCipher::UpdateL(TDes8& aBuf, TDes8& aBufOut)
+ /**
+ * Feed data to cipher engine (decrypt or encrypt).
+ *
+ * @param aBuf The input data buffer for encryption/decryption operation
+ * @param aBufOut The output data buffer for encryption/decryption operation
+ *
+ */
+ {
+ iEncrypt->ProcessL(aBuf, aBufOut);
+ }
+
+void CEncryptionCipher::UpdateFinalL(TDes8& aBuf, TDes8& aBufOut)
+ /**
+ * Feed data to cipher engine (decrypt or encrypt) to process the final block.
+ *
+ * @param aBuf The input data buffer for encryption/decryption operation
+ * @param aBufOut The output data buffer for encryption/decryption operation
+ */
+ {
+ iEncrypt->ProcessFinalL(aBuf, aBufOut);
+ }
+
+void CEncryptionCipher::Reset ()
+ /**
+ * Reset the state of encryption/decryption operation. Invoked as part of handling of internal errors.
+ *
+ * @param <None>
+ */
+ {
+ if (iEncrypt)
+ {
+ iEncrypt->Reset();
+ }
+ }
+class CEncryptionNull : public CEncryptionBase
+ /**
+ * NULL Encryption Engine.
+ *
+ * Implements the NULL encryption for the RFC-2410 purposes.
+ */
+ {
+ friend class CIpsecCryptoManager;
+public:
+ virtual void EncryptL(const TDesC8& /*anIV*/) {} // Reset encryption engine
+ virtual void DecryptL(const TDesC8& /*anIV*/) {} // Reset encryption engine
+ virtual void UpdateL(TDes8& aBuf, TDes8& aBufOut) { aBufOut.Copy(aBuf);} // Encrypt/decrypt a block
+ virtual void UpdateFinalL(TDes8& aBuf, TDes8& aBufOut) { aBufOut.Copy(aBuf);} // Encrypt/decrypt last block
+ virtual TInt GetOutputLength(TInt aInputLength) { return aInputLength;}
+ virtual TInt GetFinalOutputLength(TInt aInputLength) { return aInputLength;}
+ virtual TInt BlockSize() const {return 1; }
+ virtual TInt IVSize() const {return 0;}
+ virtual void Reset() {}
+protected:
+ CEncryptionNull() {}
+ ~CEncryptionNull() {}
+ };
+
+CEncryptionBase *CIpsecCryptoManager::NewEncryptL(TInt anAlg, const TDesC8 &aKey)
+ /**
+ * Create an instance of cipher engine.
+ *
+ * Create a new IPsec encryption engine (CEncryptionBase) using the key and
+ * encryption algorithm (anAlg).
+ *
+ * @li First, use the algorithm number to locate the symbolic name
+ * name of the algorithm from the algorithm map
+ * @li then use this name to search supported algorithm from the
+ * installed crypto libraries.
+ * If found, ask the the library to create a symmetric cipher engine for
+ * this algorithm.
+ *
+ * @param anAlg The algorithm number
+ * @param aKey The key for the algorithm
+ * @return The cipher engine.
+ */
+ {
+ TAlgorithmMap *map = iAlgorithmList->Lookup(EAlgorithmClass_Cipher, anAlg);
+
+ if (!map)
+ User::Leave(EIpsec_UnknownCipherNumber);
+
+ if (map->iAlgorithm.Length() == 0)
+ //
+ // The NULL encryption is indicated by empty string in the
+ // algorithm name. Instantiate a NULL encryption "cipher"
+ return new CEncryptionNull();
+
+ TLibraryPtr *lib;
+ TUint index = iLibraryList->Lookup(*map, &lib);
+ if (!lib)
+ User::Leave(EIpsec_UnavailableCipher);
+ LOG(Log::Printf(_L("\t* using cipher %S(%d) from library %S"), &map->iAlgorithm, anAlg, &lib->iName));
+ CEncryptionCipher *enc = CEncryptionCipher::NewL(*lib, index, aKey, map->iBits);
+ if (enc && enc->iEncrypt)
+ {
+ return enc; // All OK.
+ }
+ delete enc;
+ //
+ // Getting here implies fatal error, something is not working
+ //
+ return NULL;
+ }
+
+
+CAuthenticationBase *CIpsecCryptoManager::NewAuthL(TInt anAlg, const TDesC8 &aKey)
+ /**
+ * Create an instance of authentication engine.
+ * Create a new IPsec authentication engine (CAuthenticationBase) using the key and
+ * digest algorithm (anAlg). First use the algorithm number to find the symbolic
+ * name of the algorithm from the algorithm map, then use this name to search
+ * supported algorithm from the installed crypto libraries. If found,
+ * ask the library to create a raw message digest engine for this algorithm.
+ *
+ * The current IPsec authentication uses the digest engine to implement HMAC
+ * keyed-hash authentication as described in RFC-2104. The number of bits
+ * actually used from the digest value is determined by the respective
+ * configuration parameter in the algorithm map entry.
+ *
+ * @param anAlg The authentication algorithm number
+ * @param aKey The authentication key
+ * @return The authentication engine.
+ *
+ * @leave EIpsec_UnknownDigestNumber if anAlg does not appear in algorithm list
+ * @leave EIpsec_UnavailableDigest if no library implements the requested algorithm
+ * @leave other on other errors
+ */
+ {
+ TAlgorithmMap *map = iAlgorithmList->Lookup(EAlgorithmClass_Digest, anAlg);
+
+ if (!map)
+ User::Leave(EIpsec_UnknownDigestNumber);
+
+ if (map->iAlgorithm.Length() > 0)
+ {
+ TLibraryPtr *lib;
+ TUint index = iLibraryList->Lookup(*map, &lib);
+ if (!lib)
+ User::Leave(EIpsec_UnavailableDigest);
+ LOG(Log::Printf(_L("\t* using digest %S(%d) from library %S"), &map->iAlgorithm, anAlg, &lib->iName));
+ return CAuthenticationHmac::NewL(*lib, index, aKey, map->iBits);
+ }
+ //
+ // Getting here implies fatal error, something is not working
+ //
+ return NULL;
+ }
+
+#ifdef SYMBIAN_IPSEC_VOIP_SUPPORT
+class CAuthenticationMac : public CAuthenticationBase
+ {
+ friend class CIpsecCryptoManager;
+public:
+ virtual void Init() ;
+ virtual void Update(const TDesC8& aMessage);
+ virtual const TDesC8 &Final(TInt aSize);
+ virtual TInt BlockSize() const {return iBlockSize;}
+ virtual TInt Compare(const TDesC8& aDigest);
+ virtual TInt DigestSize() const {return (iBits + 7) / 8;}
+ //
+ // Return the number of bytes defined by the algorithm
+ // map, not the real digest length of the algorithm.
+ virtual TInt MacSize() const {return (iBits + 7) / 8;}
+protected:
+ static CAuthenticationMac* NewL(const TLibraryPtr &lib, TUint anIndex, const TDesC8 &aKey, TInt aBits);
+ void ConstructL(const TLibraryPtr &lib, TUint anIndex, const TDesC8 &aKey, TInt aBits);
+ virtual ~CAuthenticationMac();
+private:
+ CAuthenticationMac();
+protected:
+ TInt iBlockSize; //< The blocksize in bytes
+ TInt iMacOutputSize; //< The digest size in bytes
+ TInt iBits; //< Number of bits used from the digest.
+ TInt iIVSize;
+ HBufC8* iTemp;
+ CMacCrypto *iMacCrypto;
+ CryptoSpi::CMac *iMacImpl;
+ };
+
+CAuthenticationMac::CAuthenticationMac()
+ /**
+ * Constructor.
+ */
+ {
+ }
+
+CAuthenticationMac::~CAuthenticationMac()
+ /**
+ * Destructor.
+ *
+ * Clear the memory areas containing the key information, before
+ * releasing the memory.
+ */
+ {
+ }
+void CAuthenticationMac::Init()
+ /**
+ * Initialize authentication for a packet.
+ *
+ * Reset digest enginge and feed the input (HMAC) pad to it.
+ */
+ {
+ };
+CAuthenticationMac* CAuthenticationMac::NewL(const TLibraryPtr &aLib, TUint anIndex, const TDesC8 &aKey, TInt aBits)
+ /**
+ * Create MAC authentication engine.
+ *
+ * @param aLib The library to use for the MacCrypto engine
+ * @param anIndex The digest algorithm number in library
+ * @param aKey The authentication key
+ * @param aBits The number of bits used from the digets.
+ */
+ {
+ CAuthenticationMac *self = new (ELeave) CAuthenticationMac();
+ CleanupStack::PushL(self);
+ self->ConstructL(aLib, anIndex, aKey, aBits);
+ CleanupStack::Pop(); // self
+ return self;
+ }
+void CAuthenticationMac ::ConstructL(const TLibraryPtr &aLib, TUint anIndex, const TDesC8 &aKey, TInt aBits)
+ {
+ iMacImpl = aLib.iLibrary->GetMacImplementationL( aKey);
+ iMacOutputSize = aLib.iAlgs[anIndex].iVector;
+ iBlockSize = aLib.iAlgs[anIndex].iBlock;
+ iIVSize = aLib.iAlgs[anIndex].iVector;
+ iBits = aBits;
+ iTemp = HBufC8::NewMaxL(iMacOutputSize);
+ }
+
+
+
+void CAuthenticationMac::Update(const TDesC8& aMessage)
+ /**
+ * Feed data to the digest.
+ *
+ * @param aMessage The data.
+ */
+ {
+ iMacImpl->UpdateL(aMessage); // Feed actual payload material
+ }
+
+
+
+const TDesC8 &CAuthenticationMac::Final(TInt /* aSize */)
+ /**
+ * Finish the digest computation
+ */
+ {
+ //presently return temp value
+ return *iTemp;
+ }
+
+TInt CAuthenticationMac::Compare(const TDesC8 &aDigest)
+ /**
+ * Finish the digets computation and compare with ICV.
+ *
+ * @param aDigest The ICV to match
+ * @return comparison result (= 0, match, != 0, no match).
+ */
+ {
+ return aDigest.Compare(iTemp->Des());
+ }
+
+CAuthenticationBase *CIpsecCryptoManager::NewMacL(TInt anAlg, const TDesC8 &aKey)
+ {
+ TAlgorithmMap *map = iAlgorithmList->Lookup(EAlgorithmClass_Mac, anAlg);
+ if (!map)
+ User::Leave(EIpsec_UnknownCipherNumber);
+
+ if (map->iAlgorithm.Length() > 0)
+ {
+ TLibraryPtr *lib;
+ TUint index = iLibraryList->Lookup(*map, &lib);
+ if (!lib)
+ User::Leave(EIpsec_UnavailableCipher);
+ LOG(Log::Printf(_L("\t* using digest %S(%d) from library %S"), &map->iAlgorithm, anAlg, &lib->iName));
+ return CAuthenticationMac::NewL(*lib, index, aKey, map->iBits);
+ }
+ //
+ // Getting here implies fatal error, something is not working
+ //
+ return NULL;
+ }
+
+
+#endif //SYMBIAN_IPSEC_VOIP_SUPPORT
+