diff -r 675a964f4eb5 -r 35751d3474b7 cryptoservices/certificateandkeymgmt/x509/x509cert.cpp --- 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 -#include -#include "X509time.h" -#include -#include -#include -#include - -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* 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* 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* 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* 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* 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* 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* 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 (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; - iDataElements->Reset(); - TPtrC8 signedData = SignedDataL(); - TASN1DecSequence encSeq; - TInt pos = 0; - CArrayPtrFlat* 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* 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; - 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 (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* 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* 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* 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& 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 +#include +#include "X509time.h" +#include +#include +#include +#include + +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* 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* 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* 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* 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* 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* 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* 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 (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; + iDataElements->Reset(); + TPtrC8 signedData = SignedDataL(); + TASN1DecSequence encSeq; + TInt pos = 0; + CArrayPtrFlat* 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* 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; + 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 (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* 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* 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* 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& 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(); + }