diff -r 675a964f4eb5 -r 35751d3474b7 cryptoservices/certificateandkeymgmt/pkcs7/cmssignedobject.cpp --- 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 -#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); - } - - - +/* +* 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); + } + + + +