vpnengine/ikecert/src/ikecert.cpp
changeset 0 33413c0669b9
equal deleted inserted replaced
-1:000000000000 0:33413c0669b9
       
     1 /*
       
     2 * Copyright (c) 2007-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 "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:   General utility methods for certificate handling
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include <x509cert.h>
       
    21 
       
    22 #include "ikecert.h"
       
    23 #include "ikev1pkiservice.h"
       
    24 #include "ikev2const.h"
       
    25 #include "ikecaelem.h"
       
    26 #include "ikecertconst.h"
       
    27 
       
    28 
       
    29 const TUint8 Pkcs1v15Sha1Header[15] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14};
       
    30 
       
    31 
       
    32 TUint8* IkeCert::BERGetLengthL(TUint8* aP, TInt &aLen)
       
    33 {
       
    34     ASSERT(aP);
       
    35 	aP++;  // skip tag
       
    36 	if (*aP <= 127) 
       
    37 	{   
       
    38 		aLen = *aP;
       
    39 		aP++;
       
    40 	}
       
    41 	else if (*aP == 0x81)
       
    42 	{
       
    43 		aP++;
       
    44 		aLen = *aP;
       
    45 		aP++;
       
    46 	}
       
    47 	else if (*aP == 0x82)
       
    48 	{
       
    49 		aP++;
       
    50 		aLen = *aP;
       
    51 		aP++;
       
    52 		aLen *= 256;
       
    53 		aLen += *aP;
       
    54 		aP++;
       
    55 	}
       
    56 	else {
       
    57 		User::Leave(KErrGeneral);
       
    58 	}
       
    59 	return aP;
       
    60 }
       
    61 
       
    62 
       
    63 EXPORT_C HBufC8* IkeCert::GetCertificateFieldDERL(const CX509Certificate* aCert, TInt aField)
       
    64 {
       
    65 	if ( !aCert )
       
    66 	   return NULL;	
       
    67 	const TPtrC8 SignedData = aCert->SignedDataL();
       
    68 	if ( SignedData.Length() == 0 )
       
    69 	   return NULL;
       
    70 	TUint8* Ptr = (TUint8*)SignedData.Ptr();
       
    71 	TUint8* FieldPtr;
       
    72 	HBufC8* FieldBfr = NULL;
       
    73 	TInt length = 0;	
       
    74 	 // begin sequence
       
    75 	Ptr = IkeCert::BERGetLengthL(Ptr, length);
       
    76 	// context specific a0 03
       
    77 	if (*Ptr==0xa0)
       
    78 		Ptr += 2; 
       
    79 	// version
       
    80 	if (*Ptr==2)
       
    81 	{
       
    82 		Ptr = IkeCert::BERGetLengthL(Ptr, length);
       
    83 		Ptr += length;
       
    84 	}
       
    85 	// seq number
       
    86 	if (*Ptr==2)
       
    87 	{
       
    88 		Ptr = IkeCert::BERGetLengthL(Ptr, length);
       
    89 		Ptr += length;
       
    90 	}
       
    91 	// sign algorithm
       
    92 	Ptr = IkeCert::BERGetLengthL(Ptr, length);
       
    93 	Ptr += length;
       
    94 	// issuer name
       
    95 	FieldPtr = Ptr;
       
    96 	Ptr = IkeCert::BERGetLengthL(Ptr, length);
       
    97 	Ptr += length;
       
    98 	if ( aField == KIssuerName )
       
    99 	    {   
       
   100 	       FieldBfr = HBufC8::NewL(Ptr - FieldPtr);
       
   101 	       FieldBfr->Des().Copy(FieldPtr, (Ptr - FieldPtr));
       
   102 	    }
       
   103 	// validity period
       
   104 	Ptr = IkeCert::BERGetLengthL(Ptr, length);
       
   105 	Ptr += length;
       
   106 	// subject name
       
   107 	FieldPtr = Ptr;
       
   108 	Ptr = IkeCert::BERGetLengthL(Ptr, length);
       
   109 	Ptr += length;
       
   110 	if ( aField == KSubjectName )
       
   111 	{	
       
   112 	   FieldBfr = HBufC8::NewL(Ptr - FieldPtr);
       
   113 	   FieldBfr->Des().Copy(FieldPtr, (Ptr - FieldPtr));
       
   114 	}
       
   115 	// public key info	
       
   116 	FieldPtr = Ptr;
       
   117 	Ptr = IkeCert::BERGetLengthL(Ptr, length);
       
   118 	Ptr += length;
       
   119 	if ( aField == KPublicKeyInfo )
       
   120 	{	
       
   121 		FieldBfr = HBufC8::NewL(Ptr - FieldPtr);
       
   122 		FieldBfr->Des().Copy(FieldPtr, (Ptr - FieldPtr));
       
   123 	}
       
   124 
       
   125 	return FieldBfr;
       
   126 }	
       
   127 
       
   128 
       
   129 HBufC8* IkeCert::BuildPkcs1v15HashL(const TDesC8 &aHashIn)
       
   130 {
       
   131 	//
       
   132 	// Build Pkcs1v15 format ASN1 header for specified hash.
       
   133 	// Current implementation supports only hash algorithm SHA1 so
       
   134 	// the aHashIn length data MUST be exactly the length of SHA1 hash
       
   135 	// (20 bytes) 
       
   136 	//
       
   137 	HBufC8* Pkcs1v15Hash = NULL;
       
   138 	
       
   139 	ASSERT( aHashIn.Length() == 20 );
       
   140 	
       
   141    Pkcs1v15Hash = HBufC8::NewL(20 + sizeof(Pkcs1v15Sha1Header));
       
   142    if ( Pkcs1v15Hash )
       
   143    {
       
   144        Pkcs1v15Hash->Des().Copy((TUint8*)Pkcs1v15Sha1Header, sizeof(Pkcs1v15Sha1Header));
       
   145        Pkcs1v15Hash->Des().Append(aHashIn);
       
   146    }	   
       
   147 	return Pkcs1v15Hash;
       
   148 }
       
   149 
       
   150 
       
   151 EXPORT_C HBufC8* IkeCert::GetCertificateFieldDERL(HBufC8* aCertBfr, TInt aField)
       
   152 {
       
   153 	if ( !aCertBfr )
       
   154 	   return NULL;	
       
   155 	CX509Certificate* Cert = CX509Certificate::NewL(*aCertBfr);
       
   156 	CleanupStack::PushL(Cert);	
       
   157     HBufC8* Field  = IkeCert::GetCertificateFieldDERL(Cert, aField);
       
   158 	CleanupStack::PopAndDestroy(Cert); 
       
   159 	return Field;
       
   160 }
       
   161 
       
   162 
       
   163 TBool IkeCert::AltNameExistsL(const CX509Certificate *aX509Cert, const TDesC8 &aId)
       
   164 {
       
   165     ASSERT(aX509Cert);
       
   166 	const CX509CertExtension *AltNameExt = aX509Cert->Extension(KSubjectAltName);
       
   167 	CX509GeneralName *NameId = CX509GeneralName::NewLC(aId);
       
   168 	TBool found = EFalse;
       
   169 	if (AltNameExt)
       
   170 	{
       
   171 		CX509AltNameExt* AltExt = CX509AltNameExt::NewLC(AltNameExt->Data());
       
   172 		const CArrayPtrFlat<CX509GeneralName>&Names = AltExt->AltName();
       
   173 		TInt Count = Names.Count();
       
   174 		for (TInt i = 0; i < Count; i++)
       
   175 		{
       
   176 			const CX509GeneralName *Name = Names.At(i);
       
   177 			if  (NameId->Tag()  == Name->Tag() &&
       
   178 				 NameId->Data() == Name->Data())
       
   179 			{
       
   180 				found = ETrue;
       
   181 				break;
       
   182 			}
       
   183 		}
       
   184 		CleanupStack::PopAndDestroy(AltExt);
       
   185 	}
       
   186 	CleanupStack::PopAndDestroy(NameId);
       
   187 	return found;
       
   188 }
       
   189 
       
   190 
       
   191 EXPORT_C HBufC8* IkeCert::GetSubjectAltNameDataL(const CX509Certificate* aX509Cert, TUint8 aIkeIdType)
       
   192 {
       
   193     ASSERT(aX509Cert);
       
   194 	HBufC8* Identity = NULL;
       
   195 	const CX509CertExtension* AltNameExt = aX509Cert->Extension(KSubjectAltName);
       
   196 
       
   197 	if ( AltNameExt )
       
   198 	{
       
   199 		TGNType SubjAltNameType;
       
   200 		switch ( aIkeIdType )
       
   201 		{
       
   202 			case ID_IPV4_ADDR:
       
   203 				SubjAltNameType = EX509IPAddress;
       
   204 				break;
       
   205 			case ID_FQDN:
       
   206 				SubjAltNameType = EX509DNSName;
       
   207 				break;
       
   208 			case ID_RFC822_ADDR:
       
   209 				SubjAltNameType = EX509RFC822Name;
       
   210 				break;
       
   211 			case ID_IPV6_ADDR:
       
   212 				SubjAltNameType = EX509IPAddress;
       
   213 				break;
       
   214 			default:
       
   215 				SubjAltNameType = EX509RFC822Name;
       
   216 				break;
       
   217 		}   
       
   218 		CX509AltNameExt* AltExt = CX509AltNameExt::NewLC(AltNameExt->Data());
       
   219 		const CArrayPtrFlat<CX509GeneralName>&Names = AltExt->AltName();
       
   220 		TInt count = Names.Count();
       
   221 		for (TInt i = 0; i < count; i++)
       
   222 		{
       
   223 			const CX509GeneralName *Name = Names.At(i);
       
   224 			if  ( Name->Tag() == SubjAltNameType )
       
   225 			{
       
   226 				//
       
   227 				// Allocate buffer and  Copy subject alt name data to it (type tag and length is not copied !)
       
   228 				//
       
   229 				Identity = HBufC8::NewL(Name->Data().Length() - 2);
       
   230 				Identity->Des().Copy(((TUint8*)(Name->Data().Ptr()) + 2), (Name->Data().Length() - 2));
       
   231 				break;
       
   232 			}
       
   233 		}
       
   234 		CleanupStack::PopAndDestroy(AltExt); 
       
   235 
       
   236 	}   
       
   237 	return Identity;
       
   238 }
       
   239 
       
   240 
       
   241 TInt IkeCert::CheckValidityPeriod(const CX509Certificate& aCert, TInt aWarningMargin, TInt aErrorMargin )
       
   242 {
       
   243 	TInt  Status = KErrNone;
       
   244 	TTime current;
       
   245 	current.UniversalTime();
       
   246 	TTimeIntervalSeconds ErrorMargin(aErrorMargin); 
       
   247 	TTime StartTime  = aCert.ValidityPeriod().Start();
       
   248 	TTime FinishTime = aCert.ValidityPeriod().Finish();
       
   249 	if ( (current + ErrorMargin) < StartTime )
       
   250 	{
       
   251 		Status = KCertVerifyErrNotValidYet;
       
   252 	}
       
   253 	else
       
   254 	{
       
   255 		if (current > (FinishTime + ErrorMargin) )
       
   256 		{
       
   257 			Status = KCertVerifyErrExpired;
       
   258 		}
       
   259 		else
       
   260 		{
       
   261 		  //
       
   262 		  // If a warning margin defined, check is the certificate within that
       
   263 		  //
       
   264 			if ( aWarningMargin )
       
   265 			{
       
   266 				TTimeIntervalSeconds WarningMargin(aWarningMargin);
       
   267 				if ( (current + WarningMargin) > (FinishTime + ErrorMargin) ) {
       
   268 					Status = KCertVerifyWithinMargin;             
       
   269 				}   
       
   270 			}   
       
   271 		}       
       
   272 	}
       
   273 
       
   274 	return Status;
       
   275 }   
       
   276 
       
   277 //
       
   278 // Verify certificate extensions
       
   279 // 
       
   280 TInt IkeCert::VerifyCertExtensionsL(const CX509Certificate& aX509Cert)
       
   281 {
       
   282 	TInt Status = KErrNone;
       
   283 	const CArrayPtrFlat<CX509CertExtension>& CertExtensions = aX509Cert.Extensions();	
       
   284 	CX509CertExtension* Extension;  
       
   285 	TInt Count = CertExtensions.Count();
       
   286 	TInt i     = 0;
       
   287 
       
   288 	while ( i < Count )
       
   289 	{
       
   290 		Extension = CertExtensions.At(i);
       
   291 		if ( Extension->Id() == KKeyUsage )
       
   292 		{
       
   293 		   //
       
   294 		   // KeyUsage extension MUST have either digitalSignature or
       
   295 		   // nonRepudiation bit set
       
   296 		   //
       
   297 			CX509KeyUsageExt* KeyUsage = CX509KeyUsageExt::NewL(Extension->Data());
       
   298 			if ( !KeyUsage->IsSet(EX509DigitalSignature) && !KeyUsage->IsSet(EX509NonRepudiation) )
       
   299 			{
       
   300 				delete KeyUsage;  
       
   301 				Status = KCertVerifyKeyUsageErr;
       
   302 				break;
       
   303 			}
       
   304 			else delete KeyUsage;
       
   305 		}
       
   306 		else if ( Extension->Id() == KBasicConstraints )
       
   307 		{
       
   308 		   //
       
   309 		   // BasicConstraints extension MUST NOT have CA indicator
       
   310 		   //
       
   311 			CX509BasicConstraintsExt* BasicConstraints = CX509BasicConstraintsExt::NewL(Extension->Data());
       
   312 			if ( BasicConstraints->IsCA() )
       
   313 			{
       
   314 				delete BasicConstraints; 
       
   315 				Status = KCertVerifyCACertificate;
       
   316 				break;
       
   317 			}
       
   318 			else delete BasicConstraints;
       
   319 		}	
       
   320 		else if ( Extension->Id() != KSubjectAltName && Extension->Critical() )				
       
   321 		{
       
   322 		   //
       
   323 		   // Unsupported critical section ==> Certificate NOT accepted 
       
   324 		   //
       
   325 			Status = KCertVerifyCriticalExt;
       
   326 			break;
       
   327 		}   	
       
   328 
       
   329 		i++;
       
   330 	}
       
   331 
       
   332 	return Status;
       
   333 }
       
   334           
       
   335     
       
   336 void IkeCert::CleanupSequence(TAny* aArray)
       
   337     {
       
   338     ASSERT(aArray);
       
   339 	CArrayPtrFlat<TASN1DecGeneric>* array = reinterpret_cast<CArrayPtrFlat<TASN1DecGeneric>*>(aArray);
       
   340     ASSERT(array);
       
   341 	array->ResetAndDestroy();
       
   342 	delete array;
       
   343     }
       
   344