cryptoplugins/cryptospiplugins/test/h4drv/crypto_h4/cryptoldd.cpp
changeset 8 35751d3474b7
child 15 da2ae96f639b
equal deleted inserted replaced
2:675a964f4eb5 8:35751d3474b7
       
     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