securityanddataprivacytools/securitytools/certapp/encdec/filecertstore.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 09 Jun 2010 11:39:05 +0300
branchRCL_3
changeset 70 b38692a04122
parent 8 35751d3474b7
child 95 641f389e9157
permissions -rw-r--r--
Revision: 201023 Kit: 2010123

/*
* Copyright (c) 2008-2010 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: 
*
*/


#include "filecertstore.h"
#include "appuidmap.h"
#include "logger.h"
#include "stringconv.h"
#include "utils.h"
#include <iomanip>

EncDecContainerItem *AppUidListEntry::Factory()
{
	return new AppUidListEntry(AppUidMap::EnumEntries());
}

AppUidListEntry::AppUidListEntry(const EnumEntry *aEnumEntries)
	: EncDecContainerItem(), iUid("Application", aEnumEntries)
{
}

AppUidListEntry::~AppUidListEntry()
{
}

const char *AppUidListEntry::ItemType() const
{
	return 0; // n/a
}


void AppUidListEntry::Encode(REncodeWriteStream &aWriteStream)
{
	aWriteStream << iUid;
}

void AppUidListEntry::Decode(RDecodeReadStream &aReadStream)
{
	aReadStream >> iUid;
}


EncDecContainerItem *CertStoreEntry::Factory()
{
	return new CertStoreEntry;
}


static const EnumEntry enumDetailsForTBool[] =
{
    { "false", 0x00},
    { "true", 0x01},
    { "EFalse", false},
    { "ETrue", true},
	{ 0,0 }
};


CertStoreEntry::CertStoreEntry()
	: EncDecContainerItem(), 
	  iCertInfo(false),
	  iCertApps("ApplicationList", AppUidListEntry::Factory),
	  iTrusted("Trusted", enumDetailsForTBool), 
	  iReadDataStreamId("DataStreamId(read)", true),
	  iWriteDataStreamId("DataStreamId(write)", false),
	  iDataFileName("DataFileName"),
	  iCertData(),
	  iSwiMode(false)
{
	// We only need to initialise EncDecObject members which wrap non-class types
	iReadDataStreamId.Value() = 0;
	iWriteDataStreamId.Value() = 0;
}

CertStoreEntry::CertStoreEntry(bool aSwiMode)
	: EncDecContainerItem(), 
	  iCertInfo(aSwiMode),
	  iCertApps("ApplicationList", AppUidListEntry::Factory),
	  iTrusted("Trusted", enumDetailsForTBool), 
	  iReadDataStreamId("DataStreamId(read)", true),
	  iWriteDataStreamId("DataStreamId(write)", false),
	  iDataFileName("DataFileName"),
	  iCertData(),
	  iSwiMode(aSwiMode)
{
	// We only need to initialise EncDecObject members which wrap non-class types
	iReadDataStreamId.Value() = 0;
	iWriteDataStreamId.Value() = 0;
}

CertStoreEntry::~CertStoreEntry()
{
}

const TCertLabel &CertStoreEntry::Label() const
{
	return iCertInfo.Label();
}

CertInfo &CertStoreEntry::Info()
{
	return iCertInfo;
}

const CertInfo &CertStoreEntry::Info() const
{
	return iCertInfo;
}



const char *CertStoreEntry::ItemType() const
{
	return "Entry";
}

std::string CertStoreEntry::ItemName() const
{
	return stringFromUtf16(Label());
}


void CertStoreEntry::SetItemName(const std::string &aName)
{
	TInt outputWords;
	TText *outputBuf = utf16FromUtf8((const TUint8 *)aName.data(), aName.size(), outputWords);
	iCertInfo.Label() = TPtrC16(outputBuf, outputWords);
	delete [] outputBuf;
}


void CertStoreEntry::Encode(REncodeWriteStream &aWriteStream)
{
	iCertInfo.Encode(aWriteStream);
	aWriteStream << iCertApps;
	aWriteStream << iTrusted;
	if(aWriteStream.HumanReadable())
		{
		// Write data to a file

		// Generate a file name
		std::string certFileName = aWriteStream.CertFileName(iCertInfo.CertificateFormat(), iCertInfo.OutputCertificateId());
		iDataFileName.Value().Copy(TPtrC8((const TUint8*)certFileName.data(), certFileName.size()));
		
		// Write file name
		aWriteStream << iDataFileName;
		
		std::fstream certDataFile;
		OpenUtf8FStreamForWrite(certDataFile, certFileName.c_str());
		if(certDataFile.fail())
			{
			dbg << Log::Indent() << "Failed to open '" << certDataFile << "' for output!" << Log::Endl();
			FatalError();
			}
		if((iCertInfo.CertificateFormat() == EX509Certificate) && aWriteStream.PemOut())
			{
			std::string pemCert;
			Der2Pem(iCertData, pemCert);
			certDataFile.write(pemCert.data(), pemCert.size());
			}
		else
			{
			certDataFile.write(iCertData.data(), iCertData.size());
			}
		
		certDataFile.close();
		if(certDataFile.fail())
			{
			dbg << Log::Indent() << "Failed to write cert data to '" << certDataFile <<  Log::Endl();
			FatalError();
			}
		aWriteStream << iReadDataStreamId;
		}
	else
		{
		// Write to the store
		if(iCertData.size() != iCertInfo.CertSize())
			{
			dbg << Log::Indent() << "Internal error - cert data size does not match meta data" << Log::Endl();
			FatalError();
			}

		RStoreWriteStream dataStream;
		TStreamId dataStreamId = dataStream.CreateLC(*aWriteStream.StoreObject());
		prog << Log::Indent() << "Created store stream " << dataStreamId << " for certificate data" << Log::Endl();
		iWriteDataStreamId.Value() = dataStreamId;

		prog << Log::Indent() << "Writing " << iCertData.size() << " bytes of binary data" << Log::Endl();
		dataStream.WriteL((const TUint8 *)iCertData.data(), iCertData.size());

		CleanupStack::PopAndDestroy(&dataStream);
		aWriteStream << iWriteDataStreamId;
		}
}

void CertStoreEntry::Decode(RDecodeReadStream &aReadStream)
{
	iCertInfo.Decode(aReadStream);
	aReadStream >> iCertApps;
	if((!aReadStream.HumanReadable()) ||
	   (aReadStream.PeakToken() == iTrusted.Name()))
		{
		aReadStream >> iTrusted;
		}
	else
		{
		iTrusted.SetValue(true);
		}
	aReadStream >> iReadDataStreamId;
	if(aReadStream.HumanReadable())
		{
		aReadStream >> iDataFileName;
		// Read data from the specified file
		std::string nFileName = stringFromUtf16(iDataFileName.Value());
		
		std::fstream certDataFile;
		OpenUtf8FStreamForRead(certDataFile, nFileName.c_str());
		if(certDataFile.fail())
			{
			dbg << Log::Indent() << "Failed to open '" << nFileName << "' for input!" << Log::Endl();
			FatalError();
			}
		
		certDataFile.seekg(0, std::ios_base::end);
		TUint32 certSize = certDataFile.tellg();
		
		char *rawCertData = new char[certSize];
		
		certDataFile.seekg(0, std::ios_base::beg);
		certDataFile.read(rawCertData, certSize);
		
		certDataFile.close();
		if(certDataFile.fail())
			{
			dbg << Log::Indent() << "Failed to read cert data from '" << certDataFile << Log::Endl();
			FatalError();
			}
		iCertData.assign(rawCertData, certSize);
		delete [] rawCertData;
		
		if(iCertInfo.CertificateFormat() == EX509Certificate)
			{
			// It might be a PEM cert
			std::string derFromPem;
			if(Pem2Der(iCertData, derFromPem))
				{
				prog << Log::Indent() << "Converted PEM cert to DER" << Log::Endl();
				iCertData = derFromPem;
				certSize = iCertData.size();
				}
			}
		iCertInfo.SetCertSize(certSize);
		}
	else 
		{
		// Read data from the store
		RStoreReadStream dataStream;
		dataStream.OpenLC(*aReadStream.iStore, iReadDataStreamId.Value());

		TUint32 certSize = iCertInfo.CertSize();
		TUint8 * certData = new TUint8[certSize];

		prog << Log::Indent() << "Reading " << certSize << " byte certificate from store stream " << iReadDataStreamId.Value() << Log::Endl();
		
		dataStream.ReadL(certData, certSize);

		iCertData.assign((const char *)certData, certSize);
		
		CleanupStack::PopAndDestroy(&dataStream);
		}

	if(iCertInfo.CertificateFormat() == EX509Certificate)
		{
		TKeyIdentifier subjectKeyId;
		bool isCA = ( iCertInfo.CertificateOwnerType() != EUserCertificate );

		// nb. If processing a swicertstore we ignore any SubjectKeyId in the extension.
		if(X509SubjectKeyId((iSwiMode)?(KIgnoreCertificateExtension) : (KUseCertificateExtension), 
							false, isCA,
							iCertData,
							iCertSubject, subjectKeyId))
			{
			prog << Log::Indent() << "Subject = '" << iCertSubject << "'" << Log::Endl();

			prog << Log::Indent() << "Calculated SubjectKeyId is ";
			const TUint8 *p = subjectKeyId.Ptr();
			for(int i=0; i<subjectKeyId.Length(); ++i)
				{
				if(i) prog << ":";
				prog.Stream() << std::setfill('0') << std::setw(2) << int(p[i]);
				}
			prog.Stream() << std::setw(0);
			prog << Log::Endl();
			
			if(aReadStream.HumanReadable() && iCertInfo.SubjectKeyId().iAutoKey)
				{
				// Reading config file and auto set so copy generated
				// SubjectKeyId to value.
				prog << Log::Indent() << "Field set to auto so using calculated SubjectKeyId" << Log::Endl();;
				iCertInfo.SubjectKeyId().iHash = subjectKeyId;
				}
			else
				{
				// If the read value matches the calculated value then
				// set iAutoKey so we dump it as auto (with the value
				// as a comment).
				if(iCertInfo.SubjectKeyId().iHash == subjectKeyId)
					{
					prog << Log::Indent() << "Calculated SubjectKeyId matches value read from input so setting to auto" << Log::Endl();;
					iCertInfo.SubjectKeyId().iAutoKey = true;
					}
				else
					{
					prog << Log::Indent() << "Calculated SubjectKeyId does NOT match value read from input so setting to value read" << Log::Endl();;
					}
				
				}
			}
		}
}
	
CertStoreEntry& CertStoreEntry::operator= (const CertStoreEntry& aRhs)
{
	if(this == &aRhs) return *this; // handle self assignment

	EncDecContainerItem::operator=(*static_cast<const EncDecContainerItem *>(&aRhs));

	iCertInfo = aRhs.iCertInfo;

	iCertApps.reset();
	for(TUint32 i=0; i<aRhs.iCertApps.size(); ++i)
		{
		AppUidListEntry *newApp = new AppUidListEntry(AppUidMap::EnumEntries());
		const AppUidListEntry *oldApp = static_cast<const AppUidListEntry *>(&aRhs.iCertApps[i]);
		*newApp = *oldApp;
		iCertApps.push_back(newApp);
		}

	iTrusted = aRhs.iTrusted;
	iReadDataStreamId = aRhs.iReadDataStreamId;
	iWriteDataStreamId = aRhs.iWriteDataStreamId;
	iDataFileName = aRhs.iDataFileName;
	iCertData = aRhs.iCertData;

	iCertSubject = aRhs.iCertSubject;

	iSwiMode = aRhs.iSwiMode;
		
	return *this;
}

const TUint8 * CertStoreEntry::CertData() const
{
	return (const TUint8 *)iCertData.data();
}


const std::string &CertStoreEntry::CertSubject() const
{
	return iCertSubject;
}



// End of file