os/security/cryptoplugins/cryptospiplugins/test/h4drv/crypto_h4/cryptoldd.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*
     2 * Copyright (c) 2007-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  @file
    21  @internalComponent
    22  @released
    23 */
    24 #include <kernel/kern_priv.h>
    25 #include "cryptodriver.h"
    26 #include "cryptoldd.h"
    27 #include "keyhandle.h"
    28 #include "kmskext.h"
    29 
    30 DECLARE_STANDARD_LDD()
    31     {
    32     return new DCryptoLddChannelFactory;
    33     }
    34 
    35 //#define HW_PERF_CHECK
    36 
    37 _LIT(KCryptoPanicCategory,"DCrypto");
    38 
    39 /**
    40   Constructor
    41 */
    42 DCryptoLddChannelFactory::DCryptoLddChannelFactory()
    43 	{
    44 	TRACE_FUNCTION("DCryptoLddChannelFactory");
    45 	// Set version number for this device
    46     iVersion=RCryptoDriver::VersionRequired();
    47 	// Auto load a PDD
    48     iParseMask=KDeviceAllowPhysicalDevice;
    49 	}
    50 
    51 /**
    52   Destructor
    53 */
    54 DCryptoLddChannelFactory::~DCryptoLddChannelFactory()
    55 	{
    56 	TRACE_FUNCTION("~DCryptoLddChannelFactory");
    57 	TraceFunction::DumpCounts();
    58 	}
    59 
    60 
    61 /**
    62   Second stage constructor for DCryptoLddChannelFactory.
    63   This must at least set a name for the driver object.
    64 
    65   @return KErrNone if successful, otherwise one of the other system wide error codes.
    66 */
    67 TInt DCryptoLddChannelFactory::Install()
    68 	{
    69 	TRACE_FUNCTION("Install");
    70     return SetName(&RCryptoDriver::Name());
    71 	}
    72 
    73 /**
    74   Return the drivers capabilities.
    75   Called in the response to an RDevice::GetCaps() request.
    76 
    77   @param aDes Descriptor into which capabilities information is to be written.
    78 */
    79 void DCryptoLddChannelFactory::GetCaps(TDes8& aDes) const
    80 	{
    81 	TRACE_FUNCTION("GetCaps");
    82     // Create a capabilities object
    83     RCryptoDriver::TCaps caps;
    84 	caps.iVersion = iVersion;
    85 
    86 	// We do not have a handle to the PDD, and it might not have been
    87 	// loaded yet, so we can't ask it for its capabilities...
    88 
    89     // Write it back to user memory
    90     Kern::InfoCopy(aDes,(TUint8*)&caps,sizeof(caps));
    91  	return;
    92 	}
    93 
    94 /**
    95   Called by the kernel's device driver framework to create a Logical Channel.
    96   This is called in the context of the user thread (client) which requested the creation
    97   of the Logical Channel (e.g. through a call to RBusLogicalChannel::DoCreate).
    98   The thread is in a critical section.
    99 
   100   @param aChannel Set to point to the created Logical Channel
   101 
   102   @return KErrNone if successful, otherwise one of the other system wide error codes.
   103 */
   104 TInt DCryptoLddChannelFactory::Create(DLogicalChannelBase*& aChannel)
   105 	{
   106 	TRACE_FUNCTION("Create");
   107     aChannel=new DCryptoLddChannel;
   108     if(!aChannel)
   109         return KErrNoMemory;
   110 
   111     return KErrNone;
   112 	}
   113 
   114 
   115 //
   116 // Logical Channel
   117 //
   118 
   119 /**
   120   Constructor
   121 */
   122 DCryptoLddChannel::DCryptoLddChannel()
   123     : iLddChanRandom(*this),
   124 	  iLddChanAes(*this)
   125 	{
   126 	TRACE_FUNCTION("DCryptoLddChannel");
   127     // Get pointer to client thread's DThread object
   128     iClient=&Kern::CurrentThread();
   129 
   130     // Open a reference on client thread so its control block can't disappear until
   131     // this driver has finished with it.
   132     // Note, this call to Open() can't fail since it is the thread we are currently running in.
   133     iClient->Open();
   134     }
   135 
   136 
   137 /**
   138   Destructor
   139 */
   140 DCryptoLddChannel::~DCryptoLddChannel()
   141     {
   142 	TRACE_FUNCTION("~DCryptoLddChannel");
   143     // Cancel all processing that we may be doing
   144     DoCancel(RCryptoDriver::EAllRequests);
   145     // Close our reference on the client thread
   146     Kern::SafeClose((DObject*&)iClient,NULL);
   147     }
   148 
   149 
   150 /**
   151   Second stage constructor called by the kernel's device driver framework.
   152   This is called in the context of the user thread (client) which requested the creation
   153   of the Logical Channel (e.g. through a call to RBusLogicalChannel::DoCreate())
   154   The thread is in a critical section.
   155 
   156   @param aUnit The unit argument supplied by the client to RBusLogicalChannel::DoCreate()
   157   @param aInfo The info argument supplied by the client to RBusLogicalChannel::DoCreate()
   158   @param aVer The version argument supplied by the client to RBusLogicalChannel::DoCreate()
   159 
   160   @return KErrNone if successful, otherwise one of the other system wide error codes.
   161 */
   162 TInt DCryptoLddChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& aVer)
   163     {
   164 	TRACE_FUNCTION("DoCreate");
   165     // Check Platform Security capabilities of client thread (if required).
   166     //
   167     // Here we handle the simple case where:
   168     // 1. The device driver can only have one client thread
   169     // 2. The security policy is the binary all-or-nothing policy.
   170     // E.g. "If you have the right capability you can do anything with the driver
   171     // and if you don't have the capability you can't do anything"
   172     // 
   173     // If only some functionality of the driver is restricted, then the security check should
   174     // go elsewhere. E.g. in DoRequest/DoControl. In that case Kern::CurrentThreadHasCapability
   175     // shouldn't be used because the 'current thread' isn't the client.
   176     //
   177     // In this example we do a check here for ECapability_None (which always passes)...
   178     if(!Kern::CurrentThreadHasCapability(ECapability_None,__PLATSEC_DIAGNOSTIC_STRING("Checked by DRIVER1")))
   179         return KErrPermissionDenied;
   180      
   181     // Check version
   182     if (!Kern::QueryVersionSupported(RCryptoDriver::VersionRequired(),aVer))
   183         return KErrNotSupported;
   184 
   185      // Give PDD a pointer to this channel
   186     PddChan()->iCryptoLddChannel = this;
   187 
   188     // Setup LDD for receiving client messages.
   189     SetDfcQ(PddChan()->DfcQue());
   190     iMsgQ.Receive();
   191 
   192     // Done
   193     return KErrNone;
   194     }
   195 
   196 
   197 /**
   198   Called when a user thread requests a handle to this channel.
   199 */
   200 TInt DCryptoLddChannel::RequestUserHandle(DThread* aThread, TOwnerType aType)
   201     {
   202 	TRACE_FUNCTION("RequestUserHandle");
   203     // Make sure that only our client can get a handle
   204     if (aType!=EOwnerThread || aThread!=iClient)
   205         return KErrAccessDenied;
   206     return KErrNone;
   207     }
   208 
   209 
   210 /**
   211   Process a message for this logical channel.
   212   This function is called in the context of a DFC thread.
   213 
   214   @param aMessage The message to process.
   215      The iValue member of this distinguishes the message type:
   216      iValue==ECloseMsg, channel close message
   217      iValue==KMaxTInt, a 'DoCancel' message
   218      iValue>=0, a 'DoControl' message with function number equal to iValue
   219      iValue<0, a 'DoRequest' message with function number equal to ~iValue
   220 */
   221 void DCryptoLddChannel::HandleMsg(TMessageBase* aMsg)
   222     {
   223 	TRACE_FUNCTION("HandleMsg");
   224     TThreadMessage& m=*(TThreadMessage*)aMsg;
   225 
   226     // Get message type
   227     TInt id=m.iValue;
   228 
   229     // Decode the message type and dispatch it to the relevent handler function...
   230     
   231     if (id==(TInt)ECloseMsg)
   232         {
   233         // Channel Close
   234         DoCancel(RCryptoDriver::EAllRequests);
   235         m.Complete(KErrNone, EFalse);
   236         return;
   237         }
   238 
   239     if (id==KMaxTInt)
   240         {
   241         // DoCancel
   242         DoCancel(m.Int0());
   243         m.Complete(KErrNone,ETrue);
   244         return;
   245         }
   246 
   247     if (id<0)
   248         {
   249         // DoRequest
   250         TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
   251         TInt r=DoRequest(~id,pS,m.Ptr1(),m.Ptr2());
   252         if (r!=KErrNone)
   253             Kern::RequestComplete(iClient,pS,r);
   254         m.Complete(KErrNone,ETrue);
   255         }
   256     else
   257         {
   258         // DoControl
   259         TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
   260         m.Complete(r,ETrue);
   261         }
   262     }
   263 
   264 /**
   265   Process synchronous 'control' requests
   266 */
   267 TInt DCryptoLddChannel::DoControl(TInt aFunction, TAny* a1, TAny *)
   268     {
   269 	TRACE_FUNCTION("DoControl");
   270     TInt r;
   271 
   272     switch (aFunction)
   273         {
   274         case RCryptoDriver::EGetHwVersions:
   275             r = GetHwVersions((TDes8*)a1);
   276             break;
   277 
   278         case RCryptoDriver::EGetConfig:
   279             r = GetConfig((TDes8*)a1);
   280             break;
   281 
   282         case RCryptoDriver::ESetConfig:
   283             r = SetConfig((const TDesC8*)a1);
   284             break;
   285 
   286         case RCryptoDriver::EAesSetConfig:
   287             r = iLddChanAes.SetAesConfig((const TDesC8*)a1);
   288             break;
   289 
   290         default:
   291             r=KErrNotSupported;
   292             break;
   293         }
   294 
   295     return r;
   296     }
   297 
   298 
   299 /**
   300   Process asynchronous requests
   301 */
   302 TInt DCryptoLddChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
   303     {
   304 	TRACE_FUNCTION("DoRequest");
   305     (void)a2; // a2 not used in this example
   306 
   307     TInt r;
   308 
   309     switch(aReqNo)
   310         {
   311         case RCryptoDriver::ERandom:
   312 			r=iLddChanRandom.Random(aStatus,(TDes8*)a1);
   313             break;
   314 
   315         case RCryptoDriver::EAesWrite:
   316 			r=iLddChanAes.AesWrite(aStatus,(TDesC8*)a1);
   317             break;
   318 
   319         case RCryptoDriver::EAesRead:
   320 			r=iLddChanAes.AesRead(aStatus,(TDes8*)a1, (TUint32)a2);
   321             break;
   322 
   323         default:
   324             r=KErrNotSupported;
   325             break;
   326         }
   327 
   328     return r;
   329     }
   330 
   331 
   332 /**
   333   Process cancelling of asynchronous requests
   334 */
   335 void DCryptoLddChannel::DoCancel(TUint aMask)
   336     {
   337 	TRACE_FUNCTION("DoCancel");
   338     if(aMask&(1<<RCryptoDriver::ERandom))
   339 		{
   340 		iLddChanRandom.RandomCancel();
   341 		}
   342 	
   343     if(aMask&(1<<RCryptoDriver::EAesRead))
   344 		{
   345         iLddChanAes.CancelRead();
   346 		}
   347 
   348     if(aMask&(1<<RCryptoDriver::EAesWrite))
   349 		{
   350         iLddChanAes.CancelWrite();
   351 		}
   352 	
   353     }
   354 
   355 
   356 /**
   357   Process a GetHwVersions control message. This writes the crypto h/w versions to a
   358   RCryptoDriver::THwVersionsBuf supplied by the client.
   359 */
   360 TInt DCryptoLddChannel::GetHwVersions(TDes8* aHwVersionsBuf) const
   361     {
   362 	TRACE_FUNCTION("GetHwVersions");
   363     // Create a structure giving the current configuration
   364     RCryptoDriver::THwVersions versions;
   365 	
   366 	PddChan()->GetHwVersions(versions);
   367 
   368     // Write the config to the client
   369     TPtrC8 ptr((const TUint8*)&versions,sizeof(versions));
   370     return Kern::ThreadDesWrite(iClient,aHwVersionsBuf,ptr,0,KTruncateToMaxLength,NULL);
   371     }
   372 
   373 //
   374 // Functions for processing configuration control messages
   375 //
   376 
   377 /**
   378   Process a GetConfig control message. This writes the current driver configuration to a
   379   RCryptoDriver::TConfigBuf supplied by the client.
   380 */
   381 TInt DCryptoLddChannel::GetConfig(TDes8* aConfigBuf) const
   382     {
   383 	TRACE_FUNCTION("GetConfig");
   384     // Create a structure giving the current configuration
   385     RCryptoDriver::TConfig config;
   386     CurrentConfig(config);
   387 
   388     // Write the config to the client
   389     TPtrC8 ptr((const TUint8*)&config,sizeof(config));
   390     return Kern::ThreadDesWrite(iClient,aConfigBuf,ptr,0,KTruncateToMaxLength,NULL);
   391     }
   392 
   393 /**
   394   Process a SetConfig control message. This sets the driver configuration using a
   395   RCryptoDriver::TConfigBuf supplied by the client.
   396 */
   397 TInt DCryptoLddChannel::SetConfig(const TDesC8* aConfigBuf)
   398     {
   399 	TRACE_FUNCTION("SetConfig");
   400     // Don't allow configuration changes whilst we're busy
   401 	//    if(iSendDataStatus || iReceiveDataStatus)
   402 	//        return KErrInUse;
   403 
   404     // Create a config structure.
   405     RCryptoDriver::TConfig config;
   406     CurrentConfig(config);
   407 
   408     // Note: We have filled config with the current settings, this is to allow
   409     // backwards compatibility when a client gives us an old (and shorter) version
   410     // of the config structure.
   411 
   412     // Read the config structure from client
   413     TPtr8 ptr((TUint8*)&config,sizeof(config));
   414     TInt r=Kern::ThreadDesRead(iClient,aConfigBuf,ptr,0);
   415     if(r!=KErrNone)
   416         return r;
   417 
   418     // Use config data to setup the driver. Checking that parameters which aren't settable
   419     // either contain the correct values or are zero (meaning 'default')
   420 	r=PddChan()->SetFakeDriverSetting(config.iFakeDriverSetting);
   421     if(r!=KErrNone)
   422         return r;
   423 
   424     return r;
   425     }
   426 
   427 
   428 /**
   429   Fill a TConfig with the driver's current configuration.
   430 */
   431 void DCryptoLddChannel::CurrentConfig(RCryptoDriver::TConfig& aConfig) const
   432     {
   433 	TRACE_FUNCTION("TConfig");
   434     aConfig.iFakeDriverSetting = PddChan()->FakeDriverSetting();
   435     }
   436 
   437 
   438 
   439 //
   440 // Functions for processing 'Random'
   441 //
   442 
   443 DLddChanRandom::DLddChanRandom(DCryptoLddChannel &aParent)
   444 	: iParent(aParent)
   445 	{
   446 	TRACE_FUNCTION("DLddChanRandom");
   447 	}
   448 
   449 
   450 /**
   451   Start processing a Random request.
   452 */
   453 TInt DLddChanRandom::Random(TRequestStatus* aStatus,TDes8* aPtr)
   454     {
   455 	TRACE_FUNCTION("Random");
   456     // Check that a 'Random' isn't already in progress
   457     if(iRandomStatus)
   458         {
   459         Kern::ThreadKill(iParent.iClient,EExitPanic,ERequestAlreadyPending,KCryptoPanicCategory);
   460         return KErrInUse;
   461         }
   462 
   463 	// We only support a single outstanding Random request in this LDD
   464 	// channel, but the PDD supports multiple requests.
   465 
   466     // Save the client request status and descriptor
   467     iRandomStatus = aStatus;
   468     iRandomDescriptor = aPtr;
   469 
   470 	// Retrieve user request length (ie. CURRENT length of user descriptor) into iRequestLength
   471 	TInt tmp;
   472 	TUint8 *tmp2;
   473 	TInt r=Kern::ThreadGetDesInfo(iParent.iClient, iRandomDescriptor, iRequestLength, tmp, tmp2, ETrue);
   474 	if(r != KErrNone)
   475 		{
   476 		return r;
   477  		}
   478 
   479 	// Set current offset into user descriptor
   480 	iCurrentIndex = 0;
   481 
   482 	iJob = iParent.PddChan()->GetJobRandom();
   483 
   484 	// Setup PDD job
   485 	iJob->SetDetails(&iParent.LddFactory()->iJSRandom, this, iRequestLength);
   486 	// Register it, which will also (maybe later) call DoSlice to run it
   487 	iParent.LddFactory()->iJSRandom.ScheduleJob(iJob);
   488 		
   489 	return KErrNone;
   490     }
   491 
   492 
   493 
   494 TInt DLddChanRandom::DataRequired()
   495 	{
   496 	TRACE_FUNCTION("DataRequired");
   497 	return KErrNone; // We never pass data to the h/w...
   498 	}
   499 
   500 TInt DLddChanRandom::DataAvailable()
   501 	{
   502 	TRACE_FUNCTION("DataAvailable");
   503 	//	Kern::Printf("DLddChanRandom::DataAvailable()");
   504 	TInt r = KErrNone;
   505 	
   506 	TUint8 *buf;
   507 	TUint32 bufLen;
   508 	TBool check = ETrue;
   509 	while(check)
   510 		{
   511 		iJob->GetFromPddBuffer(buf, bufLen, check);
   512 		if(bufLen)
   513 			{
   514 			TInt required = iRequestLength - iCurrentIndex;
   515 			TInt toTransfer = bufLen;
   516 			if(toTransfer > required)
   517 				{
   518 				toTransfer = required;
   519 				}
   520 			// Copy the current buffer to user land
   521 			TPtr8 des(buf, toTransfer, toTransfer);
   522 			r=Kern::ThreadDesWrite(iParent.iClient, iRandomDescriptor, des, iCurrentIndex);
   523 			if(r != KErrNone)
   524 				{
   525 				break;
   526 				}
   527 			
   528 			// Update our index into the user descriptor
   529 			iCurrentIndex += toTransfer;
   530 
   531 			// Update h/w with number of bytes actually read
   532 			iJob->BytesReadFromPdd(toTransfer);
   533 
   534 			if(toTransfer != bufLen)
   535 				{
   536 				// We did not read all the available data, so do not
   537 				// re-query h/w
   538 				check = EFalse;
   539 				}
   540 			}
   541 		};
   542 
   543 	return r;
   544 	}
   545 
   546 void DLddChanRandom::JobComplete(TInt aResult)
   547 	{
   548 	TRACE_FUNCTION("JobComplete");
   549 	if(iRandomStatus)
   550 		{
   551 		// Finished with client descriptor, so NULL it to help detect coding errors
   552 		iRandomDescriptor = NULL;
   553 		// Complete client's request
   554 		Kern::RequestComplete(iParent.iClient,iRandomStatus, aResult);
   555 		}
   556 	}
   557 
   558 
   559 /**
   560   Cancel a Random request.
   561 */
   562 void DLddChanRandom::RandomCancel()
   563     {
   564 	TRACE_FUNCTION("RandomCancel");
   565     if(iRandomStatus)
   566         {
   567         // Tell PDD to stop processing the request
   568         iParent.LddFactory()->iJSRandom.DeScheduleJob(iParent.PddChan()->GetJobRandom());
   569         // Finished with client descriptor, so NULL it to help detect coding errors
   570         iRandomDescriptor = NULL;
   571         // Complete clients request
   572         Kern::RequestComplete(iParent.iClient,iRandomStatus,KErrCancel);
   573         }
   574     }
   575 
   576 //
   577 // Functions for processing 'Aes'
   578 //
   579 
   580 DLddChanAes::DLddChanAes(DCryptoLddChannel &aParent)
   581 	: iParent(aParent)
   582 	{
   583 	TRACE_FUNCTION("DLddChanAes");
   584 	}
   585 
   586 
   587 TInt DLddChanAes::SetAesConfig(const TDesC8* aConfigBuf)
   588 	{
   589 	TRACE_FUNCTION("SetAesConfig");
   590 	// Note we need to validate arguments kernel side otherwise
   591 	// someone could easily crash the kernel...
   592 
   593 	RCryptoDriver::TAesConfig config;
   594     // Read the config structure from client
   595     TPtr8 ptr((TUint8*)&config,sizeof(config));
   596     TInt r=Kern::ThreadDesRead(iParent.iClient,aConfigBuf,ptr,0);
   597     if(r!=KErrNone)
   598 		{
   599 		return r;
   600 		}
   601 
   602 	//	Kern::Printf("iEncrypt = 0x%x",config.iEncrypt);
   603 	//	Kern::Printf("iMode = 0x%x",config.iMode);
   604 	//	Kern::Printf("iKey = 0x%x",config.iKey);
   605 	//	Kern::Printf("iIV = 0x%x",config.iIV);
   606 
   607 
   608 	// Remember direction
   609 	iEncrypt = config.iEncrypt;
   610 
   611 	// Remember mode
   612 	iMode = config.iMode;
   613 
   614 	//
   615 	// Handle key
   616 	//
   617 
   618 	// Retrieve user key length into iKeyLengthBytes
   619 	TInt tmp;
   620 	TUint8 *tmp2;
   621 	r=Kern::ThreadGetDesInfo(iParent.iClient, (TAny *)config.iKey, iKeyLengthBytes, tmp, tmp2, EFalse);
   622     if(r!=KErrNone)
   623 		{
   624 		return r;
   625 		}
   626 
   627 	HBuf8 *embeddedKeyData = 0;
   628 	if(iKeyLengthBytes == 4)
   629 		{
   630 		// Some form of embedded key so value is a 32 bit handle
   631 		TPckgBuf<TKeyHandle> keyHandlePkg;	
   632 		
   633 		r=Kern::ThreadDesRead(iParent.iClient, (TAny *)config.iKey, keyHandlePkg, 0);
   634 		if(r != KErrNone)
   635 			{
   636 			return r;
   637 			}
   638 
   639 		TKeyHandle &keyHandle = keyHandlePkg();
   640 
   641 		r = HwKeyStore::ExtractKey(iParent.iClient->iOwningProcess, keyHandle, 0 /*operation*/, embeddedKeyData);
   642 		if(r != KErrNone)
   643 			{
   644 			return r;
   645 			}
   646 
   647 		// Update key length
   648 		iKeyLengthBytes = embeddedKeyData->Length();
   649 		}
   650 
   651 	switch(iKeyLengthBytes)
   652 		{
   653 		case 16: // 128 bits
   654 			break;
   655 		case 24: // 192 bits
   656 			break;
   657 		case 32: // 256 bits
   658 			break;
   659 		default: // Illegal length
   660 			if(embeddedKeyData) delete embeddedKeyData;
   661 			return KErrArgument;
   662 		}
   663 
   664 	// Make sure iJob is valid before we use it
   665 	iJob = iParent.PddChan()->GetJobAes();
   666 
   667 	TUint8 *keyBuffer = iJob->GetKeyBuffer();
   668 	TPtr8 des(keyBuffer, iKeyLengthBytes);
   669 
   670 	if(embeddedKeyData)
   671 		{
   672 		// Copy embedded key to PDD
   673 		des = *embeddedKeyData;
   674 		delete embeddedKeyData;
   675 		embeddedKeyData = 0;
   676 		}
   677 	else
   678 		{
   679 		// Retrieve key from user
   680 		r=Kern::ThreadDesRead(iParent.iClient, (TAny *)config.iKey, des, 0);
   681 		if(r != KErrNone)
   682 			{
   683 			return r;
   684 			}
   685 		}
   686 	
   687 		
   688 	//
   689 	// Handle IV
   690 	//
   691 
   692 	// Retrieve IV length
   693 	TInt ivLength;
   694 	r=Kern::ThreadGetDesInfo(iParent.iClient, (TAny *)config.iIV, ivLength, tmp, tmp2, EFalse);
   695 	//	Kern::Printf("DLddChanAes::SetAesConfig r=%d 5",r);
   696 	if(r != KErrNone)
   697 		{
   698 		return r;
   699 		}
   700 	
   701 	if((ivLength != 0) && (ivLength != 16))
   702 		{
   703 		return KErrArgument;
   704 		}
   705 
   706 	if(ivLength == 16)
   707 		{
   708 		TUint8 *ivBuffer = iJob->GetIVBuffer();
   709 		TPtr8 des(ivBuffer, 16);
   710 		r=Kern::ThreadDesRead(iParent.iClient, (TAny *)config.iIV, des, 0);
   711 		if(r != KErrNone)
   712 			{
   713 			return r;
   714 			}
   715 		}
   716 
   717 
   718 	// Set details
   719 	r = iJob->SetDetails(&iParent.LddFactory()->iJSAes, this, iEncrypt, iKeyLengthBytes, iMode);
   720 	if(r != KErrNone)
   721 		{
   722 		return r;
   723 		}
   724 	
   725 	return KErrNone;
   726 	}
   727 
   728 /**
   729   Start processing a Aes request.
   730 */
   731 TInt DLddChanAes::AesWrite(TRequestStatus* aStatus, TDesC8* aPtr)
   732     {
   733 	TRACE_FUNCTION("AesWrite");
   734 	//	Kern::Printf("DLddChanAes::AesWrite");
   735     // Check that an Aes Write isn't already in progress
   736     if(iAesWriteStatus)
   737         {
   738         Kern::ThreadKill(iParent.iClient,EExitPanic,ERequestAlreadyPending,KCryptoPanicCategory);
   739         return KErrInUse;
   740         }
   741 
   742 	// We only support a single outstanding Aes Write request in this LDD
   743 	// channel, but the PDD supports multiple requests.
   744 
   745     // Save the client request status and descriptor
   746     iAesWriteStatus = aStatus;
   747     iAesWriteDescriptor = aPtr;
   748 
   749 
   750 	// Retrieve user request length (ie. current length of user descriptor) into iRequestLength
   751 	TInt maxLen;
   752 	TUint8 *aesWriteDescriptorBufferRaw;
   753 	TInt r=Kern::ThreadGetDesInfo(iParent.iClient, iAesWriteDescriptor, iWriteRequestLength, maxLen, aesWriteDescriptorBufferRaw, EFalse);
   754 	if(r != KErrNone)
   755 		{
   756 		iAesWriteStatus = 0;
   757 		return r;
   758  		}
   759 
   760 	// Set current offset into user descriptor
   761 	iCurrentUserWriteIndex = 0;
   762 
   763 	// Make sure iJob is valid before we use it
   764 	iJob = iParent.PddChan()->GetJobAes();
   765 
   766 
   767 #ifdef HW_PERF_CHECK
   768 	iJob->HwPerfCheck();
   769 #else
   770 	// Feed some data to the PDD
   771 	r = DataRequired(); // Fake PDD callback to get data from us.
   772 	if(r != KErrNone)
   773 		{
   774 		iAesWriteStatus = 0;
   775 		return r;
   776  		}
   777 
   778 	// Make sure job is not stalled, and maybe (re)add to job list.
   779 	iJob->Resume();
   780 #endif
   781 	
   782 	return KErrNone;
   783     }
   784 
   785 
   786 TInt DLddChanAes::AesRead(TRequestStatus* aStatus, TDes8* aPtr, TUint32 aLength)
   787     {
   788 	TRACE_FUNCTION("AesRead");
   789 	//	Kern::Printf("DLddChanAes::AesRead");
   790     // Check that an Aes Read isn't already in progress
   791     if(iAesReadStatus)
   792         {
   793         Kern::ThreadKill(iParent.iClient,EExitPanic,ERequestAlreadyPending,KCryptoPanicCategory);
   794         return KErrInUse;
   795         }
   796 
   797 	// We only support a single outstanding Aes Read request in this LDD
   798 	// channel, but the PDD supports multiple requests.
   799 
   800     // Save the client request status and descriptor
   801     iAesReadStatus = aStatus;
   802     iAesReadDescriptor = aPtr;
   803 	iReadRequestLength = aLength;
   804 
   805 	// Retrieve user request length (ie. current length of user descriptor) into iRequestLength
   806 	//	TInt iOriginalUserReadDescLength;
   807 	TUint8 *aesReadDescriptorBufferRaw;
   808 	TInt maxLen;
   809 	TInt r=Kern::ThreadGetDesInfo(iParent.iClient, iAesReadDescriptor, iOriginalUserReadDescLength, maxLen, aesReadDescriptorBufferRaw, ETrue);
   810 	if(r != KErrNone)
   811 		{
   812 		iAesReadStatus = 0;
   813 		return r;
   814  		}
   815 
   816 	if(iReadRequestLength > (maxLen - iOriginalUserReadDescLength))
   817 		{
   818 		return KErrArgument;
   819 		}
   820 
   821 	// Set current offset into user descriptor
   822 	iCurrentUserReadIndex = 0;
   823 
   824 	// Tell PDD our request length so it can optimse returning the data to us.
   825 	iJob->NotifyReadRequestLength(iReadRequestLength);
   826 	
   827 
   828 #ifndef HW_PERF_CHECK
   829 	// Make sure iJob is valid before we use it
   830 	iJob = iParent.PddChan()->GetJobAes();
   831 
   832 	// Process any data already available
   833 	r = DataAvailable(); // Fake PDD callback to read data from PDD
   834 	if(r != KErrNone)
   835 		{
   836 		iAesReadStatus = 0;
   837 		return r;
   838  		}
   839 
   840 	// Make sure job is not stalled (and maybe re-add to job list) We
   841 	// do this even if we completely satisified the read from the PDD
   842 	// buffer because a write might be waiting for space in the
   843 	// buffer...
   844 	iJob->Resume();
   845 #endif
   846 
   847 	return KErrNone;
   848 	}
   849 
   850 
   851 
   852 TInt DLddChanAes::DataRequired()
   853 	{
   854 	TRACE_FUNCTION("DataRequired");
   855 	//	Kern::Printf("DLddChanAes::DataRequired");
   856 	if(!iAesWriteStatus)
   857 		{
   858 		return KErrNone;
   859 		}
   860 	
   861 	TBool moreSpace = ETrue;
   862 	TInt toWrite = (iWriteRequestLength - iCurrentUserWriteIndex);
   863 	while(toWrite && moreSpace)
   864 		{
   865 		// Get details of PDD write buffer
   866 		TUint8 *pddBuf; // always valid, though pddBufLen might be 0
   867 		TUint32 pddBufLen; // maybe 0
   868 		iJob->GetToPddBuffer(pddBuf, pddBufLen, moreSpace);
   869 
   870 		if(toWrite > pddBufLen)
   871 			{
   872 			toWrite = pddBufLen;
   873 			}
   874 
   875 		// Make sure there is some data to write
   876 		if(toWrite == 0)
   877 			{
   878 			break;
   879 			}
   880 
   881 		TPtr8 des(pddBuf, toWrite);
   882 		TInt r=Kern::ThreadDesRead(iParent.iClient, iAesWriteDescriptor, des, iCurrentUserWriteIndex);
   883 		//TInt r = 0;
   884 		if(r!=KErrNone)
   885 			return r;
   886 		iCurrentUserWriteIndex += toWrite;
   887 		// Tell the PDD how many bytes we wrote to it.
   888 		// If we wrote data, and the job was not already queued, the
   889 		// PDD will call ScheduleJob for it.
   890 		iJob->BytesWrittenToPdd(toWrite);
   891 
   892 		// Update count of bytes left to write
   893 		toWrite = (iWriteRequestLength - iCurrentUserWriteIndex);
   894 		};
   895 
   896 	if((iWriteRequestLength - iCurrentUserWriteIndex) <= 0)
   897 		{
   898 		// Write request is complete
   899 		// Finished with client descriptor, so NULL it to help detect coding errors
   900 		iAesWriteDescriptor = NULL;
   901 		// Complete client's request
   902 		Kern::RequestComplete(iParent.iClient,iAesWriteStatus, KErrNone);
   903 		return KErrNone;
   904 		}
   905 
   906 	return KErrNone;
   907 	}
   908 
   909 TInt DLddChanAes::DataAvailable()
   910 	{
   911 	TRACE_FUNCTION("DataAvailable");
   912 	//	Kern::Printf("DLddChanAes::DataAvailable()");
   913 
   914 	if(!iAesReadStatus)
   915 		{
   916 		return KErrNone;
   917 		}
   918 
   919 	TInt r = KErrNone;
   920 
   921 	TUint8 *buf;
   922 	TUint32 bufLen;
   923 	TBool check = ETrue;
   924 	while(check)
   925 		{
   926 		iJob->GetFromPddBuffer(buf, bufLen, check);
   927 		if(bufLen)
   928 			{
   929 			TInt required = iReadRequestLength - iCurrentUserReadIndex;
   930 			TInt toTransfer = bufLen;
   931 			if(toTransfer > required)
   932 				{
   933 				toTransfer = required;
   934 				}
   935 			// Copy the current buffer to user land
   936 			TPtr8 des(buf, toTransfer, toTransfer);
   937 			r=Kern::ThreadDesWrite(iParent.iClient, iAesReadDescriptor, des, iOriginalUserReadDescLength + iCurrentUserReadIndex);
   938 			//r  = 0;
   939 			if(r != KErrNone)
   940 				{
   941 				break;
   942 				}
   943 			
   944 			// Update our index into the user descriptor
   945 			iCurrentUserReadIndex += toTransfer;
   946 
   947 			// Update h/w with number of bytes actually read
   948 			iJob->BytesReadFromPdd(toTransfer);
   949 
   950 			if(toTransfer != bufLen)
   951 				{
   952 				// We did not read all the available data, so do not
   953 				// re-query h/w
   954 				check = EFalse;
   955 				}
   956 			}
   957 		};
   958 
   959 	if((iReadRequestLength - iCurrentUserReadIndex) <= 0)
   960 		{
   961 		// Read request is complete
   962 		// Finished with client descriptor, so NULL it to help detect coding errors
   963 		iAesReadDescriptor = NULL;
   964 		// Complete client's request
   965 		Kern::RequestComplete(iParent.iClient,iAesReadStatus, KErrNone);
   966 		return KErrNone;
   967 		}
   968 
   969 	return KErrNone;
   970 	}
   971 
   972 
   973 
   974 
   975 
   976 /**
   977   Called by PDD from a DFC to indicate that a Aes operation has completed.
   978 */
   979 void DLddChanAes::JobComplete(TInt aResult)
   980 	{
   981 	TRACE_FUNCTION("JobComplete");
   982 	// Normally not used for AES, instead the job keeps running and
   983 	// DataAvailable/DataRequired complete the AesRead/AesWrite
   984 	// requests.
   985 	// 
   986 	// Will be called if xfer to/from user space fails (or if another
   987 	// fatal error occurs).
   988     if(iAesReadStatus)
   989         {
   990         // Finished with client descriptor, so NULL it to help detect coding errors
   991         iAesReadDescriptor = NULL;
   992         // Complete clients request (nb following call set iAesReadStatus to 0)
   993         Kern::RequestComplete(iParent.iClient,iAesReadStatus, aResult);
   994         }
   995     if(iAesWriteStatus)
   996         {
   997         // Finished with client descriptor, so NULL it to help detect coding errors
   998         iAesWriteDescriptor = NULL;
   999         // Complete clients request (nb following call set iAesWriteStatus to 0)
  1000         Kern::RequestComplete(iParent.iClient,iAesWriteStatus, aResult);
  1001         }
  1002 	}
  1003 
  1004 
  1005 
  1006 /**
  1007   Cancel a Aes Read request.
  1008 */
  1009 void DLddChanAes::CancelRead()
  1010     {
  1011 	TRACE_FUNCTION("CancelRead");
  1012     if(iAesReadStatus)
  1013         {
  1014         // Finished with client descriptor, so NULL it to help detect coding errors
  1015         iAesReadDescriptor = NULL;
  1016         // Complete clients request (nb following call set iAesReadStatus to 0)
  1017         Kern::RequestComplete(iParent.iClient,iAesReadStatus,KErrCancel);
  1018         }
  1019     }
  1020 
  1021 /**
  1022   Cancel a Aes Write request.
  1023 */
  1024 void DLddChanAes::CancelWrite()
  1025     {
  1026 	TRACE_FUNCTION("CancelWrite");
  1027     if(iAesWriteStatus)
  1028         {
  1029         // Finished with client descriptor, so NULL it to help detect coding errors
  1030         iAesWriteDescriptor = NULL;
  1031         // Complete clients request (nb following call set iAesWriteStatus to 0)
  1032         Kern::RequestComplete(iParent.iClient,iAesWriteStatus,KErrCancel);
  1033         }
  1034     }
  1035 
  1036 // End of file