secureswitools/swisistools/source/signsislib/certificateinfo.cpp
changeset 0 ba25891c3a9e
child 73 79647526f98c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/secureswitools/swisistools/source/signsislib/certificateinfo.cpp	Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,518 @@
+/*
+* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+
+/**
+ @file 
+ @internalComponent
+ @released
+*/
+
+#include <iostream>
+
+#include <openssl/rsa.h>
+#include <openssl/dsa.h>
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+#include <openssl/x509v3.h>
+#include <openssl/sha.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+#include <openssl/bio.h>
+
+
+#include "certificateinfo.h"
+
+
+// Constants
+const char* const KUTCTimeFormat = "YYMMDDHHMMSSZ";
+const char* const KGeneralizedTimeFormat = "YYYYMMDDHHMMSSZ";
+const int KUTCLength = 13;
+const int KGeneralizedTimeLength = 15;
+
+CCertificateInfo::CCertificateInfo (X509* aCertificate):
+	iCertificate(aCertificate)
+	{
+	ConstructL();
+	}
+
+CCertificateInfo::~CCertificateInfo()
+	{
+	X509_free(iCertificate);
+	}
+
+void CCertificateInfo::ConstructL()
+	{
+	ASN1_TIME* from = X509_get_notBefore (iCertificate);
+	SetDateTime(iValidFrom, from);
+	ASN1_TIME* to = X509_get_notAfter (iCertificate);
+	SetDateTime(iValidTo, to);
+	
+	EVP_PKEY *pKey = X509_get_pubkey(iCertificate);
+	assert(pKey);
+
+	iPublicKeyType = EUnknownKey;
+	if(EVP_PKEY_type(pKey->type) == EVP_PKEY_DSA)
+		{
+		iPublicKeyType = EPubKeyDSA;
+		}
+	else if(EVP_PKEY_type(pKey->type) == EVP_PKEY_RSA)
+		{
+		iPublicKeyType = EPubKeyRSA;
+		}
+
+	if(pKey != NULL)
+		EVP_PKEY_free(pKey);
+
+	ExtractExtensions();
+	}
+
+
+void ParseConfValue(std::string& aString, std::vector<TConfValue>& aValueList)
+	{
+	std::string str = aString;
+	while(str != "")
+		{
+		str = str.substr(str.find_first_not_of(' '));
+		TConfValue conf;
+		int pos = str.find(':');
+		if(pos != std::string::npos)
+			{
+			conf.iName = str.substr(0, pos);
+			str = str.substr(pos+1);
+			}
+		str = str.substr(str.find_first_not_of(' '));
+		pos = str.find('\n');
+		conf.iValue = str.substr(0, pos);
+		if(std::string::npos == pos)
+			{
+			break;
+			}
+		str = str.substr(pos+1);
+		aValueList.push_back(conf);
+		}
+	}
+
+void CCertificateInfo::ExtractConfValues(STACK_OF(CONF_VALUE) *aConfList, TExtension& aExtInfo)
+	{
+	assert(aConfList);
+	int confCount = sk_CONF_VALUE_num(aConfList);
+	for(int j = 0; j < confCount; ++j)
+		{
+		CONF_VALUE *nval = sk_CONF_VALUE_value(aConfList, j);
+		if(NULL == nval)
+			{
+			continue;
+			}
+		TConfValue confValue;
+		if(nval->name)
+			{
+			confValue.iName = nval->name;
+			}
+		
+		if(nval->value)
+			{
+			confValue.iValue = nval->value;
+			}
+		
+		aExtInfo.iValueList.push_back(confValue);
+		}			
+	}
+
+void CCertificateInfo::ExtractExtensions()
+	{
+	STACK_OF(X509_EXTENSION)* extensions = iCertificate->cert_info->extensions;
+	int extCount = sk_X509_EXTENSION_num(extensions);
+	
+	for(int i = 0; i < extCount; ++i)
+		{
+		TExtension extInfo;
+		X509_EXTENSION* ext = sk_X509_EXTENSION_value(extensions, i);
+		ASN1_OBJECT* obj = X509_EXTENSION_get_object(ext);
+		char extType[100];
+		i2t_ASN1_OBJECT(extType, sizeof(extType), obj);
+		extInfo.iExtensionName = extType;
+		extInfo.iIsCritical = X509_EXTENSION_get_critical(ext) ? true: false;
+		X509V3_EXT_METHOD *method = X509V3_EXT_get(ext);
+		if(NULL == method)
+			{
+			extInfo.iValue = Get_ASN1_STRING_Data(ext->value);
+			continue;
+			}
+		
+		void *ext_str = X509V3_EXT_d2i(ext);
+		if(NULL == ext_str)
+			{
+			continue;
+			}
+		
+		if(method->i2s)
+			{
+			extInfo.iValue = method->i2s(method, ext_str);
+			}
+		else if(method->i2v)
+			{
+			STACK_OF(CONF_VALUE) *confList = method->i2v(method, ext_str, NULL);
+			extInfo.iIsMultiLine = (method->ext_flags & X509V3_EXT_MULTILINE)? true: false;
+			ExtractConfValues(confList, extInfo);
+			}
+		else if(method->i2r)
+			{
+			BIO *mem = BIO_new(BIO_s_mem());
+			method->i2r(method, ext_str, mem, 12);
+			BUF_MEM *bptr;
+			BIO_get_mem_ptr(mem, &bptr);
+			std::string str(bptr->data, bptr->length);
+			ParseConfValue(str, extInfo.iValueList);
+			BIO_free(mem);
+			}
+		else
+			{
+			assert(0);
+			}
+		
+		iExtensions.push_back(extInfo);
+		}
+	
+	}
+
+void CCertificateInfo::SetDateTime(CSISDateTime& dateTime, ASN1_TIME* aASNTime)
+	{
+	TUint16 year = 0;
+	if(KUTCLength == strlen((char*)aASNTime->data))
+		{
+		sscanf((char*)aASNTime->data, "%2d", &year);
+		if(year > 50)
+			{
+			year += 1900;
+			}
+		else
+			{
+			year += 2000;
+			}
+		}
+	if(KGeneralizedTimeLength == strlen((char*)aASNTime->data))
+		{
+		sscanf((char*)aASNTime->data, "%4d", &year);
+		}
+
+	int value = 0;
+	sscanf((char*)&(aASNTime->data[2]), "%2d", &value);
+	TUint8 month = value;
+	sscanf((char*)&(aASNTime->data[4]), "%2d", &value);
+	TUint8 day = value;
+	dateTime.SetDate(year, month-1, day);
+	sscanf((char*)&(aASNTime->data[6]), "%2d", &value);
+	TUint8 hours = value;
+	sscanf((char*)&(aASNTime->data[8]), "%2d", &value);
+	TUint8 minutes = value;
+	sscanf((char*)&(aASNTime->data[10]), "%2d", &value);
+	TUint8 seconds = value;
+	dateTime.SetTime(hours, minutes, seconds);	
+	}
+
+std::wstring CCertificateInfo::GetDistinguishedName (X509_NAME *x509Name, bool aGetFullName) const
+	{
+	std::wstring distinsuiName;
+	bool firstPrinted = false;
+	wchar_t* nameEntry = NULL;
+
+	if(GetNameEntry(x509Name, LN_commonName, &nameEntry))
+		{
+		if(aGetFullName)
+			{
+			distinsuiName.append(L"CN="); 
+			firstPrinted = true;
+			}
+		distinsuiName.append(nameEntry);
+		delete[] nameEntry;
+		}
+	
+	if(aGetFullName)
+		{
+		if(GetNameEntry(x509Name, LN_organizationalUnitName, &nameEntry))
+			{
+			if(firstPrinted) 
+				{
+				distinsuiName.append(L", ");
+				}
+			distinsuiName.append(L"OU=");
+			distinsuiName.append(nameEntry);
+			delete[] nameEntry;
+			firstPrinted = true;
+			}
+		if(GetNameEntry(x509Name, LN_organizationName, &nameEntry))
+			{	
+			if(firstPrinted) distinsuiName.append(L", ");
+			distinsuiName.append(L"O=");
+			distinsuiName.append(nameEntry);
+			delete[] nameEntry;
+			firstPrinted = true;
+			}
+		if(GetNameEntry(x509Name, LN_countryName, &nameEntry))
+			{	
+			if(firstPrinted) distinsuiName.append(L", ");
+			distinsuiName.append(L"C=");
+			distinsuiName.append(nameEntry);
+			delete[] nameEntry;
+			firstPrinted = true;
+			}
+		if(GetNameEntry(x509Name, LN_pkcs9_emailAddress, &nameEntry))
+			{
+			if(firstPrinted) distinsuiName.append(L", ");
+			distinsuiName.append(L"EM=");
+			distinsuiName.append(nameEntry);
+			delete[] nameEntry;
+			}
+		}
+	return distinsuiName;
+	}
+
+std::wstring CCertificateInfo::IssuerName(bool aGetFullName) const
+	{
+	X509_NAME *x509Name = X509_get_issuer_name (iCertificate);
+	
+	std::wstring issuerName = GetDistinguishedName(x509Name, aGetFullName);
+	
+	return issuerName;
+	}
+
+std::wstring CCertificateInfo::SubjectName(bool aGetFullName) const
+	{
+	X509_NAME *x509Name = X509_get_subject_name (iCertificate);
+	
+	std::wstring subjectName = GetDistinguishedName(x509Name, aGetFullName);
+	
+	return subjectName;
+	}
+
+const CSISDateTime& CCertificateInfo::ValidFrom() const
+	{
+	return iValidFrom;
+	}
+
+const CSISDateTime& CCertificateInfo::ValidTo() const
+	{
+	return iValidTo;
+	}
+
+int CCertificateInfo::Version() const
+	{
+	return X509_get_version(iCertificate);
+	}
+
+std::string CCertificateInfo::SerialNumber() const
+	{
+	std::string serialNo;
+	
+	//Get serial number
+	ASN1_INTEGER* asnNum = X509_get_serialNumber(iCertificate);
+
+	if(asnNum->length <= 4)
+		{
+		char sno[30];
+		int sNum = ASN1_INTEGER_get(asnNum);
+		
+		if(sNum < 0)
+			{
+			sNum = -1;
+			serialNo.append("-");
+			}
+	
+		sprintf(sno, " %d (0x%x)", sNum, sNum);
+		serialNo.append(sno);
+		}
+	else
+		{
+		if(asnNum->type == V_ASN1_NEG_INTEGER)
+			{
+			serialNo = " (Negative)";
+			}
+
+		for(int i = 0; i < asnNum->length; i++)
+			{
+			char sno[10];
+			sprintf(sno, "%02x", (int)asnNum->data[i]);
+			serialNo.append(sno);
+			if(i < asnNum->length - 1)
+				{
+				serialNo.append(":");
+				}
+			}
+		}
+	
+	return serialNo;
+	}
+
+std::string CCertificateInfo::SignatureAlgo() const
+	{
+	std::string algo = OBJ_nid2ln(OBJ_obj2nid(iCertificate->sig_alg->algorithm));
+	return algo;
+	}
+
+std::string CCertificateInfo::PublicKeyAlgo() const
+	{
+	std::string algo = OBJ_nid2ln(OBJ_obj2nid(iCertificate->cert_info->key->algor->algorithm));
+	return algo;
+	}
+
+int CCertificateInfo::GetNameEntry(X509_NAME* aName, char *aKey, wchar_t** aNameEntry) const
+	{
+	if(!aName || !aKey)
+		return 0;
+
+
+	int nid = 0;
+	
+	if((nid = OBJ_txt2nid(aKey)) == NID_undef)
+		return 0;
+
+	int index = X509_NAME_get_index_by_NID(aName, nid, -1);
+
+	if(index == -1)
+		return 0;
+
+
+	X509_NAME_ENTRY* nameEnt = X509_NAME_get_entry(aName, index);
+	ASN1_STRING* ASN1Str = X509_NAME_ENTRY_get_data(nameEnt);
+	
+	BYTE* UTF8Str = NULL;
+	
+	if(ASN1_STRING_to_UTF8(&UTF8Str, ASN1Str) < 0)
+	{
+		if (M_ASN1_STRING_type(ASN1Str) == V_ASN1_UTF8STRING)
+		{
+			UTF8Str = ASN1_STRING_data(ASN1Str);
+		}
+		else 
+		{
+			return 0;
+		}
+	}
+	
+	int len = ConvertMultiByteToWideChar((LPSTR)UTF8Str, strlen((LPSTR)UTF8Str)+1, NULL, 0);
+	*aNameEntry = new wchar_t[len*sizeof(wchar_t)];
+	ConvertMultiByteToWideChar((LPSTR)UTF8Str, strlen((LPSTR)UTF8Str)+1, *aNameEntry, len);
+	return 1;
+	}
+
+std::string CCertificateInfo::Get_ASN1_STRING_Data(ASN1_STRING *aASN1String)
+	{
+	if(NULL == aASN1String)
+		{
+		return NULL;
+		}
+
+	int length = aASN1String->length;
+	std::string ASN_String;
+	unsigned char* ptr = aASN1String->data;
+	
+	for (int i = 0; i < aASN1String->length; ++i)
+		{
+		if ((ptr[i] > '~') || ((ptr[i] < ' ') && (ptr[i] != '\n') && (ptr[i] != '\r')))
+			ASN_String.append(".");
+		else
+			ASN_String.append(1, ptr[i]);
+		}
+	return ASN_String;
+	}
+
+const std::vector<TExtension>& CCertificateInfo::Extensions() const
+	{
+	return iExtensions;
+	}
+
+void CCertificateInfo::PrintPublicKey(std::ostream& aStream, int aIndent) const
+	{
+	EVP_PKEY *pKey = X509_get_pubkey(iCertificate);
+	assert(pKey);
+	
+	BIO *mem = BIO_new(BIO_s_mem());
+
+	switch(iPublicKeyType)
+		{
+		case EPubKeyDSA:
+			{
+			aStream << "" << "DSA Public Key:" << std::endl;
+			struct dsa_st *pDSA = EVP_PKEY_get1_DSA(pKey);
+			DSA_print(mem, pDSA, 28);
+			break;
+			}
+	
+		case EPubKeyRSA:
+			{
+			aStream.width(aIndent);
+			aStream << "" ;
+			aStream << "RSA Public Key: (" << std::dec << BN_num_bits(pKey->pkey.rsa->n) << " bit)"<< std::endl;
+			struct rsa_st *pRSA = EVP_PKEY_get1_RSA(pKey);
+			RSA_print(mem, pRSA, 16);
+			break;
+			}
+		}
+
+	BUF_MEM *bptr = NULL;
+	BIO_get_mem_ptr(mem, &bptr);
+	std::string str(bptr->data, bptr->length);
+	aStream << str;
+
+	BIO_free(mem);
+
+	if(pKey != NULL)
+		EVP_PKEY_free(pKey);
+	}
+
+void CCertificateInfo::PrintSignature(std::ostream& aStream, int aIndent) const
+	{
+	BIO *mem = BIO_new(BIO_s_mem());
+	X509_signature_print(mem, iCertificate->sig_alg, iCertificate->signature);
+	BUF_MEM *bptr = NULL;
+	BIO_get_mem_ptr(mem, &bptr);
+	std::string str(bptr->data, bptr->length);
+	aStream << str << std::endl;
+	BIO_free(mem);
+	}
+
+void CCertificateInfo::ExtractCertificate(std::string& aCertFileName) const
+	{
+	BIO* bio = BIO_new_file(aCertFileName.c_str(), "a");
+	if(bio)
+		{
+		if (!PEM_write_bio_X509(bio, iCertificate ))
+			{
+			throw "Error While Creating pem file";
+			}
+		BIO_free(bio);
+		}
+	else
+		{
+		throw "Unable to create Certificate File";
+		}
+	}
+
+bool CCertificateInfo::IsNIDPresent(int aNID) const
+	{
+	int val = X509_get_ext_by_NID(iCertificate, aNID, -1);
+	return (val == -1)? false: true;
+	}
+
+
+// END of FILE