os/ossrv/ssl/libcrypto/src/crypto/certretriever/createx509.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/ossrv/ssl/libcrypto/src/crypto/certretriever/createx509.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,474 @@
     1.4 +/*
     1.5 +Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
     1.6 +
     1.7 +Redistribution and use in source and binary forms, with or without 
     1.8 +modification, are permitted provided that the following conditions are met:
     1.9 +
    1.10 +* Redistributions of source code must retain the above copyright notice, this 
    1.11 +  list of conditions and the following disclaimer.
    1.12 +* Redistributions in binary form must reproduce the above copyright notice, 
    1.13 +  this list of conditions and the following disclaimer in the documentation 
    1.14 +  and/or other materials provided with the distribution.
    1.15 +* Neither the name of Nokia Corporation nor the names of its contributors 
    1.16 +  may be used to endorse or promote products derived from this software 
    1.17 +  without specific prior written permission.
    1.18 +
    1.19 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
    1.20 +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
    1.21 +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
    1.22 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 
    1.23 +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
    1.24 +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
    1.25 +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
    1.26 +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
    1.27 +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    1.28 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.29 +
    1.30 +Description:
    1.31 +*/
    1.32 +
    1.33 +
    1.34 +#include "createx509.h"
    1.35 +
    1.36 +
    1.37 +X509* CX509_Initializer::CreateX509L(CX509Certificate* X509Cert)
    1.38 +{
    1.39 +	X509* ret = X509_new();
    1.40 +	TBool serail = ETrue;
    1.41 +	
    1.42 +	if(ret != NULL)
    1.43 +	{
    1.44 +	
    1.45 +//validity
    1.46 +		X509_VAL_free(ret->cert_info->validity);
    1.47 +		ret->cert_info->validity = CreateX509_VAL(X509Cert); 
    1.48 +
    1.49 +//issuer
    1.50 +		const CX500DistinguishedName& IssName = X509Cert->IssuerName();	
    1.51 +		X509_NAME_free(ret->cert_info->issuer);
    1.52 +		ret->cert_info->issuer = CreateX509_NAMEL(IssName);
    1.53 +
    1.54 +//subject
    1.55 +		const CX500DistinguishedName& SubName = X509Cert->SubjectName();	
    1.56 +		X509_NAME_free(ret->cert_info->subject);
    1.57 +		ret->cert_info->subject = CreateX509_NAMEL(SubName);
    1.58 +	//	const HBufC * name = SubName.DisplayNameL();
    1.59 +
    1.60 +//signature
    1.61 +		const TPtrC8* sig_alg_ptr = X509Cert->DataElementEncoding(CX509Certificate::EAlgorithmId);
    1.62 +		X509_ALGOR_free(ret->cert_info->signature);
    1.63 +		ret->cert_info->signature = CreateX509_ALGORL(sig_alg_ptr);
    1.64 +
    1.65 +//serialnumber
    1.66 +		const TPtrC8 sernum = X509Cert->SerialNumber();
    1.67 +		ASN1_INTEGER_free(ret->cert_info->serialNumber);
    1.68 +		ret->cert_info->serialNumber = CreateASN1_STRING(sernum.Length(),V_ASN1_INTEGER,(unsigned char *)sernum.Ptr(),0);		
    1.69 +		if((sernum.Length()== 1) && sernum[0]==0)
    1.70 +			serail = EFalse;
    1.71 +			
    1.72 +//version
    1.73 +
    1.74 +		TInt ver = X509Cert->Version();
    1.75 +		unsigned char verVal = (unsigned char)(ver-1);		
    1.76 +		ASN1_INTEGER_free(ret->cert_info->version);
    1.77 +		if( (verVal) || (!serail))// for X509 V1 certificates, version is null if any serial number present.
    1.78 +			ret->cert_info->version = CreateASN1_STRING(1,V_ASN1_INTEGER,&verVal,0);
    1.79 +
    1.80 +
    1.81 +//issuerUID
    1.82 +		const TPtrC8* issUID_enc = X509Cert->DataElementEncoding(CX509Certificate::EIssuerUID);
    1.83 +		if(issUID_enc)
    1.84 +			ret->cert_info->issuerUID = CreateASN1_STRING(issUID_enc->Length(),V_ASN1_BIT_STRING,(unsigned char *)issUID_enc->Ptr(),0);
    1.85 +		
    1.86 +
    1.87 +//subjectUID
    1.88 +		const TPtrC8* subUID_enc = X509Cert->DataElementEncoding(CX509Certificate::ESubjectUID);
    1.89 +		if(subUID_enc)
    1.90 +			ret->cert_info->subjectUID = CreateASN1_STRING(subUID_enc->Length(),V_ASN1_BIT_STRING,(unsigned char *)subUID_enc->Ptr(),0);
    1.91 +
    1.92 +//key
    1.93 +		X509_PUBKEY_free(ret->cert_info->key);
    1.94 +		ret->cert_info->key = CreateX509_PUBKEYL(X509Cert);
    1.95 +
    1.96 +	
    1.97 +//extension
    1.98 +
    1.99 +
   1.100 +		ret->cert_info->extensions = CreateSTACKOF_X509_EXTENSIONL(X509Cert);
   1.101 +
   1.102 +		
   1.103 +//name
   1.104 +		ret->name = X509_NAME_oneline(ret->cert_info->subject, NULL, 0);
   1.105 +
   1.106 +//sig_alg
   1.107 +		X509_ALGOR_free(ret->sig_alg);
   1.108 +		ret->sig_alg = CreateX509_ALGORL(sig_alg_ptr);
   1.109 +		
   1.110 +//signature
   1.111 +		const TPtrC8 sig = X509Cert->Signature();
   1.112 +		ASN1_STRING_free(ret->signature);
   1.113 +		ret->signature = CreateASN1_STRING(sig.Length(), V_ASN1_BIT_STRING, (unsigned char *)sig.Ptr(), ASN1_STRING_FLAG_BITS_LEFT);
   1.114 +	}
   1.115 +		
   1.116 +	return ret;
   1.117 +}
   1.118 +
   1.119 +
   1.120 +X509_ALGOR* CX509_Initializer::CreateX509_ALGORL(const TPtrC8* ptr)
   1.121 +{
   1.122 +	X509_ALGOR* ret = X509_ALGOR_new();
   1.123 +	
   1.124 +	TASN1DecGeneric dec((TDesC8 &)*ptr);	
   1.125 +	dec.InitL();
   1.126 +	
   1.127 +	TASN1DecSequence encSeq;
   1.128 +	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(dec);
   1.129 +	
   1.130 +	TASN1DecGeneric& AlgorEncSeq = *(seq->At(0));
   1.131 +
   1.132 +	if (dec.LengthDERContent() > AlgorEncSeq.LengthDER()) // can also check for (seq->Count() > 1) alternatively
   1.133 +	{
   1.134 +		// parameter part is present in the encoding.
   1.135 +		TASN1DecGeneric& ParameterEncSeq = *(seq->At(1));
   1.136 +		
   1.137 +		// if param = 5, ie. ASN1 type NULL, then create a NULL ASN1 STRING
   1.138 +		ret->parameter = ASN1_TYPE_new();
   1.139 +		ret->parameter->type = (TInt)ParameterEncSeq.Encoding()[0];
   1.140 +		
   1.141 +		if(ret->parameter->type != V_ASN1_NULL)
   1.142 +		{
   1.143 +			// we have some parameter 
   1.144 +			// add code to fill this stuff
   1.145 +		}
   1.146 +	}
   1.147 +	else
   1.148 +	{
   1.149 +		//encoding does not contain parameter at all
   1.150 +		//ret->parameter is anyway NULL when X509_ALGOR is created
   1.151 +		//Not sure if we need to create a NULL ASN1 string or just leave parameter = NULL
   1.152 +	}
   1.153 +	
   1.154 +	
   1.155 +	const TDesC8& algor_data = AlgorEncSeq.GetContentDER();
   1.156 +	char * ch_algor_data = (char *)algor_data.Ptr();
   1.157 +	
   1.158 +	ret->algorithm = ASN1_OBJECT_new();
   1.159 +	ret->algorithm->length = AlgorEncSeq.LengthDERContent();	
   1.160 +	ret->algorithm->data = (unsigned char *)OPENSSL_malloc(ret->algorithm->length);
   1.161 +	if(ret->algorithm->data)
   1.162 +		memcpy(ret->algorithm->data, ch_algor_data, ret->algorithm->length);
   1.163 +	//else log error- cannot malloc
   1.164 +	
   1.165 +	ret->algorithm->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;  // so that X509_ALGOR_free() frees all internally allocated data
   1.166 +	
   1.167 +	CleanupStack::PopAndDestroy();	//seq
   1.168 +	
   1.169 +	return ret;
   1.170 +}
   1.171 +
   1.172 +
   1.173 +
   1.174 +X509_NAME* CX509_Initializer::CreateX509_NAMEL(const CX500DistinguishedName& DistName)
   1.175 +{
   1.176 +	X509_NAME* ret = X509_NAME_new();
   1.177 +	
   1.178 +	CASN1EncSequence * Asn1Seq = DistName.EncodeASN1LC();			
   1.179 +
   1.180 +	HBufC8* octetData = HBufC8::NewMaxLC(5000);
   1.181 +	TPtr8 oct(octetData->Des());
   1.182 +	oct.FillZ();
   1.183 +	oct.SetLength(KMaxNameLength);
   1.184 +	TUint writePos = 0;
   1.185 +	Asn1Seq->WriteDERL(oct, writePos);			
   1.186 +
   1.187 +  	TInt len = Fill_X509_NAME_ENTRYL(ret, octetData->Des());
   1.188 +	
   1.189 +	char *p = (char *)oct.PtrZ();
   1.190 +
   1.191 +    ret->bytes->data = (char *)OPENSSL_malloc(len);        // no need to free this. BUF_MEM_free will free if not NULL
   1.192 +    if(ret->bytes->data)
   1.193 +     memcpy(ret->bytes->data, p, len);
   1.194 +    //else log error- cannot malloc
   1.195 +    
   1.196 +	ret->bytes->length = len;
   1.197 +	ret->bytes->max = len;
   1.198 +
   1.199 +	ret->hash = 0; // for now filling zero. Not sure.
   1.200 +	
   1.201 +	CleanupStack::PopAndDestroy(2); // Asn1Seq, octetData
   1.202 +	
   1.203 +	return ret;
   1.204 +} 
   1.205 +
   1.206 +
   1.207 +// return the length of the encoded sequence
   1.208 +TInt CX509_Initializer::Fill_X509_NAME_ENTRYL(X509_NAME * name, const TDesC8& aBinaryData)
   1.209 +{
   1.210 +	TInt aPos = 0;
   1.211 +	TASN1DecGeneric dec(aBinaryData.Right(aBinaryData.Length() - aPos));
   1.212 +	dec.InitL();
   1.213 +	
   1.214 +	TInt end = aPos + dec.LengthDER();
   1.215 +	aPos += dec.LengthDERHeader();
   1.216 +
   1.217 +	if (dec.Tag() != EASN1Sequence)
   1.218 +		{
   1.219 +		User::Leave(KErrArgument);
   1.220 +		}
   1.221 +	while (aPos < end)
   1.222 +		{
   1.223 +		TASN1DecGeneric rdn(aBinaryData.Right(aBinaryData.Length() - aPos));
   1.224 +		rdn.InitL();
   1.225 +		if (rdn.Tag() != EASN1Set)
   1.226 +			{
   1.227 +			User::Leave(KErrArgument);
   1.228 +			}
   1.229 +		TInt rdnEnd = rdn.LengthDER();
   1.230 +		TInt rdnPos = rdn.LengthDERHeader();//add on header
   1.231 +		while (rdnPos < rdnEnd)
   1.232 +			{
   1.233 +			const TDesC8& TypeValEnc = rdn.Encoding();
   1.234 +			
   1.235 +		    				TASN1DecGeneric dec(TypeValEnc.Right(TypeValEnc.Length() - rdnPos));
   1.236 +							dec.InitL();
   1.237 +							TInt tvend = rdnPos + dec.LengthDER();
   1.238 +							rdnPos += dec.LengthDERHeader();
   1.239 +						
   1.240 +							//first element must be the id
   1.241 +							TASN1DecObjectIdentifier encOID;
   1.242 +							//iType = encOID.DecodeDERL(TypeValEnc, rdnPos);
   1.243 +							TASN1DecGeneric first(TypeValEnc.Right(TypeValEnc.Length() - rdnPos));
   1.244 +							first.InitL();
   1.245 +							rdnPos += first.LengthDER();
   1.246 +								if (first.Tag() != EASN1ObjectIdentifier)
   1.247 +								{
   1.248 +								User::Leave(KErrArgument);
   1.249 +								}
   1.250 +						
   1.251 +							const TDesC8& type = first.GetContentDER();
   1.252 +							char * ch_type = (char *)type.Ptr();
   1.253 +				
   1.254 +							//second is the data
   1.255 +							TASN1DecGeneric second(TypeValEnc.Right(TypeValEnc.Length() - rdnPos));
   1.256 +							second.InitL();
   1.257 +							rdnPos += second.LengthDER();
   1.258 +							
   1.259 +							const TDesC8& value = second.GetContentDER();
   1.260 +							char * ch_value = (char *)value.Ptr();
   1.261 +							
   1.262 +							X509_NAME_ENTRY* new_entry = CreateX509_NAME_ENTRY(ch_type,first.LengthDERContent(), ch_value, second.LengthDERContent(), second.Tag());
   1.263 +							
   1.264 +							X509_NAME_add_entry(name, new_entry, -1, 0);
   1.265 +							
   1.266 +							//we can free this, since add_entry makes a copy and adds
   1.267 +							X509_NAME_ENTRY_free(new_entry);
   1.268 +							//
   1.269 +							
   1.270 +							if (rdnPos != tvend)
   1.271 +								{
   1.272 +								User::Leave(KErrArgument);
   1.273 +								}
   1.274 +			
   1.275 +			}
   1.276 +		aPos += rdnEnd;
   1.277 +		}
   1.278 +	if (aPos != end)
   1.279 +		{
   1.280 +		User::Leave(KErrArgument);
   1.281 +		}
   1.282 +	return end;
   1.283 +}
   1.284 +
   1.285 +
   1.286 +X509_NAME_ENTRY * CX509_Initializer::CreateX509_NAME_ENTRY(char* type, int typeLen, char * value, int valueLen, int stringType)
   1.287 +{
   1.288 +	X509_NAME_ENTRY * newEntry = X509_NAME_ENTRY_new();
   1.289 +	
   1.290 +	newEntry->object->length = typeLen;
   1.291 +	newEntry->object->data = (unsigned char *)OPENSSL_malloc(typeLen);
   1.292 +	if(newEntry->object->data)
   1.293 +		memcpy(newEntry->object->data, type, typeLen);
   1.294 +	//else log error- cannot malloc
   1.295 +	
   1.296 +	ASN1_STRING_free(newEntry->value);
   1.297 +	newEntry->value = CreateASN1_STRING(valueLen, stringType, (unsigned char* )value, 0);
   1.298 +	
   1.299 +	newEntry->object->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;  // so that X509_NAME_ENTRY_free() frees all internally allocated data
   1.300 +	
   1.301 +	return newEntry;	
   1.302 +	
   1.303 +}
   1.304 +
   1.305 +
   1.306 +X509_VAL * CX509_Initializer::CreateX509_VAL(CX509Certificate* X509Cert)
   1.307 +{
   1.308 +	X509_VAL * ret = X509_VAL_new();
   1.309 +	
   1.310 +	const CValidityPeriod& val = X509Cert->ValidityPeriod();
   1.311 +				
   1.312 +		TBuf8<KCertMaxBuffer> numBuffer8;
   1.313 +		char* numPtr = (char*)numBuffer8.PtrZ();
   1.314 +	
   1.315 +	//start date (notBefore)
   1.316 +		TDateTime dt = val.Start().DateTime();
   1.317 +			
   1.318 +		numBuffer8.AppendNum(dt.Year());
   1.319 +		if(numBuffer8.Length() > 2)
   1.320 +			numBuffer8.Delete(0, numBuffer8.Length() - 2);
   1.321 +		
   1.322 +		_LIT8(KCertTimeStampFormat, "%02d%02d%02d%02d%02dZ");
   1.323 +		numBuffer8.AppendFormat(KCertTimeStampFormat,dt.Month()+1,dt.Day()+1,dt.Hour(),dt.Minute(),dt.Second());  //Month and Day - offset from zero, so add 1
   1.324 +		numPtr[13]='\0';
   1.325 +		
   1.326 +		ASN1_STRING_free(ret->notBefore);
   1.327 +		ret->notBefore = CreateASN1_STRING(13,V_ASN1_UTCTIME,(unsigned char *)numPtr,0);
   1.328 +
   1.329 +	//finish date (notAfter)
   1.330 +		dt = val.Finish().DateTime();
   1.331 +		
   1.332 +		numBuffer8.Zero();
   1.333 +		numBuffer8.AppendNum(dt.Year());
   1.334 +		if(numBuffer8.Length() > 2)
   1.335 +			numBuffer8.Delete(0, numBuffer8.Length() - 2);
   1.336 +		
   1.337 +		numBuffer8.AppendFormat(KCertTimeStampFormat,dt.Month()+1,dt.Day()+1,dt.Hour(),dt.Minute(),dt.Second());  //Month and Day - offset from zero, so add 1
   1.338 +		numPtr[13]='\0';
   1.339 +		
   1.340 +		ASN1_STRING_free(ret->notAfter);
   1.341 +		ret->notAfter = CreateASN1_STRING(13,V_ASN1_UTCTIME,(unsigned char *)numPtr,0);
   1.342 +		
   1.343 +	return ret;
   1.344 +	
   1.345 +}
   1.346 +
   1.347 +
   1.348 +
   1.349 +ASN1_STRING* CX509_Initializer::CreateASN1_STRING(int len, int type, unsigned char* data, long flags)
   1.350 +{
   1.351 + ASN1_STRING* ret = ASN1_STRING_new();
   1.352 + ret->length = len;
   1.353 + ret->type = type;
   1.354 + if(data!=NULL)
   1.355 + {
   1.356 + 	ret->data = (unsigned char *)OPENSSL_malloc(len);
   1.357 + 	if(ret->data)
   1.358 + 	  memcpy(ret->data,data,len);
   1.359 + 	//else log error- cannot malloc
   1.360 + }
   1.361 + else
   1.362 + 	ret->data = NULL;
   1.363 + 	
   1.364 + ret->flags |= flags;
   1.365 + return ret;
   1.366 +}
   1.367 +
   1.368 +
   1.369 +
   1.370 +X509_PUBKEY* CX509_Initializer::CreateX509_PUBKEYL(CX509Certificate* X509Cert)
   1.371 +{
   1.372 +	X509_PUBKEY* ret = X509_PUBKEY_new();
   1.373 +
   1.374 +//algor
   1.375 +	const TPtrC8* ptr = X509Cert->DataElementEncoding(CX509Certificate::ESubjectPublicKeyInfo);
   1.376 +	
   1.377 +	TInt aPos = 0;
   1.378 +	TASN1DecGeneric dec(ptr->Right(ptr->Length() - aPos));
   1.379 +	dec.InitL();
   1.380 +	
   1.381 +	TInt end = aPos + dec.LengthDER();
   1.382 +	aPos += dec.LengthDERHeader();
   1.383 +
   1.384 +	if (dec.Tag() != EASN1Sequence)
   1.385 +		User::Leave(KErrArgument);
   1.386 +
   1.387 +	if (aPos < end)
   1.388 +		{
   1.389 +			TASN1DecGeneric rdn(ptr->Right(ptr->Length() - aPos));
   1.390 +			rdn.InitL();
   1.391 +			TPtrC8 newPtr = rdn.Encoding();
   1.392 +			
   1.393 +			X509_ALGOR_free(ret->algor);	// free the one allocated by X509_PUBKEY_new
   1.394 +			ret->algor = CreateX509_ALGORL(&newPtr);
   1.395 +		}
   1.396 +	
   1.397 +//public_key
   1.398 +	const CSubjectPublicKeyInfo& pubkey = X509Cert->PublicKey();
   1.399 +	const TPtrC8 keyDat =	pubkey.KeyData();
   1.400 +	
   1.401 +	ASN1_BIT_STRING_free(ret->public_key);
   1.402 +	ret->public_key = CreateASN1_STRING(keyDat.Size(),V_ASN1_BIT_STRING,(unsigned char*)keyDat.Ptr(),0);
   1.403 +	
   1.404 +//pkey
   1.405 +	ret->pkey = NULL;		// we need not create this. Will be created later. Used to cache the computed data
   1.406 +	
   1.407 +	return ret;
   1.408 +}
   1.409 +
   1.410 +
   1.411 +
   1.412 +
   1.413 +STACK_OF(X509_EXTENSION)* CX509_Initializer::CreateSTACKOF_X509_EXTENSIONL(CX509Certificate* X509Cert)
   1.414 +{
   1.415 +	//STACK_OF(X509_EXTENSION) * ret = sk_X509_EXTENSION_new_null();
   1.416 +	STACK_OF(X509_EXTENSION) * ret = NULL;
   1.417 +	
   1.418 +	const TPtrC8* ptr = X509Cert->DataElementEncoding(CX509Certificate::EExtensionList);
   1.419 +	
   1.420 +	const CArrayPtrFlat<CX509CertExtension>& extlist = X509Cert->Extensions();
   1.421 +
   1.422 +	TASN1DecSequence encSeq;
   1.423 +	TInt pos = 0;
   1.424 +
   1.425 +	if(ptr != NULL)	//There is an extension list
   1.426 +	{
   1.427 +		TASN1DecGeneric dec((TDesC8 &)*ptr);
   1.428 +		ret = sk_X509_EXTENSION_new_null();
   1.429 +		dec.InitL();
   1.430 +		
   1.431 +		CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC( dec.GetContentDER(), pos);
   1.432 +	
   1.433 +		TInt count = seq->Count(); // no of extensions in the ext list
   1.434 +		for (TInt i = 0; i < count; i++)
   1.435 +		{
   1.436 +		
   1.437 +			X509_EXTENSION* ext = X509_EXTENSION_new();
   1.438 +		
   1.439 +			ext->object = ASN1_OBJECT_new();
   1.440 +						
   1.441 +			TASN1DecGeneric* gen = seq->At(i);
   1.442 +			TASN1DecGeneric oid(seq->At(i)->GetContentDER());
   1.443 +			oid.InitL();
   1.444 +			
   1.445 +			const TDesC8& ext_obj_data = oid.GetContentDER();
   1.446 +			char * ch_ext_obj_data = (char *)ext_obj_data.Ptr();
   1.447 +			
   1.448 +			ext->object->length = oid.LengthDERContent();
   1.449 +			ext->object->data = (unsigned char *)OPENSSL_malloc(ext->object->length);
   1.450 +			if(ext->object->data)
   1.451 +				memcpy(ext->object->data, ch_ext_obj_data, ext->object->length);
   1.452 +			//else log error- cannot malloc
   1.453 +		
   1.454 +			ext->object->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;  // so that X509_free() frees all internally allocated data
   1.455 +			
   1.456 +			if(extlist.At(i)->Critical())
   1.457 +				ext->critical = extlist.At(i)->Critical();
   1.458 +			
   1.459 +			const TPtrC8 data = extlist.At(i)->Data();
   1.460 +			TASN1DecGeneric value(data);
   1.461 +			value.InitL();
   1.462 +			
   1.463 +			const TDesC8& ext_value = value.GetContentDER();
   1.464 +			char * ch_ext_value = (char *)ext_value.Ptr();
   1.465 +			ASN1_STRING_free(ext->value);
   1.466 +			ext->value = CreateASN1_STRING(value.LengthDERContent(), V_ASN1_OCTET_STRING, (unsigned char *)ch_ext_value, 0);
   1.467 +			
   1.468 +			sk_X509_EXTENSION_push(ret,ext);		
   1.469 +	
   1.470 +		}
   1.471 +			
   1.472 +		CleanupStack::PopAndDestroy();// seq
   1.473 +	}
   1.474 +	
   1.475 +	return ret;
   1.476 +}
   1.477 +