vpnengine/utlcrypto/src/utlcryptonew.cpp
changeset 0 33413c0669b9
--- /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;
+    }
+