os/security/cryptoservices/certificateandkeymgmt/pkcs7/cmsutils.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
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 "cmsutils.h"
sl@0
    20
#include <asymmetric.h>
sl@0
    21
#include <asn1enc.h>
sl@0
    22
#include <asn1dec.h> 
sl@0
    23
#include <cmsdefs.h>
sl@0
    24
#include <pkcs7excert.h>
sl@0
    25
#include <x509cert.h>
sl@0
    26
#include "pkcs7asn1.h"
sl@0
    27
sl@0
    28
sl@0
    29
TInt CmsUtils::DecodeContentTypeL(const TASN1DecGeneric* aASN1DecGeneric)
sl@0
    30
	{
sl@0
    31
	TInt type(0);
sl@0
    32
	if(aASN1DecGeneric->Tag()==EASN1ObjectIdentifier || aASN1DecGeneric->Class() == EUniversal)
sl@0
    33
		{
sl@0
    34
		TASN1DecObjectIdentifier oidDec;
sl@0
    35
		HBufC* oidVal = oidDec.DecodeDERL(*aASN1DecGeneric);
sl@0
    36
		CleanupStack::PushL(oidVal);		
sl@0
    37
		
sl@0
    38
		// Checks if it is data OID.
sl@0
    39
		if(*oidVal == KCmsDataOID)
sl@0
    40
			{
sl@0
    41
			// The Content Type is indicated by an Integer.
sl@0
    42
			// Here if Content Type is equal to Data then,it is represented by 1
sl@0
    43
			type = EContentTypeData;
sl@0
    44
			}
sl@0
    45
		else if(*oidVal == KCmsSignedDataOID)
sl@0
    46
			{
sl@0
    47
			// The Content Type is indicated by an Integer.
sl@0
    48
			// Here if Content Type is equal to SignedData then,it is represented by 2
sl@0
    49
			type = EContentTypeSignedData;
sl@0
    50
			}
sl@0
    51
		else if(*oidVal == KCmsEnvelopedDataOID) 
sl@0
    52
			{
sl@0
    53
			// The Content Type is indicated by an Integer.
sl@0
    54
			// Here if Content Type is equal to EnvelopedData then,it is represented by 3.
sl@0
    55
			type = EContentTypeEnvelopedData;
sl@0
    56
			}
sl@0
    57
		else if(*oidVal == KCmsDigestedDataOID)
sl@0
    58
			{
sl@0
    59
			// The Content Type is indicated by an Integer.
sl@0
    60
			// Here if Content Type is equal to DigestedData then,it is represented by 5.
sl@0
    61
			type = EContentTypeDigestedData;
sl@0
    62
			}
sl@0
    63
		else if(*oidVal == KCmsEncryptedDataOID)
sl@0
    64
			{
sl@0
    65
			// The Content Type is indicated by an Integer.
sl@0
    66
			// Here if Content Type is equal to EncryptedData then,it is represented by 6
sl@0
    67
			type = EContentTypeEncryptedData;
sl@0
    68
			}
sl@0
    69
		else if(*oidVal == KCmsAuthenticatedDataOID)
sl@0
    70
			{
sl@0
    71
			// The Content Type is indicated by an Integer.
sl@0
    72
			// Here if Content Type is equal to EncryptedData then,it is represented by 7
sl@0
    73
			type = EContentTypeAuthenticatedData;
sl@0
    74
			}
sl@0
    75
			
sl@0
    76
		else
sl@0
    77
			{
sl@0
    78
			User::Leave(KErrArgument);
sl@0
    79
			}
sl@0
    80
		CleanupStack::PopAndDestroy(oidVal);
sl@0
    81
		}
sl@0
    82
	else
sl@0
    83
		{
sl@0
    84
		User::Leave(KErrArgument);
sl@0
    85
		}	
sl@0
    86
	return type;
sl@0
    87
	}
sl@0
    88
sl@0
    89
CASN1EncObjectIdentifier* CmsUtils::EncodeContentTypeLC(TInt aContentType)
sl@0
    90
	{
sl@0
    91
	TPtrC oidBuf;
sl@0
    92
	switch (aContentType)
sl@0
    93
		{
sl@0
    94
	case EContentTypeData:
sl@0
    95
		oidBuf.Set(KCmsDataOID());
sl@0
    96
		break;
sl@0
    97
		
sl@0
    98
	case EContentTypeSignedData:
sl@0
    99
		oidBuf.Set(KCmsSignedDataOID());
sl@0
   100
		break;
sl@0
   101
		
sl@0
   102
	case EContentTypeEnvelopedData:
sl@0
   103
		oidBuf.Set(KCmsEnvelopedDataOID());
sl@0
   104
		break;
sl@0
   105
	
sl@0
   106
	case EContentTypeDigestedData:
sl@0
   107
		oidBuf.Set(KCmsDigestedDataOID());
sl@0
   108
		break;
sl@0
   109
	
sl@0
   110
	case EContentTypeEncryptedData:
sl@0
   111
		oidBuf.Set(KCmsEncryptedDataOID());
sl@0
   112
		break;
sl@0
   113
	
sl@0
   114
	default:
sl@0
   115
		User::Leave(KErrArgument);
sl@0
   116
		}
sl@0
   117
	//Encode the OID		
sl@0
   118
	CASN1EncObjectIdentifier* oid=CASN1EncObjectIdentifier::NewLC(oidBuf);
sl@0
   119
	return oid;	
sl@0
   120
	}
sl@0
   121
sl@0
   122
void CmsUtils::AddCertificateL(RPointerArray<CCmsCertificateChoice>& aCertList, const TDesC8& aCert, CCmsCertificateChoice::TCertificateType aType)
sl@0
   123
	{
sl@0
   124
	TInt found(EFalse);
sl@0
   125
	TInt count=aCertList.Count();
sl@0
   126
	for (TInt i=0;i<count;i++)
sl@0
   127
		{
sl@0
   128
		if (aCertList[i]->CertificateType()==CCmsCertificateChoice::ECertificateAttribute
sl@0
   129
				&& aCert.Compare(*aCertList[i]->AttributeCertificate())==0)
sl@0
   130
			{
sl@0
   131
			found=ETrue;
sl@0
   132
			break;
sl@0
   133
			}
sl@0
   134
		}
sl@0
   135
		
sl@0
   136
	if (!found)
sl@0
   137
		{
sl@0
   138
		CCmsCertificateChoice* cert=CCmsCertificateChoice::NewL(aType, aCert);
sl@0
   139
		CleanupStack::PushL(cert);
sl@0
   140
		aCertList.AppendL(cert);
sl@0
   141
		CleanupStack::Pop(cert);					
sl@0
   142
		}
sl@0
   143
	}
sl@0
   144
	
sl@0
   145
void CmsUtils::AddCertificateL(RPointerArray<CCmsCertificateChoice>& aCertList, const CX509Certificate& aCert)
sl@0
   146
	{
sl@0
   147
	
sl@0
   148
	TInt found(EFalse);
sl@0
   149
	TInt count=aCertList.Count();
sl@0
   150
	for (TInt i=0;i<count;i++)
sl@0
   151
		{
sl@0
   152
		if (aCertList[i]->CertificateType()==CCmsCertificateChoice::ECertificateX509
sl@0
   153
				&& aCert.IsEqualL(aCertList[i]->Certificate()))
sl@0
   154
			{
sl@0
   155
			found=ETrue;
sl@0
   156
			break;
sl@0
   157
			}
sl@0
   158
		}
sl@0
   159
	
sl@0
   160
	if (!found)
sl@0
   161
		{
sl@0
   162
		CCmsCertificateChoice* cert=CCmsCertificateChoice::NewL(aCert);
sl@0
   163
		CleanupStack::PushL(cert);
sl@0
   164
		aCertList.AppendL(cert);
sl@0
   165
		CleanupStack::Pop(cert);					
sl@0
   166
		}
sl@0
   167
		
sl@0
   168
	}
sl@0
   169
	
sl@0
   170
void CmsUtils::AddAlgorithmIdentifierL(RPointerArray<CX509AlgorithmIdentifier>& aAlgorithmIdList, TAlgorithmId aDigestAlgorithm)
sl@0
   171
	{
sl@0
   172
	TInt found(EFalse);
sl@0
   173
	TInt count=aAlgorithmIdList.Count();
sl@0
   174
	for (TInt i=0;i<count;i++)
sl@0
   175
		{
sl@0
   176
		if (aAlgorithmIdList[i]->Algorithm()==aDigestAlgorithm)
sl@0
   177
			{
sl@0
   178
			found=ETrue;
sl@0
   179
			break;
sl@0
   180
			}
sl@0
   181
		}
sl@0
   182
	if (!found)
sl@0
   183
		{
sl@0
   184
		CX509AlgorithmIdentifier* digAlg=CX509AlgorithmIdentifier::NewLC(aDigestAlgorithm, KNullDesC8());
sl@0
   185
		aAlgorithmIdList.AppendL(digAlg);
sl@0
   186
		CleanupStack::Pop(digAlg);					
sl@0
   187
		}
sl@0
   188
	}
sl@0
   189
sl@0
   190
void CmsUtils::DecodeDigestAlgorithmsL(RPointerArray<CX509AlgorithmIdentifier>& aDigestAlgorithms, 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
		aDigestAlgorithms.AppendL(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 CmsUtils::DecodeCertificatesL(RPointerArray<CCmsCertificateChoice>& aCertificates, const TDesC8& aRawData)
sl@0
   206
	{
sl@0
   207
	TASN1DecGeneric decGen(aRawData);
sl@0
   208
	decGen.InitL();
sl@0
   209
	TASN1DecSequence decSeq;
sl@0
   210
	// have to do manual decoding of sequence because field is optional
sl@0
   211
	CArrayPtr<TASN1DecGeneric>* items = NULL;
sl@0
   212
	items = decSeq.DecodeDERLC(decGen);
sl@0
   213
	TInt count = items->Count();
sl@0
   214
sl@0
   215
	CCmsCertificateChoice* certificate;
sl@0
   216
sl@0
   217
	for(TInt item = 0; item < count; item++)
sl@0
   218
		{
sl@0
   219
 		certificate = CCmsCertificateChoice::NewL(items->At(item)->Encoding());
sl@0
   220
		CleanupStack::PushL(certificate);
sl@0
   221
		aCertificates.AppendL(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
CASN1EncBase* CmsUtils::EncodeCertificatesLC(const RPointerArray<CCmsCertificateChoice>& aCertificates)
sl@0
   229
	{
sl@0
   230
	CASN1EncSet* certSet(NULL);
sl@0
   231
	TInt count=aCertificates.Count();
sl@0
   232
	if (count>0)
sl@0
   233
		{
sl@0
   234
		certSet = CASN1EncSet::NewLC();
sl@0
   235
		for (TInt i=0;i<count;i++)
sl@0
   236
			{
sl@0
   237
			CASN1EncEncoding* cert=aCertificates[i]->EncodeASN1DERLC();
sl@0
   238
			certSet->AddAndPopChildL(cert);
sl@0
   239
			}
sl@0
   240
		// [0] implicit
sl@0
   241
		certSet->SetTag(0);	
sl@0
   242
		}
sl@0
   243
	return certSet;
sl@0
   244
	}
sl@0
   245
sl@0
   246
CASN1EncBase* CmsUtils::EncodeDigestAlgorithmsLC(const RPointerArray<CX509AlgorithmIdentifier>& aDigestAlgorithms)
sl@0
   247
	{
sl@0
   248
	CASN1EncSet* algorithmSet = CASN1EncSet::NewLC();
sl@0
   249
	TInt count=aDigestAlgorithms.Count();
sl@0
   250
	
sl@0
   251
	for (TInt i=0;i<count;i++)
sl@0
   252
		{
sl@0
   253
		CASN1EncSequence* tmp=aDigestAlgorithms[i]->EncodeASN1DERLC();
sl@0
   254
		algorithmSet->AddAndPopChildL(tmp);
sl@0
   255
		}
sl@0
   256
		
sl@0
   257
	return algorithmSet;
sl@0
   258
	}
sl@0
   259
sl@0
   260
void CmsUtils::DecodeOctetStringL(const TDesC8& aRawData, HBufC8*& aBuf)
sl@0
   261
	{
sl@0
   262
	TASN1DecGeneric decGen(aRawData);
sl@0
   263
	decGen.InitL();
sl@0
   264
sl@0
   265
	if(decGen.Tag()==EASN1OctetString && decGen.Class()==EUniversal)
sl@0
   266
		{
sl@0
   267
		TASN1DecOctetString decOct;
sl@0
   268
		aBuf = decOct.DecodeDERL(decGen);
sl@0
   269
		}
sl@0
   270
	else
sl@0
   271
		{
sl@0
   272
		User::Leave(KErrArgument);
sl@0
   273
		}
sl@0
   274
	}
sl@0
   275
sl@0
   276
sl@0
   277
CMessageDigest* CmsUtils::CreateHashLC(TAlgorithmId aAlgorithm)
sl@0
   278
	{	
sl@0
   279
	CMessageDigest* hash(NULL);
sl@0
   280
	switch (aAlgorithm)
sl@0
   281
		{
sl@0
   282
	case EMD2:
sl@0
   283
		hash=CMD2::NewL();
sl@0
   284
		break;
sl@0
   285
		
sl@0
   286
	case EMD5:
sl@0
   287
		hash=CMD5::NewL();
sl@0
   288
		break;
sl@0
   289
		
sl@0
   290
	case ESHA1:
sl@0
   291
		hash=CSHA1::NewL();
sl@0
   292
		break;
sl@0
   293
		
sl@0
   294
	default:
sl@0
   295
		User::Leave(KErrNotSupported);
sl@0
   296
		}
sl@0
   297
	CleanupStack::PushL(hash);
sl@0
   298
	return hash;	
sl@0
   299
	}
sl@0
   300
sl@0
   301
sl@0
   302
HBufC8* CmsUtils::CreateSignatureL(const TDesC8& aDataToBeSigned, TBool aIsHash, TAlgorithmId aAlgorithm, const CDSAPrivateKey& aKey)
sl@0
   303
	{
sl@0
   304
	HBufC8* signature(NULL);
sl@0
   305
	
sl@0
   306
	if (!aIsHash)
sl@0
   307
		{
sl@0
   308
		TPtrC8 hashValue;
sl@0
   309
		// Create hash first
sl@0
   310
		CMessageDigest* hash=CreateHashLC(aAlgorithm);
sl@0
   311
		hashValue.Set(hash->Hash(aDataToBeSigned));
sl@0
   312
		signature=CreateSignatureL(hashValue, aKey);
sl@0
   313
		CleanupStack::PopAndDestroy(); // hash
sl@0
   314
		}
sl@0
   315
	else
sl@0
   316
		{
sl@0
   317
		signature=CreateSignatureL(aDataToBeSigned, aKey);
sl@0
   318
		}
sl@0
   319
		
sl@0
   320
	return signature;
sl@0
   321
	}
sl@0
   322
sl@0
   323
HBufC8* CmsUtils::CreateSignatureL(const TDesC8& aDataToBeSigned, TBool aIsHash, TAlgorithmId aAlgorithm, const CRSAPrivateKey& aKey)
sl@0
   324
	{
sl@0
   325
	HBufC8* signature(NULL);
sl@0
   326
	TPtrC8 hashValue;
sl@0
   327
	if (!aIsHash)
sl@0
   328
		{
sl@0
   329
		// Create hash first
sl@0
   330
		CMessageDigest* hash=CreateHashLC(aAlgorithm);
sl@0
   331
		hashValue.Set(hash->Hash(aDataToBeSigned));
sl@0
   332
		}
sl@0
   333
	else
sl@0
   334
		{
sl@0
   335
		hashValue.Set(aDataToBeSigned);
sl@0
   336
		}
sl@0
   337
		
sl@0
   338
	//Build the digestInfo Sequence
sl@0
   339
	CASN1EncSequence* digestInfoSeq = CASN1EncSequence::NewLC();
sl@0
   340
	
sl@0
   341
	//Encode the Algorithm
sl@0
   342
	CX509AlgorithmIdentifier* digAlg=CX509AlgorithmIdentifier::NewLC(aAlgorithm, KNullDesC8());
sl@0
   343
	CASN1EncSequence* sigAlg=digAlg->EncodeASN1DERLC();
sl@0
   344
	digestInfoSeq->AddAndPopChildL(sigAlg);
sl@0
   345
	CleanupStack::PopAndDestroy(digAlg);
sl@0
   346
	
sl@0
   347
	//Encode the digest itself
sl@0
   348
	CASN1EncOctetString* sigEnc=CASN1EncOctetString::NewLC(hashValue);
sl@0
   349
	digestInfoSeq->AddAndPopChildL(sigEnc);
sl@0
   350
sl@0
   351
	//Get the Encoding
sl@0
   352
	HBufC8* digestInfo=CreateDEREncodingLC(*digestInfoSeq);
sl@0
   353
	signature=CreateSignatureL(digestInfo->Des(), aKey);
sl@0
   354
	
sl@0
   355
	CleanupStack::PopAndDestroy(2, digestInfoSeq); //digestInfo, digestInfoSeq
sl@0
   356
	if (!aIsHash)
sl@0
   357
		{
sl@0
   358
		CleanupStack::PopAndDestroy(); // hash			
sl@0
   359
		}
sl@0
   360
	return signature;
sl@0
   361
	}
sl@0
   362
	
sl@0
   363
HBufC8* CmsUtils::CreateSignatureL(const TDesC8& aHash, const CDSAPrivateKey& aKey)
sl@0
   364
	{	
sl@0
   365
	//Create Signer and sign the hash
sl@0
   366
	CDSASigner* signer=CDSASigner::NewLC(aKey);
sl@0
   367
	const CDSASignature* sig=signer->SignL(aHash);
sl@0
   368
	CDSASignature* signonc=const_cast<CDSASignature*>(sig);
sl@0
   369
	
sl@0
   370
	CleanupStack::PushL(signonc);
sl@0
   371
	
sl@0
   372
	//The sequence
sl@0
   373
	CASN1EncSequence* sigSeq = CASN1EncSequence::NewLC();	
sl@0
   374
	CASN1EncBigInt* r = CASN1EncBigInt::NewLC(static_cast<const RInteger&>(sig->R()));
sl@0
   375
	sigSeq->AddAndPopChildL(r);
sl@0
   376
	CASN1EncBigInt* s = CASN1EncBigInt::NewLC(static_cast<const RInteger&>(sig->S()));
sl@0
   377
	sigSeq->AddAndPopChildL(s);
sl@0
   378
		
sl@0
   379
	//Write the buffer
sl@0
   380
	TUint len=sigSeq->LengthDER();
sl@0
   381
	HBufC8* buf=HBufC8::NewMaxLC(len);
sl@0
   382
	TPtr8 des=buf->Des();
sl@0
   383
	TUint pos=0;
sl@0
   384
	sigSeq->WriteDERL(des, pos);
sl@0
   385
	
sl@0
   386
	//Clean up
sl@0
   387
	CleanupStack::Pop(buf); //buf
sl@0
   388
	CleanupStack::PopAndDestroy(3, signer); //sigSeq, signonc, signer
sl@0
   389
	return buf;
sl@0
   390
	}
sl@0
   391
sl@0
   392
HBufC8* CmsUtils::CreateSignatureL(const TDesC8& aHash, const CRSAPrivateKey& aKey)
sl@0
   393
	{
sl@0
   394
	//Create Signer and sign the hash
sl@0
   395
	CRSAPKCS1v15Signer* signer=CRSAPKCS1v15Signer::NewLC(aKey);
sl@0
   396
	const CRSASignature* sig=signer->SignL(aHash);
sl@0
   397
	CRSASignature* signonc=const_cast<CRSASignature*>(sig);
sl@0
   398
	
sl@0
   399
	CleanupStack::PushL(signonc);
sl@0
   400
	
sl@0
   401
	HBufC8* sigData = sig->S().BufferWithNoTruncationLC();
sl@0
   402
	
sl@0
   403
	//Clean up
sl@0
   404
	CleanupStack::Pop(sigData);
sl@0
   405
	CleanupStack::PopAndDestroy(2, signer);//signonc signer
sl@0
   406
	return sigData;
sl@0
   407
	}
sl@0
   408
sl@0
   409
HBufC8* CmsUtils::CreateDEREncodingLC(const CASN1EncBase& aEncoding)
sl@0
   410
	{	
sl@0
   411
	TUint len = aEncoding.LengthDER();
sl@0
   412
	HBufC8* buf = HBufC8::NewMaxLC(len);
sl@0
   413
	TUint pos = 0;
sl@0
   414
	TPtr8 bufptr(buf->Des());
sl@0
   415
	aEncoding.WriteDERL(bufptr, pos);
sl@0
   416
	return buf;
sl@0
   417
	}
sl@0
   418
sl@0
   419
sl@0
   420
sl@0
   421
sl@0
   422
sl@0
   423
sl@0
   424
sl@0
   425
sl@0
   426
sl@0
   427
sl@0
   428
sl@0
   429
sl@0
   430
sl@0
   431
sl@0
   432
sl@0
   433
sl@0
   434
sl@0
   435
sl@0
   436
sl@0
   437
sl@0
   438
sl@0
   439
sl@0
   440
sl@0
   441