1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/cryptoplugins/cryptospiplugins/test/h4drv/crypto_h4/cryptoldd.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1036 @@
1.4 +/*
1.5 +* Copyright (c) 2007-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 + @file
1.24 + @internalComponent
1.25 + @released
1.26 +*/
1.27 +#include <kernel/kern_priv.h>
1.28 +#include "cryptodriver.h"
1.29 +#include "cryptoldd.h"
1.30 +#include "keyhandle.h"
1.31 +#include "kmskext.h"
1.32 +
1.33 +DECLARE_STANDARD_LDD()
1.34 + {
1.35 + return new DCryptoLddChannelFactory;
1.36 + }
1.37 +
1.38 +//#define HW_PERF_CHECK
1.39 +
1.40 +_LIT(KCryptoPanicCategory,"DCrypto");
1.41 +
1.42 +/**
1.43 + Constructor
1.44 +*/
1.45 +DCryptoLddChannelFactory::DCryptoLddChannelFactory()
1.46 + {
1.47 + TRACE_FUNCTION("DCryptoLddChannelFactory");
1.48 + // Set version number for this device
1.49 + iVersion=RCryptoDriver::VersionRequired();
1.50 + // Auto load a PDD
1.51 + iParseMask=KDeviceAllowPhysicalDevice;
1.52 + }
1.53 +
1.54 +/**
1.55 + Destructor
1.56 +*/
1.57 +DCryptoLddChannelFactory::~DCryptoLddChannelFactory()
1.58 + {
1.59 + TRACE_FUNCTION("~DCryptoLddChannelFactory");
1.60 + TraceFunction::DumpCounts();
1.61 + }
1.62 +
1.63 +
1.64 +/**
1.65 + Second stage constructor for DCryptoLddChannelFactory.
1.66 + This must at least set a name for the driver object.
1.67 +
1.68 + @return KErrNone if successful, otherwise one of the other system wide error codes.
1.69 +*/
1.70 +TInt DCryptoLddChannelFactory::Install()
1.71 + {
1.72 + TRACE_FUNCTION("Install");
1.73 + return SetName(&RCryptoDriver::Name());
1.74 + }
1.75 +
1.76 +/**
1.77 + Return the drivers capabilities.
1.78 + Called in the response to an RDevice::GetCaps() request.
1.79 +
1.80 + @param aDes Descriptor into which capabilities information is to be written.
1.81 +*/
1.82 +void DCryptoLddChannelFactory::GetCaps(TDes8& aDes) const
1.83 + {
1.84 + TRACE_FUNCTION("GetCaps");
1.85 + // Create a capabilities object
1.86 + RCryptoDriver::TCaps caps;
1.87 + caps.iVersion = iVersion;
1.88 +
1.89 + // We do not have a handle to the PDD, and it might not have been
1.90 + // loaded yet, so we can't ask it for its capabilities...
1.91 +
1.92 + // Write it back to user memory
1.93 + Kern::InfoCopy(aDes,(TUint8*)&caps,sizeof(caps));
1.94 + return;
1.95 + }
1.96 +
1.97 +/**
1.98 + Called by the kernel's device driver framework to create a Logical Channel.
1.99 + This is called in the context of the user thread (client) which requested the creation
1.100 + of the Logical Channel (e.g. through a call to RBusLogicalChannel::DoCreate).
1.101 + The thread is in a critical section.
1.102 +
1.103 + @param aChannel Set to point to the created Logical Channel
1.104 +
1.105 + @return KErrNone if successful, otherwise one of the other system wide error codes.
1.106 +*/
1.107 +TInt DCryptoLddChannelFactory::Create(DLogicalChannelBase*& aChannel)
1.108 + {
1.109 + TRACE_FUNCTION("Create");
1.110 + aChannel=new DCryptoLddChannel;
1.111 + if(!aChannel)
1.112 + return KErrNoMemory;
1.113 +
1.114 + return KErrNone;
1.115 + }
1.116 +
1.117 +
1.118 +//
1.119 +// Logical Channel
1.120 +//
1.121 +
1.122 +/**
1.123 + Constructor
1.124 +*/
1.125 +DCryptoLddChannel::DCryptoLddChannel()
1.126 + : iLddChanRandom(*this),
1.127 + iLddChanAes(*this)
1.128 + {
1.129 + TRACE_FUNCTION("DCryptoLddChannel");
1.130 + // Get pointer to client thread's DThread object
1.131 + iClient=&Kern::CurrentThread();
1.132 +
1.133 + // Open a reference on client thread so its control block can't disappear until
1.134 + // this driver has finished with it.
1.135 + // Note, this call to Open() can't fail since it is the thread we are currently running in.
1.136 + iClient->Open();
1.137 + }
1.138 +
1.139 +
1.140 +/**
1.141 + Destructor
1.142 +*/
1.143 +DCryptoLddChannel::~DCryptoLddChannel()
1.144 + {
1.145 + TRACE_FUNCTION("~DCryptoLddChannel");
1.146 + // Cancel all processing that we may be doing
1.147 + DoCancel(RCryptoDriver::EAllRequests);
1.148 + // Close our reference on the client thread
1.149 + Kern::SafeClose((DObject*&)iClient,NULL);
1.150 + }
1.151 +
1.152 +
1.153 +/**
1.154 + Second stage constructor called by the kernel's device driver framework.
1.155 + This is called in the context of the user thread (client) which requested the creation
1.156 + of the Logical Channel (e.g. through a call to RBusLogicalChannel::DoCreate())
1.157 + The thread is in a critical section.
1.158 +
1.159 + @param aUnit The unit argument supplied by the client to RBusLogicalChannel::DoCreate()
1.160 + @param aInfo The info argument supplied by the client to RBusLogicalChannel::DoCreate()
1.161 + @param aVer The version argument supplied by the client to RBusLogicalChannel::DoCreate()
1.162 +
1.163 + @return KErrNone if successful, otherwise one of the other system wide error codes.
1.164 +*/
1.165 +TInt DCryptoLddChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& aVer)
1.166 + {
1.167 + TRACE_FUNCTION("DoCreate");
1.168 + // Check Platform Security capabilities of client thread (if required).
1.169 + //
1.170 + // Here we handle the simple case where:
1.171 + // 1. The device driver can only have one client thread
1.172 + // 2. The security policy is the binary all-or-nothing policy.
1.173 + // E.g. "If you have the right capability you can do anything with the driver
1.174 + // and if you don't have the capability you can't do anything"
1.175 + //
1.176 + // If only some functionality of the driver is restricted, then the security check should
1.177 + // go elsewhere. E.g. in DoRequest/DoControl. In that case Kern::CurrentThreadHasCapability
1.178 + // shouldn't be used because the 'current thread' isn't the client.
1.179 + //
1.180 + // In this example we do a check here for ECapability_None (which always passes)...
1.181 + if(!Kern::CurrentThreadHasCapability(ECapability_None,__PLATSEC_DIAGNOSTIC_STRING("Checked by DRIVER1")))
1.182 + return KErrPermissionDenied;
1.183 +
1.184 + // Check version
1.185 + if (!Kern::QueryVersionSupported(RCryptoDriver::VersionRequired(),aVer))
1.186 + return KErrNotSupported;
1.187 +
1.188 + // Give PDD a pointer to this channel
1.189 + PddChan()->iCryptoLddChannel = this;
1.190 +
1.191 + // Setup LDD for receiving client messages.
1.192 + SetDfcQ(PddChan()->DfcQue());
1.193 + iMsgQ.Receive();
1.194 +
1.195 + // Done
1.196 + return KErrNone;
1.197 + }
1.198 +
1.199 +
1.200 +/**
1.201 + Called when a user thread requests a handle to this channel.
1.202 +*/
1.203 +TInt DCryptoLddChannel::RequestUserHandle(DThread* aThread, TOwnerType aType)
1.204 + {
1.205 + TRACE_FUNCTION("RequestUserHandle");
1.206 + // Make sure that only our client can get a handle
1.207 + if (aType!=EOwnerThread || aThread!=iClient)
1.208 + return KErrAccessDenied;
1.209 + return KErrNone;
1.210 + }
1.211 +
1.212 +
1.213 +/**
1.214 + Process a message for this logical channel.
1.215 + This function is called in the context of a DFC thread.
1.216 +
1.217 + @param aMessage The message to process.
1.218 + The iValue member of this distinguishes the message type:
1.219 + iValue==ECloseMsg, channel close message
1.220 + iValue==KMaxTInt, a 'DoCancel' message
1.221 + iValue>=0, a 'DoControl' message with function number equal to iValue
1.222 + iValue<0, a 'DoRequest' message with function number equal to ~iValue
1.223 +*/
1.224 +void DCryptoLddChannel::HandleMsg(TMessageBase* aMsg)
1.225 + {
1.226 + TRACE_FUNCTION("HandleMsg");
1.227 + TThreadMessage& m=*(TThreadMessage*)aMsg;
1.228 +
1.229 + // Get message type
1.230 + TInt id=m.iValue;
1.231 +
1.232 + // Decode the message type and dispatch it to the relevent handler function...
1.233 +
1.234 + if (id==(TInt)ECloseMsg)
1.235 + {
1.236 + // Channel Close
1.237 + DoCancel(RCryptoDriver::EAllRequests);
1.238 + m.Complete(KErrNone, EFalse);
1.239 + return;
1.240 + }
1.241 +
1.242 + if (id==KMaxTInt)
1.243 + {
1.244 + // DoCancel
1.245 + DoCancel(m.Int0());
1.246 + m.Complete(KErrNone,ETrue);
1.247 + return;
1.248 + }
1.249 +
1.250 + if (id<0)
1.251 + {
1.252 + // DoRequest
1.253 + TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
1.254 + TInt r=DoRequest(~id,pS,m.Ptr1(),m.Ptr2());
1.255 + if (r!=KErrNone)
1.256 + Kern::RequestComplete(iClient,pS,r);
1.257 + m.Complete(KErrNone,ETrue);
1.258 + }
1.259 + else
1.260 + {
1.261 + // DoControl
1.262 + TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
1.263 + m.Complete(r,ETrue);
1.264 + }
1.265 + }
1.266 +
1.267 +/**
1.268 + Process synchronous 'control' requests
1.269 +*/
1.270 +TInt DCryptoLddChannel::DoControl(TInt aFunction, TAny* a1, TAny *)
1.271 + {
1.272 + TRACE_FUNCTION("DoControl");
1.273 + TInt r;
1.274 +
1.275 + switch (aFunction)
1.276 + {
1.277 + case RCryptoDriver::EGetHwVersions:
1.278 + r = GetHwVersions((TDes8*)a1);
1.279 + break;
1.280 +
1.281 + case RCryptoDriver::EGetConfig:
1.282 + r = GetConfig((TDes8*)a1);
1.283 + break;
1.284 +
1.285 + case RCryptoDriver::ESetConfig:
1.286 + r = SetConfig((const TDesC8*)a1);
1.287 + break;
1.288 +
1.289 + case RCryptoDriver::EAesSetConfig:
1.290 + r = iLddChanAes.SetAesConfig((const TDesC8*)a1);
1.291 + break;
1.292 +
1.293 + default:
1.294 + r=KErrNotSupported;
1.295 + break;
1.296 + }
1.297 +
1.298 + return r;
1.299 + }
1.300 +
1.301 +
1.302 +/**
1.303 + Process asynchronous requests
1.304 +*/
1.305 +TInt DCryptoLddChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
1.306 + {
1.307 + TRACE_FUNCTION("DoRequest");
1.308 + (void)a2; // a2 not used in this example
1.309 +
1.310 + TInt r;
1.311 +
1.312 + switch(aReqNo)
1.313 + {
1.314 + case RCryptoDriver::ERandom:
1.315 + r=iLddChanRandom.Random(aStatus,(TDes8*)a1);
1.316 + break;
1.317 +
1.318 + case RCryptoDriver::EAesWrite:
1.319 + r=iLddChanAes.AesWrite(aStatus,(TDesC8*)a1);
1.320 + break;
1.321 +
1.322 + case RCryptoDriver::EAesRead:
1.323 + r=iLddChanAes.AesRead(aStatus,(TDes8*)a1, (TUint32)a2);
1.324 + break;
1.325 +
1.326 + default:
1.327 + r=KErrNotSupported;
1.328 + break;
1.329 + }
1.330 +
1.331 + return r;
1.332 + }
1.333 +
1.334 +
1.335 +/**
1.336 + Process cancelling of asynchronous requests
1.337 +*/
1.338 +void DCryptoLddChannel::DoCancel(TUint aMask)
1.339 + {
1.340 + TRACE_FUNCTION("DoCancel");
1.341 + if(aMask&(1<<RCryptoDriver::ERandom))
1.342 + {
1.343 + iLddChanRandom.RandomCancel();
1.344 + }
1.345 +
1.346 + if(aMask&(1<<RCryptoDriver::EAesRead))
1.347 + {
1.348 + iLddChanAes.CancelRead();
1.349 + }
1.350 +
1.351 + if(aMask&(1<<RCryptoDriver::EAesWrite))
1.352 + {
1.353 + iLddChanAes.CancelWrite();
1.354 + }
1.355 +
1.356 + }
1.357 +
1.358 +
1.359 +/**
1.360 + Process a GetHwVersions control message. This writes the crypto h/w versions to a
1.361 + RCryptoDriver::THwVersionsBuf supplied by the client.
1.362 +*/
1.363 +TInt DCryptoLddChannel::GetHwVersions(TDes8* aHwVersionsBuf) const
1.364 + {
1.365 + TRACE_FUNCTION("GetHwVersions");
1.366 + // Create a structure giving the current configuration
1.367 + RCryptoDriver::THwVersions versions;
1.368 +
1.369 + PddChan()->GetHwVersions(versions);
1.370 +
1.371 + // Write the config to the client
1.372 + TPtrC8 ptr((const TUint8*)&versions,sizeof(versions));
1.373 + return Kern::ThreadDesWrite(iClient,aHwVersionsBuf,ptr,0,KTruncateToMaxLength,NULL);
1.374 + }
1.375 +
1.376 +//
1.377 +// Functions for processing configuration control messages
1.378 +//
1.379 +
1.380 +/**
1.381 + Process a GetConfig control message. This writes the current driver configuration to a
1.382 + RCryptoDriver::TConfigBuf supplied by the client.
1.383 +*/
1.384 +TInt DCryptoLddChannel::GetConfig(TDes8* aConfigBuf) const
1.385 + {
1.386 + TRACE_FUNCTION("GetConfig");
1.387 + // Create a structure giving the current configuration
1.388 + RCryptoDriver::TConfig config;
1.389 + CurrentConfig(config);
1.390 +
1.391 + // Write the config to the client
1.392 + TPtrC8 ptr((const TUint8*)&config,sizeof(config));
1.393 + return Kern::ThreadDesWrite(iClient,aConfigBuf,ptr,0,KTruncateToMaxLength,NULL);
1.394 + }
1.395 +
1.396 +/**
1.397 + Process a SetConfig control message. This sets the driver configuration using a
1.398 + RCryptoDriver::TConfigBuf supplied by the client.
1.399 +*/
1.400 +TInt DCryptoLddChannel::SetConfig(const TDesC8* aConfigBuf)
1.401 + {
1.402 + TRACE_FUNCTION("SetConfig");
1.403 + // Don't allow configuration changes whilst we're busy
1.404 + // if(iSendDataStatus || iReceiveDataStatus)
1.405 + // return KErrInUse;
1.406 +
1.407 + // Create a config structure.
1.408 + RCryptoDriver::TConfig config;
1.409 + CurrentConfig(config);
1.410 +
1.411 + // Note: We have filled config with the current settings, this is to allow
1.412 + // backwards compatibility when a client gives us an old (and shorter) version
1.413 + // of the config structure.
1.414 +
1.415 + // Read the config structure from client
1.416 + TPtr8 ptr((TUint8*)&config,sizeof(config));
1.417 + TInt r=Kern::ThreadDesRead(iClient,aConfigBuf,ptr,0);
1.418 + if(r!=KErrNone)
1.419 + return r;
1.420 +
1.421 + // Use config data to setup the driver. Checking that parameters which aren't settable
1.422 + // either contain the correct values or are zero (meaning 'default')
1.423 + r=PddChan()->SetFakeDriverSetting(config.iFakeDriverSetting);
1.424 + if(r!=KErrNone)
1.425 + return r;
1.426 +
1.427 + return r;
1.428 + }
1.429 +
1.430 +
1.431 +/**
1.432 + Fill a TConfig with the driver's current configuration.
1.433 +*/
1.434 +void DCryptoLddChannel::CurrentConfig(RCryptoDriver::TConfig& aConfig) const
1.435 + {
1.436 + TRACE_FUNCTION("TConfig");
1.437 + aConfig.iFakeDriverSetting = PddChan()->FakeDriverSetting();
1.438 + }
1.439 +
1.440 +
1.441 +
1.442 +//
1.443 +// Functions for processing 'Random'
1.444 +//
1.445 +
1.446 +DLddChanRandom::DLddChanRandom(DCryptoLddChannel &aParent)
1.447 + : iParent(aParent)
1.448 + {
1.449 + TRACE_FUNCTION("DLddChanRandom");
1.450 + }
1.451 +
1.452 +
1.453 +/**
1.454 + Start processing a Random request.
1.455 +*/
1.456 +TInt DLddChanRandom::Random(TRequestStatus* aStatus,TDes8* aPtr)
1.457 + {
1.458 + TRACE_FUNCTION("Random");
1.459 + // Check that a 'Random' isn't already in progress
1.460 + if(iRandomStatus)
1.461 + {
1.462 + Kern::ThreadKill(iParent.iClient,EExitPanic,ERequestAlreadyPending,KCryptoPanicCategory);
1.463 + return KErrInUse;
1.464 + }
1.465 +
1.466 + // We only support a single outstanding Random request in this LDD
1.467 + // channel, but the PDD supports multiple requests.
1.468 +
1.469 + // Save the client request status and descriptor
1.470 + iRandomStatus = aStatus;
1.471 + iRandomDescriptor = aPtr;
1.472 +
1.473 + // Retrieve user request length (ie. CURRENT length of user descriptor) into iRequestLength
1.474 + TInt tmp;
1.475 + TUint8 *tmp2;
1.476 + TInt r=Kern::ThreadGetDesInfo(iParent.iClient, iRandomDescriptor, iRequestLength, tmp, tmp2, ETrue);
1.477 + if(r != KErrNone)
1.478 + {
1.479 + return r;
1.480 + }
1.481 +
1.482 + // Set current offset into user descriptor
1.483 + iCurrentIndex = 0;
1.484 +
1.485 + iJob = iParent.PddChan()->GetJobRandom();
1.486 +
1.487 + // Setup PDD job
1.488 + iJob->SetDetails(&iParent.LddFactory()->iJSRandom, this, iRequestLength);
1.489 + // Register it, which will also (maybe later) call DoSlice to run it
1.490 + iParent.LddFactory()->iJSRandom.ScheduleJob(iJob);
1.491 +
1.492 + return KErrNone;
1.493 + }
1.494 +
1.495 +
1.496 +
1.497 +TInt DLddChanRandom::DataRequired()
1.498 + {
1.499 + TRACE_FUNCTION("DataRequired");
1.500 + return KErrNone; // We never pass data to the h/w...
1.501 + }
1.502 +
1.503 +TInt DLddChanRandom::DataAvailable()
1.504 + {
1.505 + TRACE_FUNCTION("DataAvailable");
1.506 + // Kern::Printf("DLddChanRandom::DataAvailable()");
1.507 + TInt r = KErrNone;
1.508 +
1.509 + TUint8 *buf;
1.510 + TUint32 bufLen;
1.511 + TBool check = ETrue;
1.512 + while(check)
1.513 + {
1.514 + iJob->GetFromPddBuffer(buf, bufLen, check);
1.515 + if(bufLen)
1.516 + {
1.517 + TInt required = iRequestLength - iCurrentIndex;
1.518 + TInt toTransfer = bufLen;
1.519 + if(toTransfer > required)
1.520 + {
1.521 + toTransfer = required;
1.522 + }
1.523 + // Copy the current buffer to user land
1.524 + TPtr8 des(buf, toTransfer, toTransfer);
1.525 + r=Kern::ThreadDesWrite(iParent.iClient, iRandomDescriptor, des, iCurrentIndex);
1.526 + if(r != KErrNone)
1.527 + {
1.528 + break;
1.529 + }
1.530 +
1.531 + // Update our index into the user descriptor
1.532 + iCurrentIndex += toTransfer;
1.533 +
1.534 + // Update h/w with number of bytes actually read
1.535 + iJob->BytesReadFromPdd(toTransfer);
1.536 +
1.537 + if(toTransfer != bufLen)
1.538 + {
1.539 + // We did not read all the available data, so do not
1.540 + // re-query h/w
1.541 + check = EFalse;
1.542 + }
1.543 + }
1.544 + };
1.545 +
1.546 + return r;
1.547 + }
1.548 +
1.549 +void DLddChanRandom::JobComplete(TInt aResult)
1.550 + {
1.551 + TRACE_FUNCTION("JobComplete");
1.552 + if(iRandomStatus)
1.553 + {
1.554 + // Finished with client descriptor, so NULL it to help detect coding errors
1.555 + iRandomDescriptor = NULL;
1.556 + // Complete client's request
1.557 + Kern::RequestComplete(iParent.iClient,iRandomStatus, aResult);
1.558 + }
1.559 + }
1.560 +
1.561 +
1.562 +/**
1.563 + Cancel a Random request.
1.564 +*/
1.565 +void DLddChanRandom::RandomCancel()
1.566 + {
1.567 + TRACE_FUNCTION("RandomCancel");
1.568 + if(iRandomStatus)
1.569 + {
1.570 + // Tell PDD to stop processing the request
1.571 + iParent.LddFactory()->iJSRandom.DeScheduleJob(iParent.PddChan()->GetJobRandom());
1.572 + // Finished with client descriptor, so NULL it to help detect coding errors
1.573 + iRandomDescriptor = NULL;
1.574 + // Complete clients request
1.575 + Kern::RequestComplete(iParent.iClient,iRandomStatus,KErrCancel);
1.576 + }
1.577 + }
1.578 +
1.579 +//
1.580 +// Functions for processing 'Aes'
1.581 +//
1.582 +
1.583 +DLddChanAes::DLddChanAes(DCryptoLddChannel &aParent)
1.584 + : iParent(aParent)
1.585 + {
1.586 + TRACE_FUNCTION("DLddChanAes");
1.587 + }
1.588 +
1.589 +
1.590 +TInt DLddChanAes::SetAesConfig(const TDesC8* aConfigBuf)
1.591 + {
1.592 + TRACE_FUNCTION("SetAesConfig");
1.593 + // Note we need to validate arguments kernel side otherwise
1.594 + // someone could easily crash the kernel...
1.595 +
1.596 + RCryptoDriver::TAesConfig config;
1.597 + // Read the config structure from client
1.598 + TPtr8 ptr((TUint8*)&config,sizeof(config));
1.599 + TInt r=Kern::ThreadDesRead(iParent.iClient,aConfigBuf,ptr,0);
1.600 + if(r!=KErrNone)
1.601 + {
1.602 + return r;
1.603 + }
1.604 +
1.605 + // Kern::Printf("iEncrypt = 0x%x",config.iEncrypt);
1.606 + // Kern::Printf("iMode = 0x%x",config.iMode);
1.607 + // Kern::Printf("iKey = 0x%x",config.iKey);
1.608 + // Kern::Printf("iIV = 0x%x",config.iIV);
1.609 +
1.610 +
1.611 + // Remember direction
1.612 + iEncrypt = config.iEncrypt;
1.613 +
1.614 + // Remember mode
1.615 + iMode = config.iMode;
1.616 +
1.617 + //
1.618 + // Handle key
1.619 + //
1.620 +
1.621 + // Retrieve user key length into iKeyLengthBytes
1.622 + TInt tmp;
1.623 + TUint8 *tmp2;
1.624 + r=Kern::ThreadGetDesInfo(iParent.iClient, (TAny *)config.iKey, iKeyLengthBytes, tmp, tmp2, EFalse);
1.625 + if(r!=KErrNone)
1.626 + {
1.627 + return r;
1.628 + }
1.629 +
1.630 + HBuf8 *embeddedKeyData = 0;
1.631 + if(iKeyLengthBytes == 4)
1.632 + {
1.633 + // Some form of embedded key so value is a 32 bit handle
1.634 + TPckgBuf<TKeyHandle> keyHandlePkg;
1.635 +
1.636 + r=Kern::ThreadDesRead(iParent.iClient, (TAny *)config.iKey, keyHandlePkg, 0);
1.637 + if(r != KErrNone)
1.638 + {
1.639 + return r;
1.640 + }
1.641 +
1.642 + TKeyHandle &keyHandle = keyHandlePkg();
1.643 +
1.644 + r = HwKeyStore::ExtractKey(iParent.iClient->iOwningProcess, keyHandle, 0 /*operation*/, embeddedKeyData);
1.645 + if(r != KErrNone)
1.646 + {
1.647 + return r;
1.648 + }
1.649 +
1.650 + // Update key length
1.651 + iKeyLengthBytes = embeddedKeyData->Length();
1.652 + }
1.653 +
1.654 + switch(iKeyLengthBytes)
1.655 + {
1.656 + case 16: // 128 bits
1.657 + break;
1.658 + case 24: // 192 bits
1.659 + break;
1.660 + case 32: // 256 bits
1.661 + break;
1.662 + default: // Illegal length
1.663 + if(embeddedKeyData) delete embeddedKeyData;
1.664 + return KErrArgument;
1.665 + }
1.666 +
1.667 + // Make sure iJob is valid before we use it
1.668 + iJob = iParent.PddChan()->GetJobAes();
1.669 +
1.670 + TUint8 *keyBuffer = iJob->GetKeyBuffer();
1.671 + TPtr8 des(keyBuffer, iKeyLengthBytes);
1.672 +
1.673 + if(embeddedKeyData)
1.674 + {
1.675 + // Copy embedded key to PDD
1.676 + des = *embeddedKeyData;
1.677 + delete embeddedKeyData;
1.678 + embeddedKeyData = 0;
1.679 + }
1.680 + else
1.681 + {
1.682 + // Retrieve key from user
1.683 + r=Kern::ThreadDesRead(iParent.iClient, (TAny *)config.iKey, des, 0);
1.684 + if(r != KErrNone)
1.685 + {
1.686 + return r;
1.687 + }
1.688 + }
1.689 +
1.690 +
1.691 + //
1.692 + // Handle IV
1.693 + //
1.694 +
1.695 + // Retrieve IV length
1.696 + TInt ivLength;
1.697 + r=Kern::ThreadGetDesInfo(iParent.iClient, (TAny *)config.iIV, ivLength, tmp, tmp2, EFalse);
1.698 + // Kern::Printf("DLddChanAes::SetAesConfig r=%d 5",r);
1.699 + if(r != KErrNone)
1.700 + {
1.701 + return r;
1.702 + }
1.703 +
1.704 + if((ivLength != 0) && (ivLength != 16))
1.705 + {
1.706 + return KErrArgument;
1.707 + }
1.708 +
1.709 + if(ivLength == 16)
1.710 + {
1.711 + TUint8 *ivBuffer = iJob->GetIVBuffer();
1.712 + TPtr8 des(ivBuffer, 16);
1.713 + r=Kern::ThreadDesRead(iParent.iClient, (TAny *)config.iIV, des, 0);
1.714 + if(r != KErrNone)
1.715 + {
1.716 + return r;
1.717 + }
1.718 + }
1.719 +
1.720 +
1.721 + // Set details
1.722 + r = iJob->SetDetails(&iParent.LddFactory()->iJSAes, this, iEncrypt, iKeyLengthBytes, iMode);
1.723 + if(r != KErrNone)
1.724 + {
1.725 + return r;
1.726 + }
1.727 +
1.728 + return KErrNone;
1.729 + }
1.730 +
1.731 +/**
1.732 + Start processing a Aes request.
1.733 +*/
1.734 +TInt DLddChanAes::AesWrite(TRequestStatus* aStatus, TDesC8* aPtr)
1.735 + {
1.736 + TRACE_FUNCTION("AesWrite");
1.737 + // Kern::Printf("DLddChanAes::AesWrite");
1.738 + // Check that an Aes Write isn't already in progress
1.739 + if(iAesWriteStatus)
1.740 + {
1.741 + Kern::ThreadKill(iParent.iClient,EExitPanic,ERequestAlreadyPending,KCryptoPanicCategory);
1.742 + return KErrInUse;
1.743 + }
1.744 +
1.745 + // We only support a single outstanding Aes Write request in this LDD
1.746 + // channel, but the PDD supports multiple requests.
1.747 +
1.748 + // Save the client request status and descriptor
1.749 + iAesWriteStatus = aStatus;
1.750 + iAesWriteDescriptor = aPtr;
1.751 +
1.752 +
1.753 + // Retrieve user request length (ie. current length of user descriptor) into iRequestLength
1.754 + TInt maxLen;
1.755 + TUint8 *aesWriteDescriptorBufferRaw;
1.756 + TInt r=Kern::ThreadGetDesInfo(iParent.iClient, iAesWriteDescriptor, iWriteRequestLength, maxLen, aesWriteDescriptorBufferRaw, EFalse);
1.757 + if(r != KErrNone)
1.758 + {
1.759 + iAesWriteStatus = 0;
1.760 + return r;
1.761 + }
1.762 +
1.763 + // Set current offset into user descriptor
1.764 + iCurrentUserWriteIndex = 0;
1.765 +
1.766 + // Make sure iJob is valid before we use it
1.767 + iJob = iParent.PddChan()->GetJobAes();
1.768 +
1.769 +
1.770 +#ifdef HW_PERF_CHECK
1.771 + iJob->HwPerfCheck();
1.772 +#else
1.773 + // Feed some data to the PDD
1.774 + r = DataRequired(); // Fake PDD callback to get data from us.
1.775 + if(r != KErrNone)
1.776 + {
1.777 + iAesWriteStatus = 0;
1.778 + return r;
1.779 + }
1.780 +
1.781 + // Make sure job is not stalled, and maybe (re)add to job list.
1.782 + iJob->Resume();
1.783 +#endif
1.784 +
1.785 + return KErrNone;
1.786 + }
1.787 +
1.788 +
1.789 +TInt DLddChanAes::AesRead(TRequestStatus* aStatus, TDes8* aPtr, TUint32 aLength)
1.790 + {
1.791 + TRACE_FUNCTION("AesRead");
1.792 + // Kern::Printf("DLddChanAes::AesRead");
1.793 + // Check that an Aes Read isn't already in progress
1.794 + if(iAesReadStatus)
1.795 + {
1.796 + Kern::ThreadKill(iParent.iClient,EExitPanic,ERequestAlreadyPending,KCryptoPanicCategory);
1.797 + return KErrInUse;
1.798 + }
1.799 +
1.800 + // We only support a single outstanding Aes Read request in this LDD
1.801 + // channel, but the PDD supports multiple requests.
1.802 +
1.803 + // Save the client request status and descriptor
1.804 + iAesReadStatus = aStatus;
1.805 + iAesReadDescriptor = aPtr;
1.806 + iReadRequestLength = aLength;
1.807 +
1.808 + // Retrieve user request length (ie. current length of user descriptor) into iRequestLength
1.809 + // TInt iOriginalUserReadDescLength;
1.810 + TUint8 *aesReadDescriptorBufferRaw;
1.811 + TInt maxLen;
1.812 + TInt r=Kern::ThreadGetDesInfo(iParent.iClient, iAesReadDescriptor, iOriginalUserReadDescLength, maxLen, aesReadDescriptorBufferRaw, ETrue);
1.813 + if(r != KErrNone)
1.814 + {
1.815 + iAesReadStatus = 0;
1.816 + return r;
1.817 + }
1.818 +
1.819 + if(iReadRequestLength > (maxLen - iOriginalUserReadDescLength))
1.820 + {
1.821 + return KErrArgument;
1.822 + }
1.823 +
1.824 + // Set current offset into user descriptor
1.825 + iCurrentUserReadIndex = 0;
1.826 +
1.827 + // Tell PDD our request length so it can optimse returning the data to us.
1.828 + iJob->NotifyReadRequestLength(iReadRequestLength);
1.829 +
1.830 +
1.831 +#ifndef HW_PERF_CHECK
1.832 + // Make sure iJob is valid before we use it
1.833 + iJob = iParent.PddChan()->GetJobAes();
1.834 +
1.835 + // Process any data already available
1.836 + r = DataAvailable(); // Fake PDD callback to read data from PDD
1.837 + if(r != KErrNone)
1.838 + {
1.839 + iAesReadStatus = 0;
1.840 + return r;
1.841 + }
1.842 +
1.843 + // Make sure job is not stalled (and maybe re-add to job list) We
1.844 + // do this even if we completely satisified the read from the PDD
1.845 + // buffer because a write might be waiting for space in the
1.846 + // buffer...
1.847 + iJob->Resume();
1.848 +#endif
1.849 +
1.850 + return KErrNone;
1.851 + }
1.852 +
1.853 +
1.854 +
1.855 +TInt DLddChanAes::DataRequired()
1.856 + {
1.857 + TRACE_FUNCTION("DataRequired");
1.858 + // Kern::Printf("DLddChanAes::DataRequired");
1.859 + if(!iAesWriteStatus)
1.860 + {
1.861 + return KErrNone;
1.862 + }
1.863 +
1.864 + TBool moreSpace = ETrue;
1.865 + TInt toWrite = (iWriteRequestLength - iCurrentUserWriteIndex);
1.866 + while(toWrite && moreSpace)
1.867 + {
1.868 + // Get details of PDD write buffer
1.869 + TUint8 *pddBuf; // always valid, though pddBufLen might be 0
1.870 + TUint32 pddBufLen; // maybe 0
1.871 + iJob->GetToPddBuffer(pddBuf, pddBufLen, moreSpace);
1.872 +
1.873 + if(toWrite > pddBufLen)
1.874 + {
1.875 + toWrite = pddBufLen;
1.876 + }
1.877 +
1.878 + // Make sure there is some data to write
1.879 + if(toWrite == 0)
1.880 + {
1.881 + break;
1.882 + }
1.883 +
1.884 + TPtr8 des(pddBuf, toWrite);
1.885 + TInt r=Kern::ThreadDesRead(iParent.iClient, iAesWriteDescriptor, des, iCurrentUserWriteIndex);
1.886 + //TInt r = 0;
1.887 + if(r!=KErrNone)
1.888 + return r;
1.889 + iCurrentUserWriteIndex += toWrite;
1.890 + // Tell the PDD how many bytes we wrote to it.
1.891 + // If we wrote data, and the job was not already queued, the
1.892 + // PDD will call ScheduleJob for it.
1.893 + iJob->BytesWrittenToPdd(toWrite);
1.894 +
1.895 + // Update count of bytes left to write
1.896 + toWrite = (iWriteRequestLength - iCurrentUserWriteIndex);
1.897 + };
1.898 +
1.899 + if((iWriteRequestLength - iCurrentUserWriteIndex) <= 0)
1.900 + {
1.901 + // Write request is complete
1.902 + // Finished with client descriptor, so NULL it to help detect coding errors
1.903 + iAesWriteDescriptor = NULL;
1.904 + // Complete client's request
1.905 + Kern::RequestComplete(iParent.iClient,iAesWriteStatus, KErrNone);
1.906 + return KErrNone;
1.907 + }
1.908 +
1.909 + return KErrNone;
1.910 + }
1.911 +
1.912 +TInt DLddChanAes::DataAvailable()
1.913 + {
1.914 + TRACE_FUNCTION("DataAvailable");
1.915 + // Kern::Printf("DLddChanAes::DataAvailable()");
1.916 +
1.917 + if(!iAesReadStatus)
1.918 + {
1.919 + return KErrNone;
1.920 + }
1.921 +
1.922 + TInt r = KErrNone;
1.923 +
1.924 + TUint8 *buf;
1.925 + TUint32 bufLen;
1.926 + TBool check = ETrue;
1.927 + while(check)
1.928 + {
1.929 + iJob->GetFromPddBuffer(buf, bufLen, check);
1.930 + if(bufLen)
1.931 + {
1.932 + TInt required = iReadRequestLength - iCurrentUserReadIndex;
1.933 + TInt toTransfer = bufLen;
1.934 + if(toTransfer > required)
1.935 + {
1.936 + toTransfer = required;
1.937 + }
1.938 + // Copy the current buffer to user land
1.939 + TPtr8 des(buf, toTransfer, toTransfer);
1.940 + r=Kern::ThreadDesWrite(iParent.iClient, iAesReadDescriptor, des, iOriginalUserReadDescLength + iCurrentUserReadIndex);
1.941 + //r = 0;
1.942 + if(r != KErrNone)
1.943 + {
1.944 + break;
1.945 + }
1.946 +
1.947 + // Update our index into the user descriptor
1.948 + iCurrentUserReadIndex += toTransfer;
1.949 +
1.950 + // Update h/w with number of bytes actually read
1.951 + iJob->BytesReadFromPdd(toTransfer);
1.952 +
1.953 + if(toTransfer != bufLen)
1.954 + {
1.955 + // We did not read all the available data, so do not
1.956 + // re-query h/w
1.957 + check = EFalse;
1.958 + }
1.959 + }
1.960 + };
1.961 +
1.962 + if((iReadRequestLength - iCurrentUserReadIndex) <= 0)
1.963 + {
1.964 + // Read request is complete
1.965 + // Finished with client descriptor, so NULL it to help detect coding errors
1.966 + iAesReadDescriptor = NULL;
1.967 + // Complete client's request
1.968 + Kern::RequestComplete(iParent.iClient,iAesReadStatus, KErrNone);
1.969 + return KErrNone;
1.970 + }
1.971 +
1.972 + return KErrNone;
1.973 + }
1.974 +
1.975 +
1.976 +
1.977 +
1.978 +
1.979 +/**
1.980 + Called by PDD from a DFC to indicate that a Aes operation has completed.
1.981 +*/
1.982 +void DLddChanAes::JobComplete(TInt aResult)
1.983 + {
1.984 + TRACE_FUNCTION("JobComplete");
1.985 + // Normally not used for AES, instead the job keeps running and
1.986 + // DataAvailable/DataRequired complete the AesRead/AesWrite
1.987 + // requests.
1.988 + //
1.989 + // Will be called if xfer to/from user space fails (or if another
1.990 + // fatal error occurs).
1.991 + if(iAesReadStatus)
1.992 + {
1.993 + // Finished with client descriptor, so NULL it to help detect coding errors
1.994 + iAesReadDescriptor = NULL;
1.995 + // Complete clients request (nb following call set iAesReadStatus to 0)
1.996 + Kern::RequestComplete(iParent.iClient,iAesReadStatus, aResult);
1.997 + }
1.998 + if(iAesWriteStatus)
1.999 + {
1.1000 + // Finished with client descriptor, so NULL it to help detect coding errors
1.1001 + iAesWriteDescriptor = NULL;
1.1002 + // Complete clients request (nb following call set iAesWriteStatus to 0)
1.1003 + Kern::RequestComplete(iParent.iClient,iAesWriteStatus, aResult);
1.1004 + }
1.1005 + }
1.1006 +
1.1007 +
1.1008 +
1.1009 +/**
1.1010 + Cancel a Aes Read request.
1.1011 +*/
1.1012 +void DLddChanAes::CancelRead()
1.1013 + {
1.1014 + TRACE_FUNCTION("CancelRead");
1.1015 + if(iAesReadStatus)
1.1016 + {
1.1017 + // Finished with client descriptor, so NULL it to help detect coding errors
1.1018 + iAesReadDescriptor = NULL;
1.1019 + // Complete clients request (nb following call set iAesReadStatus to 0)
1.1020 + Kern::RequestComplete(iParent.iClient,iAesReadStatus,KErrCancel);
1.1021 + }
1.1022 + }
1.1023 +
1.1024 +/**
1.1025 + Cancel a Aes Write request.
1.1026 +*/
1.1027 +void DLddChanAes::CancelWrite()
1.1028 + {
1.1029 + TRACE_FUNCTION("CancelWrite");
1.1030 + if(iAesWriteStatus)
1.1031 + {
1.1032 + // Finished with client descriptor, so NULL it to help detect coding errors
1.1033 + iAesWriteDescriptor = NULL;
1.1034 + // Complete clients request (nb following call set iAesWriteStatus to 0)
1.1035 + Kern::RequestComplete(iParent.iClient,iAesWriteStatus,KErrCancel);
1.1036 + }
1.1037 + }
1.1038 +
1.1039 +// End of file