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.
25 EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewL(const CX520AttributeTypeAndValue& aPair)
27 CX520AttributeTypeAndValue* self = CX520AttributeTypeAndValue::NewLC(aPair);
28 CleanupStack::Pop();//self
32 EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewLC(const CX520AttributeTypeAndValue& aPair)
34 CX520AttributeTypeAndValue* self = new(ELeave) CX520AttributeTypeAndValue;
35 CleanupStack::PushL(self);
36 self->ConstructL(aPair);
40 EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewL(const TDesC8& aBinaryData)
43 return CX520AttributeTypeAndValue::NewL(aBinaryData, pos);
46 EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewLC(const TDesC8& aBinaryData)
49 return CX520AttributeTypeAndValue::NewLC(aBinaryData, pos);
52 EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewL(const TDesC8& aBinaryData, TInt& aPos)
54 CX520AttributeTypeAndValue* self = CX520AttributeTypeAndValue::NewLC(aBinaryData, aPos);
59 EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewLC(const TDesC8& aBinaryData, TInt& aPos)
61 CX520AttributeTypeAndValue* self = new(ELeave) CX520AttributeTypeAndValue;
62 CleanupStack::PushL(self);
63 self->ConstructL(aBinaryData, aPos);
67 EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewL(RReadStream& aStream)
69 CX520AttributeTypeAndValue* self = CX520AttributeTypeAndValue::NewLC(aStream);
70 CleanupStack::Pop();//self
74 EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewLC(RReadStream& aStream)
76 CX520AttributeTypeAndValue* self = new(ELeave) CX520AttributeTypeAndValue;
77 CleanupStack::PushL(self);
78 self->InternalizeL(aStream);
82 /** Allocates and initializes a new attribute-value pair object from
84 @param aType Type of the value (see TAttributeType enum).
85 @param aValue String value of the attribute.
86 @return Pointer to a newly allocated and initialized attribute-value pair.
87 @see CX520AttributeTypeAndValue::NewLC */
88 EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewL(TAttributeType aType, const TDesC8& aValue)
90 CX520AttributeTypeAndValue* self = CX520AttributeTypeAndValue::NewLC(aType, aValue);
91 CleanupStack::Pop(); // self
95 /** Allocates and initializes a new attribute-value pair object from
96 type and value. Pushes the newly allocated object onto the
98 @param aType Type of the value (see TAttributeType enum).
99 @param aValue String value of the attribute.
100 @return Pointer to a newly allocated and initialized attribute-value pair.
101 @see CX520AttributeTypeAndValue::NewL */
102 EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewLC(
103 TAttributeType aType,
104 const TDesC8& aValue)
106 CX520AttributeTypeAndValue* self = new(ELeave) CX520AttributeTypeAndValue;
107 CleanupStack::PushL(self);
108 self->ConstructL(aType, aValue);
112 CX520AttributeTypeAndValue::CX520AttributeTypeAndValue()
113 :iType(NULL), iValue(NULL)
117 void CX520AttributeTypeAndValue::ConstructL(const CX520AttributeTypeAndValue& aPair)
119 iType = aPair.iType->AllocL();
120 iValue = aPair.iValue->AllocL();
123 void CX520AttributeTypeAndValue::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
125 TASN1DecGeneric dec(aBinaryData.Right(aBinaryData.Length() - aPos));
127 TInt end = aPos + dec.LengthDER();
128 aPos += dec.LengthDERHeader();
130 //first element must be the id
131 TASN1DecObjectIdentifier encOID;
132 iType = encOID.DecodeDERL(aBinaryData, aPos);
134 TASN1DecGeneric second(aBinaryData.Right(aBinaryData.Length() - aPos));
137 iValue = second.Encoding().AllocL();;
138 aPos += second.LengthDER();
142 User::Leave(KErrArgument);
146 void CX520AttributeTypeAndValue::ConstructL(TAttributeType aType, const TDesC8& aValue)
148 // iType is string representation of OID corresponding to the aType.
150 TInt maxlen = 64; // a reasonable default
151 TTagType type = EASN1PrintableString; // the default for all except email, unstructured name and domain component
155 ptr.Set(KX520CommonName);
156 maxlen = KX520MaxCNLength;
159 ptr.Set(KX520LocalityName);
160 maxlen = KX520MaxLLength;
162 case EStateOrProvinceName:
163 ptr.Set(KX520StateOrProvinceName);
164 maxlen = KX520MaxSOPLength;
167 ptr.Set(KX520PostalCode);
168 maxlen = KX520MaxPostalCodeLength;
170 case EOrganizationName:
171 ptr.Set(KX520OrganizationName);
172 maxlen = KX520MaxOLength;
174 case EOrganizationalUnitName:
175 ptr.Set(KX520OrganizationalUnitName);
176 maxlen = KX520MaxOULength;
180 maxlen = KX520MaxTLength;
183 ptr.Set(KX520DNQualifier);
184 maxlen = 64; // no information was found on this one, so set to a safe minimum
187 ptr.Set(KX520CountryName);
188 maxlen = KX520MaxCNLength;
191 ptr.Set(KX520GivenName);
192 maxlen = KX520MaxGNLength;
195 ptr.Set(KX520Surname);
196 maxlen = KX520MaxSLength;
199 ptr.Set(KX520Initials);
200 maxlen = KX520MaxILength;
202 case EGenerationQualifier:
203 ptr.Set(KX520GenerationQualifier);
204 maxlen = KX520MaxGQLength;
206 case EPKCS9EmailAddress:
207 ptr.Set(KPKCS9EmailAddress);
208 maxlen = KPKCS9MaxEmailAddressLength;
209 type = EASN1IA5String;
212 ptr.Set(KX520SerialNumber);
213 maxlen = KX520MaxSNLength;
215 case ERFC2247DomainComponent:
216 ptr.Set(KRFC2247DomainComponent);
217 maxlen = KRFC2247MaxDomainComponentLength;
218 type = EASN1IA5String;
221 ptr.Set(KRFC2256Street);
222 maxlen = KRFC2256StreetLength;
224 case EPKCS9UnstructuredName:
226 ptr.Set(KPKCS9UnstructuredName);
227 maxlen = KPKCS9MaxUnstructuredNameLength;
228 // Determine the encoded value. It could be a IA5String or a UTF8String
229 TASN1DecGeneric decoderGeneric(aValue);
230 decoderGeneric.InitL();
231 type = decoderGeneric.Tag();
234 case EX520Description:
236 ptr.Set(KX520Description);
237 maxlen = KX520MaxDescriptionLength;
241 User::Leave(KErrArgument);
243 // Verify if the passed length is within limits
244 if(aValue.Length() > maxlen)
245 User::Leave(KErrArgument);
247 // Allocate OID string for iType
248 iType = ptr.AllocL();
250 // iValue must be stored in ASN.1-encoded form
251 CASN1EncOctetString* enc = CASN1EncOctetString::NewLC(aValue);
252 enc->SetTag(type, EUniversal);
253 TUint len = enc->LengthDER();
254 HBufC8* buf = HBufC8::NewMaxLC(len);
256 TPtr8 bufptr(buf->Des());
257 enc->WriteDERL(bufptr, pos);
258 iValue = bufptr.AllocL();
259 CleanupStack::PopAndDestroy(2);
262 EXPORT_C const TPtrC CX520AttributeTypeAndValue::Type() const
267 EXPORT_C const TPtrC8 CX520AttributeTypeAndValue::EncodedValue() const
269 return iValue->Des();
272 EXPORT_C HBufC* CX520AttributeTypeAndValue::ValueL() const
274 if (iType->Des() == KX520CountryName)
276 TASN1DecPrintableString encPString;
278 HBufC* res = encPString.DecodeDERL(iValue->Des(), pos);
279 CleanupStack::PushL(res);
280 if (res->Length() > KX520MaxCLength)
282 User::Leave(KErrArgument);
287 if (iType->Des() == KX520DNQualifier)
290 TASN1DecPrintableString encPString;
291 HBufC* res = encPString.DecodeDERL(iValue->Des(), pos);
294 if (iType->Des() == KPKCS9EmailAddress)
296 TASN1DecIA5String encIA5String;
298 HBufC* res = encIA5String.DecodeDERL(iValue->Des(), pos);
299 CleanupStack::PushL(res);
300 if (res->Length() > KPKCS9MaxEmailAddressLength)
302 User::Leave(KErrArgument);
307 if (iType->Des() == KRFC2247DomainComponent)
309 TASN1DecIA5String encIA5String;
311 HBufC* res = encIA5String.DecodeDERL(iValue->Des(), pos);
312 CleanupStack::PushL(res);
313 if (res->Length() > KRFC2247MaxDomainComponentLength)
315 User::Leave(KErrArgument);
320 if (iType->Des() == KX520SerialNumber)
322 TASN1DecPrintableString encPString;
324 HBufC* res = encPString.DecodeDERL(iValue->Des(), pos);
325 CleanupStack::PushL(res);
326 if (res->Length() > KX520MaxSNLength)
328 User::Leave(KErrArgument);
334 if (iType->Des() == KPKCS9UnstructuredName)
336 TASN1DecGeneric decoderGeneric(iValue->Des());
337 decoderGeneric.InitL();
338 // The encoded value should be a IA5String
339 if (decoderGeneric.Tag() == EASN1IA5String)
341 TASN1DecIA5String encIA5String;
343 HBufC* res = encIA5String.DecodeDERL(iValue->Des(), pos);
344 CleanupStack::PushL(res);
345 if (res->Length() > KPKCS9MaxUnstructuredNameLength)
347 User::Leave(KErrArgument);
352 // But it could also be a UTF8String to support internationalization issues
355 maxLength = KPKCS9MaxUnstructuredNameLength;
358 if (iType->Des() == KX520OrganizationName)
360 maxLength = KX520MaxOLength;
362 if (iType->Des() == KX520OrganizationalUnitName)
364 maxLength = KX520MaxOULength;
366 if (iType->Des() == KX520LocalityName)
368 maxLength = KX520MaxLLength;
370 if (iType->Des() == KX520StateOrProvinceName)
372 maxLength = KX520MaxSOPLength;
374 if (iType->Des() == KX520Title)
376 maxLength = KX520MaxTLength;
378 if (iType->Des() == KX520CommonName)
380 maxLength = KX520MaxCNLength;
382 if (iType->Des() == KX520Surname)
384 maxLength = KX520MaxSLength;
386 if (iType->Des() == KX520GivenName)
388 maxLength = KX520MaxGNLength;
390 if (iType->Des() == KX520Initials)
392 maxLength = KX520MaxILength;
394 if (iType->Des() == KX520GenerationQualifier)
396 maxLength = KX520MaxGQLength;
398 if (iType->Des() == KX520PostalCode)
400 maxLength = KX520MaxPostalCodeLength;
402 if (iType->Des() == KRFC2256Street)
404 maxLength = KRFC2256StreetLength;
406 if (iType->Des() == KX520Description)
408 maxLength = KX520MaxDescriptionLength;
412 User::Leave(KErrNotSupported);
414 TASN1DecX500DirectoryString encDString;
416 HBufC* res = encDString.DecodeDERL(iValue->Des(), pos, maxLength);
420 TBool CX520AttributeTypeAndValue::IsCaseInSensitiveL(const TDesC8& aSource) const
422 TPtr attribute = iType->Des();
423 TBool caseInsensitiveAttr = (attribute == KPKCS9EmailAddress || attribute == KPKCS9UnstructuredName || attribute == KX520Description);
424 TASN1DecGeneric gen(aSource);
426 return ((gen.Tag() == EASN1PrintableString) || caseInsensitiveAttr);
430 EXPORT_C CASN1EncSequence* CX520AttributeTypeAndValue::EncodeASN1LC() const
432 CASN1EncSequence *seq = CASN1EncSequence::NewLC();
433 CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(Type());
434 seq->AddAndPopChildL(oid);
436 // The current ASN.1 base encoding class assumes that ASN.1 type,
437 // length, and contents are stored and can be written to a buffer
438 // separately. Therefore it is difficult, if not impossible, to
439 // store raw ASN.1 encoding data in a tree of ASN.1 encoding
440 // objects. That is why we are forced first to decode the raw value,
441 // and then re-encode it so that we know what type and length it
443 TASN1DecGeneric decoderGeneric(EncodedValue());
444 decoderGeneric.InitL();
445 TASN1DecOctetString decoderOctetString;
446 HBufC8* valBuf = decoderOctetString.DecodeDERL(decoderGeneric);
447 CleanupStack::PushL(valBuf);
448 CASN1EncOctetString* val = CASN1EncOctetString::NewLC(*valBuf);
449 val->SetTag(decoderGeneric.Tag(), decoderGeneric.Class());
450 seq->AddAndPopChildL(val);
451 CleanupStack::PopAndDestroy(valBuf);
455 EXPORT_C CASN1EncSequence* CX520AttributeTypeAndValue::EncodeASN1L() const
457 CASN1EncSequence *seq = EncodeASN1LC();
458 CleanupStack::Pop(seq);
462 EXPORT_C CX520AttributeTypeAndValue::~CX520AttributeTypeAndValue()
468 EXPORT_C TBool CX520AttributeTypeAndValue::ExactMatchL(const CX520AttributeTypeAndValue& aElement) const
471 if (*(iType) != *(aElement.iType))
475 HBufC* lhs = this->ValueL();
476 CleanupStack::PushL(lhs);
477 HBufC* rhs = aElement.ValueL();
479 TPtr plhs = lhs->Des();
480 TPtr prhs = rhs->Des();
485 // DEF124902: Certificate name matching done in accordance to RFC3280
486 // RFC3280: Printable String and Email address(of value type 'IA5String') will
487 // be compared case-insensitively.
489 if (IsCaseInSensitiveL(iValue->Des()))
491 //case insensitive comparison for Printable String and IA5String (EmailAdress only).
492 res = (plhs.CompareF(prhs) == 0);
496 // case-sensitive comparison for strings other than printable string
497 // Exception: This may include IA5Stings other than 'EmailAddress' attiribute types.
498 res = (plhs.Compare(prhs) == 0);
500 CleanupStack::PopAndDestroy();
505 void CX520AttributeTypeAndValue::ExternalizeL(RWriteStream& aStream) const
507 aStream.WriteInt32L(iType->Des().Length());
509 aStream.WriteInt32L(iValue->Des().Length());
513 void CX520AttributeTypeAndValue::InternalizeL(RReadStream& aStream)
516 maxlen = aStream.ReadInt32L();
517 iType = HBufC::NewL(aStream,maxlen);
518 maxlen = aStream.ReadInt32L();
519 iValue = HBufC8::NewL(aStream,maxlen);