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