--- /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 <bufferedtransformation.h>
+#include <cbcmode.h>
+#include <des.h>
+#include <3des.h>
+#include <rijndael.h>
+#include <padding.h>
+#include <hash.h>
+
+#include <asymmetrickeys.h>
+#include <asymmetric.h>
+#include <bigint.h>
+#include <random.h>
+#include <cryptostrength.h>
+#include <x509keys.h>
+#include <x509cert.h>
+
+#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<HBufC8*>(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;
+ }
+