diff -r 675a964f4eb5 -r 35751d3474b7 cryptoservices/certificateandkeymgmt/x500/x520ava.cpp --- 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 -#include "X500dec.h" -#include -#include - -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 +#include "X500dec.h" +#include +#include + +#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); + }