os/security/cryptoservices/certificateandkeymgmt/recog/CertRecog.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) 2001-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 <apmrec.h>
sl@0
    20
#include <apmstd.h>
sl@0
    21
#include <asn1cons.h>
sl@0
    22
#include <ecom/ecom.h>
sl@0
    23
#include <ecom/implementationproxy.h>
sl@0
    24
sl@0
    25
#include "CertRecog.h"
sl@0
    26
#include "x509cert.h"
sl@0
    27
#include "x509certext.h"
sl@0
    28
sl@0
    29
sl@0
    30
sl@0
    31
const TInt KCertificateRecognizerValue = 0x101F4A71;
sl@0
    32
const TUid KUidMimeCertRecognizer = { KCertificateRecognizerValue };
sl@0
    33
sl@0
    34
// User certs
sl@0
    35
_LIT8( KDataTypeWAPCertificateResponse, "application/vnd.wap.cert-response" );
sl@0
    36
_LIT8( KDataTypeX509_USER_Certificate, "application/x-x509-user-cert" );
sl@0
    37
sl@0
    38
// CA certs
sl@0
    39
_LIT8( KDataTypeX509_CA_Certificate, "application/x-x509-ca-cert" );
sl@0
    40
_LIT8( KDataTypeWAP_WTLS_CA_Certificate, "application/vnd.wap.wtls-ca-certificate" );
sl@0
    41
sl@0
    42
const TInt KSupportedDataTypesTotal = 3;
sl@0
    43
sl@0
    44
const TInt KX509MinBufferLength = 30;
sl@0
    45
const TInt KCertRecMaxBufferLength = 80;
sl@0
    46
sl@0
    47
const TInt KASN1SequenceTagValue = 0x30;
sl@0
    48
const TInt KASN1SequenceTwoBytesLength = 0x82;
sl@0
    49
const TInt KASN1SequenceThreeBytesLength = 0x83;
sl@0
    50
const TInt KASN1VersionWrapperTagValue = 0xA0;
sl@0
    51
const TInt KASN1VersionWrapperLengthValue = 0x03;
sl@0
    52
const TInt KASN1VersionLengthValue = 0x01;
sl@0
    53
enum { EX509VersionValue1 = 0x00, EX509VersionValue2 = 0x01, EX509VersionValue3 = 0x02 };
sl@0
    54
const TInt KWTLSCertificateVersionValue = 0x01;
sl@0
    55
sl@0
    56
sl@0
    57
sl@0
    58
// ----------------------------------------------------------------------------
sl@0
    59
// CApaCertificateRecognizer
sl@0
    60
//
sl@0
    61
sl@0
    62
CApaCertificateRecognizer::CApaCertificateRecognizer()
sl@0
    63
	: CApaDataRecognizerType( KUidMimeCertRecognizer, CApaDataRecognizerType::ENormal )
sl@0
    64
	{
sl@0
    65
	iCountDataTypes = KSupportedDataTypesTotal;
sl@0
    66
	}
sl@0
    67
sl@0
    68
sl@0
    69
sl@0
    70
TUint CApaCertificateRecognizer::PreferredBufSize()
sl@0
    71
	{
sl@0
    72
	return KCertRecMaxBufferLength;
sl@0
    73
	}
sl@0
    74
sl@0
    75
sl@0
    76
sl@0
    77
TDataType CApaCertificateRecognizer::SupportedDataTypeL( TInt aIndex ) const
sl@0
    78
	{
sl@0
    79
	__ASSERT_DEBUG( aIndex >= 0 && aIndex < KSupportedDataTypesTotal,
sl@0
    80
					User::Panic( _L("RECCERT"), 0 ) );
sl@0
    81
	switch ( aIndex )
sl@0
    82
		{
sl@0
    83
		case 0:
sl@0
    84
			return TDataType( KDataTypeX509_CA_Certificate );
sl@0
    85
		case 1:
sl@0
    86
			return TDataType( KDataTypeWAP_WTLS_CA_Certificate );
sl@0
    87
		// Used to prevent warning about return paths not all returning a value
sl@0
    88
		default:
sl@0
    89
			return TDataType( KDataTypeWAPCertificateResponse );
sl@0
    90
		}
sl@0
    91
	}
sl@0
    92
sl@0
    93
sl@0
    94
sl@0
    95
void CApaCertificateRecognizer::DoRecognizeL( const TDesC& aName, const TDesC8& aBuffer )
sl@0
    96
	{
sl@0
    97
 	
sl@0
    98
 	RFile* filePtr = FilePassedByHandleL();
sl@0
    99
 	if (filePtr)
sl@0
   100
 		{
sl@0
   101
 		ReadFileAndRecognizeL(*filePtr);
sl@0
   102
 		return;	
sl@0
   103
 		}
sl@0
   104
 	
sl@0
   105
 	//Connect to file server
sl@0
   106
 	RFs fs;
sl@0
   107
 	User::LeaveIfError(fs.Connect());	
sl@0
   108
 	CleanupClosePushL(fs);
sl@0
   109
 	
sl@0
   110
 	// See if the data is passed by filename
sl@0
   111
 	RFile fileToRead;	
sl@0
   112
 	TInt ret = fileToRead.Open(fs, aName, EFileRead | EFileShareReadersOnly | EFileStream);
sl@0
   113
 	CleanupClosePushL(fileToRead);
sl@0
   114
 	if (ret == KErrNone)
sl@0
   115
 		{
sl@0
   116
 		//Try the preferred buffer size first
sl@0
   117
 		ReadFileAndRecognizeL(fileToRead);
sl@0
   118
 		}
sl@0
   119
 	else
sl@0
   120
 		// If not passed by file name, can try to recognize buffer.
sl@0
   121
 		{
sl@0
   122
 		DoRecognizeBufferL(aBuffer, EFalse, fileToRead);
sl@0
   123
 		}
sl@0
   124
 	
sl@0
   125
 	CleanupStack::PopAndDestroy(2); //fileToRead, fs		
sl@0
   126
 	
sl@0
   127
 	}
sl@0
   128
sl@0
   129
void CApaCertificateRecognizer::ReadFileAndRecognizeL(RFile& aFileToRead)
sl@0
   130
 	{
sl@0
   131
 	TInt size=PreferredBufSize();
sl@0
   132
 	HBufC8* memForFile = HBufC8::NewLC(size);
sl@0
   133
 	TPtr8 preferredBuffer(memForFile->Des());
sl@0
   134
 	User::LeaveIfError(aFileToRead.Read(preferredBuffer, size));
sl@0
   135
 	DoRecognizeBufferL(preferredBuffer, ETrue, aFileToRead);		
sl@0
   136
 	CleanupStack::PopAndDestroy(memForFile); //memForFile	
sl@0
   137
 	}
sl@0
   138
 
sl@0
   139
void CApaCertificateRecognizer::DoRecognizeBufferL(const TDesC8& aBuffer,  TBool aIsFile, RFile& aFile)
sl@0
   140
	{
sl@0
   141
	// Ensure length is sufficient for checking type
sl@0
   142
   	if ( aBuffer.Size() >= 1 )
sl@0
   143
   		{
sl@0
   144
   		// First byte of X.509 certificate is an ANS.1 SEQUENCE tag
sl@0
   145
   		if ( aBuffer[0] == KASN1SequenceTagValue )
sl@0
   146
   			{
sl@0
   147
  			RecognizeX509CertL( aBuffer, aIsFile, aFile);
sl@0
   148
   			}
sl@0
   149
   		// First byte of WTLS certificate is version == 1
sl@0
   150
   		else if ( aBuffer[0] == KWTLSCertificateVersionValue )
sl@0
   151
   			{
sl@0
   152
  			RecognizeWTLSCertOrCertResponse( aBuffer, aIsFile, aFile);
sl@0
   153
   			}
sl@0
   154
  		
sl@0
   155
 		}						
sl@0
   156
   	}
sl@0
   157
sl@0
   158
void CApaCertificateRecognizer::RecognizeX509CertL( const TDesC8& aBuffer,  TBool aIsFile, RFile& aFile )
sl@0
   159
		{
sl@0
   160
sl@0
   161
	//Basic check if this is a X509 certificate
sl@0
   162
	TBool isCertV1orV2(EFalse);
sl@0
   163
	TInt bufferSize = aBuffer.Size();
sl@0
   164
	if ( bufferSize < KX509MinBufferLength )
sl@0
   165
		{
sl@0
   166
		return;
sl@0
   167
		}
sl@0
   168
	TInt index = 1;
sl@0
   169
	// Check first sequence length byte and skip over the length value bytes
sl@0
   170
	if ( aBuffer[index] == KASN1SequenceTwoBytesLength )
sl@0
   171
		{
sl@0
   172
		index += 3;
sl@0
   173
		}
sl@0
   174
	else if ( aBuffer[index] == KASN1SequenceThreeBytesLength )
sl@0
   175
		{
sl@0
   176
		index += 4;
sl@0
   177
		}
sl@0
   178
	else
sl@0
   179
		{
sl@0
   180
		return;
sl@0
   181
		}
sl@0
   182
	// Check next byte that is another sequence start
sl@0
   183
	if ( aBuffer[index] != KASN1SequenceTagValue )
sl@0
   184
		{
sl@0
   185
		return;
sl@0
   186
		}
sl@0
   187
	++index;
sl@0
   188
	// Check second sequence length byte and skip over the length value bytes
sl@0
   189
	if ( aBuffer[index] == KASN1SequenceTwoBytesLength )
sl@0
   190
		{
sl@0
   191
		index += 3;
sl@0
   192
		}
sl@0
   193
	else if ( aBuffer[index] == KASN1SequenceThreeBytesLength )
sl@0
   194
		{
sl@0
   195
		index += 4;
sl@0
   196
		}
sl@0
   197
	else
sl@0
   198
		{
sl@0
   199
		return;
sl@0
   200
		}
sl@0
   201
	// Check for VERSION field
sl@0
   202
	if ( aBuffer[index] == KASN1VersionWrapperTagValue )
sl@0
   203
		{
sl@0
   204
		++index;
sl@0
   205
		if ( aBuffer[index] != KASN1VersionWrapperLengthValue )
sl@0
   206
			{
sl@0
   207
			return;
sl@0
   208
			}
sl@0
   209
		++index;
sl@0
   210
		if ( aBuffer[index] != EASN1Integer )
sl@0
   211
			{
sl@0
   212
			return;
sl@0
   213
			}
sl@0
   214
		++index;
sl@0
   215
		if ( aBuffer[index] != KASN1VersionLengthValue )
sl@0
   216
			{
sl@0
   217
			return;
sl@0
   218
			}
sl@0
   219
		++index;
sl@0
   220
sl@0
   221
		// The cert is X509 v1 or v2
sl@0
   222
 		if (aBuffer[index] == EX509VersionValue1 ||
sl@0
   223
 		    aBuffer[index] == EX509VersionValue2)
sl@0
   224
		    {
sl@0
   225
		    isCertV1orV2=ETrue;
sl@0
   226
		    }
sl@0
   227
		else
sl@0
   228
	 	   // The cert is neither X509 v1 nor v2
sl@0
   229
 		    {
sl@0
   230
 		   // The cert is not v3 as well 
sl@0
   231
 		   if (aBuffer[index] != EX509VersionValue3)
sl@0
   232
 			{
sl@0
   233
 			return;	
sl@0
   234
			}
sl@0
   235
 		    }		
sl@0
   236
sl@0
   237
		++index;
sl@0
   238
		}
sl@0
   239
	else
sl@0
   240
		{
sl@0
   241
		isCertV1orV2=ETrue;	
sl@0
   242
		}
sl@0
   243
	// Check for SerialNumber field
sl@0
   244
	if ( aBuffer[index] != EASN1Integer )
sl@0
   245
		{
sl@0
   246
		return;
sl@0
   247
		}
sl@0
   248
	++index;
sl@0
   249
	TInt serialNumberSize = aBuffer[index];
sl@0
   250
	++index;
sl@0
   251
	index += serialNumberSize;
sl@0
   252
	// 1 is added for the next increments of index
sl@0
   253
	if((index + 1) >= bufferSize)
sl@0
   254
		{
sl@0
   255
		return;
sl@0
   256
		}
sl@0
   257
	// Check for SIGNATURE field
sl@0
   258
	if ( aBuffer[index] != KASN1SequenceTagValue )
sl@0
   259
		{
sl@0
   260
		return;
sl@0
   261
		}
sl@0
   262
	++index;
sl@0
   263
	TInt signatureSize = aBuffer[index];
sl@0
   264
	++index;
sl@0
   265
	index += signatureSize;
sl@0
   266
	if(index >= bufferSize)
sl@0
   267
		{
sl@0
   268
		return;
sl@0
   269
		}
sl@0
   270
	 	
sl@0
   271
 	// if the certificate is passed by the buffer, but not file name 
sl@0
   272
 	if (!aIsFile)	
sl@0
   273
 		{
sl@0
   274
 		// Check only the starting TAG byte of the NAME field
sl@0
   275
 		if ( aBuffer[index] == KASN1SequenceTagValue )
sl@0
   276
 			{
sl@0
   277
 			iDataType = TDataType( KDataTypeX509_CA_Certificate );
sl@0
   278
 			iConfidence = EProbable;
sl@0
   279
 			}			
sl@0
   280
 		}
sl@0
   281
 	else
sl@0
   282
 		// if the certificate is passed by file name
sl@0
   283
		{
sl@0
   284
		if (!isCertV1orV2) // x509 V3 certificate
sl@0
   285
 			{ 
sl@0
   286
 			//Get the file size
sl@0
   287
 			TInt size;
sl@0
   288
 			User::LeaveIfError(aFile.Size(size));
sl@0
   289
 			HBufC8* memForFile = HBufC8::NewLC(size);
sl@0
   290
 			TPtr8 fileContent(memForFile->Des());
sl@0
   291
 			TInt pos=0;
sl@0
   292
 			aFile.Seek(ESeekStart, pos);
sl@0
   293
 			User::LeaveIfError(aFile.Read(fileContent, size));
sl@0
   294
 			RecognizeWholeX509CertificateL(fileContent);
sl@0
   295
 			CleanupStack::PopAndDestroy(memForFile);//memForFile
sl@0
   296
			}									
sl@0
   297
 		else  // x509 V1 or V2 certificate
sl@0
   298
 			{ 
sl@0
   299
 			iDataType = TDataType( KDataTypeX509_CA_Certificate );
sl@0
   300
 			iConfidence = EProbable;				
sl@0
   301
 			}
sl@0
   302
	
sl@0
   303
		}
sl@0
   304
	}
sl@0
   305
sl@0
   306
void CApaCertificateRecognizer::RecognizeWholeX509CertificateL(const TDesC8& aBuffer)
sl@0
   307
 	{
sl@0
   308
 	CX509Certificate* cert = CX509Certificate::NewLC(aBuffer);
sl@0
   309
 	if (cert)
sl@0
   310
 		{
sl@0
   311
 		const CX509CertExtension* certExt = cert->Extension(KBasicConstraints);
sl@0
   312
 		if (certExt)
sl@0
   313
 			{
sl@0
   314
 			CX509BasicConstraintsExt* basic = CX509BasicConstraintsExt::NewLC(certExt->Data());
sl@0
   315
 			if (basic->IsCA())
sl@0
   316
 				{
sl@0
   317
 				iDataType = TDataType( KDataTypeX509_CA_Certificate );
sl@0
   318
 				iConfidence = EProbable;					
sl@0
   319
 				}
sl@0
   320
 			else
sl@0
   321
 				{
sl@0
   322
 				iDataType = TDataType( KDataTypeX509_USER_Certificate );
sl@0
   323
 				iConfidence = EProbable;										
sl@0
   324
 				}
sl@0
   325
 			CleanupStack::PopAndDestroy(basic); //basic				
sl@0
   326
			}
sl@0
   327
 		else
sl@0
   328
 			{
sl@0
   329
 			iDataType = TDataType( KDataTypeX509_USER_Certificate );
sl@0
   330
 			iConfidence = EProbable;														
sl@0
   331
 			}
sl@0
   332
 		}
sl@0
   333
 	CleanupStack::PopAndDestroy(cert); //cert
sl@0
   334
 	}
sl@0
   335
sl@0
   336
sl@0
   337
sl@0
   338
void CApaCertificateRecognizer::RecognizeWTLSCertOrCertResponse( const TDesC8& aBuffer, TBool /*aIsFile*/, RFile& /*aFile*/ )
sl@0
   339
	{
sl@0
   340
	if ( aBuffer.Size() >= 3 )
sl@0
   341
		{
sl@0
   342
		// Check next byte is signature algorithm value from 0 - 2
sl@0
   343
		if ( aBuffer[1] == 0x00 || aBuffer[1] == 0x01 || aBuffer[1] == 0x02 )
sl@0
   344
			{
sl@0
   345
			// Check Identifier Type for Issuer Identifier
sl@0
   346
			if ( aBuffer[2] == 0x01 )
sl@0
   347
				{
sl@0
   348
				iDataType = TDataType( KDataTypeWAP_WTLS_CA_Certificate );
sl@0
   349
				}
sl@0
   350
			else
sl@0
   351
				{
sl@0
   352
				iDataType = TDataType( KDataTypeWAPCertificateResponse );
sl@0
   353
				}
sl@0
   354
			iConfidence = EPossible;
sl@0
   355
			}
sl@0
   356
		}
sl@0
   357
	}
sl@0
   358
sl@0
   359
CApaDataRecognizerType* CApaCertificateRecognizer::CreateRecognizerL()
sl@0
   360
	{
sl@0
   361
	return new (ELeave) CApaCertificateRecognizer();
sl@0
   362
	}
sl@0
   363
sl@0
   364
const TImplementationProxy ImplementationTable[] = 
sl@0
   365
	{
sl@0
   366
		IMPLEMENTATION_PROXY_ENTRY(0x102034A2, CApaCertificateRecognizer::CreateRecognizerL)
sl@0
   367
	};
sl@0
   368
sl@0
   369
EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
sl@0
   370
	{
sl@0
   371
	aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
sl@0
   372
	return ImplementationTable;
sl@0
   373
	}	
sl@0
   374