diff -r 000000000000 -r 2c201484c85f cryptoservices/certificateandkeymgmt/pkcs7/cmssignedobject.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cryptoservices/certificateandkeymgmt/pkcs7/cmssignedobject.cpp Wed Jul 08 11:25:26 2009 +0100 @@ -0,0 +1,896 @@ +/* +* 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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& CCmsSignedObject::Certificates() const + { + return iCertificates; + } + +EXPORT_C const RPointerArray& CCmsSignedObject::DigestAlgorithms() const + { + return iDigestAlgorithms; + } + +EXPORT_C const CEncapsulatedContentInfo& CCmsSignedObject::ContentInfo() const + { + return *iContentInfo; + } + +EXPORT_C const RPointerArray& 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* 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;iEncodeASN1DERLC(); + 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& 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& 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* 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 (posAt(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); + } + + +