cryptoservices/certificateandkeymgmt/pkcs7/cmsutils.cpp
changeset 0 2c201484c85f
child 8 35751d3474b7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptoservices/certificateandkeymgmt/pkcs7/cmsutils.cpp	Wed Jul 08 11:25:26 2009 +0100
@@ -0,0 +1,417 @@
+/*
+* Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+
+#include "cmsutils.h"
+#include <asymmetric.h>
+#include <asn1enc.h>
+#include <asn1dec.h> 
+#include <cmsdefs.h>
+#include <pkcs7excert.h>
+#include <x509cert.h>
+#include "pkcs7asn1.h"
+
+
+TInt CmsUtils::DecodeContentTypeL(const TASN1DecGeneric* aASN1DecGeneric)
+	{
+	TInt type(0);
+	if(aASN1DecGeneric->Tag()==EASN1ObjectIdentifier || aASN1DecGeneric->Class() == EUniversal)
+		{
+		TASN1DecObjectIdentifier oidDec;
+		HBufC* oidVal = oidDec.DecodeDERL(*aASN1DecGeneric);
+		CleanupStack::PushL(oidVal);		
+		
+		// Checks if it is data OID.
+		if(*oidVal == KCmsDataOID)
+			{
+			// The Content Type is indicated by an Integer.
+			// Here if Content Type is equal to Data then,it is represented by 1
+			type = EContentTypeData;
+			}
+		else if(*oidVal == KCmsSignedDataOID)
+			{
+			// The Content Type is indicated by an Integer.
+			// Here if Content Type is equal to SignedData then,it is represented by 2
+			type = EContentTypeSignedData;
+			}
+		else if(*oidVal == KCmsEnvelopedDataOID) 
+			{
+			// The Content Type is indicated by an Integer.
+			// Here if Content Type is equal to EnvelopedData then,it is represented by 3.
+			type = EContentTypeEnvelopedData;
+			}
+		else if(*oidVal == KCmsDigestedDataOID)
+			{
+			// The Content Type is indicated by an Integer.
+			// Here if Content Type is equal to DigestedData then,it is represented by 5.
+			type = EContentTypeDigestedData;
+			}
+		else if(*oidVal == KCmsEncryptedDataOID)
+			{
+			// The Content Type is indicated by an Integer.
+			// Here if Content Type is equal to EncryptedData then,it is represented by 6
+			type = EContentTypeEncryptedData;
+			}
+		else if(*oidVal == KCmsAuthenticatedDataOID)
+			{
+			// The Content Type is indicated by an Integer.
+			// Here if Content Type is equal to EncryptedData then,it is represented by 7
+			type = EContentTypeAuthenticatedData;
+			}
+			
+		else
+			{
+			User::Leave(KErrArgument);
+			}
+		CleanupStack::PopAndDestroy(oidVal);
+		}
+	else
+		{
+		User::Leave(KErrArgument);
+		}	
+	return type;
+	}
+
+CASN1EncObjectIdentifier* CmsUtils::EncodeContentTypeLC(TInt aContentType)
+	{
+	TPtrC oidBuf;
+	switch (aContentType)
+		{
+	case EContentTypeData:
+		oidBuf.Set(KCmsDataOID());
+		break;
+		
+	case EContentTypeSignedData:
+		oidBuf.Set(KCmsSignedDataOID());
+		break;
+		
+	case EContentTypeEnvelopedData:
+		oidBuf.Set(KCmsEnvelopedDataOID());
+		break;
+	
+	case EContentTypeDigestedData:
+		oidBuf.Set(KCmsDigestedDataOID());
+		break;
+	
+	case EContentTypeEncryptedData:
+		oidBuf.Set(KCmsEncryptedDataOID());
+		break;
+	
+	default:
+		User::Leave(KErrArgument);
+		}
+	//Encode the OID		
+	CASN1EncObjectIdentifier* oid=CASN1EncObjectIdentifier::NewLC(oidBuf);
+	return oid;	
+	}
+
+void CmsUtils::AddCertificateL(RPointerArray<CCmsCertificateChoice>& aCertList, const TDesC8& aCert, CCmsCertificateChoice::TCertificateType aType)
+	{
+	TInt found(EFalse);
+	TInt count=aCertList.Count();
+	for (TInt i=0;i<count;i++)
+		{
+		if (aCertList[i]->CertificateType()==CCmsCertificateChoice::ECertificateAttribute
+				&& aCert.Compare(*aCertList[i]->AttributeCertificate())==0)
+			{
+			found=ETrue;
+			break;
+			}
+		}
+		
+	if (!found)
+		{
+		CCmsCertificateChoice* cert=CCmsCertificateChoice::NewL(aType, aCert);
+		CleanupStack::PushL(cert);
+		aCertList.AppendL(cert);
+		CleanupStack::Pop(cert);					
+		}
+	}
+	
+void CmsUtils::AddCertificateL(RPointerArray<CCmsCertificateChoice>& aCertList, const CX509Certificate& aCert)
+	{
+	
+	TInt found(EFalse);
+	TInt count=aCertList.Count();
+	for (TInt i=0;i<count;i++)
+		{
+		if (aCertList[i]->CertificateType()==CCmsCertificateChoice::ECertificateX509
+				&& aCert.IsEqualL(aCertList[i]->Certificate()))
+			{
+			found=ETrue;
+			break;
+			}
+		}
+	
+	if (!found)
+		{
+		CCmsCertificateChoice* cert=CCmsCertificateChoice::NewL(aCert);
+		CleanupStack::PushL(cert);
+		aCertList.AppendL(cert);
+		CleanupStack::Pop(cert);					
+		}
+		
+	}
+	
+void CmsUtils::AddAlgorithmIdentifierL(RPointerArray<CX509AlgorithmIdentifier>& aAlgorithmIdList, TAlgorithmId aDigestAlgorithm)
+	{
+	TInt found(EFalse);
+	TInt count=aAlgorithmIdList.Count();
+	for (TInt i=0;i<count;i++)
+		{
+		if (aAlgorithmIdList[i]->Algorithm()==aDigestAlgorithm)
+			{
+			found=ETrue;
+			break;
+			}
+		}
+	if (!found)
+		{
+		CX509AlgorithmIdentifier* digAlg=CX509AlgorithmIdentifier::NewLC(aDigestAlgorithm, KNullDesC8());
+		aAlgorithmIdList.AppendL(digAlg);
+		CleanupStack::Pop(digAlg);					
+		}
+	}
+
+void CmsUtils::DecodeDigestAlgorithmsL(RPointerArray<CX509AlgorithmIdentifier>& aDigestAlgorithms, const TDesC8& aRawData)
+	{
+	CArrayPtr<TASN1DecGeneric>* algsData = PKCS7ASN1::DecodeSequenceLC(aRawData);
+	TInt count = algsData->Count();
+	CX509AlgorithmIdentifier* alIdent;
+
+	for(TInt item = 0; item < count; item++)
+		{
+ 		alIdent = CX509AlgorithmIdentifier::NewLC(algsData->At(item)->Encoding());
+		aDigestAlgorithms.AppendL(alIdent);
+		CleanupStack::Pop(alIdent);
+		}
+	CleanupStack::PopAndDestroy(algsData);			
+	}
+
+void CmsUtils::DecodeCertificatesL(RPointerArray<CCmsCertificateChoice>& aCertificates, const TDesC8& aRawData)
+	{
+	TASN1DecGeneric decGen(aRawData);
+	decGen.InitL();
+	TASN1DecSequence decSeq;
+	// have to do manual decoding of sequence because field is optional
+	CArrayPtr<TASN1DecGeneric>* items = NULL;
+	items = decSeq.DecodeDERLC(decGen);
+	TInt count = items->Count();
+
+	CCmsCertificateChoice* certificate;
+
+	for(TInt item = 0; item < count; item++)
+		{
+ 		certificate = CCmsCertificateChoice::NewL(items->At(item)->Encoding());
+		CleanupStack::PushL(certificate);
+		aCertificates.AppendL(certificate);
+		CleanupStack::Pop(certificate);
+		}
+
+	CleanupStack::PopAndDestroy(items);			
+	}
+
+CASN1EncBase* CmsUtils::EncodeCertificatesLC(const RPointerArray<CCmsCertificateChoice>& aCertificates)
+	{
+	CASN1EncSet* certSet(NULL);
+	TInt count=aCertificates.Count();
+	if (count>0)
+		{
+		certSet = CASN1EncSet::NewLC();
+		for (TInt i=0;i<count;i++)
+			{
+			CASN1EncEncoding* cert=aCertificates[i]->EncodeASN1DERLC();
+			certSet->AddAndPopChildL(cert);
+			}
+		// [0] implicit
+		certSet->SetTag(0);	
+		}
+	return certSet;
+	}
+
+CASN1EncBase* CmsUtils::EncodeDigestAlgorithmsLC(const RPointerArray<CX509AlgorithmIdentifier>& aDigestAlgorithms)
+	{
+	CASN1EncSet* algorithmSet = CASN1EncSet::NewLC();
+	TInt count=aDigestAlgorithms.Count();
+	
+	for (TInt i=0;i<count;i++)
+		{
+		CASN1EncSequence* tmp=aDigestAlgorithms[i]->EncodeASN1DERLC();
+		algorithmSet->AddAndPopChildL(tmp);
+		}
+		
+	return algorithmSet;
+	}
+
+void CmsUtils::DecodeOctetStringL(const TDesC8& aRawData, HBufC8*& aBuf)
+	{
+	TASN1DecGeneric decGen(aRawData);
+	decGen.InitL();
+
+	if(decGen.Tag()==EASN1OctetString && decGen.Class()==EUniversal)
+		{
+		TASN1DecOctetString decOct;
+		aBuf = decOct.DecodeDERL(decGen);
+		}
+	else
+		{
+		User::Leave(KErrArgument);
+		}
+	}
+
+
+CMessageDigest* CmsUtils::CreateHashLC(TAlgorithmId aAlgorithm)
+	{	
+	CMessageDigest* hash(NULL);
+	switch (aAlgorithm)
+		{
+	case EMD2:
+		hash=CMD2::NewL();
+		break;
+		
+	case EMD5:
+		hash=CMD5::NewL();
+		break;
+		
+	case ESHA1:
+		hash=CSHA1::NewL();
+		break;
+		
+	default:
+		User::Leave(KErrNotSupported);
+		}
+	CleanupStack::PushL(hash);
+	return hash;	
+	}
+
+
+HBufC8* CmsUtils::CreateSignatureL(const TDesC8& aDataToBeSigned, TBool aIsHash, TAlgorithmId aAlgorithm, const CDSAPrivateKey& aKey)
+	{
+	HBufC8* signature(NULL);
+	
+	if (!aIsHash)
+		{
+		TPtrC8 hashValue;
+		// Create hash first
+		CMessageDigest* hash=CreateHashLC(aAlgorithm);
+		hashValue.Set(hash->Hash(aDataToBeSigned));
+		signature=CreateSignatureL(hashValue, aKey);
+		CleanupStack::PopAndDestroy(); // hash
+		}
+	else
+		{
+		signature=CreateSignatureL(aDataToBeSigned, aKey);
+		}
+		
+	return signature;
+	}
+
+HBufC8* CmsUtils::CreateSignatureL(const TDesC8& aDataToBeSigned, TBool aIsHash, TAlgorithmId aAlgorithm, const CRSAPrivateKey& aKey)
+	{
+	HBufC8* signature(NULL);
+	TPtrC8 hashValue;
+	if (!aIsHash)
+		{
+		// Create hash first
+		CMessageDigest* hash=CreateHashLC(aAlgorithm);
+		hashValue.Set(hash->Hash(aDataToBeSigned));
+		}
+	else
+		{
+		hashValue.Set(aDataToBeSigned);
+		}
+		
+	//Build the digestInfo Sequence
+	CASN1EncSequence* digestInfoSeq = CASN1EncSequence::NewLC();
+	
+	//Encode the Algorithm
+	CX509AlgorithmIdentifier* digAlg=CX509AlgorithmIdentifier::NewLC(aAlgorithm, KNullDesC8());
+	CASN1EncSequence* sigAlg=digAlg->EncodeASN1DERLC();
+	digestInfoSeq->AddAndPopChildL(sigAlg);
+	CleanupStack::PopAndDestroy(digAlg);
+	
+	//Encode the digest itself
+	CASN1EncOctetString* sigEnc=CASN1EncOctetString::NewLC(hashValue);
+	digestInfoSeq->AddAndPopChildL(sigEnc);
+
+	//Get the Encoding
+	HBufC8* digestInfo=CreateDEREncodingLC(*digestInfoSeq);
+	signature=CreateSignatureL(digestInfo->Des(), aKey);
+	
+	CleanupStack::PopAndDestroy(2, digestInfoSeq); //digestInfo, digestInfoSeq
+	if (!aIsHash)
+		{
+		CleanupStack::PopAndDestroy(); // hash			
+		}
+	return signature;
+	}
+	
+HBufC8* CmsUtils::CreateSignatureL(const TDesC8& aHash, const CDSAPrivateKey& aKey)
+	{	
+	//Create Signer and sign the hash
+	CDSASigner* signer=CDSASigner::NewLC(aKey);
+	const CDSASignature* sig=signer->SignL(aHash);
+	CDSASignature* signonc=const_cast<CDSASignature*>(sig);
+	
+	CleanupStack::PushL(signonc);
+	
+	//The sequence
+	CASN1EncSequence* sigSeq = CASN1EncSequence::NewLC();	
+	CASN1EncBigInt* r = CASN1EncBigInt::NewLC(static_cast<const RInteger&>(sig->R()));
+	sigSeq->AddAndPopChildL(r);
+	CASN1EncBigInt* s = CASN1EncBigInt::NewLC(static_cast<const RInteger&>(sig->S()));
+	sigSeq->AddAndPopChildL(s);
+		
+	//Write the buffer
+	TUint len=sigSeq->LengthDER();
+	HBufC8* buf=HBufC8::NewMaxLC(len);
+	TPtr8 des=buf->Des();
+	TUint pos=0;
+	sigSeq->WriteDERL(des, pos);
+	
+	//Clean up
+	CleanupStack::Pop(buf); //buf
+	CleanupStack::PopAndDestroy(3, signer); //sigSeq, signonc, signer
+	return buf;
+	}
+
+HBufC8* CmsUtils::CreateSignatureL(const TDesC8& aHash, const CRSAPrivateKey& aKey)
+	{
+	//Create Signer and sign the hash
+	CRSAPKCS1v15Signer* signer=CRSAPKCS1v15Signer::NewLC(aKey);
+	const CRSASignature* sig=signer->SignL(aHash);
+	CRSASignature* signonc=const_cast<CRSASignature*>(sig);
+	
+	CleanupStack::PushL(signonc);
+	
+	HBufC8* sigData = sig->S().BufferWithNoTruncationLC();
+	
+	//Clean up
+	CleanupStack::Pop(sigData);
+	CleanupStack::PopAndDestroy(2, signer);//signonc signer
+	return sigData;
+	}
+
+HBufC8* CmsUtils::CreateDEREncodingLC(const CASN1EncBase& aEncoding)
+	{	
+	TUint len = aEncoding.LengthDER();
+	HBufC8* buf = HBufC8::NewMaxLC(len);
+	TUint pos = 0;
+	TPtr8 bufptr(buf->Des());
+	aEncoding.WriteDERL(bufptr, pos);
+	return buf;
+	}