1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/crypto/weakcryptospi/source/hash/hmac.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,256 @@
1.4 +/*
1.5 +* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of the License "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description:
1.18 +*
1.19 +*/
1.20 +
1.21 +
1.22 +
1.23 +#include <e32std.h>
1.24 +#include <hash.h>
1.25 +#include <cryptospi/cryptospidef.h>
1.26 +#include <cryptospi/cryptohashapi.h>
1.27 +#include <cryptospi/plugincharacteristics.h>
1.28 +#include "hashshim.h"
1.29 +
1.30 +
1.31 +#define EXPANDLOOP
1.32 +
1.33 +//
1.34 +// HMAC implementation
1.35 +//
1.36 +
1.37 +CHMAC::CHMAC()
1.38 + {
1.39 + }
1.40 +
1.41 +
1.42 +CHMAC::CHMAC(CMessageDigest* aDigest)
1.43 + :CMessageDigest(),
1.44 + iDigest(aDigest),
1.45 + iInnerPad(KMaxBlockSize),
1.46 + iOuterPad(KMaxBlockSize)
1.47 + {
1.48 + }
1.49 +
1.50 +CHMAC::CHMAC(const CHMAC& aMD)
1.51 + :CMessageDigest(aMD),
1.52 + iDigest(NULL),
1.53 + iInnerPad(aMD.iInnerPad),
1.54 + iOuterPad(aMD.iOuterPad),
1.55 + iBlockSize(aMD.iBlockSize)
1.56 + {
1.57 + }
1.58 +
1.59 +EXPORT_C CHMAC::~CHMAC(void)
1.60 + {
1.61 + delete iDigest;
1.62 + }
1.63 +
1.64 +EXPORT_C CHMAC* CHMAC::NewL(const TDesC8& aKey,CMessageDigest* aDigest)
1.65 + {
1.66 + CHMAC* self = CHMACShim::NewL(aKey, aDigest);
1.67 + if (! self)
1.68 + {
1.69 + // not able to use CryptoSpi, possibly due to an exterally
1.70 + // derived legacy class so fallback to old implementation.
1.71 + self=new(ELeave) CHMAC(aDigest);
1.72 + CleanupStack::PushL(self);
1.73 + self->InitialiseL(aKey);
1.74 + CleanupStack::Pop(self);
1.75 + }
1.76 + return self;
1.77 + }
1.78 +
1.79 +
1.80 +// These methods are now deprecated. This is because hashes and HMACs
1.81 +// should be implemented as plugins to the SPI framework. However, for
1.82 +// binary compatibility reasons, these methods must be left here.
1.83 +// There are no tests (hence no coverage) for HMACs outside the plugin
1.84 +// framework, but this original code is left unmodified.
1.85 +//
1.86 +#ifdef _BullseyeCoverage
1.87 +#pragma suppress_warnings on
1.88 +#pragma BullseyeCoverage off
1.89 +#pragma suppress_warnings off
1.90 +#endif
1.91 +
1.92 +
1.93 +void CHMAC::InitialiseL(const TDesC8& aKey)
1.94 + {
1.95 + InitBlockSizeL();
1.96 + // initialisation
1.97 + if (iDigest)
1.98 + {
1.99 + iDigest->Reset();
1.100 + if( (TUint32)aKey.Size() > iBlockSize)
1.101 + {
1.102 + iInnerPad = iDigest->Final(aKey);
1.103 + }
1.104 + else
1.105 + {
1.106 + iInnerPad = aKey;
1.107 + }
1.108 +
1.109 + TUint i;
1.110 + for (i=iInnerPad.Size();i<iBlockSize;i++)
1.111 + iInnerPad.Append(0);
1.112 +
1.113 + iOuterPad=iInnerPad;
1.114 +
1.115 + const TUint8 Magic1=0x36, Magic2=0x5c;
1.116 + for (i=0;i<iBlockSize;i++)
1.117 + {
1.118 + iInnerPad[i]^=Magic1;
1.119 + iOuterPad[i]^=Magic2;
1.120 + }
1.121 + //start inner hash
1.122 + iDigest->Hash(iInnerPad);
1.123 + }
1.124 + }
1.125 +
1.126 +void CHMAC::InitBlockSizeL()
1.127 + {
1.128 + if (iDigest)
1.129 + {
1.130 + iBlockSize = iDigest->BlockSize();
1.131 + }
1.132 + if(iBlockSize > KMaxBlockSize)
1.133 + {
1.134 + User::Leave(KErrNotSupported);
1.135 + }
1.136 +
1.137 + iInnerPad.SetLength(iBlockSize);
1.138 + iOuterPad.SetLength(iBlockSize);
1.139 + iInnerPadCopy.SetLength(iBlockSize);
1.140 + iOuterPadCopy.SetLength(iBlockSize);
1.141 + }
1.142 +
1.143 +EXPORT_C CMessageDigest* CHMAC::CopyL(void)
1.144 + {
1.145 + CHMAC* that=new(ELeave) CHMAC(*this);
1.146 + CleanupStack::PushL(that);
1.147 + that->iDigest=iDigest ? iDigest->CopyL() : NULL;
1.148 + CleanupStack::Pop();
1.149 + return that;
1.150 + }
1.151 +
1.152 +EXPORT_C CMessageDigest* CHMAC::ReplicateL(void)
1.153 + {
1.154 + CHMAC* that=new(ELeave) CHMAC(*this);
1.155 + CleanupStack::PushL(that);
1.156 + that->iDigest=iDigest ? iDigest->ReplicateL() : NULL;
1.157 + that->Reset();
1.158 + CleanupStack::Pop();
1.159 + return that;
1.160 + }
1.161 +
1.162 +EXPORT_C TInt CHMAC::BlockSize(void)
1.163 + {
1.164 + return iBlockSize;
1.165 + }
1.166 +
1.167 +EXPORT_C TInt CHMAC::HashSize(void)
1.168 + {
1.169 + return iDigest ? iDigest->HashSize() : 0;
1.170 + }
1.171 +
1.172 +EXPORT_C void CHMAC::Reset(void)
1.173 + {
1.174 + if (iDigest)
1.175 + {
1.176 + iDigest->Reset();
1.177 + iDigest->Update(iInnerPad);
1.178 + }
1.179 + }
1.180 +
1.181 +// JCS, There may be a more efficient method but I can't find it
1.182 +// because using the DoFinal/DoUpdate functions directly calls
1.183 +// Store/Restore at inappropriate times and scribbles over stored
1.184 +// data
1.185 +// This is the only way I've found to both generate a hash value
1.186 +// and get this in the correctly updated state
1.187 +EXPORT_C TPtrC8 CHMAC::Hash(const TDesC8& aMessage)
1.188 + {
1.189 + TPtrC8 ptr(KNullDesC8());
1.190 + TPtrC8 finalPtr(KNullDesC8());
1.191 + StoreState();
1.192 + if (iDigest)
1.193 + {
1.194 + ptr.Set(iDigest->Final(aMessage));
1.195 + iDigest->Update(iOuterPad);
1.196 + finalPtr.Set(iDigest->Final(ptr));
1.197 + }
1.198 +
1.199 + RestoreState();
1.200 +
1.201 + if(iDigest)
1.202 + {
1.203 + iDigest->Update(aMessage);
1.204 + }
1.205 +
1.206 + return (finalPtr);
1.207 + }
1.208 +
1.209 +EXPORT_C void CHMAC::Update(const TDesC8& aMessage)
1.210 + {
1.211 + if(iDigest)
1.212 + {
1.213 + iDigest->Update(aMessage);
1.214 + }
1.215 + }
1.216 +
1.217 +EXPORT_C TPtrC8 CHMAC::Final(const TDesC8& aMessage)
1.218 + {
1.219 + TPtrC8 ptr(KNullDesC8());
1.220 + if(iDigest)
1.221 + {
1.222 + ptr.Set(iDigest->Final(aMessage));
1.223 + iDigest->Update(iOuterPad);
1.224 + iDigest->Final(ptr);
1.225 + Reset();
1.226 + }
1.227 + return (ptr);
1.228 + }
1.229 +
1.230 +EXPORT_C TPtrC8 CHMAC::Final()
1.231 + {
1.232 + TPtrC8 ptr(KNullDesC8());
1.233 + if(iDigest)
1.234 + {
1.235 + ptr.Set(iDigest->Final());
1.236 + iDigest->Update(iOuterPad);
1.237 + iDigest->Final(ptr);
1.238 + Reset();
1.239 + }
1.240 + return (ptr);
1.241 + }
1.242 +
1.243 +void CHMAC::RestoreState()
1.244 + {
1.245 + iOuterPad.Copy(iOuterPadCopy);
1.246 + iInnerPad.Copy(iInnerPadCopy);
1.247 + if (iDigest)
1.248 + iDigest->RestoreState();
1.249 + }
1.250 +
1.251 +void CHMAC::StoreState()
1.252 + {
1.253 + iOuterPadCopy.Copy(iOuterPad);
1.254 + iInnerPadCopy.Copy(iInnerPad);
1.255 + if (iDigest)
1.256 + iDigest->StoreState();
1.257 + }
1.258 +
1.259 +