diff -r 000000000000 -r 164170e6151a pkiutilities/PKCS12/CrPkcs12/Src/crcrypto.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkiutilities/PKCS12/CrPkcs12/Src/crcrypto.cpp Tue Jan 26 15:20:08 2010 +0200 @@ -0,0 +1,919 @@ +/* +* Copyright (c) 2000, 2004 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: This file contains the implementation of CCrCrypto class. +* +*/ + + + +// INCLUDE FILES +#include "crcrypto.h" +#include // REINTERPRET_CAST +#include "crdata.h" +#include // Big integer. +#include +#include + + +// ----------------------------------------------------------------------------- +// CCrCrypto +// Constructor. +// ----------------------------------------------------------------------------- +CCrCrypto::CCrCrypto() + : iAlgorithmInfos(0) + { + } + +// ----------------------------------------------------------------------------- +// ~CCrCrypto +// Destructor. +// ----------------------------------------------------------------------------- +CCrCrypto::~CCrCrypto() + { + Reset(); + + if( iAlgorithmInfos ) + { + iAlgorithmInfos->Reset(); + delete iAlgorithmInfos; + iAlgorithmInfos = NULL; + } + } + +// ----------------------------------------------------------------------------- +// CCrCrypto::ConstructL +// This function initializes this object's members. +// ----------------------------------------------------------------------------- +void CCrCrypto::ConstructL() + { + iAlgorithmInfos = new (ELeave) CArrayPtrFlat(1); + } + +// ----------------------------------------------------------------------------- +// CCrCrypto::NewLC +// ----------------------------------------------------------------------------- +CCrCrypto* CCrCrypto::NewLC() + { + CCrCrypto* self = new (ELeave) CCrCrypto(); + CleanupStack::PushL(self); + + self->ConstructL(); + + return self; + } + +// ----------------------------------------------------------------------------- +// CCrCrypto::NewL +// ----------------------------------------------------------------------------- +CCrCrypto* CCrCrypto::NewL() + { + CCrCrypto* self = NewLC(); + CleanupStack::Pop(); + + return self; + } + +// ----------------------------------------------------------------------------- +// CCrCrypto::Reset +// Reset all algorithms initialized into this object and free +// memory associated to them. Note that GetDigest etc. functions are +// meaningles after this until new ones are initialized and finalized. +// ----------------------------------------------------------------------------- +void CCrCrypto::Reset() + { + TInt i = 0; + TInt size = 0; + CCrAlgInfo* algInfo = 0; + + size = iAlgorithmInfos->Count(); + + for (i = 0; i < size; i++) + { + algInfo = (*iAlgorithmInfos)[i]; + + if (algInfo) + { + switch (algInfo->iType) + { + case ECrDES2: + case ECrDES3: + { + if (algInfo->iAlgorithmObject) + { + delete algInfo->iAlgorithmObject; + algInfo->iAlgorithmObject = NULL; + } + if (algInfo->iPadding) + { + delete algInfo->iPadding; + algInfo->iPadding = NULL; + } + + break; + } + default: + { + if (algInfo->iAlgorithmObject) + { + delete algInfo->iAlgorithmObject; + algInfo->iAlgorithmObject = NULL; + } + + if (algInfo->iPadding) + { + delete algInfo->iPadding; + algInfo->iPadding = NULL; + } + + break; + } + } + } + } + + iAlgorithmInfos->ResetAndDestroy(); + } + +// ----------------------------------------------------------------------------- +// CCrCrypto::InitCrypt3DESL +// Initialize encryption or decryption with 3DES algorithm. +// ----------------------------------------------------------------------------- +TCrStatus CCrCrypto::InitCrypt3DESL( + const TDesC8& aKey1, + const TDesC8& aKey2, + const TDesC8& aKey3, + const TDesC8& aIV, + TBool aEncrypt, // ETrue + TCrSymmMode aMode, // ECrCBC + TPaddingRule /*aPadRule*/) // ECrPKCS1 + { + // Number of items pushed to CleanupStack + TUint pushedToCStack = 0; + + // Combined keys. + HBufC8* keys = HBufC8::NewLC( + aKey1.Length() + aKey2.Length() + aKey3.Length()); + ++pushedToCStack; + + TPtr8 ptrKeys = keys->Des(); + + // Combine given keys to be able to give them to algorithm info object. + ptrKeys = aKey1; + ptrKeys.Append(aKey2); + ptrKeys.Append(aKey3); + + // Create new algorithm info object. + CCrAlgInfo* algInfo = CCrAlgInfo::NewLC( + ECrDES3, + *keys, + aIV, + aEncrypt, + ETrue, + aMode); + ++pushedToCStack; + + switch (aMode) + { + case ECrCBC: + { + if (aEncrypt) + { + C3DESEncryptor* tripleDes = C3DESEncryptor::NewL(*algInfo->iKey); + CleanupStack::PushL(tripleDes); + + CModeCBCEncryptor* cbcEncryptor = CModeCBCEncryptor::NewL(tripleDes, aIV); + CleanupStack::Pop(tripleDes); // CModeCBCEncryptor takes care of tripleDes now + CleanupStack::PushL(cbcEncryptor); + + CPaddingPKCS7* padding = CPaddingPKCS7::NewL(tripleDes->BlockSize()); + CleanupStack::PushL(padding); + + CBufferedEncryptor* encryptor = CBufferedEncryptor::NewL(cbcEncryptor, padding); + CleanupStack::Pop(2); // CBufferedEncryptor takes care of freeing + + algInfo->iAlgorithmObject = encryptor; + } + else + { + C3DESDecryptor* tripleDes = C3DESDecryptor::NewL(*algInfo->iKey); + CleanupStack::PushL(tripleDes); + + CModeCBCDecryptor* cbcDecryptor = CModeCBCDecryptor::NewL(tripleDes, aIV); + CleanupStack::Pop(tripleDes); // CModeCBCEncryptor takes care of tripleDes now + CleanupStack::PushL(cbcDecryptor); + + CPaddingPKCS7* padding = CPaddingPKCS7::NewL(tripleDes->BlockSize()); + CleanupStack::PushL(padding); + + CBufferedDecryptor* decryptor = CBufferedDecryptor::NewL(cbcDecryptor, padding); + CleanupStack::Pop(2); // CBufferedDecryptor takes care of freeing + + algInfo->iAlgorithmObject = decryptor; + } + break; + } + case ECrCFB: + { + return KCrCrypto | KCrUnknownMode; + } + case ECrECB: + { + return KCrCrypto | KCrUnknownMode; + } + case ECrOFB: + { + return KCrCrypto | KCrUnknownMode; + } + default: + { + return KCrCrypto | KCrUnknownMode; + } + } + + CleanupStack::PushL(algInfo->iAlgorithmObject); + ++pushedToCStack; + + // Append new algorithm info object into member set. + iAlgorithmInfos->AppendL(algInfo); + + CleanupStack::Pop(pushedToCStack); + + delete keys; + keys = NULL; + + return KCrOK; + } + +// ----------------------------------------------------------------------------- +// CCrCrypto::InitCryptRC2L +// Initialize encryption or decryption with RC2 algorithm. +// ----------------------------------------------------------------------------- +TCrStatus CCrCrypto::InitCryptRC2L( + const TDesC8& aKey, + const TDesC8& aIV, + TBool aEncrypt, // ETrue + TInt aEffectiveKeyLen, // If 0 given, key len is used. + TCrSymmMode aMode, // ECrCBC + TPaddingRule /*aPadRule */) // ECrPKCS1 + { + // Number of items pushed to CleanupStack + TUint pushedToCStack = 0; + + // Create new algorithm info object. + CCrAlgInfo* algInfo = CCrAlgInfo::NewLC( + ECrRC2, + aKey, + aIV, + aEncrypt, + ETrue, + aMode); + ++pushedToCStack; + + // If given effective key length is zero, use key length. + if (aEffectiveKeyLen == 0) + { + aEffectiveKeyLen = algInfo->iKey->Length() * 8; + } + + // Create cipher object. + switch (aMode) + { + case ECrCBC: + { + if (aEncrypt) + { + CRC2Encryptor* rc2 = CRC2Encryptor::NewL(*algInfo->iKey, aEffectiveKeyLen); + CleanupStack::PushL(rc2); + + CModeCBCEncryptor* cbcEncryptor = CModeCBCEncryptor::NewL(rc2, aIV); + CleanupStack::Pop(rc2); // CModeCBCEncryptor takes care of rc2 now + CleanupStack::PushL(cbcEncryptor); + + CPaddingPKCS7* padding = CPaddingPKCS7::NewL(rc2->BlockSize()); + CleanupStack::PushL(padding); + + CBufferedEncryptor* encryptor = CBufferedEncryptor::NewL(cbcEncryptor, padding); + CleanupStack::Pop(2); // CBufferedEncryptor takes care of freeing + + algInfo->iAlgorithmObject = encryptor; + } + else + { + CRC2Decryptor* rc2 = CRC2Decryptor::NewL(*algInfo->iKey, aEffectiveKeyLen); + CleanupStack::PushL(rc2); + + CModeCBCDecryptor* cbcDecryptor = CModeCBCDecryptor::NewL(rc2, aIV); + CleanupStack::Pop(rc2); // CModeCBCEncryptor takes care of rc2 now + CleanupStack::PushL(cbcDecryptor); + + CPaddingPKCS7* padding = CPaddingPKCS7::NewL(rc2->BlockSize()); + CleanupStack::PushL(padding); + + CBufferedDecryptor* decryptor = CBufferedDecryptor::NewL(cbcDecryptor, padding); + CleanupStack::Pop(2); // CBufferedDecryptor takes care of freeing + + algInfo->iAlgorithmObject = decryptor; + } + algInfo->iMode = ECrCBC; + break; + } + case ECrCFB: + { + return KCrCrypto | KCrUnknownMode; + } + case ECrECB: + { + return KCrCrypto | KCrUnknownMode; + } + case ECrOFB: + { + return KCrCrypto | KCrUnknownMode; + } + default: + { + return KCrCrypto | KCrUnknownMode; + } + } + + CleanupStack::PushL(algInfo->iAlgorithmObject); + ++pushedToCStack; + + + // Append new algorithm info object into member set. + iAlgorithmInfos->AppendL(algInfo); + + CleanupStack::Pop(pushedToCStack); + + return KCrOK; + } + +// ----------------------------------------------------------------------------- +// CCrCrypto::InitDigestL +// Initialize message digest with MD2 algorithm. +// ----------------------------------------------------------------------------- +TCrStatus CCrCrypto::InitDigestL(TCrAlgorithm aAlgorithm) + { + // Number of items pushed to CleanupStack + TUint pushedToCStack = 0; + + // Create new algorithm info object. + CCrAlgInfo *algInfo = CCrAlgInfo::NewLC(aAlgorithm); + pushedToCStack++; + + switch(aAlgorithm) + { + case ECrSHA1: + { + // Create digest object. + algInfo->iAlgorithmObject = CSHA1::NewL(); + break; + } + case ECrMD5: + { + // Create digest object. + algInfo->iAlgorithmObject = CMD5::NewL(); + break; + } + case ECrMD2: + { + // Create digest object. + algInfo->iAlgorithmObject = CMD2::NewL(); + break; + } + case ECrSHA: + { + // Create digest object. + algInfo->iAlgorithmObject = CSHA::NewL(); + break; + } + default: + { + return KCrCrypto | KCrNotSupportedAlg; + } + } + + CleanupStack::PushL(algInfo->iAlgorithmObject); + pushedToCStack++; + + // Append new algorithm info object into member set. + iAlgorithmInfos->AppendL(algInfo); + + CleanupStack::Pop(pushedToCStack); + + return KCrOK; + } + +// ----------------------------------------------------------------------------- +// CCrCrypto::InitDigestHMACL +// Initialize message digest with HMAC algorithm. +// ----------------------------------------------------------------------------- +TCrStatus CCrCrypto::InitDigestHMACL( + const TDesC8& aKey, + TCrAlgorithm aDigestAlg) + { + // Number of items pushed to CleanupStack + TUint pushedToCStack = 0; + + TCrAlgorithm hmacDigest; + + switch (aDigestAlg) + { + case ECrSHA1: + { + hmacDigest = ECrHMAC_SHA1; + + break; + } + case ECrMD5: + { + hmacDigest = ECrHMAC_MD5; + + break; + } + default: + { + return KCrCrypto | KCrNotSupportedAlg; + } + } + + // Create new algorithm info object. + CCrAlgInfo *algInfo = CCrAlgInfo::NewLC(hmacDigest); + pushedToCStack++; + + CMessageDigest* digest = 0; + + switch(aDigestAlg) + { + case ECrSHA1: + { + // Create digest object. + digest = CSHA1::NewL(); + break; + } + case ECrMD5: + { + // Create digest object. + digest = CMD5::NewL(); + break; + } + case ECrMD2: + { + // Create digest object. + digest = CMD2::NewL(); + break; + } + case ECrSHA: + { + // Create digest object. + digest = CSHA::NewL(); + break; + } + default: + { + return KCrCrypto | KCrNotSupportedAlg; + } + } + CleanupStack::PushL(digest); + ++pushedToCStack; + // Create digest object. + algInfo->iAlgorithmObject = CHMAC::NewL(aKey, digest); + CleanupStack::PushL(algInfo->iAlgorithmObject); + ++pushedToCStack; + + // Append new algorithm info object into member set. + iAlgorithmInfos->AppendL(algInfo); + + CleanupStack::Pop(pushedToCStack); + + return KCrOK; + } + + +// ----------------------------------------------------------------------------- +// CCrCrypto::ProcessL +// Process given source data with initialized crypto operations. +// If symmetric crypto is initialized sets to aTrg encrypted +// or decrypted data without last portion. If aProcessFinalBlock +// is ETrue, appends also last portion. If only digest algorithm +// is initialized, aTrg is not used. +// ----------------------------------------------------------------------------- +TCrStatus CCrCrypto::ProcessL(const TDesC8& aSrc, TDes8& aTrg) + { + TInt i, size; + TUint pushedToCStack = 0; + CCrAlgInfo* algInfo = 0; + + size = iAlgorithmInfos->Count(); + + for (i = 0; i < size; i++) + { + algInfo = (*iAlgorithmInfos)[i]; + + // Message digest algorithm + if (algInfo->iType < ECrLAST_DIGEST) + { + // Casting to right type + CMessageDigest* digest = STATIC_CAST( + CMessageDigest*, algInfo->iAlgorithmObject); + + // Store the digest to buf + //algInfo->iDigest = HBufC8::NewL(digest->HashSize()); + TPtr8 ptr = algInfo->iDigest->Des(); + ptr.Copy(digest->Hash(aSrc)); + } + // Symmetric crypto algorithm + else if (algInfo->iType > ECrLAST_DIGEST && algInfo->iType < ECrLAST_SYMM_CRYPTO) + { + // Casting to right type + CSymmetricCipher* cipherSymm = + STATIC_CAST(CSymmetricCipher*, algInfo->iAlgorithmObject); + + + // This is not incremental + cipherSymm->ProcessFinalL(aSrc, aTrg); + + CleanupStack::Pop(pushedToCStack); + } + else + { + return KCrCrypto | KCrNotSupportedAlg; + } + } + return KCrOK; + } + +// ----------------------------------------------------------------------------- +// CCrCrypto::FinalCryptL +// Finalize symmetric algorithms objects. +// ----------------------------------------------------------------------------- +TCrStatus CCrCrypto::FinalCryptL(TDes8& aTrg) + { + TInt i, size; + CCrAlgInfo *algInfo = 0; + TCrStatus status = KCrOK; + size = iAlgorithmInfos->Count(); + + for (i = 0; i < size; i++) + { + algInfo = (*iAlgorithmInfos)[i]; + + if (algInfo->iType > ECrLAST_DIGEST && + algInfo->iType < ECrLAST_SYMM_CRYPTO) + { + TUint8 pushedToCStack = 0; + + CSymmetricCipher* cipherSymm = + STATIC_CAST(CSymmetricCipher*, algInfo->iAlgorithmObject); + + HBufC8 *lastBlock = + HBufC8::NewLC(algInfo->iLastPortion->Size()); + pushedToCStack++; + + TPtr8 ptrLastBlock = lastBlock->Des(); + + if (cipherSymm->MaxFinalOutputLength(ptrLastBlock.Size()) > 0) + { + cipherSymm->ProcessFinalL(ptrLastBlock, aTrg); + } + + CleanupStack::Pop(pushedToCStack); + + delete lastBlock; + lastBlock = 0; + + delete cipherSymm; + cipherSymm = 0; + algInfo->iAlgorithmObject = 0; + + } + } + return status; + } + + +TCrStatus CCrCrypto::FinalDigest(TDes8& aTrg) + { + TInt i, size; + CCrAlgInfo *algInfo = 0; + TCrStatus status = KCrOK; + + size = iAlgorithmInfos->Count(); + + for (i = 0; i < size; i++) + { + algInfo = (*iAlgorithmInfos)[i]; + + if ((algInfo->iType < ECrLAST_DIGEST) && (status == KCrOK)) + { + + aTrg.Copy(*algInfo->iDigest); + + CMessageDigest* digest = STATIC_CAST( + CMessageDigest*, algInfo->iAlgorithmObject); + + delete digest; + digest = 0; + algInfo->iAlgorithmObject = 0; + } + } + return status; + } + + + +// ----------------------------------------------------------------------------- +// CCrCrypto::RemoveLastBlock +// Checks that aOriginSrc length is multiple of the block size, If not, +// removes data from the end so that it is multiple of the block size. +// Parameters: aSrc Original data to remove the last block +// aBlockSize Size of the block +// alginfo Pointer to object where last portion is +// stored. +// Return Values: true if size of aOriginSrc is bigger than blockSize +// otherwise false. If false the whole aOriginSrc is stored +// to alginfo. +// ----------------------------------------------------------------------------- +TInt CCrCrypto::RemoveLastBlock( + TDesC8& aSrc, + const TInt aBlockSize, + CCrAlgInfo* algInfo) + { + TUint number_of_blocks = aSrc.Size() / aBlockSize; + TUint size_of_last_block = aSrc.Size() % aBlockSize; + + TUint size_of_checked; + + // If aOriginSrc's size is smaller or equal than aBlocksize + if (number_of_blocks == 0 || (number_of_blocks == 1 && size_of_last_block == 0)) + { + *algInfo->iLastPortion = aSrc; + + return false; + } + else if (size_of_last_block == 0 && number_of_blocks > 0) + { + // 3des fix begins: + // Don't do anything if size of data already is multiple of + // blocksize. Otherwise padding will be ruined. Return true anyway. + if(!algInfo->iEncrypt) + { + size_of_checked = aSrc.Size() - aBlockSize; + + *algInfo->iLastPortion = aSrc.Right(aBlockSize); + + aSrc = aSrc.Left(size_of_checked); + } + + // 3des fix ends. + + return true; + } + else + { + size_of_checked = aSrc.Size() - size_of_last_block; + + *algInfo->iLastPortion = aSrc.Right(size_of_last_block); + + aSrc = aSrc.Left(size_of_checked); + + return true; + } + } + +// ----------------------------------------------------------------------------- +// CCrCrypto::DeriveKeyPKCS12L +// Derives key(s) or IV vector from password, salt and iterarion count. +// Return Values: KCrOK +// KCrNotSupportedAlg +// KCrUndefinedLibrary +// KCrUnknownLibrary +// KCrUnknownMode +// KCrErrorGeneral +// ----------------------------------------------------------------------------- +TCrStatus CCrCrypto::DeriveKeyPKCS12L( + const TDesC8& aPassword, + const TDesC8& aSalt, + const TInt aIterationCount, + TCrAlgorithm aHashFunc, + const TUint8 aID, + const TInt aNumberOfBytes, + TDes8& aTrg) // Output data, possible keys and IV + { + TInt remainder = 0; + TInt rounds = 0; + TInt pushedToCStack = 0; + TInt inputSize = MesDigestInputSize(aHashFunc); + TInt outputSize = MesDigestOutputSize(aHashFunc); + + // Step 1: Construct D by concatenating copies of ID. + // Construct a string D + HBufC8* D_buf = HBufC8::NewLC(inputSize); + ++pushedToCStack; + + TPtr8 D_ptr = D_buf->Des(); + TInt i(0); + for (i = 0; i < inputSize; ++i) + { + D_ptr.Append(aID); + } + + // Step 2, 3, 4: + TInt s_length = 0; + TInt p_length = 0; + + s_length = inputSize * ((aSalt.Size() + inputSize - 1) / inputSize); + p_length = inputSize * ((aPassword.Size() + inputSize - 1) / inputSize); + + HBufC8* I_buf = HBufC8::NewLC(s_length + p_length); + ++pushedToCStack; + TPtr8 I_ptr = I_buf->Des(); + + if (aSalt.Size() != 0) + { + rounds = s_length / aSalt.Size(); + for (i = 0; i < rounds; ++i) + { + I_ptr.Append(aSalt); + } + remainder = s_length % aSalt.Size(); + if (remainder != 0) + { + I_ptr.Append(aSalt.Ptr(), remainder); + } + } + + + if (aPassword.Size() != 0) + { + rounds = p_length / aPassword.Size(); + for (i = 0; i < rounds; ++i) + { + I_ptr.Append(aPassword); + } + remainder = p_length % aPassword.Size(); + if (remainder != 0) + { + I_ptr.Append(aPassword.Ptr(), remainder); + } + } + + // Step 5: Set c. + TInt c = 0; + c = (aNumberOfBytes + outputSize - 1) / outputSize; + + // Step 6: Loop + TCrStatus status = KCrCrypto | KCrErrorGeneral; + + CCrCrypto* hash = 0; + + HBufC8* B_buf = HBufC8::NewLC(inputSize); + ++pushedToCStack; + TPtr8 B_ptr = B_buf->Des(); + + HBufC8* A_buf = HBufC8::NewLC(D_ptr.Size() + I_ptr.Size()); + ++pushedToCStack; + TPtr8 A_ptr = A_buf->Des(); + + TInt j = 0; + RInteger B_int; + RInteger Ij_int; + TInt N = aNumberOfBytes; + + rounds = inputSize / outputSize; + remainder = inputSize % outputSize; + + for (i = 0; i < c; ++i) + { + A_ptr.Zero(); + A_ptr.Append(D_ptr); + A_ptr.Append(I_ptr); + + hash = CCrCrypto::NewLC(); + + for (TInt ii = 0; ii < aIterationCount; ++ii) + { + status = hash->InitDigestL(aHashFunc); + status = hash->ProcessL(A_ptr, A_ptr); + A_ptr.Zero(); + status = hash->FinalDigest(A_ptr); + hash->Reset(); + } + + CleanupStack::PopAndDestroy(); // hash + + if (outputSize < N) + { + aTrg.Append(A_ptr); + } + else + { + aTrg.Append(A_ptr.Ptr(), N); + } + + if (outputSize >= N) + { + status = KCrOK; + break; + } + + N -= outputSize; + + rounds = inputSize / A_ptr.Size(); + remainder = inputSize % A_ptr.Size(); + for (j = 0; j < rounds; ++j) + { + B_ptr.Append(A_ptr); + } + if (remainder != 0) + { + B_ptr.Append(A_ptr.Ptr(), remainder); + } + + B_int = RInteger::NewL(B_ptr); + CleanupStack::PushL(B_int); + + B_int += 1; + + for (j = 0; j < I_ptr.Size(); j += inputSize) + { + Ij_int = RInteger::NewL(I_ptr.Mid(j, inputSize)); + CleanupStack::PushL(Ij_int); + Ij_int += B_int; + + I_ptr.Replace(j, inputSize, Ij_int.BufferLC()->Right(inputSize)); + + CleanupStack::PopAndDestroy(2); // Ij_int, BufferLC + } + + CleanupStack::PopAndDestroy(); // B_int + } + + CleanupStack::PopAndDestroy(pushedToCStack); + + return status; +} + +// ----------------------------------------------------------------------------- +// CCrCrypto::MesDigestInputSize +// Returns input size of the message digest algorithm. +// Return Values: Input size of the message digest algorithm in bytes. +// If unknown algorithm returns -1. +// ----------------------------------------------------------------------------- +TInt CCrCrypto::MesDigestInputSize(TCrAlgorithm aDigestAlg) + { + switch(aDigestAlg) + { + case ECrSHA1: + case ECrMD5: + case ECrMD2: + { + return KDigestInputSize; + } + default: + { + return -1; + } + } + } + +// ----------------------------------------------------------------------------- +// CCrCrypto::MesDigestOutputSize +// Returns output size of the message digest algorithm. +// Parameters: aDigestAlg message digest algortihm +// Return Values: Output size of the message digest algorithm in bytes. +// If unknown algorithm returns -1. +// ----------------------------------------------------------------------------- +TInt CCrCrypto::MesDigestOutputSize(TCrAlgorithm aDigestAlg) + { + switch(aDigestAlg) + { + case ECrSHA1: + { + return KCrLongDigestLength; + } + case ECrMD5: + case ECrMD2: + { + return KCrMediumDigestLength; + } + default: + { + return -1; + } + } + } + +// End Of Line + +