vpnengine/vpnmanager/src/pkiutil.cpp
changeset 0 33413c0669b9
child 25 735de8341ce4
equal deleted inserted replaced
-1:000000000000 0:33413c0669b9
       
     1 /*
       
     2 * Copyright (c) 2003-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: 
       
    15 * Provides static PKI-related helper functions 
       
    16 * (such as building Distinguished Names)
       
    17 *
       
    18 */
       
    19 
       
    20 #include <x500dn.h>
       
    21 #include <x509cert.h>
       
    22 #include <x520ava.h>
       
    23 #include <utf.h>
       
    24 #include <x509keys.h>
       
    25 
       
    26 #include "pkiutil.h"
       
    27 #include "pkiserviceapi.h"
       
    28 #include "pkcs10.h"
       
    29 #include "ikepolparser.h"
       
    30 
       
    31 
       
    32 HBufC* PkiUtil::CertSubjectNameL(const TDesC8& aCertData)
       
    33     {
       
    34     CX509Certificate* certificate = CX509Certificate::NewL(aCertData);
       
    35     CleanupStack::PushL(certificate);
       
    36 
       
    37     CX500DistinguishedName* subjectDn;
       
    38     subjectDn = CX500DistinguishedName::NewL(certificate->SubjectName());
       
    39     CleanupStack::PushL(subjectDn);
       
    40 
       
    41     HBufC* certDn = CertDnL(*subjectDn);
       
    42 
       
    43     CleanupStack::PopAndDestroy(2); // subjectDn, certificate
       
    44 
       
    45     return certDn;
       
    46     }
       
    47 
       
    48 HBufC* PkiUtil::CertIssuerNameL(const TDesC8& aCertData)
       
    49     {
       
    50     CX509Certificate* certificate = CX509Certificate::NewL(aCertData);
       
    51     CleanupStack::PushL(certificate);
       
    52 
       
    53     CX500DistinguishedName* issuerDn;
       
    54     issuerDn = CX500DistinguishedName::NewL(certificate->IssuerName());
       
    55     CleanupStack::PushL(issuerDn);
       
    56 
       
    57     HBufC* certDn = CertDnL(*issuerDn);
       
    58 
       
    59     CleanupStack::PopAndDestroy(2); // issuerDn, certificate
       
    60 
       
    61     return certDn;
       
    62     }
       
    63 
       
    64 HBufC* PkiUtil::CertDnL(const CX500DistinguishedName& aName)
       
    65     {
       
    66     TInt count = aName.Count();
       
    67     HBufC* certDn = HBufC::NewL(KCertDnSizeIncrement);
       
    68     CleanupStack::PushL(certDn);
       
    69 
       
    70     for (TInt i = 0; i < count; i++)
       
    71         {
       
    72         const CX520AttributeTypeAndValue& attribute = aName.Element(i);
       
    73 
       
    74         // Unsupported attribute is not appended (KErrNotSupported error)
       
    75         TRAPD( err, AppendAttributeL(certDn, attribute) );
       
    76         if ( err != KErrNotSupported )
       
    77             {
       
    78             User::LeaveIfError( err );
       
    79             }
       
    80         }
       
    81 
       
    82     CleanupStack::Pop(); // certDn
       
    83 
       
    84     return certDn;
       
    85     }
       
    86 
       
    87 TInt PkiUtil::CertKeySizeL(const TDesC8& aCertData)
       
    88     {
       
    89     TInt keySize = 0;
       
    90 
       
    91     CX509Certificate* certificate = CX509Certificate::NewLC(aCertData);
       
    92     const CSubjectPublicKeyInfo& publicKeyInfo = certificate->PublicKey();
       
    93     const TPtrC8 keyData = publicKeyInfo.KeyData();
       
    94 
       
    95     TX509KeyFactory keyFactory;
       
    96 
       
    97     switch(publicKeyInfo.AlgorithmId())
       
    98         {
       
    99         case ERSA:
       
   100             {
       
   101             const CRSAPublicKey* keyRSA = keyFactory.RSAPublicKeyL(keyData);
       
   102             const TInteger&  n = keyRSA->N();
       
   103             keySize = n.BitCount();
       
   104             delete keyRSA;
       
   105             }
       
   106             break;
       
   107         case EDSA:
       
   108             {
       
   109             TPtrC8 params = publicKeyInfo.EncodedParams();
       
   110 
       
   111             const CDSAPublicKey* keyDSA =
       
   112                 keyFactory.DSAPublicKeyL(params, keyData);
       
   113 
       
   114             const TInteger& y = keyDSA->Y();
       
   115             keySize = y.BitCount();
       
   116             delete keyDSA;
       
   117             }
       
   118             break;
       
   119         default:
       
   120             User::Leave(KErrNotSupported);
       
   121             break;
       
   122         }
       
   123 
       
   124     CleanupStack::PopAndDestroy(certificate);
       
   125 
       
   126     return keySize;
       
   127     }
       
   128 
       
   129 
       
   130 void PkiUtil::AppendAttributeL(HBufC*& aBuf, const CX520AttributeTypeAndValue& aAttribute)
       
   131     {
       
   132     HBufC* attrName = AttributeTypeToNameL(aAttribute.Type());
       
   133     CleanupStack::PushL(attrName);
       
   134 
       
   135     HBufC* attrValue = aAttribute.ValueL();
       
   136     CleanupStack::PushL(attrValue);
       
   137 
       
   138     if ( aBuf->Length() )
       
   139         {
       
   140         // Append comma if not first attribute
       
   141         SmartAppendL(aBuf, KComma);
       
   142         }
       
   143 
       
   144     SmartAppendL(aBuf, attrName->Des());
       
   145     SmartAppendL(aBuf, KEquals);
       
   146     SmartAppendL(aBuf, attrValue->Des());
       
   147 
       
   148     CleanupStack::PopAndDestroy(2); // attrValue, attrName
       
   149     }
       
   150 
       
   151 /*
       
   152    RFC 2253 (Lightweight Directory Access Protocol (v3):
       
   153    UTF-8 String Representation of Distinguished Names):
       
   154 
       
   155    "If the AttributeType is in a published table of attribute types
       
   156    associated with LDAP [4], then the type name string from that table
       
   157    is used, otherwise it is encoded as the dotted-decimal encoding of
       
   158    the AttributeType's OBJECT IDENTIFIER."
       
   159 
       
   160    RFC 2256 (A Summary of the X.500(96) User Schema for use with
       
   161    LDAPv3):
       
   162 
       
   163    "This document provides an overview of the attribute types and object
       
   164    classes defined by the ISO and ITU-T committees in the X.500
       
   165    documents, in particular those intended for use by directory
       
   166    clients."
       
   167 
       
   168    In essence, RFC 2256 lists the most common attribute types and their
       
   169    names.
       
   170 
       
   171    We choose to provide "user-friendly" name mapping for the following
       
   172    attribúte types:
       
   173    - countryName
       
   174    - organizationName
       
   175    - organizationalUnitName
       
   176    - localityName
       
   177    - stateOrProvinceName
       
   178    - commonName
       
   179 
       
   180    For other attribute types, we use a string representation of the OID
       
   181    as the attribute name.
       
   182 */
       
   183 
       
   184 HBufC* PkiUtil::AttributeTypeToNameL(const TDesC &aType)
       
   185     {
       
   186     HBufC* name;
       
   187 
       
   188     if (aType.Compare(KX520CountryName) == 0)
       
   189         {
       
   190         name = KC().AllocL();
       
   191         }
       
   192     else if (aType.Compare(KX520OrganizationName) == 0)
       
   193         {
       
   194         name = KO().AllocL();
       
   195         }
       
   196     else if (aType.Compare(KX520OrganizationalUnitName) == 0)
       
   197         {
       
   198         name = KOU().AllocL();
       
   199         }
       
   200     else if (aType.Compare(KX520LocalityName) == 0)
       
   201         {
       
   202         name = KL().AllocL();
       
   203         }
       
   204     else if (aType.Compare(KX520StateOrProvinceName) == 0)
       
   205         {
       
   206         name = KST().AllocL();
       
   207         }
       
   208     else if (aType.Compare(KX520CommonName) == 0)
       
   209         {
       
   210         name = KCN().AllocL();
       
   211         }
       
   212     else
       
   213         {
       
   214         // Use the dotted-decimal encoding
       
   215         // of the OID as the attribute name
       
   216         name = aType.AllocL();
       
   217         }
       
   218 
       
   219     return name;
       
   220     }
       
   221 
       
   222 void PkiUtil::SmartAppendL(HBufC*& aBuf, const TDesC& aText)
       
   223     {
       
   224     // Make sure that we have enough space for the new text
       
   225 
       
   226     TInt spaceLeft = aBuf->Des().MaxLength() - aBuf->Des().Length();
       
   227 
       
   228     if (aText.Length() > spaceLeft)
       
   229         {
       
   230         // Allocate enough space for the new text + some additional
       
   231         // free space so that allocations are not too frequent
       
   232 
       
   233         TInt newMaxLength = aBuf->Des().MaxLength() + aText.Length() + KCertDnSizeIncrement;
       
   234 
       
   235         aBuf = aBuf->ReAllocL(newMaxLength);
       
   236         }
       
   237 
       
   238     aBuf->Des().Append(aText);
       
   239     }
       
   240 
       
   241 TCertStatus PkiUtil::CertStatusL(RPKIServiceAPI& aPkiService, const TDesC8& aTrustedCaDn,
       
   242                                  const TDesC8& aSubjectDnSuffix, const TDesC8& aRfc822NameFqdn,
       
   243                                  TUint aPrivKeyLength, TInt aCertRenewalThreshold)
       
   244     {
       
   245     // Try to find a user certificate with the
       
   246     // desired properties from the PKI store
       
   247 
       
   248     TAny* opContext;
       
   249     TRequestStatus status;
       
   250     TCertStatus certStatus;
       
   251 
       
   252     HBufC8* certData = HBufC8::NewL(KExpectedMaxCertSize);
       
   253     HBufC8* subjectNameString;
       
   254     _LIT8(KEmptyString, "");
       
   255     CleanupStack::PushL(certData);
       
   256 
       
   257     TPtr8 certDataPtr = certData->Des();
       
   258 
       
   259     aPkiService.ReadCertificateL(aTrustedCaDn, aSubjectDnSuffix, aRfc822NameFqdn, EPKIUserCertificate,
       
   260                                  aPrivKeyLength, EPKIRSA, certDataPtr,
       
   261                                  &opContext, status);
       
   262 
       
   263     User::WaitForRequest(status);
       
   264 
       
   265     aPkiService.Finalize(opContext);
       
   266 
       
   267     if (status.Int() == KPKIErrBufferTooShort)
       
   268         {
       
   269         TInt realCertSize;
       
   270         aPkiService.GetRequiredBufferSize(realCertSize);
       
   271 
       
   272         CleanupStack::PopAndDestroy(); //  certData
       
   273         certData = HBufC8::NewL(realCertSize);
       
   274         CleanupStack::PushL(certData);
       
   275 
       
   276         certDataPtr = certData->Des();
       
   277         aPkiService.ReadCertificateL(aTrustedCaDn, aSubjectDnSuffix, aRfc822NameFqdn, EPKIUserCertificate,
       
   278                                      aPrivKeyLength, EPKIRSA, certDataPtr,
       
   279                                      &opContext, status);
       
   280 
       
   281         User::WaitForRequest(status);
       
   282 
       
   283         aPkiService.Finalize(opContext);
       
   284         }
       
   285 
       
   286 
       
   287     // Make sure that the cert, if found, is valid
       
   288     if (status.Int() == KErrNone)
       
   289         {
       
   290         certStatus = PkiUtil::CertStatusL(*certData, aCertRenewalThreshold);
       
   291         }
       
   292     else //if not found, check wether certificate chain exists
       
   293         {
       
   294         certStatus = ECertNotFound;
       
   295         //checking if certificate chain is found
       
   296         CleanupStack::PopAndDestroy(); //  certData
       
   297         
       
   298         certData=NULL;
       
   299         certData = HBufC8::NewL(KExpectedMaxCertSize);
       
   300         CleanupStack::PushL(certData);
       
   301         
       
   302         certDataPtr = certData->Des();
       
   303         
       
   304         //user certificate
       
   305         aPkiService.ReadCertificateL(KEmptyString, aSubjectDnSuffix, aRfc822NameFqdn, EPKIUserCertificate,
       
   306                 aPrivKeyLength, EPKIRSA, certDataPtr,
       
   307                 &opContext, status);
       
   308         User::WaitForRequest(status);
       
   309         
       
   310         aPkiService.Finalize(opContext);
       
   311         if (status.Int() == KErrNone)
       
   312            {
       
   313             certStatus = PkiUtil::CertStatusL(*certData, aCertRenewalThreshold);
       
   314            }
       
   315         else
       
   316            {
       
   317            certStatus = ECertNotFound;
       
   318            CleanupStack::PopAndDestroy(certData);
       
   319            return certStatus;
       
   320            }
       
   321         
       
   322         //intermediate certificate level 2
       
   323         HBufC* issuerName=CertIssuerNameL(*certData);
       
   324         CleanupStack::PushL(issuerName);
       
   325         
       
   326         subjectNameString=To8BitL(*issuerName);
       
   327         
       
   328         CleanupStack::PopAndDestroy(issuerName);
       
   329         CleanupStack::PopAndDestroy(certData);
       
   330         
       
   331         certData=NULL;
       
   332         certData = HBufC8::NewL(KExpectedMaxCertSize);
       
   333         CleanupStack::PushL(certData);
       
   334         
       
   335         certDataPtr = certData->Des();
       
   336         
       
   337         CleanupStack::PushL(subjectNameString);
       
   338         aPkiService.ReadCertificateL(KEmptyString, *subjectNameString, aRfc822NameFqdn, EPKICACertificate,
       
   339                                     aPrivKeyLength, EPKIRSA, certDataPtr,
       
   340                                     &opContext, status);
       
   341         User::WaitForRequest(status);
       
   342         
       
   343         aPkiService.Finalize(opContext);
       
   344         if (status.Int() == KErrNone)
       
   345            {
       
   346             certStatus = PkiUtil::CertStatusL(*certData, aCertRenewalThreshold);
       
   347            }
       
   348         else
       
   349            {
       
   350            certStatus = ECertNotFound;
       
   351            CleanupStack::PopAndDestroy(subjectNameString);
       
   352            CleanupStack::PopAndDestroy(certData);
       
   353            return certStatus;
       
   354            }
       
   355         if ( subjectNameString->Compare(aTrustedCaDn) !=0 ) //checking if issuer is reached
       
   356             {
       
   357             //intermediate certificate level 1
       
   358             certStatus = ECertNotFound;
       
   359             CleanupStack::PopAndDestroy(subjectNameString);
       
   360             
       
   361             HBufC* issuerName=CertIssuerNameL(*certData);
       
   362             CleanupStack::PushL(issuerName);
       
   363             
       
   364             subjectNameString=To8BitL(*issuerName);
       
   365             
       
   366             CleanupStack::PopAndDestroy(issuerName);
       
   367             CleanupStack::PopAndDestroy(certData);
       
   368             
       
   369             certData = HBufC8::NewL(KExpectedMaxCertSize);
       
   370             CleanupStack::PushL(certData);
       
   371             certDataPtr = certData->Des();
       
   372             
       
   373             CleanupStack::PushL(subjectNameString);
       
   374             
       
   375             aPkiService.ReadCertificateL(KEmptyString, *subjectNameString, aRfc822NameFqdn, EPKICACertificate,
       
   376                                         aPrivKeyLength, EPKIRSA, certDataPtr,
       
   377                                         &opContext, status);
       
   378             User::WaitForRequest(status);
       
   379             
       
   380             aPkiService.Finalize(opContext);
       
   381             if (status.Int() == KErrNone)
       
   382                 {
       
   383                 certStatus = PkiUtil::CertStatusL(*certData, aCertRenewalThreshold);
       
   384                 }
       
   385             else
       
   386                 {
       
   387                 certStatus = ECertNotFound;
       
   388                 CleanupStack::PopAndDestroy(subjectNameString);
       
   389                 CleanupStack::PopAndDestroy(certData);
       
   390                 return certStatus;
       
   391                 }
       
   392             }
       
   393         if ( subjectNameString->Compare(aTrustedCaDn) !=0 )  //checking if issuer is reached
       
   394             {
       
   395              //CA certificate
       
   396              certStatus = ECertNotFound;
       
   397              CleanupStack::PopAndDestroy(subjectNameString);
       
   398                         
       
   399              HBufC* issuerName=CertIssuerNameL(*certData);
       
   400              CleanupStack::PushL(issuerName);
       
   401                         
       
   402              subjectNameString=To8BitL(*issuerName);
       
   403                         
       
   404              CleanupStack::PopAndDestroy(issuerName);
       
   405              CleanupStack::PopAndDestroy(certData);
       
   406                         
       
   407              certData = HBufC8::NewL(KExpectedMaxCertSize);
       
   408              CleanupStack::PushL(certData);
       
   409              certDataPtr = certData->Des();
       
   410                         
       
   411              CleanupStack::PushL(subjectNameString);
       
   412                         
       
   413              aPkiService.ReadCertificateL(KEmptyString, *subjectNameString, aRfc822NameFqdn, EPKICACertificate,
       
   414                                           aPrivKeyLength, EPKIRSA, certDataPtr,
       
   415                                           &opContext, status);
       
   416              User::WaitForRequest(status);
       
   417                         
       
   418              aPkiService.Finalize(opContext);
       
   419              if (status.Int() == KErrNone)
       
   420                  {
       
   421                  certStatus = PkiUtil::CertStatusL(*certData, aCertRenewalThreshold);
       
   422                  }
       
   423              CleanupStack::PopAndDestroy(subjectNameString);
       
   424              }
       
   425         else
       
   426              CleanupStack::PopAndDestroy(subjectNameString);
       
   427         }
       
   428     CleanupStack::PopAndDestroy(certData);
       
   429 
       
   430     return certStatus;
       
   431     }
       
   432 
       
   433 TCertStatus PkiUtil::CertStatusL(const TDesC8& aCertData, TInt aCertRenewalThreshold)
       
   434     {
       
   435     CX509Certificate* certificate = CX509Certificate::NewL(aCertData);
       
   436     CleanupStack::PushL(certificate);
       
   437 
       
   438     TCertStatus status = CertStatusL(*certificate, aCertRenewalThreshold);
       
   439 
       
   440     CleanupStack::PopAndDestroy(certificate);
       
   441 
       
   442     return status;
       
   443     }
       
   444 
       
   445 
       
   446 TCertStatus PkiUtil::CertStatusL(const CX509Certificate& aCert, TInt aCertRenewalThreshold)
       
   447     {
       
   448 
       
   449     TTime validationTime;
       
   450     validationTime.UniversalTime();
       
   451 
       
   452     TCertStatus certStatus = ECertValid;
       
   453 
       
   454     if (aCert.ValidityPeriod().Finish() <= validationTime)
       
   455         {
       
   456         certStatus = ECertExpired;
       
   457         }
       
   458 
       
   459     if (aCert.ValidityPeriod().Start() >= validationTime)
       
   460         {
       
   461         certStatus = ECertNotValidYet;
       
   462         }
       
   463 
       
   464     // Additional validity check - if a certificate renewal threshold
       
   465     // has been specified, it can cause an otherwise valid certificate
       
   466     // to be marked as expired. This is determined as follows:
       
   467     // - Calculate the entire lifetime of the certificate (entireLifetime)
       
   468     // - Calculate the passed lifetime of the certificate (passedLifetime)
       
   469     // - Calculate thresholdLifetime as aCertRenewalTreshold % * entireLifetime
       
   470     //   (i.e. (aCertRenewalTreshold / 100) * entireLifetime
       
   471     // - If passedLifetime > thresholdLifetime --> certificate expired
       
   472 
       
   473     if (certStatus == ECertValid && aCertRenewalThreshold >= 0)
       
   474         {
       
   475         TInt64 entireLifetime = aCert.ValidityPeriod().Finish().Int64() -
       
   476                                 aCert.ValidityPeriod().Start().Int64();
       
   477 
       
   478         TInt64 passedLifetime = validationTime.Int64() -
       
   479                                 aCert.ValidityPeriod().Start().Int64();
       
   480 
       
   481         TInt64 thresholdInPercents(aCertRenewalThreshold);
       
   482         TInt64 hundred(100);
       
   483         TInt64 tresholdLifetime = (thresholdInPercents * entireLifetime) / hundred;
       
   484 
       
   485         if (passedLifetime > tresholdLifetime)
       
   486             {
       
   487             certStatus = ECertExpired;
       
   488             }
       
   489         }
       
   490 
       
   491     return certStatus;
       
   492     }
       
   493 
       
   494 
       
   495 CX509Certificate* PkiUtil::ReadCertificateLC(RPKIServiceAPI& aPkiService,
       
   496                                              const TPKIKeyIdentifier& aKeyId)
       
   497     {
       
   498 
       
   499     TAny* opContext;
       
   500     TRequestStatus status;
       
   501 
       
   502     HBufC8* certData = HBufC8::NewL(KExpectedMaxCertSize);
       
   503     CleanupStack::PushL(certData);
       
   504 
       
   505     TPtr8 certDataPtr = certData->Des();
       
   506 
       
   507     aPkiService.ReadCertificateL(aKeyId, certDataPtr,
       
   508                                  &opContext,
       
   509                                  status);
       
   510 
       
   511     User::WaitForRequest(status);
       
   512 
       
   513     aPkiService.Finalize(opContext);
       
   514 
       
   515     if (status.Int() == KPKIErrBufferTooShort)
       
   516         {
       
   517         TInt realCertSize;
       
   518         aPkiService.GetRequiredBufferSize(realCertSize);
       
   519 
       
   520         CleanupStack::PopAndDestroy(); //  certData
       
   521         certData = HBufC8::NewL(realCertSize);
       
   522         CleanupStack::PushL(certData);
       
   523 
       
   524         certDataPtr = certData->Des();
       
   525         aPkiService.ReadCertificateL(aKeyId, certDataPtr,
       
   526                                      &opContext,
       
   527                                      status);
       
   528 
       
   529         User::WaitForRequest(status);
       
   530         aPkiService.Finalize(opContext);
       
   531 
       
   532         User::LeaveIfError(status.Int());
       
   533         }
       
   534     else
       
   535         {
       
   536         User::LeaveIfError(status.Int());
       
   537         }
       
   538 
       
   539     CX509Certificate* certificate = CX509Certificate::NewL(*certData);
       
   540     CleanupStack::PopAndDestroy(certData);
       
   541     CleanupStack::PushL(certificate);
       
   542 
       
   543     return certificate;
       
   544     }
       
   545 
       
   546 
       
   547 CX509Certificate* PkiUtil::ReadCertificateLC(RPKIServiceAPI& aPkiService,
       
   548                                              const TDesC8& aTrustedAuthority,
       
   549                                              const TDesC8& aIdentitySubjectName,
       
   550                                              const TDesC8& aIdentityRfc822Name,
       
   551                                              const TPKICertificateOwnerType aOwnerType)
       
   552     {
       
   553     // Try to find a user certificate with the
       
   554     // desired properties from the PKI store
       
   555     static const TInt KUndefinedKeySize = 0;
       
   556 
       
   557     TAny* opContext;
       
   558     TRequestStatus status;
       
   559 
       
   560     HBufC8* certData = HBufC8::NewL(KExpectedMaxCertSize);
       
   561     CleanupStack::PushL(certData);
       
   562 
       
   563     TPtr8 certDataPtr = certData->Des();
       
   564 
       
   565     aPkiService.ReadCertificateL(aTrustedAuthority,
       
   566                                  aIdentitySubjectName,
       
   567                                  aIdentityRfc822Name,
       
   568                                  aOwnerType, KUndefinedKeySize,
       
   569                                  EPKIRSA, certDataPtr,
       
   570                                  &opContext,
       
   571                                  status);
       
   572 
       
   573     User::WaitForRequest(status);
       
   574 
       
   575     aPkiService.Finalize(opContext);
       
   576 
       
   577     if (status.Int() == KPKIErrBufferTooShort)
       
   578         {
       
   579         TInt realCertSize;
       
   580         aPkiService.GetRequiredBufferSize(realCertSize);
       
   581 
       
   582         CleanupStack::PopAndDestroy(); //  certData
       
   583         certData = HBufC8::NewL(realCertSize);
       
   584         CleanupStack::PushL(certData);
       
   585 
       
   586         certDataPtr = certData->Des();
       
   587         aPkiService.ReadCertificateL(aTrustedAuthority,
       
   588                                      aIdentitySubjectName,
       
   589                                      aIdentityRfc822Name,
       
   590                                      aOwnerType, KUndefinedKeySize,
       
   591                                      EPKIRSA, certDataPtr,
       
   592                                      &opContext,
       
   593                                      status);
       
   594 
       
   595         User::WaitForRequest(status);
       
   596         aPkiService.Finalize(opContext);
       
   597 
       
   598         User::LeaveIfError(status.Int());
       
   599         }
       
   600     else
       
   601         {
       
   602         User::LeaveIfError(status.Int());
       
   603         }
       
   604 
       
   605     CX509Certificate* certificate = CX509Certificate::NewL(*certData);
       
   606     CleanupStack::PopAndDestroy(certData);
       
   607     CleanupStack::PushL(certificate);
       
   608 
       
   609     return certificate;
       
   610     }
       
   611 
       
   612 
       
   613 void ResetAndDestroyCleanup(TAny* aArray)
       
   614     {
       
   615     RPointerArray<CX509Certificate>* certificateArray = (RPointerArray<CX509Certificate>*) aArray;
       
   616     certificateArray->ResetAndDestroy();
       
   617     certificateArray->Close();
       
   618     }
       
   619 
       
   620 void ResetAndDestroyPushL(RPointerArray<CX509Certificate>& aCertificateArray)
       
   621     {
       
   622     CleanupStack::PushL(TCleanupItem(ResetAndDestroyCleanup, &aCertificateArray));
       
   623     }
       
   624 
       
   625 
       
   626 RPointerArray<CX509Certificate> PkiUtil::GetCaCertListL(RPKIServiceAPI& aPkiService,
       
   627                                                         const CArrayFixFlat<TCertInfo*>& aIkeCAList)
       
   628     {
       
   629 
       
   630     __ASSERT_ALWAYS(aIkeCAList.Count() > 0, User::Invariant());
       
   631     _LIT8(KEmptyString, "");
       
   632 
       
   633     RPointerArray<CX509Certificate> certificateArray;
       
   634     ResetAndDestroyPushL(certificateArray);
       
   635 
       
   636     RArray<TUid> applUidArray;
       
   637     CleanupClosePushL(applUidArray);
       
   638 
       
   639     for (TInt i = 0; i < aIkeCAList.Count(); ++i)
       
   640         {
       
   641         const TCertInfo* certInfo = aIkeCAList[i];
       
   642         switch(certInfo->iFormat)
       
   643             {
       
   644             case CA_NAME:
       
   645                 {
       
   646                 // Reserve enough space for UTF-8
       
   647                 TInt len = 3*( certInfo->iData.Length() );
       
   648                 HBufC8* caName = HBufC8::NewLC(len);
       
   649                 TPtr8 caNamePtr(caName->Des());
       
   650 
       
   651                 if (CnvUtfConverter::ConvertFromUnicodeToUtf8(caNamePtr, certInfo->iData) != 0)
       
   652                     {
       
   653                     User::Leave(KErrCorrupt);
       
   654                     }
       
   655 
       
   656                 CX509Certificate* cert = ReadCertificateLC(aPkiService,
       
   657                                                            KEmptyString,
       
   658                                                            *caName,
       
   659                                                            KEmptyString,
       
   660                                                            EPKICACertificate);
       
   661 
       
   662                 User::LeaveIfError(certificateArray.Append(cert));
       
   663                 CleanupStack::Pop(cert);
       
   664                 CleanupStack::PopAndDestroy(caName);
       
   665                 }
       
   666                 break;
       
   667             case KEY_ID:
       
   668                 {
       
   669                 TPKIKeyIdentifier keyId(NULL);
       
   670 
       
   671                 for (TInt j = 0; j < certInfo->iData.Length(); j += 2)
       
   672                     {
       
   673                     TPtrC hexByte(certInfo->iData.Mid(j, 2));
       
   674                     TLex lex(hexByte);
       
   675                     TUint8 value;
       
   676                     User::LeaveIfError(lex.Val(value, EHex));
       
   677                     keyId.Append(&value, 1);
       
   678                     }
       
   679 
       
   680                 CX509Certificate* cert = ReadCertificateLC(aPkiService,
       
   681                                                            keyId);
       
   682                 User::LeaveIfError(certificateArray.Append(cert));
       
   683                 CleanupStack::Pop(cert);
       
   684                 }
       
   685                 break;
       
   686             case APPL_UID:
       
   687                 {
       
   688                 TLex lex(certInfo->iData);
       
   689                 TUint32 value;
       
   690                 User::LeaveIfError(lex.Val(value, EHex));
       
   691                 TUid id = { value };
       
   692                 User::LeaveIfError(applUidArray.Append(id));
       
   693                 }
       
   694                 break;
       
   695             default:
       
   696                 User::Leave(KErrArgument);
       
   697                 break;
       
   698             }
       
   699         }
       
   700 
       
   701         if (applUidArray.Count() > 0)
       
   702             {
       
   703             CArrayFix<TCertificateListEntry>* certListArray = NULL;;
       
   704             aPkiService.ListApplicableCertificatesL(applUidArray, certListArray);
       
   705 
       
   706             CleanupStack::PushL(certListArray);
       
   707             if (certListArray->Count() == 0)
       
   708                 {
       
   709                 User::Leave(KErrNotFound);
       
   710                 }
       
   711 
       
   712             for (TInt i = 0; i < certListArray->Count(); ++i)
       
   713                 {
       
   714                 TCertificateListEntry entry = (*certListArray)[i];
       
   715                 if (entry.iOwnerType == EPKICACertificate)
       
   716                     {
       
   717                     CX509Certificate* cert = ReadCertificateLC(aPkiService,
       
   718                                                                KEmptyString,
       
   719                                                                entry.iIdentitySubjectName,
       
   720                                                                KEmptyString,
       
   721                                                                EPKICACertificate);
       
   722                     User::LeaveIfError(certificateArray.Append(cert));
       
   723                     CleanupStack::Pop(cert);
       
   724                     }
       
   725                 }
       
   726             CleanupStack::PopAndDestroy(certListArray);
       
   727             }
       
   728 
       
   729         CleanupStack::PopAndDestroy(); //applUidArray
       
   730 
       
   731     CleanupStack::Pop();
       
   732     return certificateArray;
       
   733     }
       
   734 
       
   735 
       
   736 TCertStatus PkiUtil::GetValidCaCertSubjectNameListL(RPKIServiceAPI& aPkiService,
       
   737                                                    const CArrayFixFlat<TCertInfo*>& aIkeCAList,
       
   738                                                    CDesC8ArrayFlat& aCaCertNameList)
       
   739     {
       
   740 
       
   741     TCertStatus status = ECertValid;
       
   742     RPointerArray<CX509Certificate> certificateList;
       
   743     TRAPD(err, certificateList = PkiUtil::GetCaCertListL(aPkiService, aIkeCAList));
       
   744 
       
   745     switch(err)
       
   746         {
       
   747         case KErrNone:
       
   748             for (TInt i = 0; i < certificateList.Count(); ++i)
       
   749                 {
       
   750                 const CX509Certificate* cert = certificateList[i];
       
   751                 status = CertStatusL(*cert, -1);
       
   752 
       
   753                 if (status == ECertValid)
       
   754                     {
       
   755                     const CX500DistinguishedName& subjectName = cert->SubjectName();
       
   756                     HBufC* subjectNameString = PkiUtil::CertDnL(subjectName);
       
   757                     CleanupStack::PushL(subjectNameString);
       
   758 
       
   759                     // Reserve enough space for UTF-8
       
   760                     TInt len = 3*( subjectNameString->Length() );
       
   761                     HBufC8* subjectNameString8Bit = HBufC8::NewLC(len);
       
   762                     TPtr8 subjectNameString8BitPtr = subjectNameString8Bit->Des();
       
   763                     if (CnvUtfConverter::ConvertFromUnicodeToUtf8(subjectNameString8BitPtr,
       
   764                                                                   *subjectNameString) != 0)
       
   765                         {
       
   766                         User::Leave(KErrCorrupt);
       
   767                         }
       
   768                     TRAPD(err, aCaCertNameList.InsertIsqL(*subjectNameString8Bit));
       
   769 
       
   770                     CleanupStack::PopAndDestroy(subjectNameString8Bit);
       
   771                     CleanupStack::PopAndDestroy(subjectNameString);
       
   772 
       
   773                     err = (err == KErrAlreadyExists) ? KErrNone : err;
       
   774                     User::LeaveIfError(err);
       
   775                     }
       
   776                 else
       
   777                     {
       
   778                     aCaCertNameList.Reset();
       
   779                     break;
       
   780                     }
       
   781                 }
       
   782             break;
       
   783         case KErrNotFound: // Flow through
       
   784         case KErrArgument: // CA cert is not found if policys CA DATA is invalid
       
   785             status = ECertNotFound;
       
   786             break;
       
   787         default:
       
   788             certificateList.ResetAndDestroy();
       
   789             certificateList.Close();
       
   790             User::Leave(err);
       
   791         }
       
   792 
       
   793     certificateList.ResetAndDestroy();
       
   794     certificateList.Close();
       
   795 
       
   796     return status;
       
   797     }
       
   798 
       
   799 
       
   800 TCertStatus PkiUtil::CheckUserCertValidityL(RPKIServiceAPI& aPkiService,
       
   801                                             CDesC8ArrayFlat& aValidCaCertNameList,
       
   802                                             TOwnCertInfo& aOwnCert)
       
   803     {
       
   804 
       
   805     static const TInt KUndefinedKeySize = 0;
       
   806 
       
   807     TCertStatus status = ECertValid;
       
   808 
       
   809     HBufC8* subjectName = NULL;
       
   810     HBufC8* rfc822Name = NULL;
       
   811 
       
   812     if (aOwnCert.iOwnCertExists)
       
   813         {
       
   814         // Reserve enough space for UTF-8
       
   815         TInt len = 3*( aOwnCert.iSubjectDnSuffix.Length() );
       
   816         subjectName = HBufC8::NewLC(len);
       
   817         TPtr8 subjectNamePtr = subjectName->Des();
       
   818         if (CnvUtfConverter::ConvertFromUnicodeToUtf8(subjectNamePtr, aOwnCert.iSubjectDnSuffix) != 0)
       
   819             {
       
   820             User::Leave(KErrCorrupt);
       
   821             }
       
   822 
       
   823         if ( aOwnCert.iIdentityAsRfc822Name == EIdentityAsRfc822NameYes)
       
   824             {
       
   825             rfc822Name = HBufC8::NewLC(aOwnCert.iRfc822NameFqdn.Length());
       
   826             TPtr8 rfc822NamePtr = rfc822Name->Des();
       
   827             if (CnvUtfConverter::ConvertFromUnicodeToUtf8(rfc822NamePtr, aOwnCert.iRfc822NameFqdn) != 0)
       
   828                 {
       
   829                 User::Leave(KErrCorrupt);
       
   830                 }
       
   831 
       
   832             }
       
   833         else
       
   834             {
       
   835             rfc822Name = HBufC8::NewLC(1); //empty string
       
   836             }
       
   837 
       
   838             status = ECertNotFound;
       
   839             for (TInt i = 0; i < aValidCaCertNameList.Count(); ++i)
       
   840                 {
       
   841 
       
   842                 status = CertStatusL(aPkiService, aValidCaCertNameList[i],
       
   843                                      *subjectName, *rfc822Name,
       
   844                                      KUndefinedKeySize);
       
   845                 if (status != ECertNotFound)
       
   846                     {
       
   847                     break;
       
   848                     }
       
   849                 }
       
   850 
       
   851             CleanupStack::PopAndDestroy(rfc822Name);
       
   852             CleanupStack::PopAndDestroy(subjectName);
       
   853         }
       
   854 
       
   855     return status;
       
   856     }
       
   857 
       
   858 
       
   859 CX500DistinguishedName* PkiUtil::DnFromStringL(const TDesC8& aString)
       
   860     {
       
   861     HBufC8* dnDer;
       
   862     CPkcs10Req::BuildDistinguishedNameDerFromTextL(dnDer, aString,
       
   863                                                    EFalse, KNullDesC8);
       
   864     CleanupStack::PushL(dnDer);
       
   865 
       
   866     CX500DistinguishedName* dn = CX500DistinguishedName::NewL(*dnDer);
       
   867 
       
   868     CleanupStack::PopAndDestroy(); // dnDer
       
   869 
       
   870     return dn;
       
   871     }
       
   872 
       
   873 CX500DistinguishedName* PkiUtil::DnWithoutCnFromStringL(const TDesC8& aString)
       
   874     {
       
   875     HBufC8* dnDer;
       
   876     CPkcs10Req::BuildDistinguishedNameDerFromTextL(dnDer, aString,
       
   877                                                    ETrue, KCN8);
       
   878     CleanupStack::PushL(dnDer);
       
   879 
       
   880     CX500DistinguishedName* dn = CX500DistinguishedName::NewL(*dnDer);
       
   881 
       
   882     CleanupStack::PopAndDestroy(); // dnDer
       
   883 
       
   884     return dn;
       
   885     }
       
   886 
       
   887 TBool PkiUtil::DnMatchL(const TDesC8& aDnString1, const TDesC8& aDnString2)
       
   888     {
       
   889     TBool exactMatch = EFalse;
       
   890 
       
   891     if (aDnString1.Length() == 0 && aDnString2.Length() == 0)
       
   892         {
       
   893         exactMatch = ETrue;
       
   894         }
       
   895     else if (aDnString1.Length() > 0 && aDnString2.Length() > 0)
       
   896         {
       
   897         CX500DistinguishedName* dn1 = DnFromStringL(aDnString1);
       
   898         CleanupStack::PushL(dn1);
       
   899 
       
   900         CX500DistinguishedName* dn2 = DnFromStringL(aDnString2);
       
   901         CleanupStack::PushL(dn2);
       
   902 
       
   903         if (MatchL(*dn1, *dn2))
       
   904             {
       
   905             exactMatch = ETrue;
       
   906             }
       
   907 
       
   908         CleanupStack::PopAndDestroy(2); // dn2, dn1
       
   909         }
       
   910 
       
   911     return exactMatch;
       
   912     }
       
   913 
       
   914 TBool PkiUtil::MatchL(const CX500DistinguishedName& aDn1, const CX500DistinguishedName& aDn2)
       
   915     {
       
   916     if (aDn1.Count() != aDn2.Count())
       
   917         {
       
   918         return EFalse;
       
   919         }
       
   920 
       
   921     // For each field in aDn1, aDn2 must contain a field with the same value
       
   922     for (TInt i = 0; i < aDn1.Count(); i++)
       
   923     {
       
   924         if (!HasElementL(aDn2, aDn1.Element(i)))
       
   925             {
       
   926             return EFalse;
       
   927             }
       
   928         }
       
   929     return ETrue;
       
   930     }
       
   931 
       
   932 TBool PkiUtil::HasElementL(const CX500DistinguishedName& aDn, const CX520AttributeTypeAndValue& aElement)
       
   933     {
       
   934   for (TInt i = 0; i < aDn.Count(); i++)
       
   935     {
       
   936         if (aElement.ExactMatchL(aDn.Element(i)))
       
   937             {
       
   938             return ETrue;
       
   939             }
       
   940         }
       
   941     return EFalse;
       
   942     }
       
   943 
       
   944 HBufC8* PkiUtil::To8BitL(const TDesC16& aDes)
       
   945     {
       
   946     HBufC8* desCopy;
       
   947     
       
   948     TInt desLength = aDes.Length();
       
   949     
       
   950     if (desLength > 0)
       
   951         {
       
   952         desCopy = HBufC8::NewL(desLength);
       
   953         desCopy->Des().Copy(aDes);
       
   954         }
       
   955     else
       
   956         {
       
   957         desCopy = HBufC8::NewL(1);
       
   958         }
       
   959 
       
   960     return desCopy;
       
   961     }