diff -r 000000000000 -r 33413c0669b9 vpnengine/utlcrypto/src/utlcryptonew.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vpnengine/utlcrypto/src/utlcryptonew.cpp Thu Dec 17 09:14:51 2009 +0200 @@ -0,0 +1,620 @@ +/* +* Copyright (c) 2003-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: New Symbian crypto API +* +*/ + + + +#define DummyForLeaveScanL(a) + +#include "msymmetriccipher.h" +#include +#include +#include +#include <3des.h> +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "utlcrypto.h" + + + +EXPORT_C CUtlSymmetricCipher::~CUtlSymmetricCipher() +/** +* Destructor. +*/ + { + delete iSymmetricCipher; + } + +EXPORT_C void CUtlSymmetricCipher::Process(const TDesC8& aInput, TDes8& aOutput) +/** +* Runs the underlying transformation on aInput and appends the result to +* aOutput. +* @param aInput The input data to be processed. +* @param aOutput The resulting processed data appended to aOutput. aOutput must +* have MaxOutputLength() empty bytes remaining in its length. +*/ + { + iSymmetricCipher->Process(aInput, aOutput); + } + +EXPORT_C void CUtlSymmetricCipher::ProcessFinalL(const TDesC8& aInput, TDes8& aOutput) +/** +* Pads aInput to be block aligned using the underlying padding system, if any, +* and then runs the underlying transformation on aInput, and appends the result +* to aOutput. +* @param aInput The input data to be processed. +* @param aOutput The resulting, possibly padded, processed data appended to +* aOutput. aOutput must have MaxFinalOutputLength() empty bytes remaining in +* its length. +*/ + { + //Do dot call ProcessFinalL, but Process, because CPaddingNone is used. + //ProcessFinalL causes panic in this case. + DummyForLeaveScanL(1); + iSymmetricCipher->Process(aInput, aOutput); + } + +EXPORT_C TInt CUtlSymmetricCipher::MaxOutputLength(TInt aInputTextLength) const +/** +* Gets a tight upper bound on the number of bytes that would be returned by a +* call to Process() with aInputLength bytes of data. +* @param aInputLength The length of data to be supplied to Process() in bytes. +* @return The length of data which would result from a call to Process() with +* an aInputLength number of bytes. +*/ + { + return iSymmetricCipher->MaxOutputLength(aInputTextLength); + } + +EXPORT_C TInt CUtlSymmetricCipher::MaxFinalOutputLength(TInt aInputTextLength) const +/** +* Gets as tight an upper bound as possible on the number of bytes that would +* be returned by a call to ProcessFinalL() with aInputLength bytes of data. +* @param aInputLength The length of data to be supplied to Process() in bytes. +* @return An upper bound on the length of data which would result from a call to +* ProcessFinalL() with an aInputLength number of bytes. +*/ + { + return iSymmetricCipher->MaxFinalOutputLength(aInputTextLength); + } + +EXPORT_C void CUtlSymmetricCipher::Reset() +/** +* Resets the cipher back to its original state. Clears all its buffers. +*/ + { + iSymmetricCipher->Reset(); + } + +EXPORT_C TInt CUtlSymmetricCipher::BlockSize() const +/** +* Gets the block size in bytes (1 for stream ciphers). +* @return Block size of underlying cipher in bytes. +*/ + { + return iSymmetricCipher->BlockSize(); + } + +EXPORT_C TInt CUtlSymmetricCipher::KeySize() const +/** +* Gets the key size in bits. +* @return Key size in bits. +*/ + { + return iSymmetricCipher->KeySize(); + } + +CUtlSymmetricCipher::CUtlSymmetricCipher() + { + ; + } + +//-------------------------------------------------------- + +EXPORT_C CUtlMessageDigest::~CUtlMessageDigest() +/** +* Destructor. +*/ + { + delete iMessageDigest; + } + +EXPORT_C CMessageDigest* CUtlMessageDigest::ReplicateL(void) +/** +* Creates a brand new reset CMessageDigest object containing no state +* information from the current object. To make a copy of a message +* digest with its internal state intact, see CopyL(). +*/ + { + return iMessageDigest->ReplicateL(); + } + +EXPORT_C void CUtlMessageDigest::Update(const TDesC8& aMessage) +/** +* Adds data to the internal representation of messages to be hashed +* @param aMessage Data to be included in the hash. +*/ + { + iMessageDigest->Update(aMessage); + } + +EXPORT_C TPtrC8 CUtlMessageDigest::Final(const TDesC8& aMessage) +/** +* Adds aMessage to the internal representation of data to be hashed, +* returns a TPtrC8 of the finalised hash of all the previously +* appended messages, and calls Reset(). +* +* @param aMessage Data to be included in the hash +* +* @return TPtrC8 A descriptor pointer to the buffer containing the +* resulting hash. +*/ + { + return iMessageDigest->Final(aMessage); + } + +EXPORT_C TPtrC8 CUtlMessageDigest::Final(void) +/** +* Returns a TPtrC8 of the finalised hash of all the previously +* appended messages and then calls Reset(). +* +* @return TPtrC8 A descriptor pointer to the buffer containing the +* resulting hash. +*/ + { + return iMessageDigest->Final(); + } + +EXPORT_C CMessageDigest* CUtlMessageDigest::CopyL(void) +/** +* Creates a new CMessageDigest object with the exact same state as +* the current object. This function copies all internal state of the +* message digest. To create a new CMessageDigest object without the +* state of the current object, see ReplicateL(). +*/ + { + return iMessageDigest->CopyL(); + } + +EXPORT_C TInt CUtlMessageDigest::BlockSize(void) const +/** +* Returns the internal block size of the message digest. +* @return TInt internal block size of message digest in bytes. +*/ + { + return iMessageDigest->BlockSize(); + } + +EXPORT_C TInt CUtlMessageDigest::HashSize(void) const +/** +* Returns the size of the message digest output. +* @return TInt output size of the message digest in bytes. +*/ + { + return iMessageDigest->HashSize(); + } + +EXPORT_C void CUtlMessageDigest::Reset(void) +/** +* Resets the internal state of the message digest. A reset hash +* object loses all internal state representing the hashed data. A +* reset message digest is suitable to begin a new, distinct hash of +* different data. Any previously returned TPtrC8 from a call to +* Final() remains valid until any subsequent call to Update() or +* Final(). +*/ + { + iMessageDigest->Reset(); + } + + +CUtlMessageDigest::CUtlMessageDigest() + { + ; + } + +//-------------------------------------------------------- + +EXPORT_C CUtlDiffieHellman::~CUtlDiffieHellman() +/** +* Destructor. +*/ + { + delete iDhKeyPair; + delete iDhKeyAgreement; + //delete iKBuf; + } + +EXPORT_C const HBufC8* CUtlDiffieHellman::GenerateXL(void) +/** +* Generates a new Diffie-Hellman key exchange. +* @return HBufC8* X. +*/ + { + const CDHPublicKey* dhPublicKey = &iDhKeyPair->PublicKey(); + const TInteger* x = &dhPublicKey->X(); + HBufC8* resultBuf = NULL; + HBufC8* xBuf = x->BufferLC(); + + TInt padLength = iModulusLength - xBuf->Length(); + if ( padLength > 0 ) + { + // Fill prepending zero bits to DH public value. + resultBuf = HBufC8::NewL(iModulusLength); + TChar zero(0); + resultBuf->Des().AppendFill(zero, padLength); + resultBuf->Des().Append(*xBuf); + CleanupStack::PopAndDestroy(xBuf); + } + else + { + CleanupStack::Pop(xBuf); + resultBuf = xBuf; + } + + return resultBuf; + } + +EXPORT_C const HBufC8* CUtlDiffieHellman::CompleteKL(const TDesC8& aY) +/** +* Completes a Diffie-Hellman key exchange. +* @param aY Y. +* @return HBufC8* K. +*/ + { + const CDHPrivateKey* privateKey = &iDhKeyPair->PrivateKey(); + + RInteger n = RInteger::NewL(privateKey->N()); + CleanupClosePushL(n); + RInteger g = RInteger::NewL(privateKey->G()); + CleanupClosePushL(g); + RInteger Y = RInteger::NewL(aY); + CleanupClosePushL(Y); + + CDHPublicKey* dhPublicKeyY = CDHPublicKey::NewL(n, g, Y); + CleanupStack::Pop(3); // Y, g, n + CleanupStack::PushL(dhPublicKeyY); + + const HBufC8* kBuf = iDhKeyAgreement->AgreeL(*dhPublicKeyY); + + CleanupStack::PopAndDestroy(); // dhPublicKeyY + + //delete iKBuf; + //iKBuf = const_cast(kBuf); + //return iKBuf; + return kBuf; + } + +CUtlDiffieHellman::CUtlDiffieHellman() + { + ; + } + +//-------------------------------------------------------- + +EXPORT_C CUtlSymmetricCipher* +TUtlCrypto::MakeSymmetricEncryptorL(TUtlSymmetricCipherId aCipherId, + const TDesC8& aKey, + const TDesC8& aIv) +/** +* Makes symmetric block encryptor without padding. +* @param aCipherId Cipher id. +* @param aKey Key. +* @param aIv Initialization vector. +* @return CUtlSymmetricCipher* Pointer to symmetric cipher. +*/ + { + CSymmetricCipher* cipher = 0; + CBlockTransformation* block = 0; + + switch (aCipherId) + { + case EUtlSymmetricCipherDesCbc: + block = CDESEncryptor::NewLC(aKey); + block = CModeCBCEncryptor::NewL(block, aIv); + CleanupStack::Pop(); //1st block owned by 2nd + CleanupStack::PushL(block);//2nd block + break; + case EUtlSymmetricCipher3DesCbc: + block = C3DESEncryptor::NewLC(aKey); + block = CModeCBCEncryptor::NewL(block, aIv); + CleanupStack::Pop(); //1st block owned by 2nd + CleanupStack::PushL(block);//2nd block + break; + case EUtlSymmetricCipherAesCbc: + block = CAESEncryptor::NewLC(aKey); + block = CModeCBCEncryptor::NewL(block, aIv); + CleanupStack::Pop(); //1st block owned by 2nd + CleanupStack::PushL(block);//2nd block + break; + default: + User::Leave(KErrGeneral); + break; + } + + if (cipher == 0) // it's a block cipher -> make a buffered version + { + CPadding* padding = CPaddingNone::NewLC(); + cipher = CBufferedEncryptor::NewL(block, padding); + CleanupStack::Pop(); //padding - owned by cipher + CleanupStack::Pop(); //block - owned by cipher + } + else + { + //-- it's a stream cipher -> everything is already made + } + + CleanupStack::PushL(cipher); + CUtlSymmetricCipher* utlCipher = new (ELeave) CUtlSymmetricCipher(); + utlCipher->iSymmetricCipher = cipher; + CleanupStack::Pop(); //cipher - owned by utlCipher + + return utlCipher; + } + + +EXPORT_C CUtlSymmetricCipher* +TUtlCrypto::MakeSymmetricDecryptorL(TUtlSymmetricCipherId aCipherId, + const TDesC8& aKey, + const TDesC8& aIv) +/** +* Makes symmetric block decryptor without padding. +* @param aCipherId Cipher id. +* @param aKey Key. +* @param aIv Initialization vector. +* @return CUtlSymmetricCipher* Pointer to symmetric cipher. +*/ + { + if (aKey.Length() < 1) + { + User::Leave(KErrArgument); + } + CSymmetricCipher* cipher = 0; + CBlockTransformation* block = 0; + + switch (aCipherId) + { + case EUtlSymmetricCipherDesCbc: + block = CDESDecryptor::NewLC(aKey); + block = CModeCBCDecryptor::NewL(block, aIv); + CleanupStack::Pop(); //1st block owned by 2nd + CleanupStack::PushL(block);//2nd block + break; + case EUtlSymmetricCipher3DesCbc: + block = C3DESDecryptor::NewLC(aKey); + block = CModeCBCDecryptor::NewL(block, aIv); + CleanupStack::Pop(); //1st block owned by 2nd + CleanupStack::PushL(block);//2nd block + break; + case EUtlSymmetricCipherAesCbc: + block = CAESDecryptor::NewLC(aKey); + block = CModeCBCDecryptor::NewL(block, aIv); + CleanupStack::Pop(); //1st block owned by 2nd + CleanupStack::PushL(block);//2nd block + break; + default: + User::Leave(KErrGeneral); + break; + } + + if (cipher == 0) // it's a block cipher -> make a buffered version + { + CPadding* padding = CPaddingNone::NewLC(); + cipher = CBufferedDecryptor::NewL(block, padding); + CleanupStack::Pop(); //padding - owned by cipher + CleanupStack::Pop(); //block - owned by cipher + } + else + { + //-- it's a stream cipher -> everything is already made + } + + CleanupStack::PushL(cipher); + CUtlSymmetricCipher* utlCipher = new (ELeave) CUtlSymmetricCipher(); + utlCipher->iSymmetricCipher = cipher; + CleanupStack::Pop(); //cipher - owned by utlCipher + + return utlCipher; + } + +EXPORT_C CUtlMessageDigest* +TUtlCrypto::MakeMessageDigesterL(TUtlMessageDigestId aDigestId, + const TDesC8& aHmacKey) +/** +* Makes message digester. +* @param aDigestId Digest id. +* @param aHmacKey HMAC key, if HMAC. +* @return CUtlMessageDigest* Pointer to message digester. +*/ + { + CMessageDigest* digest = 0; + + switch (aDigestId) + { + case EUtlMessageDigestMd5: + digest = CMD5::NewL(); + break; + case EUtlMessageDigestSha1: + digest = CSHA1::NewL(); + break; + default: + User::Leave(KErrGeneral); + break; + } + CleanupStack::PushL(digest); + + if (aHmacKey.Length() > 0) + { + digest = CHMAC::NewL(aHmacKey, digest); + CleanupStack::Pop(); //original digest - owned by CHMAC + CleanupStack::PushL(digest); + } + + CUtlMessageDigest* utlMessageDigest = new (ELeave) CUtlMessageDigest(); + utlMessageDigest->iMessageDigest = digest; + CleanupStack::Pop(); //digest - owned by utlMessageDigest + + return utlMessageDigest; + } + +EXPORT_C CUtlDiffieHellman* +TUtlCrypto::MakeDiffieHellmanL(const TDesC8& aN, const TDesC8& aG) +/** +* Makes Diffie-Hellman key exchange object. +* @param aN N. +* @param aG G. +* @return CUtlDiffieHellman* Pointer to Diffie-Hellman key exchange object. +*/ + { + RInteger n = RInteger::NewL(aN); + CleanupClosePushL(n); + RInteger g = RInteger::NewL(aG); + CleanupClosePushL(g); + + CDHKeyPair* dhKeyPair = CDHKeyPair::NewL(n, g); + CleanupStack::PushL(dhKeyPair); + + CDH* dhKeyAgreement = CDH::NewLC(dhKeyPair->PrivateKey()); + + CUtlDiffieHellman* utlDiffieHellman = new (ELeave) CUtlDiffieHellman(); + utlDiffieHellman->iDhKeyAgreement = dhKeyAgreement; + utlDiffieHellman->iDhKeyPair = dhKeyPair; + utlDiffieHellman->iModulusLength = aN.Length(); + CleanupStack::Pop(2); //dhKeyAgreement, dhKeyPair + CleanupStack::Pop(2); // g, n + + return utlDiffieHellman; + } + +EXPORT_C void TUtlCrypto::RsaPublicKeyEncryptL(const TDesC8& aPublicKeyData, + const TDesC8& aPlaintext, + HBufC8*& aCiphertext) +/** +* RSA encrypts the plain text with the public key. +* @param aPublicKeyData Public key. +* @param aPlaintext Plain text. +* @param aCiphertext Cipher text. +*/ + { + CX509RSAPublicKey* publicKey = CX509RSAPublicKey::NewLC(aPublicKeyData); + CRSAPKCS1v15Encryptor* rsaEncryptor = CRSAPKCS1v15Encryptor::NewLC(*publicKey); + + TInt publicKeySize = 2048; //publicKey->Size() + TInt encrLth = publicKeySize / 8; + HBufC8* ciphertext = HBufC8::NewLC(encrLth); + TPtr8 ciphertextDesc(ciphertext->Des()); + + rsaEncryptor->EncryptL(aPlaintext, ciphertextDesc); + + CleanupStack::Pop(); //ciphertext + CleanupStack::PopAndDestroy(2); //rsaEncryptor, publicKey + aCiphertext = ciphertext; + } + +EXPORT_C void TUtlCrypto::RsaPublicKeyDecryptL(const TDesC8& aPublicKeyData, + const TDesC8& aCiphertext, + HBufC8*& aPlaintext) +/** +* RSA decrypts the cipher text with the public key. +* @param aPublicKeyData Public key. +* @param aCiphertext Cipher text. +* @param aPlaintext Plain text. +*/ + { + CX509RSAPublicKey* publicKey = CX509RSAPublicKey::NewLC(aPublicKeyData); + CRSAPKCS1v15Verifier* verifier = CRSAPKCS1v15Verifier::NewLC(*publicKey); + + RInteger S = RInteger::NewL(aCiphertext); + CleanupClosePushL(S); + CRSASignature* signature = CRSASignature::NewL(S); + CleanupStack::Pop(); //S + CleanupStack::PushL(signature); + + aPlaintext = verifier->InverseSignLC(*signature); + + CleanupStack::Pop(); //aPlaintext + CleanupStack::PopAndDestroy(3); //signature, verifier, publicKey + } + +EXPORT_C TBool TUtlCrypto::DsaVerifySignatureL(const TDesC8& aPublicKeyData, + const TDesC8& aDsaParams, + const TDesC8& aDsaSignatureR, + const TDesC8& aDsaSignatureS, + const TDesC8& aHashData) +/** +* Verifies DSA signature. +* @param aPublicKeyData Public key. +* @param aDsaParams DSA parameters. +* @param aDsaSignatureR R. +* @param aDsaSignatureS S. +* @param aHashData Hash data. +* @return TBool Verify signature status: ETrue, if OK. +*/ + { + TBool ret; + TX509KeyFactory keyFactory; + CDSAParameters* params = keyFactory.DSAParametersL(aDsaParams); + CleanupStack::PushL(params); + CDSAPublicKey* key = keyFactory.DSAPublicKeyL(*params, aPublicKeyData); + CleanupStack::PushL(key); + + RInteger R = RInteger::NewL(aDsaSignatureR); + CleanupClosePushL(R); + RInteger S = RInteger::NewL(aDsaSignatureS); + CleanupClosePushL(S); + CDSASignature* signature = CDSASignature::NewL(R, S); + CleanupStack::Pop(2); //S, R + CleanupStack::PushL(signature); + + CDSAVerifier* verifier = CDSAVerifier::NewLC(*key); + ret = verifier->VerifyL(aHashData, *signature); + + CleanupStack::PopAndDestroy(4); //verifier, signature, key, params + return ret; + } + +EXPORT_C TBool TUtlCrypto::IsWeakCryptoLibrary(void) +/** +* Tests the strength of the crypto libary. +* @return TBool ETrue, if weak crypto library. +*/ + { + TCrypto::TStrength strength = TCrypto::Strength(); + if (strength == TCrypto::EWeak) + return ETrue; + else + return EFalse; + } + +EXPORT_C TUtlCrypto::TUtlCryptoVersion TUtlCrypto::CryptoVersion(void) +/** +* Returns the version of the crypto libary. +* @return TUtlCryptoVersion, crypto version +*/ + { + return EUtlCryptoVersionSymbian1; + } +