--- a/cryptoservices/certificateandkeymgmt/pkcs7/cmssignedobject.cpp Tue Jul 21 01:04:32 2009 +0100
+++ b/cryptoservices/certificateandkeymgmt/pkcs7/cmssignedobject.cpp Thu Sep 10 14:01:51 2009 +0300
@@ -1,896 +1,897 @@
-/*
-* 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 <cmssignedobject.h>
-#include <x509cert.h>
-#include <x509certext.h>
-#include <asymmetrickeys.h>
-#include <hash.h>
-#include <asn1enc.h>
-#include <asn1dec.h>
-#include <pkcs7excert.h>
-#include <cmssigneridentifier.h>
-#include <cmscontentinfo.h>
-#include <cmssignerinfo.h>
-#include "cmsutils.h"
-#include "pkcs7asn1.h"
-
-const TInt KSignedDataCertificates = 0;
-const TInt KSignedDataRevocationLists = 1;
-
-const TInt KCmsMinSignedDataElements = 4;
-//
-// Implementation of CMS Signed object
-//
-EXPORT_C CCmsSignedObject* CCmsSignedObject::NewLC(TCmsContentInfoType aType, TBool aIsDetached, const TDesC8& aContentData)
- {
- CCmsSignedObject* self = new (ELeave) CCmsSignedObject();
- CleanupStack::PushL(self);
- self->ConstructL(aType, aIsDetached, aContentData);
- return self;
- }
-
-EXPORT_C CCmsSignedObject* CCmsSignedObject::NewL(TCmsContentInfoType aType, TBool aIsDetached, const TDesC8& aContentData)
- {
- CCmsSignedObject* self = NewLC(aType, aIsDetached, aContentData);
- CleanupStack::Pop(self);
- return self;
- }
-
-EXPORT_C CCmsSignedObject* CCmsSignedObject::NewLC(TCmsContentInfoType aType,
- const TDesC8& aHashValue,
- TAlgorithmId aDigestAlgorithm,
- const CDSAPrivateKey& aKey,
- const CX509Certificate& aCert,
- TBool aAddCertificate)
- {
- CCmsSignedObject* self = new (ELeave) CCmsSignedObject();
- CleanupStack::PushL(self);
- self->ConstructL(aType, aHashValue, aDigestAlgorithm, aKey, aCert, aAddCertificate);
- return self;
- }
-
-EXPORT_C CCmsSignedObject* CCmsSignedObject::NewL(TCmsContentInfoType aType,
- const TDesC8& aHashValue,
- TAlgorithmId aDigestAlgorithm,
- const CDSAPrivateKey& aKey,
- const CX509Certificate& aCert,
- TBool aAddCertificate)
- {
- CCmsSignedObject* self = NewLC(aType, aHashValue, aDigestAlgorithm, aKey, aCert, aAddCertificate);
- CleanupStack::Pop(self);
- return self;
- }
-
-
-EXPORT_C CCmsSignedObject* CCmsSignedObject::NewLC(TCmsContentInfoType aType,
- const TDesC8& aHashValue,
- TAlgorithmId aDigestAlgorithm,
- const CRSAPrivateKey& aKey,
- const CX509Certificate& aCert,
- TBool aAddCertificate)
- {
- CCmsSignedObject* self = new (ELeave) CCmsSignedObject();
- CleanupStack::PushL(self);
- self->ConstructL(aType, aHashValue, aDigestAlgorithm, aKey, aCert, aAddCertificate);
- return self;
- }
-
-EXPORT_C CCmsSignedObject* CCmsSignedObject::NewL(TCmsContentInfoType aType,
- const TDesC8& aHashValue,
- TAlgorithmId aDigestAlgorithm,
- const CRSAPrivateKey& aKey,
- const CX509Certificate& aCert,
- TBool aAddCertificate)
- {
- CCmsSignedObject* self = NewLC(aType, aHashValue, aDigestAlgorithm, aKey, aCert, aAddCertificate);
- CleanupStack::Pop(self);
- return self;
- }
-
-
-EXPORT_C CCmsSignedObject* CCmsSignedObject::NewL(const CCmsContentInfo& aContentInfo)
- {
- CCmsSignedObject* self = NewLC(aContentInfo);
- CleanupStack::Pop(self);
- return self;
- }
-
-EXPORT_C CCmsSignedObject* CCmsSignedObject::NewLC(const CCmsContentInfo& aContentInfo)
- {
- CCmsSignedObject* self = new (ELeave) CCmsSignedObject();
- CleanupStack::PushL(self);
- self->ConstructL(aContentInfo);
- return self;
- }
-
-CCmsSignedObject::CCmsSignedObject() : iVersion(EVersion_1)
- {
- }
-
-EXPORT_C CCmsSignedObject::~CCmsSignedObject()
- {
- delete iContentInfo;
- iDigestAlgorithms.ResetAndDestroy();
- iCertificates.ResetAndDestroy();
- iSignerInfo.ResetAndDestroy();
- for(TInt i = 0; i < KCmsMaxSignedDataElements; i++)
- {
- delete iDataElements.At(i);
- }
- }
-
-
-EXPORT_C TBool CCmsSignedObject::IsCertificateSetPresent() const
- {
- return iIsCertificateSetPresent;
- }
-
-EXPORT_C TBool CCmsSignedObject::IsCertificateRevocationListsPresent() const
- {
- return iIsCertificateRevocationListsPresent;
- }
-
-EXPORT_C TInt CCmsSignedObject::Version() const
- {
- return iVersion;
- }
-
-EXPORT_C const RPointerArray<CCmsCertificateChoice>& CCmsSignedObject::Certificates() const
- {
- return iCertificates;
- }
-
-EXPORT_C const RPointerArray<CX509AlgorithmIdentifier>& CCmsSignedObject::DigestAlgorithms() const
- {
- return iDigestAlgorithms;
- }
-
-EXPORT_C const CEncapsulatedContentInfo& CCmsSignedObject::ContentInfo() const
- {
- return *iContentInfo;
- }
-
-EXPORT_C const RPointerArray<CCmsSignerInfo>& CCmsSignedObject::SignerInfo() const
- {
- return iSignerInfo;
- }
-
-EXPORT_C void CCmsSignedObject::AddCertificateL(const CX509Certificate& aCert)
- {
- CmsUtils::AddCertificateL(iCertificates, aCert);
- }
-
-void CCmsSignedObject::AddDigestAlgorithmL(TAlgorithmId aDigestAlgorithm)
- {
- CmsUtils::AddAlgorithmIdentifierL(iDigestAlgorithms, aDigestAlgorithm);
- }
-
-EXPORT_C void CCmsSignedObject::AddCertificateL(const TDesC8& aCert, CCmsCertificateChoice::TCertificateType aType)
- {
- if (aType==CCmsCertificateChoice::ECertificateAttribute)
- {
- iVersion=EVersion_3;
- }
- CmsUtils::AddCertificateL(iCertificates, aCert, aType);
- }
-
-void CCmsSignedObject::DecodeSignerInfoL(const TDesC8& aRawData)
- {
- CArrayPtr<TASN1DecGeneric>* signerInfo = PKCS7ASN1::DecodeSequenceLC(aRawData);
- TInt total = signerInfo->Count();
- CCmsSignerInfo* signer(NULL);
-
- for(TInt item = 0; item < total; item ++)
- {
- signer = CCmsSignerInfo::NewL(signerInfo->At(item)->Encoding());
- CleanupStack::PushL(signer);
- User::LeaveIfError(iSignerInfo.Append(signer));
- CleanupStack::Pop(signer);
- }
- CleanupStack::PopAndDestroy(signerInfo);
- }
-
-void CCmsSignedObject::DecodeEncapsulatedContentInfoL(const TDesC8& aRawData)
- {
- iContentInfo = CEncapsulatedContentInfo::NewL(aRawData);
- }
-
-void CCmsSignedObject::ConstructL(const CCmsContentInfo& aContentInfo)
- {
- if(aContentInfo.ContentType() != EContentTypeSignedData)
- {
- User::Leave(KErrArgument);
- }
-
- TASN1DecGeneric decGen(aContentInfo.ContentData());
- decGen.InitL();
-
- if(decGen.Tag() == EASN1Sequence && decGen.Class()==EUniversal)
- {
- InitSignedObjectL(decGen.Encoding());
- DecodeSignedDataL(*iEncoding);
- }
- else
- {
- User::Leave(KErrArgument);
- }
- }
-
-void CCmsSignedObject::ConstructL(TCmsContentInfoType aType, TBool aIsDetached, const TDesC8& aContentData)
- {
- if (aContentData==KNullDesC8() && !aIsDetached)
- {
- User::Leave(KErrArgument);
- }
- iContentInfo=CEncapsulatedContentInfo::NewL(aType, !aIsDetached, aContentData);
- //For later use to create hash if detached and hash not provided
- iContentData.Set(aContentData);
- }
-
-CCmsSignerIdentifier* CCmsSignedObject::BuildSignerIdentifierLC(const CX509Certificate& aCert)
- {
- CCmsSignerIdentifier* sid(NULL);
- const CX509CertExtension* certExt = aCert.Extension(KSubjectKeyId);
- if (certExt)
- {
- CX509SubjectKeyIdExt* ext=CX509SubjectKeyIdExt::NewLC(certExt->Data());
- HBufC8* subKeyId=ext->KeyId().AllocL();
- CleanupStack::PopAndDestroy(ext);
- CleanupStack::PushL(subKeyId);
- sid=CCmsSignerIdentifier::NewL(subKeyId);
- CleanupStack::Pop(subKeyId);
- CleanupStack::PushL(sid);
- iVersion=EVersion_3;
- }
- else
- {
- CX500DistinguishedName* distinguishedName=CX500DistinguishedName::NewLC(aCert.IssuerName());
- CPKCS7IssuerAndSerialNumber* issuerAndSN=CPKCS7IssuerAndSerialNumber::NewL(distinguishedName, aCert.SerialNumber());
- CleanupStack::Pop(distinguishedName);
- CleanupStack::PushL(issuerAndSN);
- sid=CCmsSignerIdentifier::NewL(issuerAndSN);
- CleanupStack::Pop(issuerAndSN);
- CleanupStack::PushL(sid);
- }
- return sid;
- }
-
-
-void CCmsSignedObject::BuildSignerInfoCertListAndAlgoritmListL(TAlgorithmId aDigestAlgorithm,
- TBool aIsHash,
- const TDesC8& aValue,
- const CDSAPrivateKey& aKey,
- const CX509Certificate& aCert,
- TBool aAddCertificate)
- {
- //build Signer Identifier
- CCmsSignerIdentifier* sid=BuildSignerIdentifierLC(aCert);
-
- //build digest algorithm and signing algorithm
- CX509AlgorithmIdentifier* digAlg=CX509AlgorithmIdentifier::NewLC(aDigestAlgorithm, KNullDesC8());
- const CSubjectPublicKeyInfo& publicKeyInfo=aCert.PublicKey();
- CX509AlgorithmIdentifier* signingAlg=CX509AlgorithmIdentifier::NewLC(publicKeyInfo.AlgorithmId(), KNullDesC8());
-
- //build signer info
- CCmsSignerInfo* signerInfo=CCmsSignerInfo::NewL(aValue,
- aIsHash,
- aKey,
- sid,
- digAlg,
- signingAlg);
- CleanupStack::Pop(3, sid);
- CleanupStack::PushL(signerInfo);
- //add to the signer info list
- iSignerInfo.AppendL(signerInfo);
- CleanupStack::Pop();
-
- //Add the certificate to the list if needed
- if (aAddCertificate)
- {
- AddCertificateL(aCert);
- }
-
- //Add the digest algorithm the list if needed
- AddDigestAlgorithmL(aDigestAlgorithm);
- }
-
-
-
-void CCmsSignedObject::BuildSignerInfoCertListAndAlgoritmListL(TAlgorithmId aDigestAlgorithm,
- TBool aIsHash,
- const TDesC8& aValue,
- const CRSAPrivateKey& aKey,
- const CX509Certificate& aCert,
- TBool aAddCertificate)
-
- {
- //build Signer Identifier
- CCmsSignerIdentifier* sid=BuildSignerIdentifierLC(aCert);
-
- //build digest algorithm and signing algorithm
- CX509AlgorithmIdentifier* digAlg=CX509AlgorithmIdentifier::NewLC(aDigestAlgorithm, KNullDesC8());
- const CSubjectPublicKeyInfo& publicKeyInfo=aCert.PublicKey();
- CX509AlgorithmIdentifier* signingAlg=CX509AlgorithmIdentifier::NewLC(publicKeyInfo.AlgorithmId(), publicKeyInfo.EncodedParams());
-
- //build signer info
- CCmsSignerInfo* signerInfo=CCmsSignerInfo::NewL(aValue,
- aIsHash,
- aKey,
- sid,
- digAlg,
- signingAlg);
- CleanupStack::Pop(3, sid);
- CleanupStack::PushL(signerInfo);
- //add to the signer info list
- iSignerInfo.AppendL(signerInfo);
- CleanupStack::Pop();
-
- //Add the certificate to the list if needed
- if (aAddCertificate)
- {
- AddCertificateL(aCert);
- }
-
- //Add the digest algorithm the list if needed
- AddDigestAlgorithmL(aDigestAlgorithm);
- }
-
-void CCmsSignedObject::ConstructL(TCmsContentInfoType aType,
- const TDesC8& aHashValue,
- TAlgorithmId aDigestAlgorithm,
- const CDSAPrivateKey& aKey,
- const CX509Certificate& aCert,
- TBool aAddCertificate)
- {
- //Set the CMS object version to version 3 if the encapsulatedconetent data type is not data
- if (aType != EContentTypeData)
- {
- iVersion=EVersion_3;
- }
-
- //build EncapsulatedContentInfo
- iContentInfo=CEncapsulatedContentInfo::NewL(aType, EFalse, KNullDesC8());
-
- BuildSignerInfoCertListAndAlgoritmListL(aDigestAlgorithm,
- ETrue,
- aHashValue,
- aKey,
- aCert,
- aAddCertificate);
-
- }
-void CCmsSignedObject::ConstructL(TCmsContentInfoType aType,
- const TDesC8& aHashValue,
- TAlgorithmId aDigestAlgorithm,
- const CRSAPrivateKey& aKey,
- const CX509Certificate& aCert,
- TBool aAddCertificate)
- {
- //Set the CMS object version to version 3 if the encapsulatedconetent data type is not data
- if (aType != EContentTypeData)
- {
- iVersion=EVersion_3;
- }
-
- //build EncapsulatedContentInfo
- iContentInfo=CEncapsulatedContentInfo::NewL(aType, EFalse, KNullDesC8());
-
- BuildSignerInfoCertListAndAlgoritmListL(aDigestAlgorithm,
- ETrue,
- aHashValue,
- aKey,
- aCert,
- aAddCertificate);
- }
-
-
-EXPORT_C void CCmsSignedObject::SignL(const TDesC8& aHashValue,
- TAlgorithmId aDigestAlgorithm,
- const CDSAPrivateKey& aKey,
- const CX509Certificate& aCert,
- TBool aAddCertificate)
-
- {
- TBool isHash=(aHashValue!=KNullDesC8())? ETrue:EFalse;
- if (isHash)
- {
- BuildSignerInfoCertListAndAlgoritmListL(aDigestAlgorithm,
- isHash,
- aHashValue,
- aKey,
- aCert,
- aAddCertificate);
- }
- else
- {
- if (iContentData!=KNullDesC8())
- {
- BuildSignerInfoCertListAndAlgoritmListL(aDigestAlgorithm,
- isHash,
- iContentData,
- aKey,
- aCert,
- aAddCertificate);
- }
- else
- {
- //No way to sign if no data content nor its hash.
- User::Leave(KErrArgument);
- }
- }
- }
-
-EXPORT_C void CCmsSignedObject::SignL(const TDesC8& aHashValue,
- TAlgorithmId aDigestAlgorithm,
- const CRSAPrivateKey& aKey,
- const CX509Certificate& aCert,
- TBool aAddCertificate)
- {
- TBool isHash=(aHashValue!=KNullDesC8())? ETrue:EFalse;
- if (isHash)
- {
- BuildSignerInfoCertListAndAlgoritmListL(aDigestAlgorithm,
- isHash,
- aHashValue,
- aKey,
- aCert,
- aAddCertificate);
- }
- else
- {
- if (iContentData!=KNullDesC8())
- {
- BuildSignerInfoCertListAndAlgoritmListL(aDigestAlgorithm,
- isHash,
- iContentData,
- aKey,
- aCert,
- aAddCertificate);
- }
- else
- {
- //No way to sign if no data content nor its hash.
- User::Leave(KErrArgument);
- }
- }
- }
-
-
-EXPORT_C CASN1EncSequence* CCmsSignedObject::EncodeASN1DERLC() const
- {
- // the root sequence contains the signed object
- CASN1EncSequence* root = CASN1EncSequence::NewLC();
-
- // Encode version
- CASN1EncInt* version=CASN1EncInt::NewLC(iVersion);
- root->AddAndPopChildL(version);
-
- // Encode Algorithm
- CASN1EncBase* algorithm=EncodeAlgorithmsLC();
- root->AddAndPopChildL(algorithm);
-
-
- // Encode EncapsulatedContentInfo
- CASN1EncSequence* contentInfo=iContentInfo->EncodeASN1DERLC();
- root->AddAndPopChildL(contentInfo);
-
- // Encode option fields certificates SET
- CASN1EncBase* cert=EncodeCertificatesLC();
- if (cert)
- {
- root->AddAndPopChildL(cert);
- }
-
- // Encode signerinfo
- CASN1EncBase* signerInfo=EncodeSignerInfoLC();
- root->AddAndPopChildL(signerInfo);
-
- return root;
- }
-
-
-CASN1EncBase* CCmsSignedObject::EncodeCertificatesLC() const
- {
- return CmsUtils::EncodeCertificatesLC(iCertificates);
- }
-
-CASN1EncBase* CCmsSignedObject::EncodeAlgorithmsLC() const
- {
- return CmsUtils::EncodeDigestAlgorithmsLC(iDigestAlgorithms);
- }
-
-CASN1EncBase* CCmsSignedObject::EncodeSignerInfoLC() const
- {
- CASN1EncSet* signerInfoSet = CASN1EncSet::NewLC();
- TInt count=iSignerInfo.Count();
-
- for (TInt i=0;i<count;i++)
- {
- CASN1EncSequence* signerInfo=iSignerInfo[i]->EncodeASN1DERLC();
- signerInfoSet->AddAndPopChildL(signerInfo);
- }
- return signerInfoSet;
- }
-
-EXPORT_C TBool CCmsSignedObject::ValidateSignerLC(const CCmsSignerInfo& aSignerInfo, HBufC8*& aCertChainEncoding)
- {
- TInt certCount = iCertificates.Count();
- TInt endEntityPos = -1;
- TInt endEncodingSize = 0;
- TPtrC8 endEntityEncoding;
- TInt cert;
- TBool valid = EFalse;
-
- const CCmsSignerIdentifier& signerId = aSignerInfo.SignerIdentifier();
-
- // looks for end entity certificate
- for(cert = 0; cert < certCount; cert++)
- {
- if (iCertificates[cert]->CertificateType()==CCmsCertificateChoice::ECertificateX509)
- {
- const CX509Certificate& certificate = iCertificates[cert]->Certificate();
-
- endEncodingSize+= certificate.Encoding().Length();
-
- if(endEntityPos == -1)
- {
- if (signerId.SignerIdentifierType()==CCmsSignerIdentifier::EIssuerAndSerialNumber)
- {
- if (certificate.IssuerName().ExactMatchL(signerId.IssuerAndSerialNumber()->IssuerName()))
- {
- RInteger sn1=RInteger::NewL(certificate.SerialNumber());
- CleanupClosePushL(sn1);
- RInteger sn2=RInteger::NewL(signerId.IssuerAndSerialNumber()->SerialNumber());
- CleanupClosePushL(sn2);
- if (sn1==sn2)
- {
- endEntityPos = cert;
- endEntityEncoding.Set(certificate.Encoding());
- valid = ValidateSignatureL(aSignerInfo, certificate);
- }
- CleanupStack::PopAndDestroy(2, &sn1);//sn2, sn1
- }
- }
- else
- {
- const CX509CertExtension* certExt = certificate.Extension(KSubjectKeyId);
- if (certExt)
- {
- CX509SubjectKeyIdExt* ext=CX509SubjectKeyIdExt::NewLC(certExt->Data());
- if (signerId.SubjectKeyIdentifier().Compare(ext->KeyId())==0)
- {
- endEntityPos = cert;
- endEntityEncoding.Set(certificate.Encoding());
- valid = ValidateSignatureL(aSignerInfo, certificate);
- }
- CleanupStack::PopAndDestroy(ext);
- }
- }
- }
- }
- }
-
- // checks if end entity was found
- if(endEntityPos != -1)
- {
- // builds the cert chain encoding by putting the end entity first then all remaining
- // certs
- aCertChainEncoding = HBufC8::NewLC(endEncodingSize);
- TPtr8 encodingPtr(aCertChainEncoding->Des());
- encodingPtr.Copy(endEntityEncoding);
- for(cert = 0; cert < certCount; cert++)
- {
- if (iCertificates[cert]->CertificateType()==CCmsCertificateChoice::ECertificateX509)
- {
- const CX509Certificate& certificate = iCertificates[cert]->Certificate();
- if(cert != endEntityPos)
- {
- encodingPtr.Append(certificate.Encoding());
- }
- }
- }
- }
- else
- {
- User::Leave(KErrNotFound);
- }
- return valid;
- }
-
-
-EXPORT_C TBool CCmsSignedObject::ValidateSignerLC(const CCmsSignerInfo& aSignerInfo, const RPointerArray<CX509Certificate>& aCertificates, HBufC8*& aCertChainEncoding)
- {
- TInt certCount = aCertificates.Count();
- TInt endEntityPos = -1;
- TInt endEncodingSize = 0;
- TPtrC8 endEntityEncoding;
- TInt cert;
- TBool valid = EFalse;
- const CCmsSignerIdentifier& signerId = aSignerInfo.SignerIdentifier();
-
- // looks for end entity certificate
- for(cert = 0; cert < certCount; cert++)
- {
- const CX509Certificate& certificate = *aCertificates[cert];
- endEncodingSize+= certificate.Encoding().Length();
- if(endEntityPos == -1)
- {
- if (signerId.SignerIdentifierType()==CCmsSignerIdentifier::EIssuerAndSerialNumber)
- {
- if (certificate.IssuerName().ExactMatchL(signerId.IssuerAndSerialNumber()->IssuerName()))
- {
- RInteger sn1=RInteger::NewL(certificate.SerialNumber());
- CleanupClosePushL(sn1);
- RInteger sn2=RInteger::NewL(signerId.IssuerAndSerialNumber()->SerialNumber());
- CleanupClosePushL(sn2);
- if (sn1==sn2)
- {
- endEntityPos = cert;
- endEntityEncoding.Set(certificate.Encoding());
- valid = ValidateSignatureL(aSignerInfo, certificate);
- }
- CleanupStack::PopAndDestroy(2, &sn1);//sn2, sn1
- }
- }
- else
- {
- const CX509CertExtension* certExt = certificate.Extension(KSubjectKeyId);
- if (certExt)
- {
- CX509SubjectKeyIdExt* ext=CX509SubjectKeyIdExt::NewLC(certExt->Data());
- if (signerId.SubjectKeyIdentifier().Compare(ext->KeyId())==0)
- {
- endEntityPos = cert;
- endEntityEncoding.Set(certificate.Encoding());
- valid = ValidateSignatureL(aSignerInfo, certificate);
- }
- CleanupStack::PopAndDestroy(ext);
- }
- }
- }
- }
-
- // checks if end entity was found
- if(endEntityPos != -1)
- {
- // builds the cert chain encoding by putting the end entity first then all remaining
- // certs
- aCertChainEncoding = HBufC8::NewLC(endEncodingSize);
- TPtr8 encodingPtr(aCertChainEncoding->Des());
- encodingPtr.Copy(endEntityEncoding);
- for(cert = 0; cert < certCount; cert++)
- {
- const CX509Certificate& certificate = *aCertificates[cert];
-
- if(cert != endEntityPos)
- {
- encodingPtr.Append(certificate.Encoding());
- }
- }
- }
- else
- {
- User::Leave(KErrNotFound);
- }
-
- return valid;
- }
-
-
-EXPORT_C TBool CCmsSignedObject::ValidateSignerLC(const CCmsSignerInfo& aSignerInfo, HBufC8*& aCertChainEncoding, TBool aIsHash, const TDesC8& aContentDataOrHash)
- {
- if (aIsHash)
- {
- SetHash(aContentDataOrHash);
- }
- else
- {
- SetContentData(aContentDataOrHash);
- }
- return ValidateSignerLC(aSignerInfo, aCertChainEncoding);
- }
-
-EXPORT_C TBool CCmsSignedObject::ValidateSignerLC(const CCmsSignerInfo& aSignerInfo, const RPointerArray<CX509Certificate>& aCertificates, HBufC8*& aCertChainEncoding, TBool aIsHash, const TDesC8& aContentDataOrHash)
- {
- if (aIsHash)
- {
- SetHash(aContentDataOrHash);
- }
- else
- {
- SetContentData(aContentDataOrHash);
- }
- return ValidateSignerLC(aSignerInfo, aCertificates, aCertChainEncoding);
- }
-
-TBool CCmsSignedObject::ValidateSignatureL(const CCmsSignerInfo& aSignerInfo, const CX509Certificate& aEndEntityCert)
- {
- delete iSigningAlgorithm;
- iSigningAlgorithm = NULL;
- iSigningAlgorithm = CX509SigningAlgorithmIdentifier::NewL(aSignerInfo.SignatureAlgorithm(), aSignerInfo.DigestAlgorithm());
-
- delete iSignature;
- iSignature = NULL;
- iSignature = aSignerInfo.SignatureValue().AllocL();
-
- if (aSignerInfo.SignatureAlgorithm().Algorithm()==EDSA)
- {
- delete iParameters;
- iParameters = NULL;
- CDSAParameters* theDSAParams = iKeyFactory->DSAParametersL(aEndEntityCert.PublicKey().EncodedParams());
- CleanupStack::PushL(theDSAParams);
- CSigningKeyParameters* params = CSigningKeyParameters::NewLC();
- params->SetDSAParamsL(*theDSAParams);
- SetParametersL(*params);
- CleanupStack::PopAndDestroy(2, theDSAParams);
- }
-
- if (iContentInfo->IsContentDataPresent() || iContentData != KNullDesC8)
- {
- return VerifySignatureL(aEndEntityCert.PublicKey().KeyData());
- }
- else if (iHash!=KNullDesC8)
- {
- return VerifySignatureL(aEndEntityCert.PublicKey().KeyData(), iHash);
- }
- else
- {
- User::Leave(KErrArgument);
- return EFalse;
- }
-
- }
-
-void CCmsSignedObject::InitSignedObjectL(const TDesC8& aRawData)
- {
- // Populate CSignedObject data members
- iKeyFactory = new (ELeave) TX509KeyFactory;
- iEncoding = aRawData.AllocL();
-
- CSHA1* hash = CSHA1::NewL();
- CleanupStack::PushL(hash);
- iFingerprint = hash->Hash(Encoding()).AllocL();
- CleanupStack::PopAndDestroy(hash);
- }
-
-void CCmsSignedObject::DecodeSignedDataL(const TDesC8& aRawData)
- {
- CArrayPtr<TASN1DecGeneric>* signedData = PKCS7ASN1::DecodeSequenceLC(aRawData, KCmsMinSignedDataElements, KCmsMaxSignedDataElements);
- TInt totalItems = signedData->Count();
- TASN1DecInteger decInt;
-
- // decodes version
- iDataElements.At(EVersionNumber) = new(ELeave) TPtrC8(signedData->At(0)->GetContentDER());
- iVersion = decInt.DecodeDERShortL(*signedData->At(0));
- if (iVersion>4 || iVersion<0)
- {
- User::Leave(KErrArgument);
- }
- // decodes algorithms
- iDataElements.At(EDigestAlgorithms) = new(ELeave) TPtrC8(signedData->At(1)->GetContentDER());
- DecodeDigestAlgorithmsL(signedData->At(1)->Encoding());
- // decodes contentinfo
- iDataElements.At(EEncapsulatedContentInfo) = new(ELeave) TPtrC8(signedData->At(2)->GetContentDER());
- DecodeEncapsulatedContentInfoL(signedData->At(2)->Encoding());
-
- // Checks for optional fields
- TInt pos = 3; // Skip first non-optional fields
- do
- {
- const TASN1DecGeneric& currentItem = *signedData->At(pos);
- switch(currentItem.Tag())
- {
- case KSignedDataCertificates:
- {
- if (currentItem.Class()!=EContextSpecific)
- {
- User::Leave(KErrArgument);
- }
- iIsCertificateSetPresent=ETrue;
- iDataElements.At(ECertificates) = new(ELeave) TPtrC8(currentItem.GetContentDER());
- DecodeCertificatesL(currentItem.Encoding());
- break;
- }
- case KSignedDataRevocationLists:
- {
- if (currentItem.Class()!=EContextSpecific)
- {
- User::Leave(KErrArgument);
- }
- iIsCertificateRevocationListsPresent=ETrue;
- iDataElements.At(ERevocationLists) = new(ELeave) TPtrC8(currentItem.GetContentDER());
- DecodeRevocationListsL(currentItem.Encoding());
- break;
- }
- default:
- {
- //Optional field with wrong tag and class
- if (pos<totalItems-1)
- {
- User::Leave(KErrArgument);
- }
- // else Non-optional field
- }
- }
- pos++;
- }
- while(pos < totalItems);
-
- iDataElements.At(ESignedInfo) = new(ELeave) TPtrC8(signedData->At(totalItems-1)->GetContentDER());
- DecodeSignerInfoL(signedData->At(totalItems-1)->Encoding());
-
- CleanupStack::PopAndDestroy(signedData);
- }
-
-void CCmsSignedObject::DecodeDigestAlgorithmsL(const TDesC8& aRawData)
- {
- CmsUtils::DecodeDigestAlgorithmsL(iDigestAlgorithms, aRawData);
- }
-
-void CCmsSignedObject::DecodeCertificatesL(const TDesC8& aRawData)
- {
- CmsUtils::DecodeCertificatesL(iCertificates, aRawData);
- }
-
-void CCmsSignedObject::DecodeRevocationListsL(const TDesC8& /*aRawData*/)
- {
- }
-
-EXPORT_C const TPtrC8 CCmsSignedObject::SignedDataL() const
- {
- if (iContentInfo->IsContentDataPresent())
- {
- return iContentInfo->ContentData();
- }
- else
- {
- if (iContentData!=KNullDesC8)
- {
- return iContentData;
- }
- else
- {
- User::Leave(KErrArgument);
- }
- }
- return KNullDesC8();
- }
-
-EXPORT_C void CCmsSignedObject::InternalizeL(RReadStream& /*aStream*/)
- {
- User::Leave(KErrNotSupported);
- }
-
-EXPORT_C const TPtrC8* CCmsSignedObject::DataElementEncoding(const TUint aIndex) const
- {
- return iDataElements.At(aIndex);
- }
-
-void CCmsSignedObject::SetContentData(const TDesC8& aContentData)
- {
- iContentData.Set(aContentData);
- }
-
-void CCmsSignedObject::SetHash(const TDesC8& aHash)
- {
- iHash.Set(aHash);
- }
-
-
-
+/*
+* 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 <cmssignedobject.h>
+#include <x509cert.h>
+#include <x509certext.h>
+#include <asymmetrickeys.h>
+#include <hash.h>
+#include <asn1enc.h>
+#include <asn1dec.h>
+#include <pkcs7excert.h>
+#include <cmssigneridentifier.h>
+#include <cmscontentinfo.h>
+#include <cmssignerinfo.h>
+#include "cmsutils.h"
+#include "pkcs7asn1.h"
+
+const TInt KSignedDataCertificates = 0;
+const TInt KSignedDataRevocationLists = 1;
+
+const TInt KCmsMinSignedDataElements = 4;
+//
+// Implementation of CMS Signed object
+//
+EXPORT_C CCmsSignedObject* CCmsSignedObject::NewLC(TCmsContentInfoType aType, TBool aIsDetached, const TDesC8& aContentData)
+ {
+ CCmsSignedObject* self = new (ELeave) CCmsSignedObject();
+ CleanupStack::PushL(self);
+ self->ConstructL(aType, aIsDetached, aContentData);
+ return self;
+ }
+
+EXPORT_C CCmsSignedObject* CCmsSignedObject::NewL(TCmsContentInfoType aType, TBool aIsDetached, const TDesC8& aContentData)
+ {
+ CCmsSignedObject* self = NewLC(aType, aIsDetached, aContentData);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+EXPORT_C CCmsSignedObject* CCmsSignedObject::NewLC(TCmsContentInfoType aType,
+ const TDesC8& aHashValue,
+ TAlgorithmId aDigestAlgorithm,
+ const CDSAPrivateKey& aKey,
+ const CX509Certificate& aCert,
+ TBool aAddCertificate)
+ {
+ CCmsSignedObject* self = new (ELeave) CCmsSignedObject();
+ CleanupStack::PushL(self);
+ self->ConstructL(aType, aHashValue, aDigestAlgorithm, aKey, aCert, aAddCertificate);
+ return self;
+ }
+
+EXPORT_C CCmsSignedObject* CCmsSignedObject::NewL(TCmsContentInfoType aType,
+ const TDesC8& aHashValue,
+ TAlgorithmId aDigestAlgorithm,
+ const CDSAPrivateKey& aKey,
+ const CX509Certificate& aCert,
+ TBool aAddCertificate)
+ {
+ CCmsSignedObject* self = NewLC(aType, aHashValue, aDigestAlgorithm, aKey, aCert, aAddCertificate);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+
+EXPORT_C CCmsSignedObject* CCmsSignedObject::NewLC(TCmsContentInfoType aType,
+ const TDesC8& aHashValue,
+ TAlgorithmId aDigestAlgorithm,
+ const CRSAPrivateKey& aKey,
+ const CX509Certificate& aCert,
+ TBool aAddCertificate)
+ {
+ CCmsSignedObject* self = new (ELeave) CCmsSignedObject();
+ CleanupStack::PushL(self);
+ self->ConstructL(aType, aHashValue, aDigestAlgorithm, aKey, aCert, aAddCertificate);
+ return self;
+ }
+
+EXPORT_C CCmsSignedObject* CCmsSignedObject::NewL(TCmsContentInfoType aType,
+ const TDesC8& aHashValue,
+ TAlgorithmId aDigestAlgorithm,
+ const CRSAPrivateKey& aKey,
+ const CX509Certificate& aCert,
+ TBool aAddCertificate)
+ {
+ CCmsSignedObject* self = NewLC(aType, aHashValue, aDigestAlgorithm, aKey, aCert, aAddCertificate);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+
+EXPORT_C CCmsSignedObject* CCmsSignedObject::NewL(const CCmsContentInfo& aContentInfo)
+ {
+ CCmsSignedObject* self = NewLC(aContentInfo);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+EXPORT_C CCmsSignedObject* CCmsSignedObject::NewLC(const CCmsContentInfo& aContentInfo)
+ {
+ CCmsSignedObject* self = new (ELeave) CCmsSignedObject();
+ CleanupStack::PushL(self);
+ self->ConstructL(aContentInfo);
+ return self;
+ }
+
+CCmsSignedObject::CCmsSignedObject() : iVersion(EVersion_1)
+ {
+ }
+
+EXPORT_C CCmsSignedObject::~CCmsSignedObject()
+ {
+ delete iContentInfo;
+ iDigestAlgorithms.ResetAndDestroy();
+ iCertificates.ResetAndDestroy();
+ iSignerInfo.ResetAndDestroy();
+ for(TInt i = 0; i < KCmsMaxSignedDataElements; i++)
+ {
+ delete iDataElements.At(i);
+ }
+ }
+
+
+EXPORT_C TBool CCmsSignedObject::IsCertificateSetPresent() const
+ {
+ return iIsCertificateSetPresent;
+ }
+
+EXPORT_C TBool CCmsSignedObject::IsCertificateRevocationListsPresent() const
+ {
+ return iIsCertificateRevocationListsPresent;
+ }
+
+EXPORT_C TInt CCmsSignedObject::Version() const
+ {
+ return iVersion;
+ }
+
+EXPORT_C const RPointerArray<CCmsCertificateChoice>& CCmsSignedObject::Certificates() const
+ {
+ return iCertificates;
+ }
+
+EXPORT_C const RPointerArray<CX509AlgorithmIdentifier>& CCmsSignedObject::DigestAlgorithms() const
+ {
+ return iDigestAlgorithms;
+ }
+
+EXPORT_C const CEncapsulatedContentInfo& CCmsSignedObject::ContentInfo() const
+ {
+ return *iContentInfo;
+ }
+
+EXPORT_C const RPointerArray<CCmsSignerInfo>& CCmsSignedObject::SignerInfo() const
+ {
+ return iSignerInfo;
+ }
+
+EXPORT_C void CCmsSignedObject::AddCertificateL(const CX509Certificate& aCert)
+ {
+ CmsUtils::AddCertificateL(iCertificates, aCert);
+ }
+
+void CCmsSignedObject::AddDigestAlgorithmL(TAlgorithmId aDigestAlgorithm)
+ {
+ CmsUtils::AddAlgorithmIdentifierL(iDigestAlgorithms, aDigestAlgorithm);
+ }
+
+EXPORT_C void CCmsSignedObject::AddCertificateL(const TDesC8& aCert, CCmsCertificateChoice::TCertificateType aType)
+ {
+ if (aType==CCmsCertificateChoice::ECertificateAttribute)
+ {
+ iVersion=EVersion_3;
+ }
+ CmsUtils::AddCertificateL(iCertificates, aCert, aType);
+ }
+
+void CCmsSignedObject::DecodeSignerInfoL(const TDesC8& aRawData)
+ {
+ CArrayPtr<TASN1DecGeneric>* signerInfo = PKCS7ASN1::DecodeSequenceLC(aRawData);
+ TInt total = signerInfo->Count();
+ CCmsSignerInfo* signer(NULL);
+
+ for(TInt item = 0; item < total; item ++)
+ {
+ signer = CCmsSignerInfo::NewL(signerInfo->At(item)->Encoding());
+ CleanupStack::PushL(signer);
+ User::LeaveIfError(iSignerInfo.Append(signer));
+ CleanupStack::Pop(signer);
+ }
+ CleanupStack::PopAndDestroy(signerInfo);
+ }
+
+void CCmsSignedObject::DecodeEncapsulatedContentInfoL(const TDesC8& aRawData)
+ {
+ iContentInfo = CEncapsulatedContentInfo::NewL(aRawData);
+ }
+
+void CCmsSignedObject::ConstructL(const CCmsContentInfo& aContentInfo)
+ {
+ if(aContentInfo.ContentType() != EContentTypeSignedData)
+ {
+ User::Leave(KErrArgument);
+ }
+
+ TASN1DecGeneric decGen(aContentInfo.ContentData());
+ decGen.InitL();
+
+ if(decGen.Tag() == EASN1Sequence && decGen.Class()==EUniversal)
+ {
+ InitSignedObjectL(decGen.Encoding());
+ DecodeSignedDataL(*iEncoding);
+ }
+ else
+ {
+ User::Leave(KErrArgument);
+ }
+ }
+
+void CCmsSignedObject::ConstructL(TCmsContentInfoType aType, TBool aIsDetached, const TDesC8& aContentData)
+ {
+ if (aContentData==KNullDesC8() && !aIsDetached)
+ {
+ User::Leave(KErrArgument);
+ }
+ iContentInfo=CEncapsulatedContentInfo::NewL(aType, !aIsDetached, aContentData);
+ //For later use to create hash if detached and hash not provided
+ iContentData.Set(aContentData);
+ }
+
+CCmsSignerIdentifier* CCmsSignedObject::BuildSignerIdentifierLC(const CX509Certificate& aCert)
+ {
+ CCmsSignerIdentifier* sid(NULL);
+ const CX509CertExtension* certExt = aCert.Extension(KSubjectKeyId);
+ if (certExt)
+ {
+ CX509SubjectKeyIdExt* ext=CX509SubjectKeyIdExt::NewLC(certExt->Data());
+ HBufC8* subKeyId=ext->KeyId().AllocL();
+ CleanupStack::PopAndDestroy(ext);
+ CleanupStack::PushL(subKeyId);
+ sid=CCmsSignerIdentifier::NewL(subKeyId);
+ CleanupStack::Pop(subKeyId);
+ CleanupStack::PushL(sid);
+ iVersion=EVersion_3;
+ }
+ else
+ {
+ CX500DistinguishedName* distinguishedName=CX500DistinguishedName::NewLC(aCert.IssuerName());
+ CPKCS7IssuerAndSerialNumber* issuerAndSN=CPKCS7IssuerAndSerialNumber::NewL(distinguishedName, aCert.SerialNumber());
+ CleanupStack::Pop(distinguishedName);
+ CleanupStack::PushL(issuerAndSN);
+ sid=CCmsSignerIdentifier::NewL(issuerAndSN);
+ CleanupStack::Pop(issuerAndSN);
+ CleanupStack::PushL(sid);
+ }
+ return sid;
+ }
+
+
+void CCmsSignedObject::BuildSignerInfoCertListAndAlgoritmListL(TAlgorithmId aDigestAlgorithm,
+ TBool aIsHash,
+ const TDesC8& aValue,
+ const CDSAPrivateKey& aKey,
+ const CX509Certificate& aCert,
+ TBool aAddCertificate)
+ {
+ //build Signer Identifier
+ CCmsSignerIdentifier* sid=BuildSignerIdentifierLC(aCert);
+
+ //build digest algorithm and signing algorithm
+ CX509AlgorithmIdentifier* digAlg=CX509AlgorithmIdentifier::NewLC(aDigestAlgorithm, KNullDesC8());
+ const CSubjectPublicKeyInfo& publicKeyInfo=aCert.PublicKey();
+ CX509AlgorithmIdentifier* signingAlg=CX509AlgorithmIdentifier::NewLC(publicKeyInfo.AlgorithmId(), KNullDesC8());
+
+ //build signer info
+ CCmsSignerInfo* signerInfo=CCmsSignerInfo::NewL(aValue,
+ aIsHash,
+ aKey,
+ sid,
+ digAlg,
+ signingAlg);
+ CleanupStack::Pop(3, sid);
+ CleanupStack::PushL(signerInfo);
+ //add to the signer info list
+ iSignerInfo.AppendL(signerInfo);
+ CleanupStack::Pop();
+
+ //Add the certificate to the list if needed
+ if (aAddCertificate)
+ {
+ AddCertificateL(aCert);
+ }
+
+ //Add the digest algorithm the list if needed
+ AddDigestAlgorithmL(aDigestAlgorithm);
+ }
+
+
+
+void CCmsSignedObject::BuildSignerInfoCertListAndAlgoritmListL(TAlgorithmId aDigestAlgorithm,
+ TBool aIsHash,
+ const TDesC8& aValue,
+ const CRSAPrivateKey& aKey,
+ const CX509Certificate& aCert,
+ TBool aAddCertificate)
+
+ {
+ //build Signer Identifier
+ CCmsSignerIdentifier* sid=BuildSignerIdentifierLC(aCert);
+
+ //build digest algorithm and signing algorithm
+ CX509AlgorithmIdentifier* digAlg=CX509AlgorithmIdentifier::NewLC(aDigestAlgorithm, KNullDesC8());
+ const CSubjectPublicKeyInfo& publicKeyInfo=aCert.PublicKey();
+ CX509AlgorithmIdentifier* signingAlg=CX509AlgorithmIdentifier::NewLC(publicKeyInfo.AlgorithmId(), publicKeyInfo.EncodedParams());
+
+ //build signer info
+ CCmsSignerInfo* signerInfo=CCmsSignerInfo::NewL(aValue,
+ aIsHash,
+ aKey,
+ sid,
+ digAlg,
+ signingAlg);
+ CleanupStack::Pop(3, sid);
+ CleanupStack::PushL(signerInfo);
+ //add to the signer info list
+ iSignerInfo.AppendL(signerInfo);
+ CleanupStack::Pop();
+
+ //Add the certificate to the list if needed
+ if (aAddCertificate)
+ {
+ AddCertificateL(aCert);
+ }
+
+ //Add the digest algorithm the list if needed
+ AddDigestAlgorithmL(aDigestAlgorithm);
+ }
+
+void CCmsSignedObject::ConstructL(TCmsContentInfoType aType,
+ const TDesC8& aHashValue,
+ TAlgorithmId aDigestAlgorithm,
+ const CDSAPrivateKey& aKey,
+ const CX509Certificate& aCert,
+ TBool aAddCertificate)
+ {
+ //Set the CMS object version to version 3 if the encapsulatedconetent data type is not data
+ if (aType != EContentTypeData)
+ {
+ iVersion=EVersion_3;
+ }
+
+ //build EncapsulatedContentInfo
+ iContentInfo=CEncapsulatedContentInfo::NewL(aType, EFalse, KNullDesC8());
+
+ BuildSignerInfoCertListAndAlgoritmListL(aDigestAlgorithm,
+ ETrue,
+ aHashValue,
+ aKey,
+ aCert,
+ aAddCertificate);
+
+ }
+void CCmsSignedObject::ConstructL(TCmsContentInfoType aType,
+ const TDesC8& aHashValue,
+ TAlgorithmId aDigestAlgorithm,
+ const CRSAPrivateKey& aKey,
+ const CX509Certificate& aCert,
+ TBool aAddCertificate)
+ {
+ //Set the CMS object version to version 3 if the encapsulatedconetent data type is not data
+ if (aType != EContentTypeData)
+ {
+ iVersion=EVersion_3;
+ }
+
+ //build EncapsulatedContentInfo
+ iContentInfo=CEncapsulatedContentInfo::NewL(aType, EFalse, KNullDesC8());
+
+ BuildSignerInfoCertListAndAlgoritmListL(aDigestAlgorithm,
+ ETrue,
+ aHashValue,
+ aKey,
+ aCert,
+ aAddCertificate);
+ }
+
+
+EXPORT_C void CCmsSignedObject::SignL(const TDesC8& aHashValue,
+ TAlgorithmId aDigestAlgorithm,
+ const CDSAPrivateKey& aKey,
+ const CX509Certificate& aCert,
+ TBool aAddCertificate)
+
+ {
+ TBool isHash=(aHashValue!=KNullDesC8())? ETrue:EFalse;
+ if (isHash)
+ {
+ BuildSignerInfoCertListAndAlgoritmListL(aDigestAlgorithm,
+ isHash,
+ aHashValue,
+ aKey,
+ aCert,
+ aAddCertificate);
+ }
+ else
+ {
+ if (iContentData!=KNullDesC8())
+ {
+ BuildSignerInfoCertListAndAlgoritmListL(aDigestAlgorithm,
+ isHash,
+ iContentData,
+ aKey,
+ aCert,
+ aAddCertificate);
+ }
+ else
+ {
+ //No way to sign if no data content nor its hash.
+ User::Leave(KErrArgument);
+ }
+ }
+ }
+
+EXPORT_C void CCmsSignedObject::SignL(const TDesC8& aHashValue,
+ TAlgorithmId aDigestAlgorithm,
+ const CRSAPrivateKey& aKey,
+ const CX509Certificate& aCert,
+ TBool aAddCertificate)
+ {
+ TBool isHash=(aHashValue!=KNullDesC8())? ETrue:EFalse;
+ if (isHash)
+ {
+ BuildSignerInfoCertListAndAlgoritmListL(aDigestAlgorithm,
+ isHash,
+ aHashValue,
+ aKey,
+ aCert,
+ aAddCertificate);
+ }
+ else
+ {
+ if (iContentData!=KNullDesC8())
+ {
+ BuildSignerInfoCertListAndAlgoritmListL(aDigestAlgorithm,
+ isHash,
+ iContentData,
+ aKey,
+ aCert,
+ aAddCertificate);
+ }
+ else
+ {
+ //No way to sign if no data content nor its hash.
+ User::Leave(KErrArgument);
+ }
+ }
+ }
+
+
+EXPORT_C CASN1EncSequence* CCmsSignedObject::EncodeASN1DERLC() const
+ {
+ // the root sequence contains the signed object
+ CASN1EncSequence* root = CASN1EncSequence::NewLC();
+
+ // Encode version
+ CASN1EncInt* version=CASN1EncInt::NewLC(iVersion);
+ root->AddAndPopChildL(version);
+
+ // Encode Algorithm
+ CASN1EncBase* algorithm=EncodeAlgorithmsLC();
+ root->AddAndPopChildL(algorithm);
+
+
+ // Encode EncapsulatedContentInfo
+ CASN1EncSequence* contentInfo=iContentInfo->EncodeASN1DERLC();
+ root->AddAndPopChildL(contentInfo);
+
+ // Encode option fields certificates SET
+ CASN1EncBase* cert=EncodeCertificatesLC();
+ if (cert)
+ {
+ root->AddAndPopChildL(cert);
+ }
+
+ // Encode signerinfo
+ CASN1EncBase* signerInfo=EncodeSignerInfoLC();
+ root->AddAndPopChildL(signerInfo);
+
+ return root;
+ }
+
+
+CASN1EncBase* CCmsSignedObject::EncodeCertificatesLC() const
+ {
+ return CmsUtils::EncodeCertificatesLC(iCertificates);
+ }
+
+CASN1EncBase* CCmsSignedObject::EncodeAlgorithmsLC() const
+ {
+ return CmsUtils::EncodeDigestAlgorithmsLC(iDigestAlgorithms);
+ }
+
+CASN1EncBase* CCmsSignedObject::EncodeSignerInfoLC() const
+ {
+ CASN1EncSet* signerInfoSet = CASN1EncSet::NewLC();
+ TInt count=iSignerInfo.Count();
+
+ for (TInt i=0;i<count;i++)
+ {
+ CASN1EncSequence* signerInfo=iSignerInfo[i]->EncodeASN1DERLC();
+ signerInfoSet->AddAndPopChildL(signerInfo);
+ }
+ return signerInfoSet;
+ }
+
+EXPORT_C TBool CCmsSignedObject::ValidateSignerLC(const CCmsSignerInfo& aSignerInfo, HBufC8*& aCertChainEncoding)
+ {
+ TInt certCount = iCertificates.Count();
+ TInt endEntityPos = -1;
+ TInt endEncodingSize = 0;
+ TPtrC8 endEntityEncoding;
+ TInt cert;
+ TBool valid = EFalse;
+
+ const CCmsSignerIdentifier& signerId = aSignerInfo.SignerIdentifier();
+
+ // looks for end entity certificate
+ for(cert = 0; cert < certCount; cert++)
+ {
+ if (iCertificates[cert]->CertificateType()==CCmsCertificateChoice::ECertificateX509)
+ {
+ const CX509Certificate& certificate = iCertificates[cert]->Certificate();
+
+ endEncodingSize+= certificate.Encoding().Length();
+
+ if(endEntityPos == -1)
+ {
+ if (signerId.SignerIdentifierType()==CCmsSignerIdentifier::EIssuerAndSerialNumber)
+ {
+ if (certificate.IssuerName().ExactMatchL(signerId.IssuerAndSerialNumber()->IssuerName()))
+ {
+ RInteger sn1=RInteger::NewL(certificate.SerialNumber());
+ CleanupClosePushL(sn1);
+ RInteger sn2=RInteger::NewL(signerId.IssuerAndSerialNumber()->SerialNumber());
+ CleanupClosePushL(sn2);
+ if (sn1==sn2)
+ {
+ endEntityPos = cert;
+ endEntityEncoding.Set(certificate.Encoding());
+ valid = ValidateSignatureL(aSignerInfo, certificate);
+ }
+ CleanupStack::PopAndDestroy(2, &sn1);//sn2, sn1
+ }
+ }
+ else
+ {
+ const CX509CertExtension* certExt = certificate.Extension(KSubjectKeyId);
+ if (certExt)
+ {
+ CX509SubjectKeyIdExt* ext=CX509SubjectKeyIdExt::NewLC(certExt->Data());
+ if (signerId.SubjectKeyIdentifier().Compare(ext->KeyId())==0)
+ {
+ endEntityPos = cert;
+ endEntityEncoding.Set(certificate.Encoding());
+ valid = ValidateSignatureL(aSignerInfo, certificate);
+ }
+ CleanupStack::PopAndDestroy(ext);
+ }
+ }
+ }
+ }
+ }
+
+ // checks if end entity was found
+ if(endEntityPos != -1)
+ {
+ // builds the cert chain encoding by putting the end entity first then all remaining
+ // certs
+ aCertChainEncoding = HBufC8::NewLC(endEncodingSize);
+ TPtr8 encodingPtr(aCertChainEncoding->Des());
+ encodingPtr.Copy(endEntityEncoding);
+ for(cert = 0; cert < certCount; cert++)
+ {
+ if (iCertificates[cert]->CertificateType()==CCmsCertificateChoice::ECertificateX509)
+ {
+ const CX509Certificate& certificate = iCertificates[cert]->Certificate();
+ if(cert != endEntityPos)
+ {
+ encodingPtr.Append(certificate.Encoding());
+ }
+ }
+ }
+ }
+ else
+ {
+ User::Leave(KErrNotFound);
+ }
+ return valid;
+ }
+
+
+EXPORT_C TBool CCmsSignedObject::ValidateSignerLC(const CCmsSignerInfo& aSignerInfo, const RPointerArray<CX509Certificate>& aCertificates, HBufC8*& aCertChainEncoding)
+ {
+ TInt certCount = aCertificates.Count();
+ TInt endEntityPos = -1;
+ TInt endEncodingSize = 0;
+ TPtrC8 endEntityEncoding;
+ TInt cert;
+ TBool valid = EFalse;
+ const CCmsSignerIdentifier& signerId = aSignerInfo.SignerIdentifier();
+
+ // looks for end entity certificate
+ for(cert = 0; cert < certCount; cert++)
+ {
+ const CX509Certificate& certificate = *aCertificates[cert];
+ endEncodingSize+= certificate.Encoding().Length();
+ if(endEntityPos == -1)
+ {
+ if (signerId.SignerIdentifierType()==CCmsSignerIdentifier::EIssuerAndSerialNumber)
+ {
+ if (certificate.IssuerName().ExactMatchL(signerId.IssuerAndSerialNumber()->IssuerName()))
+ {
+ RInteger sn1=RInteger::NewL(certificate.SerialNumber());
+ CleanupClosePushL(sn1);
+ RInteger sn2=RInteger::NewL(signerId.IssuerAndSerialNumber()->SerialNumber());
+ CleanupClosePushL(sn2);
+ if (sn1==sn2)
+ {
+ endEntityPos = cert;
+ endEntityEncoding.Set(certificate.Encoding());
+ valid = ValidateSignatureL(aSignerInfo, certificate);
+ }
+ CleanupStack::PopAndDestroy(2, &sn1);//sn2, sn1
+ }
+ }
+ else
+ {
+ const CX509CertExtension* certExt = certificate.Extension(KSubjectKeyId);
+ if (certExt)
+ {
+ CX509SubjectKeyIdExt* ext=CX509SubjectKeyIdExt::NewLC(certExt->Data());
+ if (signerId.SubjectKeyIdentifier().Compare(ext->KeyId())==0)
+ {
+ endEntityPos = cert;
+ endEntityEncoding.Set(certificate.Encoding());
+ valid = ValidateSignatureL(aSignerInfo, certificate);
+ }
+ CleanupStack::PopAndDestroy(ext);
+ }
+ }
+ }
+ }
+
+ // checks if end entity was found
+ if(endEntityPos != -1)
+ {
+ // builds the cert chain encoding by putting the end entity first then all remaining
+ // certs
+ aCertChainEncoding = HBufC8::NewLC(endEncodingSize);
+ TPtr8 encodingPtr(aCertChainEncoding->Des());
+ encodingPtr.Copy(endEntityEncoding);
+ for(cert = 0; cert < certCount; cert++)
+ {
+ const CX509Certificate& certificate = *aCertificates[cert];
+
+ if(cert != endEntityPos)
+ {
+ encodingPtr.Append(certificate.Encoding());
+ }
+ }
+ }
+ else
+ {
+ User::Leave(KErrNotFound);
+ }
+
+ return valid;
+ }
+
+
+EXPORT_C TBool CCmsSignedObject::ValidateSignerLC(const CCmsSignerInfo& aSignerInfo, HBufC8*& aCertChainEncoding, TBool aIsHash, const TDesC8& aContentDataOrHash)
+ {
+ if (aIsHash)
+ {
+ SetHash(aContentDataOrHash);
+ }
+ else
+ {
+ SetContentData(aContentDataOrHash);
+ }
+ return ValidateSignerLC(aSignerInfo, aCertChainEncoding);
+ }
+
+EXPORT_C TBool CCmsSignedObject::ValidateSignerLC(const CCmsSignerInfo& aSignerInfo, const RPointerArray<CX509Certificate>& aCertificates, HBufC8*& aCertChainEncoding, TBool aIsHash, const TDesC8& aContentDataOrHash)
+ {
+ if (aIsHash)
+ {
+ SetHash(aContentDataOrHash);
+ }
+ else
+ {
+ SetContentData(aContentDataOrHash);
+ }
+ return ValidateSignerLC(aSignerInfo, aCertificates, aCertChainEncoding);
+ }
+
+TBool CCmsSignedObject::ValidateSignatureL(const CCmsSignerInfo& aSignerInfo, const CX509Certificate& aEndEntityCert)
+ {
+ delete iSigningAlgorithm;
+ iSigningAlgorithm = NULL;
+ iSigningAlgorithm = CX509SigningAlgorithmIdentifier::NewL(aSignerInfo.SignatureAlgorithm(), aSignerInfo.DigestAlgorithm());
+
+ delete iSignature;
+ iSignature = NULL;
+ iSignature = aSignerInfo.SignatureValue().AllocL();
+
+ if (aSignerInfo.SignatureAlgorithm().Algorithm()==EDSA)
+ {
+ delete iParameters;
+ iParameters = NULL;
+ CDSAParameters* theDSAParams = iKeyFactory->DSAParametersL(aEndEntityCert.PublicKey().EncodedParams());
+ CleanupStack::PushL(theDSAParams);
+ CSigningKeyParameters* params = CSigningKeyParameters::NewLC();
+ params->SetDSAParamsL(*theDSAParams);
+ SetParametersL(*params);
+ CleanupStack::PopAndDestroy(2, theDSAParams);
+ }
+
+ if (iContentInfo->IsContentDataPresent() || iContentData != KNullDesC8)
+ {
+ return VerifySignatureL(aEndEntityCert.PublicKey().KeyData());
+ }
+ else if (iHash!=KNullDesC8)
+ {
+ return VerifySignatureL(aEndEntityCert.PublicKey().KeyData(), iHash);
+ }
+ else
+ {
+ User::Leave(KErrArgument);
+ return EFalse;
+ }
+
+ }
+
+void CCmsSignedObject::InitSignedObjectL(const TDesC8& aRawData)
+ {
+ // Populate CSignedObject data members
+ iKeyFactory = new (ELeave) TX509KeyFactory;
+ iEncoding = aRawData.AllocL();
+
+ CSHA1* hash = CSHA1::NewL();
+ CleanupStack::PushL(hash);
+ iFingerprint = hash->Hash(Encoding()).AllocL();
+ CleanupStack::PopAndDestroy(hash);
+ }
+
+void CCmsSignedObject::DecodeSignedDataL(const TDesC8& aRawData)
+ {
+ CArrayPtr<TASN1DecGeneric>* signedData = PKCS7ASN1::DecodeSequenceLC(aRawData, KCmsMinSignedDataElements, KCmsMaxSignedDataElements);
+ TInt totalItems = signedData->Count();
+ TASN1DecInteger decInt;
+
+ // decodes version
+ iDataElements.At(EVersionNumber) = new(ELeave) TPtrC8(signedData->At(0)->GetContentDER());
+ iVersion = decInt.DecodeDERShortL(*signedData->At(0));
+ if (iVersion>4 || iVersion<0)
+ {
+ User::Leave(KErrArgument);
+ }
+ // decodes algorithms
+ iDataElements.At(EDigestAlgorithms) = new(ELeave) TPtrC8(signedData->At(1)->GetContentDER());
+ DecodeDigestAlgorithmsL(signedData->At(1)->Encoding());
+ // decodes contentinfo
+ iDataElements.At(EEncapsulatedContentInfo) = new(ELeave) TPtrC8(signedData->At(2)->GetContentDER());
+ DecodeEncapsulatedContentInfoL(signedData->At(2)->Encoding());
+
+ // Checks for optional fields
+ TInt pos = 3; // Skip first non-optional fields
+ do
+ {
+ const TASN1DecGeneric& currentItem = *signedData->At(pos);
+ switch(currentItem.Tag())
+ {
+ case KSignedDataCertificates:
+ {
+ if (currentItem.Class()!=EContextSpecific)
+ {
+ User::Leave(KErrArgument);
+ }
+ iIsCertificateSetPresent=ETrue;
+ iDataElements.At(ECertificates) = new(ELeave) TPtrC8(currentItem.GetContentDER());
+ DecodeCertificatesL(currentItem.Encoding());
+ break;
+ }
+ case KSignedDataRevocationLists:
+ {
+ if (currentItem.Class()!=EContextSpecific)
+ {
+ User::Leave(KErrArgument);
+ }
+ iIsCertificateRevocationListsPresent=ETrue;
+ iDataElements.At(ERevocationLists) = new(ELeave) TPtrC8(currentItem.GetContentDER());
+ DecodeRevocationListsL(currentItem.Encoding());
+ break;
+ }
+ default:
+ {
+ //Optional field with wrong tag and class
+ if (pos<totalItems-1)
+ {
+ User::Leave(KErrArgument);
+ }
+ // else Non-optional field
+ }
+ }
+ pos++;
+ }
+ while(pos < totalItems);
+
+ iDataElements.At(ESignedInfo) = new(ELeave) TPtrC8(signedData->At(totalItems-1)->GetContentDER());
+ DecodeSignerInfoL(signedData->At(totalItems-1)->Encoding());
+
+ CleanupStack::PopAndDestroy(signedData);
+ }
+
+void CCmsSignedObject::DecodeDigestAlgorithmsL(const TDesC8& aRawData)
+ {
+ CmsUtils::DecodeDigestAlgorithmsL(iDigestAlgorithms, aRawData);
+ }
+
+void CCmsSignedObject::DecodeCertificatesL(const TDesC8& aRawData)
+ {
+ CmsUtils::DecodeCertificatesL(iCertificates, aRawData);
+ }
+
+void CCmsSignedObject::DecodeRevocationListsL(const TDesC8& /*aRawData*/)
+ {
+ }
+
+EXPORT_C const TPtrC8 CCmsSignedObject::SignedDataL() const
+ {
+ if (iContentInfo->IsContentDataPresent())
+ {
+ return iContentInfo->ContentData();
+ }
+ else
+ {
+ if (iContentData!=KNullDesC8)
+ {
+ return iContentData;
+ }
+ else
+ {
+ User::Leave(KErrArgument);
+ }
+ }
+ return KNullDesC8();
+ }
+
+EXPORT_C void CCmsSignedObject::InternalizeL(RReadStream& /*aStream*/)
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+EXPORT_C const TPtrC8* CCmsSignedObject::DataElementEncoding(const TUint aIndex) const
+ {
+ return iDataElements.At(aIndex);
+ }
+
+void CCmsSignedObject::SetContentData(const TDesC8& aContentData)
+ {
+ iContentData.Set(aContentData);
+ }
+
+void CCmsSignedObject::SetHash(const TDesC8& aHash)
+ {
+ iHash.Set(aHash);
+ }
+
+
+
+