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