ssl/libcrypto/src/crypto/certretriever/createx509.cpp
changeset 0 e4d67989cc36
child 52 bf6a71c50e42
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 /*
       
     2 Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
       
     3 
       
     4 Redistribution and use in source and binary forms, with or without 
       
     5 modification, are permitted provided that the following conditions are met:
       
     6 
       
     7 * Redistributions of source code must retain the above copyright notice, this 
       
     8   list of conditions and the following disclaimer.
       
     9 * Redistributions in binary form must reproduce the above copyright notice, 
       
    10   this list of conditions and the following disclaimer in the documentation 
       
    11   and/or other materials provided with the distribution.
       
    12 * Neither the name of Nokia Corporation nor the names of its contributors 
       
    13   may be used to endorse or promote products derived from this software 
       
    14   without specific prior written permission.
       
    15 
       
    16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
       
    17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
       
    18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
       
    19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 
       
    20 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
       
    21 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
       
    22 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
       
    23 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
       
    24 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
       
    25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    26 
       
    27 Description:
       
    28 */
       
    29 
       
    30 
       
    31 #include "createx509.h"
       
    32 
       
    33 
       
    34 X509* CX509_Initializer::CreateX509(CX509Certificate* X509Cert)
       
    35 {
       
    36 	X509* ret = X509_new();
       
    37 	TBool serail = ETrue;
       
    38 	
       
    39 	if(ret != NULL)
       
    40 	{
       
    41 	
       
    42 //validity
       
    43 		X509_VAL_free(ret->cert_info->validity);
       
    44 		ret->cert_info->validity = CreateX509_VAL(X509Cert); 
       
    45 
       
    46 //issuer
       
    47 		const CX500DistinguishedName& IssName = X509Cert->IssuerName();	
       
    48 		X509_NAME_free(ret->cert_info->issuer);
       
    49 		ret->cert_info->issuer = CreateX509_NAME(IssName);
       
    50 
       
    51 //subject
       
    52 		const CX500DistinguishedName& SubName = X509Cert->SubjectName();	
       
    53 		X509_NAME_free(ret->cert_info->subject);
       
    54 		ret->cert_info->subject = CreateX509_NAME(SubName);
       
    55 	//	const HBufC * name = SubName.DisplayNameL();
       
    56 
       
    57 //signature
       
    58 		const TPtrC8* sig_alg_ptr = X509Cert->DataElementEncoding(CX509Certificate::EAlgorithmId);
       
    59 		X509_ALGOR_free(ret->cert_info->signature);
       
    60 		ret->cert_info->signature = CreateX509_ALGOR(sig_alg_ptr);
       
    61 
       
    62 //serialnumber
       
    63 		const TPtrC8 sernum = X509Cert->SerialNumber();
       
    64 		ASN1_INTEGER_free(ret->cert_info->serialNumber);
       
    65 		ret->cert_info->serialNumber = CreateASN1_STRING(sernum.Length(),V_ASN1_INTEGER,(unsigned char *)sernum.Ptr(),0);		
       
    66 		if((sernum.Length()== 1) && sernum[0]==0)
       
    67 			serail = EFalse;
       
    68 			
       
    69 //version
       
    70 
       
    71 		TInt ver = X509Cert->Version();
       
    72 		unsigned char verVal = (unsigned char)(ver-1);		
       
    73 		ASN1_INTEGER_free(ret->cert_info->version);
       
    74 		if( (verVal) || (!serail))// for X509 V1 certificates, version is null if any serial number present.
       
    75 			ret->cert_info->version = CreateASN1_STRING(1,V_ASN1_INTEGER,&verVal,0);
       
    76 
       
    77 
       
    78 //issuerUID
       
    79 		const TPtrC8* issUID_enc = X509Cert->DataElementEncoding(CX509Certificate::EIssuerUID);
       
    80 		if(issUID_enc)
       
    81 			ret->cert_info->issuerUID = CreateASN1_STRING(issUID_enc->Length(),V_ASN1_BIT_STRING,(unsigned char *)issUID_enc->Ptr(),0);
       
    82 		
       
    83 
       
    84 //subjectUID
       
    85 		const TPtrC8* subUID_enc = X509Cert->DataElementEncoding(CX509Certificate::ESubjectUID);
       
    86 		if(subUID_enc)
       
    87 			ret->cert_info->subjectUID = CreateASN1_STRING(subUID_enc->Length(),V_ASN1_BIT_STRING,(unsigned char *)subUID_enc->Ptr(),0);
       
    88 
       
    89 //key
       
    90 		X509_PUBKEY_free(ret->cert_info->key);
       
    91 		ret->cert_info->key = CreateX509_PUBKEY(X509Cert);
       
    92 
       
    93 	
       
    94 //extension
       
    95 
       
    96 
       
    97 		ret->cert_info->extensions = CreateSTACKOF_X509_EXTENSION(X509Cert);
       
    98 
       
    99 		
       
   100 //name
       
   101 		ret->name = X509_NAME_oneline(ret->cert_info->subject, NULL, 0);
       
   102 
       
   103 //sig_alg
       
   104 		X509_ALGOR_free(ret->sig_alg);
       
   105 		ret->sig_alg = CreateX509_ALGOR(sig_alg_ptr);
       
   106 		
       
   107 //signature
       
   108 		const TPtrC8 sig = X509Cert->Signature();
       
   109 		ASN1_STRING_free(ret->signature);
       
   110 		ret->signature = CreateASN1_STRING(sig.Length(), V_ASN1_BIT_STRING, (unsigned char *)sig.Ptr(), ASN1_STRING_FLAG_BITS_LEFT);
       
   111 	}
       
   112 		
       
   113 	return ret;
       
   114 }
       
   115 
       
   116 
       
   117 X509_ALGOR* CX509_Initializer::CreateX509_ALGOR(const TPtrC8* ptr)
       
   118 {
       
   119 	X509_ALGOR* ret = X509_ALGOR_new();
       
   120 	
       
   121 	TASN1DecGeneric dec((TDesC8 &)*ptr);	
       
   122 	dec.InitL();
       
   123 	
       
   124 	TASN1DecSequence encSeq;
       
   125 	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(dec);
       
   126 	
       
   127 	TASN1DecGeneric& AlgorEncSeq = *(seq->At(0));
       
   128 
       
   129 	if (dec.LengthDERContent() > AlgorEncSeq.LengthDER()) // can also check for (seq->Count() > 1) alternatively
       
   130 	{
       
   131 		// parameter part is present in the encoding.
       
   132 		TASN1DecGeneric& ParameterEncSeq = *(seq->At(1));
       
   133 		
       
   134 		// if param = 5, ie. ASN1 type NULL, then create a NULL ASN1 STRING
       
   135 		ret->parameter = ASN1_TYPE_new();
       
   136 		ret->parameter->type = (TInt)ParameterEncSeq.Encoding()[0];
       
   137 		
       
   138 		if(ret->parameter->type != V_ASN1_NULL)
       
   139 		{
       
   140 			// we have some parameter 
       
   141 			// add code to fill this stuff
       
   142 		}
       
   143 	}
       
   144 	else
       
   145 	{
       
   146 		//encoding does not contain parameter at all
       
   147 		//ret->parameter is anyway NULL when X509_ALGOR is created
       
   148 		//Not sure if we need to create a NULL ASN1 string or just leave parameter = NULL
       
   149 	}
       
   150 	
       
   151 	
       
   152 	const TDesC8& algor_data = AlgorEncSeq.GetContentDER();
       
   153 	char * ch_algor_data = (char *)algor_data.Ptr();
       
   154 	
       
   155 	ret->algorithm = ASN1_OBJECT_new();
       
   156 	ret->algorithm->length = AlgorEncSeq.LengthDERContent();	
       
   157 	ret->algorithm->data = (unsigned char *)OPENSSL_malloc(ret->algorithm->length);
       
   158 	if(ret->algorithm->data)
       
   159 		memcpy(ret->algorithm->data, ch_algor_data, ret->algorithm->length);
       
   160 	//else log error- cannot malloc
       
   161 	
       
   162 	ret->algorithm->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;  // so that X509_ALGOR_free() frees all internally allocated data
       
   163 	
       
   164 	CleanupStack::PopAndDestroy();	//seq
       
   165 	
       
   166 	return ret;
       
   167 }
       
   168 
       
   169 
       
   170 
       
   171 X509_NAME* CX509_Initializer::CreateX509_NAME(const CX500DistinguishedName& DistName)
       
   172 {
       
   173 	X509_NAME* ret = X509_NAME_new();
       
   174 	
       
   175 	CASN1EncSequence * Asn1Seq = DistName.EncodeASN1LC();			
       
   176 
       
   177 	HBufC8* octetData = HBufC8::NewMaxLC(5000);
       
   178 	TPtr8 oct(octetData->Des());
       
   179 	oct.FillZ();
       
   180 	oct.SetLength(KMaxNameLength);
       
   181 	TUint writePos = 0;
       
   182 	Asn1Seq->WriteDERL(oct, writePos);			
       
   183 
       
   184   	TInt len = Fill_X509_NAME_ENTRY(ret, octetData->Des());
       
   185 	
       
   186 	char *p = (char *)oct.PtrZ();
       
   187 
       
   188     ret->bytes->data = (char *)OPENSSL_malloc(len);        // no need to free this. BUF_MEM_free will free if not NULL
       
   189     if(ret->bytes->data)
       
   190      memcpy(ret->bytes->data, p, len);
       
   191     //else log error- cannot malloc
       
   192     
       
   193 	ret->bytes->length = len;
       
   194 	ret->bytes->max = len;
       
   195 
       
   196 	ret->hash = 0; // for now filling zero. Not sure.
       
   197 	
       
   198 	CleanupStack::PopAndDestroy(2); // Asn1Seq, octetData
       
   199 	
       
   200 	return ret;
       
   201 } 
       
   202 
       
   203 
       
   204 // return the length of the encoded sequence
       
   205 TInt CX509_Initializer::Fill_X509_NAME_ENTRY(X509_NAME * name, const TDesC8& aBinaryData)
       
   206 {
       
   207 	TInt aPos = 0;
       
   208 	TASN1DecGeneric dec(aBinaryData.Right(aBinaryData.Length() - aPos));
       
   209 	dec.InitL();
       
   210 	
       
   211 	TInt end = aPos + dec.LengthDER();
       
   212 	aPos += dec.LengthDERHeader();
       
   213 
       
   214 	if (dec.Tag() != EASN1Sequence)
       
   215 		{
       
   216 		User::Leave(KErrArgument);
       
   217 		}
       
   218 	while (aPos < end)
       
   219 		{
       
   220 		TASN1DecGeneric rdn(aBinaryData.Right(aBinaryData.Length() - aPos));
       
   221 		rdn.InitL();
       
   222 		if (rdn.Tag() != EASN1Set)
       
   223 			{
       
   224 			User::Leave(KErrArgument);
       
   225 			}
       
   226 		TInt rdnEnd = rdn.LengthDER();
       
   227 		TInt rdnPos = rdn.LengthDERHeader();//add on header
       
   228 		while (rdnPos < rdnEnd)
       
   229 			{
       
   230 			const TDesC8& TypeValEnc = rdn.Encoding();
       
   231 			
       
   232 		    				TASN1DecGeneric dec(TypeValEnc.Right(TypeValEnc.Length() - rdnPos));
       
   233 							dec.InitL();
       
   234 							TInt tvend = rdnPos + dec.LengthDER();
       
   235 							rdnPos += dec.LengthDERHeader();
       
   236 						
       
   237 							//first element must be the id
       
   238 							TASN1DecObjectIdentifier encOID;
       
   239 							//iType = encOID.DecodeDERL(TypeValEnc, rdnPos);
       
   240 							TASN1DecGeneric first(TypeValEnc.Right(TypeValEnc.Length() - rdnPos));
       
   241 							first.InitL();
       
   242 							rdnPos += first.LengthDER();
       
   243 								if (first.Tag() != EASN1ObjectIdentifier)
       
   244 								{
       
   245 								User::Leave(KErrArgument);
       
   246 								}
       
   247 						
       
   248 							const TDesC8& type = first.GetContentDER();
       
   249 							char * ch_type = (char *)type.Ptr();
       
   250 				
       
   251 							//second is the data
       
   252 							TASN1DecGeneric second(TypeValEnc.Right(TypeValEnc.Length() - rdnPos));
       
   253 							second.InitL();
       
   254 							rdnPos += second.LengthDER();
       
   255 							
       
   256 							const TDesC8& value = second.GetContentDER();
       
   257 							char * ch_value = (char *)value.Ptr();
       
   258 							
       
   259 							X509_NAME_ENTRY* new_entry = CreateX509_NAME_ENTRY(ch_type,first.LengthDERContent(), ch_value, second.LengthDERContent(), second.Tag());
       
   260 							
       
   261 							X509_NAME_add_entry(name, new_entry, -1, 0);
       
   262 							
       
   263 							//we can free this, since add_entry makes a copy and adds
       
   264 							X509_NAME_ENTRY_free(new_entry);
       
   265 							//
       
   266 							
       
   267 							if (rdnPos != tvend)
       
   268 								{
       
   269 								User::Leave(KErrArgument);
       
   270 								}
       
   271 			
       
   272 			}
       
   273 		aPos += rdnEnd;
       
   274 		}
       
   275 	if (aPos != end)
       
   276 		{
       
   277 		User::Leave(KErrArgument);
       
   278 		}
       
   279 	return end;
       
   280 }
       
   281 
       
   282 
       
   283 X509_NAME_ENTRY * CX509_Initializer::CreateX509_NAME_ENTRY(char* type, int typeLen, char * value, int valueLen, int stringType)
       
   284 {
       
   285 	X509_NAME_ENTRY * newEntry = X509_NAME_ENTRY_new();
       
   286 	
       
   287 	newEntry->object->length = typeLen;
       
   288 	newEntry->object->data = (unsigned char *)OPENSSL_malloc(typeLen);
       
   289 	if(newEntry->object->data)
       
   290 		memcpy(newEntry->object->data, type, typeLen);
       
   291 	//else log error- cannot malloc
       
   292 	
       
   293 	ASN1_STRING_free(newEntry->value);
       
   294 	newEntry->value = CreateASN1_STRING(valueLen, stringType, (unsigned char* )value, 0);
       
   295 	
       
   296 	newEntry->object->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;  // so that X509_NAME_ENTRY_free() frees all internally allocated data
       
   297 	
       
   298 	return newEntry;	
       
   299 	
       
   300 }
       
   301 
       
   302 
       
   303 X509_VAL * CX509_Initializer::CreateX509_VAL(CX509Certificate* X509Cert)
       
   304 {
       
   305 	X509_VAL * ret = X509_VAL_new();
       
   306 	
       
   307 	const CValidityPeriod& val = X509Cert->ValidityPeriod();
       
   308 				
       
   309 		TBuf8<KCertMaxBuffer> numBuffer8;
       
   310 		char* numPtr = (char*)numBuffer8.PtrZ();
       
   311 	
       
   312 	//start date (notBefore)
       
   313 		TDateTime dt = val.Start().DateTime();
       
   314 			
       
   315 		numBuffer8.AppendNum(dt.Year());
       
   316 		if(numBuffer8.Length() > 2)
       
   317 			numBuffer8.Delete(0, numBuffer8.Length() - 2);
       
   318 		
       
   319 		_LIT8(KCertTimeStampFormat, "%02d%02d%02d%02d%02dZ");
       
   320 		numBuffer8.AppendFormat(KCertTimeStampFormat,dt.Month()+1,dt.Day()+1,dt.Hour(),dt.Minute(),dt.Second());  //Month and Day - offset from zero, so add 1
       
   321 		numPtr[13]='\0';
       
   322 		
       
   323 		ASN1_STRING_free(ret->notBefore);
       
   324 		ret->notBefore = CreateASN1_STRING(13,V_ASN1_UTCTIME,(unsigned char *)numPtr,0);
       
   325 
       
   326 	//finish date (notAfter)
       
   327 		dt = val.Finish().DateTime();
       
   328 		
       
   329 		numBuffer8.Zero();
       
   330 		numBuffer8.AppendNum(dt.Year());
       
   331 		if(numBuffer8.Length() > 2)
       
   332 			numBuffer8.Delete(0, numBuffer8.Length() - 2);
       
   333 		
       
   334 		numBuffer8.AppendFormat(KCertTimeStampFormat,dt.Month()+1,dt.Day()+1,dt.Hour(),dt.Minute(),dt.Second());  //Month and Day - offset from zero, so add 1
       
   335 		numPtr[13]='\0';
       
   336 		
       
   337 		ASN1_STRING_free(ret->notAfter);
       
   338 		ret->notAfter = CreateASN1_STRING(13,V_ASN1_UTCTIME,(unsigned char *)numPtr,0);
       
   339 		
       
   340 	return ret;
       
   341 	
       
   342 }
       
   343 
       
   344 
       
   345 
       
   346 ASN1_STRING* CX509_Initializer::CreateASN1_STRING(int len, int type, unsigned char* data, long flags)
       
   347 {
       
   348  ASN1_STRING* ret = ASN1_STRING_new();
       
   349  ret->length = len;
       
   350  ret->type = type;
       
   351  if(data!=NULL)
       
   352  {
       
   353  	ret->data = (unsigned char *)OPENSSL_malloc(len);
       
   354  	if(ret->data)
       
   355  	  memcpy(ret->data,data,len);
       
   356  	//else log error- cannot malloc
       
   357  }
       
   358  else
       
   359  	ret->data = NULL;
       
   360  	
       
   361  ret->flags |= flags;
       
   362  return ret;
       
   363 }
       
   364 
       
   365 
       
   366 
       
   367 X509_PUBKEY* CX509_Initializer::CreateX509_PUBKEY(CX509Certificate* X509Cert)
       
   368 {
       
   369 	X509_PUBKEY* ret = X509_PUBKEY_new();
       
   370 
       
   371 //algor
       
   372 	const TPtrC8* ptr = X509Cert->DataElementEncoding(CX509Certificate::ESubjectPublicKeyInfo);
       
   373 	
       
   374 	TInt aPos = 0;
       
   375 	TASN1DecGeneric dec(ptr->Right(ptr->Length() - aPos));
       
   376 	dec.InitL();
       
   377 	
       
   378 	TInt end = aPos + dec.LengthDER();
       
   379 	aPos += dec.LengthDERHeader();
       
   380 
       
   381 	if (dec.Tag() != EASN1Sequence)
       
   382 		User::Leave(KErrArgument);
       
   383 
       
   384 	if (aPos < end)
       
   385 		{
       
   386 			TASN1DecGeneric rdn(ptr->Right(ptr->Length() - aPos));
       
   387 			rdn.InitL();
       
   388 			TPtrC8 newPtr = rdn.Encoding();
       
   389 			
       
   390 			X509_ALGOR_free(ret->algor);	// free the one allocated by X509_PUBKEY_new
       
   391 			ret->algor = CreateX509_ALGOR(&newPtr);
       
   392 		}
       
   393 	
       
   394 //public_key
       
   395 	const CSubjectPublicKeyInfo& pubkey = X509Cert->PublicKey();
       
   396 	const TPtrC8 keyDat =	pubkey.KeyData();
       
   397 	
       
   398 	ASN1_BIT_STRING_free(ret->public_key);
       
   399 	ret->public_key = CreateASN1_STRING(keyDat.Size(),V_ASN1_BIT_STRING,(unsigned char*)keyDat.Ptr(),0);
       
   400 	
       
   401 //pkey
       
   402 	ret->pkey = NULL;		// we need not create this. Will be created later. Used to cache the computed data
       
   403 	
       
   404 	return ret;
       
   405 }
       
   406 
       
   407 
       
   408 
       
   409 
       
   410 STACK_OF(X509_EXTENSION)* CX509_Initializer::CreateSTACKOF_X509_EXTENSION(CX509Certificate* X509Cert)
       
   411 {
       
   412 	//STACK_OF(X509_EXTENSION) * ret = sk_X509_EXTENSION_new_null();
       
   413 	STACK_OF(X509_EXTENSION) * ret = NULL;
       
   414 	
       
   415 	const TPtrC8* ptr = X509Cert->DataElementEncoding(CX509Certificate::EExtensionList);
       
   416 	
       
   417 	const CArrayPtrFlat<CX509CertExtension>& extlist = X509Cert->Extensions();
       
   418 
       
   419 	TASN1DecSequence encSeq;
       
   420 	TInt pos = 0;
       
   421 
       
   422 	if(ptr != NULL)	//There is an extension list
       
   423 	{
       
   424 		TASN1DecGeneric dec((TDesC8 &)*ptr);
       
   425 		ret = sk_X509_EXTENSION_new_null();
       
   426 		dec.InitL();
       
   427 		
       
   428 		CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC( dec.GetContentDER(), pos);
       
   429 	
       
   430 		TInt count = seq->Count(); // no of extensions in the ext list
       
   431 		for (TInt i = 0; i < count; i++)
       
   432 		{
       
   433 		
       
   434 			X509_EXTENSION* ext = X509_EXTENSION_new();
       
   435 		
       
   436 			ext->object = ASN1_OBJECT_new();
       
   437 						
       
   438 			TASN1DecGeneric* gen = seq->At(i);
       
   439 			TASN1DecGeneric oid(seq->At(i)->GetContentDER());
       
   440 			oid.InitL();
       
   441 			
       
   442 			const TDesC8& ext_obj_data = oid.GetContentDER();
       
   443 			char * ch_ext_obj_data = (char *)ext_obj_data.Ptr();
       
   444 			
       
   445 			ext->object->length = oid.LengthDERContent();
       
   446 			ext->object->data = (unsigned char *)OPENSSL_malloc(ext->object->length);
       
   447 			if(ext->object->data)
       
   448 				memcpy(ext->object->data, ch_ext_obj_data, ext->object->length);
       
   449 			//else log error- cannot malloc
       
   450 		
       
   451 			ext->object->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;  // so that X509_free() frees all internally allocated data
       
   452 			
       
   453 			if(extlist.At(i)->Critical())
       
   454 				ext->critical = extlist.At(i)->Critical();
       
   455 			
       
   456 			const TPtrC8 data = extlist.At(i)->Data();
       
   457 			TASN1DecGeneric value(data);
       
   458 			value.InitL();
       
   459 			
       
   460 			const TDesC8& ext_value = value.GetContentDER();
       
   461 			char * ch_ext_value = (char *)ext_value.Ptr();
       
   462 			ASN1_STRING_free(ext->value);
       
   463 			ext->value = CreateASN1_STRING(value.LengthDERContent(), V_ASN1_OCTET_STRING, (unsigned char *)ch_ext_value, 0);
       
   464 			
       
   465 			sk_X509_EXTENSION_push(ret,ext);		
       
   466 	
       
   467 		}
       
   468 			
       
   469 		CleanupStack::PopAndDestroy();// seq
       
   470 	}
       
   471 	
       
   472 	return ret;
       
   473 }
       
   474