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 +