diff -r 000000000000 -r 2c201484c85f cryptoservices/certificateandkeymgmt/pkcs7/pkcs7signedobject_v2.cpp --- /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 +#include "pkcs7excert.h" +#include "pkcs7signerinfo.h" +#include "pkcs7issuerserial.h" +#include "pkcs7asn1.h" +#include +#include +#include + +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& 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& CPKCS7SignedObject::Certificates() const + { + return iCertificates; + } + +EXPORT_C const RPointerArray& 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* 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* 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* 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* 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()); + }