First public contribution.
2 * Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
4 * This component and the accompanying materials are made available
5 * under the terms of the License "Eclipse Public License v1.0"
6 * which accompanies this distribution, and is available
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
19 #include "pkcs7signedobject.h"
20 #include <pkcs7contentinfo_v2.h>
21 #include "pkcs7excert.h"
22 #include "pkcs7signerinfo.h"
23 #include "pkcs7issuerserial.h"
24 #include "pkcs7asn1.h"
29 const TInt KSignedDataCertificates = 0;
30 const TInt KSignedDataRevocationLists = 1;
32 EXPORT_C CPKCS7SignedObject::~CPKCS7SignedObject(void)
34 iDigestAlgorithms.ResetAndDestroy();
35 iCertificates.ResetAndDestroy();
37 iSignerInfo.ResetAndDestroy();
38 for(TInt i = 0; i < KPKCS7MaxDataElements; i++)
40 delete iDataElements.At(i);
44 EXPORT_C CPKCS7SignedObject::CPKCS7SignedObject(void)
49 EXPORT_C CPKCS7SignedObject* CPKCS7SignedObject::NewLC(const CPKCS7ContentInfo& aContentInfo)
51 CPKCS7SignedObject* self = new (ELeave) CPKCS7SignedObject();
52 CleanupStack::PushL(self);
53 self->ConstructL(aContentInfo);
57 EXPORT_C CPKCS7SignedObject* CPKCS7SignedObject::NewL(const CPKCS7ContentInfo& aContentInfo)
59 CPKCS7SignedObject* self = NewLC(aContentInfo);
60 CleanupStack::Pop(self);
64 EXPORT_C void CPKCS7SignedObject::ConstructL(const CPKCS7ContentInfo& aContentInfo)
66 if(aContentInfo.ContentType() != KPkcs7SignedData)
68 User::Leave(KErrArgument);
71 TASN1DecGeneric decGen(aContentInfo.ContentData());
74 if(decGen.Tag() == EASN1Sequence)
76 InitSignedObjectL(decGen.Encoding());
77 DecodeSignedDataL(*iEncoding);
81 User::Leave(KErrArgument);
85 EXPORT_C const TPtrC8 CPKCS7SignedObject::SignedDataL() const
87 return iContentInfo->ContentData();
90 EXPORT_C void CPKCS7SignedObject::InternalizeL(RReadStream& /*aStream*/)
92 User::Leave(KErrNotSupported);
95 EXPORT_C const TPtrC8* CPKCS7SignedObject::DataElementEncoding(const TUint aIndex) const
97 return iDataElements.At(aIndex);
101 EXPORT_C const RPointerArray<CX509AlgorithmIdentifier>& CPKCS7SignedObject::DigestAlgorithms() const
103 return iDigestAlgorithms;
106 EXPORT_C TInt CPKCS7SignedObject::Version() const
111 EXPORT_C const CPKCS7ContentInfo& CPKCS7SignedObject::ContentInfo() const
113 return *iContentInfo;
116 EXPORT_C const RPointerArray<CPKCS7ExtendedCertificateOrCertificate>& CPKCS7SignedObject::Certificates() const
118 return iCertificates;
121 EXPORT_C const RPointerArray<CPKCS7SignerInfo>& CPKCS7SignedObject::SignerInfo() const
126 void CPKCS7SignedObject::InitSignedObjectL(const TDesC8& aRawData)
128 // Populate CSignedObject data members
129 iKeyFactory = new (ELeave) TX509KeyFactory;
130 iEncoding = aRawData.AllocL();
132 CSHA1* hash = CSHA1::NewL();
133 CleanupStack::PushL(hash);
134 iFingerprint = hash->Hash(Encoding()).AllocL();
135 CleanupStack::PopAndDestroy(hash);
138 void CPKCS7SignedObject::DecodeSignedDataL(const TDesC8& aRawData)
140 CArrayPtr<TASN1DecGeneric>* signedData = PKCS7ASN1::DecodeSequenceLC(aRawData, 4, KPKCS7MaxDataElements);
141 TInt totalItems = signedData->Count();
142 TASN1DecInteger decInt;
145 iDataElements.At(EVersionNumber) = new(ELeave) TPtrC8(signedData->At(0)->GetContentDER());
146 iVersion = decInt.DecodeDERShortL(*signedData->At(0));
147 // decodes algorithms
148 iDataElements.At(EDigestAlgorithms) = new(ELeave) TPtrC8(signedData->At(1)->GetContentDER());
149 DecodeDigestAlgorithmsL(signedData->At(1)->Encoding());
150 // decodes contentinfo
151 iDataElements.At(EContentInfo) = new(ELeave) TPtrC8(signedData->At(2)->GetContentDER());
152 iContentInfo = CPKCS7ContentInfo::NewL(signedData->At(2)->Encoding());
154 // Checks for optional fields
155 TInt pos = 3; // Skip first non-optional fields
158 const TASN1DecGeneric& currentItem = *signedData->At(pos);
159 switch(currentItem.Tag())
161 case KSignedDataCertificates:
163 iDataElements.At(ECertificates) = new(ELeave) TPtrC8(currentItem.GetContentDER());
164 DecodeCertificatesL(currentItem.Encoding());
167 case KSignedDataRevocationLists:
170 iDataElements.At(ERevocationLists) = new(ELeave) TPtrC8(currentItem.GetContentDER());
171 DecodeRevocationListsL(currentItem.Encoding());
174 default: // Non-optional field
181 while(pos < totalItems);
183 iDataElements.At(ESignedInfo) = new(ELeave) TPtrC8(signedData->At(totalItems-1)->GetContentDER());
184 DecodeSignerInfoL(signedData->At(totalItems-1)->Encoding());
186 CleanupStack::PopAndDestroy(signedData);
190 void CPKCS7SignedObject::DecodeDigestAlgorithmsL(const TDesC8& aRawData)
192 CArrayPtr<TASN1DecGeneric>* algsData = PKCS7ASN1::DecodeSequenceLC(aRawData);
193 TInt count = algsData->Count();
194 CX509AlgorithmIdentifier* alIdent;
196 for(TInt item = 0; item < count; item++)
198 alIdent = CX509AlgorithmIdentifier::NewLC(algsData->At(item)->Encoding());
199 User::LeaveIfError(iDigestAlgorithms.Append(alIdent));
200 CleanupStack::Pop(alIdent);
202 CleanupStack::PopAndDestroy(algsData);
205 void CPKCS7SignedObject::DecodeCertificatesL(const TDesC8& aRawData)
207 CArrayPtr<TASN1DecGeneric>* items = NULL;
208 TASN1DecGeneric decGen(aRawData);
210 TASN1DecSequence decSeq;
211 // have to do manual decoding of sequence because field is optional
212 items = decSeq.DecodeDERLC(decGen);
213 TInt count = items->Count();
215 CPKCS7ExtendedCertificateOrCertificate* certificate;
217 for(TInt item = 0; item < count; item++)
219 certificate = CPKCS7ExtendedCertificateOrCertificate::NewL(items->At(item)->Encoding());
220 CleanupStack::PushL(certificate);
221 User::LeaveIfError(iCertificates.Append(certificate));
222 CleanupStack::Pop(certificate);
225 CleanupStack::PopAndDestroy(items);
228 void CPKCS7SignedObject::DecodeRevocationListsL(const TDesC8& /*aRawData*/)
231 User::Leave(KErrNotSupported);
234 void CPKCS7SignedObject::DecodeSignerInfoL(const TDesC8& aRawData)
236 CArrayPtr<TASN1DecGeneric>* signerInfo = PKCS7ASN1::DecodeSequenceLC(aRawData);
237 TInt total = signerInfo->Count();
238 CPKCS7SignerInfo* signer;
240 for(TInt item = 0; item < total; item ++)
242 signer = CPKCS7SignerInfo::NewL(signerInfo->At(item)->Encoding());
243 CleanupStack::PushL(signer);
244 User::LeaveIfError(iSignerInfo.Append(signer));
245 CleanupStack::Pop(signer);
247 CleanupStack::PopAndDestroy(signerInfo);
250 EXPORT_C TBool CPKCS7SignedObject::ValidateSignerL(const CPKCS7SignerInfo& aSignerInfo, HBufC8*& aCertChainEncoding)
252 TInt certCount = iCertificates.Count();
253 TInt endEntityPos = -1;
254 TInt endEncodingSize = 0;
255 TPtrC8 endEntityEncoding;
257 TBool valid = EFalse;
259 // looks for end entity certificate
260 for(cert = 0; cert < certCount; cert++)
262 const CX509Certificate& certificate = iCertificates[cert]->Certificate();
264 endEncodingSize+= certificate.Encoding().Length();
265 if(certificate.IssuerName().ExactMatchL(aSignerInfo.IssuerAndSerialNumber().IssuerName()))
268 endEntityEncoding.Set(certificate.Encoding());
269 valid = ValidateSignatureL(aSignerInfo, certificate);
273 // checks if end entity was found
274 if(endEntityPos != -1)
276 // builds the cert chain encoding by putting the end entity first then all remaining
278 aCertChainEncoding = HBufC8::NewLC(endEncodingSize);
279 TPtr8 encodingPtr(aCertChainEncoding->Des());
280 encodingPtr.Copy(endEntityEncoding);
281 for(cert = 0; cert < certCount; cert++)
283 const CX509Certificate& certificate = iCertificates[cert]->Certificate();
285 if(cert != endEntityPos)
287 encodingPtr.Append(certificate.Encoding());
293 User::Leave(KErrNotFound);
298 TBool CPKCS7SignedObject::ValidateSignatureL(const CPKCS7SignerInfo& aSignerInfo, const CX509Certificate& aEndEntityCert)
300 iSigningAlgorithm = CX509SigningAlgorithmIdentifier::NewL(aSignerInfo.DigestEncryptionAlgorithm(), aSignerInfo.DigestAlgorithm());
306 iSignature = aSignerInfo.EncryptedDigest().AllocL();
307 return VerifySignatureL(aEndEntityCert.PublicKey().KeyData());