os/security/cryptoplugins/cryptospiplugins/test/h4drv/crypto_h4/tcrypto.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
/*
sl@0
     2
* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     3
* All rights reserved.
sl@0
     4
* This component and the accompanying materials are made available
sl@0
     5
* under the terms of the License "Eclipse Public License v1.0"
sl@0
     6
* which accompanies this distribution, and is available
sl@0
     7
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     8
*
sl@0
     9
* Initial Contributors:
sl@0
    10
* Nokia Corporation - initial contribution.
sl@0
    11
*
sl@0
    12
* Contributors:
sl@0
    13
*
sl@0
    14
* Description: 
sl@0
    15
*
sl@0
    16
*/
sl@0
    17
sl@0
    18
sl@0
    19
/**
sl@0
    20
 @file
sl@0
    21
 @internalComponent
sl@0
    22
 @released
sl@0
    23
*/
sl@0
    24
#include "cryptodriver.h"
sl@0
    25
#include <e32base.h>
sl@0
    26
#include <e32cons.h>
sl@0
    27
#include <e32test.h>
sl@0
    28
#include <e32debug.h>
sl@0
    29
#include <rijndael.h>
sl@0
    30
#include <cbcmode.h>
sl@0
    31
#include <padding.h>
sl@0
    32
#include <bufferedtransformation.h>
sl@0
    33
#include <random.h>
sl@0
    34
#include <e32def_private.h>
sl@0
    35
sl@0
    36
_LIT(KTxtEPOC32EX,"tcrypto: mainL failed");
sl@0
    37
_LIT(KTxtPressAnyKey," [press any key]");
sl@0
    38
sl@0
    39
#define RNG_TESTS
sl@0
    40
//#define RNG_USE_SVR
sl@0
    41
//#define KEYLEN 16
sl@0
    42
#define KEYLEN 24
sl@0
    43
//#define KEYLEN 32
sl@0
    44
sl@0
    45
#define USE_CBCMODE
sl@0
    46
//#define DISABLE_AES_CHECKS
sl@0
    47
sl@0
    48
//#define PADDING_PKCS7
sl@0
    49
sl@0
    50
//#define BUFLEN 256
sl@0
    51
#define BUFLEN (256*16)
sl@0
    52
#define LOOPCOUNT 10000
sl@0
    53
sl@0
    54
sl@0
    55
// public
sl@0
    56
CConsoleBase* console; // write all your messages to this
sl@0
    57
sl@0
    58
// private
sl@0
    59
LOCAL_C void mainL();
sl@0
    60
sl@0
    61
GLDEF_C TInt E32Main() // main function called by E32
sl@0
    62
    {
sl@0
    63
	__UHEAP_MARK;
sl@0
    64
	CTrapCleanup* cleanup=CTrapCleanup::New(); // get clean-up stack
sl@0
    65
	TRAPD(error,mainL()); // more initialization, then do example
sl@0
    66
	__ASSERT_ALWAYS(!error,User::Panic(KTxtEPOC32EX,error));
sl@0
    67
	delete cleanup; // destroy clean-up stack
sl@0
    68
	__UHEAP_MARKEND;
sl@0
    69
	return 0; // and return
sl@0
    70
    }
sl@0
    71
sl@0
    72
LOCAL_D RTest test(_L("tcrypto"));
sl@0
    73
sl@0
    74
_LIT(KLddFileName,"cryptoldd.ldd");
sl@0
    75
_LIT(KPddFileName,"crypto.h4.pdd");
sl@0
    76
sl@0
    77
LOCAL_C void mainL() // initialize and call example code under cleanup stack
sl@0
    78
    {
sl@0
    79
#if 0
sl@0
    80
	test.Printf(KTxtPressAnyKey);
sl@0
    81
	test.Getch(); // get and ignore character
sl@0
    82
	test.Printf(_L("\n"));
sl@0
    83
#endif
sl@0
    84
sl@0
    85
	test.Title();
sl@0
    86
sl@0
    87
	RDebug::Printf("Hello from user side\n");
sl@0
    88
	
sl@0
    89
sl@0
    90
    TInt r;
sl@0
    91
sl@0
    92
    test.Start(_L(" @SYMTestCaseID:SEC-CRYPTOSPI-CRYPTO-0001 Loading Physical Device "));
sl@0
    93
    r=User::LoadPhysicalDevice(KPddFileName);
sl@0
    94
    test(r==KErrNone || r==KErrAlreadyExists);
sl@0
    95
sl@0
    96
	test.Next(_L("Re-Loading Physical Device"));
sl@0
    97
	r=User::LoadPhysicalDevice(KPddFileName);
sl@0
    98
	test(r==KErrNone || r==KErrAlreadyExists);
sl@0
    99
sl@0
   100
    test.Next(_L("Loading Logical Device"));
sl@0
   101
    r=User::LoadLogicalDevice(KLddFileName);
sl@0
   102
    test(r==KErrNone || r==KErrAlreadyExists);
sl@0
   103
sl@0
   104
	test.Next(_L("Re-Loading Logical Device"));
sl@0
   105
	r=User::LoadLogicalDevice(KLddFileName);
sl@0
   106
	test(r==KErrNone || r==KErrAlreadyExists);
sl@0
   107
	
sl@0
   108
    test.Next(_L("Open Device"));
sl@0
   109
    RDevice device;
sl@0
   110
    r=device.Open(RCryptoDriver::Name());
sl@0
   111
    test(r==KErrNone);
sl@0
   112
sl@0
   113
    test.Next(_L("Get Device Capabilities"));
sl@0
   114
    RCryptoDriver::TCaps caps;
sl@0
   115
    TPckg<RCryptoDriver::TCaps>capsPckg(caps);
sl@0
   116
    capsPckg.FillZ(); // Zero 'caps' so we can tell if GetCaps has really filled it
sl@0
   117
    device.GetCaps(capsPckg);
sl@0
   118
    TVersion expectedVer(RCryptoDriver::VersionRequired());
sl@0
   119
    test(caps.iVersion.iMajor==expectedVer.iMajor);
sl@0
   120
    test(caps.iVersion.iMinor==expectedVer.iMinor);
sl@0
   121
    test(caps.iVersion.iBuild==expectedVer.iBuild);
sl@0
   122
sl@0
   123
	test.Next(_L("Close Device"));
sl@0
   124
    device.Close();
sl@0
   125
sl@0
   126
    test.Next(_L("Open Logical Channel"));
sl@0
   127
    RCryptoDriver ldd;
sl@0
   128
    r=ldd.Open();
sl@0
   129
    test(r==KErrNone);
sl@0
   130
sl@0
   131
	test.Next(_L("GetHwVersions"));
sl@0
   132
    RCryptoDriver::THwVersionsBuf hwVersionsBuf;
sl@0
   133
    hwVersionsBuf.FillZ(); // Zero 'config' so we can tell if GetConfig has really filled it
sl@0
   134
    r=ldd.GetHwVersions(hwVersionsBuf);
sl@0
   135
    test(r==KErrNone);
sl@0
   136
	test.Printf(_L("RNG h/w version 0x%x\n"), hwVersionsBuf().iRngHwVersion);
sl@0
   137
	test.Printf(_L("DES/3DES h/w version 0x%x\n"), hwVersionsBuf().iDes3DesHwVersion);
sl@0
   138
	test.Printf(_L("SHA1/MD5 h/w version 0x%x\n"), hwVersionsBuf().iSha1Md5HwVersion);
sl@0
   139
	test.Printf(_L("AES h/w version 0x%x\n"), hwVersionsBuf().iAesHwVersion);
sl@0
   140
	test.Printf(_L("PKA h/w version 0x%x\n"), hwVersionsBuf().iPkaHwVersion);
sl@0
   141
sl@0
   142
	test.Next(_L("GetConfig"));
sl@0
   143
    RCryptoDriver::TConfigBuf configBuf;
sl@0
   144
    configBuf.FillZ(); // Zero 'config' so we can tell if GetConfig has really filled it
sl@0
   145
    r=ldd.GetConfig(configBuf);
sl@0
   146
    test(r==KErrNone);
sl@0
   147
	
sl@0
   148
	{
sl@0
   149
	test.Next(_L("Open Logical Channel 2nd time"));
sl@0
   150
	RCryptoDriver lddB;
sl@0
   151
	r=lddB.Open();
sl@0
   152
	test(r==KErrNone);
sl@0
   153
	
sl@0
   154
	test.Next(_L("GetConfig"));
sl@0
   155
	RCryptoDriver::TConfigBuf configBuf;
sl@0
   156
	configBuf.FillZ(); // Zero 'config' so we can tell if GetConfig has really filled it
sl@0
   157
	r=lddB.GetConfig(configBuf);
sl@0
   158
	test(r==KErrNone);
sl@0
   159
	lddB.Close();
sl@0
   160
	}
sl@0
   161
	
sl@0
   162
    RCryptoDriver::TConfig& config=configBuf();
sl@0
   163
sl@0
   164
    test.Next(_L("SetConfig"));
sl@0
   165
    TInt setting = configBuf().iFakeDriverSetting+1;
sl@0
   166
    configBuf().iFakeDriverSetting = setting;
sl@0
   167
    r=ldd.SetConfig(configBuf); // Use SetConfig to change setting
sl@0
   168
    test(r==KErrNone);
sl@0
   169
sl@0
   170
    configBuf.FillZ();
sl@0
   171
    r=ldd.GetConfig(configBuf);
sl@0
   172
    test(r==KErrNone);
sl@0
   173
    test(configBuf().iFakeDriverSetting==setting);
sl@0
   174
sl@0
   175
    test.Next(_L("Check access by wrong client"));
sl@0
   176
    RCryptoDriver ldd2=ldd;
sl@0
   177
    r=ldd2.Duplicate(RThread(),EOwnerProcess);
sl@0
   178
    test(r==KErrAccessDenied);
sl@0
   179
sl@0
   180
    test.Next(_L("Check handle duplication"));
sl@0
   181
    ldd2=ldd;
sl@0
   182
    r=ldd2.Duplicate(RThread(),EOwnerThread);
sl@0
   183
    test(r==KErrNone);
sl@0
   184
    ldd2.Close();
sl@0
   185
sl@0
   186
	
sl@0
   187
    TRequestStatus status;
sl@0
   188
    TRequestStatus status2;
sl@0
   189
	TInt startCount;
sl@0
   190
	TInt endCount;
sl@0
   191
sl@0
   192
sl@0
   193
	{
sl@0
   194
    test.Next(_L("Random h/w use 2nd chan"));
sl@0
   195
	HBufC8 *hbuf = HBufC8::NewLC(20);
sl@0
   196
	TPtr8 buf = hbuf->Des();
sl@0
   197
	buf.SetLength(buf.MaxLength());
sl@0
   198
	ldd.Random(status,buf);
sl@0
   199
	User::WaitForRequest(status);
sl@0
   200
sl@0
   201
	test.Printf(_L("    Try 2nd chan"));
sl@0
   202
	RCryptoDriver lddB;
sl@0
   203
    r=lddB.Open();
sl@0
   204
    test(r==KErrNone);
sl@0
   205
	buf.SetLength(buf.MaxLength());
sl@0
   206
	lddB.Random(status,buf);
sl@0
   207
	User::WaitForRequest(status);
sl@0
   208
sl@0
   209
	test.Printf(_L("    Try re-using 1st chan\n"));
sl@0
   210
	buf.SetLength(buf.MaxLength());
sl@0
   211
	ldd.Random(status,buf);
sl@0
   212
	User::WaitForRequest(status);
sl@0
   213
sl@0
   214
	lddB.Close();
sl@0
   215
	CleanupStack::PopAndDestroy(hbuf);
sl@0
   216
	}
sl@0
   217
	
sl@0
   218
sl@0
   219
sl@0
   220
sl@0
   221
#ifdef RNG_TESTS
sl@0
   222
    test.Next(_L("Random (h/w)"));
sl@0
   223
#ifdef __MARM__
sl@0
   224
	HBufC8 *hbuf = HBufC8::NewLC(32768);
sl@0
   225
#else
sl@0
   226
	HBufC8 *hbuf = HBufC8::NewLC(1024);
sl@0
   227
#endif
sl@0
   228
	TPtr8 buf = hbuf->Des();
sl@0
   229
	buf.SetLength(buf.MaxLength());
sl@0
   230
	startCount = User::NTickCount();
sl@0
   231
	for(TInt i=0; i<100; ++i)
sl@0
   232
		{
sl@0
   233
		// Should discard existing contents of buf
sl@0
   234
		ldd.Random(status,buf);
sl@0
   235
		//	User::After(20);
sl@0
   236
		//	return;
sl@0
   237
		User::WaitForRequest(status);
sl@0
   238
		}
sl@0
   239
	endCount = User::NTickCount();
sl@0
   240
	test.Printf(_L("Duration in ticks (h/w) = %d\n"), endCount - startCount);
sl@0
   241
	
sl@0
   242
#ifndef __MARM__
sl@0
   243
	{
sl@0
   244
	TUint32 *p = (TUint32 *) &buf[0];
sl@0
   245
	test.Printf(_L("buf =\n    "));
sl@0
   246
	for(TInt i = 0 ; i<256; ++i)
sl@0
   247
		{
sl@0
   248
		if(i && (i%16 == 0))
sl@0
   249
			{
sl@0
   250
			test.Printf(_L("\n    "));
sl@0
   251
			}
sl@0
   252
		test.Printf(_L("%08x "), p[i]);
sl@0
   253
		}
sl@0
   254
	test.Printf(_L("\n"));
sl@0
   255
	}
sl@0
   256
	
sl@0
   257
#endif
sl@0
   258
	
sl@0
   259
	{
sl@0
   260
    test.Next(_L("Random (s/w)"));
sl@0
   261
#ifdef RNG_USE_SVR
sl@0
   262
 	RRandomSession rs;
sl@0
   263
	TRAPD(ret,rs.ConnectL());
sl@0
   264
	User::LeaveIfError(ret);
sl@0
   265
	CleanupClosePushL(rs);
sl@0
   266
#endif
sl@0
   267
sl@0
   268
	TInt startCount = User::NTickCount();
sl@0
   269
	for(TInt i=0; i<100; ++i)
sl@0
   270
		{
sl@0
   271
		// Should discard existing contents of buf
sl@0
   272
#ifdef RNG_USE_SVR
sl@0
   273
		User::LeaveIfError(rs.GetRandom(buf));
sl@0
   274
#else
sl@0
   275
		TRandom::RandomL(buf);
sl@0
   276
#endif
sl@0
   277
		}
sl@0
   278
	TInt endCount = User::NTickCount();
sl@0
   279
	test.Printf(_L("Duration in ticks (s/w) = %d\n"), endCount - startCount);
sl@0
   280
	
sl@0
   281
#ifdef RNG_USE_SVR
sl@0
   282
	CleanupStack::PopAndDestroy(&rs);
sl@0
   283
#endif
sl@0
   284
	}
sl@0
   285
	
sl@0
   286
sl@0
   287
#ifdef __MARM__
sl@0
   288
	const TInt end = 10;
sl@0
   289
#else
sl@0
   290
	const TInt end = 1;
sl@0
   291
#endif
sl@0
   292
sl@0
   293
	for(TInt i = 0 ; i<end; ++i)
sl@0
   294
		{
sl@0
   295
		test.Printf(_L("buf[%d] = 0x%x\n"), i, buf[i]);
sl@0
   296
		}
sl@0
   297
    r=status.Int();
sl@0
   298
    test(r==KErrNone);
sl@0
   299
sl@0
   300
	CleanupStack::PopAndDestroy(hbuf);
sl@0
   301
sl@0
   302
#endif
sl@0
   303
sl@0
   304
    test.Next(_L("Random - Generating key & IV for AES tests"));
sl@0
   305
	test.Printf(_L("Generating random key\n"));
sl@0
   306
	// Generate random 16 byte key
sl@0
   307
	TBuf8<KEYLEN> key;
sl@0
   308
	key.SetLength(key.MaxLength());
sl@0
   309
	ldd.Random(status, key);
sl@0
   310
	User::WaitForRequest(status);
sl@0
   311
	key[0] = 'K';
sl@0
   312
	key[1] = 'E';
sl@0
   313
	key[2] = 'Y';
sl@0
   314
	key[3] = '*';
sl@0
   315
	for(int z=4; z<KEYLEN; ++z) key[z] = z;
sl@0
   316
sl@0
   317
	test.Printf(_L("Generating random IV\n"));
sl@0
   318
	// Generate random 16 byte IV
sl@0
   319
	TBuf8<16> iv;
sl@0
   320
	iv.SetLength(iv.MaxLength());
sl@0
   321
	ldd.Random(status, iv);
sl@0
   322
	User::WaitForRequest(status);
sl@0
   323
	iv[0] = 'I';
sl@0
   324
	iv[1] = 'V';
sl@0
   325
	iv[2] = '*';
sl@0
   326
	iv[3] = '*';
sl@0
   327
sl@0
   328
	TBuf8<BUFLEN> plaintext;
sl@0
   329
	plaintext.SetLength(BUFLEN);
sl@0
   330
	plaintext[0] = 'P';
sl@0
   331
	plaintext[1] = 'L';
sl@0
   332
	plaintext[2] = 'A';
sl@0
   333
	plaintext[3] = 'I';
sl@0
   334
	plaintext[4] = 'N';
sl@0
   335
	plaintext.SetLength(BUFLEN);
sl@0
   336
	for(int i=0; i<BUFLEN; ++i)
sl@0
   337
		{
sl@0
   338
		plaintext[i] = i;
sl@0
   339
		}
sl@0
   340
	
sl@0
   341
sl@0
   342
sl@0
   343
    test.Next(_L("AES - S/W"));
sl@0
   344
sl@0
   345
#ifdef PADDING_PKCS7
sl@0
   346
	CPadding *pad = CPaddingPKCS7::NewLC(16);
sl@0
   347
#else
sl@0
   348
	CPadding *pad = CPaddingNone::NewLC(16);
sl@0
   349
#endif
sl@0
   350
sl@0
   351
#ifdef USE_CBCMODE
sl@0
   352
	// CBC
sl@0
   353
	test.Printf(_L("    CBC\n"));
sl@0
   354
	CAESEncryptor *rawaes = CAESEncryptor::NewLC(key); // pad, rawaes
sl@0
   355
	CModeCBCEncryptor *cbc = CModeCBCEncryptor::NewL(rawaes, iv);
sl@0
   356
	CleanupStack::Pop(rawaes); // pad
sl@0
   357
	CleanupStack::PushL(cbc);  // pad, cbc
sl@0
   358
sl@0
   359
	CBufferedEncryptor *aes = CBufferedEncryptor::NewL(cbc, pad);
sl@0
   360
	CleanupStack::Pop(cbc); // pad
sl@0
   361
	CleanupStack::Pop(pad); //
sl@0
   362
	CleanupStack::PushL(aes); //aes
sl@0
   363
#else
sl@0
   364
	// ECB
sl@0
   365
	test.Printf(_L("    ECB\n"));
sl@0
   366
	CAESEncryptor *rawaes = CAESEncryptor::NewLC(key); // pad, rawaes
sl@0
   367
	CBufferedEncryptor *aes = CBufferedEncryptor::NewL(rawaes, pad);
sl@0
   368
	CleanupStack::Pop(rawaes); // pad
sl@0
   369
	CleanupStack::Pop(pad); // 
sl@0
   370
	CleanupStack::PushL(aes); // aes
sl@0
   371
#endif	
sl@0
   372
	
sl@0
   373
	{
sl@0
   374
	TBuf8<10> b1;
sl@0
   375
	b1 = _L8("0123456789");
sl@0
   376
	TBuf8<6> b2;
sl@0
   377
	b2 = _L8("012345");
sl@0
   378
	TBuf8<64> b3;
sl@0
   379
	
sl@0
   380
	test.Printf(_L("Test of Process/ProcessFinal\n"));
sl@0
   381
	aes->Reset();
sl@0
   382
	aes->Process(b1,b3);
sl@0
   383
	aes->ProcessFinalL(b2, b3);
sl@0
   384
	aes->Reset();
sl@0
   385
	}
sl@0
   386
	
sl@0
   387
	test.Printf(_L("About to s/w encrypt\n"));
sl@0
   388
	TBuf8<BUFLEN> sw;
sl@0
   389
	sw.SetLength(0);
sl@0
   390
	aes->ProcessFinalL(plaintext, sw);
sl@0
   391
sl@0
   392
	test.Printf(_L("sw =\n    "));
sl@0
   393
	for(TInt i = 0 ; i<256; ++i)
sl@0
   394
		{
sl@0
   395
		if(i && (i%16 == 0))
sl@0
   396
			{
sl@0
   397
			test.Printf(_L("\n    "));
sl@0
   398
			}
sl@0
   399
		test.Printf(_L("%02x "), sw[i]);
sl@0
   400
		}
sl@0
   401
	test.Printf(_L("\n"));
sl@0
   402
sl@0
   403
	aes->Reset();
sl@0
   404
	test.Printf(_L("S/W - Encrypt %d bytes %d times\n"), BUFLEN, LOOPCOUNT);
sl@0
   405
	startCount = User::NTickCount();
sl@0
   406
	for(int z=0; z < LOOPCOUNT; ++z)
sl@0
   407
		{
sl@0
   408
		//aes->Reset();
sl@0
   409
		sw.SetLength(0);
sl@0
   410
		//aes->ProcessFinalL(plaintext, sw);
sl@0
   411
		aes->Process(plaintext, sw);
sl@0
   412
		}
sl@0
   413
	endCount = User::NTickCount();
sl@0
   414
	test.Printf(_L("Duration in ticks (s/w) = %d\n"), endCount - startCount);
sl@0
   415
sl@0
   416
sl@0
   417
	CleanupStack::PopAndDestroy(aes);
sl@0
   418
sl@0
   419
    test.Next(_L("AES - H/W"));
sl@0
   420
sl@0
   421
	
sl@0
   422
	test.Printf(_L("Setting config\n"));
sl@0
   423
#ifdef USE_CBCMODE
sl@0
   424
	r = ldd.SetAesConfig(ETrue, RCryptoDriver::ECbcMode, key, iv);
sl@0
   425
	test.Printf(_L("    CBC\n"));
sl@0
   426
#else
sl@0
   427
	r = ldd.SetAesConfig(ETrue, RCryptoDriver::EEcbMode, key, iv);
sl@0
   428
	test.Printf(_L("    ECB\n"));
sl@0
   429
#endif
sl@0
   430
	test(r==KErrNone);
sl@0
   431
	
sl@0
   432
sl@0
   433
	test.Printf(_L("H/W - Encrypt %d bytes %d times\n"), BUFLEN, LOOPCOUNT);
sl@0
   434
	TBuf8<BUFLEN> tmp2;
sl@0
   435
	startCount = User::NTickCount();
sl@0
   436
	for(int z=0; z < LOOPCOUNT; ++z)
sl@0
   437
		{
sl@0
   438
		tmp2.SetLength(0);
sl@0
   439
		ldd.AesRead(status2, tmp2, tmp2.MaxLength());
sl@0
   440
		ldd.AesWrite(status, plaintext);
sl@0
   441
		User::WaitForRequest(status);	
sl@0
   442
		User::WaitForRequest(status2);
sl@0
   443
#ifdef DISABLE_AES_CHECKS
sl@0
   444
		tmp2.SetLength(BUFLEN);
sl@0
   445
#endif
sl@0
   446
		}
sl@0
   447
	endCount = User::NTickCount();
sl@0
   448
	test.Printf(_L("Duration in ticks (h/w) = %d\n"), endCount - startCount);
sl@0
   449
sl@0
   450
	
sl@0
   451
#ifndef DISABLE_AES_CHECKS
sl@0
   452
#ifdef __MARM__
sl@0
   453
	test.Printf(_L("Compare tmp2 and sw\n"));
sl@0
   454
	test(tmp2==sw);
sl@0
   455
#else
sl@0
   456
	test.Printf(_L("Compare tmp2 and plaintext\n"));
sl@0
   457
    test(tmp2==plaintext);
sl@0
   458
#endif
sl@0
   459
#endif
sl@0
   460
sl@0
   461
sl@0
   462
sl@0
   463
sl@0
   464
sl@0
   465
//	User::Panic(_L("Fake app crash"), 42);
sl@0
   466
sl@0
   467
    test.Next(_L("Close Logical Channel"));
sl@0
   468
    ldd.Close();
sl@0
   469
sl@0
   470
    __KHEAP_MARKEND;
sl@0
   471
sl@0
   472
    test.Next(_L("Unload Logical Device"));
sl@0
   473
    r=User::FreeLogicalDevice(RCryptoDriver::Name());
sl@0
   474
    test(r==KErrNone);
sl@0
   475
sl@0
   476
    test.Next(_L("Unload Physical Device"));
sl@0
   477
    TName pddName(RCryptoDriver::Name());
sl@0
   478
    _LIT(KVariantExtension,".h4");
sl@0
   479
    pddName.Append(KVariantExtension);
sl@0
   480
    r=User::FreePhysicalDevice(pddName);
sl@0
   481
    test(r==KErrNone);
sl@0
   482
sl@0
   483
    test.End();
sl@0
   484
sl@0
   485
	test.Printf(KTxtPressAnyKey);
sl@0
   486
	test.Getch(); // get and ignore character
sl@0
   487
	test.Close();
sl@0
   488
    }
sl@0
   489
sl@0
   490
sl@0
   491
// End of file