os/security/cryptoservices/asnpkcs/source/asnpkcs8.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) 2004-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
#include <asn1dec.h>
sl@0
    20
#include <x509keys.h>
sl@0
    21
#include <x509cert.h>
sl@0
    22
#include "asnpkcs.h"
sl@0
    23
#include <pbe.h>
sl@0
    24
#include <pbedata.h>
sl@0
    25
#include <keyidentifierutil.h>
sl@0
    26
sl@0
    27
/*static*/ EXPORT_C CDecPKCS8Data* TASN1DecPKCS8::DecodeDERL(const TDesC8& aBinaryData)
sl@0
    28
{
sl@0
    29
	return (CDecPKCS8Data::NewL(aBinaryData));
sl@0
    30
}
sl@0
    31
sl@0
    32
/*
sl@0
    33
EncryptedPrivateKeyInfo ::= SEQUENCE {
sl@0
    34
  encryptionAlgorithm EncryptionAlgorithmIdentifier,
sl@0
    35
  encryptedData EncryptedData }
sl@0
    36
EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
sl@0
    37
EncryptedData ::= OCTET STRING
sl@0
    38
*/
sl@0
    39
sl@0
    40
/*static*/ EXPORT_C CDecPKCS8Data* TASN1DecPKCS8::DecodeEncryptedDERL(const TDesC8& aBinaryData, const TDesC8& aPassword)
sl@0
    41
{
sl@0
    42
	TASN1DecGeneric seqGen(aBinaryData);
sl@0
    43
	seqGen.InitL();
sl@0
    44
	if (seqGen.Tag() != EASN1Sequence)
sl@0
    45
		{
sl@0
    46
		User::Leave(KErrArgument);
sl@0
    47
		}
sl@0
    48
	
sl@0
    49
	TASN1DecSequence dec;
sl@0
    50
	CArrayPtrFlat<TASN1DecGeneric>* theData = dec.DecodeDERLC(seqGen);
sl@0
    51
	TInt seqIndex = 0;
sl@0
    52
	TInt count = theData->Count();
sl@0
    53
	if (seqIndex >= count)
sl@0
    54
		{
sl@0
    55
		User::Leave(KErrArgument);		
sl@0
    56
		}
sl@0
    57
sl@0
    58
//	Get the first part of the sequence -> PKCS5 data
sl@0
    59
	TASN1DecGeneric* pkcs5 = theData->operator[](seqIndex);
sl@0
    60
	TPtrC8 theContent(pkcs5->Encoding());	//	expect this to be a sequence
sl@0
    61
	CPBEncryptParms* encryptParams = TASN1DecPKCS5::DecodeDERL(theContent);
sl@0
    62
	CleanupStack::PushL(encryptParams);
sl@0
    63
sl@0
    64
//	Create the decryptor	
sl@0
    65
	CPBEncryptElement* encryptElement = CPBEncryptElement::NewLC(aPassword, *encryptParams);
sl@0
    66
	CPBDecryptor* decryptor = encryptElement->NewDecryptLC();
sl@0
    67
//	Decrypt the final part of the sequence -> encrypted PKCS8 object
sl@0
    68
	TASN1DecGeneric* pkcs8 = theData->operator[](count-1);
sl@0
    69
	if (pkcs8->Tag() != EASN1OctetString)
sl@0
    70
		{
sl@0
    71
		User::Leave(KErrArgument);
sl@0
    72
		}
sl@0
    73
	TPtrC8 encryptedKey(pkcs8->GetContentDER());
sl@0
    74
	TUint encryptLength = encryptedKey.Length();
sl@0
    75
	TUint maxDecryptLength = decryptor->MaxOutputLength(encryptLength);
sl@0
    76
	if (maxDecryptLength<=0)
sl@0
    77
		{
sl@0
    78
		User::Leave(KErrGeneral);		
sl@0
    79
		}
sl@0
    80
	
sl@0
    81
	HBufC8* decryptOutput = HBufC8::NewLC(encryptLength);
sl@0
    82
	TPtr8 decryptOutputPtr(decryptOutput->Des());
sl@0
    83
	decryptOutputPtr.FillZ();
sl@0
    84
	decryptor->Process(encryptedKey, decryptOutputPtr);
sl@0
    85
			
sl@0
    86
	CDecPKCS8Data* pkcs8Data = CDecPKCS8Data::NewL(decryptOutputPtr);
sl@0
    87
sl@0
    88
	//	decryptOutput decryptor encryptElement 
sl@0
    89
	//	encryptParams theData
sl@0
    90
	CleanupStack::PopAndDestroy(5, theData);
sl@0
    91
	
sl@0
    92
	return (pkcs8Data);
sl@0
    93
}
sl@0
    94
sl@0
    95
/*
sl@0
    96
Sample cleartext pkcs8 data from pkcs8dsa.001:
sl@0
    97
sl@0
    98
          SEQUENCE
sl@0
    99
30          Tag: Constructed sequence
sl@0
   100
81 c8       Length (may be one or more bytes)
sl@0
   101
sl@0
   102
            INTEGER
sl@0
   103
02            Tag: Integer
sl@0
   104
01            Length: 1 byte
sl@0
   105
00            Value: 0
sl@0
   106
sl@0
   107
            SEQUENCE    
sl@0
   108
30            Tag: Constructed sequence
sl@0
   109
81 a9         Length (may be one or more bytes)
sl@0
   110
sl@0
   111
              OID
sl@0
   112
06              Tag: OID
sl@0
   113
07              Length: 7 bytes
sl@0
   114
2a 86 48 ce 38 04 01
sl@0
   115
                Value: dsa (1 2 840 10040 4 1)
sl@0
   116
*/
sl@0
   117
sl@0
   118
_LIT8(KPKCS8DataVersion0, "\x02\x01\x00");
sl@0
   119
_LIT8(KPKCS8DataOIDDSA, "\x06\x07\x2a\x86\x48\xce\x38\x04\x01");
sl@0
   120
_LIT8(KPKCS8DataOIDRSA, "\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01");
sl@0
   121
sl@0
   122
/*static*/ EXPORT_C TBool TASN1DecPKCS8::IsPKCS8Data(const TDesC8& aBinaryData)
sl@0
   123
	{
sl@0
   124
	// We don't decode the data because we may only have the first few bytes -
sl@0
   125
	// instead we check the ASN1 by hand.
sl@0
   126
sl@0
   127
	ASSERT(aBinaryData.Length() >= KIsPKCS8DataMinLength);
sl@0
   128
	TInt pos = 0;
sl@0
   129
sl@0
   130
	return
sl@0
   131
		IsASN1Sequence(aBinaryData, pos) &&
sl@0
   132
		IsExpectedData(aBinaryData, pos, KPKCS8DataVersion0) &&
sl@0
   133
		IsASN1Sequence(aBinaryData, pos) &&
sl@0
   134
		(IsExpectedData(aBinaryData, pos, KPKCS8DataOIDDSA) ||
sl@0
   135
		 IsExpectedData(aBinaryData, pos, KPKCS8DataOIDRSA));
sl@0
   136
	}
sl@0
   137
sl@0
   138
/*
sl@0
   139
Sample encrypted pkcs8 data from encryptPK8rsa1.txt
sl@0
   140
sl@0
   141
          SEQUENCE
sl@0
   142
30          Tag: Constructed sequence
sl@0
   143
82 01 a3    Length (may be one or more bytes)
sl@0
   144
sl@0
   145
            SEQUENCE
sl@0
   146
30            Tag: Constructed sequence
sl@0
   147
3d            Length (may be one or more bytes)
sl@0
   148
sl@0
   149
              OID
sl@0
   150
06              Tag: OID
sl@0
   151
09              Length: 9 bytes
sl@0
   152
2a 86 48 86 f7 0d 01 05 0d
sl@0
   153
                Value: pkcs5PBES2 (1 2 840 113549 1 5 13)
sl@0
   154
sl@0
   155
              SEQUENCE
sl@0
   156
30              Tag: Constructed sequence
sl@0
   157
30              Length (may be one or more bytes)
sl@0
   158
sl@0
   159
                SEQUENCE
sl@0
   160
30                Tag: Constructed sequence
sl@0
   161
1b                Length (may be one or more bytes)
sl@0
   162
sl@0
   163
                  OID
sl@0
   164
06                  Tag: OID
sl@0
   165
09                  Length: 9 bytes
sl@0
   166
2a 86 48 86 f7 0d 01 05 0c
sl@0
   167
                    Value: pkcs5PBKDF2 (1 2 840 113549 1 5 12)
sl@0
   168
*/
sl@0
   169
sl@0
   170
_LIT8(KEncryptedPKCS8DataOIDpkcs5PBES2, "\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x05\x0d");
sl@0
   171
_LIT8(KEncryptedPKCS8DataOIDpkcs5PBKDF2, "\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x05\x0c");
sl@0
   172
sl@0
   173
EXPORT_C TBool TASN1DecPKCS8::IsEncryptedPKCS8Data(const TDesC8& aBinaryData)
sl@0
   174
	{
sl@0
   175
	// We don't decode the data because we may only have the first few bytes -
sl@0
   176
	// instead we check the ASN1 by hand.
sl@0
   177
sl@0
   178
	ASSERT(aBinaryData.Length() >= KIsEncryptedPKCS8DataMinLength);
sl@0
   179
	TInt pos = 0;
sl@0
   180
sl@0
   181
	return
sl@0
   182
		IsASN1Sequence(aBinaryData, pos) &&
sl@0
   183
		IsASN1Sequence(aBinaryData, pos) &&
sl@0
   184
		IsExpectedData(aBinaryData, pos, KEncryptedPKCS8DataOIDpkcs5PBES2) &&
sl@0
   185
		IsASN1Sequence(aBinaryData, pos) &&
sl@0
   186
		IsASN1Sequence(aBinaryData, pos) &&
sl@0
   187
		IsExpectedData(aBinaryData, pos, KEncryptedPKCS8DataOIDpkcs5PBKDF2);
sl@0
   188
	}
sl@0
   189
sl@0
   190
/**
sl@0
   191
 * Determine if the some data represents the start of an ASN1 sequence.  The
sl@0
   192
 * data is specified by a descriptor and an offset.  If the data matches, the
sl@0
   193
 * offset is advanced to point to the contents of the sequence.
sl@0
   194
 */
sl@0
   195
TBool TASN1DecPKCS8::IsASN1Sequence(const TDesC8& aBinaryData, TInt& aPos)
sl@0
   196
	{
sl@0
   197
	// Check we have enough data
sl@0
   198
	if ((aPos + 2) >= aBinaryData.Length())
sl@0
   199
		{
sl@0
   200
		return EFalse;
sl@0
   201
		}
sl@0
   202
	// Check the outermost sequence is valid
sl@0
   203
	if (aBinaryData[aPos++] != 0x30 /* constructed sequence */)
sl@0
   204
		{
sl@0
   205
		return EFalse;
sl@0
   206
		}
sl@0
   207
	// Skip sequence length
sl@0
   208
	TInt length0 = aBinaryData[aPos++];
sl@0
   209
	if (length0 & 0x80)
sl@0
   210
		{
sl@0
   211
		aPos += length0 & 0x7f;
sl@0
   212
		}
sl@0
   213
	return ETrue;
sl@0
   214
	}
sl@0
   215
sl@0
   216
/**
sl@0
   217
 * Determine if some data starts with an expected string.  The data is specified
sl@0
   218
 * by a descriptor and an offset.  If the data matches, the offset is advanced
sl@0
   219
 * to point after the match.
sl@0
   220
 */
sl@0
   221
TBool TASN1DecPKCS8::IsExpectedData(const TDesC8& aBinaryData, TInt& aPos, const TDesC8& aExpectedData)
sl@0
   222
	{
sl@0
   223
	TInt length = aExpectedData.Length();
sl@0
   224
	// Check we have enough data
sl@0
   225
	if (aPos + length >= aBinaryData.Length())
sl@0
   226
		{
sl@0
   227
		return EFalse;
sl@0
   228
		}
sl@0
   229
	// Check data matches	
sl@0
   230
	if (aBinaryData.Mid(aPos, length) != aExpectedData)
sl@0
   231
		{
sl@0
   232
		return EFalse;
sl@0
   233
		}
sl@0
   234
	aPos += length;
sl@0
   235
	return ETrue;
sl@0
   236
	}
sl@0
   237
sl@0
   238
//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	
sl@0
   239
//	PKCS#8 object data representation
sl@0
   240
//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	
sl@0
   241
sl@0
   242
/*static*/ CDecPKCS8Data* CDecPKCS8Data::NewL(const TDesC8& aData)
sl@0
   243
{
sl@0
   244
	CDecPKCS8Data* me = new (ELeave) CDecPKCS8Data();
sl@0
   245
	CleanupStack::PushL(me);
sl@0
   246
	me->ConstructL(aData);
sl@0
   247
	CleanupStack::Pop(me);
sl@0
   248
	return (me);
sl@0
   249
}
sl@0
   250
sl@0
   251
CDecPKCS8Data::CDecPKCS8Data()
sl@0
   252
{}
sl@0
   253
sl@0
   254
CDecPKCS8Data::~CDecPKCS8Data()
sl@0
   255
{
sl@0
   256
	if (iKeyPairData)
sl@0
   257
	{
sl@0
   258
		iKeyPairData->Release();
sl@0
   259
		iKeyPairData = NULL;
sl@0
   260
	}
sl@0
   261
sl@0
   262
	if (iAttributes)
sl@0
   263
	{
sl@0
   264
		delete iAttributes;
sl@0
   265
		iAttributes = NULL;
sl@0
   266
	}
sl@0
   267
}
sl@0
   268
sl@0
   269
//	Because this is part of construction, don't rely on
sl@0
   270
//	cleanup of partially constructed items...
sl@0
   271
void CDecPKCS8Data::ConstructL(const TDesC8& aData)
sl@0
   272
	{
sl@0
   273
	TASN1DecGeneric seqGen(aData);
sl@0
   274
	seqGen.InitL();
sl@0
   275
	if (seqGen.Tag() != EASN1Sequence)
sl@0
   276
		{
sl@0
   277
		User::Leave(KErrArgument);
sl@0
   278
		}
sl@0
   279
sl@0
   280
	TASN1DecSequence seq;
sl@0
   281
	CArrayPtrFlat<TASN1DecGeneric>* seqContents = seq.DecodeDERLC(seqGen);
sl@0
   282
	if (seqContents->Count() < 3 || seqContents->Count() > 4)
sl@0
   283
		{
sl@0
   284
		User::Leave(KErrArgument);
sl@0
   285
		}
sl@0
   286
				
sl@0
   287
//	VERSION
sl@0
   288
	if (seqContents->At(0)->Tag() != EASN1Integer)
sl@0
   289
		{
sl@0
   290
		User::Leave(KErrArgument);
sl@0
   291
		}
sl@0
   292
	TASN1DecInteger intDecoder;
sl@0
   293
	iVersion = intDecoder.DecodeDERShortL(*(seqContents->At(0)));
sl@0
   294
	if (iVersion!=0)
sl@0
   295
		{
sl@0
   296
		User::Leave(KErrArgument);
sl@0
   297
		}
sl@0
   298
	
sl@0
   299
//	ALGORITHM
sl@0
   300
	CX509AlgorithmIdentifier* algorithm = CX509AlgorithmIdentifier::NewLC(seqContents->At(1)->Encoding());
sl@0
   301
	iAlgorithmID = algorithm->Algorithm();
sl@0
   302
		
sl@0
   303
//	KEY DATA
sl@0
   304
	switch (iAlgorithmID)
sl@0
   305
		{//	Only support RSA, DSA, DH
sl@0
   306
		case ERSA:
sl@0
   307
			iKeyPairData = CPKCS8KeyPairRSA::NewL(*(seqContents->At(2)));
sl@0
   308
			break;
sl@0
   309
			
sl@0
   310
		case EDSA:
sl@0
   311
			{
sl@0
   312
			TPtrC8 params(algorithm->EncodedParams());		
sl@0
   313
			iKeyPairData = CPKCS8KeyPairDSA::NewL(params, *(seqContents->At(2)));
sl@0
   314
			break;
sl@0
   315
			}
sl@0
   316
			
sl@0
   317
		case EDH: // Currently not supported because no test data is available
sl@0
   318
		default:
sl@0
   319
			User::Leave(KErrNotSupported);
sl@0
   320
			break;
sl@0
   321
		}
sl@0
   322
sl@0
   323
	CleanupStack::PopAndDestroy(algorithm);
sl@0
   324
sl@0
   325
	if (seqContents->Count() == 4)
sl@0
   326
		{
sl@0
   327
		// I think we should check the tag is zero here, but we're going to be
sl@0
   328
		// lenient due to lack of real test data
sl@0
   329
		
sl@0
   330
		//if (seqContents->At(3)->Tag() != 0) // Implicitly tagged
sl@0
   331
		//	{
sl@0
   332
		//	User::Leave(KErrArgument);
sl@0
   333
		//	}
sl@0
   334
		
sl@0
   335
		iAttributes = seqContents->At(3)->Encoding().AllocL();
sl@0
   336
		}
sl@0
   337
sl@0
   338
	CleanupStack::PopAndDestroy(seqContents);
sl@0
   339
	}
sl@0
   340
sl@0
   341
//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	
sl@0
   342
//	RSA decoding
sl@0
   343
//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	
sl@0
   344
sl@0
   345
/*static*/ MPKCS8DecodedKeyPairData* CPKCS8KeyPairRSA::NewL(const TASN1DecGeneric& aSource)
sl@0
   346
{
sl@0
   347
	CPKCS8KeyPairRSA* me = new (ELeave) CPKCS8KeyPairRSA();
sl@0
   348
	CleanupStack::PushL(me);
sl@0
   349
	me->ConstructL(aSource);
sl@0
   350
	CleanupStack::Pop(me);
sl@0
   351
sl@0
   352
	return (me);
sl@0
   353
}
sl@0
   354
sl@0
   355
MPKCS8DecodedKeyPairData::~MPKCS8DecodedKeyPairData()
sl@0
   356
	{	
sl@0
   357
	}
sl@0
   358
sl@0
   359
CPKCS8KeyPairRSA::~CPKCS8KeyPairRSA()
sl@0
   360
{
sl@0
   361
	delete iPublicKey;
sl@0
   362
	delete iPrivateKey;
sl@0
   363
}
sl@0
   364
sl@0
   365
void CPKCS8KeyPairRSA::Release()
sl@0
   366
{
sl@0
   367
	delete this;
sl@0
   368
}
sl@0
   369
sl@0
   370
void CPKCS8KeyPairRSA::GetKeyIdentifierL(TKeyIdentifier& aKeyIdentifier) const
sl@0
   371
{
sl@0
   372
	if (iPublicKey)
sl@0
   373
		KeyIdentifierUtil::RSAKeyIdentifierL(*iPublicKey, aKeyIdentifier);	
sl@0
   374
	else
sl@0
   375
		User::Leave(KErrNotReady);
sl@0
   376
}
sl@0
   377
sl@0
   378
TUint CPKCS8KeyPairRSA::KeySize() const
sl@0
   379
{
sl@0
   380
	if (!iPublicKey)
sl@0
   381
	{
sl@0
   382
		ASSERT(EFalse);
sl@0
   383
		return (0xffffffff);
sl@0
   384
	}
sl@0
   385
	
sl@0
   386
	const TInteger& modulus = iPublicKey->N();
sl@0
   387
sl@0
   388
	TUint size = modulus.BitCount();
sl@0
   389
	return (size);
sl@0
   390
}
sl@0
   391
sl@0
   392
void CPKCS8KeyPairRSA::ConstructL(const TASN1DecGeneric& aSource)
sl@0
   393
{
sl@0
   394
	TPtrC8 theContent(aSource.GetContentDER());
sl@0
   395
	TASN1DecRSAKeyPair keyPairDecoder;
sl@0
   396
	TInt tempPos = 0;
sl@0
   397
	keyPairDecoder.DecodeDERL(theContent, tempPos, iPublicKey, iPrivateKey);
sl@0
   398
}
sl@0
   399
sl@0
   400
sl@0
   401
//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	
sl@0
   402
//	DSA decoding
sl@0
   403
//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	//	\\	
sl@0
   404
sl@0
   405
/*static*/ MPKCS8DecodedKeyPairData* CPKCS8KeyPairDSA::NewL(const TDesC8& aParamsData, const TASN1DecGeneric& aSource)
sl@0
   406
{
sl@0
   407
	CPKCS8KeyPairDSA* me = new (ELeave) CPKCS8KeyPairDSA();
sl@0
   408
	CleanupStack::PushL(me);
sl@0
   409
	me->ConstructL(aParamsData, aSource);
sl@0
   410
	CleanupStack::Pop(me);
sl@0
   411
sl@0
   412
	return (me);
sl@0
   413
}
sl@0
   414
sl@0
   415
CPKCS8KeyPairDSA::~CPKCS8KeyPairDSA()
sl@0
   416
{
sl@0
   417
	delete iPublicKey;
sl@0
   418
	delete iPrivateKey;
sl@0
   419
}
sl@0
   420
sl@0
   421
void CPKCS8KeyPairDSA::Release()
sl@0
   422
{
sl@0
   423
	delete this;
sl@0
   424
}
sl@0
   425
sl@0
   426
void CPKCS8KeyPairDSA::GetKeyIdentifierL(TKeyIdentifier& aKeyIdentifier) const
sl@0
   427
{
sl@0
   428
	if (iPublicKey)
sl@0
   429
		KeyIdentifierUtil::DSAKeyIdentifierL(*iPublicKey, aKeyIdentifier);	
sl@0
   430
	else
sl@0
   431
		User::Leave(KErrNotReady);
sl@0
   432
}
sl@0
   433
sl@0
   434
TUint CPKCS8KeyPairDSA::KeySize() const
sl@0
   435
{
sl@0
   436
	if (!iPublicKey)
sl@0
   437
	{
sl@0
   438
		ASSERT(EFalse);
sl@0
   439
		return (0xffffffff);
sl@0
   440
	}
sl@0
   441
	
sl@0
   442
	const TInteger& P = iPublicKey->P();
sl@0
   443
sl@0
   444
	TUint size = P.BitCount();
sl@0
   445
	return (size);
sl@0
   446
}
sl@0
   447
sl@0
   448
void CPKCS8KeyPairDSA::ConstructL(const TDesC8& aParamsData, const TASN1DecGeneric& aSource)
sl@0
   449
{
sl@0
   450
	TX509KeyFactory keyFactory;
sl@0
   451
	CDSAParameters* params = keyFactory.DSAParametersL(aParamsData);
sl@0
   452
	CleanupStack::PushL(params);
sl@0
   453
sl@0
   454
	RInteger P = RInteger::NewL(params->P());
sl@0
   455
	CleanupStack::PushL(P);
sl@0
   456
sl@0
   457
	RInteger Q = RInteger::NewL(params->Q());
sl@0
   458
	CleanupStack::PushL(Q);
sl@0
   459
sl@0
   460
	RInteger G = RInteger::NewL(params->G());
sl@0
   461
	CleanupStack::PushL(G);
sl@0
   462
sl@0
   463
	if (aSource.Tag() != EASN1OctetString)
sl@0
   464
		{
sl@0
   465
		User::Leave(KErrArgument);
sl@0
   466
		}
sl@0
   467
	TASN1DecOctetString  octetDecoder;
sl@0
   468
	HBufC8* wrapped = octetDecoder.DecodeDERL(aSource);
sl@0
   469
	CleanupStack::PushL(wrapped);	
sl@0
   470
sl@0
   471
	TASN1DecGeneric integer(*wrapped);
sl@0
   472
	integer.InitL();
sl@0
   473
	if (integer.Tag() != EASN1Integer)
sl@0
   474
		{
sl@0
   475
		User::Leave(KErrArgument);
sl@0
   476
		}		
sl@0
   477
	TASN1DecInteger decInt;
sl@0
   478
	RInteger X = decInt.DecodeDERLongL(integer);
sl@0
   479
	CleanupStack::PopAndDestroy(wrapped);
sl@0
   480
	CleanupStack::PushL(X);
sl@0
   481
			
sl@0
   482
	RInteger P1 = RInteger::NewL(params->P());
sl@0
   483
	CleanupStack::PushL(P1);
sl@0
   484
	
sl@0
   485
	RInteger Q1 = RInteger::NewL(params->Q());
sl@0
   486
	CleanupStack::PushL(Q1);
sl@0
   487
	
sl@0
   488
	RInteger G1 = RInteger::NewL(params->G());
sl@0
   489
	CleanupStack::PushL(G1);
sl@0
   490
sl@0
   491
	RInteger Y = TInteger::ModularExponentiateL(G, X, P);
sl@0
   492
	CleanupStack::PushL(Y);
sl@0
   493
sl@0
   494
	iPublicKey = CDSAPublicKey::NewL(P1, Q1, G1, Y);
sl@0
   495
sl@0
   496
	// Now have to pop everything owned by iPublicKey otherwise it will be
sl@0
   497
	// deleted twice if the CDSAPrivateKey::NewL leaves
sl@0
   498
sl@0
   499
	CleanupStack::Pop(4, &P1);	// now owned by iPublicKey
sl@0
   500
	
sl@0
   501
	iPrivateKey = CDSAPrivateKey::NewL(P, Q, G, X);
sl@0
   502
sl@0
   503
	CleanupStack::Pop(4, &P);	// now owned by iPrivateKey
sl@0
   504
		
sl@0
   505
	CleanupStack::PopAndDestroy(params);
sl@0
   506
}