--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptoservices/certificateandkeymgmt/pkcs7/pkcs7signedobject_v2.cpp Wed Jul 08 11:25:26 2009 +0100
@@ -0,0 +1,308 @@
+/*
+* 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 "pkcs7signedobject.h"
+#include <pkcs7contentinfo_v2.h>
+#include "pkcs7excert.h"
+#include "pkcs7signerinfo.h"
+#include "pkcs7issuerserial.h"
+#include "pkcs7asn1.h"
+#include <asn1dec.h>
+#include <x509cert.h>
+#include <hash.h>
+
+const TInt KSignedDataCertificates = 0;
+const TInt KSignedDataRevocationLists = 1;
+
+EXPORT_C CPKCS7SignedObject::~CPKCS7SignedObject(void)
+ {
+ iDigestAlgorithms.ResetAndDestroy();
+ iCertificates.ResetAndDestroy();
+ delete iContentInfo;
+ iSignerInfo.ResetAndDestroy();
+ for(TInt i = 0; i < KPKCS7MaxDataElements; i++)
+ {
+ delete iDataElements.At(i);
+ }
+ }
+
+EXPORT_C CPKCS7SignedObject::CPKCS7SignedObject(void)
+ {
+ }
+
+
+EXPORT_C CPKCS7SignedObject* CPKCS7SignedObject::NewLC(const CPKCS7ContentInfo& aContentInfo)
+ {
+ CPKCS7SignedObject* self = new (ELeave) CPKCS7SignedObject();
+ CleanupStack::PushL(self);
+ self->ConstructL(aContentInfo);
+ return self;
+ }
+
+EXPORT_C CPKCS7SignedObject* CPKCS7SignedObject::NewL(const CPKCS7ContentInfo& aContentInfo)
+ {
+ CPKCS7SignedObject* self = NewLC(aContentInfo);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+EXPORT_C void CPKCS7SignedObject::ConstructL(const CPKCS7ContentInfo& aContentInfo)
+ {
+ if(aContentInfo.ContentType() != KPkcs7SignedData)
+ {
+ User::Leave(KErrArgument);
+ }
+
+ TASN1DecGeneric decGen(aContentInfo.ContentData());
+ decGen.InitL();
+
+ if(decGen.Tag() == EASN1Sequence)
+ {
+ InitSignedObjectL(decGen.Encoding());
+ DecodeSignedDataL(*iEncoding);
+ }
+ else
+ {
+ User::Leave(KErrArgument);
+ }
+ }
+
+EXPORT_C const TPtrC8 CPKCS7SignedObject::SignedDataL() const
+ {
+ return iContentInfo->ContentData();
+ }
+
+EXPORT_C void CPKCS7SignedObject::InternalizeL(RReadStream& /*aStream*/)
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+EXPORT_C const TPtrC8* CPKCS7SignedObject::DataElementEncoding(const TUint aIndex) const
+ {
+ return iDataElements.At(aIndex);
+ }
+
+
+EXPORT_C const RPointerArray<CX509AlgorithmIdentifier>& CPKCS7SignedObject::DigestAlgorithms() const
+ {
+ return iDigestAlgorithms;
+ }
+
+EXPORT_C TInt CPKCS7SignedObject::Version() const
+ {
+ return iVersion;
+ }
+
+EXPORT_C const CPKCS7ContentInfo& CPKCS7SignedObject::ContentInfo() const
+ {
+ return *iContentInfo;
+ }
+
+EXPORT_C const RPointerArray<CPKCS7ExtendedCertificateOrCertificate>& CPKCS7SignedObject::Certificates() const
+ {
+ return iCertificates;
+ }
+
+EXPORT_C const RPointerArray<CPKCS7SignerInfo>& CPKCS7SignedObject::SignerInfo() const
+ {
+ return iSignerInfo;
+ }
+
+void CPKCS7SignedObject::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 CPKCS7SignedObject::DecodeSignedDataL(const TDesC8& aRawData)
+ {
+ CArrayPtr<TASN1DecGeneric>* signedData = PKCS7ASN1::DecodeSequenceLC(aRawData, 4, KPKCS7MaxDataElements);
+ TInt totalItems = signedData->Count();
+ TASN1DecInteger decInt;
+
+ // decodes version
+ iDataElements.At(EVersionNumber) = new(ELeave) TPtrC8(signedData->At(0)->GetContentDER());
+ iVersion = decInt.DecodeDERShortL(*signedData->At(0));
+ // decodes algorithms
+ iDataElements.At(EDigestAlgorithms) = new(ELeave) TPtrC8(signedData->At(1)->GetContentDER());
+ DecodeDigestAlgorithmsL(signedData->At(1)->Encoding());
+ // decodes contentinfo
+ iDataElements.At(EContentInfo) = new(ELeave) TPtrC8(signedData->At(2)->GetContentDER());
+ iContentInfo = CPKCS7ContentInfo::NewL(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:
+ {
+ iDataElements.At(ECertificates) = new(ELeave) TPtrC8(currentItem.GetContentDER());
+ DecodeCertificatesL(currentItem.Encoding());
+ break;
+ }
+ case KSignedDataRevocationLists:
+ {
+
+ iDataElements.At(ERevocationLists) = new(ELeave) TPtrC8(currentItem.GetContentDER());
+ DecodeRevocationListsL(currentItem.Encoding());
+ break;
+ }
+ default: // Non-optional field
+ {
+ break;
+ }
+ }
+ 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 CPKCS7SignedObject::DecodeDigestAlgorithmsL(const TDesC8& aRawData)
+ {
+ CArrayPtr<TASN1DecGeneric>* algsData = PKCS7ASN1::DecodeSequenceLC(aRawData);
+ TInt count = algsData->Count();
+ CX509AlgorithmIdentifier* alIdent;
+
+ for(TInt item = 0; item < count; item++)
+ {
+ alIdent = CX509AlgorithmIdentifier::NewLC(algsData->At(item)->Encoding());
+ User::LeaveIfError(iDigestAlgorithms.Append(alIdent));
+ CleanupStack::Pop(alIdent);
+ }
+ CleanupStack::PopAndDestroy(algsData);
+ }
+
+void CPKCS7SignedObject::DecodeCertificatesL(const TDesC8& aRawData)
+ {
+ CArrayPtr<TASN1DecGeneric>* items = NULL;
+ TASN1DecGeneric decGen(aRawData);
+ decGen.InitL();
+ TASN1DecSequence decSeq;
+ // have to do manual decoding of sequence because field is optional
+ items = decSeq.DecodeDERLC(decGen);
+ TInt count = items->Count();
+
+ CPKCS7ExtendedCertificateOrCertificate* certificate;
+
+ for(TInt item = 0; item < count; item++)
+ {
+ certificate = CPKCS7ExtendedCertificateOrCertificate::NewL(items->At(item)->Encoding());
+ CleanupStack::PushL(certificate);
+ User::LeaveIfError(iCertificates.Append(certificate));
+ CleanupStack::Pop(certificate);
+ }
+
+ CleanupStack::PopAndDestroy(items);
+ }
+
+void CPKCS7SignedObject::DecodeRevocationListsL(const TDesC8& /*aRawData*/)
+ {
+ // not yet supported
+ User::Leave(KErrNotSupported);
+ }
+
+void CPKCS7SignedObject::DecodeSignerInfoL(const TDesC8& aRawData)
+ {
+ CArrayPtr<TASN1DecGeneric>* signerInfo = PKCS7ASN1::DecodeSequenceLC(aRawData);
+ TInt total = signerInfo->Count();
+ CPKCS7SignerInfo* signer;
+
+ for(TInt item = 0; item < total; item ++)
+ {
+ signer = CPKCS7SignerInfo::NewL(signerInfo->At(item)->Encoding());
+ CleanupStack::PushL(signer);
+ User::LeaveIfError(iSignerInfo.Append(signer));
+ CleanupStack::Pop(signer);
+ }
+ CleanupStack::PopAndDestroy(signerInfo);
+ }
+
+EXPORT_C TBool CPKCS7SignedObject::ValidateSignerL(const CPKCS7SignerInfo& aSignerInfo, HBufC8*& aCertChainEncoding)
+ {
+ TInt certCount = iCertificates.Count();
+ TInt endEntityPos = -1;
+ TInt endEncodingSize = 0;
+ TPtrC8 endEntityEncoding;
+ TInt cert;
+ TBool valid = EFalse;
+
+ // looks for end entity certificate
+ for(cert = 0; cert < certCount; cert++)
+ {
+ const CX509Certificate& certificate = iCertificates[cert]->Certificate();
+
+ endEncodingSize+= certificate.Encoding().Length();
+ if(certificate.IssuerName().ExactMatchL(aSignerInfo.IssuerAndSerialNumber().IssuerName()))
+ {
+ endEntityPos = cert;
+ endEntityEncoding.Set(certificate.Encoding());
+ valid = ValidateSignatureL(aSignerInfo, certificate);
+ }
+ }
+
+ // 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 = iCertificates[cert]->Certificate();
+
+ if(cert != endEntityPos)
+ {
+ encodingPtr.Append(certificate.Encoding());
+ }
+ }
+ }
+ else
+ {
+ User::Leave(KErrNotFound);
+ }
+ return valid;
+ }
+
+TBool CPKCS7SignedObject::ValidateSignatureL(const CPKCS7SignerInfo& aSignerInfo, const CX509Certificate& aEndEntityCert)
+ {
+ iSigningAlgorithm = CX509SigningAlgorithmIdentifier::NewL(aSignerInfo.DigestEncryptionAlgorithm(), aSignerInfo.DigestAlgorithm());
+ if(iSignature)
+ {
+ delete iSignature;
+ iSignature = NULL;
+ }
+ iSignature = aSignerInfo.EncryptedDigest().AllocL();
+ return VerifySignatureL(aEndEntityCert.PublicKey().KeyData());
+ }