secureswitools/swisistools/source/signsislib/certificateinfo.cpp
changeset 0 ba25891c3a9e
child 73 79647526f98c
equal deleted inserted replaced
-1:000000000000 0:ba25891c3a9e
       
     1 /*
       
     2 * Copyright (c) 2008-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 /**
       
    20  @file 
       
    21  @internalComponent
       
    22  @released
       
    23 */
       
    24 
       
    25 #include <iostream>
       
    26 
       
    27 #include <openssl/rsa.h>
       
    28 #include <openssl/dsa.h>
       
    29 #include <openssl/evp.h>
       
    30 #include <openssl/objects.h>
       
    31 #include <openssl/x509v3.h>
       
    32 #include <openssl/sha.h>
       
    33 #include <openssl/pem.h>
       
    34 #include <openssl/x509.h>
       
    35 #include <openssl/err.h>
       
    36 #include <openssl/pem.h>
       
    37 #include <openssl/evp.h>
       
    38 #include <openssl/err.h>
       
    39 #include <openssl/ssl.h>
       
    40 #include <openssl/bio.h>
       
    41 
       
    42 
       
    43 #include "certificateinfo.h"
       
    44 
       
    45 
       
    46 // Constants
       
    47 const char* const KUTCTimeFormat = "YYMMDDHHMMSSZ";
       
    48 const char* const KGeneralizedTimeFormat = "YYYYMMDDHHMMSSZ";
       
    49 const int KUTCLength = 13;
       
    50 const int KGeneralizedTimeLength = 15;
       
    51 
       
    52 CCertificateInfo::CCertificateInfo (X509* aCertificate):
       
    53 	iCertificate(aCertificate)
       
    54 	{
       
    55 	ConstructL();
       
    56 	}
       
    57 
       
    58 CCertificateInfo::~CCertificateInfo()
       
    59 	{
       
    60 	X509_free(iCertificate);
       
    61 	}
       
    62 
       
    63 void CCertificateInfo::ConstructL()
       
    64 	{
       
    65 	ASN1_TIME* from = X509_get_notBefore (iCertificate);
       
    66 	SetDateTime(iValidFrom, from);
       
    67 	ASN1_TIME* to = X509_get_notAfter (iCertificate);
       
    68 	SetDateTime(iValidTo, to);
       
    69 	
       
    70 	EVP_PKEY *pKey = X509_get_pubkey(iCertificate);
       
    71 	assert(pKey);
       
    72 
       
    73 	iPublicKeyType = EUnknownKey;
       
    74 	if(EVP_PKEY_type(pKey->type) == EVP_PKEY_DSA)
       
    75 		{
       
    76 		iPublicKeyType = EPubKeyDSA;
       
    77 		}
       
    78 	else if(EVP_PKEY_type(pKey->type) == EVP_PKEY_RSA)
       
    79 		{
       
    80 		iPublicKeyType = EPubKeyRSA;
       
    81 		}
       
    82 
       
    83 	if(pKey != NULL)
       
    84 		EVP_PKEY_free(pKey);
       
    85 
       
    86 	ExtractExtensions();
       
    87 	}
       
    88 
       
    89 
       
    90 void ParseConfValue(std::string& aString, std::vector<TConfValue>& aValueList)
       
    91 	{
       
    92 	std::string str = aString;
       
    93 	while(str != "")
       
    94 		{
       
    95 		str = str.substr(str.find_first_not_of(' '));
       
    96 		TConfValue conf;
       
    97 		int pos = str.find(':');
       
    98 		if(pos != std::string::npos)
       
    99 			{
       
   100 			conf.iName = str.substr(0, pos);
       
   101 			str = str.substr(pos+1);
       
   102 			}
       
   103 		str = str.substr(str.find_first_not_of(' '));
       
   104 		pos = str.find('\n');
       
   105 		conf.iValue = str.substr(0, pos);
       
   106 		if(std::string::npos == pos)
       
   107 			{
       
   108 			break;
       
   109 			}
       
   110 		str = str.substr(pos+1);
       
   111 		aValueList.push_back(conf);
       
   112 		}
       
   113 	}
       
   114 
       
   115 void CCertificateInfo::ExtractConfValues(STACK_OF(CONF_VALUE) *aConfList, TExtension& aExtInfo)
       
   116 	{
       
   117 	assert(aConfList);
       
   118 	int confCount = sk_CONF_VALUE_num(aConfList);
       
   119 	for(int j = 0; j < confCount; ++j)
       
   120 		{
       
   121 		CONF_VALUE *nval = sk_CONF_VALUE_value(aConfList, j);
       
   122 		if(NULL == nval)
       
   123 			{
       
   124 			continue;
       
   125 			}
       
   126 		TConfValue confValue;
       
   127 		if(nval->name)
       
   128 			{
       
   129 			confValue.iName = nval->name;
       
   130 			}
       
   131 		
       
   132 		if(nval->value)
       
   133 			{
       
   134 			confValue.iValue = nval->value;
       
   135 			}
       
   136 		
       
   137 		aExtInfo.iValueList.push_back(confValue);
       
   138 		}			
       
   139 	}
       
   140 
       
   141 void CCertificateInfo::ExtractExtensions()
       
   142 	{
       
   143 	STACK_OF(X509_EXTENSION)* extensions = iCertificate->cert_info->extensions;
       
   144 	int extCount = sk_X509_EXTENSION_num(extensions);
       
   145 	
       
   146 	for(int i = 0; i < extCount; ++i)
       
   147 		{
       
   148 		TExtension extInfo;
       
   149 		X509_EXTENSION* ext = sk_X509_EXTENSION_value(extensions, i);
       
   150 		ASN1_OBJECT* obj = X509_EXTENSION_get_object(ext);
       
   151 		char extType[100];
       
   152 		i2t_ASN1_OBJECT(extType, sizeof(extType), obj);
       
   153 		extInfo.iExtensionName = extType;
       
   154 		extInfo.iIsCritical = X509_EXTENSION_get_critical(ext) ? true: false;
       
   155 		X509V3_EXT_METHOD *method = X509V3_EXT_get(ext);
       
   156 		if(NULL == method)
       
   157 			{
       
   158 			extInfo.iValue = Get_ASN1_STRING_Data(ext->value);
       
   159 			continue;
       
   160 			}
       
   161 		
       
   162 		void *ext_str = X509V3_EXT_d2i(ext);
       
   163 		if(NULL == ext_str)
       
   164 			{
       
   165 			continue;
       
   166 			}
       
   167 		
       
   168 		if(method->i2s)
       
   169 			{
       
   170 			extInfo.iValue = method->i2s(method, ext_str);
       
   171 			}
       
   172 		else if(method->i2v)
       
   173 			{
       
   174 			STACK_OF(CONF_VALUE) *confList = method->i2v(method, ext_str, NULL);
       
   175 			extInfo.iIsMultiLine = (method->ext_flags & X509V3_EXT_MULTILINE)? true: false;
       
   176 			ExtractConfValues(confList, extInfo);
       
   177 			}
       
   178 		else if(method->i2r)
       
   179 			{
       
   180 			BIO *mem = BIO_new(BIO_s_mem());
       
   181 			method->i2r(method, ext_str, mem, 12);
       
   182 			BUF_MEM *bptr;
       
   183 			BIO_get_mem_ptr(mem, &bptr);
       
   184 			std::string str(bptr->data, bptr->length);
       
   185 			ParseConfValue(str, extInfo.iValueList);
       
   186 			BIO_free(mem);
       
   187 			}
       
   188 		else
       
   189 			{
       
   190 			assert(0);
       
   191 			}
       
   192 		
       
   193 		iExtensions.push_back(extInfo);
       
   194 		}
       
   195 	
       
   196 	}
       
   197 
       
   198 void CCertificateInfo::SetDateTime(CSISDateTime& dateTime, ASN1_TIME* aASNTime)
       
   199 	{
       
   200 	TUint16 year = 0;
       
   201 	if(KUTCLength == strlen((char*)aASNTime->data))
       
   202 		{
       
   203 		sscanf((char*)aASNTime->data, "%2d", &year);
       
   204 		if(year > 50)
       
   205 			{
       
   206 			year += 1900;
       
   207 			}
       
   208 		else
       
   209 			{
       
   210 			year += 2000;
       
   211 			}
       
   212 		}
       
   213 	if(KGeneralizedTimeLength == strlen((char*)aASNTime->data))
       
   214 		{
       
   215 		sscanf((char*)aASNTime->data, "%4d", &year);
       
   216 		}
       
   217 
       
   218 	int value = 0;
       
   219 	sscanf((char*)&(aASNTime->data[2]), "%2d", &value);
       
   220 	TUint8 month = value;
       
   221 	sscanf((char*)&(aASNTime->data[4]), "%2d", &value);
       
   222 	TUint8 day = value;
       
   223 	dateTime.SetDate(year, month-1, day);
       
   224 	sscanf((char*)&(aASNTime->data[6]), "%2d", &value);
       
   225 	TUint8 hours = value;
       
   226 	sscanf((char*)&(aASNTime->data[8]), "%2d", &value);
       
   227 	TUint8 minutes = value;
       
   228 	sscanf((char*)&(aASNTime->data[10]), "%2d", &value);
       
   229 	TUint8 seconds = value;
       
   230 	dateTime.SetTime(hours, minutes, seconds);	
       
   231 	}
       
   232 
       
   233 std::wstring CCertificateInfo::GetDistinguishedName (X509_NAME *x509Name, bool aGetFullName) const
       
   234 	{
       
   235 	std::wstring distinsuiName;
       
   236 	bool firstPrinted = false;
       
   237 	wchar_t* nameEntry = NULL;
       
   238 
       
   239 	if(GetNameEntry(x509Name, LN_commonName, &nameEntry))
       
   240 		{
       
   241 		if(aGetFullName)
       
   242 			{
       
   243 			distinsuiName.append(L"CN="); 
       
   244 			firstPrinted = true;
       
   245 			}
       
   246 		distinsuiName.append(nameEntry);
       
   247 		delete[] nameEntry;
       
   248 		}
       
   249 	
       
   250 	if(aGetFullName)
       
   251 		{
       
   252 		if(GetNameEntry(x509Name, LN_organizationalUnitName, &nameEntry))
       
   253 			{
       
   254 			if(firstPrinted) 
       
   255 				{
       
   256 				distinsuiName.append(L", ");
       
   257 				}
       
   258 			distinsuiName.append(L"OU=");
       
   259 			distinsuiName.append(nameEntry);
       
   260 			delete[] nameEntry;
       
   261 			firstPrinted = true;
       
   262 			}
       
   263 		if(GetNameEntry(x509Name, LN_organizationName, &nameEntry))
       
   264 			{	
       
   265 			if(firstPrinted) distinsuiName.append(L", ");
       
   266 			distinsuiName.append(L"O=");
       
   267 			distinsuiName.append(nameEntry);
       
   268 			delete[] nameEntry;
       
   269 			firstPrinted = true;
       
   270 			}
       
   271 		if(GetNameEntry(x509Name, LN_countryName, &nameEntry))
       
   272 			{	
       
   273 			if(firstPrinted) distinsuiName.append(L", ");
       
   274 			distinsuiName.append(L"C=");
       
   275 			distinsuiName.append(nameEntry);
       
   276 			delete[] nameEntry;
       
   277 			firstPrinted = true;
       
   278 			}
       
   279 		if(GetNameEntry(x509Name, LN_pkcs9_emailAddress, &nameEntry))
       
   280 			{
       
   281 			if(firstPrinted) distinsuiName.append(L", ");
       
   282 			distinsuiName.append(L"EM=");
       
   283 			distinsuiName.append(nameEntry);
       
   284 			delete[] nameEntry;
       
   285 			}
       
   286 		}
       
   287 	return distinsuiName;
       
   288 	}
       
   289 
       
   290 std::wstring CCertificateInfo::IssuerName(bool aGetFullName) const
       
   291 	{
       
   292 	X509_NAME *x509Name = X509_get_issuer_name (iCertificate);
       
   293 	
       
   294 	std::wstring issuerName = GetDistinguishedName(x509Name, aGetFullName);
       
   295 	
       
   296 	return issuerName;
       
   297 	}
       
   298 
       
   299 std::wstring CCertificateInfo::SubjectName(bool aGetFullName) const
       
   300 	{
       
   301 	X509_NAME *x509Name = X509_get_subject_name (iCertificate);
       
   302 	
       
   303 	std::wstring subjectName = GetDistinguishedName(x509Name, aGetFullName);
       
   304 	
       
   305 	return subjectName;
       
   306 	}
       
   307 
       
   308 const CSISDateTime& CCertificateInfo::ValidFrom() const
       
   309 	{
       
   310 	return iValidFrom;
       
   311 	}
       
   312 
       
   313 const CSISDateTime& CCertificateInfo::ValidTo() const
       
   314 	{
       
   315 	return iValidTo;
       
   316 	}
       
   317 
       
   318 int CCertificateInfo::Version() const
       
   319 	{
       
   320 	return X509_get_version(iCertificate);
       
   321 	}
       
   322 
       
   323 std::string CCertificateInfo::SerialNumber() const
       
   324 	{
       
   325 	std::string serialNo;
       
   326 	
       
   327 	//Get serial number
       
   328 	ASN1_INTEGER* asnNum = X509_get_serialNumber(iCertificate);
       
   329 
       
   330 	if(asnNum->length <= 4)
       
   331 		{
       
   332 		char sno[30];
       
   333 		int sNum = ASN1_INTEGER_get(asnNum);
       
   334 		
       
   335 		if(sNum < 0)
       
   336 			{
       
   337 			sNum = -1;
       
   338 			serialNo.append("-");
       
   339 			}
       
   340 	
       
   341 		sprintf(sno, " %d (0x%x)", sNum, sNum);
       
   342 		serialNo.append(sno);
       
   343 		}
       
   344 	else
       
   345 		{
       
   346 		if(asnNum->type == V_ASN1_NEG_INTEGER)
       
   347 			{
       
   348 			serialNo = " (Negative)";
       
   349 			}
       
   350 
       
   351 		for(int i = 0; i < asnNum->length; i++)
       
   352 			{
       
   353 			char sno[10];
       
   354 			sprintf(sno, "%02x", (int)asnNum->data[i]);
       
   355 			serialNo.append(sno);
       
   356 			if(i < asnNum->length - 1)
       
   357 				{
       
   358 				serialNo.append(":");
       
   359 				}
       
   360 			}
       
   361 		}
       
   362 	
       
   363 	return serialNo;
       
   364 	}
       
   365 
       
   366 std::string CCertificateInfo::SignatureAlgo() const
       
   367 	{
       
   368 	std::string algo = OBJ_nid2ln(OBJ_obj2nid(iCertificate->sig_alg->algorithm));
       
   369 	return algo;
       
   370 	}
       
   371 
       
   372 std::string CCertificateInfo::PublicKeyAlgo() const
       
   373 	{
       
   374 	std::string algo = OBJ_nid2ln(OBJ_obj2nid(iCertificate->cert_info->key->algor->algorithm));
       
   375 	return algo;
       
   376 	}
       
   377 
       
   378 int CCertificateInfo::GetNameEntry(X509_NAME* aName, char *aKey, wchar_t** aNameEntry) const
       
   379 	{
       
   380 	if(!aName || !aKey)
       
   381 		return 0;
       
   382 
       
   383 
       
   384 	int nid = 0;
       
   385 	
       
   386 	if((nid = OBJ_txt2nid(aKey)) == NID_undef)
       
   387 		return 0;
       
   388 
       
   389 	int index = X509_NAME_get_index_by_NID(aName, nid, -1);
       
   390 
       
   391 	if(index == -1)
       
   392 		return 0;
       
   393 
       
   394 
       
   395 	X509_NAME_ENTRY* nameEnt = X509_NAME_get_entry(aName, index);
       
   396 	ASN1_STRING* ASN1Str = X509_NAME_ENTRY_get_data(nameEnt);
       
   397 	
       
   398 	BYTE* UTF8Str = NULL;
       
   399 	
       
   400 	if(ASN1_STRING_to_UTF8(&UTF8Str, ASN1Str) < 0)
       
   401 	{
       
   402 		if (M_ASN1_STRING_type(ASN1Str) == V_ASN1_UTF8STRING)
       
   403 		{
       
   404 			UTF8Str = ASN1_STRING_data(ASN1Str);
       
   405 		}
       
   406 		else 
       
   407 		{
       
   408 			return 0;
       
   409 		}
       
   410 	}
       
   411 	
       
   412 	int len = ConvertMultiByteToWideChar((LPSTR)UTF8Str, strlen((LPSTR)UTF8Str)+1, NULL, 0);
       
   413 	*aNameEntry = new wchar_t[len*sizeof(wchar_t)];
       
   414 	ConvertMultiByteToWideChar((LPSTR)UTF8Str, strlen((LPSTR)UTF8Str)+1, *aNameEntry, len);
       
   415 	return 1;
       
   416 	}
       
   417 
       
   418 std::string CCertificateInfo::Get_ASN1_STRING_Data(ASN1_STRING *aASN1String)
       
   419 	{
       
   420 	if(NULL == aASN1String)
       
   421 		{
       
   422 		return NULL;
       
   423 		}
       
   424 
       
   425 	int length = aASN1String->length;
       
   426 	std::string ASN_String;
       
   427 	unsigned char* ptr = aASN1String->data;
       
   428 	
       
   429 	for (int i = 0; i < aASN1String->length; ++i)
       
   430 		{
       
   431 		if ((ptr[i] > '~') || ((ptr[i] < ' ') && (ptr[i] != '\n') && (ptr[i] != '\r')))
       
   432 			ASN_String.append(".");
       
   433 		else
       
   434 			ASN_String.append(1, ptr[i]);
       
   435 		}
       
   436 	return ASN_String;
       
   437 	}
       
   438 
       
   439 const std::vector<TExtension>& CCertificateInfo::Extensions() const
       
   440 	{
       
   441 	return iExtensions;
       
   442 	}
       
   443 
       
   444 void CCertificateInfo::PrintPublicKey(std::ostream& aStream, int aIndent) const
       
   445 	{
       
   446 	EVP_PKEY *pKey = X509_get_pubkey(iCertificate);
       
   447 	assert(pKey);
       
   448 	
       
   449 	BIO *mem = BIO_new(BIO_s_mem());
       
   450 
       
   451 	switch(iPublicKeyType)
       
   452 		{
       
   453 		case EPubKeyDSA:
       
   454 			{
       
   455 			aStream << "" << "DSA Public Key:" << std::endl;
       
   456 			struct dsa_st *pDSA = EVP_PKEY_get1_DSA(pKey);
       
   457 			DSA_print(mem, pDSA, 28);
       
   458 			break;
       
   459 			}
       
   460 	
       
   461 		case EPubKeyRSA:
       
   462 			{
       
   463 			aStream.width(aIndent);
       
   464 			aStream << "" ;
       
   465 			aStream << "RSA Public Key: (" << std::dec << BN_num_bits(pKey->pkey.rsa->n) << " bit)"<< std::endl;
       
   466 			struct rsa_st *pRSA = EVP_PKEY_get1_RSA(pKey);
       
   467 			RSA_print(mem, pRSA, 16);
       
   468 			break;
       
   469 			}
       
   470 		}
       
   471 
       
   472 	BUF_MEM *bptr = NULL;
       
   473 	BIO_get_mem_ptr(mem, &bptr);
       
   474 	std::string str(bptr->data, bptr->length);
       
   475 	aStream << str;
       
   476 
       
   477 	BIO_free(mem);
       
   478 
       
   479 	if(pKey != NULL)
       
   480 		EVP_PKEY_free(pKey);
       
   481 	}
       
   482 
       
   483 void CCertificateInfo::PrintSignature(std::ostream& aStream, int aIndent) const
       
   484 	{
       
   485 	BIO *mem = BIO_new(BIO_s_mem());
       
   486 	X509_signature_print(mem, iCertificate->sig_alg, iCertificate->signature);
       
   487 	BUF_MEM *bptr = NULL;
       
   488 	BIO_get_mem_ptr(mem, &bptr);
       
   489 	std::string str(bptr->data, bptr->length);
       
   490 	aStream << str << std::endl;
       
   491 	BIO_free(mem);
       
   492 	}
       
   493 
       
   494 void CCertificateInfo::ExtractCertificate(std::string& aCertFileName) const
       
   495 	{
       
   496 	BIO* bio = BIO_new_file(aCertFileName.c_str(), "a");
       
   497 	if(bio)
       
   498 		{
       
   499 		if (!PEM_write_bio_X509(bio, iCertificate ))
       
   500 			{
       
   501 			throw "Error While Creating pem file";
       
   502 			}
       
   503 		BIO_free(bio);
       
   504 		}
       
   505 	else
       
   506 		{
       
   507 		throw "Unable to create Certificate File";
       
   508 		}
       
   509 	}
       
   510 
       
   511 bool CCertificateInfo::IsNIDPresent(int aNID) const
       
   512 	{
       
   513 	int val = X509_get_ext_by_NID(iCertificate, aNID, -1);
       
   514 	return (val == -1)? false: true;
       
   515 	}
       
   516 
       
   517 
       
   518 // END of FILE