--- a/cryptoservices/certificateandkeymgmt/x500/x520ava.cpp Tue Jul 21 01:04:32 2009 +0100
+++ b/cryptoservices/certificateandkeymgmt/x500/x520ava.cpp Thu Sep 10 14:01:51 2009 +0300
@@ -1,507 +1,559 @@
-/*
-* Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
-* All rights reserved.
-* This component and the accompanying materials are made available
-* under the terms of the License "Eclipse Public License v1.0"
-* which accompanies this distribution, and is available
-* at the URL "http://www.eclipse.org/legal/epl-v10.html".
-*
-* Initial Contributors:
-* Nokia Corporation - initial contribution.
-*
-* Contributors:
-*
-* Description:
-*
-*/
-
-
-#include <x520ava.h>
-#include "X500dec.h"
-#include <asn1enc.h>
-#include <asn1dec.h>
-
-EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewL(const CX520AttributeTypeAndValue& aPair)
- {
- CX520AttributeTypeAndValue* self = CX520AttributeTypeAndValue::NewLC(aPair);
- CleanupStack::Pop();//self
- return self;
- }
-
-EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewLC(const CX520AttributeTypeAndValue& aPair)
- {
- CX520AttributeTypeAndValue* self = new(ELeave) CX520AttributeTypeAndValue;
- CleanupStack::PushL(self);
- self->ConstructL(aPair);
- return self;
- }
-
-EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewL(const TDesC8& aBinaryData)
- {
- TInt pos = 0;
- return CX520AttributeTypeAndValue::NewL(aBinaryData, pos);
- }
-
-EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewLC(const TDesC8& aBinaryData)
- {
- TInt pos = 0;
- return CX520AttributeTypeAndValue::NewLC(aBinaryData, pos);
- }
-
-EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewL(const TDesC8& aBinaryData, TInt& aPos)
- {
- CX520AttributeTypeAndValue* self = CX520AttributeTypeAndValue::NewLC(aBinaryData, aPos);
- CleanupStack::Pop();
- return self;
- }
-
-EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewLC(const TDesC8& aBinaryData, TInt& aPos)
- {
- CX520AttributeTypeAndValue* self = new(ELeave) CX520AttributeTypeAndValue;
- CleanupStack::PushL(self);
- self->ConstructL(aBinaryData, aPos);
- return self;
- }
-
-EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewL(RReadStream& aStream)
- {
- CX520AttributeTypeAndValue* self = CX520AttributeTypeAndValue::NewLC(aStream);
- CleanupStack::Pop();//self
- return self;
- }
-
-EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewLC(RReadStream& aStream)
- {
- CX520AttributeTypeAndValue* self = new(ELeave) CX520AttributeTypeAndValue;
- CleanupStack::PushL(self);
- self->InternalizeL(aStream);
- return self;
- }
-
-/** Allocates and initializes a new attribute-value pair object from
- type and value.
- @param aType Type of the value (see TAttributeType enum).
- @param aValue String value of the attribute.
- @return Pointer to a newly allocated and initialized attribute-value pair.
- @see CX520AttributeTypeAndValue::NewLC */
-EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewL(TAttributeType aType, const TDesC8& aValue)
- {
- CX520AttributeTypeAndValue* self = CX520AttributeTypeAndValue::NewLC(aType, aValue);
- CleanupStack::Pop(); // self
- return self;
- }
-
-/** Allocates and initializes a new attribute-value pair object from
- type and value. Pushes the newly allocated object onto the
- cleanup stack.
- @param aType Type of the value (see TAttributeType enum).
- @param aValue String value of the attribute.
- @return Pointer to a newly allocated and initialized attribute-value pair.
- @see CX520AttributeTypeAndValue::NewL */
-EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewLC(
- TAttributeType aType,
- const TDesC8& aValue)
- {
- CX520AttributeTypeAndValue* self = new(ELeave) CX520AttributeTypeAndValue;
- CleanupStack::PushL(self);
- self->ConstructL(aType, aValue);
- return self;
- }
-
-CX520AttributeTypeAndValue::CX520AttributeTypeAndValue()
- :iType(NULL), iValue(NULL)
- {
- }
-
-void CX520AttributeTypeAndValue::ConstructL(const CX520AttributeTypeAndValue& aPair)
- {
- iType = aPair.iType->AllocL();
- iValue = aPair.iValue->AllocL();
- }
-
-void CX520AttributeTypeAndValue::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
- {
- TASN1DecGeneric dec(aBinaryData.Right(aBinaryData.Length() - aPos));
- dec.InitL();
- TInt end = aPos + dec.LengthDER();
- aPos += dec.LengthDERHeader();
-
- //first element must be the id
- TASN1DecObjectIdentifier encOID;
- iType = encOID.DecodeDERL(aBinaryData, aPos);
- //second is the data
- TASN1DecGeneric second(aBinaryData.Right(aBinaryData.Length() - aPos));
- second.InitL();
-
- iValue = second.Encoding().AllocL();;
- aPos += second.LengthDER();
-
- if (aPos != end)
- {
- User::Leave(KErrArgument);
- }
- }
-
-void CX520AttributeTypeAndValue::ConstructL(TAttributeType aType, const TDesC8& aValue)
- {
- // iType is string representation of OID corresponding to the aType.
- TPtrC ptr;
- TInt maxlen = 64; // a reasonable default
- TTagType type = EASN1PrintableString; // the default for all except email, unstructured name and domain component
- switch(aType)
- {
- case ECommonName:
- ptr.Set(KX520CommonName);
- maxlen = KX520MaxCNLength;
- break;
- case ELocalityName:
- ptr.Set(KX520LocalityName);
- maxlen = KX520MaxLLength;
- break;
- case EStateOrProvinceName:
- ptr.Set(KX520StateOrProvinceName);
- maxlen = KX520MaxSOPLength;
- break;
- case EPostalCode:
- ptr.Set(KX520PostalCode);
- maxlen = KX520MaxPostalCodeLength;
- break;
- case EOrganizationName:
- ptr.Set(KX520OrganizationName);
- maxlen = KX520MaxOLength;
- break;
- case EOrganizationalUnitName:
- ptr.Set(KX520OrganizationalUnitName);
- maxlen = KX520MaxOULength;
- break;
- case ETitle:
- ptr.Set(KX520Title);
- maxlen = KX520MaxTLength;
- break;
- case EDNQualifier:
- ptr.Set(KX520DNQualifier);
- maxlen = 64; // no information was found on this one, so set to a safe minimum
- break;
- case ECountryName:
- ptr.Set(KX520CountryName);
- maxlen = KX520MaxCNLength;
- break;
- case EGivenName:
- ptr.Set(KX520GivenName);
- maxlen = KX520MaxGNLength;
- break;
- case ESurname:
- ptr.Set(KX520Surname);
- maxlen = KX520MaxSLength;
- break;
- case EInitials:
- ptr.Set(KX520Initials);
- maxlen = KX520MaxILength;
- break;
- case EGenerationQualifier:
- ptr.Set(KX520GenerationQualifier);
- maxlen = KX520MaxGQLength;
- break;
- case EPKCS9EmailAddress:
- ptr.Set(KPKCS9EmailAddress);
- maxlen = KPKCS9MaxEmailAddressLength;
- type = EASN1IA5String;
- break;
- case ESerialNumber:
- ptr.Set(KX520SerialNumber);
- maxlen = KX520MaxSNLength;
- break;
- case ERFC2247DomainComponent:
- ptr.Set(KRFC2247DomainComponent);
- maxlen = KRFC2247MaxDomainComponentLength;
- type = EASN1IA5String;
- break;
- case ERFC2256Street:
- ptr.Set(KRFC2256Street);
- maxlen = KRFC2256StreetLength;
- break;
- case EPKCS9UnstructuredName:
- {
- ptr.Set(KPKCS9UnstructuredName);
- maxlen = KPKCS9MaxUnstructuredNameLength;
- // Determine the encoded value. It could be a IA5String or a UTF8String
- TASN1DecGeneric decoderGeneric(aValue);
- decoderGeneric.InitL();
- type = decoderGeneric.Tag();
- break;
- }
- default:
- User::Leave(KErrArgument);
- }
- // Verify if the passed length is within limits
- if(aValue.Length() > maxlen)
- User::Leave(KErrArgument);
-
- // Allocate OID string for iType
- iType = ptr.AllocL();
-
- // iValue must be stored in ASN.1-encoded form
- CASN1EncOctetString* enc = CASN1EncOctetString::NewLC(aValue);
- enc->SetTag(type, EUniversal);
- TUint len = enc->LengthDER();
- HBufC8* buf = HBufC8::NewMaxLC(len);
- TUint pos = 0;
- TPtr8 bufptr(buf->Des());
- enc->WriteDERL(bufptr, pos);
- iValue = bufptr.AllocL();
- CleanupStack::PopAndDestroy(2);
- }
-
-EXPORT_C const TPtrC CX520AttributeTypeAndValue::Type() const
- {
- return iType->Des();
- }
-
-EXPORT_C const TPtrC8 CX520AttributeTypeAndValue::EncodedValue() const
- {
- return iValue->Des();
- }
-
-EXPORT_C HBufC* CX520AttributeTypeAndValue::ValueL() const
- {
- if (iType->Des() == KX520CountryName)
- {
- TASN1DecPrintableString encPString;
- TInt pos = 0;
- HBufC* res = encPString.DecodeDERL(iValue->Des(), pos);
- CleanupStack::PushL(res);
- if (res->Length() > KX520MaxCLength)
- {
- User::Leave(KErrArgument);
- }
- CleanupStack::Pop();
- return res;
- }
- if (iType->Des() == KX520DNQualifier)
- {
- TInt pos = 0;
- TASN1DecPrintableString encPString;
- HBufC* res = encPString.DecodeDERL(iValue->Des(), pos);
- return res;
- }
- if (iType->Des() == KPKCS9EmailAddress)
- {
- TASN1DecIA5String encIA5String;
- TInt pos = 0;
- HBufC* res = encIA5String.DecodeDERL(iValue->Des(), pos);
- CleanupStack::PushL(res);
- if (res->Length() > KPKCS9MaxEmailAddressLength)
- {
- User::Leave(KErrArgument);
- }
- CleanupStack::Pop();
- return res;
- }
- if (iType->Des() == KRFC2247DomainComponent)
- {
- TASN1DecIA5String encIA5String;
- TInt pos = 0;
- HBufC* res = encIA5String.DecodeDERL(iValue->Des(), pos);
- CleanupStack::PushL(res);
- if (res->Length() > KRFC2247MaxDomainComponentLength)
- {
- User::Leave(KErrArgument);
- }
- CleanupStack::Pop();
- return res;
- }
- if (iType->Des() == KX520SerialNumber)
- {
- TASN1DecPrintableString encPString;
- TInt pos = 0;
- HBufC* res = encPString.DecodeDERL(iValue->Des(), pos);
- CleanupStack::PushL(res);
- if (res->Length() > KX520MaxSNLength)
- {
- User::Leave(KErrArgument);
- }
- CleanupStack::Pop();
- return res;
- }
- TInt maxLength = 0;
- if (iType->Des() == KPKCS9UnstructuredName)
- {
- TASN1DecGeneric decoderGeneric(iValue->Des());
- decoderGeneric.InitL();
- // The encoded value should be a IA5String
- if (decoderGeneric.Tag() == EASN1IA5String)
- {
- TASN1DecIA5String encIA5String;
- TInt pos = 0;
- HBufC* res = encIA5String.DecodeDERL(iValue->Des(), pos);
- CleanupStack::PushL(res);
- if (res->Length() > KPKCS9MaxUnstructuredNameLength)
- {
- User::Leave(KErrArgument);
- }
- CleanupStack::Pop();
- return res;
- }
- // But it could also be a UTF8String to support internationalization issues
- else
- {
- maxLength = KPKCS9MaxUnstructuredNameLength;
- }
- }
- if (iType->Des() == KX520OrganizationName)
- {
- maxLength = KX520MaxOLength;
- }
- if (iType->Des() == KX520OrganizationalUnitName)
- {
- maxLength = KX520MaxOULength;
- }
- if (iType->Des() == KX520LocalityName)
- {
- maxLength = KX520MaxLLength;
- }
- if (iType->Des() == KX520StateOrProvinceName)
- {
- maxLength = KX520MaxSOPLength;
- }
- if (iType->Des() == KX520Title)
- {
- maxLength = KX520MaxTLength;
- }
- if (iType->Des() == KX520CommonName)
- {
- maxLength = KX520MaxCNLength;
- }
- if (iType->Des() == KX520Surname)
- {
- maxLength = KX520MaxSLength;
- }
- if (iType->Des() == KX520GivenName)
- {
- maxLength = KX520MaxGNLength;
- }
- if (iType->Des() == KX520Initials)
- {
- maxLength = KX520MaxILength;
- }
- if (iType->Des() == KX520GenerationQualifier)
- {
- maxLength = KX520MaxGQLength;
- }
- if (iType->Des() == KX520PostalCode)
- {
- maxLength = KX520MaxPostalCodeLength;
- }
- if (iType->Des() == KRFC2256Street)
- {
- maxLength = KRFC2256StreetLength;
- }
- if (maxLength == 0)
- {
- User::Leave(KErrNotSupported);
- }
-
- TASN1DecX500DirectoryString encDString;
- TInt pos = 0;
- HBufC* res = encDString.DecodeDERL(iValue->Des(), pos, maxLength);
- return res;
- }
-
-TBool CX520AttributeTypeAndValue::IsCaseInSensitive(const TDesC8& aSource) const
- {
- TPtr attribute = iType->Des();
- TBool caseInsensitiveAttr = (attribute == KPKCS9EmailAddress || attribute == KPKCS9UnstructuredName);
- TASN1DecGeneric gen(aSource);
- gen.InitL();
- return ((gen.Tag() == EASN1PrintableString) || caseInsensitiveAttr);
- }
-
-EXPORT_C CASN1EncSequence* CX520AttributeTypeAndValue::EncodeASN1LC() const
- {
- CASN1EncSequence *seq = CASN1EncSequence::NewLC();
- CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(Type());
- seq->AddAndPopChildL(oid);
-
- // The current ASN.1 base encoding class assumes that ASN.1 type,
- // length, and contents are stored and can be written to a buffer
- // separately. Therefore it is difficult, if not impossible, to
- // store raw ASN.1 encoding data in a tree of ASN.1 encoding
- // objects. That is why we are forced first to decode the raw value,
- // and then re-encode it so that we know what type and length it
- // has.
- TASN1DecGeneric decoderGeneric(EncodedValue());
- decoderGeneric.InitL();
- TASN1DecOctetString decoderOctetString;
- HBufC8* valBuf = decoderOctetString.DecodeDERL(decoderGeneric);
- CleanupStack::PushL(valBuf);
- CASN1EncOctetString* val = CASN1EncOctetString::NewLC(*valBuf);
- val->SetTag(decoderGeneric.Tag(), decoderGeneric.Class());
- seq->AddAndPopChildL(val);
- CleanupStack::PopAndDestroy(valBuf);
- return seq;
- }
-
-EXPORT_C CASN1EncSequence* CX520AttributeTypeAndValue::EncodeASN1L() const
- {
- CASN1EncSequence *seq = EncodeASN1LC();
- CleanupStack::Pop(seq);
- return seq;
- }
-
-EXPORT_C CX520AttributeTypeAndValue::~CX520AttributeTypeAndValue()
- {
- delete iType;
- delete iValue;
- }
-
-EXPORT_C TBool CX520AttributeTypeAndValue::ExactMatchL(const CX520AttributeTypeAndValue& aElement) const
- {
- TBool res = EFalse;
- if (*(iType) != *(aElement.iType))
- {
- return res;
- }
- HBufC* lhs = this->ValueL();
- CleanupStack::PushL(lhs);
- HBufC* rhs = aElement.ValueL();
-
- TPtr plhs = lhs->Des();
- TPtr prhs = rhs->Des();
- plhs.TrimAll();
- prhs.TrimAll();
-
- // PDEF125098: Certificate name matching done in accordance to RFC3280
- // RFC3280: Printable String and Email address(of value type 'IA5String') will
- // be compared case-insensitively.
- if (IsCaseInSensitive(iValue->Des()))
- {
- //case insensitive comparison for Printable String and IA5String (EmailAdress only).
- res = (plhs.CompareF(prhs) == 0);
- }
- else
- {
- // case-sensitive comparison for strings other than printable string
- // Exception: This may include IA5Stings other than 'EmailAddress' attiribute types.
- res = (plhs.Compare(prhs) == 0);
- }
- CleanupStack::PopAndDestroy();
- delete rhs;
- return res;
- }
-
-void CX520AttributeTypeAndValue::ExternalizeL(RWriteStream& aStream) const
- {
- aStream.WriteInt32L(iType->Des().Length());
- aStream << *iType;
- aStream.WriteInt32L(iValue->Des().Length());
- aStream << *iValue;
- }
-
-void CX520AttributeTypeAndValue::InternalizeL(RReadStream& aStream)
- {
- TInt maxlen;
- maxlen = aStream.ReadInt32L();
- iType = HBufC::NewL(aStream,maxlen);
- maxlen = aStream.ReadInt32L();
- iValue = HBufC8::NewL(aStream,maxlen);
- }
+/*
+* Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+#include <x520ava.h>
+#include "X500dec.h"
+#include <asn1enc.h>
+#include <asn1dec.h>
+
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+//these are the only attribute types we handle at present
+_LIT(KX520PostalCode,"2.5.4.17");
+_LIT(KRFC2247DomainComponent, "0.9.2342.19200300.100.1.25");
+_LIT(KRFC2256Street,"2.5.4.9");
+_LIT(KPKCS9UnstructuredName, "1.2.840.113549.1.9.2");
+
+//email address is deprecated but we support it anyway...
+_LIT(KPKCS9EmailAddress, "1.2.840.113549.1.9.1");
+
+/** The maximum length allowed for a country name. */
+const TInt KX520MaxCLength = 2;
+/** The maximum length allowed for an organization name. */
+const TInt KX520MaxOLength = 64;
+/** The maximum length allowed for an organizational unit name. */
+const TInt KX520MaxOULength = 64;
+/** The maximum length allowed for a locality name. */
+const TInt KX520MaxLLength = 128;
+/** The maximum length allowed for a state or province name. */
+const TInt KX520MaxSOPLength = 128;
+/** The maximum length allowed for an title. */
+const TInt KX520MaxTLength = 64;
+/** The maximum length allowed for a common name. */
+const TInt KX520MaxCNLength = 256;
+/** The maximum length allowed for a given name. */
+const TInt KX520MaxGNLength = 16;
+/** The maximum length allowed for a surname. */
+const TInt KX520MaxSLength = 40;
+/** The maximum length allowed for initials. */
+const TInt KX520MaxILength = 5;
+/** The maximum length allowed for a generation qualifier. */
+const TInt KX520MaxGQLength = 3;
+/** The maximum length allowed for a serial number. */
+const TInt KX520MaxSNLength = 64;
+/** The maximum length allowed for a postal code. */
+const TInt KX520MaxPostalCodeLength = 40;
+/** The maximum length allowed for an email address. */
+const TInt KPKCS9MaxEmailAddressLength = 256;
+/** The maximum length allowed for an unstructured name. */
+const TInt KPKCS9MaxUnstructuredNameLength = 256;
+// No maximum was specified in the standard - 128 should be sufficient
+/** The maximum length allowed for an RFC 2247 domain component.
+*
+* Each component of the domain name is a short string. */
+const TInt KRFC2247MaxDomainComponentLength = 128;
+/** The maximum length allowed a for street. */
+const TInt KRFC2256StreetLength = 128;
+
+#endif
+
+EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewL(const CX520AttributeTypeAndValue& aPair)
+ {
+ CX520AttributeTypeAndValue* self = CX520AttributeTypeAndValue::NewLC(aPair);
+ CleanupStack::Pop();//self
+ return self;
+ }
+
+EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewLC(const CX520AttributeTypeAndValue& aPair)
+ {
+ CX520AttributeTypeAndValue* self = new(ELeave) CX520AttributeTypeAndValue;
+ CleanupStack::PushL(self);
+ self->ConstructL(aPair);
+ return self;
+ }
+
+EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewL(const TDesC8& aBinaryData)
+ {
+ TInt pos = 0;
+ return CX520AttributeTypeAndValue::NewL(aBinaryData, pos);
+ }
+
+EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewLC(const TDesC8& aBinaryData)
+ {
+ TInt pos = 0;
+ return CX520AttributeTypeAndValue::NewLC(aBinaryData, pos);
+ }
+
+EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewL(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ CX520AttributeTypeAndValue* self = CX520AttributeTypeAndValue::NewLC(aBinaryData, aPos);
+ CleanupStack::Pop();
+ return self;
+ }
+
+EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewLC(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ CX520AttributeTypeAndValue* self = new(ELeave) CX520AttributeTypeAndValue;
+ CleanupStack::PushL(self);
+ self->ConstructL(aBinaryData, aPos);
+ return self;
+ }
+
+EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewL(RReadStream& aStream)
+ {
+ CX520AttributeTypeAndValue* self = CX520AttributeTypeAndValue::NewLC(aStream);
+ CleanupStack::Pop();//self
+ return self;
+ }
+
+EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewLC(RReadStream& aStream)
+ {
+ CX520AttributeTypeAndValue* self = new(ELeave) CX520AttributeTypeAndValue;
+ CleanupStack::PushL(self);
+ self->InternalizeL(aStream);
+ return self;
+ }
+
+/** Allocates and initializes a new attribute-value pair object from
+ type and value.
+ @param aType Type of the value (see TAttributeType enum).
+ @param aValue String value of the attribute.
+ @return Pointer to a newly allocated and initialized attribute-value pair.
+ @see CX520AttributeTypeAndValue::NewLC */
+EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewL(TAttributeType aType, const TDesC8& aValue)
+ {
+ CX520AttributeTypeAndValue* self = CX520AttributeTypeAndValue::NewLC(aType, aValue);
+ CleanupStack::Pop(); // self
+ return self;
+ }
+
+/** Allocates and initializes a new attribute-value pair object from
+ type and value. Pushes the newly allocated object onto the
+ cleanup stack.
+ @param aType Type of the value (see TAttributeType enum).
+ @param aValue String value of the attribute.
+ @return Pointer to a newly allocated and initialized attribute-value pair.
+ @see CX520AttributeTypeAndValue::NewL */
+EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewLC(
+ TAttributeType aType,
+ const TDesC8& aValue)
+ {
+ CX520AttributeTypeAndValue* self = new(ELeave) CX520AttributeTypeAndValue;
+ CleanupStack::PushL(self);
+ self->ConstructL(aType, aValue);
+ return self;
+ }
+
+CX520AttributeTypeAndValue::CX520AttributeTypeAndValue()
+ :iType(NULL), iValue(NULL)
+ {
+ }
+
+void CX520AttributeTypeAndValue::ConstructL(const CX520AttributeTypeAndValue& aPair)
+ {
+ iType = aPair.iType->AllocL();
+ iValue = aPair.iValue->AllocL();
+ }
+
+void CX520AttributeTypeAndValue::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ TASN1DecGeneric dec(aBinaryData.Right(aBinaryData.Length() - aPos));
+ dec.InitL();
+ TInt end = aPos + dec.LengthDER();
+ aPos += dec.LengthDERHeader();
+
+ //first element must be the id
+ TASN1DecObjectIdentifier encOID;
+ iType = encOID.DecodeDERL(aBinaryData, aPos);
+ //second is the data
+ TASN1DecGeneric second(aBinaryData.Right(aBinaryData.Length() - aPos));
+ second.InitL();
+
+ iValue = second.Encoding().AllocL();;
+ aPos += second.LengthDER();
+
+ if (aPos != end)
+ {
+ User::Leave(KErrArgument);
+ }
+ }
+
+void CX520AttributeTypeAndValue::ConstructL(TAttributeType aType, const TDesC8& aValue)
+ {
+ // iType is string representation of OID corresponding to the aType.
+ TPtrC ptr;
+ TInt maxlen = 64; // a reasonable default
+ TTagType type = EASN1PrintableString; // the default for all except email, unstructured name and domain component
+ switch(aType)
+ {
+ case ECommonName:
+ ptr.Set(KX520CommonName);
+ maxlen = KX520MaxCNLength;
+ break;
+ case ELocalityName:
+ ptr.Set(KX520LocalityName);
+ maxlen = KX520MaxLLength;
+ break;
+ case EStateOrProvinceName:
+ ptr.Set(KX520StateOrProvinceName);
+ maxlen = KX520MaxSOPLength;
+ break;
+ case EPostalCode:
+ ptr.Set(KX520PostalCode);
+ maxlen = KX520MaxPostalCodeLength;
+ break;
+ case EOrganizationName:
+ ptr.Set(KX520OrganizationName);
+ maxlen = KX520MaxOLength;
+ break;
+ case EOrganizationalUnitName:
+ ptr.Set(KX520OrganizationalUnitName);
+ maxlen = KX520MaxOULength;
+ break;
+ case ETitle:
+ ptr.Set(KX520Title);
+ maxlen = KX520MaxTLength;
+ break;
+ case EDNQualifier:
+ ptr.Set(KX520DNQualifier);
+ maxlen = 64; // no information was found on this one, so set to a safe minimum
+ break;
+ case ECountryName:
+ ptr.Set(KX520CountryName);
+ maxlen = KX520MaxCNLength;
+ break;
+ case EGivenName:
+ ptr.Set(KX520GivenName);
+ maxlen = KX520MaxGNLength;
+ break;
+ case ESurname:
+ ptr.Set(KX520Surname);
+ maxlen = KX520MaxSLength;
+ break;
+ case EInitials:
+ ptr.Set(KX520Initials);
+ maxlen = KX520MaxILength;
+ break;
+ case EGenerationQualifier:
+ ptr.Set(KX520GenerationQualifier);
+ maxlen = KX520MaxGQLength;
+ break;
+ case EPKCS9EmailAddress:
+ ptr.Set(KPKCS9EmailAddress);
+ maxlen = KPKCS9MaxEmailAddressLength;
+ type = EASN1IA5String;
+ break;
+ case ESerialNumber:
+ ptr.Set(KX520SerialNumber);
+ maxlen = KX520MaxSNLength;
+ break;
+ case ERFC2247DomainComponent:
+ ptr.Set(KRFC2247DomainComponent);
+ maxlen = KRFC2247MaxDomainComponentLength;
+ type = EASN1IA5String;
+ break;
+ case ERFC2256Street:
+ ptr.Set(KRFC2256Street);
+ maxlen = KRFC2256StreetLength;
+ break;
+ case EPKCS9UnstructuredName:
+ {
+ ptr.Set(KPKCS9UnstructuredName);
+ maxlen = KPKCS9MaxUnstructuredNameLength;
+ // Determine the encoded value. It could be a IA5String or a UTF8String
+ TASN1DecGeneric decoderGeneric(aValue);
+ decoderGeneric.InitL();
+ type = decoderGeneric.Tag();
+ break;
+ }
+ default:
+ User::Leave(KErrArgument);
+ }
+ // Verify if the passed length is within limits
+ if(aValue.Length() > maxlen)
+ User::Leave(KErrArgument);
+
+ // Allocate OID string for iType
+ iType = ptr.AllocL();
+
+ // iValue must be stored in ASN.1-encoded form
+ CASN1EncOctetString* enc = CASN1EncOctetString::NewLC(aValue);
+ enc->SetTag(type, EUniversal);
+ TUint len = enc->LengthDER();
+ HBufC8* buf = HBufC8::NewMaxLC(len);
+ TUint pos = 0;
+ TPtr8 bufptr(buf->Des());
+ enc->WriteDERL(bufptr, pos);
+ iValue = bufptr.AllocL();
+ CleanupStack::PopAndDestroy(2);
+ }
+
+EXPORT_C const TPtrC CX520AttributeTypeAndValue::Type() const
+ {
+ return iType->Des();
+ }
+
+EXPORT_C const TPtrC8 CX520AttributeTypeAndValue::EncodedValue() const
+ {
+ return iValue->Des();
+ }
+
+EXPORT_C HBufC* CX520AttributeTypeAndValue::ValueL() const
+ {
+ if (iType->Des() == KX520CountryName)
+ {
+ TASN1DecPrintableString encPString;
+ TInt pos = 0;
+ HBufC* res = encPString.DecodeDERL(iValue->Des(), pos);
+ CleanupStack::PushL(res);
+ if (res->Length() > KX520MaxCLength)
+ {
+ User::Leave(KErrArgument);
+ }
+ CleanupStack::Pop();
+ return res;
+ }
+ if (iType->Des() == KX520DNQualifier)
+ {
+ TInt pos = 0;
+ TASN1DecPrintableString encPString;
+ HBufC* res = encPString.DecodeDERL(iValue->Des(), pos);
+ return res;
+ }
+ if (iType->Des() == KPKCS9EmailAddress)
+ {
+ TASN1DecIA5String encIA5String;
+ TInt pos = 0;
+ HBufC* res = encIA5String.DecodeDERL(iValue->Des(), pos);
+ CleanupStack::PushL(res);
+ if (res->Length() > KPKCS9MaxEmailAddressLength)
+ {
+ User::Leave(KErrArgument);
+ }
+ CleanupStack::Pop();
+ return res;
+ }
+ if (iType->Des() == KRFC2247DomainComponent)
+ {
+ TASN1DecIA5String encIA5String;
+ TInt pos = 0;
+ HBufC* res = encIA5String.DecodeDERL(iValue->Des(), pos);
+ CleanupStack::PushL(res);
+ if (res->Length() > KRFC2247MaxDomainComponentLength)
+ {
+ User::Leave(KErrArgument);
+ }
+ CleanupStack::Pop();
+ return res;
+ }
+ if (iType->Des() == KX520SerialNumber)
+ {
+ TASN1DecPrintableString encPString;
+ TInt pos = 0;
+ HBufC* res = encPString.DecodeDERL(iValue->Des(), pos);
+ CleanupStack::PushL(res);
+ if (res->Length() > KX520MaxSNLength)
+ {
+ User::Leave(KErrArgument);
+ }
+ CleanupStack::Pop();
+ return res;
+ }
+ TInt maxLength = 0;
+ if (iType->Des() == KPKCS9UnstructuredName)
+ {
+ TASN1DecGeneric decoderGeneric(iValue->Des());
+ decoderGeneric.InitL();
+ // The encoded value should be a IA5String
+ if (decoderGeneric.Tag() == EASN1IA5String)
+ {
+ TASN1DecIA5String encIA5String;
+ TInt pos = 0;
+ HBufC* res = encIA5String.DecodeDERL(iValue->Des(), pos);
+ CleanupStack::PushL(res);
+ if (res->Length() > KPKCS9MaxUnstructuredNameLength)
+ {
+ User::Leave(KErrArgument);
+ }
+ CleanupStack::Pop();
+ return res;
+ }
+ // But it could also be a UTF8String to support internationalization issues
+ else
+ {
+ maxLength = KPKCS9MaxUnstructuredNameLength;
+ }
+ }
+ if (iType->Des() == KX520OrganizationName)
+ {
+ maxLength = KX520MaxOLength;
+ }
+ if (iType->Des() == KX520OrganizationalUnitName)
+ {
+ maxLength = KX520MaxOULength;
+ }
+ if (iType->Des() == KX520LocalityName)
+ {
+ maxLength = KX520MaxLLength;
+ }
+ if (iType->Des() == KX520StateOrProvinceName)
+ {
+ maxLength = KX520MaxSOPLength;
+ }
+ if (iType->Des() == KX520Title)
+ {
+ maxLength = KX520MaxTLength;
+ }
+ if (iType->Des() == KX520CommonName)
+ {
+ maxLength = KX520MaxCNLength;
+ }
+ if (iType->Des() == KX520Surname)
+ {
+ maxLength = KX520MaxSLength;
+ }
+ if (iType->Des() == KX520GivenName)
+ {
+ maxLength = KX520MaxGNLength;
+ }
+ if (iType->Des() == KX520Initials)
+ {
+ maxLength = KX520MaxILength;
+ }
+ if (iType->Des() == KX520GenerationQualifier)
+ {
+ maxLength = KX520MaxGQLength;
+ }
+ if (iType->Des() == KX520PostalCode)
+ {
+ maxLength = KX520MaxPostalCodeLength;
+ }
+ if (iType->Des() == KRFC2256Street)
+ {
+ maxLength = KRFC2256StreetLength;
+ }
+ if (maxLength == 0)
+ {
+ User::Leave(KErrNotSupported);
+ }
+ TASN1DecX500DirectoryString encDString;
+ TInt pos = 0;
+ HBufC* res = encDString.DecodeDERL(iValue->Des(), pos, maxLength);
+ return res;
+ }
+
+TBool CX520AttributeTypeAndValue::IsCaseInSensitiveL(const TDesC8& aSource) const
+ {
+ TPtr attribute = iType->Des();
+ TBool caseInsensitiveAttr = (attribute == KPKCS9EmailAddress || attribute == KPKCS9UnstructuredName);
+ TASN1DecGeneric gen(aSource);
+ gen.InitL();
+ return ((gen.Tag() == EASN1PrintableString) || caseInsensitiveAttr);
+ }
+
+
+EXPORT_C CASN1EncSequence* CX520AttributeTypeAndValue::EncodeASN1LC() const
+ {
+ CASN1EncSequence *seq = CASN1EncSequence::NewLC();
+ CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(Type());
+ seq->AddAndPopChildL(oid);
+
+ // The current ASN.1 base encoding class assumes that ASN.1 type,
+ // length, and contents are stored and can be written to a buffer
+ // separately. Therefore it is difficult, if not impossible, to
+ // store raw ASN.1 encoding data in a tree of ASN.1 encoding
+ // objects. That is why we are forced first to decode the raw value,
+ // and then re-encode it so that we know what type and length it
+ // has.
+ TASN1DecGeneric decoderGeneric(EncodedValue());
+ decoderGeneric.InitL();
+ TASN1DecOctetString decoderOctetString;
+ HBufC8* valBuf = decoderOctetString.DecodeDERL(decoderGeneric);
+ CleanupStack::PushL(valBuf);
+ CASN1EncOctetString* val = CASN1EncOctetString::NewLC(*valBuf);
+ val->SetTag(decoderGeneric.Tag(), decoderGeneric.Class());
+ seq->AddAndPopChildL(val);
+ CleanupStack::PopAndDestroy(valBuf);
+ return seq;
+ }
+
+EXPORT_C CASN1EncSequence* CX520AttributeTypeAndValue::EncodeASN1L() const
+ {
+ CASN1EncSequence *seq = EncodeASN1LC();
+ CleanupStack::Pop(seq);
+ return seq;
+ }
+
+EXPORT_C CX520AttributeTypeAndValue::~CX520AttributeTypeAndValue()
+ {
+ delete iType;
+ delete iValue;
+ }
+
+EXPORT_C TBool CX520AttributeTypeAndValue::ExactMatchL(const CX520AttributeTypeAndValue& aElement) const
+ {
+ TBool res = EFalse;
+ if (*(iType) != *(aElement.iType))
+ {
+ return res;
+ }
+ HBufC* lhs = this->ValueL();
+ CleanupStack::PushL(lhs);
+ HBufC* rhs = aElement.ValueL();
+
+ TPtr plhs = lhs->Des();
+ TPtr prhs = rhs->Des();
+ plhs.TrimAll();
+ prhs.TrimAll();
+
+
+ // DEF124902: Certificate name matching done in accordance to RFC3280
+ // RFC3280: Printable String and Email address(of value type 'IA5String') will
+ // be compared case-insensitively.
+
+ if (IsCaseInSensitiveL(iValue->Des()))
+ {
+ //case insensitive comparison for Printable String and IA5String (EmailAdress only).
+ res = (plhs.CompareF(prhs) == 0);
+ }
+ else
+ {
+ // case-sensitive comparison for strings other than printable string
+ // Exception: This may include IA5Stings other than 'EmailAddress' attiribute types.
+ res = (plhs.Compare(prhs) == 0);
+ }
+ CleanupStack::PopAndDestroy();
+ delete rhs;
+ return res;
+ }
+
+void CX520AttributeTypeAndValue::ExternalizeL(RWriteStream& aStream) const
+ {
+ aStream.WriteInt32L(iType->Des().Length());
+ aStream << *iType;
+ aStream.WriteInt32L(iValue->Des().Length());
+ aStream << *iValue;
+ }
+
+void CX520AttributeTypeAndValue::InternalizeL(RReadStream& aStream)
+ {
+ TInt maxlen;
+ maxlen = aStream.ReadInt32L();
+ iType = HBufC::NewL(aStream,maxlen);
+ maxlen = aStream.ReadInt32L();
+ iValue = HBufC8::NewL(aStream,maxlen);
+ }