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