ssl/libcrypto/src/crypto/certretriever/createx509.cpp
changeset 0 e4d67989cc36
child 52 bf6a71c50e42
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ssl/libcrypto/src/crypto/certretriever/createx509.cpp	Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,474 @@
+/*
+Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this 
+  list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice, 
+  this list of conditions and the following disclaimer in the documentation 
+  and/or other materials provided with the distribution.
+* Neither the name of Nokia Corporation nor the names of its contributors 
+  may be used to endorse or promote products derived from this software 
+  without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Description:
+*/
+
+
+#include "createx509.h"
+
+
+X509* CX509_Initializer::CreateX509(CX509Certificate* X509Cert)
+{
+	X509* ret = X509_new();
+	TBool serail = ETrue;
+	
+	if(ret != NULL)
+	{
+	
+//validity
+		X509_VAL_free(ret->cert_info->validity);
+		ret->cert_info->validity = CreateX509_VAL(X509Cert); 
+
+//issuer
+		const CX500DistinguishedName& IssName = X509Cert->IssuerName();	
+		X509_NAME_free(ret->cert_info->issuer);
+		ret->cert_info->issuer = CreateX509_NAME(IssName);
+
+//subject
+		const CX500DistinguishedName& SubName = X509Cert->SubjectName();	
+		X509_NAME_free(ret->cert_info->subject);
+		ret->cert_info->subject = CreateX509_NAME(SubName);
+	//	const HBufC * name = SubName.DisplayNameL();
+
+//signature
+		const TPtrC8* sig_alg_ptr = X509Cert->DataElementEncoding(CX509Certificate::EAlgorithmId);
+		X509_ALGOR_free(ret->cert_info->signature);
+		ret->cert_info->signature = CreateX509_ALGOR(sig_alg_ptr);
+
+//serialnumber
+		const TPtrC8 sernum = X509Cert->SerialNumber();
+		ASN1_INTEGER_free(ret->cert_info->serialNumber);
+		ret->cert_info->serialNumber = CreateASN1_STRING(sernum.Length(),V_ASN1_INTEGER,(unsigned char *)sernum.Ptr(),0);		
+		if((sernum.Length()== 1) && sernum[0]==0)
+			serail = EFalse;
+			
+//version
+
+		TInt ver = X509Cert->Version();
+		unsigned char verVal = (unsigned char)(ver-1);		
+		ASN1_INTEGER_free(ret->cert_info->version);
+		if( (verVal) || (!serail))// for X509 V1 certificates, version is null if any serial number present.
+			ret->cert_info->version = CreateASN1_STRING(1,V_ASN1_INTEGER,&verVal,0);
+
+
+//issuerUID
+		const TPtrC8* issUID_enc = X509Cert->DataElementEncoding(CX509Certificate::EIssuerUID);
+		if(issUID_enc)
+			ret->cert_info->issuerUID = CreateASN1_STRING(issUID_enc->Length(),V_ASN1_BIT_STRING,(unsigned char *)issUID_enc->Ptr(),0);
+		
+
+//subjectUID
+		const TPtrC8* subUID_enc = X509Cert->DataElementEncoding(CX509Certificate::ESubjectUID);
+		if(subUID_enc)
+			ret->cert_info->subjectUID = CreateASN1_STRING(subUID_enc->Length(),V_ASN1_BIT_STRING,(unsigned char *)subUID_enc->Ptr(),0);
+
+//key
+		X509_PUBKEY_free(ret->cert_info->key);
+		ret->cert_info->key = CreateX509_PUBKEY(X509Cert);
+
+	
+//extension
+
+
+		ret->cert_info->extensions = CreateSTACKOF_X509_EXTENSION(X509Cert);
+
+		
+//name
+		ret->name = X509_NAME_oneline(ret->cert_info->subject, NULL, 0);
+
+//sig_alg
+		X509_ALGOR_free(ret->sig_alg);
+		ret->sig_alg = CreateX509_ALGOR(sig_alg_ptr);
+		
+//signature
+		const TPtrC8 sig = X509Cert->Signature();
+		ASN1_STRING_free(ret->signature);
+		ret->signature = CreateASN1_STRING(sig.Length(), V_ASN1_BIT_STRING, (unsigned char *)sig.Ptr(), ASN1_STRING_FLAG_BITS_LEFT);
+	}
+		
+	return ret;
+}
+
+
+X509_ALGOR* CX509_Initializer::CreateX509_ALGOR(const TPtrC8* ptr)
+{
+	X509_ALGOR* ret = X509_ALGOR_new();
+	
+	TASN1DecGeneric dec((TDesC8 &)*ptr);	
+	dec.InitL();
+	
+	TASN1DecSequence encSeq;
+	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(dec);
+	
+	TASN1DecGeneric& AlgorEncSeq = *(seq->At(0));
+
+	if (dec.LengthDERContent() > AlgorEncSeq.LengthDER()) // can also check for (seq->Count() > 1) alternatively
+	{
+		// parameter part is present in the encoding.
+		TASN1DecGeneric& ParameterEncSeq = *(seq->At(1));
+		
+		// if param = 5, ie. ASN1 type NULL, then create a NULL ASN1 STRING
+		ret->parameter = ASN1_TYPE_new();
+		ret->parameter->type = (TInt)ParameterEncSeq.Encoding()[0];
+		
+		if(ret->parameter->type != V_ASN1_NULL)
+		{
+			// we have some parameter 
+			// add code to fill this stuff
+		}
+	}
+	else
+	{
+		//encoding does not contain parameter at all
+		//ret->parameter is anyway NULL when X509_ALGOR is created
+		//Not sure if we need to create a NULL ASN1 string or just leave parameter = NULL
+	}
+	
+	
+	const TDesC8& algor_data = AlgorEncSeq.GetContentDER();
+	char * ch_algor_data = (char *)algor_data.Ptr();
+	
+	ret->algorithm = ASN1_OBJECT_new();
+	ret->algorithm->length = AlgorEncSeq.LengthDERContent();	
+	ret->algorithm->data = (unsigned char *)OPENSSL_malloc(ret->algorithm->length);
+	if(ret->algorithm->data)
+		memcpy(ret->algorithm->data, ch_algor_data, ret->algorithm->length);
+	//else log error- cannot malloc
+	
+	ret->algorithm->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;  // so that X509_ALGOR_free() frees all internally allocated data
+	
+	CleanupStack::PopAndDestroy();	//seq
+	
+	return ret;
+}
+
+
+
+X509_NAME* CX509_Initializer::CreateX509_NAME(const CX500DistinguishedName& DistName)
+{
+	X509_NAME* ret = X509_NAME_new();
+	
+	CASN1EncSequence * Asn1Seq = DistName.EncodeASN1LC();			
+
+	HBufC8* octetData = HBufC8::NewMaxLC(5000);
+	TPtr8 oct(octetData->Des());
+	oct.FillZ();
+	oct.SetLength(KMaxNameLength);
+	TUint writePos = 0;
+	Asn1Seq->WriteDERL(oct, writePos);			
+
+  	TInt len = Fill_X509_NAME_ENTRY(ret, octetData->Des());
+	
+	char *p = (char *)oct.PtrZ();
+
+    ret->bytes->data = (char *)OPENSSL_malloc(len);        // no need to free this. BUF_MEM_free will free if not NULL
+    if(ret->bytes->data)
+     memcpy(ret->bytes->data, p, len);
+    //else log error- cannot malloc
+    
+	ret->bytes->length = len;
+	ret->bytes->max = len;
+
+	ret->hash = 0; // for now filling zero. Not sure.
+	
+	CleanupStack::PopAndDestroy(2); // Asn1Seq, octetData
+	
+	return ret;
+} 
+
+
+// return the length of the encoded sequence
+TInt CX509_Initializer::Fill_X509_NAME_ENTRY(X509_NAME * name, const TDesC8& aBinaryData)
+{
+	TInt aPos = 0;
+	TASN1DecGeneric dec(aBinaryData.Right(aBinaryData.Length() - aPos));
+	dec.InitL();
+	
+	TInt end = aPos + dec.LengthDER();
+	aPos += dec.LengthDERHeader();
+
+	if (dec.Tag() != EASN1Sequence)
+		{
+		User::Leave(KErrArgument);
+		}
+	while (aPos < end)
+		{
+		TASN1DecGeneric rdn(aBinaryData.Right(aBinaryData.Length() - aPos));
+		rdn.InitL();
+		if (rdn.Tag() != EASN1Set)
+			{
+			User::Leave(KErrArgument);
+			}
+		TInt rdnEnd = rdn.LengthDER();
+		TInt rdnPos = rdn.LengthDERHeader();//add on header
+		while (rdnPos < rdnEnd)
+			{
+			const TDesC8& TypeValEnc = rdn.Encoding();
+			
+		    				TASN1DecGeneric dec(TypeValEnc.Right(TypeValEnc.Length() - rdnPos));
+							dec.InitL();
+							TInt tvend = rdnPos + dec.LengthDER();
+							rdnPos += dec.LengthDERHeader();
+						
+							//first element must be the id
+							TASN1DecObjectIdentifier encOID;
+							//iType = encOID.DecodeDERL(TypeValEnc, rdnPos);
+							TASN1DecGeneric first(TypeValEnc.Right(TypeValEnc.Length() - rdnPos));
+							first.InitL();
+							rdnPos += first.LengthDER();
+								if (first.Tag() != EASN1ObjectIdentifier)
+								{
+								User::Leave(KErrArgument);
+								}
+						
+							const TDesC8& type = first.GetContentDER();
+							char * ch_type = (char *)type.Ptr();
+				
+							//second is the data
+							TASN1DecGeneric second(TypeValEnc.Right(TypeValEnc.Length() - rdnPos));
+							second.InitL();
+							rdnPos += second.LengthDER();
+							
+							const TDesC8& value = second.GetContentDER();
+							char * ch_value = (char *)value.Ptr();
+							
+							X509_NAME_ENTRY* new_entry = CreateX509_NAME_ENTRY(ch_type,first.LengthDERContent(), ch_value, second.LengthDERContent(), second.Tag());
+							
+							X509_NAME_add_entry(name, new_entry, -1, 0);
+							
+							//we can free this, since add_entry makes a copy and adds
+							X509_NAME_ENTRY_free(new_entry);
+							//
+							
+							if (rdnPos != tvend)
+								{
+								User::Leave(KErrArgument);
+								}
+			
+			}
+		aPos += rdnEnd;
+		}
+	if (aPos != end)
+		{
+		User::Leave(KErrArgument);
+		}
+	return end;
+}
+
+
+X509_NAME_ENTRY * CX509_Initializer::CreateX509_NAME_ENTRY(char* type, int typeLen, char * value, int valueLen, int stringType)
+{
+	X509_NAME_ENTRY * newEntry = X509_NAME_ENTRY_new();
+	
+	newEntry->object->length = typeLen;
+	newEntry->object->data = (unsigned char *)OPENSSL_malloc(typeLen);
+	if(newEntry->object->data)
+		memcpy(newEntry->object->data, type, typeLen);
+	//else log error- cannot malloc
+	
+	ASN1_STRING_free(newEntry->value);
+	newEntry->value = CreateASN1_STRING(valueLen, stringType, (unsigned char* )value, 0);
+	
+	newEntry->object->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;  // so that X509_NAME_ENTRY_free() frees all internally allocated data
+	
+	return newEntry;	
+	
+}
+
+
+X509_VAL * CX509_Initializer::CreateX509_VAL(CX509Certificate* X509Cert)
+{
+	X509_VAL * ret = X509_VAL_new();
+	
+	const CValidityPeriod& val = X509Cert->ValidityPeriod();
+				
+		TBuf8<KCertMaxBuffer> numBuffer8;
+		char* numPtr = (char*)numBuffer8.PtrZ();
+	
+	//start date (notBefore)
+		TDateTime dt = val.Start().DateTime();
+			
+		numBuffer8.AppendNum(dt.Year());
+		if(numBuffer8.Length() > 2)
+			numBuffer8.Delete(0, numBuffer8.Length() - 2);
+		
+		_LIT8(KCertTimeStampFormat, "%02d%02d%02d%02d%02dZ");
+		numBuffer8.AppendFormat(KCertTimeStampFormat,dt.Month()+1,dt.Day()+1,dt.Hour(),dt.Minute(),dt.Second());  //Month and Day - offset from zero, so add 1
+		numPtr[13]='\0';
+		
+		ASN1_STRING_free(ret->notBefore);
+		ret->notBefore = CreateASN1_STRING(13,V_ASN1_UTCTIME,(unsigned char *)numPtr,0);
+
+	//finish date (notAfter)
+		dt = val.Finish().DateTime();
+		
+		numBuffer8.Zero();
+		numBuffer8.AppendNum(dt.Year());
+		if(numBuffer8.Length() > 2)
+			numBuffer8.Delete(0, numBuffer8.Length() - 2);
+		
+		numBuffer8.AppendFormat(KCertTimeStampFormat,dt.Month()+1,dt.Day()+1,dt.Hour(),dt.Minute(),dt.Second());  //Month and Day - offset from zero, so add 1
+		numPtr[13]='\0';
+		
+		ASN1_STRING_free(ret->notAfter);
+		ret->notAfter = CreateASN1_STRING(13,V_ASN1_UTCTIME,(unsigned char *)numPtr,0);
+		
+	return ret;
+	
+}
+
+
+
+ASN1_STRING* CX509_Initializer::CreateASN1_STRING(int len, int type, unsigned char* data, long flags)
+{
+ ASN1_STRING* ret = ASN1_STRING_new();
+ ret->length = len;
+ ret->type = type;
+ if(data!=NULL)
+ {
+ 	ret->data = (unsigned char *)OPENSSL_malloc(len);
+ 	if(ret->data)
+ 	  memcpy(ret->data,data,len);
+ 	//else log error- cannot malloc
+ }
+ else
+ 	ret->data = NULL;
+ 	
+ ret->flags |= flags;
+ return ret;
+}
+
+
+
+X509_PUBKEY* CX509_Initializer::CreateX509_PUBKEY(CX509Certificate* X509Cert)
+{
+	X509_PUBKEY* ret = X509_PUBKEY_new();
+
+//algor
+	const TPtrC8* ptr = X509Cert->DataElementEncoding(CX509Certificate::ESubjectPublicKeyInfo);
+	
+	TInt aPos = 0;
+	TASN1DecGeneric dec(ptr->Right(ptr->Length() - aPos));
+	dec.InitL();
+	
+	TInt end = aPos + dec.LengthDER();
+	aPos += dec.LengthDERHeader();
+
+	if (dec.Tag() != EASN1Sequence)
+		User::Leave(KErrArgument);
+
+	if (aPos < end)
+		{
+			TASN1DecGeneric rdn(ptr->Right(ptr->Length() - aPos));
+			rdn.InitL();
+			TPtrC8 newPtr = rdn.Encoding();
+			
+			X509_ALGOR_free(ret->algor);	// free the one allocated by X509_PUBKEY_new
+			ret->algor = CreateX509_ALGOR(&newPtr);
+		}
+	
+//public_key
+	const CSubjectPublicKeyInfo& pubkey = X509Cert->PublicKey();
+	const TPtrC8 keyDat =	pubkey.KeyData();
+	
+	ASN1_BIT_STRING_free(ret->public_key);
+	ret->public_key = CreateASN1_STRING(keyDat.Size(),V_ASN1_BIT_STRING,(unsigned char*)keyDat.Ptr(),0);
+	
+//pkey
+	ret->pkey = NULL;		// we need not create this. Will be created later. Used to cache the computed data
+	
+	return ret;
+}
+
+
+
+
+STACK_OF(X509_EXTENSION)* CX509_Initializer::CreateSTACKOF_X509_EXTENSION(CX509Certificate* X509Cert)
+{
+	//STACK_OF(X509_EXTENSION) * ret = sk_X509_EXTENSION_new_null();
+	STACK_OF(X509_EXTENSION) * ret = NULL;
+	
+	const TPtrC8* ptr = X509Cert->DataElementEncoding(CX509Certificate::EExtensionList);
+	
+	const CArrayPtrFlat<CX509CertExtension>& extlist = X509Cert->Extensions();
+
+	TASN1DecSequence encSeq;
+	TInt pos = 0;
+
+	if(ptr != NULL)	//There is an extension list
+	{
+		TASN1DecGeneric dec((TDesC8 &)*ptr);
+		ret = sk_X509_EXTENSION_new_null();
+		dec.InitL();
+		
+		CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC( dec.GetContentDER(), pos);
+	
+		TInt count = seq->Count(); // no of extensions in the ext list
+		for (TInt i = 0; i < count; i++)
+		{
+		
+			X509_EXTENSION* ext = X509_EXTENSION_new();
+		
+			ext->object = ASN1_OBJECT_new();
+						
+			TASN1DecGeneric* gen = seq->At(i);
+			TASN1DecGeneric oid(seq->At(i)->GetContentDER());
+			oid.InitL();
+			
+			const TDesC8& ext_obj_data = oid.GetContentDER();
+			char * ch_ext_obj_data = (char *)ext_obj_data.Ptr();
+			
+			ext->object->length = oid.LengthDERContent();
+			ext->object->data = (unsigned char *)OPENSSL_malloc(ext->object->length);
+			if(ext->object->data)
+				memcpy(ext->object->data, ch_ext_obj_data, ext->object->length);
+			//else log error- cannot malloc
+		
+			ext->object->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;  // so that X509_free() frees all internally allocated data
+			
+			if(extlist.At(i)->Critical())
+				ext->critical = extlist.At(i)->Critical();
+			
+			const TPtrC8 data = extlist.At(i)->Data();
+			TASN1DecGeneric value(data);
+			value.InitL();
+			
+			const TDesC8& ext_value = value.GetContentDER();
+			char * ch_ext_value = (char *)ext_value.Ptr();
+			ASN1_STRING_free(ext->value);
+			ext->value = CreateASN1_STRING(value.LengthDERContent(), V_ASN1_OCTET_STRING, (unsigned char *)ch_ext_value, 0);
+			
+			sk_X509_EXTENSION_push(ret,ext);		
+	
+		}
+			
+		CleanupStack::PopAndDestroy();// seq
+	}
+	
+	return ret;
+}
+