pkiutilities/CertSaver/src/certparser.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:19:59 +0100
branchRCL_3
changeset 22 03674e5abf46
parent 21 09b1ac925e3f
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201033 Kit: 201035

/*
* Copyright (c) 2003-2007 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:   Implementation of CCertParser class
*
*/


// INCLUDE FILES
#include <e32std.h>
#include <apmrec.h>
#include <x509cert.h>
#include <x509certext.h>
#include <hash.h>
#include <X509CertNameParser.h>
#include <featmgr.h>
#include <data_caging_path_literals.hrh>
#include <AknQueryDialog.h>
#include <CertSaver.rsg>
#include <StringLoader.h>
#include <securityerr.h>
#include <aknnotewrappers.h>              // Note dialogs
#include <apmrec.h>
#include "certparser.h"

// CONSTANTS
_LIT( KPKCS12DllName, "crpkcs12.dll" );   // PKCS12 DLL name
const TInt KX509Version3 = 3;
const TInt KPwMaxLength = 32;

// MACROS

// LOCAL CONSTANTS AND MACROS

// MODULE DATA STRUCTURES

// LOCAL FUNCTION PROTOTYPES

// ==================== LOCAL FUNCTIONS ====================

// ================= MEMBER FUNCTIONS =======================

// C++ default constructor can NOT contain any code, that
// might leave.
//
CCertParser::CCertParser()
    {
    }

// EPOC default constructor can leave.
void CCertParser::ConstructL()
    {
    }

// Two-phased constructor.
CCertParser* CCertParser::NewL()
    {
    CCertParser* self = new (ELeave) CCertParser;

    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );

    return self;
    }


// Destructor
CCertParser::~CCertParser()
    {
    delete iCert;
    if ( iPKCS12 )
        {
        iPKCS12->Release();
        }
    iLibrary.Close();
    }

// ----------------------------------------------------------
// CCertParser::SetContentL()
// Checks if given buffer is a WTLS or a X.509 certificate and
// sets member data accordingly.
// ----------------------------------------------------------
//
void CCertParser::SetContentL( RFile& aFile )
    {
    delete iCert;
    iCert = NULL;
    TInt fileSize = 0;
    CleanupClosePushL( aFile );
    User::LeaveIfError( aFile.Size( fileSize ) );

    HBufC8* buffer = HBufC8::NewL( fileSize );
    CleanupStack::PushL( buffer );

    TPtr8 ptr8(buffer->Des());
    User::LeaveIfError( aFile.Read( ptr8 ) );

    if ( !CheckIfX509CertificateL( *buffer ) )
        {
        TFileName fileName;
        User::LeaveIfError( aFile.Name( fileName ) );
        if ( !CheckIfPKCS12L( *buffer, fileName ) )
            {
            iCertType = ETypeCorrupt;
            }
        }
    CleanupStack::PopAndDestroy( buffer );
    CleanupStack::PopAndDestroy( &aFile );
    }

// ----------------------------------------------------------
// CCertParser::CreatePKCS12L()
// Creates PKCS#12 DLL
// ----------------------------------------------------------
//
void CCertParser::CreatePKCS12L()
    {
    // Load PKCS#12 dll
#ifdef __WINS__
    User::LeaveIfError ( iLibrary.Load( KPKCS12DllName ) );
#else
    User::LeaveIfError ( iLibrary.Load( KPKCS12DllName, KDC_SHARED_LIB_DIR ) );
#endif

    // Define the function that returns pointer to MPKCS12
    typedef MPKCS12* ( *TLibraryFunc )();
    // Find CreateL() method from pkcs12.dll that implements the function
    TLibraryFunc createL =
        reinterpret_cast<TLibraryFunc>( iLibrary.Lookup( 1 ) );
    // Create new instance of MPKCS12
    iPKCS12 = createL();
    }

// ----------------------------------------------------------
// CCertParser::CheckIfPKCS12L()
// Checks if PKCS#12 file
// ----------------------------------------------------------
//
TBool CCertParser::CheckIfPKCS12L(
    const TDesC8& aPKCS12,
    const TDesC& aFileName )
    {
    CreatePKCS12L();

    if ( !iPKCS12->IsPKCS12Data( aPKCS12 ) )
        {
        ShowErrorNoteL( R_CERTSAVER_PKCS12_FILE_CORRUPTED );
        return EFalse;
        }

    TBool done = EFalse;
    TBuf<KPwMaxLength> password;
    HBufC* buffer = NULL;

    if ( !iEikEnv )
        {
        iEikEnv = CEikonEnv::Static();
        }

    while ( !done )
        {
        if ( !GetPasswordL( password, aFileName ) )
            {
            buffer = iEikEnv->AllocReadResourceLC( R_CERTSAVER_PKCS12_DISCARDED );
            CAknInformationNote* note = new (ELeave) CAknInformationNote( ETrue );
            note->ExecuteLD(buffer->Des());
            CleanupStack::PopAndDestroy( buffer );
            User::Leave( KErrExitApp );
            }
        TRAPD( err, iPKCS12->ParseL( aPKCS12, password ) );
        if ( err != KErrBadPassphrase )
            {
            switch ( err )
                {
                case KErrNone:
                    {
                    iCertType = ETypePKCS12;
                    break;
                    }
                case KErrNoMemory:
                    {
                    User::Leave( KErrNoMemory );
                    }
                case KErrNotSupported:
                    {
                    ShowErrorNoteL( R_QTN_CM_PKCS12_FORMAT_NOT_SUPPORTED );
                    break;
                    }
                default:
                    {
                    ShowErrorNoteL( R_CERTSAVER_PKCS12_FILE_CORRUPTED );
                    break;
                    }
                }
            if ( err != KErrNone )
                {
                return EFalse;
                }
            done = ETrue;
            }
        else
            {
            password.Zero();
            // Show error note
            ShowErrorNoteL( R_QTN_CM_INCORRECT_PASSWORD );
            }
        }
    return ETrue;
    }

// ----------------------------------------------------------
// CCertParser::GetPasswordL(...)
//
// ----------------------------------------------------------
//
TInt CCertParser::GetPasswordL( TDes& aPassword, const TDesC& aFileName )
    {
    CAknTextQueryDialog* query = CAknTextQueryDialog::NewL( aPassword );
    CleanupStack::PushL( query );
    HBufC* prompt =
        StringLoader::LoadLC( R_QTN_CM_TITLE_P12_PASSWORD, aFileName );
    query->SetPromptL( *prompt );
    CleanupStack::PopAndDestroy( prompt );
    CleanupStack::Pop( query );
    return query->ExecuteLD( R_PKCS12_PW_QUERY_DIALOG );
    }

// ----------------------------------------------------------
// CCertParser::CheckIfX509CertificateL()
// Returns the type of the certificate.
// ----------------------------------------------------------
//
TBool CCertParser::CheckIfX509CertificateL(const TDesC8& aCert)
    {
    TRAPD( err,
           iCert = CX509Certificate::NewL(aCert);
         );

    if ( err != KErrNone )
        {
        iCertType = ETypeCorrupt;
        if ( err == KErrNoMemory )
            {
            User::Leave( err );
            }
        else
            {
            return EFalse;
            }
        }

  if ( iCert )
      {
      // Check certificate version
      if ( iCert->Version() != KX509Version3 )
          {
          // X509 v1 or v2 certificate. Certificate type is CA
          iCertType = ETypeX509CA;
          }
      else
          {
          // X509 v3 certificate. Check basicConstrains
          const CX509CertExtension* certExt = iCert->Extension( KBasicConstraints );
          if ( certExt )
              {
              CX509BasicConstraintsExt* basic = CX509BasicConstraintsExt::NewLC( certExt->Data() );
              if ( basic->IsCA() )
                  {
                  iCertType = ETypeX509CA;
                  }
              else
                  {
                  iCertType = ETypeX509Peer;
                  }
              CleanupStack::PopAndDestroy( basic ); //basic
              }
           else
              {
              // No basicConstrains extension
              iCertType = ETypeX509Peer;
              }
          }
      }

    return ETrue;
    }

// ----------------------------------------------------------
// CCertParser::CACertificates()
// ----------------------------------------------------------
//
const CArrayPtr<CX509Certificate>&  CCertParser::CACertificates() const
    {
    __ASSERT_ALWAYS( iPKCS12, User::Panic( KCertSaverPanic, KPanicNullPointer ) );
    return iPKCS12->CACertificates();
    }

// ----------------------------------------------------------
// CCertParser::UserCertificates()
// ----------------------------------------------------------
//
const CArrayPtr<CX509Certificate>&  CCertParser::UserCertificates() const
    {
    __ASSERT_ALWAYS( iPKCS12, User::Panic( KCertSaverPanic, KPanicNullPointer ) );
    return iPKCS12->UserCertificates();
    }

// ----------------------------------------------------------
// CCertParser::Keys()
// ----------------------------------------------------------
//
const CArrayPtr<HBufC8>& CCertParser::Keys() const
    {
    __ASSERT_ALWAYS( iPKCS12, User::Panic( KCertSaverPanic, KPanicNullPointer ) );
    return iPKCS12->PrivateKeys();
    }

// ----------------------------------------------------------
// CCertParser::CertType()
// ----------------------------------------------------------
//
 CCertParser::TCertType CCertParser::CertType() const
    {
    return iCertType;
    }

// ----------------------------------------------------------
// CCertParser::CertificateBuf()
// Returns the content of the certificate.
// ----------------------------------------------------------
//
const TPtrC8 CCertParser::CertificateBuf() const
    {
    __ASSERT_ALWAYS( iCert, User::Panic( KCertSaverPanic, KPanicNullPointer ) );
    return iCert->Encoding();
    }

// ----------------------------------------------------------
// CCertParser::Certificate()
// Returns the X.509 certificate object.
// ----------------------------------------------------------
//
const CX509Certificate& CCertParser::Certificate() const
    {
    __ASSERT_ALWAYS( iCert, User::Panic( KCertSaverPanic, KPanicNullPointer ) );
    return *((CX509Certificate*)iCert);
    }

// ----------------------------------------------------------
// CCertParser::ShowErrorNoteL() const
// Creates and shows an error note.
// ----------------------------------------------------------
//
void CCertParser::ShowErrorNoteL( TInt aResourceID )
    {
     if ( !iEikEnv )
        {
        iEikEnv = CEikonEnv::Static();
        }
    HBufC* buffer = iEikEnv->AllocReadResourceLC( aResourceID );
    CAknErrorNote* note = new (ELeave) CAknErrorNote( ETrue );
    note->ExecuteLD(buffer->Des());
    CleanupStack::PopAndDestroy( buffer );
    }

//  End of File