--- a/cryptoservices/certificateandkeymgmt/x509/x509cert.cpp Tue Jul 21 01:04:32 2009 +0100
+++ b/cryptoservices/certificateandkeymgmt/x509/x509cert.cpp Thu Sep 10 14:01:51 2009 +0300
@@ -1,1248 +1,1248 @@
-/*
-* Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
-* All rights reserved.
-* This component and the accompanying materials are made available
-* under the terms of the License "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:
-* -- FingerPrint Note:
-* Developers have to be aware that if they are going to change the fingerprint for this certificate
-* for a different hash, then there are other places that need to reflect this change
-* -- Location
-* void CX509Certificate::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
-* EXPORT_C void CX509Certificate::InternalizeL(RReadStream& aStream)
-* Also change the CWTLSCertificate and search for other occurences of the current
-* hash.
-* -- TeletexString type support Note:
-* If the certificate has decoded the members from TeletexString then the return value
-* may be incorrect because TeletexString type is not fully supported by this library.
-* Instead the decode methods perform a direct conversion from 8 to 16bits by adding
-* null characters in the second byte of each character. This will work as expected
-* for cases where the string contains ASCII data.
-*
-*/
-
-
-
-
-#include <x509cert.h>
-#include <x509certext.h>
-#include "X509time.h"
-#include <x509keys.h>
-#include <keyidentifierutil.h>
-#include <asn1enc.h>
-#include <asn1dec.h>
-
-EXPORT_C CPKCS1SignatureResult* CPKCS1SignatureResult::NewL(const CAlgorithmIdentifier& aDigestAlgorithm, const TDesC8& aDigest)
- {
- CPKCS1SignatureResult* self = CPKCS1SignatureResult::NewLC(aDigestAlgorithm, aDigest);
- CleanupStack::Pop();
- return self;
- }
-
-EXPORT_C CPKCS1SignatureResult* CPKCS1SignatureResult::NewLC(const CAlgorithmIdentifier& aDigestAlgorithm, const TDesC8& aDigest)
- {
- CPKCS1SignatureResult* self = new(ELeave) CPKCS1SignatureResult;
- CleanupStack::PushL(self);
- self->ConstructL(aDigestAlgorithm, aDigest);
- return self;
- }
-
-void CPKCS1SignatureResult::ConstructL(const CAlgorithmIdentifier& aDigestAlgorithm, const TDesC8& aDigest)
- {
- iDigestAlgorithm = CAlgorithmIdentifier::NewL(aDigestAlgorithm);
- iDigest = aDigest.AllocL();
- }
-
-EXPORT_C TBool CPKCS1SignatureResult::VerifyL(const TDesC8& aResult)
- {
-
- TBool res = EFalse;
- TRAPD(err, res = DoVerifyL(aResult));
- if ((err != KErrNone) && (err != KErrArgument))
- {
- User::Leave(err);
- }
- return res;
- }
-
-TBool CPKCS1SignatureResult::DoVerifyL(const TDesC8& aResult)
- {
- TBool res = EFalse;
- TASN1DecSequence decSeq;
- TInt pos = 0;
- TInt len = aResult.Length();
-
- const CArrayPtrFlat<TASN1DecGeneric>* seq = decSeq.DecodeDERLC(aResult, pos);
- if (seq->Count() == 2)
- {
- const TASN1DecGeneric* gen1 = seq->At(0);
- const TASN1DecGeneric* gen2 = seq->At(1);
- CAlgorithmIdentifier* algId = CX509AlgorithmIdentifier::NewLC(gen1->Encoding());
- HBufC8* digest = gen2->GetContentDER().AllocL();
- if ((*algId == *iDigestAlgorithm) && (*digest == *iDigest) && (pos == len))
- {
- res = ETrue;
- }
- delete digest;
- CleanupStack::PopAndDestroy();
- }
- CleanupStack::PopAndDestroy();
- return res;
- }
-
-
-EXPORT_C CRSAPublicKey* TX509KeyFactory::RSAPublicKeyL(const TDesC8& aEncoding) const
- {
- return CX509RSAPublicKey::NewL(aEncoding);
- }
-
-EXPORT_C CRSASignatureResult* TX509KeyFactory::RSASignatureResultL(const CAlgorithmIdentifier& aDigestAlgorithm, TDesC8& aDigest) const
- {
- return CPKCS1SignatureResult::NewL(aDigestAlgorithm, aDigest);
- }
-
-EXPORT_C CDSAPublicKey* TX509KeyFactory::DSAPublicKeyL(const TDesC8& aParamsEncoding, const TDesC8& aEncoding) const
- {
- return CX509DSAPublicKey::NewL(aParamsEncoding, aEncoding);
- }
-
-EXPORT_C CDSAPublicKey* TX509KeyFactory::DSAPublicKeyL(const CDSAParameters& aParams, const TDesC8& aEncoding) const
- {
- return CX509DSAPublicKey::NewL(aParams, aEncoding);
- }
-
-
-EXPORT_C CDSASignature* TX509KeyFactory::DSASignatureL(const TDesC8& aEncoding) const
- {
- return CX509DSASignature::NewL(aEncoding);
- }
-
-EXPORT_C CDSAParameters* TX509KeyFactory::DSAParametersL(const TDesC8& aParamsEncoding) const
-{
- return (CX509DSAPublicKey::DSAParametersL(aParamsEncoding));
-}
-
-//CX509ValidityPeriod
-EXPORT_C CX509ValidityPeriod* CX509ValidityPeriod::NewL(const TDesC8& aBinaryData)
- {
- TInt pos = 0;
- return CX509ValidityPeriod::NewL(aBinaryData, pos);
- }
-
-EXPORT_C CX509ValidityPeriod* CX509ValidityPeriod::NewLC(const TDesC8& aBinaryData)
- {
- TInt pos = 0;
- return CX509ValidityPeriod::NewLC(aBinaryData, pos);
- }
-
-EXPORT_C CX509ValidityPeriod* CX509ValidityPeriod::NewL(const TDesC8& aBinaryData, TInt& aPos)
- {
- CX509ValidityPeriod* self = CX509ValidityPeriod::NewLC(aBinaryData, aPos);
- CleanupStack::Pop();
- return self;
- }
-
-EXPORT_C CX509ValidityPeriod* CX509ValidityPeriod::NewLC(const TDesC8& aBinaryData, TInt& aPos)
- {
- CX509ValidityPeriod* self = new(ELeave) CX509ValidityPeriod;
- CleanupStack::PushL(self);
- self->ConstructL(aBinaryData, aPos);
- return self;
- }
-
-CX509ValidityPeriod::CX509ValidityPeriod()
- {
- }
-
-void CX509ValidityPeriod::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
- {
- TASN1DecSequence encSeq;
- CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos);
- if (seq->Count() != 2)
- {
- User::Leave(KErrArgument);
- }
- TASN1DecX509Time decTime;
- iStart = decTime.DecodeDERL(*(seq->At(0)));
- iFinish = decTime.DecodeDERL(*(seq->At(1)));
- CleanupStack::PopAndDestroy();//seq + contents
- }
-
-//algorithm id
-EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewL(const TDesC8& aBinaryData)
- {
- TInt pos = 0;
- return CX509AlgorithmIdentifier::NewL(aBinaryData, pos);
- }
-
-EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewLC(const TDesC8& aBinaryData)
- {
- TInt pos = 0;
- return CX509AlgorithmIdentifier::NewLC(aBinaryData, pos);
- }
-
-EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewL(const TDesC8& aBinaryData, TInt& aPos)
- {
- CX509AlgorithmIdentifier* self = CX509AlgorithmIdentifier::NewLC(aBinaryData, aPos);
- CleanupStack::Pop();
- return self;
- }
-
-EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewLC(const TDesC8& aBinaryData, TInt& aPos)
- {
- CX509AlgorithmIdentifier* self = new(ELeave) CX509AlgorithmIdentifier;
- CleanupStack::PushL(self);
- self->InitializeL(aBinaryData, aPos);
- return self;
- }
-
-EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewL(TAlgorithmId aAlgorithmId, const TDesC8& aEncodedParams)
- {
- CX509AlgorithmIdentifier* self = CX509AlgorithmIdentifier::NewLC(aAlgorithmId, aEncodedParams);
- CleanupStack::Pop();
- return self;
- }
-
-EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewLC(TAlgorithmId aAlgorithmId, const TDesC8& aEncodedParams)
- {
- CX509AlgorithmIdentifier* self = new(ELeave) CX509AlgorithmIdentifier(aAlgorithmId);
- CleanupStack::PushL(self);
- self->ConstructL(aEncodedParams);
- return self;
- }
-
-CX509AlgorithmIdentifier::CX509AlgorithmIdentifier(TAlgorithmId& aAlgorithmId):CAlgorithmIdentifier(aAlgorithmId)
- {
- }
-
-
-CX509AlgorithmIdentifier::CX509AlgorithmIdentifier()
- {
- }
-
-void CX509AlgorithmIdentifier::InitializeL(const TDesC8& aBinaryData, TInt& aPos)
- {
- TASN1DecSequence encSeq;
- CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 1, KMaxTInt);
- TInt count = seq->Count();
- TASN1DecObjectIdentifier encOID;
- HBufC* oid = encOID.DecodeDERL(*(seq->At(0)));
- CleanupStack::PushL(oid);
- TPtrC oidDes(oid->Des());
- if (oidDes == KDSA)
- {
- //optional params
- if (count > 1)//if we still have stuff left
- {
- TASN1DecGeneric* gen = seq->At(1);
- iEncodedParams = gen->Encoding().AllocL();
- }
- else
- {
- iEncodedParams = HBufC8::NewL(1);
- *iEncodedParams = KNullDesC8;
- }
- iAlgorithmId = EDSA;
- CleanupStack::PopAndDestroy(2);//seq, oid
- return;
- }
- if (count > 1)
- {
- TASN1DecGeneric* gen = seq->At(1);
- if (oidDes == KDH)
- {
- iEncodedParams = gen->Encoding().AllocL();
- iAlgorithmId = EDH;
- CleanupStack::PopAndDestroy(2);//seq, oid
- return;
- }
- if (oidDes == KRSA)
- {
- iAlgorithmId = ERSA;
- TASN1DecNull null;
- null.DecodeDERL(*gen);//just to check the syntax is OK
- iEncodedParams = HBufC8::NewL(1);
- *iEncodedParams = KNullDesC8;
- CleanupStack::PopAndDestroy(2);//seq, oid
- return;
- }
- if (oidDes == KMD5)
- {
- iAlgorithmId = EMD5;
- TASN1DecNull null;
- null.DecodeDERL(*gen);//just to check the syntax is OK
- iEncodedParams = HBufC8::NewL(1);
- *iEncodedParams = KNullDesC8;
- CleanupStack::PopAndDestroy(2);//seq, oid
- return;
- }
- if (oidDes == KMD2)
- {
- iAlgorithmId = EMD2;
- TASN1DecNull null;
- null.DecodeDERL(*gen);//just to check the syntax is OK
- iEncodedParams = HBufC8::NewL(1);
- *iEncodedParams = KNullDesC8;
- CleanupStack::PopAndDestroy(2);//seq, oid
- return;
- }
- if (oidDes == KSHA1)
- {
- iAlgorithmId = ESHA1;
- TASN1DecNull null;
- null.DecodeDERL(*gen);//just to check the syntax is OK
- iEncodedParams = HBufC8::NewL(1);
- *iEncodedParams = KNullDesC8;
- CleanupStack::PopAndDestroy(2);//seq, oid
- return;
- }
- }
- User::Leave(KErrNotSupported);
- }
-
-EXPORT_C CASN1EncSequence* CX509AlgorithmIdentifier::EncodeASN1DERLC() const
- {
- // the root sequence contains the signed object
- CASN1EncSequence* root = CASN1EncSequence::NewLC();
-
- //encode the oid
- CASN1EncObjectIdentifier* oid(NULL);
- switch (iAlgorithmId)
- {
- case EDSA:
- oid=CASN1EncObjectIdentifier::NewLC(KDSA);
- break;
-
- case EDH:
- oid=CASN1EncObjectIdentifier::NewLC(KDH);
- break;
-
- case ERSA:
- oid=CASN1EncObjectIdentifier::NewLC(KRSA);
- break;
-
- case EMD5:
- oid=CASN1EncObjectIdentifier::NewLC(KMD5);
- break;
-
- case EMD2:
- oid=CASN1EncObjectIdentifier::NewLC(KMD2);
- break;
-
- case ESHA1:
- oid=CASN1EncObjectIdentifier::NewLC(KSHA1);
- break;
-
- default:
- User::Leave(KErrNotSupported);
- }
-
- root->AddAndPopChildL(oid);
-
- //Encode parameters
- if (*iEncodedParams!=KNullDesC8)
- {
- CASN1EncEncoding* enc=CASN1EncEncoding::NewLC(*iEncodedParams);
- root->AddAndPopChildL(enc);
- }
- else
- {
- if (iAlgorithmId!=EDSA)
- {
- CASN1EncNull* enc=CASN1EncNull::NewLC();
- root->AddAndPopChildL(enc);
- }
- }
-
- return root;
- }
-
-
-//signing algorithm id
-EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewL(const TDesC8& aBinaryData)
- {
- TInt pos = 0;
- return CX509SigningAlgorithmIdentifier::NewL(aBinaryData, pos);
- }
-
-EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewLC(const TDesC8& aBinaryData)
- {
- TInt pos = 0;
- return CX509SigningAlgorithmIdentifier::NewLC(aBinaryData, pos);
- }
-
-EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewL(const TDesC8& aBinaryData, TInt& aPos)
- {
- CX509SigningAlgorithmIdentifier* self = CX509SigningAlgorithmIdentifier::NewLC(aBinaryData, aPos);
- CleanupStack::Pop();
- return self;
- }
-
-EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewLC(const TDesC8& aBinaryData, TInt& aPos)
- {
- CX509SigningAlgorithmIdentifier* self = new(ELeave) CX509SigningAlgorithmIdentifier;
- CleanupStack::PushL(self);
- self->ConstructL(aBinaryData, aPos);
- return self;
- }
-
-EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewL(const CAlgorithmIdentifier& aAsymmetricAlgorithm, const CAlgorithmIdentifier& aDigestAlgorithm)
- {
- CX509SigningAlgorithmIdentifier* self = CX509SigningAlgorithmIdentifier::NewLC(aAsymmetricAlgorithm, aDigestAlgorithm);
- CleanupStack::Pop();
- return self;
- }
-
-EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewLC(const CAlgorithmIdentifier& aAsymmetricAlgorithm, const CAlgorithmIdentifier& aDigestAlgorithm)
- {
- CX509SigningAlgorithmIdentifier* self = new(ELeave) CX509SigningAlgorithmIdentifier;
- CleanupStack::PushL(self);
- self->ConstructL(aAsymmetricAlgorithm, aDigestAlgorithm);
- return self;
- }
-
-CX509SigningAlgorithmIdentifier::CX509SigningAlgorithmIdentifier()
- {
- }
-
-void CX509SigningAlgorithmIdentifier::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
- {
- TASN1DecSequence encSeq;
- CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 1, KMaxTInt);
- TInt count = seq->Count();
- TASN1DecObjectIdentifier encOID;
- HBufC* oid = encOID.DecodeDERL(*(seq->At(0)));
- CleanupStack::PushL(oid);
- TPtrC oidDes(oid->Des());
- //none of the signing algorithms we support have parameters here...
- HBufC8* encodedParams = HBufC8::NewLC(1);
- *encodedParams = KNullDesC8;
-
- if (oidDes == KDSAWithSHA1)
- {
- //should be no params, but we allow params encoded as NULL for interop reasons
- TAlgorithmId algId = EDSA;
- TAlgorithmId digestId = ESHA1;
- iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
- iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
- if (count == 1)
- {
- CleanupStack::PopAndDestroy(3);//seq, oid, encodedParams
- return;
- }
- }
-
- if (oidDes == KMD2WithRSA)
- {
- TAlgorithmId algId = ERSA;
- TAlgorithmId digestId = EMD2;
- iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
- iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
- }
-
- if (oidDes == KMD5WithRSA)
- {
- TAlgorithmId algId = ERSA;
- TAlgorithmId digestId = EMD5;
- iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
- iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
- }
-
- if (oidDes == KSHA1WithRSA)
- {
- TAlgorithmId algId = ERSA;
- TAlgorithmId digestId = ESHA1;
- iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
- iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
- }
- //???not sure if we should just leave here...
- if (iDigestAlgorithm == NULL)
- {
- User::Leave(KErrNotSupported);
- }
- else
- {
- if (count != 2)
- {
- // Shouldn't ever get here, since RFC2459 mandates having 2
- // data items. However, some people miss out the second
- // when it's NULL, so we'll not report and error here
- }
- else
- {
- TASN1DecGeneric* gen = seq->At(1);
- TASN1DecNull null;
- null.DecodeDERL(*gen);//just to check the syntax is OK
- }
- }
- CleanupStack::PopAndDestroy(3);//seq, oid, encodedParams
- }
-
-void CX509SigningAlgorithmIdentifier::ConstructL(const CAlgorithmIdentifier& aAsymmetricAlgorithm, const CAlgorithmIdentifier& aDigestAlgorithm)
- {
- iDigestAlgorithm = CAlgorithmIdentifier::NewL(aDigestAlgorithm);
- iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(aAsymmetricAlgorithm);
- };
-
-//subject public key info
-EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewL(const TDesC8& aBinaryData, TInt& aPos)
- {
- CX509SubjectPublicKeyInfo* self = CX509SubjectPublicKeyInfo::NewLC(aBinaryData, aPos);
- CleanupStack::Pop();
- return self;
- }
-
-EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewLC(const TDesC8& aBinaryData, TInt& aPos)
- {
- CX509SubjectPublicKeyInfo* self = new(ELeave) CX509SubjectPublicKeyInfo;
- CleanupStack::PushL(self);
- self->ConstructL(aBinaryData, aPos);
- return self;
- }
-
-EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewL(const TDesC8& aBinaryData)
- {
- TInt pos = 0;
- return CX509SubjectPublicKeyInfo::NewL(aBinaryData, pos);
- }
-
-EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewLC(const TDesC8& aBinaryData)
- {
- TInt pos = 0;
- return CX509SubjectPublicKeyInfo::NewLC(aBinaryData, pos);
- }
-
-CX509SubjectPublicKeyInfo::CX509SubjectPublicKeyInfo()
- {
- }
-
-void CX509SubjectPublicKeyInfo::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
- {
- TASN1DecSequence encSeq;
- CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 2, KMaxTInt);
- iAlgId = CX509AlgorithmIdentifier::NewL(seq->At(0)->Encoding());
- TASN1DecBitString encBS;
- iEncodedKeyData = encBS.ExtractOctetStringL(*(seq->At(1)));
- CleanupStack::PopAndDestroy();//seq
- }
-
-//generic X 509 extension syntax
-EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const CX509CertExtension& aExtension)
- {
- CX509CertExtension* self = CX509CertExtension::NewLC(aExtension);
- CleanupStack::Pop();
- return self;
- }
-
-EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const CX509CertExtension& aExtension)
- {
- CX509CertExtension* self = new(ELeave) CX509CertExtension;
- CleanupStack::PushL(self);
- self->ConstructL(aExtension);
- return self;
- }
-
-EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const TDesC8& aBinaryData, TInt& aPos)
- {
- CX509CertExtension* self = CX509CertExtension::NewLC(aBinaryData, aPos);
- CleanupStack::Pop();
- return self;
- }
-
-EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const TDesC8& aBinaryData, TInt& aPos)
- {
- CX509CertExtension* self = new(ELeave) CX509CertExtension;
- CleanupStack::PushL(self);
- self->ConstructL(aBinaryData, aPos);
- return self;
- }
-
-EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const TDesC8& aBinaryData)
- {
- TInt pos = 0;
- return CX509CertExtension::NewL(aBinaryData, pos);
- }
-
-EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const TDesC8& aBinaryData)
- {
- TInt pos = 0;
- return CX509CertExtension::NewLC(aBinaryData, pos);
- }
-
-EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const TDesC& aCertExtOID,
- const TBool aCritical,
- const TDesC8& aCertExtValue)
- {
- CX509CertExtension* self = CX509CertExtension::NewLC(aCertExtOID, aCritical, aCertExtValue);
- CleanupStack::Pop();
- return self;
- }
-
-EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const TDesC& aCertExtOID,
- const TBool aCritical,
- const TDesC8& aCertExtValue)
- {
- CX509CertExtension* self = new(ELeave) CX509CertExtension;
- CleanupStack::PushL(self);
- self->ConstructL(aCertExtOID, aCritical, aCertExtValue);
- return self;
- }
-
-void CX509CertExtension::ConstructL(const CX509CertExtension& aExtension)
- {
- iCritical = aExtension.iCritical;
- iId = aExtension.iId->Des().AllocL();
- iData = aExtension.iData->Des().AllocL();
- }
-
-void CX509CertExtension::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
- {
- TASN1DecSequence encSeq;
- CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 2, KMaxTInt);
-
- TASN1DecObjectIdentifier encOID;
- iId = encOID.DecodeDERL(*(seq->At(0)));
- //second is either critical flag, or the ext
- TASN1DecGeneric* second = seq->At(1);
- if (second->Tag() != EASN1Boolean)
- {
- iData = second->Encoding().AllocL();
- aPos += second->LengthDER();
- }
- else
- {
- TASN1DecBoolean encBool;
- iCritical = encBool.DecodeDERL(*second);
- if (seq->Count() != 3)
- {
- User::Leave(KErrArgument);
- }
-
- TASN1DecGeneric* third = seq->At(2);
- iData = third->Encoding().AllocL();
- }
- CleanupStack::PopAndDestroy();//seq
- }
-
-void CX509CertExtension::ConstructL(const TDesC& aCertExtOID,
- const TBool aCritical,
- const TDesC8& aCertExtValue)
- {
- iId = aCertExtOID.AllocL();
- iCritical = aCritical;
- iData = aCertExtValue.AllocL();
- }
-
-EXPORT_C CX509CertExtension::~CX509CertExtension()
- {
- delete iData;
- delete iId;
- }
-
-EXPORT_C TBool CX509CertExtension::Critical() const
- {
- return iCritical;
- }
-
-EXPORT_C TPtrC CX509CertExtension::Id() const //OID for the extension
- {
- return iId->Des();
- }
-
-EXPORT_C TPtrC8 CX509CertExtension::Data() const //the extension itself
- {
- return iData->Des();
- }
-
-EXPORT_C CASN1EncSequence* CX509CertExtension::EncodeASN1DERLC() const
- {
- CASN1EncSequence *result = CASN1EncSequence::NewLC();
- CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(*iId);
- result->AddAndPopChildL(oid);
- // Encode critical flag only if true
- if (iCritical)
- {
- CASN1EncBoolean *critical = CASN1EncBoolean::NewLC(iCritical);
- result->AddAndPopChildL(critical);
- }
- CASN1EncOctetString *data = CASN1EncOctetString::NewLC(*iData);
- result->AddAndPopChildL(data);
- return result;
- }
-
-CX509CertExtension::CX509CertExtension()
- :iCritical(EFalse)
- {
- }
-
-//CX509Certificate
-EXPORT_C CX509Certificate* CX509Certificate::NewL(const CX509Certificate& aCert)
- {
- CX509Certificate* self = CX509Certificate::NewLC(aCert);
- CleanupStack::Pop();//self
- return self;
- }
-
-EXPORT_C CX509Certificate* CX509Certificate::NewLC(const CX509Certificate& aCert)
- {
- CX509Certificate* self = new(ELeave) CX509Certificate;
- CleanupStack::PushL(self);
- self->ConstructL(aCert);
- return self;
- }
-
-EXPORT_C CX509Certificate* CX509Certificate::NewL(const TDesC8& aBinaryData)
- {
- TInt pos = 0;
- return CX509Certificate::NewL(aBinaryData, pos);
- }
-
-EXPORT_C CX509Certificate* CX509Certificate::NewLC(const TDesC8& aBinaryData)
- {
- TInt pos = 0;
- return CX509Certificate::NewLC(aBinaryData, pos);
- }
-
-EXPORT_C CX509Certificate* CX509Certificate::NewL(const TDesC8& aBinaryData, TInt& aPos)
- {
- CX509Certificate* self = CX509Certificate::NewLC(aBinaryData, aPos);
- CleanupStack::Pop();
- return self;
- }
-
-EXPORT_C CX509Certificate* CX509Certificate::NewLC(const TDesC8& aBinaryData, TInt& aPos)
- {
- CX509Certificate* self = new(ELeave) CX509Certificate();
- CleanupStack::PushL(self);
- self->ConstructL(aBinaryData, aPos);
- return self;
- }
-
-EXPORT_C CX509Certificate* CX509Certificate::NewL(RReadStream& aStream)
- {
- CX509Certificate* self = CX509Certificate::NewLC(aStream);
- CleanupStack::Pop();//self
- return self;
- }
-
-EXPORT_C CX509Certificate* CX509Certificate::NewLC(RReadStream& aStream)
- {
- CX509Certificate* self = new(ELeave) CX509Certificate;
- CleanupStack::PushL(self);
- self->InternalizeL(aStream);
- return self;
- }
-
-void CX509Certificate::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
- {
- TASN1DecGeneric gen(aBinaryData.Right(aBinaryData.Length() - aPos));
- gen.InitL();
-
- // The outermost tag for X509 certificates is always a sequence.
- // Since this tag does not form part of the signed data it is possible
- // to corrupt the tag by changing it to any other ASN.1 tag and process
- // the rest of the certificate as normal.
- // However, we still reject the certificate anyway to avoid
- // confusion because the data does not match the X.509 specification.
- if (gen.Tag() != EASN1Sequence)
- {
- User::Leave(KErrArgument);
- }
-
- aPos += gen.LengthDER();
- iKeyFactory = new(ELeave) TX509KeyFactory;
-
- iEncoding = gen.Encoding().AllocL();
-
- TASN1DecSequence encSeq;
- TInt pos = 0;
- CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(*iEncoding, pos, 3, 3);
- TASN1DecGeneric* encSigAlg = seq->At(1);
- iSigningAlgorithm = CX509SigningAlgorithmIdentifier::NewL(encSigAlg->Encoding());
- TASN1DecBitString encBS;
- iSignature = encBS.ExtractOctetStringL(*(seq->At(2)));
- CleanupStack::PopAndDestroy();//seq
-
- CSHA1* hash = CSHA1::NewL();
- CleanupStack::PushL(hash);
- iFingerprint = hash->Final(Encoding()).AllocL();
- CleanupStack::PopAndDestroy();//hash
- ConstructCertL();
- }
-
-void CX509Certificate::ConstructL(const CX509Certificate& aCertificate)
- {
- iKeyFactory = new(ELeave) TX509KeyFactory;
-
- iEncoding = aCertificate.iEncoding->AllocL();
- iSignature = aCertificate.iSignature->AllocL();
- iFingerprint = aCertificate.iFingerprint->AllocL();
- iSigningAlgorithm = CSigningAlgorithmIdentifier::NewL(aCertificate.SigningAlgorithm());
- iSerialNumber = aCertificate.iSerialNumber->Des().AllocL();
- iIssuerName = CX500DistinguishedName::NewL(*(aCertificate.iIssuerName));
- iValidityPeriod = new(ELeave) CValidityPeriod(*(aCertificate.iValidityPeriod));
- iSubjectName = CX500DistinguishedName::NewL(*(aCertificate.iSubjectName));
- iSubjectPublicKeyInfo = CSubjectPublicKeyInfo::NewL(*(aCertificate.iSubjectPublicKeyInfo));
- iIssuerUid = aCertificate.iIssuerUid->Des().AllocL();
- iSubjectUid = aCertificate.iSubjectUid->Des().AllocL();
- iExtensions = new(ELeave) CArrayPtrFlat<CX509CertExtension> (1);
- TInt count = aCertificate.iExtensions->Count();
- for (TInt i = 0; i < count; i++)
- {
- CX509CertExtension* ext = CX509CertExtension::NewLC(*aCertificate.iExtensions->At(i));
- iExtensions->AppendL(ext);
- CleanupStack::Pop();//ext
- }
- iVersion = aCertificate.Version();
- InitDataElementsL(aCertificate);
- }
-
-void CX509Certificate::InitDataElementsL(const CX509Certificate& aCertificate)
- {
- iDataElements = new(ELeave) TFixedArray<TPtrC8*, KX509MaxDataElements>;
- iDataElements->Reset();
- TPtrC8 signedData = SignedDataL();
- TASN1DecSequence encSeq;
- TInt pos = 0;
- CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(signedData, pos, 6, KMaxTInt);//6 is the minimum number of elements in an x509 cert
- pos = 0;
-
- TPtrC8** pElement = iDataElements->Begin();
- *pElement++ = aCertificate.DataElementEncoding(CX509Certificate::EVersionNumber)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
- for (TInt i = 0; i < 6; i++) //init all the non-optional elements
- {
- *pElement++ = new(ELeave) TPtrC8(seq->At(pos++)->Encoding());
- }
- *pElement++ = aCertificate.DataElementEncoding(CX509Certificate::EIssuerUID)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
- *pElement++ = aCertificate.DataElementEncoding(CX509Certificate::ESubjectUID)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
- *pElement++ = aCertificate.DataElementEncoding(CX509Certificate::EExtensionList)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
- CleanupStack::PopAndDestroy();
- }
-
-void CX509Certificate::ConstructCertL()
- {
- TPtrC8 signedData = SignedDataL();
- TASN1DecSequence encSeq;
- TInt pos = 0;
- CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(signedData, pos, 6, KMaxTInt);//6 is the minimum number of elements in an x509 cert
- TInt count = seq->Count();
- pos = 0;
- TASN1DecGeneric* curr = seq->At(pos);
- pos++;
- iDataElements = new(ELeave) TFixedArray<TPtrC8*, KX509MaxDataElements>;
- iDataElements->Reset();
- TPtrC8** pElement = iDataElements->Begin();
- if ((curr->Class() == EContextSpecific) && (curr->Tag() == 0))
- {
- //version!
- TASN1DecGeneric ver(curr->GetContentDER());
- ver.InitL();
- TPtrC8 pVer8 = ver.GetContentDER();
- if(pVer8.Length() != 1)
- {
- User::Leave(KErrArgument);
- }
- iVersion = (pVer8[0]) + 1;
- if ((iVersion < 1) || (iVersion > 3) || (count < 7))
- {
- User::Leave(KErrArgument);
- }
- *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
- curr = seq->At(pos);
- pos++;
- }
- else
- {
- *pElement++ = NULL;
- }
- if (curr->Tag() != EASN1Integer)
- {
- User::Leave(KErrArgument);
- }
- iSerialNumber = (curr->GetContentDER()).AllocL();
- *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
- curr = seq->At(pos);
- pos++;
- CX509SigningAlgorithmIdentifier* algorithmId = CX509SigningAlgorithmIdentifier::NewLC(curr->Encoding());
- if (!(SigningAlgorithm() == *(algorithmId)))
- {
- User::Leave(KErrArgument);
- }
- CleanupStack::PopAndDestroy();//algorithmId
- *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
-
- curr = seq->At(pos);
- pos++;
- iIssuerName = CX500DistinguishedName::NewL(curr->Encoding());
- *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
- curr = seq->At(pos);
- pos++;
- iValidityPeriod = CX509ValidityPeriod::NewL(curr->Encoding());
- *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
- curr = seq->At(pos);
- pos++;
- iSubjectName = CX500DistinguishedName::NewL(curr->Encoding());
- *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
- curr = seq->At(pos);
- pos++;
- iSubjectPublicKeyInfo = CX509SubjectPublicKeyInfo::NewL(curr->Encoding());
- *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
- //do issuer uid, subject uid, exts
- //these are all optional
- TBool hasIssuerUid = EFalse;
- TBool hasSubjectUid = EFalse;
- TBool hasExts = EFalse;
- iExtensions = new(ELeave)CArrayPtrFlat<CX509CertExtension> (1);
- if (pos < count)//otherwise there aren't any of 'em
- {
- curr = seq->At(pos);
- pos++;
- if (curr->Class() != EContextSpecific)
- {
- User::Leave(KErrArgument);
- }
- switch(curr->Tag())
- {
- case 1:
- {
- iIssuerUid = DecodeUidL(curr->GetContentDER(), hasIssuerUid);
- *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
- break;
- }
- case 2:
- {
- iSubjectUid = DecodeUidL(curr->GetContentDER(), hasSubjectUid);
- *pElement++ = NULL;
- *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
- break;
- }
- case 3:
- {
- DecodeExtsL(curr->GetContentDER(), hasExts);
- *pElement++ = NULL;
- *pElement++ = NULL;
- *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
- break;
- }
- default:
- {
- User::Leave(KErrArgument);
- }
- }
- if (pos < count)
- {
- curr = seq->At(pos);
- pos++;
- switch(curr->Tag())
- {
- case 2:
- {
- iSubjectUid = DecodeUidL(curr->GetContentDER(), hasSubjectUid);
- *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
- break;
- }
- case 3:
- {
- DecodeExtsL(curr->GetContentDER(), hasExts);
- *pElement++ = NULL;
- *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
- break;
- }
- default:
- {
- User::Leave(KErrArgument);
- }
- }
- if (pos < count)
- {
- curr = seq->At(pos);
- pos++;
- if (curr->Tag() == 3)
- {
- DecodeExtsL(curr->GetContentDER(), hasExts);
- *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
- }
- else
- {
- User::Leave(KErrArgument);
- }
- }
- }
- }
- if (pos != count)
- {
- User::Leave(KErrArgument);
- }
- if (!iIssuerUid)
- {
- iIssuerUid = HBufC8::NewL(1);
- *iIssuerUid = KNullDesC8;
- }
- if (!iSubjectUid)
- {
- iSubjectUid = HBufC8::NewL(1);
- *iSubjectUid = KNullDesC8;
- }
-
- // we have not checked for the certificate version number based on
- // the certificate contents. This is primarily done to avoid BC for
- // clients who are still using malformed certificates.
-
- CleanupStack::PopAndDestroy();//seq
- }
-
-CX509Certificate::CX509Certificate()
- :iVersion(1)
- {
- }
-
-EXPORT_C CX509Certificate::~CX509Certificate()
- {
- delete iIssuerName;
- delete iSubjectName;
- delete iIssuerUid;
- delete iSubjectUid;
-
- if (iDataElements != NULL)
- {
- for (TInt i = 0; i < KX509MaxDataElements; i++)
- {
- delete iDataElements->At(i);
- }
- delete iDataElements;
- }
- if (iExtensions != NULL)
- {
- iExtensions->ResetAndDestroy();
- }
- delete iExtensions;
- }
-
-EXPORT_C TBool CX509Certificate::IsEqualL(const CX509Certificate& aCert) const
- {
- return ( (*(iSerialNumber) == *(aCert.iSerialNumber)) &&
- (iIssuerName->ExactMatchL(*(aCert.iIssuerName))) );
- }
-
-EXPORT_C void CX509Certificate::InternalizeL(RReadStream& aStream)
- {
- if (iIssuerName != NULL) //just to check cert is uninitialised
- {
- User::Leave(KErrArgument);
- }
- iKeyFactory = new(ELeave) TX509KeyFactory;
-
- TInt len = aStream.ReadInt32L(); //Read the length of the streamed encoding
- HBufC8* temp= HBufC8::NewLC(len);
- TPtr8 ptr=temp->Des();
- aStream.ReadL(ptr,len);
- iEncoding=temp->AllocL();
- CleanupStack::PopAndDestroy(); // temp
-
- TASN1DecSequence encSeq;
- TInt pos = 0;
- CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(*iEncoding, pos, 3, 3);
- TASN1DecGeneric* encSigAlg = seq->At(1);
- iSigningAlgorithm = CX509SigningAlgorithmIdentifier::NewL(encSigAlg->Encoding());
- TASN1DecBitString encBS;
- iSignature = encBS.ExtractOctetStringL(*(seq->At(2)));
- CleanupStack::PopAndDestroy();//seq
-
- CSHA1* hash = CSHA1::NewL();
- CleanupStack::PushL(hash);
- iFingerprint = hash->Final(Encoding()).AllocL();
- CleanupStack::PopAndDestroy();//hash
-
- ConstructCertL();
- }
-
-void CX509Certificate::DecodeExtsL(const TDesC8& aBinaryData, TBool& aHasElementAlready)
- {
- TASN1DecSequence encSeq;
- TInt pos = 0;
- CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, pos);
- TInt count = seq->Count();
- for (TInt i = 0; i < count; i++)
- {
- TASN1DecGeneric* gen = seq->At(i);
- CX509CertExtension* ext = CX509CertExtension::NewLC(gen->Encoding());
- iExtensions->AppendL(ext);
- CleanupStack::Pop();//ext
- }
- CleanupStack::PopAndDestroy();//
- aHasElementAlready = ETrue;
- }
-
-HBufC8* CX509Certificate::DecodeUidL(const TDesC8& aBinaryData, TBool& aHasElementAlready)
- {
- if ((aHasElementAlready) || (iVersion ==1))
- {
- User::Leave(KErrArgument);
- }
- aHasElementAlready = ETrue;
- return aBinaryData.AllocL();
- }
-
-//***************************************************************************************//
-//extra accessors
-EXPORT_C const TPtrC8 CX509Certificate::SignedDataL() const
- {
- TASN1DecSequence encSeq;
- TInt pos = 0;
- CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(*iEncoding, pos, 3, 3);
- TASN1DecGeneric* gen = seq->At(0);
- TPtrC8 res = gen->Encoding();
- CleanupStack::PopAndDestroy();
- return res;
- }
-
-EXPORT_C TInt CX509Certificate::Version() const
- {
- return iVersion;
- }
-
-/**
-* If the certificate has decoded the members from TeletexString then the return value
-* may be incorrect because TeletexString type is not fully supported by this library.
-* Instead the decode methods perform a direct conversion from 8 to 16bits by adding
-* null characters in the second byte of each character. This will work as expected
-* for cases where the string contains ASCII data.
-*/
-EXPORT_C const CX500DistinguishedName& CX509Certificate::IssuerName() const
- {
- return *iIssuerName;
- }
-
-/**
-* If the certificate has decoded the members from TeletexString then the return value
-* may be incorrect because TeletexString type is not fully supported by this library.
-* Instead the decode methods perform a direct conversion from 8 to 16bits by adding
-* null characters in the second byte of each character. This will work as expected
-* for cases where the string contains ASCII data.
-*/
-EXPORT_C const CX500DistinguishedName& CX509Certificate::SubjectName() const
- {
- return *iSubjectName;
- }
-
-EXPORT_C const CArrayPtrFlat<CX509CertExtension>& CX509Certificate::Extensions() const
- {
- return *iExtensions;
- }
-
-EXPORT_C const CX509CertExtension* CX509Certificate::Extension(const TDesC& aExtensionName) const
- {
- TInt count = iExtensions->Count();
- for (TInt i = 0; i < count; i++)
- {
- CX509CertExtension* ext = iExtensions->At(i);
- if (ext->Id() == aExtensionName)
- return ext;
- }
- return NULL;
- }
-
-EXPORT_C const TPtrC8* CX509Certificate::DataElementEncoding(const TUint aIndex) const
- {
- return iDataElements->At(aIndex);
- }
-
-/**
-* If the certificate has decoded the members from TeletexString then the return value
-* may be incorrect because TeletexString type is not fully supported by this library.
-* Instead the decode methods perform a direct conversion from 8 to 16bits by adding
-* null characters in the second byte of each character. This will work as expected
-* for cases where the string contains ASCII data.
-*/
-EXPORT_C HBufC* CX509Certificate::IssuerL() const
- {
- return iIssuerName->DisplayNameL();
- }
-
-/**
-* If the certificate has decoded the members from TeletexString then the return value
-* may be incorrect because TeletexString type is not fully supported by this library.
-* Instead the decode methods perform a direct conversion from 8 to 16bits by adding
-* null characters in the second byte of each character. This will work as expected
-* for cases where the string contains ASCII data.
-*/
-EXPORT_C HBufC* CX509Certificate::SubjectL() const
- {
- return iSubjectName->DisplayNameL();
- }
-
-EXPORT_C TBool CX509Certificate::IsSelfSignedL() const
- {
- if (iSubjectName->Count() > 0)
- {
- return iSubjectName->ExactMatchL(*iIssuerName);
- }
- else
- {
- TBool res = EFalse;
- const CX509CertExtension* subjectExt = Extension(KIssuerAltName);
- const CX509CertExtension* issuerExt = Extension(KSubjectAltName);
- if ((subjectExt) && (issuerExt))
- {
- const CX509AltNameExt* issuerAltName = CX509AltNameExt::NewLC(subjectExt->Data());
- const CX509AltNameExt* subjectAltName = CX509AltNameExt::NewLC(issuerExt->Data());
- if (subjectAltName->Match(*issuerAltName))
- {
- res = ETrue;
- }
- CleanupStack::PopAndDestroy(2);//subjectAltName, issuerAltName
- }
- return res;
- }
- }
-
-
-EXPORT_C TKeyIdentifier CX509Certificate::KeyIdentifierL() const
- {
- if (iSubjectPublicKeyInfo->AlgorithmId() != EDSA)
- {
- // The base class handles the RSA case and leaves with KErrNotSupported if
- // it is not RSA.
- return CCertificate::KeyIdentifierL();
- }
- else
- {
- // This handles the DSA case
- CDSAPublicKey* dsaKey =
- iKeyFactory->DSAPublicKeyL(iSubjectPublicKeyInfo->EncodedParams(),
- iSubjectPublicKeyInfo->KeyData());
- CleanupStack::PushL(dsaKey);
- TKeyIdentifier retVal;
- KeyIdentifierUtil::DSAKeyIdentifierL(*dsaKey, retVal);
- CleanupStack::PopAndDestroy(dsaKey);
- return retVal;
- }
- }
-
-EXPORT_C TKeyIdentifier CX509Certificate::SubjectKeyIdentifierL() const
- {
- const CX509CertExtension* subjectKeyIdExtStr = this->Extension(KSubjectKeyId);
- if (subjectKeyIdExtStr)
- {
- TKeyIdentifier ret;
- CX509SubjectKeyIdExt *subjectKeyIdExt = CX509SubjectKeyIdExt::NewLC(subjectKeyIdExtStr->Data());
- // Currently, we do not support key identifiers larger than 160 bits - make sure not to overflow the descriptor
- if (subjectKeyIdExt->KeyId().Length() <= ret.MaxLength())
- {
- ret.Copy(subjectKeyIdExt->KeyId());
- CleanupStack::PopAndDestroy(subjectKeyIdExt);
- return ret;
- }
- CleanupStack::PopAndDestroy(subjectKeyIdExt);
- }
-
- return KeyIdentifierL();
- }
+/*
+* Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "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:
+* -- FingerPrint Note:
+* Developers have to be aware that if they are going to change the fingerprint for this certificate
+* for a different hash, then there are other places that need to reflect this change
+* -- Location
+* void CX509Certificate::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
+* EXPORT_C void CX509Certificate::InternalizeL(RReadStream& aStream)
+* Also change the CWTLSCertificate and search for other occurences of the current
+* hash.
+* -- TeletexString type support Note:
+* If the certificate has decoded the members from TeletexString then the return value
+* may be incorrect because TeletexString type is not fully supported by this library.
+* Instead the decode methods perform a direct conversion from 8 to 16bits by adding
+* null characters in the second byte of each character. This will work as expected
+* for cases where the string contains ASCII data.
+*
+*/
+
+
+
+
+#include <x509cert.h>
+#include <x509certext.h>
+#include "X509time.h"
+#include <x509keys.h>
+#include <keyidentifierutil.h>
+#include <asn1enc.h>
+#include <asn1dec.h>
+
+EXPORT_C CPKCS1SignatureResult* CPKCS1SignatureResult::NewL(const CAlgorithmIdentifier& aDigestAlgorithm, const TDesC8& aDigest)
+ {
+ CPKCS1SignatureResult* self = CPKCS1SignatureResult::NewLC(aDigestAlgorithm, aDigest);
+ CleanupStack::Pop();
+ return self;
+ }
+
+EXPORT_C CPKCS1SignatureResult* CPKCS1SignatureResult::NewLC(const CAlgorithmIdentifier& aDigestAlgorithm, const TDesC8& aDigest)
+ {
+ CPKCS1SignatureResult* self = new(ELeave) CPKCS1SignatureResult;
+ CleanupStack::PushL(self);
+ self->ConstructL(aDigestAlgorithm, aDigest);
+ return self;
+ }
+
+void CPKCS1SignatureResult::ConstructL(const CAlgorithmIdentifier& aDigestAlgorithm, const TDesC8& aDigest)
+ {
+ iDigestAlgorithm = CAlgorithmIdentifier::NewL(aDigestAlgorithm);
+ iDigest = aDigest.AllocL();
+ }
+
+EXPORT_C TBool CPKCS1SignatureResult::VerifyL(const TDesC8& aResult)
+ {
+
+ TBool res = EFalse;
+ TRAPD(err, res = DoVerifyL(aResult));
+ if ((err != KErrNone) && (err != KErrArgument))
+ {
+ User::Leave(err);
+ }
+ return res;
+ }
+
+TBool CPKCS1SignatureResult::DoVerifyL(const TDesC8& aResult)
+ {
+ TBool res = EFalse;
+ TASN1DecSequence decSeq;
+ TInt pos = 0;
+ TInt len = aResult.Length();
+
+ const CArrayPtrFlat<TASN1DecGeneric>* seq = decSeq.DecodeDERLC(aResult, pos);
+ if (seq->Count() == 2)
+ {
+ const TASN1DecGeneric* gen1 = seq->At(0);
+ const TASN1DecGeneric* gen2 = seq->At(1);
+ CAlgorithmIdentifier* algId = CX509AlgorithmIdentifier::NewLC(gen1->Encoding());
+ HBufC8* digest = gen2->GetContentDER().AllocL();
+ if ((*algId == *iDigestAlgorithm) && (*digest == *iDigest) && (pos == len))
+ {
+ res = ETrue;
+ }
+ delete digest;
+ CleanupStack::PopAndDestroy();
+ }
+ CleanupStack::PopAndDestroy();
+ return res;
+ }
+
+
+EXPORT_C CRSAPublicKey* TX509KeyFactory::RSAPublicKeyL(const TDesC8& aEncoding) const
+ {
+ return CX509RSAPublicKey::NewL(aEncoding);
+ }
+
+EXPORT_C CRSASignatureResult* TX509KeyFactory::RSASignatureResultL(const CAlgorithmIdentifier& aDigestAlgorithm, TDesC8& aDigest) const
+ {
+ return CPKCS1SignatureResult::NewL(aDigestAlgorithm, aDigest);
+ }
+
+EXPORT_C CDSAPublicKey* TX509KeyFactory::DSAPublicKeyL(const TDesC8& aParamsEncoding, const TDesC8& aEncoding) const
+ {
+ return CX509DSAPublicKey::NewL(aParamsEncoding, aEncoding);
+ }
+
+EXPORT_C CDSAPublicKey* TX509KeyFactory::DSAPublicKeyL(const CDSAParameters& aParams, const TDesC8& aEncoding) const
+ {
+ return CX509DSAPublicKey::NewL(aParams, aEncoding);
+ }
+
+
+EXPORT_C CDSASignature* TX509KeyFactory::DSASignatureL(const TDesC8& aEncoding) const
+ {
+ return CX509DSASignature::NewL(aEncoding);
+ }
+
+EXPORT_C CDSAParameters* TX509KeyFactory::DSAParametersL(const TDesC8& aParamsEncoding) const
+{
+ return (CX509DSAPublicKey::DSAParametersL(aParamsEncoding));
+}
+
+//CX509ValidityPeriod
+EXPORT_C CX509ValidityPeriod* CX509ValidityPeriod::NewL(const TDesC8& aBinaryData)
+ {
+ TInt pos = 0;
+ return CX509ValidityPeriod::NewL(aBinaryData, pos);
+ }
+
+EXPORT_C CX509ValidityPeriod* CX509ValidityPeriod::NewLC(const TDesC8& aBinaryData)
+ {
+ TInt pos = 0;
+ return CX509ValidityPeriod::NewLC(aBinaryData, pos);
+ }
+
+EXPORT_C CX509ValidityPeriod* CX509ValidityPeriod::NewL(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ CX509ValidityPeriod* self = CX509ValidityPeriod::NewLC(aBinaryData, aPos);
+ CleanupStack::Pop();
+ return self;
+ }
+
+EXPORT_C CX509ValidityPeriod* CX509ValidityPeriod::NewLC(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ CX509ValidityPeriod* self = new(ELeave) CX509ValidityPeriod;
+ CleanupStack::PushL(self);
+ self->ConstructL(aBinaryData, aPos);
+ return self;
+ }
+
+CX509ValidityPeriod::CX509ValidityPeriod()
+ {
+ }
+
+void CX509ValidityPeriod::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ TASN1DecSequence encSeq;
+ CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos);
+ if (seq->Count() != 2)
+ {
+ User::Leave(KErrArgument);
+ }
+ TASN1DecX509Time decTime;
+ iStart = decTime.DecodeDERL(*(seq->At(0)));
+ iFinish = decTime.DecodeDERL(*(seq->At(1)));
+ CleanupStack::PopAndDestroy();//seq + contents
+ }
+
+//algorithm id
+EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewL(const TDesC8& aBinaryData)
+ {
+ TInt pos = 0;
+ return CX509AlgorithmIdentifier::NewL(aBinaryData, pos);
+ }
+
+EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewLC(const TDesC8& aBinaryData)
+ {
+ TInt pos = 0;
+ return CX509AlgorithmIdentifier::NewLC(aBinaryData, pos);
+ }
+
+EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewL(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ CX509AlgorithmIdentifier* self = CX509AlgorithmIdentifier::NewLC(aBinaryData, aPos);
+ CleanupStack::Pop();
+ return self;
+ }
+
+EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewLC(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ CX509AlgorithmIdentifier* self = new(ELeave) CX509AlgorithmIdentifier;
+ CleanupStack::PushL(self);
+ self->InitializeL(aBinaryData, aPos);
+ return self;
+ }
+
+EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewL(TAlgorithmId aAlgorithmId, const TDesC8& aEncodedParams)
+ {
+ CX509AlgorithmIdentifier* self = CX509AlgorithmIdentifier::NewLC(aAlgorithmId, aEncodedParams);
+ CleanupStack::Pop();
+ return self;
+ }
+
+EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewLC(TAlgorithmId aAlgorithmId, const TDesC8& aEncodedParams)
+ {
+ CX509AlgorithmIdentifier* self = new(ELeave) CX509AlgorithmIdentifier(aAlgorithmId);
+ CleanupStack::PushL(self);
+ self->ConstructL(aEncodedParams);
+ return self;
+ }
+
+CX509AlgorithmIdentifier::CX509AlgorithmIdentifier(TAlgorithmId& aAlgorithmId):CAlgorithmIdentifier(aAlgorithmId)
+ {
+ }
+
+
+CX509AlgorithmIdentifier::CX509AlgorithmIdentifier()
+ {
+ }
+
+void CX509AlgorithmIdentifier::InitializeL(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ TASN1DecSequence encSeq;
+ CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 1, KMaxTInt);
+ TInt count = seq->Count();
+ TASN1DecObjectIdentifier encOID;
+ HBufC* oid = encOID.DecodeDERL(*(seq->At(0)));
+ CleanupStack::PushL(oid);
+ TPtrC oidDes(oid->Des());
+ if (oidDes == KDSA)
+ {
+ //optional params
+ if (count > 1)//if we still have stuff left
+ {
+ TASN1DecGeneric* gen = seq->At(1);
+ iEncodedParams = gen->Encoding().AllocL();
+ }
+ else
+ {
+ iEncodedParams = HBufC8::NewL(1);
+ *iEncodedParams = KNullDesC8;
+ }
+ iAlgorithmId = EDSA;
+ CleanupStack::PopAndDestroy(2);//seq, oid
+ return;
+ }
+ if (count > 1)
+ {
+ TASN1DecGeneric* gen = seq->At(1);
+ if (oidDes == KDH)
+ {
+ iEncodedParams = gen->Encoding().AllocL();
+ iAlgorithmId = EDH;
+ CleanupStack::PopAndDestroy(2);//seq, oid
+ return;
+ }
+ if (oidDes == KRSA)
+ {
+ iAlgorithmId = ERSA;
+ TASN1DecNull null;
+ null.DecodeDERL(*gen);//just to check the syntax is OK
+ iEncodedParams = HBufC8::NewL(1);
+ *iEncodedParams = KNullDesC8;
+ CleanupStack::PopAndDestroy(2);//seq, oid
+ return;
+ }
+ if (oidDes == KMD5)
+ {
+ iAlgorithmId = EMD5;
+ TASN1DecNull null;
+ null.DecodeDERL(*gen);//just to check the syntax is OK
+ iEncodedParams = HBufC8::NewL(1);
+ *iEncodedParams = KNullDesC8;
+ CleanupStack::PopAndDestroy(2);//seq, oid
+ return;
+ }
+ if (oidDes == KMD2)
+ {
+ iAlgorithmId = EMD2;
+ TASN1DecNull null;
+ null.DecodeDERL(*gen);//just to check the syntax is OK
+ iEncodedParams = HBufC8::NewL(1);
+ *iEncodedParams = KNullDesC8;
+ CleanupStack::PopAndDestroy(2);//seq, oid
+ return;
+ }
+ if (oidDes == KSHA1)
+ {
+ iAlgorithmId = ESHA1;
+ TASN1DecNull null;
+ null.DecodeDERL(*gen);//just to check the syntax is OK
+ iEncodedParams = HBufC8::NewL(1);
+ *iEncodedParams = KNullDesC8;
+ CleanupStack::PopAndDestroy(2);//seq, oid
+ return;
+ }
+ }
+ User::Leave(KErrNotSupported);
+ }
+
+EXPORT_C CASN1EncSequence* CX509AlgorithmIdentifier::EncodeASN1DERLC() const
+ {
+ // the root sequence contains the signed object
+ CASN1EncSequence* root = CASN1EncSequence::NewLC();
+
+ //encode the oid
+ CASN1EncObjectIdentifier* oid(NULL);
+ switch (iAlgorithmId)
+ {
+ case EDSA:
+ oid=CASN1EncObjectIdentifier::NewLC(KDSA);
+ break;
+
+ case EDH:
+ oid=CASN1EncObjectIdentifier::NewLC(KDH);
+ break;
+
+ case ERSA:
+ oid=CASN1EncObjectIdentifier::NewLC(KRSA);
+ break;
+
+ case EMD5:
+ oid=CASN1EncObjectIdentifier::NewLC(KMD5);
+ break;
+
+ case EMD2:
+ oid=CASN1EncObjectIdentifier::NewLC(KMD2);
+ break;
+
+ case ESHA1:
+ oid=CASN1EncObjectIdentifier::NewLC(KSHA1);
+ break;
+
+ default:
+ User::Leave(KErrNotSupported);
+ }
+
+ root->AddAndPopChildL(oid);
+
+ //Encode parameters
+ if (*iEncodedParams!=KNullDesC8)
+ {
+ CASN1EncEncoding* enc=CASN1EncEncoding::NewLC(*iEncodedParams);
+ root->AddAndPopChildL(enc);
+ }
+ else
+ {
+ if (iAlgorithmId!=EDSA)
+ {
+ CASN1EncNull* enc=CASN1EncNull::NewLC();
+ root->AddAndPopChildL(enc);
+ }
+ }
+
+ return root;
+ }
+
+
+//signing algorithm id
+EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewL(const TDesC8& aBinaryData)
+ {
+ TInt pos = 0;
+ return CX509SigningAlgorithmIdentifier::NewL(aBinaryData, pos);
+ }
+
+EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewLC(const TDesC8& aBinaryData)
+ {
+ TInt pos = 0;
+ return CX509SigningAlgorithmIdentifier::NewLC(aBinaryData, pos);
+ }
+
+EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewL(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ CX509SigningAlgorithmIdentifier* self = CX509SigningAlgorithmIdentifier::NewLC(aBinaryData, aPos);
+ CleanupStack::Pop();
+ return self;
+ }
+
+EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewLC(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ CX509SigningAlgorithmIdentifier* self = new(ELeave) CX509SigningAlgorithmIdentifier;
+ CleanupStack::PushL(self);
+ self->ConstructL(aBinaryData, aPos);
+ return self;
+ }
+
+EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewL(const CAlgorithmIdentifier& aAsymmetricAlgorithm, const CAlgorithmIdentifier& aDigestAlgorithm)
+ {
+ CX509SigningAlgorithmIdentifier* self = CX509SigningAlgorithmIdentifier::NewLC(aAsymmetricAlgorithm, aDigestAlgorithm);
+ CleanupStack::Pop();
+ return self;
+ }
+
+EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewLC(const CAlgorithmIdentifier& aAsymmetricAlgorithm, const CAlgorithmIdentifier& aDigestAlgorithm)
+ {
+ CX509SigningAlgorithmIdentifier* self = new(ELeave) CX509SigningAlgorithmIdentifier;
+ CleanupStack::PushL(self);
+ self->ConstructL(aAsymmetricAlgorithm, aDigestAlgorithm);
+ return self;
+ }
+
+CX509SigningAlgorithmIdentifier::CX509SigningAlgorithmIdentifier()
+ {
+ }
+
+void CX509SigningAlgorithmIdentifier::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ TASN1DecSequence encSeq;
+ CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 1, KMaxTInt);
+ TInt count = seq->Count();
+ TASN1DecObjectIdentifier encOID;
+ HBufC* oid = encOID.DecodeDERL(*(seq->At(0)));
+ CleanupStack::PushL(oid);
+ TPtrC oidDes(oid->Des());
+ //none of the signing algorithms we support have parameters here...
+ HBufC8* encodedParams = HBufC8::NewLC(1);
+ *encodedParams = KNullDesC8;
+
+ if (oidDes == KDSAWithSHA1)
+ {
+ //should be no params, but we allow params encoded as NULL for interop reasons
+ TAlgorithmId algId = EDSA;
+ TAlgorithmId digestId = ESHA1;
+ iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
+ iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
+ if (count == 1)
+ {
+ CleanupStack::PopAndDestroy(3);//seq, oid, encodedParams
+ return;
+ }
+ }
+
+ if (oidDes == KMD2WithRSA)
+ {
+ TAlgorithmId algId = ERSA;
+ TAlgorithmId digestId = EMD2;
+ iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
+ iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
+ }
+
+ if (oidDes == KMD5WithRSA)
+ {
+ TAlgorithmId algId = ERSA;
+ TAlgorithmId digestId = EMD5;
+ iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
+ iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
+ }
+
+ if (oidDes == KSHA1WithRSA)
+ {
+ TAlgorithmId algId = ERSA;
+ TAlgorithmId digestId = ESHA1;
+ iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
+ iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
+ }
+ //???not sure if we should just leave here...
+ if (iDigestAlgorithm == NULL)
+ {
+ User::Leave(KErrNotSupported);
+ }
+ else
+ {
+ if (count != 2)
+ {
+ // Shouldn't ever get here, since RFC2459 mandates having 2
+ // data items. However, some people miss out the second
+ // when it's NULL, so we'll not report and error here
+ }
+ else
+ {
+ TASN1DecGeneric* gen = seq->At(1);
+ TASN1DecNull null;
+ null.DecodeDERL(*gen);//just to check the syntax is OK
+ }
+ }
+ CleanupStack::PopAndDestroy(3);//seq, oid, encodedParams
+ }
+
+void CX509SigningAlgorithmIdentifier::ConstructL(const CAlgorithmIdentifier& aAsymmetricAlgorithm, const CAlgorithmIdentifier& aDigestAlgorithm)
+ {
+ iDigestAlgorithm = CAlgorithmIdentifier::NewL(aDigestAlgorithm);
+ iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(aAsymmetricAlgorithm);
+ };
+
+//subject public key info
+EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewL(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ CX509SubjectPublicKeyInfo* self = CX509SubjectPublicKeyInfo::NewLC(aBinaryData, aPos);
+ CleanupStack::Pop();
+ return self;
+ }
+
+EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewLC(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ CX509SubjectPublicKeyInfo* self = new(ELeave) CX509SubjectPublicKeyInfo;
+ CleanupStack::PushL(self);
+ self->ConstructL(aBinaryData, aPos);
+ return self;
+ }
+
+EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewL(const TDesC8& aBinaryData)
+ {
+ TInt pos = 0;
+ return CX509SubjectPublicKeyInfo::NewL(aBinaryData, pos);
+ }
+
+EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewLC(const TDesC8& aBinaryData)
+ {
+ TInt pos = 0;
+ return CX509SubjectPublicKeyInfo::NewLC(aBinaryData, pos);
+ }
+
+CX509SubjectPublicKeyInfo::CX509SubjectPublicKeyInfo()
+ {
+ }
+
+void CX509SubjectPublicKeyInfo::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ TASN1DecSequence encSeq;
+ CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 2, KMaxTInt);
+ iAlgId = CX509AlgorithmIdentifier::NewL(seq->At(0)->Encoding());
+ TASN1DecBitString encBS;
+ iEncodedKeyData = encBS.ExtractOctetStringL(*(seq->At(1)));
+ CleanupStack::PopAndDestroy();//seq
+ }
+
+//generic X 509 extension syntax
+EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const CX509CertExtension& aExtension)
+ {
+ CX509CertExtension* self = CX509CertExtension::NewLC(aExtension);
+ CleanupStack::Pop();
+ return self;
+ }
+
+EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const CX509CertExtension& aExtension)
+ {
+ CX509CertExtension* self = new(ELeave) CX509CertExtension;
+ CleanupStack::PushL(self);
+ self->ConstructL(aExtension);
+ return self;
+ }
+
+EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ CX509CertExtension* self = CX509CertExtension::NewLC(aBinaryData, aPos);
+ CleanupStack::Pop();
+ return self;
+ }
+
+EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ CX509CertExtension* self = new(ELeave) CX509CertExtension;
+ CleanupStack::PushL(self);
+ self->ConstructL(aBinaryData, aPos);
+ return self;
+ }
+
+EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const TDesC8& aBinaryData)
+ {
+ TInt pos = 0;
+ return CX509CertExtension::NewL(aBinaryData, pos);
+ }
+
+EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const TDesC8& aBinaryData)
+ {
+ TInt pos = 0;
+ return CX509CertExtension::NewLC(aBinaryData, pos);
+ }
+
+EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const TDesC& aCertExtOID,
+ const TBool aCritical,
+ const TDesC8& aCertExtValue)
+ {
+ CX509CertExtension* self = CX509CertExtension::NewLC(aCertExtOID, aCritical, aCertExtValue);
+ CleanupStack::Pop();
+ return self;
+ }
+
+EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const TDesC& aCertExtOID,
+ const TBool aCritical,
+ const TDesC8& aCertExtValue)
+ {
+ CX509CertExtension* self = new(ELeave) CX509CertExtension;
+ CleanupStack::PushL(self);
+ self->ConstructL(aCertExtOID, aCritical, aCertExtValue);
+ return self;
+ }
+
+void CX509CertExtension::ConstructL(const CX509CertExtension& aExtension)
+ {
+ iCritical = aExtension.iCritical;
+ iId = aExtension.iId->Des().AllocL();
+ iData = aExtension.iData->Des().AllocL();
+ }
+
+void CX509CertExtension::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ TASN1DecSequence encSeq;
+ CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 2, KMaxTInt);
+
+ TASN1DecObjectIdentifier encOID;
+ iId = encOID.DecodeDERL(*(seq->At(0)));
+ //second is either critical flag, or the ext
+ TASN1DecGeneric* second = seq->At(1);
+ if (second->Tag() != EASN1Boolean)
+ {
+ iData = second->Encoding().AllocL();
+ aPos += second->LengthDER();
+ }
+ else
+ {
+ TASN1DecBoolean encBool;
+ iCritical = encBool.DecodeDERL(*second);
+ if (seq->Count() != 3)
+ {
+ User::Leave(KErrArgument);
+ }
+
+ TASN1DecGeneric* third = seq->At(2);
+ iData = third->Encoding().AllocL();
+ }
+ CleanupStack::PopAndDestroy();//seq
+ }
+
+void CX509CertExtension::ConstructL(const TDesC& aCertExtOID,
+ const TBool aCritical,
+ const TDesC8& aCertExtValue)
+ {
+ iId = aCertExtOID.AllocL();
+ iCritical = aCritical;
+ iData = aCertExtValue.AllocL();
+ }
+
+EXPORT_C CX509CertExtension::~CX509CertExtension()
+ {
+ delete iData;
+ delete iId;
+ }
+
+EXPORT_C TBool CX509CertExtension::Critical() const
+ {
+ return iCritical;
+ }
+
+EXPORT_C TPtrC CX509CertExtension::Id() const //OID for the extension
+ {
+ return iId->Des();
+ }
+
+EXPORT_C TPtrC8 CX509CertExtension::Data() const //the extension itself
+ {
+ return iData->Des();
+ }
+
+EXPORT_C CASN1EncSequence* CX509CertExtension::EncodeASN1DERLC() const
+ {
+ CASN1EncSequence *result = CASN1EncSequence::NewLC();
+ CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(*iId);
+ result->AddAndPopChildL(oid);
+ // Encode critical flag only if true
+ if (iCritical)
+ {
+ CASN1EncBoolean *critical = CASN1EncBoolean::NewLC(iCritical);
+ result->AddAndPopChildL(critical);
+ }
+ CASN1EncOctetString *data = CASN1EncOctetString::NewLC(*iData);
+ result->AddAndPopChildL(data);
+ return result;
+ }
+
+CX509CertExtension::CX509CertExtension()
+ :iCritical(EFalse)
+ {
+ }
+
+//CX509Certificate
+EXPORT_C CX509Certificate* CX509Certificate::NewL(const CX509Certificate& aCert)
+ {
+ CX509Certificate* self = CX509Certificate::NewLC(aCert);
+ CleanupStack::Pop();//self
+ return self;
+ }
+
+EXPORT_C CX509Certificate* CX509Certificate::NewLC(const CX509Certificate& aCert)
+ {
+ CX509Certificate* self = new(ELeave) CX509Certificate;
+ CleanupStack::PushL(self);
+ self->ConstructL(aCert);
+ return self;
+ }
+
+EXPORT_C CX509Certificate* CX509Certificate::NewL(const TDesC8& aBinaryData)
+ {
+ TInt pos = 0;
+ return CX509Certificate::NewL(aBinaryData, pos);
+ }
+
+EXPORT_C CX509Certificate* CX509Certificate::NewLC(const TDesC8& aBinaryData)
+ {
+ TInt pos = 0;
+ return CX509Certificate::NewLC(aBinaryData, pos);
+ }
+
+EXPORT_C CX509Certificate* CX509Certificate::NewL(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ CX509Certificate* self = CX509Certificate::NewLC(aBinaryData, aPos);
+ CleanupStack::Pop();
+ return self;
+ }
+
+EXPORT_C CX509Certificate* CX509Certificate::NewLC(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ CX509Certificate* self = new(ELeave) CX509Certificate();
+ CleanupStack::PushL(self);
+ self->ConstructL(aBinaryData, aPos);
+ return self;
+ }
+
+EXPORT_C CX509Certificate* CX509Certificate::NewL(RReadStream& aStream)
+ {
+ CX509Certificate* self = CX509Certificate::NewLC(aStream);
+ CleanupStack::Pop();//self
+ return self;
+ }
+
+EXPORT_C CX509Certificate* CX509Certificate::NewLC(RReadStream& aStream)
+ {
+ CX509Certificate* self = new(ELeave) CX509Certificate;
+ CleanupStack::PushL(self);
+ self->InternalizeL(aStream);
+ return self;
+ }
+
+void CX509Certificate::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ TASN1DecGeneric gen(aBinaryData.Right(aBinaryData.Length() - aPos));
+ gen.InitL();
+
+ // The outermost tag for X509 certificates is always a sequence.
+ // Since this tag does not form part of the signed data it is possible
+ // to corrupt the tag by changing it to any other ASN.1 tag and process
+ // the rest of the certificate as normal.
+ // However, we still reject the certificate anyway to avoid
+ // confusion because the data does not match the X.509 specification.
+ if (gen.Tag() != EASN1Sequence)
+ {
+ User::Leave(KErrArgument);
+ }
+
+ aPos += gen.LengthDER();
+ iKeyFactory = new(ELeave) TX509KeyFactory;
+
+ iEncoding = gen.Encoding().AllocL();
+
+ TASN1DecSequence encSeq;
+ TInt pos = 0;
+ CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(*iEncoding, pos, 3, 3);
+ TASN1DecGeneric* encSigAlg = seq->At(1);
+ iSigningAlgorithm = CX509SigningAlgorithmIdentifier::NewL(encSigAlg->Encoding());
+ TASN1DecBitString encBS;
+ iSignature = encBS.ExtractOctetStringL(*(seq->At(2)));
+ CleanupStack::PopAndDestroy();//seq
+
+ CSHA1* hash = CSHA1::NewL();
+ CleanupStack::PushL(hash);
+ iFingerprint = hash->Final(Encoding()).AllocL();
+ CleanupStack::PopAndDestroy();//hash
+ ConstructCertL();
+ }
+
+void CX509Certificate::ConstructL(const CX509Certificate& aCertificate)
+ {
+ iKeyFactory = new(ELeave) TX509KeyFactory;
+
+ iEncoding = aCertificate.iEncoding->AllocL();
+ iSignature = aCertificate.iSignature->AllocL();
+ iFingerprint = aCertificate.iFingerprint->AllocL();
+ iSigningAlgorithm = CSigningAlgorithmIdentifier::NewL(aCertificate.SigningAlgorithm());
+ iSerialNumber = aCertificate.iSerialNumber->Des().AllocL();
+ iIssuerName = CX500DistinguishedName::NewL(*(aCertificate.iIssuerName));
+ iValidityPeriod = new(ELeave) CValidityPeriod(*(aCertificate.iValidityPeriod));
+ iSubjectName = CX500DistinguishedName::NewL(*(aCertificate.iSubjectName));
+ iSubjectPublicKeyInfo = CSubjectPublicKeyInfo::NewL(*(aCertificate.iSubjectPublicKeyInfo));
+ iIssuerUid = aCertificate.iIssuerUid->Des().AllocL();
+ iSubjectUid = aCertificate.iSubjectUid->Des().AllocL();
+ iExtensions = new(ELeave) CArrayPtrFlat<CX509CertExtension> (1);
+ TInt count = aCertificate.iExtensions->Count();
+ for (TInt i = 0; i < count; i++)
+ {
+ CX509CertExtension* ext = CX509CertExtension::NewLC(*aCertificate.iExtensions->At(i));
+ iExtensions->AppendL(ext);
+ CleanupStack::Pop();//ext
+ }
+ iVersion = aCertificate.Version();
+ InitDataElementsL(aCertificate);
+ }
+
+void CX509Certificate::InitDataElementsL(const CX509Certificate& aCertificate)
+ {
+ iDataElements = new(ELeave) TFixedArray<TPtrC8*, KX509MaxDataElements>;
+ iDataElements->Reset();
+ TPtrC8 signedData = SignedDataL();
+ TASN1DecSequence encSeq;
+ TInt pos = 0;
+ CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(signedData, pos, 6, KMaxTInt);//6 is the minimum number of elements in an x509 cert
+ pos = 0;
+
+ TPtrC8** pElement = iDataElements->Begin();
+ *pElement++ = aCertificate.DataElementEncoding(CX509Certificate::EVersionNumber)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
+ for (TInt i = 0; i < 6; i++) //init all the non-optional elements
+ {
+ *pElement++ = new(ELeave) TPtrC8(seq->At(pos++)->Encoding());
+ }
+ *pElement++ = aCertificate.DataElementEncoding(CX509Certificate::EIssuerUID)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
+ *pElement++ = aCertificate.DataElementEncoding(CX509Certificate::ESubjectUID)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
+ *pElement++ = aCertificate.DataElementEncoding(CX509Certificate::EExtensionList)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
+ CleanupStack::PopAndDestroy();
+ }
+
+void CX509Certificate::ConstructCertL()
+ {
+ TPtrC8 signedData = SignedDataL();
+ TASN1DecSequence encSeq;
+ TInt pos = 0;
+ CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(signedData, pos, 6, KMaxTInt);//6 is the minimum number of elements in an x509 cert
+ TInt count = seq->Count();
+ pos = 0;
+ TASN1DecGeneric* curr = seq->At(pos);
+ pos++;
+ iDataElements = new(ELeave) TFixedArray<TPtrC8*, KX509MaxDataElements>;
+ iDataElements->Reset();
+ TPtrC8** pElement = iDataElements->Begin();
+ if ((curr->Class() == EContextSpecific) && (curr->Tag() == 0))
+ {
+ //version!
+ TASN1DecGeneric ver(curr->GetContentDER());
+ ver.InitL();
+ TPtrC8 pVer8 = ver.GetContentDER();
+ if(pVer8.Length() != 1)
+ {
+ User::Leave(KErrArgument);
+ }
+ iVersion = (pVer8[0]) + 1;
+ if ((iVersion < 1) || (iVersion > 3) || (count < 7))
+ {
+ User::Leave(KErrArgument);
+ }
+ *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+ curr = seq->At(pos);
+ pos++;
+ }
+ else
+ {
+ *pElement++ = NULL;
+ }
+ if (curr->Tag() != EASN1Integer)
+ {
+ User::Leave(KErrArgument);
+ }
+ iSerialNumber = (curr->GetContentDER()).AllocL();
+ *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+ curr = seq->At(pos);
+ pos++;
+ CX509SigningAlgorithmIdentifier* algorithmId = CX509SigningAlgorithmIdentifier::NewLC(curr->Encoding());
+ if (!(SigningAlgorithm() == *(algorithmId)))
+ {
+ User::Leave(KErrArgument);
+ }
+ CleanupStack::PopAndDestroy();//algorithmId
+ *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+
+ curr = seq->At(pos);
+ pos++;
+ iIssuerName = CX500DistinguishedName::NewL(curr->Encoding());
+ *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+ curr = seq->At(pos);
+ pos++;
+ iValidityPeriod = CX509ValidityPeriod::NewL(curr->Encoding());
+ *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+ curr = seq->At(pos);
+ pos++;
+ iSubjectName = CX500DistinguishedName::NewL(curr->Encoding());
+ *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+ curr = seq->At(pos);
+ pos++;
+ iSubjectPublicKeyInfo = CX509SubjectPublicKeyInfo::NewL(curr->Encoding());
+ *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+ //do issuer uid, subject uid, exts
+ //these are all optional
+ TBool hasIssuerUid = EFalse;
+ TBool hasSubjectUid = EFalse;
+ TBool hasExts = EFalse;
+ iExtensions = new(ELeave)CArrayPtrFlat<CX509CertExtension> (1);
+ if (pos < count)//otherwise there aren't any of 'em
+ {
+ curr = seq->At(pos);
+ pos++;
+ if (curr->Class() != EContextSpecific)
+ {
+ User::Leave(KErrArgument);
+ }
+ switch(curr->Tag())
+ {
+ case 1:
+ {
+ iIssuerUid = DecodeUidL(curr->GetContentDER(), hasIssuerUid);
+ *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+ break;
+ }
+ case 2:
+ {
+ iSubjectUid = DecodeUidL(curr->GetContentDER(), hasSubjectUid);
+ *pElement++ = NULL;
+ *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+ break;
+ }
+ case 3:
+ {
+ DecodeExtsL(curr->GetContentDER(), hasExts);
+ *pElement++ = NULL;
+ *pElement++ = NULL;
+ *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+ break;
+ }
+ default:
+ {
+ User::Leave(KErrArgument);
+ }
+ }
+ if (pos < count)
+ {
+ curr = seq->At(pos);
+ pos++;
+ switch(curr->Tag())
+ {
+ case 2:
+ {
+ iSubjectUid = DecodeUidL(curr->GetContentDER(), hasSubjectUid);
+ *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+ break;
+ }
+ case 3:
+ {
+ DecodeExtsL(curr->GetContentDER(), hasExts);
+ *pElement++ = NULL;
+ *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+ break;
+ }
+ default:
+ {
+ User::Leave(KErrArgument);
+ }
+ }
+ if (pos < count)
+ {
+ curr = seq->At(pos);
+ pos++;
+ if (curr->Tag() == 3)
+ {
+ DecodeExtsL(curr->GetContentDER(), hasExts);
+ *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+ }
+ else
+ {
+ User::Leave(KErrArgument);
+ }
+ }
+ }
+ }
+ if (pos != count)
+ {
+ User::Leave(KErrArgument);
+ }
+ if (!iIssuerUid)
+ {
+ iIssuerUid = HBufC8::NewL(1);
+ *iIssuerUid = KNullDesC8;
+ }
+ if (!iSubjectUid)
+ {
+ iSubjectUid = HBufC8::NewL(1);
+ *iSubjectUid = KNullDesC8;
+ }
+
+ // we have not checked for the certificate version number based on
+ // the certificate contents. This is primarily done to avoid BC for
+ // clients who are still using malformed certificates.
+
+ CleanupStack::PopAndDestroy();//seq
+ }
+
+CX509Certificate::CX509Certificate()
+ :iVersion(1)
+ {
+ }
+
+EXPORT_C CX509Certificate::~CX509Certificate()
+ {
+ delete iIssuerName;
+ delete iSubjectName;
+ delete iIssuerUid;
+ delete iSubjectUid;
+
+ if (iDataElements != NULL)
+ {
+ for (TInt i = 0; i < KX509MaxDataElements; i++)
+ {
+ delete iDataElements->At(i);
+ }
+ delete iDataElements;
+ }
+ if (iExtensions != NULL)
+ {
+ iExtensions->ResetAndDestroy();
+ }
+ delete iExtensions;
+ }
+
+EXPORT_C TBool CX509Certificate::IsEqualL(const CX509Certificate& aCert) const
+ {
+ return ( (*(iSerialNumber) == *(aCert.iSerialNumber)) &&
+ (iIssuerName->ExactMatchL(*(aCert.iIssuerName))) );
+ }
+
+EXPORT_C void CX509Certificate::InternalizeL(RReadStream& aStream)
+ {
+ if (iIssuerName != NULL) //just to check cert is uninitialised
+ {
+ User::Leave(KErrArgument);
+ }
+ iKeyFactory = new(ELeave) TX509KeyFactory;
+
+ TInt len = aStream.ReadInt32L(); //Read the length of the streamed encoding
+ HBufC8* temp= HBufC8::NewLC(len);
+ TPtr8 ptr=temp->Des();
+ aStream.ReadL(ptr,len);
+ iEncoding=temp->AllocL();
+ CleanupStack::PopAndDestroy(); // temp
+
+ TASN1DecSequence encSeq;
+ TInt pos = 0;
+ CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(*iEncoding, pos, 3, 3);
+ TASN1DecGeneric* encSigAlg = seq->At(1);
+ iSigningAlgorithm = CX509SigningAlgorithmIdentifier::NewL(encSigAlg->Encoding());
+ TASN1DecBitString encBS;
+ iSignature = encBS.ExtractOctetStringL(*(seq->At(2)));
+ CleanupStack::PopAndDestroy();//seq
+
+ CSHA1* hash = CSHA1::NewL();
+ CleanupStack::PushL(hash);
+ iFingerprint = hash->Final(Encoding()).AllocL();
+ CleanupStack::PopAndDestroy();//hash
+
+ ConstructCertL();
+ }
+
+void CX509Certificate::DecodeExtsL(const TDesC8& aBinaryData, TBool& aHasElementAlready)
+ {
+ TASN1DecSequence encSeq;
+ TInt pos = 0;
+ CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, pos);
+ TInt count = seq->Count();
+ for (TInt i = 0; i < count; i++)
+ {
+ TASN1DecGeneric* gen = seq->At(i);
+ CX509CertExtension* ext = CX509CertExtension::NewLC(gen->Encoding());
+ iExtensions->AppendL(ext);
+ CleanupStack::Pop();//ext
+ }
+ CleanupStack::PopAndDestroy();//
+ aHasElementAlready = ETrue;
+ }
+
+HBufC8* CX509Certificate::DecodeUidL(const TDesC8& aBinaryData, TBool& aHasElementAlready)
+ {
+ if ((aHasElementAlready) || (iVersion ==1))
+ {
+ User::Leave(KErrArgument);
+ }
+ aHasElementAlready = ETrue;
+ return aBinaryData.AllocL();
+ }
+
+//***************************************************************************************//
+//extra accessors
+EXPORT_C const TPtrC8 CX509Certificate::SignedDataL() const
+ {
+ TASN1DecSequence encSeq;
+ TInt pos = 0;
+ CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(*iEncoding, pos, 3, 3);
+ TASN1DecGeneric* gen = seq->At(0);
+ TPtrC8 res = gen->Encoding();
+ CleanupStack::PopAndDestroy();
+ return res;
+ }
+
+EXPORT_C TInt CX509Certificate::Version() const
+ {
+ return iVersion;
+ }
+
+/**
+* If the certificate has decoded the members from TeletexString then the return value
+* may be incorrect because TeletexString type is not fully supported by this library.
+* Instead the decode methods perform a direct conversion from 8 to 16bits by adding
+* null characters in the second byte of each character. This will work as expected
+* for cases where the string contains ASCII data.
+*/
+EXPORT_C const CX500DistinguishedName& CX509Certificate::IssuerName() const
+ {
+ return *iIssuerName;
+ }
+
+/**
+* If the certificate has decoded the members from TeletexString then the return value
+* may be incorrect because TeletexString type is not fully supported by this library.
+* Instead the decode methods perform a direct conversion from 8 to 16bits by adding
+* null characters in the second byte of each character. This will work as expected
+* for cases where the string contains ASCII data.
+*/
+EXPORT_C const CX500DistinguishedName& CX509Certificate::SubjectName() const
+ {
+ return *iSubjectName;
+ }
+
+EXPORT_C const CArrayPtrFlat<CX509CertExtension>& CX509Certificate::Extensions() const
+ {
+ return *iExtensions;
+ }
+
+EXPORT_C const CX509CertExtension* CX509Certificate::Extension(const TDesC& aExtensionName) const
+ {
+ TInt count = iExtensions->Count();
+ for (TInt i = 0; i < count; i++)
+ {
+ CX509CertExtension* ext = iExtensions->At(i);
+ if (ext->Id() == aExtensionName)
+ return ext;
+ }
+ return NULL;
+ }
+
+EXPORT_C const TPtrC8* CX509Certificate::DataElementEncoding(const TUint aIndex) const
+ {
+ return iDataElements->At(aIndex);
+ }
+
+/**
+* If the certificate has decoded the members from TeletexString then the return value
+* may be incorrect because TeletexString type is not fully supported by this library.
+* Instead the decode methods perform a direct conversion from 8 to 16bits by adding
+* null characters in the second byte of each character. This will work as expected
+* for cases where the string contains ASCII data.
+*/
+EXPORT_C HBufC* CX509Certificate::IssuerL() const
+ {
+ return iIssuerName->DisplayNameL();
+ }
+
+/**
+* If the certificate has decoded the members from TeletexString then the return value
+* may be incorrect because TeletexString type is not fully supported by this library.
+* Instead the decode methods perform a direct conversion from 8 to 16bits by adding
+* null characters in the second byte of each character. This will work as expected
+* for cases where the string contains ASCII data.
+*/
+EXPORT_C HBufC* CX509Certificate::SubjectL() const
+ {
+ return iSubjectName->DisplayNameL();
+ }
+
+EXPORT_C TBool CX509Certificate::IsSelfSignedL() const
+ {
+ if (iSubjectName->Count() > 0)
+ {
+ return iSubjectName->ExactMatchL(*iIssuerName);
+ }
+ else
+ {
+ TBool res = EFalse;
+ const CX509CertExtension* subjectExt = Extension(KIssuerAltName);
+ const CX509CertExtension* issuerExt = Extension(KSubjectAltName);
+ if ((subjectExt) && (issuerExt))
+ {
+ const CX509AltNameExt* issuerAltName = CX509AltNameExt::NewLC(subjectExt->Data());
+ const CX509AltNameExt* subjectAltName = CX509AltNameExt::NewLC(issuerExt->Data());
+ if (subjectAltName->Match(*issuerAltName))
+ {
+ res = ETrue;
+ }
+ CleanupStack::PopAndDestroy(2);//subjectAltName, issuerAltName
+ }
+ return res;
+ }
+ }
+
+
+EXPORT_C TKeyIdentifier CX509Certificate::KeyIdentifierL() const
+ {
+ if (iSubjectPublicKeyInfo->AlgorithmId() != EDSA)
+ {
+ // The base class handles the RSA case and leaves with KErrNotSupported if
+ // it is not RSA.
+ return CCertificate::KeyIdentifierL();
+ }
+ else
+ {
+ // This handles the DSA case
+ CDSAPublicKey* dsaKey =
+ iKeyFactory->DSAPublicKeyL(iSubjectPublicKeyInfo->EncodedParams(),
+ iSubjectPublicKeyInfo->KeyData());
+ CleanupStack::PushL(dsaKey);
+ TKeyIdentifier retVal;
+ KeyIdentifierUtil::DSAKeyIdentifierL(*dsaKey, retVal);
+ CleanupStack::PopAndDestroy(dsaKey);
+ return retVal;
+ }
+ }
+
+EXPORT_C TKeyIdentifier CX509Certificate::SubjectKeyIdentifierL() const
+ {
+ const CX509CertExtension* subjectKeyIdExtStr = this->Extension(KSubjectKeyId);
+ if (subjectKeyIdExtStr)
+ {
+ TKeyIdentifier ret;
+ CX509SubjectKeyIdExt *subjectKeyIdExt = CX509SubjectKeyIdExt::NewLC(subjectKeyIdExtStr->Data());
+ // Currently, we do not support key identifiers larger than 160 bits - make sure not to overflow the descriptor
+ if (subjectKeyIdExt->KeyId().Length() <= ret.MaxLength())
+ {
+ ret.Copy(subjectKeyIdExt->KeyId());
+ CleanupStack::PopAndDestroy(subjectKeyIdExt);
+ return ret;
+ }
+ CleanupStack::PopAndDestroy(subjectKeyIdExt);
+ }
+
+ return KeyIdentifierL();
+ }