--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/src/CCMSX509CertificateList.cpp Tue Jan 26 15:20:08 2010 +0200
@@ -0,0 +1,605 @@
+/*
+* Copyright (c) 2002 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:
+*
+*/
+
+
+// INCLUDE FILES
+#include "CCMSX509CertificateList.h"
+#include "TCMSTimeUtil.h"
+#include "CCMSX509AlgorithmIdentifier.h"
+#include <x509cert.h>
+#include <asn1dec.h>
+#include <asn1enc.h>
+
+// CONSTANTS
+const TInt KDefaultGranularity = 1;
+const TInt KCertificateListParams = 3;
+const TInt KMinTBSCertListParams = 3;
+const TInt KMaxTBSCertListParams = 7;
+const TInt KDefaultVersion = 1;
+const TInt KMinRevokedCertParams = 2;
+const TInt KMaxRevokedCertParams = 3;
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CCMSX509RevokedCertificate::CCMSX509RevokedCertificate
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+
+EXPORT_C CCMSX509RevokedCertificate::CCMSX509RevokedCertificate()
+ {
+ }
+
+// Destructor
+CCMSX509RevokedCertificate::~CCMSX509RevokedCertificate()
+ {
+ if( iExtensions )
+ {
+ iExtensions->ResetAndDestroy();
+ delete iExtensions;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CCMSX509RevokedCertificate::CCMSX509RevokedCertificate
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+EXPORT_C CCMSX509CertificateListParameters::CCMSX509CertificateListParameters()
+ {
+ }
+
+// Destructor
+CCMSX509CertificateListParameters::~CCMSX509CertificateListParameters()
+ {
+ delete iIssuer;
+ delete iSignatureAlgorithm;
+ delete iSignature;
+ if( iRevokedCertificates )
+ {
+ iRevokedCertificates->ResetAndDestroy();
+ delete iRevokedCertificates;
+ }
+
+ if( iExtensions )
+ {
+ iExtensions->ResetAndDestroy();
+ delete iExtensions;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CCMSX509CertificateList::CCMSX509CertificateList
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CCMSX509CertificateList::CCMSX509CertificateList()
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CCMSX509CertificateList::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CCMSX509CertificateList::ConstructL()
+ {
+ iParams = new(ELeave) CCMSX509CertificateListParameters();
+ // version is always v2(1)
+ iParams->iVersion = KDefaultVersion;
+ }
+
+// -----------------------------------------------------------------------------
+// CCMSX509CertificateList::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CCMSX509CertificateList::ConstructL(
+ const CX509Certificate& aSigningCertificate,
+ const CArrayPtrFlat<CX509Certificate>& aRevokedCertificates )
+ {
+ ConstructL();
+
+ // setting signature
+ const CSigningAlgorithmIdentifier& signAlgorithm =
+ aSigningCertificate.SigningAlgorithm();
+ iParams->iSignatureAlgorithm =
+ CCMSX509AlgorithmIdentifier::NewL( signAlgorithm.AsymmetricAlgorithm(),
+ signAlgorithm.DigestAlgorithm() );
+
+ // setting issuer
+ iParams->iIssuer =
+ CX500DistinguishedName::NewL( aSigningCertificate.IssuerName() );
+
+ // setting validity
+ const CValidityPeriod& validity = aSigningCertificate.ValidityPeriod();
+ iParams->iThisUpdate = validity.Start();
+ iParams->iNextUpdate = validity.Finish();
+
+
+ // copying revoked certificates
+ TInt revCerts = aRevokedCertificates.Count();
+ if( revCerts > 0 )
+ {
+ iParams->iRevokedCertificates =
+ new( ELeave )CArrayPtrFlat< CCMSX509RevokedCertificate >
+ ( KDefaultGranularity );
+ for( TInt i = 0; i < revCerts; i++ )
+ {
+ CX509Certificate* cert = aRevokedCertificates[ i ];
+ CCMSX509RevokedCertificate* tmpRevCer =
+ new(ELeave) CCMSX509RevokedCertificate();
+ CleanupStack::PushL( tmpRevCer );
+ // convert serial from des to int
+ TPtrC8 serialDes = cert->SerialNumber();
+ TInt length = serialDes.Size();
+ const TUint8* ptr = serialDes.Ptr();
+ TInt serial = ( ptr[ 0 ] & 0x80 ) ? -1 : 0;
+ for( TInt j = 0; j < length; j++ )
+ {
+ serial <<= 8;
+ serial += *ptr++;
+ }
+ tmpRevCer->iUserCertificateSerialNumber = serial;
+
+ const CValidityPeriod& reValidity = cert->ValidityPeriod();
+ tmpRevCer->iRevokationDate = reValidity.Start();
+
+ // copying extensions
+ const CArrayPtrFlat<CX509CertExtension>& extensions =
+ cert->Extensions();
+ TInt extensionCount = extensions.Count();
+ if( extensionCount > 0 )
+ {
+ tmpRevCer->iExtensions =
+ new(ELeave) CArrayPtrFlat<CX509CertExtension>
+ ( KDefaultGranularity );
+ for( TInt j = 0; j < extensionCount; j++ )
+ {
+ CX509CertExtension* ext = extensions[ j ];
+ CX509CertExtension* tmpExt =
+ CX509CertExtension::NewLC( *ext );
+ tmpRevCer->iExtensions->AppendL( tmpExt );
+ CleanupStack::Pop( tmpExt );
+ }
+ }
+ iParams->iRevokedCertificates->AppendL( tmpRevCer );
+ CleanupStack::Pop( tmpRevCer );
+ }
+ }
+ // copying possible extensions
+ TInt extensionCount = aSigningCertificate.Extensions().Count();
+ if( extensionCount > 0 )
+ {
+ iParams->iExtensions =
+ new( ELeave )CArrayPtrFlat< CX509CertExtension >
+ ( KDefaultGranularity );
+ const CArrayPtrFlat< CX509CertExtension >& extensions =
+ aSigningCertificate.Extensions();
+
+ for( TInt i = 0; i < extensionCount; i++ )
+ {
+ CX509CertExtension* copy = CX509CertExtension::NewL( *extensions[ i ] );
+ CleanupStack::PushL( copy );
+ iParams->iExtensions->AppendL( copy );
+ CleanupStack::Pop( copy );
+ }
+ }
+
+ // copying signature
+ iParams->iSignature = aSigningCertificate.Signature().AllocL();
+ }
+
+// -----------------------------------------------------------------------------
+// CCMSX509CertificateList::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CCMSX509CertificateList* CCMSX509CertificateList::NewLC()
+ {
+ CCMSX509CertificateList* self = new( ELeave ) CCMSX509CertificateList();
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CCMSX509CertificateList::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CCMSX509CertificateList* CCMSX509CertificateList::NewLC(
+ const CX509Certificate& aSigningCertificate,
+ const CArrayPtrFlat<CX509Certificate>& aRevokedCertificates )
+ {
+ CCMSX509CertificateList* self = new( ELeave ) CCMSX509CertificateList();
+ CleanupStack::PushL( self );
+ self->ConstructL( aSigningCertificate,
+ aRevokedCertificates );
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CCMSX509CertificateList::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CCMSX509CertificateList* CCMSX509CertificateList::NewLC(
+ CCMSX509CertificateListParameters& aParameters )
+ {
+ CCMSX509CertificateList* self = new( ELeave ) CCMSX509CertificateList();
+ CleanupStack::PushL( self );
+ self->SetParametersL( aParameters );
+ return self;
+ }
+
+// Destructor
+CCMSX509CertificateList::~CCMSX509CertificateList()
+ {
+ delete iParams;
+ }
+
+// -----------------------------------------------------------------------------
+// CCMSX509CertificateList::DecodeL
+// Decrypts raw data to this instance
+// -----------------------------------------------------------------------------
+void CCMSX509CertificateList::DecodeL( const TDesC8& aRawData )
+ {
+ CCMSX509CertificateListParameters* params =
+ new(ELeave) CCMSX509CertificateListParameters();
+ CleanupStack::PushL( params );
+
+ CArrayPtr<TASN1DecGeneric>* certificateList = DecodeSequenceLC( aRawData,
+ KCertificateListParams, // 3
+ KCertificateListParams );
+
+
+ // decode tbsCertList
+ CArrayPtr<TASN1DecGeneric>* tbsCertList =
+ DecodeSequenceLC( certificateList->At( 0 )->Encoding(),
+ KMinTBSCertListParams, // 3
+ KMaxTBSCertListParams ); // 7
+
+ TInt pos = 0;
+ // decode Version (optional)
+ TASN1DecGeneric ver( *tbsCertList->At( pos ) );
+ if( ver.Tag() == EASN1Integer )
+ {
+ TASN1DecInteger version;
+ params->iVersion = version.DecodeDERShortL( ver );
+ pos++;
+ }
+ else
+ {
+ // always ver v2( 1 )
+ params->iVersion = KDefaultVersion;
+ }
+
+ // decode Signature algorithm
+ CCMSX509AlgorithmIdentifier* signAlg = CCMSX509AlgorithmIdentifier::NewL();
+ CleanupStack::PushL( signAlg );
+ signAlg->DecodeL( tbsCertList->At( pos++ )->Encoding() );
+ params->iSignatureAlgorithm = signAlg;
+ CleanupStack::Pop( signAlg );
+
+ // decode Issuer
+ params->iIssuer =
+ CX500DistinguishedName::NewL( tbsCertList->At( pos++ )->Encoding() );
+
+ // check that we have enough parameters for mandatory thisUpdate
+ if( tbsCertList->Count() <= pos )
+ {
+ User::Leave( KErrArgument );
+ }
+
+ // decode thisUpdate
+ params->iThisUpdate = TCMSTimeUtil::ConvertToTimeL(
+ tbsCertList->At( pos++ )->Encoding() );
+
+ // decode nextUpdate (optional)
+ if( ( tbsCertList->Count() > pos ) &&
+ ( ( tbsCertList->At( pos )->Tag() == EASN1UTCTime ) ||
+ ( tbsCertList->At( pos )->Tag() == EASN1GeneralizedTime ) ) )
+ {
+ params->iNextUpdate = TCMSTimeUtil::ConvertToTimeL(
+ tbsCertList->At( pos++ )->Encoding() );
+ }
+
+ // decode revokedCerts (optional)
+ if( ( tbsCertList->Count() > pos ) &&
+ ( tbsCertList->At( pos )->Tag() == EASN1Sequence ) )
+ {
+ // if it is sequence then it must be set of revoked certificates
+ CArrayPtr<TASN1DecGeneric>* revokedCerts =
+ DecodeSequenceLC( tbsCertList->At( pos++ )->Encoding() );
+ TInt rCertCount = revokedCerts->Count();
+ params->iRevokedCertificates =
+ new(ELeave)CArrayPtrFlat< CCMSX509RevokedCertificate >
+ ( KDefaultGranularity );
+ for( TInt i = 0; i < rCertCount; i++ )
+ {
+ // decode certificate
+ CArrayPtr<TASN1DecGeneric>* rCert =
+ DecodeSequenceLC( revokedCerts->At( i )->Encoding(),
+ KMinRevokedCertParams, // 2
+ KMaxRevokedCertParams ); // 3
+ CCMSX509RevokedCertificate* tmpCert =
+ new( ELeave )CCMSX509RevokedCertificate;
+ CleanupStack::PushL( tmpCert );
+
+ // decode serial number
+ TASN1DecInteger serial;
+ tmpCert->iUserCertificateSerialNumber =
+ serial.DecodeDERShortL( *rCert->At( 0 ) );
+
+ // decode revocationDate
+ tmpCert->iRevokationDate = TCMSTimeUtil::ConvertToTimeL(
+ rCert->At( 1 )->Encoding() );
+
+ // decode possible extensions
+ if( rCert->Count() == KMaxRevokedCertParams )
+ {
+ tmpCert->iExtensions = DecodeExtensionsL( rCert->At( 2 ) );
+ }
+ params->iRevokedCertificates->AppendL( tmpCert );
+
+ CleanupStack::Pop( tmpCert );
+ CleanupStack::PopAndDestroy( rCert );
+ }
+ CleanupStack::PopAndDestroy( revokedCerts );
+ }
+ // decode extensions (optional), tagged with 0
+ if( ( tbsCertList->Count() > pos ) &&
+ ( tbsCertList->At( pos )->Tag() == 0 ) )
+ {
+ TASN1DecGeneric extens( tbsCertList->At( pos )->GetContentDER() );
+ extens.InitL();
+ params->iExtensions = DecodeExtensionsL( &extens );
+ }
+
+ CleanupStack::PopAndDestroy( tbsCertList );
+
+ // decode signature algorithm,
+ // just check that it is same as
+ // already set one
+ signAlg = CCMSX509AlgorithmIdentifier::NewL();
+ CleanupStack::PushL( signAlg );
+ signAlg->DecodeL( certificateList->At( 1 )->Encoding() );
+ if( !( signAlg->AlgorithmIdentifier() ==
+ params->iSignatureAlgorithm->AlgorithmIdentifier() ) )
+ {
+ User::Leave( KErrArgument );
+ }
+ CleanupStack::PopAndDestroy( signAlg );
+
+ // decode signature
+ TASN1DecBitString signature;
+ params->iSignature = signature.ExtractOctetStringL( *certificateList->At( 2 ) );
+ CleanupStack::PopAndDestroy( certificateList );
+
+ delete iParams;
+ iParams = params;
+ CleanupStack::Pop( params );
+ }
+// -----------------------------------------------------------------------------
+// CCMSX509CertificateList::DecodeExtensionsL
+// Decodes Extensions
+// -----------------------------------------------------------------------------
+CArrayPtrFlat<CX509CertExtension>* CCMSX509CertificateList::DecodeExtensionsL(
+ const TASN1DecGeneric* aExtensions )
+ {
+ CArrayPtr<TASN1DecGeneric>* extens =
+ DecodeSequenceLC( aExtensions->Encoding() );
+ TInt extensionCount = extens->Count();
+ CArrayPtrFlat< CX509CertExtension >* tmpExtensions =
+ new(ELeave)CArrayPtrFlat< CX509CertExtension >( KDefaultGranularity );
+ CleanupStack::PushL( tmpExtensions );
+ CleanupResetAndDestroyPushL( *tmpExtensions );
+ for( TInt j = 0; j < extensionCount; j++ )
+ {
+ CX509CertExtension* extension =
+ CX509CertExtension::NewLC( extens->At( j )->Encoding() );
+ tmpExtensions->AppendL( extension );
+ CleanupStack::Pop( extension );
+ }
+ CleanupStack::Pop( tmpExtensions ); // ResetAndDestroy
+ CleanupStack::Pop( tmpExtensions ); // normal cleanup
+ CleanupStack::PopAndDestroy( extens );
+ return tmpExtensions;
+ }
+
+// -----------------------------------------------------------------------------
+// CCMSX509CertificateList::EncoderLC
+// Returns ASN1 encoder for this instance
+// -----------------------------------------------------------------------------
+
+CASN1EncBase* CCMSX509CertificateList::EncoderLC() const
+ {
+ CASN1EncSequence* root = CASN1EncSequence::NewLC();
+
+ // encoding tbsCertList
+ CASN1EncSequence* tbsCertList = CASN1EncSequence::NewLC();
+
+ // encoding version
+ CASN1EncInt* version = CASN1EncInt::NewLC( KDefaultVersion );
+ tbsCertList->AddAndPopChildL( version );
+
+ // encoding signature
+ HBufC8* signDes;
+ iParams->iSignatureAlgorithm->EncodeL( signDes );
+ CleanupStack::PushL( signDes );
+ CASN1EncEncoding* signatureEnc =
+ CASN1EncEncoding::NewLC( *signDes );
+ tbsCertList->AddAndPopChildL( signatureEnc );
+ CleanupStack::PopAndDestroy( signDes );
+
+ // encoding issuer
+ CASN1EncSequence* issuer = iParams->iIssuer->EncodeASN1LC();
+ tbsCertList->AddAndPopChildL( issuer );
+
+ // encoding thisUpdate
+ CASN1EncBase* thisUpdate =
+ TCMSTimeUtil::ConvertToEncoderLC( iParams->iThisUpdate );
+ tbsCertList->AddAndPopChildL( thisUpdate );
+
+ // encoding nextUpdate
+ CASN1EncBase* nextUpdate =
+ TCMSTimeUtil::ConvertToEncoderLC( iParams->iNextUpdate );
+ tbsCertList->AddAndPopChildL( nextUpdate );
+
+ // encoding possible revokedCerts
+ if( iParams->iRevokedCertificates &&
+ iParams->iRevokedCertificates->Count() )
+ {
+ CASN1EncSequence* revokedCerts = CASN1EncSequence::NewLC();
+ TInt numOfRevokedCerts = iParams->iRevokedCertificates->Count();
+
+ for( TInt i = 0; i < numOfRevokedCerts; i++ )
+ {
+ // encoding certificate
+ CASN1EncSequence* revokedCertificate = CASN1EncSequence::NewLC();
+
+ CCMSX509RevokedCertificate* cert = iParams->iRevokedCertificates->At( i );
+ // encoding serial number
+ CASN1EncInt* serialEnc =
+ CASN1EncInt::NewLC( cert->iUserCertificateSerialNumber );
+ revokedCertificate->AddAndPopChildL( serialEnc );
+
+ // encoding revocationDate
+ CASN1EncBase* revocationDate =
+ TCMSTimeUtil::ConvertToEncoderLC( cert->iRevokationDate );
+ revokedCertificate->AddAndPopChildL( revocationDate );
+
+ // encoding possible extensions
+ CASN1EncSequence* extensions = EncodeExtensionsLC( cert->iExtensions );
+ if( extensions )
+ {
+ revokedCertificate->AddAndPopChildL( extensions );
+ }
+ revokedCerts->AddAndPopChildL( revokedCertificate );
+ }
+ tbsCertList->AddAndPopChildL( revokedCerts );
+ }
+
+ // encoding possible extensions
+ CASN1EncSequence* ext = EncodeExtensionsLC( iParams->iExtensions );
+ if( ext )
+ {
+ CleanupStack::Pop( ext );
+ // this will take ownership of the extensions
+ // tagging extensions with value 0
+ CASN1EncExplicitTag* explExt =
+ CASN1EncExplicitTag::NewLC( ext, 0 );
+ tbsCertList->AddAndPopChildL( explExt );
+ }
+
+ root->AddAndPopChildL( tbsCertList );
+
+ // encoding signatureValue
+ iParams->iSignatureAlgorithm->EncodeL( signDes );
+ CleanupStack::PushL( signDes );
+ signatureEnc =
+ CASN1EncEncoding::NewLC( *signDes );
+ root->AddAndPopChildL( signatureEnc );
+ CleanupStack::PopAndDestroy( signDes );
+
+ // encoding signature
+ CASN1EncBitString* signatureBitString =
+ CASN1EncBitString::NewLC( *iParams->iSignature );
+ root->AddAndPopChildL( signatureBitString );
+
+ return root;
+ }
+
+// -----------------------------------------------------------------------------
+// CCMSX509CertificateList::EncodeExtensionsLC
+// Encodes Extensions
+// -----------------------------------------------------------------------------
+CASN1EncSequence* CCMSX509CertificateList::EncodeExtensionsLC(
+ const CArrayPtrFlat<CX509CertExtension>* aExtensions ) const
+ {
+ CASN1EncSequence* extensionsEnc = NULL;
+ if( aExtensions &&
+ ( aExtensions->Count() > 0 ) )
+ {
+ TInt extensionCount = aExtensions->Count();
+ extensionsEnc = CASN1EncSequence::NewLC();
+ for( TInt i = 0; i < extensionCount; i++ )
+ {
+ CASN1EncSequence* extEnc = CASN1EncSequence::NewLC();
+ CX509CertExtension* extension = aExtensions->At( i );
+ // encoding id
+ CASN1EncObjectIdentifier* id =
+ CASN1EncObjectIdentifier::NewLC( extension->Id() );
+ extEnc->AddAndPopChildL( id );
+
+ // encoding possible critical flag
+ if( extension->Critical() )
+ {
+ CASN1EncBoolean* critical =
+ CASN1EncBoolean::NewLC( ETrue );
+ extEnc->AddAndPopChildL( critical );
+ }
+ // encoding data, have to decode it before encoding it again
+ // because CASN1EncEncoding changes TagType to Constructed
+ TASN1DecOctetString dataDec;
+ TInt pos = 0;
+ HBufC8* data = dataDec.DecodeDERL( extension->Data(), pos );
+ CleanupStack::PushL( data );
+ CASN1EncOctetString* dataEnc =
+ CASN1EncOctetString::NewLC( *data );
+ extEnc->AddAndPopChildL( dataEnc );
+ CleanupStack::PopAndDestroy( data );
+
+ extensionsEnc->AddAndPopChildL( extEnc );
+ }
+ }
+ return extensionsEnc;
+ }
+
+// -----------------------------------------------------------------------------
+// CCMSX509CertificateList::Parameters
+// Getter for Signing Certificate
+// -----------------------------------------------------------------------------
+EXPORT_C const CCMSX509CertificateListParameters&
+ CCMSX509CertificateList::Parameters() const
+ {
+ return *iParams;
+ }
+
+// -----------------------------------------------------------------------------
+// CCMSX509CertificateList::SetParametersL
+// Setter for signing certificate, takes ownership
+// -----------------------------------------------------------------------------
+EXPORT_C void CCMSX509CertificateList::SetParametersL(
+ CCMSX509CertificateListParameters& aParameters )
+ {
+ // some sanity checks
+ if( !aParameters.iIssuer ||
+ !aParameters.iSignature ||
+ !aParameters.iSignatureAlgorithm ||
+ ( aParameters.iVersion != KDefaultVersion ) )
+ {
+ User::Leave( KErrArgument );
+ }
+ delete iParams;
+ iParams = &aParameters;
+ }
+
+// End of File