os/security/cryptoservices/certificateandkeymgmt/pkcs7/pkcs7signedobject_v2.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200 (2012-06-15)
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
/*
sl@0
     2
* Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     3
* All rights reserved.
sl@0
     4
* This component and the accompanying materials are made available
sl@0
     5
* under the terms of the License "Eclipse Public License v1.0"
sl@0
     6
* which accompanies this distribution, and is available
sl@0
     7
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     8
*
sl@0
     9
* Initial Contributors:
sl@0
    10
* Nokia Corporation - initial contribution.
sl@0
    11
*
sl@0
    12
* Contributors:
sl@0
    13
*
sl@0
    14
* Description: 
sl@0
    15
*
sl@0
    16
*/
sl@0
    17
sl@0
    18
 
sl@0
    19
#include "pkcs7signedobject.h"
sl@0
    20
#include <pkcs7contentinfo_v2.h>
sl@0
    21
#include "pkcs7excert.h"
sl@0
    22
#include "pkcs7signerinfo.h"
sl@0
    23
#include "pkcs7issuerserial.h"
sl@0
    24
#include "pkcs7asn1.h"
sl@0
    25
#include <asn1dec.h>
sl@0
    26
#include <x509cert.h>
sl@0
    27
#include <hash.h>
sl@0
    28
sl@0
    29
const TInt KSignedDataCertificates = 0;
sl@0
    30
const TInt KSignedDataRevocationLists = 1;
sl@0
    31
sl@0
    32
EXPORT_C CPKCS7SignedObject::~CPKCS7SignedObject(void)
sl@0
    33
	{
sl@0
    34
	iDigestAlgorithms.ResetAndDestroy();
sl@0
    35
	iCertificates.ResetAndDestroy();
sl@0
    36
	delete iContentInfo;
sl@0
    37
	iSignerInfo.ResetAndDestroy();
sl@0
    38
	for(TInt i = 0; i < KPKCS7MaxDataElements; i++)
sl@0
    39
		{
sl@0
    40
		delete iDataElements.At(i);
sl@0
    41
		}
sl@0
    42
	}
sl@0
    43
sl@0
    44
EXPORT_C CPKCS7SignedObject::CPKCS7SignedObject(void)
sl@0
    45
	{
sl@0
    46
	}
sl@0
    47
sl@0
    48
sl@0
    49
EXPORT_C CPKCS7SignedObject* CPKCS7SignedObject::NewLC(const CPKCS7ContentInfo& aContentInfo)
sl@0
    50
	{
sl@0
    51
	CPKCS7SignedObject* self = new (ELeave) CPKCS7SignedObject();
sl@0
    52
	CleanupStack::PushL(self);
sl@0
    53
	self->ConstructL(aContentInfo);
sl@0
    54
	return self;
sl@0
    55
	}
sl@0
    56
sl@0
    57
EXPORT_C CPKCS7SignedObject* CPKCS7SignedObject::NewL(const CPKCS7ContentInfo& aContentInfo)
sl@0
    58
	{
sl@0
    59
	CPKCS7SignedObject* self = NewLC(aContentInfo);
sl@0
    60
	CleanupStack::Pop(self);
sl@0
    61
	return self;
sl@0
    62
	}
sl@0
    63
sl@0
    64
EXPORT_C void CPKCS7SignedObject::ConstructL(const CPKCS7ContentInfo& aContentInfo)
sl@0
    65
	{
sl@0
    66
	if(aContentInfo.ContentType() != KPkcs7SignedData)
sl@0
    67
		{
sl@0
    68
		User::Leave(KErrArgument);
sl@0
    69
		}
sl@0
    70
	
sl@0
    71
	TASN1DecGeneric decGen(aContentInfo.ContentData());
sl@0
    72
	decGen.InitL();
sl@0
    73
sl@0
    74
	if(decGen.Tag() == EASN1Sequence)
sl@0
    75
		{
sl@0
    76
		InitSignedObjectL(decGen.Encoding());
sl@0
    77
	    DecodeSignedDataL(*iEncoding);
sl@0
    78
		}
sl@0
    79
	else
sl@0
    80
		{
sl@0
    81
	    User::Leave(KErrArgument);
sl@0
    82
		}
sl@0
    83
	}
sl@0
    84
sl@0
    85
EXPORT_C const TPtrC8 CPKCS7SignedObject::SignedDataL() const
sl@0
    86
	{
sl@0
    87
	return iContentInfo->ContentData();
sl@0
    88
	}
sl@0
    89
sl@0
    90
EXPORT_C void CPKCS7SignedObject::InternalizeL(RReadStream& /*aStream*/) 
sl@0
    91
	{
sl@0
    92
	User::Leave(KErrNotSupported);
sl@0
    93
	}
sl@0
    94
sl@0
    95
EXPORT_C const TPtrC8* CPKCS7SignedObject::DataElementEncoding(const TUint aIndex) const
sl@0
    96
	{
sl@0
    97
	return iDataElements.At(aIndex);
sl@0
    98
	}
sl@0
    99
sl@0
   100
sl@0
   101
EXPORT_C const RPointerArray<CX509AlgorithmIdentifier>& CPKCS7SignedObject::DigestAlgorithms() const
sl@0
   102
	{
sl@0
   103
	return iDigestAlgorithms;
sl@0
   104
	}
sl@0
   105
sl@0
   106
EXPORT_C TInt CPKCS7SignedObject::Version() const
sl@0
   107
	{
sl@0
   108
	return iVersion;
sl@0
   109
	}
sl@0
   110
sl@0
   111
EXPORT_C const CPKCS7ContentInfo& CPKCS7SignedObject::ContentInfo() const
sl@0
   112
	{
sl@0
   113
	return *iContentInfo;
sl@0
   114
	}
sl@0
   115
sl@0
   116
EXPORT_C const RPointerArray<CPKCS7ExtendedCertificateOrCertificate>& CPKCS7SignedObject::Certificates() const
sl@0
   117
	{
sl@0
   118
	return iCertificates;
sl@0
   119
	}
sl@0
   120
sl@0
   121
EXPORT_C const RPointerArray<CPKCS7SignerInfo>& CPKCS7SignedObject::SignerInfo() const
sl@0
   122
	{
sl@0
   123
	return iSignerInfo;
sl@0
   124
	}
sl@0
   125
sl@0
   126
void CPKCS7SignedObject::InitSignedObjectL(const TDesC8& aRawData)
sl@0
   127
	{
sl@0
   128
	// Populate CSignedObject data members
sl@0
   129
	iKeyFactory = new (ELeave) TX509KeyFactory;
sl@0
   130
	iEncoding = aRawData.AllocL();
sl@0
   131
sl@0
   132
	CSHA1* hash = CSHA1::NewL();
sl@0
   133
	CleanupStack::PushL(hash);
sl@0
   134
	iFingerprint = hash->Hash(Encoding()).AllocL();
sl@0
   135
	CleanupStack::PopAndDestroy(hash);
sl@0
   136
	}
sl@0
   137
sl@0
   138
void CPKCS7SignedObject::DecodeSignedDataL(const TDesC8& aRawData)
sl@0
   139
	{
sl@0
   140
	CArrayPtr<TASN1DecGeneric>* signedData = PKCS7ASN1::DecodeSequenceLC(aRawData, 4, KPKCS7MaxDataElements);
sl@0
   141
	TInt totalItems = signedData->Count();
sl@0
   142
	TASN1DecInteger decInt;
sl@0
   143
sl@0
   144
	// decodes version
sl@0
   145
	iDataElements.At(EVersionNumber) = new(ELeave) TPtrC8(signedData->At(0)->GetContentDER());
sl@0
   146
	iVersion = decInt.DecodeDERShortL(*signedData->At(0));	
sl@0
   147
	// decodes algorithms
sl@0
   148
	iDataElements.At(EDigestAlgorithms) = new(ELeave) TPtrC8(signedData->At(1)->GetContentDER());
sl@0
   149
	DecodeDigestAlgorithmsL(signedData->At(1)->Encoding());
sl@0
   150
	// decodes contentinfo
sl@0
   151
	iDataElements.At(EContentInfo) = new(ELeave) TPtrC8(signedData->At(2)->GetContentDER());
sl@0
   152
	iContentInfo = CPKCS7ContentInfo::NewL(signedData->At(2)->Encoding());
sl@0
   153
sl@0
   154
	// Checks for optional fields
sl@0
   155
	TInt pos = 3;	// Skip first non-optional fields
sl@0
   156
	do
sl@0
   157
		{
sl@0
   158
		const TASN1DecGeneric& currentItem = *signedData->At(pos);
sl@0
   159
		switch(currentItem.Tag())
sl@0
   160
			{
sl@0
   161
			case KSignedDataCertificates:
sl@0
   162
				{
sl@0
   163
				iDataElements.At(ECertificates) = new(ELeave) TPtrC8(currentItem.GetContentDER());
sl@0
   164
				DecodeCertificatesL(currentItem.Encoding());
sl@0
   165
				break;
sl@0
   166
				}
sl@0
   167
			case KSignedDataRevocationLists:
sl@0
   168
				{
sl@0
   169
				
sl@0
   170
				iDataElements.At(ERevocationLists) = new(ELeave) TPtrC8(currentItem.GetContentDER());
sl@0
   171
				DecodeRevocationListsL(currentItem.Encoding());
sl@0
   172
				break;
sl@0
   173
				}
sl@0
   174
			default:	// Non-optional field
sl@0
   175
				{
sl@0
   176
				break;
sl@0
   177
				}
sl@0
   178
			}
sl@0
   179
		pos++;
sl@0
   180
		}
sl@0
   181
	while(pos < totalItems);
sl@0
   182
sl@0
   183
	iDataElements.At(ESignedInfo) = new(ELeave) TPtrC8(signedData->At(totalItems-1)->GetContentDER());
sl@0
   184
	DecodeSignerInfoL(signedData->At(totalItems-1)->Encoding());
sl@0
   185
sl@0
   186
	CleanupStack::PopAndDestroy(signedData);
sl@0
   187
	}
sl@0
   188
sl@0
   189
sl@0
   190
void CPKCS7SignedObject::DecodeDigestAlgorithmsL(const TDesC8& aRawData)
sl@0
   191
	{
sl@0
   192
	CArrayPtr<TASN1DecGeneric>* algsData = PKCS7ASN1::DecodeSequenceLC(aRawData);
sl@0
   193
	TInt count = algsData->Count();
sl@0
   194
	CX509AlgorithmIdentifier* alIdent;
sl@0
   195
sl@0
   196
	for(TInt item = 0; item < count; item++)
sl@0
   197
		{
sl@0
   198
 		alIdent = CX509AlgorithmIdentifier::NewLC(algsData->At(item)->Encoding());
sl@0
   199
		User::LeaveIfError(iDigestAlgorithms.Append(alIdent));
sl@0
   200
		CleanupStack::Pop(alIdent);
sl@0
   201
		}
sl@0
   202
	CleanupStack::PopAndDestroy(algsData);
sl@0
   203
	}
sl@0
   204
sl@0
   205
void CPKCS7SignedObject::DecodeCertificatesL(const TDesC8& aRawData)
sl@0
   206
	{
sl@0
   207
	CArrayPtr<TASN1DecGeneric>* items = NULL;
sl@0
   208
	TASN1DecGeneric decGen(aRawData);
sl@0
   209
	decGen.InitL();
sl@0
   210
	TASN1DecSequence decSeq;
sl@0
   211
	// have to do manual decoding of sequence because field is optional
sl@0
   212
	items = decSeq.DecodeDERLC(decGen);
sl@0
   213
	TInt count = items->Count();
sl@0
   214
sl@0
   215
	CPKCS7ExtendedCertificateOrCertificate* certificate;
sl@0
   216
sl@0
   217
	for(TInt item = 0; item < count; item++)
sl@0
   218
		{
sl@0
   219
 		certificate = CPKCS7ExtendedCertificateOrCertificate::NewL(items->At(item)->Encoding());
sl@0
   220
		CleanupStack::PushL(certificate);
sl@0
   221
		User::LeaveIfError(iCertificates.Append(certificate));
sl@0
   222
		CleanupStack::Pop(certificate);
sl@0
   223
		}
sl@0
   224
sl@0
   225
	CleanupStack::PopAndDestroy(items);
sl@0
   226
	}
sl@0
   227
sl@0
   228
void CPKCS7SignedObject::DecodeRevocationListsL(const TDesC8& /*aRawData*/)
sl@0
   229
	{
sl@0
   230
	// not yet supported
sl@0
   231
	User::Leave(KErrNotSupported);
sl@0
   232
	}
sl@0
   233
sl@0
   234
void CPKCS7SignedObject::DecodeSignerInfoL(const TDesC8& aRawData)
sl@0
   235
	{
sl@0
   236
	CArrayPtr<TASN1DecGeneric>* signerInfo = PKCS7ASN1::DecodeSequenceLC(aRawData);
sl@0
   237
	TInt total = signerInfo->Count();
sl@0
   238
	CPKCS7SignerInfo* signer;
sl@0
   239
sl@0
   240
	for(TInt item = 0; item < total; item ++)
sl@0
   241
		{
sl@0
   242
		signer = CPKCS7SignerInfo::NewL(signerInfo->At(item)->Encoding());
sl@0
   243
		CleanupStack::PushL(signer);
sl@0
   244
		User::LeaveIfError(iSignerInfo.Append(signer));
sl@0
   245
		CleanupStack::Pop(signer);
sl@0
   246
		}
sl@0
   247
	CleanupStack::PopAndDestroy(signerInfo);
sl@0
   248
	}
sl@0
   249
sl@0
   250
EXPORT_C TBool CPKCS7SignedObject::ValidateSignerL(const CPKCS7SignerInfo& aSignerInfo, HBufC8*& aCertChainEncoding)
sl@0
   251
	{
sl@0
   252
	TInt certCount = iCertificates.Count();
sl@0
   253
	TInt endEntityPos = -1;
sl@0
   254
	TInt endEncodingSize = 0;
sl@0
   255
	TPtrC8 endEntityEncoding;
sl@0
   256
	TInt cert;
sl@0
   257
	TBool valid = EFalse;
sl@0
   258
sl@0
   259
	// looks for end entity certificate
sl@0
   260
	for(cert = 0; cert < certCount; cert++)
sl@0
   261
		{
sl@0
   262
		const CX509Certificate& certificate = iCertificates[cert]->Certificate();
sl@0
   263
sl@0
   264
		endEncodingSize+= certificate.Encoding().Length();
sl@0
   265
		if(certificate.IssuerName().ExactMatchL(aSignerInfo.IssuerAndSerialNumber().IssuerName()))
sl@0
   266
			{
sl@0
   267
			endEntityPos = cert;
sl@0
   268
			endEntityEncoding.Set(certificate.Encoding());
sl@0
   269
			valid = ValidateSignatureL(aSignerInfo, certificate);
sl@0
   270
			}
sl@0
   271
		}
sl@0
   272
sl@0
   273
	// checks if end entity was found
sl@0
   274
	if(endEntityPos != -1)
sl@0
   275
		{
sl@0
   276
		// builds the cert chain encoding by putting the end entity first then all remaining
sl@0
   277
		// certs
sl@0
   278
		aCertChainEncoding = HBufC8::NewLC(endEncodingSize);
sl@0
   279
		TPtr8 encodingPtr(aCertChainEncoding->Des());
sl@0
   280
		encodingPtr.Copy(endEntityEncoding);
sl@0
   281
		for(cert = 0; cert < certCount; cert++)
sl@0
   282
			{
sl@0
   283
			const CX509Certificate& certificate = iCertificates[cert]->Certificate();
sl@0
   284
	
sl@0
   285
			if(cert != endEntityPos)
sl@0
   286
				{
sl@0
   287
				encodingPtr.Append(certificate.Encoding());
sl@0
   288
				}
sl@0
   289
			}
sl@0
   290
		}
sl@0
   291
	else
sl@0
   292
		{
sl@0
   293
		User::Leave(KErrNotFound);
sl@0
   294
		}
sl@0
   295
	return valid;
sl@0
   296
	}
sl@0
   297
sl@0
   298
TBool CPKCS7SignedObject::ValidateSignatureL(const CPKCS7SignerInfo& aSignerInfo, const CX509Certificate& aEndEntityCert)
sl@0
   299
	{
sl@0
   300
	iSigningAlgorithm = CX509SigningAlgorithmIdentifier::NewL(aSignerInfo.DigestEncryptionAlgorithm(), aSignerInfo.DigestAlgorithm());
sl@0
   301
	if(iSignature)
sl@0
   302
		{
sl@0
   303
		delete iSignature;
sl@0
   304
		iSignature = NULL;
sl@0
   305
		}
sl@0
   306
	iSignature = aSignerInfo.EncryptedDigest().AllocL();
sl@0
   307
	return VerifySignatureL(aEndEntityCert.PublicKey().KeyData());
sl@0
   308
	}