--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptoservices/certificateandkeymgmt/x509/x509cert.cpp Wed Jul 08 11:25:26 2009 +0100
@@ -0,0 +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();
+ }