First public contribution.
2 * Copyright (c) 1998-2009 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.
23 * __SECURITY_PLATSEC_ARCH__: Changes for platform security
25 * If this macro is defined, the represenation of TPtrC arrays is changed from
26 * using CPtrCArray to RArray<TPtrC>. This is because CPtrCArray is supplied by
27 * bafl.dll, which is not trusted for TCB. x509 needs to be trusted for TCB so
28 * it can be used by software install, hence this dependency was removed.
30 * This changes is implmented as a series of macros for the basic operations,
31 * to minimise the amount of conditional compilation.
35 #define REP_INIT_L /* do nothing */
36 #define REP_FINAL iRep.Close()
37 #define REP_APPEND_L(X) User::LeaveIfError(iRep.Append(X))
38 #define REP_COUNT iRep.Count()
39 #define REP_AT(X) iRep[X]
41 #define REP_VAL_TYPE RArray<TPtrC>
44 _LIT(KX509RFC822HostDomainSeparator,"@");
45 _LIT(KX509SubdomainSeparator,".");
46 _LIT(KX509URISchemeSpecificStart, "//");
47 _LIT(KX509URIUserPasswordEnd, "@");
48 _LIT(KX509URIPortStart, ":");
49 _LIT(KX509URIurlPathStart, "/");
51 const TInt KX509URISchemeSpecificStartLength = 2;
52 const TInt KX509URIUserPasswordEndLength = 1;
53 const TInt KX509MaxDNSNameLabelLength = 63;
55 //superclass: common functionality for DNS names & RFC 822 email addresses
56 EXPORT_C CX509DomainName::~CX509DomainName()
62 CX509DomainName::CX509DomainName()
66 EXPORT_C TPtrC CX509DomainName::Name() const
71 EXPORT_C TBool CX509DomainName::IsWithinSubtree(const CX509DomainName& aName) const
73 TInt myCount = REP_COUNT;
74 TInt otherCount = aName.REP_COUNT;
75 if (otherCount > myCount)
79 for (TInt i = otherCount-1; i >= 0; i--)
82 if ( KErrNotFound == REP_AT(myCount).MatchF(aName.REP_AT(i)) )
90 TBool CX509DomainName::AddDomainL(TInt& aPos)
92 TInt end = iName->Length();
95 if (!(AddSubdomainL(aPos)))
103 AddSubdomainSeparatorL(aPos);
108 TBool CX509DomainName::AddSubdomainL(TInt& aPos)
111 TInt end = iName->Length();
116 TPtrC whatsLeft(&(iName->operator[] (aPos)), end - aPos);
117 TInt subdomainEnd = whatsLeft.FindF(KX509SubdomainSeparator);
118 if (subdomainEnd == 0)
122 if (subdomainEnd == KErrNotFound)
124 subdomainEnd = end - aPos;
126 TPtrC subdomain(&whatsLeft[0], subdomainEnd);
127 if (IsValidString(subdomain))
129 REP_APPEND_L(subdomain);
132 aPos = aPos + subdomainEnd;
136 TBool CX509DomainName::AddSubdomainSeparatorL(TInt& aPos)
139 TInt end = iName->Length();
144 TPtrC whatsLeft(&(iName->operator[] (aPos)), end - aPos);
145 TInt separatorEnd = whatsLeft.FindF(KX509SubdomainSeparator);
146 if (separatorEnd == 0)
148 TPtrC separator(&whatsLeft[0], 1);
149 REP_APPEND_L(separator);
156 TBool CX509DomainName::IsValidString(const TDesC& aStr) const
159 TInt end=aStr.Length()-1;
164 while (pos<end && IsValidChar(aStr[pos]))
168 return (pos==end && IsValidChar(aStr[end]));
171 TBool CX509DomainName::IsAlpha(const TChar& aChar) const
173 return ( ((aChar >= 97) && (aChar <= 122)) ||
174 ((aChar >= 65) && (aChar <= 90)) );
177 TBool CX509DomainName::IsAlphaOrNum(const TChar& aChar) const
179 return ((IsAlpha(aChar)) ||
180 ((aChar >= 48) && (aChar <= 57)) || (aChar == 42));
183 TBool CX509DomainName::IsValidChar(const TChar& aChar) const
185 //default implementation: must be letter, number or hyphen
186 return ((IsAlphaOrNum(aChar)) ||
187 (aChar == 45) || (aChar == 42));
190 //RFC 822 email address
192 EXPORT_C CX509RFC822NameSubtree* CX509RFC822NameSubtree::NewL(const TDesC8& aBinaryData)
194 CX509RFC822NameSubtree* self = CX509RFC822NameSubtree::NewLC(aBinaryData);
195 CleanupStack::Pop();//self
199 EXPORT_C CX509RFC822NameSubtree* CX509RFC822NameSubtree::NewLC(const TDesC8& aBinaryData)
201 CX509RFC822NameSubtree* self = new(ELeave) CX509RFC822NameSubtree;
202 CleanupStack::PushL(self);
203 self->ConstructL(aBinaryData);
207 void CX509RFC822NameSubtree::ConstructL(const TDesC8& aBinaryData)
210 TASN1DecIA5String encStr;
211 iName = encStr.DecodeDERL(aBinaryData, pos);
213 //now, parse your data
216 AddSubdomainSeparatorL(pos);
217 if (!(AddDomainL(pos)))
219 User::Leave(KErrArgument);
223 TBool CX509RFC822NameSubtree::AddLocalHostL(TInt& aPos)
225 TInt localHostLength = iName->FindF(KX509RFC822HostDomainSeparator);
226 if ((localHostLength != KErrNotFound) && (localHostLength > 0))
228 TPtrC localHost(&(iName->operator[] (aPos)), localHostLength);
229 //the local host name is not checked here as it caused defect PDEF108960
230 //and for compatability with IE and Firefox.
231 REP_APPEND_L(localHost);
232 aPos = aPos + localHostLength;
233 aPos++; //skip the @ symbol
236 return EFalse; //local host not found
240 EXPORT_C const REP_VAL_TYPE& CX509RFC822NameSubtree::Rep() const
245 TBool CX509RFC822NameSubtree::IsValidChar(const TChar& aChar) const
247 //we permit "." here, 'cos it's allowed in local host names
248 //and must have been stripped out by domain parsing code,
249 //since it's the separator char
250 return ( (aChar == 33) ||
251 ((aChar >= 35) && (aChar <= 40)) ||
254 ((aChar >= 45) && (aChar <= 57)) ||
257 ((aChar >= 65) && (aChar <= 90)) ||
258 ((aChar >= 94) && (aChar <= 126)) );
261 //full rfc 822 name: exactly as subtree, but requires local host and full domain name
262 EXPORT_C CX509RFC822Name* CX509RFC822Name::NewL(const TDesC8& aBinaryData)
264 CX509RFC822Name* self = CX509RFC822Name::NewLC(aBinaryData);
265 CleanupStack::Pop();//self
269 EXPORT_C CX509RFC822Name* CX509RFC822Name::NewLC(const TDesC8& aBinaryData)
271 CX509RFC822Name* self = new(ELeave) CX509RFC822Name;
272 CleanupStack::PushL(self);
273 self->ConstructL(aBinaryData);
277 void CX509RFC822Name::ConstructL(const TDesC8& aBinaryData)
280 TASN1DecIA5String encStr;
281 iName = encStr.DecodeDERL(aBinaryData, pos);
283 //now, parse your data
285 if (! ((AddLocalHostL(pos)) && (AddDomainL(pos))) )
287 User::Leave(KErrArgument);
292 EXPORT_C CX509DNSNameSubtree* CX509DNSNameSubtree::NewL(const TDesC8& aBinaryData)
294 CX509DNSNameSubtree* self = CX509DNSNameSubtree::NewLC(aBinaryData);
295 CleanupStack::Pop();//self
299 EXPORT_C CX509DNSNameSubtree* CX509DNSNameSubtree::NewLC(const TDesC8& aBinaryData)
301 CX509DNSNameSubtree* self = new(ELeave) CX509DNSNameSubtree;
302 CleanupStack::PushL(self);
303 self->ConstructL(aBinaryData);
307 void CX509DNSNameSubtree::ConstructL(const TDesC8& aBinaryData)
310 TASN1DecIA5String encStr;
311 iName = encStr.DecodeDERL(aBinaryData, pos);
314 AddSubdomainSeparatorL(pos);//a subtree may start with a period
315 if (!(AddDomainL(pos)))
317 User::Leave(KErrArgument);
321 EXPORT_C const REP_VAL_TYPE& CX509DNSNameSubtree::Rep() const
326 TBool CX509DNSNameSubtree::IsValidString(const TDesC& aStr) const
328 //must be <= 63 chars long
329 //must start with letter, end with letter or number
330 TInt len = aStr.Length();
331 return ( (len <= KX509MaxDNSNameLabelLength) &&
332 (IsAlphaOrNum(aStr[0])) &&
333 (IsAlphaOrNum(aStr[len-1])) &&
334 (CX509DomainName::IsValidString(aStr)) );
337 //dns name: exactly as subtree but requires full domain name
338 EXPORT_C CX509DNSName* CX509DNSName::NewL(const TDesC8& aBinaryData)
340 CX509DNSName* self = CX509DNSName::NewLC(aBinaryData);
341 CleanupStack::Pop();//self
345 EXPORT_C CX509DNSName* CX509DNSName::NewLC(const TDesC8& aBinaryData)
347 CX509DNSName* self = new(ELeave) CX509DNSName;
348 CleanupStack::PushL(self);
349 self->ConstructL(aBinaryData);
353 EXPORT_C CX509DNSName* CX509DNSName::NewL(const CX509DNSName& aName)
355 CX509DNSName* self = CX509DNSName::NewLC(aName);
356 CleanupStack::Pop();//self
360 EXPORT_C CX509DNSName* CX509DNSName::NewLC(const CX509DNSName& aName)
362 CX509DNSName* self = new(ELeave) CX509DNSName;
363 CleanupStack::PushL(self);
364 self->ConstructL(aName);
369 EXPORT_C CX509DNSName* CX509DNSName::NewL(const TDesC& aNameString)
371 CX509DNSName* self = CX509DNSName::NewLC(aNameString);
372 CleanupStack::Pop();//self
376 EXPORT_C CX509DNSName* CX509DNSName::NewLC(const TDesC& aNameString)
378 CX509DNSName* self = new(ELeave) CX509DNSName;
379 CleanupStack::PushL(self);
380 self->ConstructL(aNameString);
384 void CX509DNSName::ConstructL(const TDesC& aNameString)
388 iName = aNameString.AllocL();
389 AddSubdomainSeparatorL(pos);//a subtree may start with a period
390 if (!(AddDomainL(pos)))
392 User::Leave(KErrArgument);
396 void CX509DNSName::ConstructL(const TDesC8& aBinaryData)
399 TASN1DecIA5String encStr;
400 iName = encStr.DecodeDERL(aBinaryData, pos);
404 void CX509DNSName::ConstructL(const CX509DNSName& aName)
406 iName = aName.iName->AllocL();
410 void CX509DNSName::ParseNameL()
414 if (!AddDomainL(pos))
416 User::Leave(KErrArgument);
420 //URI: must be of 'ip-based' form (rfc 1738 section 3.1)
421 //_and_ contain a domain name (not an IP address)
422 EXPORT_C CX509IPBasedURI* CX509IPBasedURI::NewL(const TDesC8& aBinaryData)
424 CX509IPBasedURI* self = CX509IPBasedURI::NewLC(aBinaryData);
425 CleanupStack::Pop();//self
429 EXPORT_C CX509IPBasedURI* CX509IPBasedURI::NewLC(const TDesC8& aBinaryData)
431 CX509IPBasedURI* self = new(ELeave) CX509IPBasedURI;
432 CleanupStack::PushL(self);
433 self->ConstructL(aBinaryData);
437 void CX509IPBasedURI::ConstructL(const TDesC8& aBinaryData)
440 TASN1DecIA5String encStr;
441 iName = encStr.DecodeDERL(aBinaryData, pos);
442 iHost = CX509DNSName::NewL(ExtractHostNameL());
445 EXPORT_C CX509IPBasedURI::~CX509IPBasedURI()
451 CX509IPBasedURI::CX509IPBasedURI()
452 :iHost(NULL), iName(NULL)
456 EXPORT_C const CX509DNSName& CX509IPBasedURI::Host() const
461 EXPORT_C TPtrC CX509IPBasedURI::Name() const
466 TPtrC CX509IPBasedURI::ExtractHostNameL() const
470 TInt len = iName->Length();
471 TInt schemeSpecificStart = (iName->FindF(KX509URISchemeSpecificStart) + KX509URISchemeSpecificStartLength);
472 TInt userPasswordEnd = (iName->FindF(KX509URIUserPasswordEnd)) + KX509URIUserPasswordEndLength;
473 hostStart = ((userPasswordEnd == 0)? schemeSpecificStart : userPasswordEnd);
474 if (hostStart == KErrNotFound)
476 User::Leave(KErrArgument);
478 TPtrC whatsLeft(&(iName->operator[](hostStart)), len - hostStart);
479 TInt newlen = whatsLeft.Length();
480 TInt portStart = whatsLeft.FindF(KX509URIPortStart);
481 TInt urlPathStart = whatsLeft.FindF(KX509URIurlPathStart);
482 if (portStart == KErrNotFound)
484 if (urlPathStart == KErrNotFound)
490 hostEnd = urlPathStart;
495 if (urlPathStart == KErrNotFound)
499 else //both are there, choose the first one
501 hostEnd = ((urlPathStart > portStart)? portStart: urlPathStart);
504 TPtrC host(&(iName->operator[](hostStart)), hostEnd);
510 EXPORT_C CX509IPSubnetMask* CX509IPSubnetMask::NewL(const TDesC8& aBinaryData)
512 CX509IPSubnetMask* self = CX509IPSubnetMask::NewLC(aBinaryData);
513 CleanupStack::Pop();//self;
517 EXPORT_C CX509IPSubnetMask* CX509IPSubnetMask::NewLC(const TDesC8& aBinaryData)
519 CX509IPSubnetMask* self = new(ELeave) CX509IPSubnetMask;
520 CleanupStack::PushL(self);
521 self->ConstructL(aBinaryData);
525 void CX509IPSubnetMask::ConstructL(const TDesC8& aBinaryData)
527 //!!!need to correct this when we have octet strings going!!!
528 TASN1DecGeneric encAddr(aBinaryData);
530 iName = encAddr.GetContentDER().AllocL();// = CASN1OctetString::DecodeDERL(aBinaryData, pos);
531 TInt len = iName->Length();
532 if (!((len == 8) || (len == 32)))
534 User::Leave(KErrArgument);
538 EXPORT_C CX509IPSubnetMask::~CX509IPSubnetMask()
543 EXPORT_C TPtrC8 CX509IPSubnetMask::BaseAddress() const
545 TInt half = iName->Length()/2;
546 TPtrC8 ptr(&(iName->operator [] (0)), half);
550 EXPORT_C TPtrC8 CX509IPSubnetMask::Mask() const
552 TInt half = iName->Length()/2;
553 TPtrC8 ptr(&(iName->operator [] (half)), half);
557 CX509IPSubnetMask::CX509IPSubnetMask()
563 EXPORT_C CX509IPAddress* CX509IPAddress::NewL(const TDesC8& aBinaryData)
565 CX509IPAddress* self = CX509IPAddress::NewLC(aBinaryData);
566 CleanupStack::Pop();//self
570 EXPORT_C CX509IPAddress* CX509IPAddress::NewLC(const TDesC8& aBinaryData)
572 CX509IPAddress* self = new(ELeave) CX509IPAddress;
573 CleanupStack::PushL(self);
574 self->ConstructL(aBinaryData);
578 void CX509IPAddress::ConstructL(const TDesC8& aBinaryData)
580 TASN1DecGeneric encAddr(aBinaryData);
582 iName = encAddr.GetContentDER().AllocL();
583 TInt len = iName->Length();
584 if (!(len == 4 || len == 16))
586 User::Leave(KErrArgument);
590 EXPORT_C CX509IPAddress::~CX509IPAddress()
595 EXPORT_C TBool CX509IPAddress::IsWithinSubtree(const CX509IPSubnetMask& aName) const
597 TInt addrLen = iName->Length();
598 if (((aName.iName->Length())/2) != addrLen)
602 for (TInt i = 0; i < addrLen; i++)
604 //stop stupid compiler warning
605 TUint8 masked = (TUint8) ((iName->operator [] (i)) & (aName.iName->operator [] (i + addrLen)));
606 if (masked != (aName.iName->operator [] (i)))
614 EXPORT_C TPtrC8 CX509IPAddress::Address() const
619 CX509IPAddress::CX509IPAddress()
624 //*******************X.509 General Name**********************//
625 EXPORT_C CX509GeneralName* CX509GeneralName::NewL(const TDesC8& aBinaryData)
628 return CX509GeneralName::NewL(aBinaryData, pos);
631 EXPORT_C CX509GeneralName* CX509GeneralName::NewLC(const TDesC8& aBinaryData)
634 return CX509GeneralName::NewLC(aBinaryData, pos);
637 EXPORT_C CX509GeneralName* CX509GeneralName::NewL(const TDesC8& aBinaryData, TInt& aPos)
639 CX509GeneralName* self = CX509GeneralName::NewLC(aBinaryData, aPos);
644 EXPORT_C CX509GeneralName* CX509GeneralName::NewLC(const TDesC8& aBinaryData, TInt& aPos)
646 CX509GeneralName* self = new(ELeave) CX509GeneralName;
647 CleanupStack::PushL(self);
648 self->ConstructL(aBinaryData, aPos);
652 EXPORT_C CX509GeneralName* CX509GeneralName::NewL(const CX509GeneralName& aName)
654 CX509GeneralName* self = CX509GeneralName::NewLC(aName);
659 EXPORT_C CX509GeneralName* CX509GeneralName::NewLC(const CX509GeneralName& aName)
661 CX509GeneralName* self = new(ELeave) CX509GeneralName(aName.iTag);
662 CleanupStack::PushL(self);
663 self->ConstructL(aName.iData->Des());
667 void CX509GeneralName::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
669 TASN1DecGeneric gen(aBinaryData.Right(aBinaryData.Length() - aPos));
671 aPos += gen.LengthDER();//add on header info
672 if (gen.Class() != EContextSpecific)
674 User::Leave(KErrArgument);
676 iData = gen.Tag() == 4 ? gen.GetContentDER().AllocL(): gen.Encoding().AllocL();
680 void CX509GeneralName::ConstructL(const TDesC8& aData)
682 iData = aData.AllocL();
685 CX509GeneralName::CX509GeneralName(TGNType aType)
690 CX509GeneralName::CX509GeneralName()
694 EXPORT_C TGNType CX509GeneralName::Tag() const
699 EXPORT_C TPtrC8 CX509GeneralName::Data() const
704 EXPORT_C TBool CX509GeneralName::ExactMatch(const CX509GeneralName& /*aName*/) const
709 EXPORT_C CX509GeneralName::~CX509GeneralName()