os/security/cryptoservices/certificateandkeymgmt/recog/CertRecog.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/security/cryptoservices/certificateandkeymgmt/recog/CertRecog.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,374 @@
     1.4 +/*
     1.5 +* Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.6 +* All rights reserved.
     1.7 +* This component and the accompanying materials are made available
     1.8 +* under the terms of the License "Eclipse Public License v1.0"
     1.9 +* which accompanies this distribution, and is available
    1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.11 +*
    1.12 +* Initial Contributors:
    1.13 +* Nokia Corporation - initial contribution.
    1.14 +*
    1.15 +* Contributors:
    1.16 +*
    1.17 +* Description: 
    1.18 +*
    1.19 +*/
    1.20 +
    1.21 +
    1.22 +#include <apmrec.h>
    1.23 +#include <apmstd.h>
    1.24 +#include <asn1cons.h>
    1.25 +#include <ecom/ecom.h>
    1.26 +#include <ecom/implementationproxy.h>
    1.27 +
    1.28 +#include "CertRecog.h"
    1.29 +#include "x509cert.h"
    1.30 +#include "x509certext.h"
    1.31 +
    1.32 +
    1.33 +
    1.34 +const TInt KCertificateRecognizerValue = 0x101F4A71;
    1.35 +const TUid KUidMimeCertRecognizer = { KCertificateRecognizerValue };
    1.36 +
    1.37 +// User certs
    1.38 +_LIT8( KDataTypeWAPCertificateResponse, "application/vnd.wap.cert-response" );
    1.39 +_LIT8( KDataTypeX509_USER_Certificate, "application/x-x509-user-cert" );
    1.40 +
    1.41 +// CA certs
    1.42 +_LIT8( KDataTypeX509_CA_Certificate, "application/x-x509-ca-cert" );
    1.43 +_LIT8( KDataTypeWAP_WTLS_CA_Certificate, "application/vnd.wap.wtls-ca-certificate" );
    1.44 +
    1.45 +const TInt KSupportedDataTypesTotal = 3;
    1.46 +
    1.47 +const TInt KX509MinBufferLength = 30;
    1.48 +const TInt KCertRecMaxBufferLength = 80;
    1.49 +
    1.50 +const TInt KASN1SequenceTagValue = 0x30;
    1.51 +const TInt KASN1SequenceTwoBytesLength = 0x82;
    1.52 +const TInt KASN1SequenceThreeBytesLength = 0x83;
    1.53 +const TInt KASN1VersionWrapperTagValue = 0xA0;
    1.54 +const TInt KASN1VersionWrapperLengthValue = 0x03;
    1.55 +const TInt KASN1VersionLengthValue = 0x01;
    1.56 +enum { EX509VersionValue1 = 0x00, EX509VersionValue2 = 0x01, EX509VersionValue3 = 0x02 };
    1.57 +const TInt KWTLSCertificateVersionValue = 0x01;
    1.58 +
    1.59 +
    1.60 +
    1.61 +// ----------------------------------------------------------------------------
    1.62 +// CApaCertificateRecognizer
    1.63 +//
    1.64 +
    1.65 +CApaCertificateRecognizer::CApaCertificateRecognizer()
    1.66 +	: CApaDataRecognizerType( KUidMimeCertRecognizer, CApaDataRecognizerType::ENormal )
    1.67 +	{
    1.68 +	iCountDataTypes = KSupportedDataTypesTotal;
    1.69 +	}
    1.70 +
    1.71 +
    1.72 +
    1.73 +TUint CApaCertificateRecognizer::PreferredBufSize()
    1.74 +	{
    1.75 +	return KCertRecMaxBufferLength;
    1.76 +	}
    1.77 +
    1.78 +
    1.79 +
    1.80 +TDataType CApaCertificateRecognizer::SupportedDataTypeL( TInt aIndex ) const
    1.81 +	{
    1.82 +	__ASSERT_DEBUG( aIndex >= 0 && aIndex < KSupportedDataTypesTotal,
    1.83 +					User::Panic( _L("RECCERT"), 0 ) );
    1.84 +	switch ( aIndex )
    1.85 +		{
    1.86 +		case 0:
    1.87 +			return TDataType( KDataTypeX509_CA_Certificate );
    1.88 +		case 1:
    1.89 +			return TDataType( KDataTypeWAP_WTLS_CA_Certificate );
    1.90 +		// Used to prevent warning about return paths not all returning a value
    1.91 +		default:
    1.92 +			return TDataType( KDataTypeWAPCertificateResponse );
    1.93 +		}
    1.94 +	}
    1.95 +
    1.96 +
    1.97 +
    1.98 +void CApaCertificateRecognizer::DoRecognizeL( const TDesC& aName, const TDesC8& aBuffer )
    1.99 +	{
   1.100 + 	
   1.101 + 	RFile* filePtr = FilePassedByHandleL();
   1.102 + 	if (filePtr)
   1.103 + 		{
   1.104 + 		ReadFileAndRecognizeL(*filePtr);
   1.105 + 		return;	
   1.106 + 		}
   1.107 + 	
   1.108 + 	//Connect to file server
   1.109 + 	RFs fs;
   1.110 + 	User::LeaveIfError(fs.Connect());	
   1.111 + 	CleanupClosePushL(fs);
   1.112 + 	
   1.113 + 	// See if the data is passed by filename
   1.114 + 	RFile fileToRead;	
   1.115 + 	TInt ret = fileToRead.Open(fs, aName, EFileRead | EFileShareReadersOnly | EFileStream);
   1.116 + 	CleanupClosePushL(fileToRead);
   1.117 + 	if (ret == KErrNone)
   1.118 + 		{
   1.119 + 		//Try the preferred buffer size first
   1.120 + 		ReadFileAndRecognizeL(fileToRead);
   1.121 + 		}
   1.122 + 	else
   1.123 + 		// If not passed by file name, can try to recognize buffer.
   1.124 + 		{
   1.125 + 		DoRecognizeBufferL(aBuffer, EFalse, fileToRead);
   1.126 + 		}
   1.127 + 	
   1.128 + 	CleanupStack::PopAndDestroy(2); //fileToRead, fs		
   1.129 + 	
   1.130 + 	}
   1.131 +
   1.132 +void CApaCertificateRecognizer::ReadFileAndRecognizeL(RFile& aFileToRead)
   1.133 + 	{
   1.134 + 	TInt size=PreferredBufSize();
   1.135 + 	HBufC8* memForFile = HBufC8::NewLC(size);
   1.136 + 	TPtr8 preferredBuffer(memForFile->Des());
   1.137 + 	User::LeaveIfError(aFileToRead.Read(preferredBuffer, size));
   1.138 + 	DoRecognizeBufferL(preferredBuffer, ETrue, aFileToRead);		
   1.139 + 	CleanupStack::PopAndDestroy(memForFile); //memForFile	
   1.140 + 	}
   1.141 + 
   1.142 +void CApaCertificateRecognizer::DoRecognizeBufferL(const TDesC8& aBuffer,  TBool aIsFile, RFile& aFile)
   1.143 +	{
   1.144 +	// Ensure length is sufficient for checking type
   1.145 +   	if ( aBuffer.Size() >= 1 )
   1.146 +   		{
   1.147 +   		// First byte of X.509 certificate is an ANS.1 SEQUENCE tag
   1.148 +   		if ( aBuffer[0] == KASN1SequenceTagValue )
   1.149 +   			{
   1.150 +  			RecognizeX509CertL( aBuffer, aIsFile, aFile);
   1.151 +   			}
   1.152 +   		// First byte of WTLS certificate is version == 1
   1.153 +   		else if ( aBuffer[0] == KWTLSCertificateVersionValue )
   1.154 +   			{
   1.155 +  			RecognizeWTLSCertOrCertResponse( aBuffer, aIsFile, aFile);
   1.156 +   			}
   1.157 +  		
   1.158 + 		}						
   1.159 +   	}
   1.160 +
   1.161 +void CApaCertificateRecognizer::RecognizeX509CertL( const TDesC8& aBuffer,  TBool aIsFile, RFile& aFile )
   1.162 +		{
   1.163 +
   1.164 +	//Basic check if this is a X509 certificate
   1.165 +	TBool isCertV1orV2(EFalse);
   1.166 +	TInt bufferSize = aBuffer.Size();
   1.167 +	if ( bufferSize < KX509MinBufferLength )
   1.168 +		{
   1.169 +		return;
   1.170 +		}
   1.171 +	TInt index = 1;
   1.172 +	// Check first sequence length byte and skip over the length value bytes
   1.173 +	if ( aBuffer[index] == KASN1SequenceTwoBytesLength )
   1.174 +		{
   1.175 +		index += 3;
   1.176 +		}
   1.177 +	else if ( aBuffer[index] == KASN1SequenceThreeBytesLength )
   1.178 +		{
   1.179 +		index += 4;
   1.180 +		}
   1.181 +	else
   1.182 +		{
   1.183 +		return;
   1.184 +		}
   1.185 +	// Check next byte that is another sequence start
   1.186 +	if ( aBuffer[index] != KASN1SequenceTagValue )
   1.187 +		{
   1.188 +		return;
   1.189 +		}
   1.190 +	++index;
   1.191 +	// Check second sequence length byte and skip over the length value bytes
   1.192 +	if ( aBuffer[index] == KASN1SequenceTwoBytesLength )
   1.193 +		{
   1.194 +		index += 3;
   1.195 +		}
   1.196 +	else if ( aBuffer[index] == KASN1SequenceThreeBytesLength )
   1.197 +		{
   1.198 +		index += 4;
   1.199 +		}
   1.200 +	else
   1.201 +		{
   1.202 +		return;
   1.203 +		}
   1.204 +	// Check for VERSION field
   1.205 +	if ( aBuffer[index] == KASN1VersionWrapperTagValue )
   1.206 +		{
   1.207 +		++index;
   1.208 +		if ( aBuffer[index] != KASN1VersionWrapperLengthValue )
   1.209 +			{
   1.210 +			return;
   1.211 +			}
   1.212 +		++index;
   1.213 +		if ( aBuffer[index] != EASN1Integer )
   1.214 +			{
   1.215 +			return;
   1.216 +			}
   1.217 +		++index;
   1.218 +		if ( aBuffer[index] != KASN1VersionLengthValue )
   1.219 +			{
   1.220 +			return;
   1.221 +			}
   1.222 +		++index;
   1.223 +
   1.224 +		// The cert is X509 v1 or v2
   1.225 + 		if (aBuffer[index] == EX509VersionValue1 ||
   1.226 + 		    aBuffer[index] == EX509VersionValue2)
   1.227 +		    {
   1.228 +		    isCertV1orV2=ETrue;
   1.229 +		    }
   1.230 +		else
   1.231 +	 	   // The cert is neither X509 v1 nor v2
   1.232 + 		    {
   1.233 + 		   // The cert is not v3 as well 
   1.234 + 		   if (aBuffer[index] != EX509VersionValue3)
   1.235 + 			{
   1.236 + 			return;	
   1.237 +			}
   1.238 + 		    }		
   1.239 +
   1.240 +		++index;
   1.241 +		}
   1.242 +	else
   1.243 +		{
   1.244 +		isCertV1orV2=ETrue;	
   1.245 +		}
   1.246 +	// Check for SerialNumber field
   1.247 +	if ( aBuffer[index] != EASN1Integer )
   1.248 +		{
   1.249 +		return;
   1.250 +		}
   1.251 +	++index;
   1.252 +	TInt serialNumberSize = aBuffer[index];
   1.253 +	++index;
   1.254 +	index += serialNumberSize;
   1.255 +	// 1 is added for the next increments of index
   1.256 +	if((index + 1) >= bufferSize)
   1.257 +		{
   1.258 +		return;
   1.259 +		}
   1.260 +	// Check for SIGNATURE field
   1.261 +	if ( aBuffer[index] != KASN1SequenceTagValue )
   1.262 +		{
   1.263 +		return;
   1.264 +		}
   1.265 +	++index;
   1.266 +	TInt signatureSize = aBuffer[index];
   1.267 +	++index;
   1.268 +	index += signatureSize;
   1.269 +	if(index >= bufferSize)
   1.270 +		{
   1.271 +		return;
   1.272 +		}
   1.273 +	 	
   1.274 + 	// if the certificate is passed by the buffer, but not file name 
   1.275 + 	if (!aIsFile)	
   1.276 + 		{
   1.277 + 		// Check only the starting TAG byte of the NAME field
   1.278 + 		if ( aBuffer[index] == KASN1SequenceTagValue )
   1.279 + 			{
   1.280 + 			iDataType = TDataType( KDataTypeX509_CA_Certificate );
   1.281 + 			iConfidence = EProbable;
   1.282 + 			}			
   1.283 + 		}
   1.284 + 	else
   1.285 + 		// if the certificate is passed by file name
   1.286 +		{
   1.287 +		if (!isCertV1orV2) // x509 V3 certificate
   1.288 + 			{ 
   1.289 + 			//Get the file size
   1.290 + 			TInt size;
   1.291 + 			User::LeaveIfError(aFile.Size(size));
   1.292 + 			HBufC8* memForFile = HBufC8::NewLC(size);
   1.293 + 			TPtr8 fileContent(memForFile->Des());
   1.294 + 			TInt pos=0;
   1.295 + 			aFile.Seek(ESeekStart, pos);
   1.296 + 			User::LeaveIfError(aFile.Read(fileContent, size));
   1.297 + 			RecognizeWholeX509CertificateL(fileContent);
   1.298 + 			CleanupStack::PopAndDestroy(memForFile);//memForFile
   1.299 +			}									
   1.300 + 		else  // x509 V1 or V2 certificate
   1.301 + 			{ 
   1.302 + 			iDataType = TDataType( KDataTypeX509_CA_Certificate );
   1.303 + 			iConfidence = EProbable;				
   1.304 + 			}
   1.305 +	
   1.306 +		}
   1.307 +	}
   1.308 +
   1.309 +void CApaCertificateRecognizer::RecognizeWholeX509CertificateL(const TDesC8& aBuffer)
   1.310 + 	{
   1.311 + 	CX509Certificate* cert = CX509Certificate::NewLC(aBuffer);
   1.312 + 	if (cert)
   1.313 + 		{
   1.314 + 		const CX509CertExtension* certExt = cert->Extension(KBasicConstraints);
   1.315 + 		if (certExt)
   1.316 + 			{
   1.317 + 			CX509BasicConstraintsExt* basic = CX509BasicConstraintsExt::NewLC(certExt->Data());
   1.318 + 			if (basic->IsCA())
   1.319 + 				{
   1.320 + 				iDataType = TDataType( KDataTypeX509_CA_Certificate );
   1.321 + 				iConfidence = EProbable;					
   1.322 + 				}
   1.323 + 			else
   1.324 + 				{
   1.325 + 				iDataType = TDataType( KDataTypeX509_USER_Certificate );
   1.326 + 				iConfidence = EProbable;										
   1.327 + 				}
   1.328 + 			CleanupStack::PopAndDestroy(basic); //basic				
   1.329 +			}
   1.330 + 		else
   1.331 + 			{
   1.332 + 			iDataType = TDataType( KDataTypeX509_USER_Certificate );
   1.333 + 			iConfidence = EProbable;														
   1.334 + 			}
   1.335 + 		}
   1.336 + 	CleanupStack::PopAndDestroy(cert); //cert
   1.337 + 	}
   1.338 +
   1.339 +
   1.340 +
   1.341 +void CApaCertificateRecognizer::RecognizeWTLSCertOrCertResponse( const TDesC8& aBuffer, TBool /*aIsFile*/, RFile& /*aFile*/ )
   1.342 +	{
   1.343 +	if ( aBuffer.Size() >= 3 )
   1.344 +		{
   1.345 +		// Check next byte is signature algorithm value from 0 - 2
   1.346 +		if ( aBuffer[1] == 0x00 || aBuffer[1] == 0x01 || aBuffer[1] == 0x02 )
   1.347 +			{
   1.348 +			// Check Identifier Type for Issuer Identifier
   1.349 +			if ( aBuffer[2] == 0x01 )
   1.350 +				{
   1.351 +				iDataType = TDataType( KDataTypeWAP_WTLS_CA_Certificate );
   1.352 +				}
   1.353 +			else
   1.354 +				{
   1.355 +				iDataType = TDataType( KDataTypeWAPCertificateResponse );
   1.356 +				}
   1.357 +			iConfidence = EPossible;
   1.358 +			}
   1.359 +		}
   1.360 +	}
   1.361 +
   1.362 +CApaDataRecognizerType* CApaCertificateRecognizer::CreateRecognizerL()
   1.363 +	{
   1.364 +	return new (ELeave) CApaCertificateRecognizer();
   1.365 +	}
   1.366 +
   1.367 +const TImplementationProxy ImplementationTable[] = 
   1.368 +	{
   1.369 +		IMPLEMENTATION_PROXY_ENTRY(0x102034A2, CApaCertificateRecognizer::CreateRecognizerL)
   1.370 +	};
   1.371 +
   1.372 +EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
   1.373 +	{
   1.374 +	aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
   1.375 +	return ImplementationTable;
   1.376 +	}	
   1.377 +