rtp/srtpstack/src/srtpaesctrcrypto.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 16 Apr 2010 15:18:54 +0300
changeset 15 8248b03a2669
parent 0 307788aac0a8
permissions -rw-r--r--
Revision: 201011 Kit: 201015

/*
* Copyright (c) 2005 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:    Class for AES (in Counter Mode) encryption operations
*
*/




#include "srtpaesctrcrypto.h"
#include <e32uid.h>
#include <symmetric.h>
#include "srtpdef.h"
#include "srtputils.h"
// ---------------------------------------------------------------------------
// CSrtpAESCTRCrypto::NewL()
// 
// ---------------------------------------------------------------------------
//
EXPORT_C CSrtpAESCTRCrypto* CSrtpAESCTRCrypto::NewL()
	{
	CSrtpAESCTRCrypto* self=new (ELeave) CSrtpAESCTRCrypto( );
	return self;
	}

// ---------------------------------------------------------------------------
// CSrtpAESCTRCrypto::~CSrtpAESCTRCrypto()
// 
// ---------------------------------------------------------------------------
//
CSrtpAESCTRCrypto::~CSrtpAESCTRCrypto()
	{
	delete iEncryptor;
	delete iKey;
	}


// ---------------------------------------------------------------------------
// CSrtpAESCTRCrypto::CSrtpAESCTRCrypto
// 
// ---------------------------------------------------------------------------
//
CSrtpAESCTRCrypto::CSrtpAESCTRCrypto( ) 
	{
	}


// ---------------------------------------------------------------------------
// CSrtpAESCTRCrypto::KeystreamL
// 
// ---------------------------------------------------------------------------
//
EXPORT_C HBufC8* CSrtpAESCTRCrypto::KeystreamL(TUint aBitLength, 
                                                const TDesC8& aKey, 
                                                const TDesC8& aIV )
	{
    TBuf8<16> iv;           //temp for IV    
    TBuf8<16> data;         //for a 128-bit piece of a keystream    
    CAESEncryptor*  encryptor = NULL;
    TUint buffLength;       //length of the result (as 8 bit descriptor)
    TUint count;          // how many 128-bit AES calls needed 
    
    buffLength = aBitLength/8;  
    if (aBitLength%8)
        {
        buffLength++;            
        }

    count = aBitLength/128;    
    if (aBitLength%128)
        {
        count++;            
        }
    
	HBufC8* outputBuff = HBufC8::NewLC(16*count);
	TPtr8 ptrOutputBuff = outputBuff->Des();	
    
    SRTP_DEBUG_TUINT_VALUE( "KeyStreamL, Check the length of aKey==16 and the length is", (aKey.Length()) );
    
    if(aKey.Length() != 16)
    	{
	    CleanupStack::Pop(outputBuff);
        delete outputBuff;    
        outputBuff=NULL;    
    	User::Leave(KErrArgument);
    	}
    
    SRTP_DEBUG_TUINT_VALUE( "KeyStreamL, Check the length of aIV==16 and the length is", (TUint)aIV.Length() );
    
    //if IV's length is not valid
    if(aIV.Length() != 16)
    	{
	    CleanupStack::Pop(outputBuff);
        delete outputBuff;    
        outputBuff= NULL; 
    	User::Leave(KErrArgument);
    	}    
            
    iv.Copy(aIV);
    
    SRTP_DEBUG_TUINT_VALUE( "KeyStreamL, Check aBitLength/128>KSRTPMaxKeyStreamBlocks and the length is", 
                (TUint)aBitLength/128  );
    if(aBitLength/128 > KSRTPMaxKeyStreamBlocks)
    	{
	    CleanupStack::Pop(outputBuff);
        delete outputBuff;    
        outputBuff=NULL;   
    	User::Leave(KErrArgument);
    	}

    encryptor = CAESEncryptor::NewLC(aKey);
                   
    for(int x = 0; x < count; x++)
    	{    	    	   	
    	data.Copy(iv);
    
    	encryptor->Transform(data);

    	IncreaseIV(iv);
    	    			
		ptrOutputBuff.Append(data);		    	
    	}
    
    //set the size if it was changed
    TInt size= ptrOutputBuff.Size();
    ptrOutputBuff.SetLength(buffLength);
    	
	CleanupStack::PopAndDestroy(encryptor);
    CleanupStack::Pop(outputBuff); 
       	    
    SRTP_DEBUG_TUINT_VALUE( "CSrtpAESCTRCrypto::KeystreamL ptrOutputBuff.Size()", 
    			(TUint)size );
    
    return outputBuff;	
	}


// ---------------------------------------------------------------------------
// CSrtpAESCTRCrypto::EncryptL
// 
// ---------------------------------------------------------------------------
//
EXPORT_C HBufC8* CSrtpAESCTRCrypto::EncryptL(const TDesC8& aKey, 
                                            const TDesC8& aIV, 
                                            const TDesC8& aSrc)
	{
		
		HBufC8* outputBuff = HBufC8::NewLC(aSrc.Length());
		TPtr8 ptrOutputBuff = outputBuff->Des();
			
	    TBuf8<16> iv; //temp for IV
	    TBuf8<16> data; //for a 128-bit piece of a keystream
	    TBuf8<16> msg; //for a 128-bit piece of a message
	    TInt count=0; // how many full 128-bit pieces can be made of a source
	    
	    SRTP_DEBUG_TINT_VALUE( "EncryptL, Check aBitLengh ==16 and the length is", 
	                aKey.Length()  );
	      
	    //if key's length is not valid
	    if(aKey.Length() != 16)
	    	{
		    CleanupStack::Pop(outputBuff);
	        delete outputBuff;    
	        outputBuff= NULL;
	    	User::Leave(KErrArgument);
	    	}
	    SRTP_DEBUG_TINT_VALUE( "EncryptL, Check the length of aIV==16 and the length is", 
	                aIV.Length() );
	               
	    //if IV's length is not valid
	    if(aIV.Length() != 16)
	    	{
		    CleanupStack::Pop(outputBuff);
	        delete outputBuff;    
	        outputBuff= NULL;  
	    	User::Leave(KErrArgument);
	    	}    
		
		SRTP_DEBUG_TINT_VALUE("EncryptL, Check aSrc.Length()>KSRTPMaxTextLength and the length is", 
	                aSrc.Length()  );
	          
	    //check that text length is less than 2^23
	    if(aSrc.Length() > KSRTPMaxTextLength)
	    	{
		    CleanupStack::Pop(outputBuff);
	        delete outputBuff;    
	        outputBuff= NULL;    
	    	User::Leave(KErrArgument);
	    	}
	            
	    iv.Copy(aIV);
	        
	    count = aSrc.Length()/16;
		
		SRTP_DEBUG_TINT_VALUE("EncryptL, count>KSRTPMaxKeyStreamBlocks and the length is", 
	                count  );
	         

	    if(count > KSRTPMaxKeyStreamBlocks)
	    	{
		    CleanupStack::Pop(outputBuff);
	        delete outputBuff;    
	        outputBuff= NULL;  
	    	User::Leave(KErrArgument);
	    	}

	    if ( !iEncryptor || !iKey || (*iKey != aKey) )
	        {
	        CreateEncryptorL(aKey);
            }
	                   
	    for(int x = 0; x < count; x++)
	    	{
	    	msg.Copy(aSrc.Mid(x*16, 16));
	    	
	    	data.Copy(iv);
	    	   	
	    	iEncryptor->Transform(data);

	    	IncreaseIV(iv);
	    	    	
		    // XOR 128-bits of message with encrypted IV
		    for(int i = 0; i < 16; i++)
				{
				msg[i] ^= data[i];
				}
			
			ptrOutputBuff.Append(msg);
			    	
	    	}
	    
	    //if source's length isn't an exact multiple of 128-bits
	    if(aSrc.Length()%16)
	    	{
	    	TInt bytesleft;
	    	bytesleft = aSrc.Length() - count*16;
	    	
	    	msg.Copy(aSrc.Mid(count*16, bytesleft));
	    	data.Copy(iv);
	    	iEncryptor->Transform(data);
	    		
		    // XOR last piece of message with encrypted IV
		    for(int i = 0; i < bytesleft; i++)
			{
					msg[i] ^= data[i];
			}
			
			ptrOutputBuff.Append(msg);
			    		
	    	}
		
	    CleanupStack::Pop(outputBuff);    	    
	    
	    return outputBuff;
	}

// ---------------------------------------------------------------------------
// CSrtpAESCTRCrypto::IncreaseIV
// 
// ---------------------------------------------------------------------------
//
void CSrtpAESCTRCrypto::IncreaseIV(TDes8& iv)
	{
	
	if(iv[15] != 0xFF)
		{
		iv[15] += 1;	
		}
	else if(iv[14] != 0xFF)
		{
		iv[15] = 0;
		iv[14] += 1;
		}
	else if(iv[13] != 0xFF)
		{
		iv[15] = 0;
		iv[14] = 0;
		iv[13] += 1;
		}	
	else if (iv[12] != 0xFF)
		{
		iv[15] = 0;
		iv[14] = 0;
		iv[13] = 0;
		iv[12] += 1;
		}		
	else
		{
		iv[15] = 0;
		iv[14] = 0;
		iv[13] = 0;
		iv[12] = 0;
		}

	} 

// ---------------------------------------------------------------------------
// CSrtpAESCTRCrypto::CreateEncryptorL
// ---------------------------------------------------------------------------
//
void CSrtpAESCTRCrypto::CreateEncryptorL(const TDesC8& aKey)
    {
    delete iEncryptor;
    iEncryptor = 0;
    delete iKey;
    iKey = 0;
    iKey = aKey.AllocL();
    iEncryptor = CAESEncryptor::NewL(*iKey);
    }