pkiutilities/PKCS12/CrPkcs12/Src/pkcs12.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 26 Jan 2010 15:20:08 +0200
changeset 0 164170e6151a
permissions -rw-r--r--
Revision: 201004

/*
* Copyright (c) 2004 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 the PKCS#12 parser API
*
*/


// INCLUDE FILES
#include <securityerr.h>
#include    "pkcs12.h"
#include    "crpkcs12.h"
//#include    <?include_file>

// EXTERNAL DATA STRUCTURES
//extern  ?external_data;

// EXTERNAL FUNCTION PROTOTYPES  
//extern ?external_function( ?arg_type,?arg_type );

// CONSTANTS

// ASN.1 tag values
const TInt KASN1SequenceTagValue = 0x30;
const TInt KASN1ImplicitConstructedTagValue = 0xA0;   // Implicit constructed tag
const TInt KASN1OctetStringTagValue   = 0x04;     // Octet string tag
const TInt KASN1BerConstructedBit = 0x20;

_LIT8(KPKCS12Version3, "\x02\x01\x03");
_LIT8(KPKCS7DataOID, "\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x07\x01");
_LIT8(KPKC7EncryptedDataOID, "\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x07\x06");
_LIT8(KSequenceTagInOctet,"\x04\x01\x30\x04\x01\x80");
_LIT8(KMozillaPKCS7EncryptedDataOID, 
    "\x04\x01\x06\x04\x01\x09\x04\x09\x2a\x86\x48\x86\xf7\x0d\x01\x07\x06");
_LIT8(KMozillaPKCS7DataOID, 
    "\x04\x01\x06\x04\x01\x09\x04\x09\x2a\x86\x48\x86\xf7\x0d\x01\x07\x01");

// MACROS
//#define ?macro ?macro_def

// LOCAL CONSTANTS AND MACROS
//const ?type ?constant_var = ?constant;
//#define ?macro_name ?macro_def

// MODULE DATA STRUCTURES
//enum ?declaration
//typedef ?declaration

// LOCAL FUNCTION PROTOTYPES
//?type ?function_name( ?arg_type, ?arg_type );

// FORWARD DECLARATIONS
//class ?FORWARD_CLASSNAME;

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

// ---------------------------------------------------------
// PKCS12Factory::CreateL
// ---------------------------------------------------------
//
EXPORT_C MPKCS12* PKCS12Factory::CreateL()
    {
    return CPKCS12::NewL();
    }

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

// -----------------------------------------------------------------------------
// CPKCS12::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CPKCS12::ConstructL()
    {        
    
    }

// -----------------------------------------------------------------------------
// CPKCS12::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CPKCS12* CPKCS12::NewL()
    {
    CPKCS12* self = new( ELeave ) CPKCS12();
    
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop();

    return self;
    }

void CPKCS12::Release()
    {
    delete this;
    }

// ---------------------------------------------------------
// CPKCS12::IsPKCS12Data
// ---------------------------------------------------------
//    
TBool CPKCS12::IsPKCS12Data(const TDesC8& aBinaryData)
     {     
    // We don't decode the data because we may only have the first few bytes -
	// instead we check the ASN1 by hand.
	ASSERT(aBinaryData.Length() >= KPKCS12DataMinLength);
	TInt pos = 0;
	
	if (!IsASN1Tag(KASN1SequenceTagValue,aBinaryData, pos))
	    {
	    return EFalse;
	    }
	if (!IsExpectedData(aBinaryData, pos, KPKCS12Version3))
	    {
	    return EFalse;
	    }
    if (!IsASN1Tag(KASN1SequenceTagValue, aBinaryData, pos))
	    {
	    return EFalse;
	    } 
	if (!IsExpectedData(aBinaryData, pos, KPKCS7DataOID))
	    {
	    return EFalse;
	    } 
    if (!IsASN1Tag(KASN1ImplicitConstructedTagValue, aBinaryData, pos))
	    {
	    return EFalse;
	    } 
	// OpenSSL, IE and Opera type of PKCS#12 file    
    if (IsASN1Tag(KASN1OctetStringTagValue, aBinaryData, pos))
        {
        if (!IsASN1Tag(KASN1SequenceTagValue, aBinaryData, pos))
            {
            return EFalse;
            }
        if (!IsASN1Tag(KASN1SequenceTagValue, aBinaryData, pos))
            {
            return EFalse;
            }    
    	if  (IsExpectedData(aBinaryData, pos, KPKC7EncryptedDataOID) || 
    	     IsExpectedData(aBinaryData, pos, KPKCS7DataOID))    		
    	    {    	    
    	    return ETrue;
    	    }
    	else
    	    {
    	    return EFalse;
    	    }
        }
    // Netscape and Mozilla type of PKCS#12 file    
	else if (IsASN1Tag(KASN1OctetStringTagValue + KASN1BerConstructedBit, aBinaryData, pos))
	    {
	    if (IsExpectedData(aBinaryData, pos, KSequenceTagInOctet))
            {
            if (!IsExpectedData(aBinaryData, pos, KSequenceTagInOctet))
                {
                return EFalse;
                }    
        	if  (IsExpectedData(aBinaryData, pos, KMozillaPKCS7DataOID) ||
        		IsExpectedData(aBinaryData, pos, KMozillaPKCS7EncryptedDataOID))
        	    {    	    
        	    return ETrue;
        	    }
            }
        // Firefox version 1.5 type of PKCS#12 data    
        else if (IsASN1Tag(KASN1OctetStringTagValue, aBinaryData, pos))
            {
            if (!IsASN1Tag(KASN1SequenceTagValue, aBinaryData, pos))
                {
                return EFalse;
                }
            if (!IsASN1Tag(KASN1SequenceTagValue, aBinaryData, pos))
                {
                return EFalse;
                }    
    	    if (IsExpectedData(aBinaryData, pos, KPKC7EncryptedDataOID) || 
    	     IsExpectedData(aBinaryData, pos, KPKCS7DataOID))    		
    	        {    	    
    	        return ETrue;
    	        }
    	    else
    	        {
    	        return EFalse;
    	        }
            }
        else
            {
            return EFalse;
            }            
	    }
    else
        {            
        return EFalse;
        }
    return EFalse;    
    }
    
// ---------------------------------------------------------
// CPKCS12Recognizer::IsASN1Tag
// ---------------------------------------------------------
//  
TBool CPKCS12::IsASN1Tag(
    TInt aTag, 
    const TDesC8& aBinaryData, 
    TInt& aPos)
	{	
	// Check we have enough data
	if ((aPos + 2) >= aBinaryData.Length())
		{
		return EFalse;
		}
	// Check the outermost sequence is valid
	if (aBinaryData[aPos] != aTag)
		{
		return EFalse;
		}
	// Skip sequence length
	aPos++;
	TInt length0 = aBinaryData[aPos++];
	if (length0 & 0x80)
		{
		aPos += length0 & 0x7f;
		}
	return ETrue;
	}

// ---------------------------------------------------------
// CPKCS12Recognizer::IsExpectedData
// ---------------------------------------------------------
//  
TBool CPKCS12::IsExpectedData(
    const TDesC8& aBinaryData, 
    TInt& aPos, 
    const TDesC8& aExpectedData)
	{	
	TInt length = aExpectedData.Length();
	// Check we have enough data
	if (aPos + length >= aBinaryData.Length())
		{
		return EFalse;
		}
	// Check data matches	
	if (aBinaryData.Mid(aPos, length) != aExpectedData)
		{
		return EFalse;
		}
	aPos += length;
	return ETrue;
	}    

// -----------------------------------------------------------------------------
// CPKCS12::ParseL
// 
// -----------------------------------------------------------------------------
//
void CPKCS12::ParseL(const TDesC8& aPKCS12, const TDesC16& aPassword)
    {
    Reset();
    iCrPkcs12 = CCrPKCS12::NewL();
    iCrData = CCrData::NewL(EFalse);
    User::LeaveIfError(iCrData->Write(aPKCS12));
    TInt start = 0;
    iCrData->Seek( ESeekStart, start );
    HandleErrorL( iCrPkcs12->OpenL( *iCrData, aPassword ));
    }

// -----------------------------------------------------------------------------
// CPKCS12::HandleErrorL
// 
// -----------------------------------------------------------------------------
//
void CPKCS12::HandleErrorL( TUint16 aError ) const
    {

    switch ( aError & 0x00ff )
        {
        case KCrOK:
            return;
        case KCrNotValidPkcs12Object:
            User::Leave(KErrArgument);
        case KCrBerLibraryError:
            User::Leave(KErrGeneral);
        case KCrNotSupportedHMACalgorithm:
            User::Leave(KErrNotSupported);
        case KCrCancelled:
            User::Leave(KErrCancel);
        case KCrGeneralError:
            User::Leave(KErrGeneral);
        case KCrWrongPassWordOrCorruptedFile:
            User::Leave(KErrBadPassphrase);
        case KCrNotPasswordBasedEncryption:
            User::Leave(KErrNotSupported);
        case KCrNoMemory:
            User::Leave(KErrNoMemory);
        default:
            User::Leave(KErrGeneral);
        }
    }
    
// Destructor
CPKCS12::~CPKCS12()
    {
    Reset();
    }

// -----------------------------------------------------------------------------
// CPKCS12::Reset
// ?implementation_description
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CPKCS12::Reset()
    {
    if (iCrData)
        {        
        iCrData->Close();
        delete iCrData;
        iCrData = NULL;
        }    
    delete iCrPkcs12;
    iCrPkcs12 = NULL;
    }

// -----------------------------------------------------------------------------
// CPKCS12::CACertificates
// ?implementation_description
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
const CArrayPtr<CX509Certificate>& CPKCS12::CACertificates() const
    {
    return iCrPkcs12->CACertificates();
    }

// -----------------------------------------------------------------------------
// CPKCS12::UserCertificates
// ?implementation_description
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
const CArrayPtr<CX509Certificate>& CPKCS12::UserCertificates() const
    {    
    return iCrPkcs12->UserCertificates();
    }

// -----------------------------------------------------------------------------
// CPKCS12::PrivateKeys
// ?implementation_description
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
const CArrayPtr<HBufC8>& CPKCS12::PrivateKeys() const
    {    
    return iCrPkcs12->PrivateKeys();
    }

// -----------------------------------------------------------------------------
// CPKCS12::SafeBagsCount
// ?implementation_description
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TUint CPKCS12::SafeBagsCount() const
    {
    return iCrPkcs12->SafeBagsCount();
    }

// -----------------------------------------------------------------------------
// CPKCS12::IterCount
// ?implementation_description
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//     
TUint CPKCS12::IterCount() const
    {
    return iCrPkcs12->Iter();
    }

// ========================== OTHER EXPORTED FUNCTIONS =========================
                                                                                
// ---------------------------------------------------------
// E32Dll
// DLL entry point
// ---------------------------------------------------------
//
#ifndef EKA2
GLDEF_C TInt E32Dll(TDllReason /*aReason*/)
    {
    return KErrNone;
    }
#endif

//  End of File