--- /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;
+ }