Update contrib.
2 * Copyright (c) 1998-2010 Nokia Corporation and/or its subsidiary(-ies).
4 * This component and the accompanying materials are made available
5 * under the terms of the License "Eclipse Public License v1.0"
6 * which accompanies this distribution, and is available
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
15 * -- FingerPrint Note:
16 * Developers have to be aware that if they are going to change the fingerprint for this certificate
17 * for a different hash, then there are other places that need to reflect this change
19 * void CX509Certificate::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
20 * EXPORT_C void CX509Certificate::InternalizeL(RReadStream& aStream)
21 * Also change the CWTLSCertificate and search for other occurences of the current
23 * -- TeletexString type support Note:
24 * If the certificate has decoded the members from TeletexString then the return value
25 * may be incorrect because TeletexString type is not fully supported by this library.
26 * Instead the decode methods perform a direct conversion from 8 to 16bits by adding
27 * null characters in the second byte of each character. This will work as expected
28 * for cases where the string contains ASCII data.
36 #include <x509certext.h>
39 #include <keyidentifierutil.h>
43 EXPORT_C CPKCS1SignatureResult* CPKCS1SignatureResult::NewL(const CAlgorithmIdentifier& aDigestAlgorithm, const TDesC8& aDigest)
45 CPKCS1SignatureResult* self = CPKCS1SignatureResult::NewLC(aDigestAlgorithm, aDigest);
50 EXPORT_C CPKCS1SignatureResult* CPKCS1SignatureResult::NewLC(const CAlgorithmIdentifier& aDigestAlgorithm, const TDesC8& aDigest)
52 CPKCS1SignatureResult* self = new(ELeave) CPKCS1SignatureResult;
53 CleanupStack::PushL(self);
54 self->ConstructL(aDigestAlgorithm, aDigest);
58 void CPKCS1SignatureResult::ConstructL(const CAlgorithmIdentifier& aDigestAlgorithm, const TDesC8& aDigest)
60 iDigestAlgorithm = CAlgorithmIdentifier::NewL(aDigestAlgorithm);
61 iDigest = aDigest.AllocL();
64 EXPORT_C TBool CPKCS1SignatureResult::VerifyL(const TDesC8& aResult)
68 TRAPD(err, res = DoVerifyL(aResult));
69 if ((err != KErrNone) && (err != KErrArgument))
76 TBool CPKCS1SignatureResult::DoVerifyL(const TDesC8& aResult)
79 TASN1DecSequence decSeq;
81 TInt len = aResult.Length();
83 const CArrayPtrFlat<TASN1DecGeneric>* seq = decSeq.DecodeDERLC(aResult, pos);
84 if (seq->Count() == 2)
86 const TASN1DecGeneric* gen1 = seq->At(0);
87 const TASN1DecGeneric* gen2 = seq->At(1);
88 CAlgorithmIdentifier* algId = CX509AlgorithmIdentifier::NewLC(gen1->Encoding());
89 HBufC8* digest = gen2->GetContentDER().AllocL();
90 if ((*algId == *iDigestAlgorithm) && (*digest == *iDigest) && (pos == len))
95 CleanupStack::PopAndDestroy();
97 CleanupStack::PopAndDestroy();
102 EXPORT_C CRSAPublicKey* TX509KeyFactory::RSAPublicKeyL(const TDesC8& aEncoding) const
104 return CX509RSAPublicKey::NewL(aEncoding);
107 EXPORT_C CRSASignatureResult* TX509KeyFactory::RSASignatureResultL(const CAlgorithmIdentifier& aDigestAlgorithm, TDesC8& aDigest) const
109 return CPKCS1SignatureResult::NewL(aDigestAlgorithm, aDigest);
112 EXPORT_C CDSAPublicKey* TX509KeyFactory::DSAPublicKeyL(const TDesC8& aParamsEncoding, const TDesC8& aEncoding) const
114 return CX509DSAPublicKey::NewL(aParamsEncoding, aEncoding);
117 EXPORT_C CDSAPublicKey* TX509KeyFactory::DSAPublicKeyL(const CDSAParameters& aParams, const TDesC8& aEncoding) const
119 return CX509DSAPublicKey::NewL(aParams, aEncoding);
123 EXPORT_C CDSASignature* TX509KeyFactory::DSASignatureL(const TDesC8& aEncoding) const
125 return CX509DSASignature::NewL(aEncoding);
128 EXPORT_C CDSAParameters* TX509KeyFactory::DSAParametersL(const TDesC8& aParamsEncoding) const
130 return (CX509DSAPublicKey::DSAParametersL(aParamsEncoding));
133 //CX509ValidityPeriod
134 EXPORT_C CX509ValidityPeriod* CX509ValidityPeriod::NewL(const TDesC8& aBinaryData)
137 return CX509ValidityPeriod::NewL(aBinaryData, pos);
140 EXPORT_C CX509ValidityPeriod* CX509ValidityPeriod::NewLC(const TDesC8& aBinaryData)
143 return CX509ValidityPeriod::NewLC(aBinaryData, pos);
146 EXPORT_C CX509ValidityPeriod* CX509ValidityPeriod::NewL(const TDesC8& aBinaryData, TInt& aPos)
148 CX509ValidityPeriod* self = CX509ValidityPeriod::NewLC(aBinaryData, aPos);
153 EXPORT_C CX509ValidityPeriod* CX509ValidityPeriod::NewLC(const TDesC8& aBinaryData, TInt& aPos)
155 CX509ValidityPeriod* self = new(ELeave) CX509ValidityPeriod;
156 CleanupStack::PushL(self);
157 self->ConstructL(aBinaryData, aPos);
161 CX509ValidityPeriod::CX509ValidityPeriod()
165 void CX509ValidityPeriod::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
167 TASN1DecSequence encSeq;
168 CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos);
169 if (seq->Count() != 2)
171 User::Leave(KErrArgument);
173 TASN1DecX509Time decTime;
174 iStart = decTime.DecodeDERL(*(seq->At(0)));
175 iFinish = decTime.DecodeDERL(*(seq->At(1)));
176 CleanupStack::PopAndDestroy();//seq + contents
180 EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewL(const TDesC8& aBinaryData)
183 return CX509AlgorithmIdentifier::NewL(aBinaryData, pos);
186 EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewLC(const TDesC8& aBinaryData)
189 return CX509AlgorithmIdentifier::NewLC(aBinaryData, pos);
192 EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewL(const TDesC8& aBinaryData, TInt& aPos)
194 CX509AlgorithmIdentifier* self = CX509AlgorithmIdentifier::NewLC(aBinaryData, aPos);
199 EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewLC(const TDesC8& aBinaryData, TInt& aPos)
201 CX509AlgorithmIdentifier* self = new(ELeave) CX509AlgorithmIdentifier;
202 CleanupStack::PushL(self);
203 self->InitializeL(aBinaryData, aPos);
207 EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewL(TAlgorithmId aAlgorithmId, const TDesC8& aEncodedParams)
209 CX509AlgorithmIdentifier* self = CX509AlgorithmIdentifier::NewLC(aAlgorithmId, aEncodedParams);
214 EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewLC(TAlgorithmId aAlgorithmId, const TDesC8& aEncodedParams)
216 CX509AlgorithmIdentifier* self = new(ELeave) CX509AlgorithmIdentifier(aAlgorithmId);
217 CleanupStack::PushL(self);
218 self->ConstructL(aEncodedParams);
222 CX509AlgorithmIdentifier::CX509AlgorithmIdentifier(TAlgorithmId& aAlgorithmId):CAlgorithmIdentifier(aAlgorithmId)
227 CX509AlgorithmIdentifier::CX509AlgorithmIdentifier()
231 void CX509AlgorithmIdentifier::InitializeL(const TDesC8& aBinaryData, TInt& aPos)
233 TASN1DecSequence encSeq;
234 CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 1, KMaxTInt);
235 TInt count = seq->Count();
236 TASN1DecObjectIdentifier encOID;
237 HBufC* oid = encOID.DecodeDERL(*(seq->At(0)));
238 CleanupStack::PushL(oid);
239 TPtrC oidDes(oid->Des());
243 if (count > 1)//if we still have stuff left
245 TASN1DecGeneric* gen = seq->At(1);
246 iEncodedParams = gen->Encoding().AllocL();
250 iEncodedParams = HBufC8::NewL(1);
251 *iEncodedParams = KNullDesC8;
254 CleanupStack::PopAndDestroy(2);//seq, oid
259 TASN1DecGeneric* gen = seq->At(1);
262 iEncodedParams = gen->Encoding().AllocL();
264 CleanupStack::PopAndDestroy(2);//seq, oid
271 null.DecodeDERL(*gen);//just to check the syntax is OK
272 iEncodedParams = HBufC8::NewL(1);
273 *iEncodedParams = KNullDesC8;
274 CleanupStack::PopAndDestroy(2);//seq, oid
281 null.DecodeDERL(*gen);//just to check the syntax is OK
282 iEncodedParams = HBufC8::NewL(1);
283 *iEncodedParams = KNullDesC8;
284 CleanupStack::PopAndDestroy(2);//seq, oid
291 null.DecodeDERL(*gen);//just to check the syntax is OK
292 iEncodedParams = HBufC8::NewL(1);
293 *iEncodedParams = KNullDesC8;
294 CleanupStack::PopAndDestroy(2);//seq, oid
299 iAlgorithmId = ESHA1;
301 null.DecodeDERL(*gen);//just to check the syntax is OK
302 iEncodedParams = HBufC8::NewL(1);
303 *iEncodedParams = KNullDesC8;
304 CleanupStack::PopAndDestroy(2);//seq, oid
308 if (oidDes == KSHA224)
310 iAlgorithmId = ESHA224;
312 null.DecodeDERL(*gen);//just to check the syntax is OK
313 iEncodedParams = HBufC8::NewL(1);
314 *iEncodedParams = KNullDesC8;
315 CleanupStack::PopAndDestroy(2);//seq, oid
318 if (oidDes == KSHA256)
320 iAlgorithmId = ESHA256;
322 null.DecodeDERL(*gen);//just to check the syntax is OK
323 iEncodedParams = HBufC8::NewL(1);
324 *iEncodedParams = KNullDesC8;
325 CleanupStack::PopAndDestroy(2);//seq, oid
328 if (oidDes == KSHA384)
330 iAlgorithmId = ESHA384;
332 null.DecodeDERL(*gen);//just to check the syntax is OK
333 iEncodedParams = HBufC8::NewL(1);
334 *iEncodedParams = KNullDesC8;
335 CleanupStack::PopAndDestroy(2);//seq, oid
338 if (oidDes == KSHA512)
340 iAlgorithmId = ESHA512;
342 null.DecodeDERL(*gen);//just to check the syntax is OK
343 iEncodedParams = HBufC8::NewL(1);
344 *iEncodedParams = KNullDesC8;
345 CleanupStack::PopAndDestroy(2);//seq, oid
350 User::Leave(KErrNotSupported);
353 EXPORT_C CASN1EncSequence* CX509AlgorithmIdentifier::EncodeASN1DERLC() const
355 // the root sequence contains the signed object
356 CASN1EncSequence* root = CASN1EncSequence::NewLC();
359 CASN1EncObjectIdentifier* oid(NULL);
360 switch (iAlgorithmId)
363 oid=CASN1EncObjectIdentifier::NewLC(KDSA);
367 oid=CASN1EncObjectIdentifier::NewLC(KDH);
371 oid=CASN1EncObjectIdentifier::NewLC(KRSA);
375 oid=CASN1EncObjectIdentifier::NewLC(KMD5);
379 oid=CASN1EncObjectIdentifier::NewLC(KMD2);
383 oid=CASN1EncObjectIdentifier::NewLC(KSHA1);
387 oid=CASN1EncObjectIdentifier::NewLC(KSHA224);
391 oid=CASN1EncObjectIdentifier::NewLC(KSHA256);
395 oid=CASN1EncObjectIdentifier::NewLC(KSHA384);
399 oid=CASN1EncObjectIdentifier::NewLC(KSHA512);
403 User::Leave(KErrNotSupported);
406 root->AddAndPopChildL(oid);
409 if (*iEncodedParams!=KNullDesC8)
411 CASN1EncEncoding* enc=CASN1EncEncoding::NewLC(*iEncodedParams);
412 root->AddAndPopChildL(enc);
416 if (iAlgorithmId!=EDSA)
418 CASN1EncNull* enc=CASN1EncNull::NewLC();
419 root->AddAndPopChildL(enc);
427 //signing algorithm id
428 EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewL(const TDesC8& aBinaryData)
431 return CX509SigningAlgorithmIdentifier::NewL(aBinaryData, pos);
434 EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewLC(const TDesC8& aBinaryData)
437 return CX509SigningAlgorithmIdentifier::NewLC(aBinaryData, pos);
440 EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewL(const TDesC8& aBinaryData, TInt& aPos)
442 CX509SigningAlgorithmIdentifier* self = CX509SigningAlgorithmIdentifier::NewLC(aBinaryData, aPos);
447 EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewLC(const TDesC8& aBinaryData, TInt& aPos)
449 CX509SigningAlgorithmIdentifier* self = new(ELeave) CX509SigningAlgorithmIdentifier;
450 CleanupStack::PushL(self);
451 self->ConstructL(aBinaryData, aPos);
455 EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewL(const CAlgorithmIdentifier& aAsymmetricAlgorithm, const CAlgorithmIdentifier& aDigestAlgorithm)
457 CX509SigningAlgorithmIdentifier* self = CX509SigningAlgorithmIdentifier::NewLC(aAsymmetricAlgorithm, aDigestAlgorithm);
462 EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewLC(const CAlgorithmIdentifier& aAsymmetricAlgorithm, const CAlgorithmIdentifier& aDigestAlgorithm)
464 CX509SigningAlgorithmIdentifier* self = new(ELeave) CX509SigningAlgorithmIdentifier;
465 CleanupStack::PushL(self);
466 self->ConstructL(aAsymmetricAlgorithm, aDigestAlgorithm);
470 CX509SigningAlgorithmIdentifier::CX509SigningAlgorithmIdentifier()
474 void CX509SigningAlgorithmIdentifier::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
476 TASN1DecSequence encSeq;
477 CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 1, KMaxTInt);
478 TInt count = seq->Count();
479 TASN1DecObjectIdentifier encOID;
480 HBufC* oid = encOID.DecodeDERL(*(seq->At(0)));
481 CleanupStack::PushL(oid);
482 TPtrC oidDes(oid->Des());
483 //none of the signing algorithms we support have parameters here...
484 HBufC8* encodedParams = HBufC8::NewLC(1);
485 *encodedParams = KNullDesC8;
487 if (oidDes == KDSAWithSHA1)
489 //should be no params, but we allow params encoded as NULL for interop reasons
490 TAlgorithmId algId = EDSA;
491 TAlgorithmId digestId = ESHA1;
492 iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
493 iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
496 CleanupStack::PopAndDestroy(3);//seq, oid, encodedParams
501 if (oidDes == KMD2WithRSA)
503 TAlgorithmId algId = ERSA;
504 TAlgorithmId digestId = EMD2;
505 iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
506 iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
509 if (oidDes == KMD5WithRSA)
511 TAlgorithmId algId = ERSA;
512 TAlgorithmId digestId = EMD5;
513 iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
514 iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
517 if (oidDes == KSHA1WithRSA || oidDes == KSHA1WithRSASignature)
519 TAlgorithmId algId = ERSA;
520 TAlgorithmId digestId = ESHA1;
521 iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
522 iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
525 if (oidDes == KSHA224WithRSA)
527 TAlgorithmId algId = ERSA;
528 TAlgorithmId digestId = ESHA224;
529 iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
530 iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
533 if (oidDes == KSHA256WithRSA)
535 TAlgorithmId algId = ERSA;
536 TAlgorithmId digestId = ESHA256;
537 iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
538 iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
541 if (oidDes == KSHA384WithRSA)
543 TAlgorithmId algId = ERSA;
544 TAlgorithmId digestId = ESHA384;
545 iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
546 iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
549 if (oidDes == KSHA512WithRSA)
551 TAlgorithmId algId = ERSA;
552 TAlgorithmId digestId = ESHA512;
553 iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
554 iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
557 //???not sure if we should just leave here...
558 if (iDigestAlgorithm == NULL)
560 User::Leave(KErrNotSupported);
566 // Shouldn't ever get here, since RFC2459 mandates having 2
567 // data items. However, some people miss out the second
568 // when it's NULL, so we'll not report and error here
572 TASN1DecGeneric* gen = seq->At(1);
574 null.DecodeDERL(*gen);//just to check the syntax is OK
577 CleanupStack::PopAndDestroy(3);//seq, oid, encodedParams
580 void CX509SigningAlgorithmIdentifier::ConstructL(const CAlgorithmIdentifier& aAsymmetricAlgorithm, const CAlgorithmIdentifier& aDigestAlgorithm)
582 iDigestAlgorithm = CAlgorithmIdentifier::NewL(aDigestAlgorithm);
583 iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(aAsymmetricAlgorithm);
586 //subject public key info
587 EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewL(const TDesC8& aBinaryData, TInt& aPos)
589 CX509SubjectPublicKeyInfo* self = CX509SubjectPublicKeyInfo::NewLC(aBinaryData, aPos);
594 EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewLC(const TDesC8& aBinaryData, TInt& aPos)
596 CX509SubjectPublicKeyInfo* self = new(ELeave) CX509SubjectPublicKeyInfo;
597 CleanupStack::PushL(self);
598 self->ConstructL(aBinaryData, aPos);
602 EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewL(const TDesC8& aBinaryData)
605 return CX509SubjectPublicKeyInfo::NewL(aBinaryData, pos);
608 EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewLC(const TDesC8& aBinaryData)
611 return CX509SubjectPublicKeyInfo::NewLC(aBinaryData, pos);
614 CX509SubjectPublicKeyInfo::CX509SubjectPublicKeyInfo()
618 void CX509SubjectPublicKeyInfo::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
620 TASN1DecSequence encSeq;
621 CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 2, KMaxTInt);
622 iAlgId = CX509AlgorithmIdentifier::NewL(seq->At(0)->Encoding());
623 TASN1DecBitString encBS;
624 iEncodedKeyData = encBS.ExtractOctetStringL(*(seq->At(1)));
625 CleanupStack::PopAndDestroy();//seq
628 //generic X 509 extension syntax
629 EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const CX509CertExtension& aExtension)
631 CX509CertExtension* self = CX509CertExtension::NewLC(aExtension);
636 EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const CX509CertExtension& aExtension)
638 CX509CertExtension* self = new(ELeave) CX509CertExtension;
639 CleanupStack::PushL(self);
640 self->ConstructL(aExtension);
644 EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const TDesC8& aBinaryData, TInt& aPos)
646 CX509CertExtension* self = CX509CertExtension::NewLC(aBinaryData, aPos);
651 EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const TDesC8& aBinaryData, TInt& aPos)
653 CX509CertExtension* self = new(ELeave) CX509CertExtension;
654 CleanupStack::PushL(self);
655 self->ConstructL(aBinaryData, aPos);
659 EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const TDesC8& aBinaryData)
662 return CX509CertExtension::NewL(aBinaryData, pos);
665 EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const TDesC8& aBinaryData)
668 return CX509CertExtension::NewLC(aBinaryData, pos);
671 EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const TDesC& aCertExtOID,
672 const TBool aCritical,
673 const TDesC8& aCertExtValue)
675 CX509CertExtension* self = CX509CertExtension::NewLC(aCertExtOID, aCritical, aCertExtValue);
680 EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const TDesC& aCertExtOID,
681 const TBool aCritical,
682 const TDesC8& aCertExtValue)
684 CX509CertExtension* self = new(ELeave) CX509CertExtension;
685 CleanupStack::PushL(self);
686 self->ConstructL(aCertExtOID, aCritical, aCertExtValue);
690 void CX509CertExtension::ConstructL(const CX509CertExtension& aExtension)
692 iCritical = aExtension.iCritical;
693 iId = aExtension.iId->Des().AllocL();
694 iData = aExtension.iData->Des().AllocL();
697 void CX509CertExtension::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
699 TASN1DecSequence encSeq;
700 CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 2, KMaxTInt);
702 TASN1DecObjectIdentifier encOID;
703 iId = encOID.DecodeDERL(*(seq->At(0)));
704 //second is either critical flag, or the ext
705 TASN1DecGeneric* second = seq->At(1);
706 if (second->Tag() != EASN1Boolean)
708 iData = second->Encoding().AllocL();
709 aPos += second->LengthDER();
713 TASN1DecBoolean encBool;
714 iCritical = encBool.DecodeDERL(*second);
715 if (seq->Count() != 3)
717 User::Leave(KErrArgument);
720 TASN1DecGeneric* third = seq->At(2);
721 iData = third->Encoding().AllocL();
723 CleanupStack::PopAndDestroy();//seq
726 void CX509CertExtension::ConstructL(const TDesC& aCertExtOID,
727 const TBool aCritical,
728 const TDesC8& aCertExtValue)
730 iId = aCertExtOID.AllocL();
731 iCritical = aCritical;
732 iData = aCertExtValue.AllocL();
735 EXPORT_C CX509CertExtension::~CX509CertExtension()
741 EXPORT_C TBool CX509CertExtension::Critical() const
746 EXPORT_C TPtrC CX509CertExtension::Id() const //OID for the extension
751 EXPORT_C TPtrC8 CX509CertExtension::Data() const //the extension itself
756 EXPORT_C CASN1EncSequence* CX509CertExtension::EncodeASN1DERLC() const
758 CASN1EncSequence *result = CASN1EncSequence::NewLC();
759 CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(*iId);
760 result->AddAndPopChildL(oid);
761 // Encode critical flag only if true
764 CASN1EncBoolean *critical = CASN1EncBoolean::NewLC(iCritical);
765 result->AddAndPopChildL(critical);
767 CASN1EncOctetString *data = CASN1EncOctetString::NewLC(*iData);
768 result->AddAndPopChildL(data);
772 CX509CertExtension::CX509CertExtension()
778 EXPORT_C CX509Certificate* CX509Certificate::NewL(const CX509Certificate& aCert)
780 CX509Certificate* self = CX509Certificate::NewLC(aCert);
781 CleanupStack::Pop();//self
785 EXPORT_C CX509Certificate* CX509Certificate::NewLC(const CX509Certificate& aCert)
787 CX509Certificate* self = new(ELeave) CX509Certificate;
788 CleanupStack::PushL(self);
789 self->ConstructL(aCert);
793 EXPORT_C CX509Certificate* CX509Certificate::NewL(const TDesC8& aBinaryData)
796 return CX509Certificate::NewL(aBinaryData, pos);
799 EXPORT_C CX509Certificate* CX509Certificate::NewLC(const TDesC8& aBinaryData)
802 return CX509Certificate::NewLC(aBinaryData, pos);
805 EXPORT_C CX509Certificate* CX509Certificate::NewL(const TDesC8& aBinaryData, TInt& aPos)
807 CX509Certificate* self = CX509Certificate::NewLC(aBinaryData, aPos);
812 EXPORT_C CX509Certificate* CX509Certificate::NewLC(const TDesC8& aBinaryData, TInt& aPos)
814 CX509Certificate* self = new(ELeave) CX509Certificate();
815 CleanupStack::PushL(self);
816 self->ConstructL(aBinaryData, aPos);
820 EXPORT_C CX509Certificate* CX509Certificate::NewL(RReadStream& aStream)
822 CX509Certificate* self = CX509Certificate::NewLC(aStream);
823 CleanupStack::Pop();//self
827 EXPORT_C CX509Certificate* CX509Certificate::NewLC(RReadStream& aStream)
829 CX509Certificate* self = new(ELeave) CX509Certificate;
830 CleanupStack::PushL(self);
831 self->InternalizeL(aStream);
835 void CX509Certificate::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
837 TASN1DecGeneric gen(aBinaryData.Right(aBinaryData.Length() - aPos));
840 // The outermost tag for X509 certificates is always a sequence.
841 // Since this tag does not form part of the signed data it is possible
842 // to corrupt the tag by changing it to any other ASN.1 tag and process
843 // the rest of the certificate as normal.
844 // However, we still reject the certificate anyway to avoid
845 // confusion because the data does not match the X.509 specification.
846 if (gen.Tag() != EASN1Sequence)
848 User::Leave(KErrArgument);
851 aPos += gen.LengthDER();
852 iKeyFactory = new(ELeave) TX509KeyFactory;
854 iEncoding = gen.Encoding().AllocL();
856 TASN1DecSequence encSeq;
858 CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(*iEncoding, pos, 3, 3);
859 TASN1DecGeneric* encSigAlg = seq->At(1);
860 iSigningAlgorithm = CX509SigningAlgorithmIdentifier::NewL(encSigAlg->Encoding());
861 TASN1DecBitString encBS;
862 iSignature = encBS.ExtractOctetStringL(*(seq->At(2)));
863 CleanupStack::PopAndDestroy();//seq
865 CSHA1* hash = CSHA1::NewL();
866 CleanupStack::PushL(hash);
867 iFingerprint = hash->Final(Encoding()).AllocL();
868 CleanupStack::PopAndDestroy();//hash
872 void CX509Certificate::ConstructL(const CX509Certificate& aCertificate)
874 iKeyFactory = new(ELeave) TX509KeyFactory;
876 iEncoding = aCertificate.iEncoding->AllocL();
877 iSignature = aCertificate.iSignature->AllocL();
878 iFingerprint = aCertificate.iFingerprint->AllocL();
879 iSigningAlgorithm = CSigningAlgorithmIdentifier::NewL(aCertificate.SigningAlgorithm());
880 iSerialNumber = aCertificate.iSerialNumber->Des().AllocL();
881 iIssuerName = CX500DistinguishedName::NewL(*(aCertificate.iIssuerName));
882 iValidityPeriod = new(ELeave) CValidityPeriod(*(aCertificate.iValidityPeriod));
883 iSubjectName = CX500DistinguishedName::NewL(*(aCertificate.iSubjectName));
884 iSubjectPublicKeyInfo = CSubjectPublicKeyInfo::NewL(*(aCertificate.iSubjectPublicKeyInfo));
885 iIssuerUid = aCertificate.iIssuerUid->Des().AllocL();
886 iSubjectUid = aCertificate.iSubjectUid->Des().AllocL();
887 iExtensions = new(ELeave) CArrayPtrFlat<CX509CertExtension> (1);
888 TInt count = aCertificate.iExtensions->Count();
889 for (TInt i = 0; i < count; i++)
891 CX509CertExtension* ext = CX509CertExtension::NewLC(*aCertificate.iExtensions->At(i));
892 iExtensions->AppendL(ext);
893 CleanupStack::Pop();//ext
895 iVersion = aCertificate.Version();
896 InitDataElementsL(aCertificate);
899 void CX509Certificate::InitDataElementsL(const CX509Certificate& aCertificate)
901 iDataElements = new(ELeave) TFixedArray<TPtrC8*, KX509MaxDataElements>;
902 iDataElements->Reset();
903 TPtrC8 signedData = SignedDataL();
904 TASN1DecSequence encSeq;
906 CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(signedData, pos, 6, KMaxTInt);//6 is the minimum number of elements in an x509 cert
909 TPtrC8** pElement = iDataElements->Begin();
910 *pElement++ = aCertificate.DataElementEncoding(CX509Certificate::EVersionNumber)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
911 for (TInt i = 0; i < 6; i++) //init all the non-optional elements
913 *pElement++ = new(ELeave) TPtrC8(seq->At(pos++)->Encoding());
915 *pElement++ = aCertificate.DataElementEncoding(CX509Certificate::EIssuerUID)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
916 *pElement++ = aCertificate.DataElementEncoding(CX509Certificate::ESubjectUID)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
917 *pElement++ = aCertificate.DataElementEncoding(CX509Certificate::EExtensionList)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
918 CleanupStack::PopAndDestroy();
921 void CX509Certificate::ConstructCertL()
923 TPtrC8 signedData = SignedDataL();
924 TASN1DecSequence encSeq;
926 CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(signedData, pos, 6, KMaxTInt);//6 is the minimum number of elements in an x509 cert
927 TInt count = seq->Count();
929 TASN1DecGeneric* curr = seq->At(pos);
931 iDataElements = new(ELeave) TFixedArray<TPtrC8*, KX509MaxDataElements>;
932 iDataElements->Reset();
933 TPtrC8** pElement = iDataElements->Begin();
934 if ((curr->Class() == EContextSpecific) && (curr->Tag() == 0))
937 TASN1DecGeneric ver(curr->GetContentDER());
939 TPtrC8 pVer8 = ver.GetContentDER();
940 if(pVer8.Length() != 1)
942 User::Leave(KErrArgument);
944 iVersion = (pVer8[0]) + 1;
945 if ((iVersion < 1) || (iVersion > 3) || (count < 7))
947 User::Leave(KErrArgument);
949 *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
957 if (curr->Tag() != EASN1Integer)
959 User::Leave(KErrArgument);
961 iSerialNumber = (curr->GetContentDER()).AllocL();
962 *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
965 CX509SigningAlgorithmIdentifier* algorithmId = CX509SigningAlgorithmIdentifier::NewLC(curr->Encoding());
966 if (!(SigningAlgorithm() == *(algorithmId)))
968 User::Leave(KErrArgument);
970 CleanupStack::PopAndDestroy();//algorithmId
971 *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
975 iIssuerName = CX500DistinguishedName::NewL(curr->Encoding());
976 *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
979 iValidityPeriod = CX509ValidityPeriod::NewL(curr->Encoding());
980 *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
983 iSubjectName = CX500DistinguishedName::NewL(curr->Encoding());
984 *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
987 iSubjectPublicKeyInfo = CX509SubjectPublicKeyInfo::NewL(curr->Encoding());
988 *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
989 //do issuer uid, subject uid, exts
990 //these are all optional
991 TBool hasIssuerUid = EFalse;
992 TBool hasSubjectUid = EFalse;
993 TBool hasExts = EFalse;
994 iExtensions = new(ELeave)CArrayPtrFlat<CX509CertExtension> (1);
995 if (pos < count)//otherwise there aren't any of 'em
999 if (curr->Class() != EContextSpecific)
1001 User::Leave(KErrArgument);
1007 iIssuerUid = DecodeUidL(curr->GetContentDER(), hasIssuerUid);
1008 *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
1013 iSubjectUid = DecodeUidL(curr->GetContentDER(), hasSubjectUid);
1015 *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
1020 DecodeExtsL(curr->GetContentDER(), hasExts);
1023 *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
1028 User::Leave(KErrArgument);
1033 curr = seq->At(pos);
1039 iSubjectUid = DecodeUidL(curr->GetContentDER(), hasSubjectUid);
1040 *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
1045 DecodeExtsL(curr->GetContentDER(), hasExts);
1047 *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
1052 User::Leave(KErrArgument);
1057 curr = seq->At(pos);
1059 if (curr->Tag() == 3)
1061 DecodeExtsL(curr->GetContentDER(), hasExts);
1062 *pElement++ = new(ELeave) TPtrC8(curr->Encoding());
1066 User::Leave(KErrArgument);
1073 User::Leave(KErrArgument);
1077 iIssuerUid = HBufC8::NewL(1);
1078 *iIssuerUid = KNullDesC8;
1082 iSubjectUid = HBufC8::NewL(1);
1083 *iSubjectUid = KNullDesC8;
1086 // we have not checked for the certificate version number based on
1087 // the certificate contents. This is primarily done to avoid BC for
1088 // clients who are still using malformed certificates.
1090 CleanupStack::PopAndDestroy();//seq
1093 CX509Certificate::CX509Certificate()
1098 EXPORT_C CX509Certificate::~CX509Certificate()
1101 delete iSubjectName;
1105 if (iDataElements != NULL)
1107 for (TInt i = 0; i < KX509MaxDataElements; i++)
1109 delete iDataElements->At(i);
1111 delete iDataElements;
1113 if (iExtensions != NULL)
1115 iExtensions->ResetAndDestroy();
1120 EXPORT_C TBool CX509Certificate::IsEqualL(const CX509Certificate& aCert) const
1122 return ( (*(iSerialNumber) == *(aCert.iSerialNumber)) &&
1123 (iIssuerName->ExactMatchL(*(aCert.iIssuerName))) );
1126 EXPORT_C void CX509Certificate::InternalizeL(RReadStream& aStream)
1128 if (iIssuerName != NULL) //just to check cert is uninitialised
1130 User::Leave(KErrArgument);
1132 iKeyFactory = new(ELeave) TX509KeyFactory;
1134 TInt len = aStream.ReadInt32L(); //Read the length of the streamed encoding
1135 HBufC8* temp= HBufC8::NewLC(len);
1136 TPtr8 ptr=temp->Des();
1137 aStream.ReadL(ptr,len);
1138 iEncoding=temp->AllocL();
1139 CleanupStack::PopAndDestroy(); // temp
1141 TASN1DecSequence encSeq;
1143 CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(*iEncoding, pos, 3, 3);
1144 TASN1DecGeneric* encSigAlg = seq->At(1);
1145 iSigningAlgorithm = CX509SigningAlgorithmIdentifier::NewL(encSigAlg->Encoding());
1146 TASN1DecBitString encBS;
1147 iSignature = encBS.ExtractOctetStringL(*(seq->At(2)));
1148 CleanupStack::PopAndDestroy();//seq
1150 CSHA1* hash = CSHA1::NewL();
1151 CleanupStack::PushL(hash);
1152 iFingerprint = hash->Final(Encoding()).AllocL();
1153 CleanupStack::PopAndDestroy();//hash
1158 void CX509Certificate::DecodeExtsL(const TDesC8& aBinaryData, TBool& aHasElementAlready)
1160 TASN1DecSequence encSeq;
1162 CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, pos);
1163 TInt count = seq->Count();
1164 for (TInt i = 0; i < count; i++)
1166 TASN1DecGeneric* gen = seq->At(i);
1167 CX509CertExtension* ext = CX509CertExtension::NewLC(gen->Encoding());
1168 iExtensions->AppendL(ext);
1169 CleanupStack::Pop();//ext
1171 CleanupStack::PopAndDestroy();//
1172 aHasElementAlready = ETrue;
1175 HBufC8* CX509Certificate::DecodeUidL(const TDesC8& aBinaryData, TBool& aHasElementAlready)
1177 if ((aHasElementAlready) || (iVersion ==1))
1179 User::Leave(KErrArgument);
1181 aHasElementAlready = ETrue;
1182 return aBinaryData.AllocL();
1185 //***************************************************************************************//
1187 EXPORT_C const TPtrC8 CX509Certificate::SignedDataL() const
1189 TASN1DecSequence encSeq;
1191 CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(*iEncoding, pos, 3, 3);
1192 TASN1DecGeneric* gen = seq->At(0);
1193 TPtrC8 res = gen->Encoding();
1194 CleanupStack::PopAndDestroy();
1198 EXPORT_C TInt CX509Certificate::Version() const
1204 * If the certificate has decoded the members from TeletexString then the return value
1205 * may be incorrect because TeletexString type is not fully supported by this library.
1206 * Instead the decode methods perform a direct conversion from 8 to 16bits by adding
1207 * null characters in the second byte of each character. This will work as expected
1208 * for cases where the string contains ASCII data.
1210 EXPORT_C const CX500DistinguishedName& CX509Certificate::IssuerName() const
1212 return *iIssuerName;
1216 * If the certificate has decoded the members from TeletexString then the return value
1217 * may be incorrect because TeletexString type is not fully supported by this library.
1218 * Instead the decode methods perform a direct conversion from 8 to 16bits by adding
1219 * null characters in the second byte of each character. This will work as expected
1220 * for cases where the string contains ASCII data.
1222 EXPORT_C const CX500DistinguishedName& CX509Certificate::SubjectName() const
1224 return *iSubjectName;
1227 EXPORT_C const CArrayPtrFlat<CX509CertExtension>& CX509Certificate::Extensions() const
1229 return *iExtensions;
1232 EXPORT_C const CX509CertExtension* CX509Certificate::Extension(const TDesC& aExtensionName) const
1234 TInt count = iExtensions->Count();
1235 for (TInt i = 0; i < count; i++)
1237 CX509CertExtension* ext = iExtensions->At(i);
1238 if (ext->Id() == aExtensionName)
1244 EXPORT_C const TPtrC8* CX509Certificate::DataElementEncoding(const TUint aIndex) const
1246 return iDataElements->At(aIndex);
1250 * If the certificate has decoded the members from TeletexString then the return value
1251 * may be incorrect because TeletexString type is not fully supported by this library.
1252 * Instead the decode methods perform a direct conversion from 8 to 16bits by adding
1253 * null characters in the second byte of each character. This will work as expected
1254 * for cases where the string contains ASCII data.
1256 EXPORT_C HBufC* CX509Certificate::IssuerL() const
1258 return iIssuerName->DisplayNameL();
1262 * If the certificate has decoded the members from TeletexString then the return value
1263 * may be incorrect because TeletexString type is not fully supported by this library.
1264 * Instead the decode methods perform a direct conversion from 8 to 16bits by adding
1265 * null characters in the second byte of each character. This will work as expected
1266 * for cases where the string contains ASCII data.
1268 EXPORT_C HBufC* CX509Certificate::SubjectL() const
1270 return iSubjectName->DisplayNameL();
1273 EXPORT_C TBool CX509Certificate::IsSelfSignedL() const
1275 if (iSubjectName->Count() > 0)
1277 return iSubjectName->ExactMatchL(*iIssuerName);
1282 const CX509CertExtension* subjectExt = Extension(KIssuerAltName);
1283 const CX509CertExtension* issuerExt = Extension(KSubjectAltName);
1284 if ((subjectExt) && (issuerExt))
1286 const CX509AltNameExt* issuerAltName = CX509AltNameExt::NewLC(subjectExt->Data());
1287 const CX509AltNameExt* subjectAltName = CX509AltNameExt::NewLC(issuerExt->Data());
1288 if (subjectAltName->Match(*issuerAltName))
1292 CleanupStack::PopAndDestroy(2);//subjectAltName, issuerAltName
1299 EXPORT_C TKeyIdentifier CX509Certificate::KeyIdentifierL() const
1301 if (iSubjectPublicKeyInfo->AlgorithmId() != EDSA)
1303 // The base class handles the RSA case and leaves with KErrNotSupported if
1305 return CCertificate::KeyIdentifierL();
1309 // This handles the DSA case
1310 CDSAPublicKey* dsaKey =
1311 iKeyFactory->DSAPublicKeyL(iSubjectPublicKeyInfo->EncodedParams(),
1312 iSubjectPublicKeyInfo->KeyData());
1313 CleanupStack::PushL(dsaKey);
1314 TKeyIdentifier retVal;
1315 KeyIdentifierUtil::DSAKeyIdentifierL(*dsaKey, retVal);
1316 CleanupStack::PopAndDestroy(dsaKey);
1321 EXPORT_C TKeyIdentifier CX509Certificate::SubjectKeyIdentifierL() const
1323 const CX509CertExtension* subjectKeyIdExtStr = this->Extension(KSubjectKeyId);
1324 if (subjectKeyIdExtStr)
1327 CX509SubjectKeyIdExt *subjectKeyIdExt = CX509SubjectKeyIdExt::NewLC(subjectKeyIdExtStr->Data());
1328 // Currently, we do not support key identifiers larger than 160 bits - make sure not to overflow the descriptor
1329 if (subjectKeyIdExt->KeyId().Length() <= ret.MaxLength())
1331 ret.Copy(subjectKeyIdExt->KeyId());
1332 CleanupStack::PopAndDestroy(subjectKeyIdExt);
1335 CleanupStack::PopAndDestroy(subjectKeyIdExt);
1338 return KeyIdentifierL();
1342 EXPORT_C TKeyIdentifier CX509Certificate::SubjectKeyIdL() const
1344 // 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.
1347 return SubjectKeyIdentifierL();
1350 // if it is x509 v3 certificate then check for the basic constraint extension.
1351 const CX509CertExtension* ext = Extension(KBasicConstraints);
1354 CX509BasicConstraintsExt* basic = CX509BasicConstraintsExt::NewLC(ext->Data());
1355 TBool markedAsCA = basic->IsCA();
1356 CleanupStack::PopAndDestroy(basic);
1357 // it can be an intermediate as well as root CA
1360 return SubjectKeyIdentifierL();
1363 // For non-CA certs, use the recommended method of computing it from RFC5280, section 4.2.1.2
1364 return KeyIdentifierL();