os/security/crypto/weakcryptospi/source/hash/hmac.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*
     2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     4 * This component and the accompanying materials are made available
     5 * under the terms of the License "Eclipse Public License v1.0"
     6 * which accompanies this distribution, and is available
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
     8 *
     9 * Initial Contributors:
    10 * Nokia Corporation - initial contribution.
    11 *
    12 * Contributors:
    13 *
    14 * Description: 
    15 *
    16 */
    17 
    18 
    19 
    20 #include <e32std.h>
    21 #include <hash.h>
    22 #include <cryptospi/cryptospidef.h>
    23 #include <cryptospi/cryptohashapi.h>
    24 #include <cryptospi/plugincharacteristics.h>
    25 #include "hashshim.h"
    26 
    27 
    28 #define EXPANDLOOP
    29 
    30 //
    31 // HMAC implementation
    32 //
    33 
    34 CHMAC::CHMAC()
    35 	{
    36 	}
    37 
    38 
    39 CHMAC::CHMAC(CMessageDigest* aDigest)
    40 	:CMessageDigest(),
    41 	iDigest(aDigest),
    42 	iInnerPad(KMaxBlockSize),
    43 	iOuterPad(KMaxBlockSize)
    44 	{
    45 	}
    46 
    47 CHMAC::CHMAC(const CHMAC& aMD)
    48 	:CMessageDigest(aMD), 
    49 	iDigest(NULL),
    50 	iInnerPad(aMD.iInnerPad), 
    51 	iOuterPad(aMD.iOuterPad),
    52 	iBlockSize(aMD.iBlockSize)
    53 	{
    54 	}
    55 
    56 EXPORT_C CHMAC::~CHMAC(void)
    57 	{
    58 	delete iDigest;
    59 	}
    60 
    61 EXPORT_C CHMAC* CHMAC::NewL(const TDesC8& aKey,CMessageDigest* aDigest)
    62 	{		
    63 	CHMAC* self = CHMACShim::NewL(aKey, aDigest);
    64 	if (! self)
    65 		{			
    66 		// not able to use CryptoSpi, possibly due to an exterally 
    67 		// derived legacy class so fallback to old implementation.			
    68 		self=new(ELeave) CHMAC(aDigest);
    69 		CleanupStack::PushL(self);
    70 		self->InitialiseL(aKey);
    71 		CleanupStack::Pop(self);
    72 		}
    73 	return self;	
    74 	}
    75 
    76 
    77 // These methods are now deprecated. This is because hashes and HMACs
    78 // should be implemented as plugins to the SPI framework. However, for
    79 // binary compatibility reasons, these methods must be left here.
    80 // There are no tests (hence no coverage) for HMACs outside the plugin
    81 // framework, but this original code is left unmodified.
    82 //
    83 #ifdef _BullseyeCoverage
    84 #pragma suppress_warnings on
    85 #pragma BullseyeCoverage off
    86 #pragma suppress_warnings off
    87 #endif
    88 
    89 
    90 void CHMAC::InitialiseL(const TDesC8& aKey)
    91 	{
    92 	InitBlockSizeL();
    93 	// initialisation
    94 	if (iDigest)
    95 		{
    96 		iDigest->Reset();
    97 		if( (TUint32)aKey.Size() > iBlockSize)
    98 			{
    99 			iInnerPad = iDigest->Final(aKey);
   100 			}
   101 		else 
   102 			{
   103 			iInnerPad = aKey;
   104 			}
   105 			
   106 		TUint i;
   107 		for (i=iInnerPad.Size();i<iBlockSize;i++)
   108 			iInnerPad.Append(0);
   109 
   110 		iOuterPad=iInnerPad;
   111 
   112 		const TUint8 Magic1=0x36, Magic2=0x5c;
   113 		for (i=0;i<iBlockSize;i++)
   114 		{
   115 			iInnerPad[i]^=Magic1;
   116 			iOuterPad[i]^=Magic2;
   117 		}
   118 		//start inner hash
   119 		iDigest->Hash(iInnerPad);
   120 		}
   121 	}
   122 
   123 void CHMAC::InitBlockSizeL()
   124  	{
   125 	 if (iDigest)
   126 		{
   127 	 	iBlockSize = iDigest->BlockSize();
   128 		}
   129 	 if(iBlockSize > KMaxBlockSize)
   130 		 {
   131 		 User::Leave(KErrNotSupported);
   132 		 }
   133  	 
   134  	 iInnerPad.SetLength(iBlockSize);
   135  	 iOuterPad.SetLength(iBlockSize);
   136  	 iInnerPadCopy.SetLength(iBlockSize);
   137  	 iOuterPadCopy.SetLength(iBlockSize);
   138    	}
   139 
   140 EXPORT_C CMessageDigest* CHMAC::CopyL(void)
   141 	{
   142 	CHMAC* that=new(ELeave) CHMAC(*this);
   143 	CleanupStack::PushL(that);
   144 	that->iDigest=iDigest ? iDigest->CopyL() : NULL;
   145 	CleanupStack::Pop();
   146 	return that;
   147 	}
   148 	
   149 EXPORT_C CMessageDigest*  CHMAC::ReplicateL(void)
   150 	{
   151 	CHMAC* that=new(ELeave) CHMAC(*this);
   152 	CleanupStack::PushL(that);
   153 	that->iDigest=iDigest ? iDigest->ReplicateL() : NULL;
   154 	that->Reset();
   155 	CleanupStack::Pop();
   156 	return that;
   157 	}
   158 
   159 EXPORT_C TInt CHMAC::BlockSize(void)
   160 	{
   161 	return iBlockSize;
   162 	}
   163 
   164 EXPORT_C TInt CHMAC::HashSize(void)
   165 	{
   166 	return iDigest ? iDigest->HashSize() : 0;
   167 	}
   168 	
   169 EXPORT_C void CHMAC::Reset(void)
   170 	{
   171 	if (iDigest)
   172 		{
   173 		iDigest->Reset();
   174 		iDigest->Update(iInnerPad);
   175 		}
   176 	}
   177 
   178 //	JCS, There may be a more efficient method but I can't find it
   179 //	because using the DoFinal/DoUpdate functions directly calls
   180 //	Store/Restore at inappropriate times and scribbles over stored
   181 //	data
   182 //	This is the only way I've found to both generate a hash value
   183 //	and get this in the correctly updated state
   184 EXPORT_C TPtrC8 CHMAC::Hash(const TDesC8& aMessage)
   185 	{
   186 	TPtrC8 ptr(KNullDesC8());
   187 	TPtrC8 finalPtr(KNullDesC8());
   188 	StoreState();
   189 	if (iDigest)
   190 	{
   191 		ptr.Set(iDigest->Final(aMessage));
   192 		iDigest->Update(iOuterPad);
   193 		finalPtr.Set(iDigest->Final(ptr));
   194 	}
   195 
   196 	RestoreState();
   197 
   198 	if(iDigest)
   199 		{
   200 		iDigest->Update(aMessage);
   201 		}
   202 
   203 	return (finalPtr);
   204 	}
   205 
   206 EXPORT_C void CHMAC::Update(const TDesC8& aMessage)
   207 	{
   208 	if(iDigest)
   209 		{
   210 		iDigest->Update(aMessage);
   211 		}
   212 	}
   213 
   214 EXPORT_C TPtrC8 CHMAC::Final(const TDesC8& aMessage)
   215 	{
   216 	TPtrC8 ptr(KNullDesC8());
   217 	if(iDigest)
   218 		{
   219 		ptr.Set(iDigest->Final(aMessage));
   220 		iDigest->Update(iOuterPad);
   221 		iDigest->Final(ptr);
   222 		Reset();
   223 		}
   224 	return (ptr);
   225 	}
   226 
   227 EXPORT_C TPtrC8 CHMAC::Final()
   228 	{
   229 	TPtrC8 ptr(KNullDesC8());
   230 	if(iDigest)
   231 		{
   232 		ptr.Set(iDigest->Final());
   233 		iDigest->Update(iOuterPad);
   234 		iDigest->Final(ptr);
   235 		Reset();
   236 		}
   237 	return (ptr);
   238 	}
   239 
   240 void CHMAC::RestoreState()
   241 	{
   242 	iOuterPad.Copy(iOuterPadCopy);
   243 	iInnerPad.Copy(iInnerPadCopy);
   244 	if (iDigest)
   245 		iDigest->RestoreState();
   246 	}
   247 
   248 void CHMAC::StoreState()
   249 	{
   250 	iOuterPadCopy.Copy(iOuterPad);
   251 	iInnerPadCopy.Copy(iInnerPad);
   252 	if (iDigest)
   253 		iDigest->StoreState();
   254 	}
   255 
   256