os/security/cryptoservices/certificateandkeymgmt/pkcs7/pkcs7encrypteddataobject.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) 2005-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 "pkcs7encrypteddataobject.h"
sl@0
    20
sl@0
    21
/** The last character in the PKCS7 EncryptedData OID */
sl@0
    22
const TInt KPkcs7EncryptedData = 6;
sl@0
    23
sl@0
    24
EXPORT_C CPKCS7EncryptedDataObject* CPKCS7EncryptedDataObject::NewL(const CPKCS7ContentInfo& aContentInfo)
sl@0
    25
	{
sl@0
    26
	CPKCS7EncryptedDataObject* self = new (ELeave) CPKCS7EncryptedDataObject();
sl@0
    27
	CleanupStack::PushL(self);
sl@0
    28
	self->ConstructL(aContentInfo);
sl@0
    29
	CleanupStack::Pop(self);
sl@0
    30
	return self;	
sl@0
    31
	}
sl@0
    32
sl@0
    33
CPKCS7EncryptedDataObject::CPKCS7EncryptedDataObject(void)
sl@0
    34
	{
sl@0
    35
	}
sl@0
    36
sl@0
    37
CPKCS7EncryptedDataObject::~CPKCS7EncryptedDataObject()
sl@0
    38
	{
sl@0
    39
	delete iEncryptParams;
sl@0
    40
	}
sl@0
    41
sl@0
    42
EXPORT_C TInt CPKCS7EncryptedDataObject::Version() const
sl@0
    43
	{
sl@0
    44
	return iVersion;
sl@0
    45
	}
sl@0
    46
	
sl@0
    47
EXPORT_C CPKCS7EncryptedDataObject::TContentType CPKCS7EncryptedDataObject::ContentType() const
sl@0
    48
	{
sl@0
    49
	return iContentType;
sl@0
    50
	}
sl@0
    51
	
sl@0
    52
EXPORT_C const TDesC8& CPKCS7EncryptedDataObject::EncryptedContentInfoData() const
sl@0
    53
	{
sl@0
    54
	return iEncryptedContent;
sl@0
    55
	}	
sl@0
    56
sl@0
    57
EXPORT_C const CPBEncryptParms& CPKCS7EncryptedDataObject::EncryptParams() const
sl@0
    58
	{
sl@0
    59
	return *iEncryptParams;
sl@0
    60
	}
sl@0
    61
sl@0
    62
CPBEncryptParms* CPKCS7EncryptedDataObject::DecodeContentEncryptionAlgorithmL(const TDesC8& aBinaryData) const
sl@0
    63
	{
sl@0
    64
	TASN1DecGeneric seqGen(aBinaryData);
sl@0
    65
	seqGen.InitL();
sl@0
    66
	if (seqGen.Tag() != EASN1Sequence || seqGen.Class() != EUniversal)
sl@0
    67
		{
sl@0
    68
		User::Leave(KErrArgument);
sl@0
    69
		}
sl@0
    70
	
sl@0
    71
    TPtrC8 theContent(seqGen.Encoding());
sl@0
    72
    CPBEncryptParms* encryptParams =  TASN1DecPKCS5::DecodeDERL(theContent);
sl@0
    73
    return encryptParams;
sl@0
    74
	}	
sl@0
    75
sl@0
    76
EXPORT_C HBufC8* CPKCS7EncryptedDataObject::DecryptDataL(const TDesC& aPassword) const
sl@0
    77
	{
sl@0
    78
	CPBEncryptElement* encryptElement;
sl@0
    79
    HBufC8* pkcs12Pwd = PKCS12KDF::GeneratePasswordLC(aPassword);
sl@0
    80
    if(iEncryptParams->Kdf() == CPBEncryptParms::EKdfPkcs12)
sl@0
    81
		{
sl@0
    82
	 	TPtrC8 iv = iEncryptParams->IV();
sl@0
    83
	    HBufC8* ivValue = HBufC8::NewMaxLC(iv.Length());
sl@0
    84
	    TPtr8 encryptKeyBuf = ivValue->Des();
sl@0
    85
sl@0
    86
	 	switch(iEncryptParams->Cipher())	
sl@0
    87
			{
sl@0
    88
	 		case ECipherARC4_128:
sl@0
    89
	 		case ECipherARC4_40:
sl@0
    90
	 			{
sl@0
    91
	 	    	//derive only key it is unnecessary to derive an IV for RC4
sl@0
    92
	 	    	break;
sl@0
    93
	 			}
sl@0
    94
			case ECipher3DES_CBC:
sl@0
    95
			case ECipher2Key3DES_CBC:
sl@0
    96
			case ECipherRC2_CBC_128_16:	 
sl@0
    97
			case ECipherRC2_CBC_40_5:	
sl@0
    98
				{
sl@0
    99
				PKCS12KDF::DeriveKeyL(encryptKeyBuf, PKCS12KDF::EIDByteIV, *pkcs12Pwd, iEncryptParams->Salt(), iEncryptParams->Iterations());
sl@0
   100
				iEncryptParams->SetIV(encryptKeyBuf);
sl@0
   101
		    	break;
sl@0
   102
				}
sl@0
   103
			default:
sl@0
   104
				{
sl@0
   105
		    	User::Leave(KErrNotSupported);
sl@0
   106
		    	break;
sl@0
   107
				}
sl@0
   108
	 		}
sl@0
   109
	 	CleanupStack::PopAndDestroy(ivValue);
sl@0
   110
		// Create the decryptor	
sl@0
   111
		encryptElement = CPBEncryptElement::NewLC(*pkcs12Pwd, *iEncryptParams);
sl@0
   112
		}
sl@0
   113
	else
sl@0
   114
		{
sl@0
   115
		TPBPassword password(aPassword);
sl@0
   116
		// Create the decryptor	
sl@0
   117
		encryptElement = CPBEncryptElement::NewLC(password.Password(), *iEncryptParams);	
sl@0
   118
		}
sl@0
   119
	 
sl@0
   120
	CPBDecryptor* decryptor = encryptElement->NewDecryptLC();
sl@0
   121
   	
sl@0
   122
	TPtrC8 encryptedKey(iEncryptedContent);
sl@0
   123
	TUint encryptLength = encryptedKey.Length();
sl@0
   124
	TUint maxDecryptLength = decryptor->MaxOutputLength(encryptLength);
sl@0
   125
	
sl@0
   126
	if ( maxDecryptLength <= 0 )
sl@0
   127
		{
sl@0
   128
		User::Leave(KErrGeneral);		
sl@0
   129
		}
sl@0
   130
	
sl@0
   131
	HBufC8* decryptedContent = HBufC8::NewLC(maxDecryptLength);
sl@0
   132
	TPtr8 dcDes(decryptedContent->Des());
sl@0
   133
	decryptor->Process(encryptedKey, dcDes);
sl@0
   134
	CleanupStack::Pop(decryptedContent);
sl@0
   135
	CleanupStack::PopAndDestroy(3, pkcs12Pwd); // pkcs12Pwd, encryptElement, decryptor
sl@0
   136
   	return decryptedContent;
sl@0
   137
   	}
sl@0
   138
sl@0
   139
 void CPKCS7EncryptedDataObject::ConstructL(const CPKCS7ContentInfo& aContentInfo)
sl@0
   140
	{
sl@0
   141
	if(aContentInfo.ContentType() != KPkcs7EncryptedData)
sl@0
   142
		{
sl@0
   143
		User::Leave(KErrArgument);
sl@0
   144
		}
sl@0
   145
    
sl@0
   146
	// EncryptedData SEQUENCE
sl@0
   147
	TASN1DecGeneric decGen(aContentInfo.ContentData());
sl@0
   148
	decGen.InitL();
sl@0
   149
	if(decGen.Tag() != EASN1Sequence || decGen.Class() != EUniversal)
sl@0
   150
		{
sl@0
   151
	    User::Leave(KErrArgument);
sl@0
   152
		}
sl@0
   153
    TASN1DecSequence seq1;
sl@0
   154
    CArrayPtrFlat<TASN1DecGeneric>* EncryptedDataContents = seq1.DecodeDERLC(decGen);       					
sl@0
   155
			    
sl@0
   156
	// Both version and encryptedContentInfo should be present
sl@0
   157
	if (EncryptedDataContents->Count() != 2)
sl@0
   158
		{
sl@0
   159
		User::Leave(KErrArgument);
sl@0
   160
		}
sl@0
   161
		            
sl@0
   162
	// VERSION
sl@0
   163
	// version is the syntax version number. It shall be 0 for this version of the standard
sl@0
   164
	const TASN1DecGeneric* EncryptedDataContentsAt0 = EncryptedDataContents->At(0);
sl@0
   165
	if(EncryptedDataContentsAt0->Tag() != EASN1Integer || EncryptedDataContentsAt0->Class() != EUniversal)
sl@0
   166
		{
sl@0
   167
		User::Leave(KErrArgument);
sl@0
   168
		}
sl@0
   169
	 
sl@0
   170
	TASN1DecInteger intDecoder;
sl@0
   171
	iVersion = intDecoder.DecodeDERShortL(*EncryptedDataContentsAt0);
sl@0
   172
	if (iVersion != 0)
sl@0
   173
		{
sl@0
   174
	    User::Leave(KErrArgument);		
sl@0
   175
	    }
sl@0
   176
		                
sl@0
   177
    // ENCRYPTED CONTENT INFO a SEQUENCE
sl@0
   178
    const TASN1DecGeneric* EncryptedDataContentsAt1 = EncryptedDataContents->At(1);
sl@0
   179
	if (EncryptedDataContentsAt1->Tag() != EASN1Sequence || EncryptedDataContentsAt1->Class() != EUniversal)
sl@0
   180
		{
sl@0
   181
	    User::Leave(KErrArgument);
sl@0
   182
	    }		               
sl@0
   183
	TASN1DecSequence seq2;
sl@0
   184
    CArrayPtrFlat<TASN1DecGeneric>* EncryptedContentInfo = seq2.DecodeDERLC(*EncryptedDataContentsAt1);       
sl@0
   185
		        
sl@0
   186
    // CONTENT TYPE IDENTIFIED BY AN OBJECT IDENTIFIER
sl@0
   187
	// Gets the oid
sl@0
   188
	TASN1DecObjectIdentifier ContentTypeoidDec;
sl@0
   189
	HBufC* contentType = ContentTypeoidDec.DecodeDERL(*EncryptedContentInfo->At(0));
sl@0
   190
	if(contentType->Compare(KPkcs7DataOID()) == 0)
sl@0
   191
		{
sl@0
   192
		iContentType = EPkcs7Data;
sl@0
   193
		}
sl@0
   194
	else
sl@0
   195
		{
sl@0
   196
		User::Leave(KErrNotSupported);
sl@0
   197
		}
sl@0
   198
	delete contentType;	        
sl@0
   199
	// CONTENT ENCRYPTION ALGORITHM
sl@0
   200
	// Get the Cipher used and the encoded params in it
sl@0
   201
    iEncryptParams = DecodeContentEncryptionAlgorithmL(EncryptedContentInfo->At(1)->Encoding());
sl@0
   202
                
sl@0
   203
    // ENCRYPTED CONTENT
sl@0
   204
	// This is an OPTIONAL field
sl@0
   205
	TInt encryptedContentInfoCount = EncryptedContentInfo->Count();
sl@0
   206
	if(encryptedContentInfoCount == 3)
sl@0
   207
		{
sl@0
   208
		TASN1DecGeneric decOctetString(*EncryptedContentInfo->At(2));
sl@0
   209
		decOctetString.InitL();
sl@0
   210
	    iEncryptedContent.Set(decOctetString.GetContentDER());
sl@0
   211
	   	}
sl@0
   212
	else if(encryptedContentInfoCount > 3 || encryptedContentInfoCount < 2)
sl@0
   213
	    {
sl@0
   214
	    User::Leave(KErrArgument);
sl@0
   215
	    }
sl@0
   216
	else if(encryptedContentInfoCount == 2)
sl@0
   217
		{
sl@0
   218
		iEncryptedContent.Set(KNullDesC8());
sl@0
   219
		}
sl@0
   220
sl@0
   221
	CleanupStack::PopAndDestroy(2, EncryptedDataContents); //EncryptedDataContents, EncryptedContentInfo    	
sl@0
   222
	}
sl@0
   223