os/security/cryptoservices/asnpkcs/source/asnpkcs5.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.
     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 <asn1enc.h>
    20 #include <asn1dec.h>
    21 #include <pbedata.h>
    22 #include <rc2.h>
    23 
    24 #include "asnpkcs.h"
    25 
    26 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
    27 
    28 /** OpenSSL PKCS8 Effective Key Length Compatibility.*/
    29 const TUint KPkcs8CompatibilityBits = 128;
    30 
    31 #endif
    32 
    33 
    34 _LIT(Kpkcs5PBES2, "1.2.840.113549.1.5.13");
    35 _LIT(Kpkcs5PBKDF2, "1.2.840.113549.1.5.12");
    36 _LIT(KDESCBC, "1.3.14.3.2.7");
    37 _LIT(K3DESCBC, "1.2.840.113549.3.7");
    38 _LIT(KRC2CBC, "1.2.840.113549.3.2");
    39 
    40 // pbe12Algorithm Ids
    41 _LIT(KPbeWithSHA1And128BitRC4, "1.2.840.113549.1.12.1.1");
    42 _LIT(KPbeWithSHA1And40BitRC4, "1.2.840.113549.1.12.1.2");
    43 _LIT(KPbeWithSHA1And3_KeyTripleDES_CBC, "1.2.840.113549.1.12.1.3");
    44 _LIT(KPbeWithSHA1And2_KeyTripleDES_CBC, "1.2.840.113549.1.12.1.4");
    45 _LIT(KPbeWithSHA1And128BitRC2_CBC, "1.2.840.113549.1.12.1.5");
    46 _LIT(KPbeWithSHA1And40BitRC2_CBC, "1.2.840.113549.1.12.1.6");
    47 //The size of the Initialization vector
    48 const TInt KIvSize = 8;
    49 
    50 
    51 /*
    52 * //For RC2
    53 * SEQUENCE
    54 * 	OID -- pkcs5PBES2
    55 *	SEQUENCE
    56 *		SEQUENCE
    57 *		OID -- pkcs5PBKDF2
    58 *		SEQUENCE
    59 *			OCTET STRING -- salt
    60 *			INTEGER -- iteration count
    61 *			INTEGER -- effective key length in octets
    62 * 	SEQUENCE
    63 *		OID -- algorithm id (rc2)
    64 *		SEQUENCE
    65 *			INTEGER -- RC2 parameter version 58 = 128, 160 = 40
    66 *			OCTET STRING -- iv
    67 *
    68 * //For DES and 3DES
    69 * SEQUENCE
    70 * 	OID -- pkcs5PBES2
    71 *	SEQUENCE
    72 *		SEQUENCE
    73 *		OID -- pkcs5PBKDF2
    74 *		SEQUENCE
    75 *			OCTET STRING -- salt
    76 *			INTEGER -- iteration count
    77 * 	SEQUENCE
    78 *		OID -- algorithm id (des, 3des)
    79 *		OCTET STRING -- iv
    80 */
    81 
    82 EXPORT_C CASN1EncSequence* TASN1EncPKCS5::EncodeDERL(const CPBEncryptParms& aParms)
    83 	{
    84 	CASN1EncSequence* seq = CASN1EncSequence::NewLC();
    85 	CASN1EncObjectIdentifier* pbes2 = CASN1EncObjectIdentifier::NewLC(Kpkcs5PBES2);
    86 	seq->AddChildL(pbes2);
    87 	CleanupStack::Pop(pbes2);
    88 
    89 	CASN1EncSequence* seq1 = CASN1EncSequence::NewLC();
    90 	seq->AddChildL(seq1);
    91 	CleanupStack::Pop(seq1);
    92 
    93 	CASN1EncSequence* seq2 = CASN1EncSequence::NewLC();
    94 	seq1->AddChildL(seq2);
    95 	CleanupStack::Pop(seq2);
    96 
    97 	CASN1EncObjectIdentifier* pbkdf2 = CASN1EncObjectIdentifier::NewLC(Kpkcs5PBKDF2);
    98 	seq2->AddChildL(pbkdf2);
    99 	CleanupStack::Pop(pbkdf2);
   100 
   101 	CASN1EncSequence* seq3 = CASN1EncSequence::NewLC();
   102 	seq2->AddChildL(seq3);
   103 	CleanupStack::Pop(seq3);
   104 
   105 	CASN1EncOctetString* salt = CASN1EncOctetString::NewLC(aParms.Salt());
   106 	seq3->AddChildL(salt);
   107 	CleanupStack::Pop(salt);
   108 
   109 	CASN1EncInt* iterations = CASN1EncInt::NewLC(aParms.Iterations());
   110 	seq3->AddChildL(iterations);
   111 	CleanupStack::Pop(iterations);
   112 
   113 	CASN1EncInt* keysize = 0;
   114 	switch(aParms.Cipher())
   115 		{
   116 		case ECipherDES_CBC:
   117 		case ECipher3DES_CBC: 
   118 			break;
   119 		case ECipherRC2_CBC_40:
   120  			keysize = CASN1EncInt::NewLC(KSSLCompatibilityBits/8);  // effective key length in *octets*
   121 			seq3->AddChildL(keysize);
   122 			CleanupStack::Pop(keysize);
   123 			break;
   124 		case ECipherRC2_CBC_128:
   125  			keysize = CASN1EncInt::NewLC(KSSLCompatibilityBits/8);  // effective key length in *octets*
   126 			seq3->AddChildL(keysize);
   127 			CleanupStack::Pop(keysize);
   128 			break;
   129 		case ECipherRC2_CBC_40_16:
   130  			keysize = CASN1EncInt::NewLC(KPkcs8CompatibilityBits/8);  // effective key length in *octets*
   131 			seq3->AddChildL(keysize);
   132 			CleanupStack::Pop(keysize);
   133 			break;
   134 		case ECipherRC2_CBC_128_16:
   135  			keysize = CASN1EncInt::NewLC(KPkcs8CompatibilityBits/8);  // effective key length in *octets*
   136 			seq3->AddChildL(keysize);
   137 			CleanupStack::Pop(keysize);
   138 			break;
   139 		default:
   140 			User::Leave(KErrNotSupported);
   141 			break;
   142 		}
   143 
   144 	CASN1EncSequence* seq4 = CASN1EncSequence::NewLC();
   145 	seq1->AddChildL(seq4);
   146 	CleanupStack::Pop(seq4);
   147 
   148 	CASN1EncObjectIdentifier* algid = 0;
   149 	switch(aParms.Cipher())
   150 		{
   151 		case ECipherDES_CBC:
   152 			algid = CASN1EncObjectIdentifier::NewLC(KDESCBC);
   153 			break;
   154 		case ECipher3DES_CBC:
   155 			algid = CASN1EncObjectIdentifier::NewLC(K3DESCBC);
   156 			break;
   157 		case ECipherRC2_CBC_40:
   158 		case ECipherRC2_CBC_128:
   159 		case ECipherRC2_CBC_40_16:
   160 		case ECipherRC2_CBC_128_16:
   161 			algid = CASN1EncObjectIdentifier::NewLC(KRC2CBC);
   162 			break;
   163 		default:
   164 			User::Leave(KErrNotSupported);
   165 			break;
   166 		}
   167 	seq4->AddChildL(algid);
   168 	CleanupStack::Pop(algid);
   169 
   170 	CASN1EncSequence* seq5 = 0;
   171 	CASN1EncInt* keysize1 = 0;
   172 	CASN1EncOctetString* iv = 0;
   173 	switch(aParms.Cipher())
   174 		{
   175 		case ECipherDES_CBC:
   176 		case ECipher3DES_CBC:
   177 			iv = CASN1EncOctetString::NewLC(aParms.IV());
   178 			seq4->AddChildL(iv);
   179 			CleanupStack::Pop(iv);
   180 			break;
   181 		case ECipherRC2_CBC_40:
   182 		case ECipherRC2_CBC_40_16:
   183 			seq5 = CASN1EncSequence::NewLC();
   184 			seq4->AddChildL(seq5);
   185 			CleanupStack::Pop(seq5);
   186 
   187 			keysize1 = CASN1EncInt::NewLC(160); //encoding for 40 bit
   188 			seq5->AddChildL(keysize1);
   189 			CleanupStack::Pop(keysize1);
   190 
   191 			iv = CASN1EncOctetString::NewLC(aParms.IV());
   192 			seq5->AddChildL(iv);
   193 			CleanupStack::Pop(iv);
   194 			break;
   195 		case ECipherRC2_CBC_128:
   196 		case ECipherRC2_CBC_128_16:
   197 			seq5 = CASN1EncSequence::NewLC();
   198 			seq4->AddChildL(seq5);
   199 			CleanupStack::Pop(seq5);
   200 			
   201 			keysize1 = CASN1EncInt::NewLC(58); //encoding for 128 bit
   202 			seq5->AddChildL(keysize1);
   203 			CleanupStack::Pop(keysize1);
   204 
   205 			iv = CASN1EncOctetString::NewLC(aParms.IV());
   206 			seq5->AddChildL(iv);
   207 			CleanupStack::Pop(iv);
   208 			break;
   209 		default:
   210 			User::Leave(KErrNotSupported);
   211 			break;
   212 		}
   213 	CleanupStack::Pop(seq);
   214 	return seq;
   215 	}
   216 
   217 EXPORT_C CPBEncryptParms* TASN1DecPKCS5::DecodeDERL(const TDesC8& aBinaryData)
   218 	{
   219 	TASN1DecGeneric seqGen(aBinaryData);
   220 	seqGen.InitL();
   221 	if (seqGen.Tag() != EASN1Sequence)
   222 		{
   223 		User::Leave(KErrArgument);
   224 		}
   225 	
   226 	//Decode the Algorithm Identifier Sequence
   227 	TASN1DecSequence seq;
   228 	CArrayPtrFlat<TASN1DecGeneric>* seqContents = seq.DecodeDERLC(seqGen);
   229 
   230 	//PbeAlgorithm Id
   231 	if (seqContents->At(0)->Tag() != EASN1ObjectIdentifier)
   232 		{
   233 		User::Leave(KErrArgument);
   234 		}	
   235 	CPBEncryptParms* params = NULL;	
   236 	TASN1DecObjectIdentifier oid;
   237 	HBufC* oiddes = oid.DecodeDERL(*(seqContents->At(0)));
   238 	CleanupStack::PushL(oiddes);
   239 	//Algorithm Id is a pkcs-12Pbe Algorithm Id.
   240 	if(*oiddes != Kpkcs5PBES2)
   241 		{
   242 		// Initialise to impossible value
   243 		TPBECipher cipher = (TPBECipher) -1; 
   244 		// Pbe12Algorithm Ids
   245 		if(*oiddes == KPbeWithSHA1And128BitRC4)
   246 			{
   247 			cipher = ECipherARC4_128;
   248 			}
   249 		else if(*oiddes == KPbeWithSHA1And40BitRC4)
   250 			{
   251 			cipher = ECipherARC4_40;
   252 			}
   253 		else if(*oiddes == KPbeWithSHA1And3_KeyTripleDES_CBC)
   254 			{
   255 			cipher = ECipher3DES_CBC;
   256 			}
   257 		else if(*oiddes == KPbeWithSHA1And2_KeyTripleDES_CBC)
   258 			{
   259 			cipher = ECipher2Key3DES_CBC;
   260 			}
   261 		else if(*oiddes == KPbeWithSHA1And128BitRC2_CBC)
   262 			{
   263 			cipher = ECipherRC2_CBC_128_16; 
   264 			}
   265 		else if(*oiddes == KPbeWithSHA1And40BitRC2_CBC)
   266 			{
   267 			cipher = ECipherRC2_CBC_40_5; 
   268 			}
   269 	    else
   270         	{
   271         	User::Leave(KErrNotSupported);
   272         	}	 
   273         
   274         TInt seqContentsCount = seqContents->Count();
   275 		
   276 		//All pkcs-12Pbe algorithms require the Algorithm Parameters.
   277 		//Algorithm Parameters are not OPTIONAL for pkcs-12Pbe algorithms.
   278 		
   279 		//seqContentsCount should be equal to 2.That is, the Algorithm Id 
   280 		//and associated Algorithm Parameters have to be present.
   281 		if(seqContentsCount != 2)
   282 			{
   283 			User::Leave(KErrArgument);	
   284 			}
   285 		//This if statement checks if the pkcs-12PbeParams Sequence is present in the 
   286 		//AlgorithmIdentifier Sequence Since pkcs-12PbeParams are OPTIONAL
   287 		else 
   288 			{
   289 			//Set the Initialization vector size to 8 bytes.
   290 			TBuf8<KIvSize> iv(KIvSize);
   291 			// Initialized to NULL, if salt is not present.
   292 			TPtrC8 salt;
   293 			TInt iterations; 
   294 
   295 			const TASN1DecGeneric* seqContentsAt1 = seqContents->At(1);
   296 			if (seqContentsAt1->Tag() != EASN1Sequence || seqContentsAt1->Class() != EUniversal)
   297 				{
   298 				User::Leave(KErrArgument);
   299 				}
   300 				
   301 			CArrayPtrFlat<TASN1DecGeneric>* seq1Contents = seq.DecodeDERLC(*seqContentsAt1);
   302 			const TASN1DecGeneric* seq1ContentsAt0 = seq1Contents->At(0);
   303 			if (seq1ContentsAt0->Tag() != EASN1OctetString || seq1ContentsAt0->Class() != EUniversal)
   304 				{
   305 				User::Leave(KErrArgument);
   306 				}
   307 			salt.Set(seq1ContentsAt0->GetContentDER());
   308 			const TASN1DecGeneric* seq1ContentsAt1 = seq1Contents->At(1);
   309 			if (seq1ContentsAt1->Tag() != EASN1Integer || seq1ContentsAt1->Class() != EUniversal)
   310 				{
   311 				User::Leave(KErrArgument);
   312 				}
   313 			TASN1DecInteger integer;
   314 			iterations = integer.DecodeDERShortL(*seq1ContentsAt1);
   315 			if (iterations <= 0)
   316 				{
   317 				User::Leave(KErrArgument);
   318 				}
   319 			params = CPBEncryptParms::NewL(cipher, salt, iv, iterations);
   320 			params->SetKdf(CPBEncryptParms::EKdfPkcs12);
   321 			CleanupStack::PopAndDestroy(seq1Contents);
   322 			}
   323 		}
   324 	//Algorithm Id is a pkcs-5Pbe Algorithm Id.
   325    	 else if (*oiddes == Kpkcs5PBES2)
   326     	{
   327     	if (seqContents->At(1)->Tag() != EASN1Sequence)
   328 			{
   329 			User::Leave(KErrArgument);
   330 			}
   331 		CArrayPtrFlat<TASN1DecGeneric>* seq1Contents = seq.DecodeDERLC(*(seqContents->At(1)));
   332 
   333 		if (seq1Contents->At(0)->Tag() != EASN1Sequence)
   334 			{
   335 			User::Leave(KErrArgument);
   336 			}
   337 		CArrayPtrFlat<TASN1DecGeneric>* seq2Contents = seq.DecodeDERLC(*(seq1Contents->At(0)));
   338 
   339 		if (seq2Contents->At(0)->Tag() != EASN1ObjectIdentifier)
   340 			{
   341 			User::Leave(KErrArgument);
   342 			}
   343 		HBufC* oid1des = oid.DecodeDERL(*(seq2Contents->At(0)));
   344 		CleanupStack::PushL(oid1des);
   345 		
   346 		if(*oid1des != Kpkcs5PBKDF2)
   347 			{
   348 			User::Leave(KErrNotSupported);
   349 			}
   350 		if (seq2Contents->At(1)->Tag() != EASN1Sequence)
   351 			{
   352 			User::Leave(KErrArgument);
   353 			}
   354 		CArrayPtrFlat<TASN1DecGeneric>* seq3Contents = seq.DecodeDERLC(*(seq2Contents->At(1)));
   355 
   356 		if (seq3Contents->At(0)->Tag() != EASN1OctetString)
   357 			{
   358 			User::Leave(KErrArgument);
   359 			}
   360 		TASN1DecOctetString octet;
   361 		HBufC8* salt = octet.DecodeDERL(*(seq3Contents->At(0)));
   362 		CleanupStack::PushL(salt);
   363 		
   364 		if (seq3Contents->At(1)->Tag() != EASN1Integer)
   365 			{
   366 			User::Leave(KErrArgument);
   367 			}
   368 		TASN1DecInteger integer;
   369 		TInt iterations = integer.DecodeDERShortL(*(seq3Contents->At(1)));
   370 
   371 		if (seq1Contents->At(1)->Tag() != EASN1Sequence)
   372 			{
   373 			User::Leave(KErrArgument);
   374 			}
   375 		CArrayPtrFlat<TASN1DecGeneric>* seq4Contents = seq.DecodeDERLC(*(seq1Contents->At(1)));
   376 	
   377 		TPBECipher cipher = (TPBECipher) -1; // Initialise to impossible value
   378 		if (seq4Contents->At(0)->Tag() != EASN1ObjectIdentifier)
   379 			{
   380 			User::Leave(KErrArgument);
   381 			}
   382 		HBufC* oid2des = oid.DecodeDERL(*(seq4Contents->At(0)));
   383 		CleanupStack::PushL(oid2des);
   384 		
   385 		CArrayPtrFlat<TASN1DecGeneric>* seq5Contents = 0; 
   386 
   387 		if(*oid2des == K3DESCBC)
   388 			{
   389 			cipher = ECipher3DES_CBC;
   390 		CleanupStack::PushL(seq5Contents);
   391 			}
   392 		else if(*oid2des == KDESCBC)
   393 			{
   394 			cipher = ECipherDES_CBC;
   395 		CleanupStack::PushL(seq5Contents);
   396 			}
   397 		else if(*oid2des == KRC2CBC)
   398 			{
   399 			// RC2 has an additional parameter, the effective key lenght in octets.
   400 			if (seq3Contents->At(2)->Tag() != EASN1Integer)
   401 				{
   402 				User::Leave(KErrArgument);
   403 				}		
   404 			TInt effectiveKeyLength =  integer.DecodeDERShortL(*(seq3Contents->At(2)));
   405 
   406 			if (seq4Contents->At(1)->Tag() != EASN1Sequence)
   407 				{
   408 				User::Leave(KErrArgument);
   409 				}
   410 			seq5Contents = seq.DecodeDERLC(*(seq4Contents->At(1)));
   411 			if (seq5Contents->At(0)->Tag() != EASN1Integer)
   412 				{
   413 				User::Leave(KErrArgument);
   414 				}
   415 			TInt keysize = integer.DecodeDERShortL(*(seq5Contents->At(0)));
   416 			switch(keysize)
   417 				{
   418 				// These values come from the PKCS#5 v2 specs
   419 				case 160:
   420 					if (effectiveKeyLength == 16)
   421 						{
   422 						cipher = ECipherRC2_CBC_40_16;					
   423 						}
   424 					else 
   425 						{
   426 						if (effectiveKeyLength == 128)
   427 							{
   428 							cipher = ECipherRC2_CBC_40;
   429 							}
   430 						else 
   431 							{
   432 							User::Leave(KErrNotSupported); // Unsupported effective key length!						
   433 							}
   434 						}
   435 					break;
   436 				case 58:
   437 					if (effectiveKeyLength == 16)
   438 						{
   439 						cipher = ECipherRC2_CBC_128_16;					
   440 						}
   441 					else 
   442 						{
   443 						if (effectiveKeyLength == 128)
   444 							{
   445 							cipher = ECipherRC2_CBC_128;
   446 							}
   447 						else 
   448 							{
   449 							User::Leave(KErrNotSupported); // Unsupported effective key length!						
   450 							}
   451 						}			
   452 					break;
   453 				case 120:
   454 					//would be RC_CBC_64 but we don't support that
   455 				default:
   456 					User::Leave(KErrNotSupported);
   457 					break;
   458 				}
   459 			}
   460 		else 
   461 			{
   462 			User::Leave(KErrNotSupported);
   463 			}	
   464 
   465 		HBufC8* iv = 0;
   466 		switch(cipher)
   467 			{
   468 			case ECipher3DES_CBC:
   469 			case ECipherDES_CBC:
   470 				if (seq4Contents->At(1)->Tag() != EASN1OctetString)
   471 					{
   472 					User::Leave(KErrArgument);
   473 					}
   474 				iv = octet.DecodeDERL(*(seq4Contents->At(1)));	
   475 			CleanupStack::PushL(iv);
   476 				break;
   477 			case ECipherRC2_CBC_40:
   478 			case ECipherRC2_CBC_128:
   479 			case ECipherRC2_CBC_40_16:
   480 			case ECipherRC2_CBC_128_16:	
   481 				if (seq5Contents->At(1)->Tag() != EASN1OctetString)
   482 					{
   483 					User::Leave(KErrArgument);
   484 					}
   485 				iv = octet.DecodeDERL(*(seq5Contents->At(1)));
   486 			CleanupStack::PushL(iv);
   487 				break;
   488 			default:
   489 				User::Leave(KErrNotSupported);
   490 				break;
   491 			}
   492 
   493 		params = CPBEncryptParms::NewL(cipher, *salt, *iv,
   494 		iterations);
   495 	CleanupStack::PopAndDestroy(9); //iv, seq5contents, oid2des, seq4Contents,
   496 	//salt, seq3Contents, oid1des, seq2Contents, seq1Contents
   497     	}
   498 	else
   499 		{
   500 		User::Leave(KErrNotSupported);
   501 		}
   502 	CleanupStack::PopAndDestroy(2, seqContents);
   503 	return params;
   504 	}