os/security/cryptoplugins/cryptospiplugins/test/h4drv/crypto_h4/cryptoldd.cpp
changeset 0 bde4ae8d615e
     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