os/security/cryptoservices/certificateandkeymgmt/x500/x520ava.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /*
     2 * Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     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".
     8 *
     9 * Initial Contributors:
    10 * Nokia Corporation - initial contribution.
    11 *
    12 * Contributors:
    13 *
    14 * Description: 
    15 *
    16 */
    17 
    18 
    19 #include <x520ava.h>
    20 #include "X500dec.h"
    21 #include <asn1enc.h>
    22 #include <asn1dec.h>
    23 
    24 
    25 EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewL(const CX520AttributeTypeAndValue& aPair)
    26 	{
    27 	CX520AttributeTypeAndValue* self = CX520AttributeTypeAndValue::NewLC(aPair);
    28 	CleanupStack::Pop();//self
    29 	return self;
    30 	}
    31 
    32 EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewLC(const CX520AttributeTypeAndValue& aPair)
    33 	{
    34 	CX520AttributeTypeAndValue* self = new(ELeave) CX520AttributeTypeAndValue;
    35 	CleanupStack::PushL(self);
    36 	self->ConstructL(aPair);
    37 	return self;
    38 	}
    39 
    40 EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewL(const TDesC8& aBinaryData)
    41 	{
    42 	TInt pos = 0;
    43 	return CX520AttributeTypeAndValue::NewL(aBinaryData, pos);
    44 	}
    45 
    46 EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewLC(const TDesC8& aBinaryData)
    47 	{
    48 	TInt pos = 0;
    49 	return CX520AttributeTypeAndValue::NewLC(aBinaryData, pos);
    50 	}
    51 
    52 EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewL(const TDesC8& aBinaryData, TInt& aPos)
    53 	{
    54 	CX520AttributeTypeAndValue* self = CX520AttributeTypeAndValue::NewLC(aBinaryData, aPos);
    55 	CleanupStack::Pop();
    56 	return self;
    57 	}
    58 
    59 EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewLC(const TDesC8& aBinaryData, TInt& aPos)
    60 	{
    61 	CX520AttributeTypeAndValue* self = new(ELeave) CX520AttributeTypeAndValue;
    62 	CleanupStack::PushL(self);
    63 	self->ConstructL(aBinaryData, aPos);
    64 	return self;
    65 	}
    66 
    67 EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewL(RReadStream& aStream)
    68 	{
    69 	CX520AttributeTypeAndValue* self = CX520AttributeTypeAndValue::NewLC(aStream);
    70 	CleanupStack::Pop();//self
    71 	return self;
    72 	}
    73 
    74 EXPORT_C CX520AttributeTypeAndValue* CX520AttributeTypeAndValue::NewLC(RReadStream& aStream)
    75 	{
    76 	CX520AttributeTypeAndValue* self = new(ELeave) CX520AttributeTypeAndValue;
    77 	CleanupStack::PushL(self);
    78 	self->InternalizeL(aStream);
    79 	return self;
    80 	}
    81 
    82 /** Allocates and initializes a new attribute-value pair object from 
    83 	type and value.
    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)
    89 	{
    90 	CX520AttributeTypeAndValue* self = CX520AttributeTypeAndValue::NewLC(aType, aValue);
    91 	CleanupStack::Pop(); // self
    92 	return self;
    93 	}
    94 
    95 /** Allocates and initializes a new attribute-value pair object from 
    96 	type and value. Pushes the newly allocated object onto the 
    97 	cleanup stack.
    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)
   105 	{
   106 	CX520AttributeTypeAndValue* self = new(ELeave) CX520AttributeTypeAndValue;
   107 	CleanupStack::PushL(self);
   108 	self->ConstructL(aType, aValue);
   109 	return self;
   110 	}
   111 
   112 CX520AttributeTypeAndValue::CX520AttributeTypeAndValue()
   113 	:iType(NULL), iValue(NULL)
   114 	{
   115 	}
   116 
   117 void CX520AttributeTypeAndValue::ConstructL(const CX520AttributeTypeAndValue& aPair)
   118 	{
   119 	iType = aPair.iType->AllocL();
   120 	iValue = aPair.iValue->AllocL();
   121 	}
   122 
   123 void CX520AttributeTypeAndValue::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
   124 	{
   125 	TASN1DecGeneric dec(aBinaryData.Right(aBinaryData.Length() - aPos));
   126 	dec.InitL();
   127 	TInt end = aPos + dec.LengthDER();
   128 	aPos += dec.LengthDERHeader();
   129 
   130 	//first element must be the id
   131 	TASN1DecObjectIdentifier encOID;
   132 	iType = encOID.DecodeDERL(aBinaryData, aPos);
   133 	//second is the data
   134 	TASN1DecGeneric second(aBinaryData.Right(aBinaryData.Length() - aPos));
   135 	second.InitL();
   136 
   137 	iValue = second.Encoding().AllocL();;
   138 	aPos += second.LengthDER();
   139 
   140 	if (aPos != end)
   141 		{
   142 		User::Leave(KErrArgument);
   143 		}
   144 	}
   145 
   146 void CX520AttributeTypeAndValue::ConstructL(TAttributeType aType, const TDesC8& aValue)
   147 	{
   148 	// iType is string representation of OID corresponding to the aType.
   149 	TPtrC ptr;
   150 	TInt maxlen = 64; // a reasonable default
   151 	TTagType type = EASN1PrintableString; // the default for all except email, unstructured name and domain component
   152 	switch(aType)
   153 		{
   154 		case ECommonName: 
   155 			ptr.Set(KX520CommonName); 
   156 			maxlen = KX520MaxCNLength;
   157 			break;
   158 		case ELocalityName:
   159 			ptr.Set(KX520LocalityName);
   160 			maxlen = KX520MaxLLength;
   161 			break;
   162 		case EStateOrProvinceName:
   163 			ptr.Set(KX520StateOrProvinceName);
   164 			maxlen = KX520MaxSOPLength;
   165 			break;
   166 		case EPostalCode:
   167 			ptr.Set(KX520PostalCode);
   168 			maxlen = KX520MaxPostalCodeLength;
   169 			break;
   170 		case EOrganizationName:
   171 			ptr.Set(KX520OrganizationName);
   172 			maxlen = KX520MaxOLength;
   173 			break;
   174 		case EOrganizationalUnitName:
   175 			ptr.Set(KX520OrganizationalUnitName);
   176 			maxlen = KX520MaxOULength;
   177 			break;
   178 		case ETitle:
   179 			ptr.Set(KX520Title);
   180 			maxlen = KX520MaxTLength;
   181 			break;
   182 		case EDNQualifier:
   183 			ptr.Set(KX520DNQualifier);
   184 			maxlen = 64; // no information was found on this one, so set to a safe minimum
   185 			break;
   186 		case ECountryName:
   187 			ptr.Set(KX520CountryName);
   188 			maxlen = KX520MaxCNLength;
   189 			break;
   190 		case EGivenName:
   191 			ptr.Set(KX520GivenName);
   192 			maxlen = KX520MaxGNLength;
   193 			break;
   194 		case ESurname:
   195 			ptr.Set(KX520Surname);
   196 			maxlen = KX520MaxSLength;
   197 			break;
   198 		case EInitials:
   199 			ptr.Set(KX520Initials);
   200 			maxlen = KX520MaxILength;
   201 			break;
   202 		case EGenerationQualifier:
   203 			ptr.Set(KX520GenerationQualifier);
   204 			maxlen = KX520MaxGQLength;
   205 			break;
   206 		case EPKCS9EmailAddress:
   207 			ptr.Set(KPKCS9EmailAddress);
   208 			maxlen = KPKCS9MaxEmailAddressLength;
   209 			type = EASN1IA5String;
   210 			break;
   211 		case ESerialNumber:
   212 			ptr.Set(KX520SerialNumber);
   213 			maxlen = KX520MaxSNLength;
   214 			break;
   215 		case ERFC2247DomainComponent:
   216 			ptr.Set(KRFC2247DomainComponent);
   217 			maxlen = KRFC2247MaxDomainComponentLength;
   218 			type = EASN1IA5String;
   219 			break;
   220 		case ERFC2256Street:
   221 			ptr.Set(KRFC2256Street);
   222 			maxlen = KRFC2256StreetLength;
   223 			break;
   224 		case EPKCS9UnstructuredName:
   225 			{
   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();	
   232 			break;	
   233 			}
   234 		case EX520Description:
   235 			{
   236 			ptr.Set(KX520Description);
   237 			maxlen = KX520MaxDescriptionLength;
   238 			break;
   239 			}
   240 		default:
   241 			User::Leave(KErrArgument);
   242 		}
   243 	// Verify if the passed length is within limits
   244 	if(aValue.Length() > maxlen)
   245 		User::Leave(KErrArgument);
   246 
   247 	// Allocate OID string for iType
   248 	iType = ptr.AllocL();
   249 
   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);
   255 	TUint pos = 0;
   256 	TPtr8 bufptr(buf->Des());
   257 	enc->WriteDERL(bufptr, pos);
   258 	iValue = bufptr.AllocL();
   259 	CleanupStack::PopAndDestroy(2);
   260 	}
   261 
   262 EXPORT_C const TPtrC CX520AttributeTypeAndValue::Type() const
   263 	{
   264 	return iType->Des();
   265 	}
   266 
   267 EXPORT_C const TPtrC8 CX520AttributeTypeAndValue::EncodedValue() const
   268 	{
   269 	return iValue->Des();
   270 	}
   271 
   272 EXPORT_C HBufC* CX520AttributeTypeAndValue::ValueL() const
   273 	{
   274 	if (iType->Des() == KX520CountryName)
   275 		{
   276 		TASN1DecPrintableString encPString;
   277 		TInt pos = 0;
   278 		HBufC* res = encPString.DecodeDERL(iValue->Des(), pos);
   279 		CleanupStack::PushL(res);
   280 		if (res->Length() > KX520MaxCLength)
   281 			{
   282 			User::Leave(KErrArgument);
   283 			}
   284 		CleanupStack::Pop();
   285 		return res;
   286 		}
   287 	if (iType->Des() == KX520DNQualifier)
   288 		{
   289 		TInt pos = 0;
   290 		TASN1DecPrintableString encPString;
   291 		HBufC* res = encPString.DecodeDERL(iValue->Des(), pos);
   292 		return res;
   293 		}
   294 	if (iType->Des() == KPKCS9EmailAddress)
   295 		{
   296 		TASN1DecIA5String encIA5String;
   297 		TInt pos = 0;
   298 		HBufC* res = encIA5String.DecodeDERL(iValue->Des(), pos);
   299 		CleanupStack::PushL(res);
   300 		if (res->Length() > KPKCS9MaxEmailAddressLength)
   301 			{
   302 			User::Leave(KErrArgument);
   303 			}
   304 		CleanupStack::Pop();
   305 		return res;
   306 		}
   307 	if (iType->Des() == KRFC2247DomainComponent)
   308 		{
   309 		TASN1DecIA5String encIA5String;
   310 		TInt pos = 0;
   311 		HBufC* res = encIA5String.DecodeDERL(iValue->Des(), pos);
   312 		CleanupStack::PushL(res);
   313 		if (res->Length() > KRFC2247MaxDomainComponentLength)
   314 			{
   315 			User::Leave(KErrArgument);
   316 			}
   317 		CleanupStack::Pop();
   318 		return res;
   319 		}
   320 	if (iType->Des() == KX520SerialNumber)
   321 		{
   322 		TASN1DecPrintableString encPString;
   323 		TInt pos = 0;
   324 		HBufC* res = encPString.DecodeDERL(iValue->Des(), pos);
   325 		CleanupStack::PushL(res);
   326 		if (res->Length() > KX520MaxSNLength)
   327 			{
   328 			User::Leave(KErrArgument);
   329 			}
   330 		CleanupStack::Pop();
   331 		return res;
   332 		}
   333 	TInt maxLength = 0;
   334 	if (iType->Des() == KPKCS9UnstructuredName)
   335 		{
   336 		TASN1DecGeneric decoderGeneric(iValue->Des());
   337 		decoderGeneric.InitL();
   338 		// The encoded value should be a IA5String
   339 		if (decoderGeneric.Tag() == EASN1IA5String)
   340 			{
   341 			TASN1DecIA5String encIA5String;
   342 			TInt pos = 0;
   343 			HBufC* res = encIA5String.DecodeDERL(iValue->Des(), pos);
   344 			CleanupStack::PushL(res);
   345 			if (res->Length() > KPKCS9MaxUnstructuredNameLength)
   346 				{
   347 				User::Leave(KErrArgument);
   348 				}
   349 			CleanupStack::Pop();
   350 			return res;					
   351 			}
   352 		// But it could also be a UTF8String to support internationalization issues
   353 		else
   354 			{
   355 			maxLength = KPKCS9MaxUnstructuredNameLength;	
   356 			}
   357 		}	
   358 	if (iType->Des() == KX520OrganizationName)
   359 		{
   360 		maxLength = KX520MaxOLength;
   361 		}
   362 	if (iType->Des() == KX520OrganizationalUnitName)
   363 		{
   364 		maxLength = KX520MaxOULength;
   365 		}
   366 	if (iType->Des() == KX520LocalityName)
   367 		{
   368 		maxLength = KX520MaxLLength;
   369 		}
   370 	if (iType->Des() == KX520StateOrProvinceName)
   371 		{
   372 		maxLength = KX520MaxSOPLength;
   373 		}
   374 	if (iType->Des() == KX520Title)
   375 		{
   376 		maxLength = KX520MaxTLength;
   377 		}
   378 	if (iType->Des() == KX520CommonName)
   379 		{
   380 		maxLength = KX520MaxCNLength;
   381 		}
   382 	if (iType->Des() == KX520Surname)
   383 		{
   384 		maxLength = KX520MaxSLength;
   385 		}
   386 	if (iType->Des() == KX520GivenName)
   387 		{
   388 		maxLength = KX520MaxGNLength;
   389 		}
   390 	if (iType->Des() == KX520Initials)
   391 		{
   392 		maxLength = KX520MaxILength;
   393 		}
   394 	if (iType->Des() == KX520GenerationQualifier)
   395 		{
   396 		maxLength = KX520MaxGQLength;
   397 		}
   398 	if (iType->Des() == KX520PostalCode)
   399 		{
   400 		maxLength = KX520MaxPostalCodeLength;
   401 		}
   402 	if (iType->Des() == KRFC2256Street)
   403 		{
   404 		maxLength = KRFC2256StreetLength;
   405 		}
   406 	if (iType->Des() == KX520Description)
   407 		{
   408 		maxLength = KX520MaxDescriptionLength;
   409 		}
   410 	if (maxLength == 0)
   411 		{
   412 		User::Leave(KErrNotSupported);
   413 		}
   414 	TASN1DecX500DirectoryString encDString;
   415 	TInt pos = 0;
   416 	HBufC* res = encDString.DecodeDERL(iValue->Des(), pos, maxLength);
   417 	return res;
   418 	}
   419 
   420 TBool CX520AttributeTypeAndValue::IsCaseInSensitiveL(const TDesC8& aSource) const
   421 	{
   422 	TPtr attribute = iType->Des();
   423 	TBool caseInsensitiveAttr = (attribute == KPKCS9EmailAddress || attribute == KPKCS9UnstructuredName || attribute == KX520Description);
   424 	TASN1DecGeneric gen(aSource);
   425 	gen.InitL();
   426 	return ((gen.Tag() == EASN1PrintableString) || caseInsensitiveAttr);
   427 	}
   428 
   429 
   430 EXPORT_C CASN1EncSequence* CX520AttributeTypeAndValue::EncodeASN1LC() const
   431 	{
   432 	CASN1EncSequence *seq = CASN1EncSequence::NewLC();
   433 	CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(Type());
   434 	seq->AddAndPopChildL(oid);
   435 
   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 
   442 	// has.
   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);
   452 	return seq;
   453 	}
   454 
   455 EXPORT_C CASN1EncSequence* CX520AttributeTypeAndValue::EncodeASN1L() const
   456 	{
   457 	CASN1EncSequence *seq = EncodeASN1LC();
   458 	CleanupStack::Pop(seq);
   459 	return seq;
   460 	}
   461 
   462 EXPORT_C CX520AttributeTypeAndValue::~CX520AttributeTypeAndValue()
   463 	{
   464 	delete iType;
   465 	delete iValue;
   466 	}
   467 
   468 EXPORT_C TBool CX520AttributeTypeAndValue::ExactMatchL(const CX520AttributeTypeAndValue& aElement) const
   469 	{
   470 	TBool res = EFalse;
   471 	if (*(iType) != *(aElement.iType))
   472 		{
   473 		return res;
   474 		}
   475 	HBufC* lhs = this->ValueL();
   476 	CleanupStack::PushL(lhs);
   477 	HBufC* rhs = aElement.ValueL();
   478 
   479 	TPtr plhs = lhs->Des();
   480 	TPtr prhs = rhs->Des();
   481 	plhs.TrimAll();
   482 	prhs.TrimAll();
   483 
   484 
   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.  
   488  	
   489     if (IsCaseInSensitiveL(iValue->Des()))
   490  	    {
   491  	     //case insensitive comparison for Printable String and IA5String (EmailAdress only).
   492  	     res = (plhs.CompareF(prhs) == 0);
   493  	    }
   494     else
   495 	    {
   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);
   499 	    }
   500 	CleanupStack::PopAndDestroy();
   501 	delete rhs;
   502 	return res; 
   503 	}
   504 
   505 void CX520AttributeTypeAndValue::ExternalizeL(RWriteStream& aStream) const
   506 	{
   507 	aStream.WriteInt32L(iType->Des().Length());
   508 	aStream << *iType;
   509 	aStream.WriteInt32L(iValue->Des().Length());
   510 	aStream << *iValue;
   511 	}
   512 
   513 void CX520AttributeTypeAndValue::InternalizeL(RReadStream& aStream)
   514 	{
   515 	TInt maxlen;
   516 	maxlen = aStream.ReadInt32L();
   517 	iType = HBufC::NewL(aStream,maxlen);
   518 	maxlen = aStream.ReadInt32L();
   519 	iValue = HBufC8::NewL(aStream,maxlen);
   520 	}