os/security/securityanddataprivacytools/securitytools/certapp/certapp.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/security/securityanddataprivacytools/securitytools/certapp/certapp.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1054 @@
     1.4 +/*
     1.5 +* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.6 +* All rights reserved.
     1.7 +* This component and the accompanying materials are made available
     1.8 +* under the terms of the License "Eclipse Public License v1.0"
     1.9 +* which accompanies this distribution, and is available
    1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.11 +*
    1.12 +* Initial Contributors:
    1.13 +* Nokia Corporation - initial contribution.
    1.14 +*
    1.15 +* Contributors:
    1.16 +*
    1.17 +* Description: 
    1.18 +*
    1.19 +*/
    1.20 +
    1.21 +
    1.22 +static const char * const sVersion = "certapp version 1.1.++";
    1.23 +#include <e32base.h>
    1.24 +#include <f32file.h>
    1.25 +#include <s32file.h>
    1.26 +#include <map>
    1.27 +#include <sys/stat.h>
    1.28 +#include "encdec.h"
    1.29 +#include "certclients.h"
    1.30 +#include "filecertstore.h"
    1.31 +#include "swicertstore.h"
    1.32 +#include "logger.h"
    1.33 +#include "stringconv.h"
    1.34 +#include <errno.h>
    1.35 +#include "appuidmap.h"
    1.36 +#include "openssl_license.h"
    1.37 +#include "utils.h"
    1.38 +
    1.39 +#ifdef __TOOLS2_LINUX__
    1.40 +#include <unistd.h>
    1.41 +#include <stdio.h>
    1.42 +#else
    1.43 +#include <io.h>
    1.44 +#endif // __TOOLS2_LINUX__
    1.45 +
    1.46 +#ifdef __TOOLS2_LINUX__
    1.47 +#define DIR_SEPARATOR "/"
    1.48 +#else
    1.49 +#define DIR_SEPARATOR "\\"
    1.50 +#endif
    1.51 +
    1.52 +enum CertStoreFileType
    1.53 +{
    1.54 +	EBinCertClients,
    1.55 +	EHumanCertClients,
    1.56 +	EBinFileCertStore,
    1.57 +	EHumanFileCertStore,
    1.58 +	EBinSwiCertStore,
    1.59 +	EHumanSwiCertStore
    1.60 +};
    1.61 +
    1.62 +struct AppMapEntry
    1.63 +	{
    1.64 +	TUint32 iUid;
    1.65 +	TUint32 iInputFileIndex;
    1.66 +	};
    1.67 +typedef std::map<std::string, AppMapEntry> AppMap;
    1.68 +
    1.69 +typedef std::map<std::string, TUint32> FCSLabelMap; // maps cert label to inputFileIndex
    1.70 +
    1.71 +typedef std::vector<std::string> StringVector;
    1.72 +typedef std::vector<CertStoreFileType> CertStoreFileTypeVector;
    1.73 +
    1.74 +void ProcessCommandLine(int aArgc, char **aArgv, 
    1.75 +						StringVector &aInputFiles, 
    1.76 +						StringVector &aInputDirs,
    1.77 +						CertStoreFileTypeVector &aInputFileTypes,
    1.78 +						StringVector &aOutputFiles,
    1.79 +						StringVector &aOutputDirs,
    1.80 +						CertStoreFileTypeVector &aOutputFileTypes,
    1.81 +						bool &aVerbose, bool &aPemOut, bool &aAllowDuplicates);
    1.82 +
    1.83 +void ProcessCertClientFiles(const std::string &aBaseDir,
    1.84 +							const StringVector &aInputFiles,
    1.85 +							const StringVector &aInputDirs,
    1.86 +							const CertStoreFileTypeVector &aInputFileTypes,
    1.87 +							bool &aAllowDuplicates,
    1.88 +							EncDecContainer &aCertAppInfoContainer);
    1.89 +
    1.90 +void GenerateOutputFiles(const EncDecContainer &aCertAppInfoContainer,
    1.91 +						 const EncDecContainer &aFileCertStoreContainer,
    1.92 +						 const EncDecContainer &aSwiCertStoreContainer,
    1.93 +						 const std::string &aBaseDir,
    1.94 +						 const StringVector &aOutputFiles, 
    1.95 +						 const StringVector &aOutputDirs,
    1.96 +						 const CertStoreFileTypeVector &aOutputFileTypes,
    1.97 +						 bool aVerbose, bool aPemOut);
    1.98 +
    1.99 +bool ValidateLabel(FCSLabelMap &aLabelMap, 
   1.100 +				   const StringVector &aInputFiles, 
   1.101 +				   CertStoreFileType aFileType,
   1.102 +				   TUint32 aFileIndex, 
   1.103 +				   const TCertLabel &aCertLabel);
   1.104 +
   1.105 +
   1.106 +struct SubjectToSubjectKeyIdEntry
   1.107 +	{
   1.108 +	bool iDuplicate;
   1.109 +	std::string iLabel;
   1.110 +	TKeyIdentifier iSubjectKeyIdentifier;
   1.111 +	};
   1.112 +typedef std::map<std::string, SubjectToSubjectKeyIdEntry> SubjectToSubjectKeyIdMap;
   1.113 +void BuildSubjectToSubjectKeyIdMap(const EncDecContainer &aCertStoreContainer,
   1.114 +								   SubjectToSubjectKeyIdMap &aSubjectMap);
   1.115 +
   1.116 +void SetIssuerKeyId(SubjectToSubjectKeyIdMap &aSubjectMap, 
   1.117 +					EUseCertificateExtension aUseExtension,
   1.118 +					EncDecContainer &aCertStoreContainer);
   1.119 +
   1.120 +static const std::string OPT_PROGRESS("--progress=");
   1.121 +static const std::string OPT_ERRORS("--errors=");
   1.122 +static const std::string OPT_VERBOSE("--verbose");
   1.123 +static const std::string OPT_ALLOWDUPLICATES("--allowduplicates");
   1.124 +static const std::string OPT_CHDIR("--chdir=");
   1.125 +static const std::string OPT_HCERTCLIENTS_L("--hcertclients=");
   1.126 +static const std::string OPT_HCERTCLIENTS_S("--hcc=");
   1.127 +static const std::string OPT_BCERTCLIENTS_L("--bcertclients=");
   1.128 +static const std::string OPT_BCERTCLIENTS_S("--bcc=");
   1.129 +static const std::string OPT_HFILECERTSTORE_L("--hfilecertstore=");
   1.130 +static const std::string OPT_HFILECERTSTORE_S("--hca=");
   1.131 +static const std::string OPT_BFILECERTSTORE_L("--bfilecertstore=");
   1.132 +static const std::string OPT_BFILECERTSTORE_S("--bca=");
   1.133 +static const std::string OPT_HSWICERTSTORE_L("--hswicertstore=");
   1.134 +static const std::string OPT_HSWICERTSTORE_S("--hswi=");
   1.135 +static const std::string OPT_BSWICERTSTORE_L("--bswicertstore=");
   1.136 +static const std::string OPT_BSWICERTSTORE_S("--bswi=");
   1.137 +
   1.138 +
   1.139 +
   1.140 +void usage()
   1.141 +{
   1.142 +	prog << "certapp: general_options file_options --out file_options" << Log::Endl();
   1.143 +	prog << Log::Endl();
   1.144 +	prog << "Basic usage is to give one or more input files of any supported type, followed by --out and a list of output files using the same syntax" << Log::Endl();
   1.145 +	prog << "Typically at least one input file of type certclients should be given (via --bcertclients or --hcertclients) because this is required to encode/decode the application usage fields in the swicertstore and filecertstore files." << Log::Endl();
   1.146 +	prog << Log::Endl();
   1.147 +	prog << "general_options contains one or more of the following options:-" << Log::Endl();
   1.148 +	prog << "\t--help|-h\tDisplay this usage message" << Log::Endl();
   1.149 +	prog << "\t" << OPT_PROGRESS << "filename\tSave progress output to specified file" << Log::Endl();
   1.150 +	prog << "\t" << OPT_ERRORS << "filename\tSave error output to specified file" << Log::Endl();
   1.151 +	prog << "\t" << OPT_VERBOSE << "Include additional debug comments in output files" << Log::Endl();
   1.152 +	prog << "\t--license Display license information" << Log::Endl();
   1.153 +	prog << "\t--pemout Output certificates in PEM format (nb. format is auto-detected when reading)" << Log::Endl();
   1.154 +	prog << "\t" << OPT_ALLOWDUPLICATES << "\tWhen reading human readable config files, permit adding duplicate certificate labels in stores and UIDs in certclients (testing ONLY)" << Log::Endl();
   1.155 +	prog << "An errors/progress filename of - will write to the standard output." << Log::Endl();
   1.156 +	prog << "If the errors/progress filenames are identical, the output will be merged." << Log::Endl();
   1.157 +	prog << Log::Endl();
   1.158 +	prog << "Both instances of file_options contains one or more of the following options:-" << Log::Endl();
   1.159 +	prog << "\t" << OPT_HCERTCLIENTS_L << "|" << OPT_HCERTCLIENTS_S << "filename\t\tHuman readable certclients file" << Log::Endl();
   1.160 +	prog << "\t" << OPT_BCERTCLIENTS_L << "|" << OPT_BCERTCLIENTS_S << "filename\t\tBinary certclients file" << Log::Endl();
   1.161 +	prog << Log::Endl();
   1.162 +	prog << "\t" << OPT_HFILECERTSTORE_L << "|" << OPT_HFILECERTSTORE_S << "filename\tHuman readable filecertstore" << Log::Endl();
   1.163 +	prog << "\t" << OPT_BFILECERTSTORE_L << "|" << OPT_BFILECERTSTORE_S << "filename\tBinary filecertstore" << Log::Endl();
   1.164 +	prog << Log::Endl();
   1.165 +	prog << "\t" << OPT_HSWICERTSTORE_L << "|" << OPT_HSWICERTSTORE_S << "filename\tHuman readable swicertstore" << Log::Endl();
   1.166 +	prog << "\t" << OPT_BSWICERTSTORE_L << "|" << OPT_BSWICERTSTORE_S << "filename\tBinary swicertstore" << Log::Endl();
   1.167 +	prog << Log::Endl();
   1.168 +	prog << "\t" << "--out Change to specifying output files" << Log::Endl();
   1.169 +	prog << "\t" << "--in Change to specifying input files" << Log::Endl();
   1.170 +	prog << "\t" << "--chdir=relativeDir Change to the specified dir. Can be specified multiple times. Missing dir will be created if only last element is missing." << Log::Endl();	
   1.171 +	prog << Log::Endl();
   1.172 +	
   1.173 +	prog << "Examples" << Log::Endl();
   1.174 +	prog << "Read/dump a swicertstore" << Log::Endl();
   1.175 +	prog << "\tcertapp --bcertclients=certclients.dat --bswicertstore=swicertstore.dat --out --hswicertstore=swicertstore.txt" << Log::Endl();
   1.176 +	prog << "Read/dump a filecertstore" << Log::Endl();
   1.177 +	prog << "\tcertapp --bcertclients=certclients.dat --bfilecertstore=cacerts.dat --out --hfilecertstore=cacerts.txt" << Log::Endl();
   1.178 +	prog << "Augment a filecertstore" << Log::Endl();
   1.179 +	prog << "\tcertapp --bcertclients=certclients.dat --bfilecertstore=cacerts.dat --hfilecertstore=cacerts_extras.txt --out --bfilecertstore=cacerts_new.dat" << Log::Endl();
   1.180 +	prog << Log::Endl();
   1.181 +	prog << "Device file locations" << Log::Endl();
   1.182 +	prog << "ROM swicertstore - z:\\resource\\swicertstore.dat" << Log::Endl();
   1.183 +	prog << "Writable swicertstore - !:\\resource\\swicertstore\\dat\\* where ! is the system drive" << Log::Endl();
   1.184 +	prog << "Initial filecertstore and certclients z:\\private\\101f72a6\\cacerts.dat and certclients.dat. Copied to sys drive on first use." << Log::Endl();
   1.185 +	prog << "Filecertstore !:\\private\\101f72a6\\cacerts.dat and certclients.dat. where ! is the system drive." << Log::Endl();
   1.186 +}
   1.187 +
   1.188 +void ChangeDir(const std::string &aBaseDir, const std::string &aRelativeDir)
   1.189 +{
   1.190 +	std::string dir(aBaseDir);
   1.191 +	if(aRelativeDir != ".")
   1.192 +		{
   1.193 +		// Build dir to create and change into
   1.194 +		dir.append(DIR_SEPARATOR);
   1.195 +		dir.append(aRelativeDir);
   1.196 +		}
   1.197 +		
   1.198 +	prog << Log::Indent() << "Setting dir to " << dir << Log::Endl();
   1.199 +#ifdef __LINUX__
   1.200 +	(void) mkdir(dir.c_str(),0755); // May already exist so no need to check return code
   1.201 +#else
   1.202 +	(void) mkdir(dir.c_str()); // May already exist so no need to check return code
   1.203 +#endif
   1.204 +	if(chdir(dir.c_str()) < 0)
   1.205 +		{
   1.206 +		dbg << Log::Indent() << "failed to change dir to " << dir << Log::Endl();
   1.207 +		FatalError();
   1.208 +		}
   1.209 +	return;
   1.210 +}
   1.211 +
   1.212 +int main(int argc, char **argv)
   1.213 +{
   1.214 +	dbg.SetStream(&std::cout);
   1.215 +	prog.SetStream(&std::cout);
   1.216 +
   1.217 +	try{
   1.218 +	if(argc==1)
   1.219 +		{
   1.220 +		prog << sVersion << " Use -h for help." << Log::Endl();
   1.221 +		}
   1.222 +
   1.223 +	StringVector inputFiles;
   1.224 +	StringVector inputDirs;
   1.225 +	CertStoreFileTypeVector inputFileTypes;
   1.226 +
   1.227 +	StringVector outputFiles;
   1.228 +	StringVector outputDirs;
   1.229 +	CertStoreFileTypeVector outputFileTypes;
   1.230 +
   1.231 +
   1.232 +	bool verbose = false;
   1.233 +	bool pemOut = false;
   1.234 +	bool allowDuplicates = false;
   1.235 +
   1.236 +	// Process all the command line options and file arguments
   1.237 +	ProcessCommandLine(argc, argv, 
   1.238 +					   inputFiles, inputDirs, inputFileTypes,
   1.239 +					   outputFiles, outputDirs, outputFileTypes,
   1.240 +					   verbose, pemOut, allowDuplicates);
   1.241 +
   1.242 +
   1.243 +	// Save current directory
   1.244 +	std::string baseDir;
   1.245 +	{
   1.246 +	char tmp[FILENAME_MAX];
   1.247 +	if(getcwd(tmp, FILENAME_MAX) == 0)
   1.248 +		{
   1.249 +		dbg << Log::Indent() << "Failed to read current dir" << Log::Endl();
   1.250 +		FatalError();
   1.251 +		}
   1.252 +	baseDir = tmp;
   1.253 +	}
   1.254 +	
   1.255 +
   1.256 +	//
   1.257 +	// Process input files starting with certclient files and working from right to left
   1.258 +	//
   1.259 +	EncDecContainer certAppInfoContainer("ClientInfo", CertificateAppInfo::Factory);
   1.260 +	ProcessCertClientFiles(baseDir, inputFiles, inputDirs, inputFileTypes, 
   1.261 +						   allowDuplicates,
   1.262 +						   certAppInfoContainer);
   1.263 +	
   1.264 +	
   1.265 +	// Generate config data for application uid EncDecEnum object in AppUidListEntry
   1.266 +	AppUidMap::GenerateEnumEntries();
   1.267 +
   1.268 +	//
   1.269 +	// Process remaining input files working from right to left
   1.270 +	//
   1.271 +	EncDecContainer fileCertStoreContainer("CertStoreEntries", CertStoreEntry::Factory);
   1.272 +	FCSLabelMap fcsLabels;
   1.273 +	EncDecContainer swiCertStoreContainer("SwiCertStoreEntries", SwiCertStoreEntry::Factory);
   1.274 +	FCSLabelMap swiLabels;
   1.275 +	for(int fileIndex = inputFiles.size()-1; fileIndex >= 0 ; --fileIndex)
   1.276 +		{
   1.277 +		CertStoreFileType fileType = inputFileTypes[fileIndex];
   1.278 +		if((fileType == EBinFileCertStore) || (fileType == EHumanFileCertStore))
   1.279 +			{
   1.280 +			// Change to correct directory
   1.281 +			ChangeDir(baseDir, inputDirs[fileIndex]);
   1.282 +
   1.283 +			EncDecContainer tmpFileCertStoreContainer("CertStoreEntries", CertStoreEntry::Factory);
   1.284 +			if(fileType == EBinFileCertStore)
   1.285 +				{
   1.286 +				prog << "Reading binary filecertstore file '" << inputFiles[fileIndex] << "'" << Log::Endl();
   1.287 +				AutoIndent ai(prog);
   1.288 +				readContainer(inputFiles[fileIndex], false, tmpFileCertStoreContainer);
   1.289 +				}
   1.290 +			if(fileType == EHumanFileCertStore)
   1.291 +				{
   1.292 +				prog << "Reading human filecertstore file '" << inputFiles[fileIndex] << "'" << Log::Endl();
   1.293 +				AutoIndent ai(prog);
   1.294 +				readContainer(inputFiles[fileIndex], true, tmpFileCertStoreContainer);
   1.295 +				}
   1.296 +			
   1.297 +			// Now merge the new file into the running store.
   1.298 +			prog << Log::Indent() << "Merging filecertstore data" << Log::Endl();
   1.299 +			AutoIndent ai(prog);
   1.300 +			for(TUint32 entryIndex = 0; entryIndex < tmpFileCertStoreContainer.size(); ++entryIndex)
   1.301 +				{
   1.302 +				const CertStoreEntry &entry = static_cast<const CertStoreEntry &>(tmpFileCertStoreContainer[entryIndex]);
   1.303 +				std::string nname = stringFromUtf16(entry.Label());
   1.304 +
   1.305 +				if(!ValidateLabel(fcsLabels, inputFiles, fileType, fileIndex, entry.Label()))
   1.306 +					{
   1.307 +					// Duplicate detected
   1.308 +					if(!allowDuplicates || (fileType == EBinFileCertStore))
   1.309 +						{
   1.310 +						continue; // Skip adding duplicate
   1.311 +						}
   1.312 +					// Only allow duplicates if debugging and reading
   1.313 +					// human readable config file.
   1.314 +					dbg << Log::Indent() << "Adding anyway due to " << OPT_ALLOWDUPLICATES << Log::Endl();
   1.315 +					}
   1.316 +				
   1.317 +				// Add entry
   1.318 +				CertStoreEntry *newEntry = new CertStoreEntry;
   1.319 +				*newEntry = entry;
   1.320 +				fileCertStoreContainer.push_back(newEntry);
   1.321 +				}
   1.322 +			continue;
   1.323 +			}
   1.324 +		
   1.325 +
   1.326 +		if((fileType == EBinSwiCertStore) || (fileType == EHumanSwiCertStore))
   1.327 +			{
   1.328 +			// Change to correct directory
   1.329 +			ChangeDir(baseDir, inputDirs[fileIndex]);
   1.330 +
   1.331 +			EncDecContainer tmpSwiCertStoreContainer("SwiCertStoreEntries", SwiCertStoreEntry::Factory);
   1.332 +			if(fileType == EBinSwiCertStore)
   1.333 +				{
   1.334 +				prog << "Reading binary swicertstore file '" << inputFiles[fileIndex] << "'" << Log::Endl();
   1.335 +				AutoIndent ai(prog);
   1.336 +				readContainer(inputFiles[fileIndex], false, tmpSwiCertStoreContainer);
   1.337 +				}
   1.338 +			if(fileType == EHumanSwiCertStore)
   1.339 +				{
   1.340 +				prog << "Reading human swicertstore file '" << inputFiles[fileIndex] << "'" << Log::Endl();
   1.341 +				AutoIndent ai(prog);
   1.342 +				readContainer(inputFiles[fileIndex], true, tmpSwiCertStoreContainer);
   1.343 +				}
   1.344 +
   1.345 +			// Now merge the new file into the running store.
   1.346 +			prog << Log::Indent() << "Merging swicerstore data" << Log::Endl();
   1.347 +			AutoIndent ai(prog);
   1.348 +			for(TUint32 entryIndex = 0; entryIndex < tmpSwiCertStoreContainer.size(); ++entryIndex)
   1.349 +				{
   1.350 +				const SwiCertStoreEntry &entry = static_cast<const SwiCertStoreEntry &>(tmpSwiCertStoreContainer[entryIndex]);
   1.351 +				std::string nname = stringFromUtf16(entry.Label());
   1.352 +		
   1.353 +				if(!ValidateLabel(swiLabels, inputFiles, fileType, fileIndex, entry.Label()))
   1.354 +					{
   1.355 +					// Duplicate detected
   1.356 +					if(!allowDuplicates || (fileType == EBinSwiCertStore))
   1.357 +						{
   1.358 +						continue; // Skip adding duplicate
   1.359 +						}
   1.360 +					// Only allow duplicates if debugging and reading
   1.361 +					// human readable config file.
   1.362 +					dbg << Log::Indent() << "Adding anyway due to " << OPT_ALLOWDUPLICATES << Log::Endl();
   1.363 +					}
   1.364 +				
   1.365 +				// Add entry
   1.366 +				SwiCertStoreEntry *newEntry = new SwiCertStoreEntry;
   1.367 +				*newEntry = entry;
   1.368 +				swiCertStoreContainer.push_back(newEntry);
   1.369 +				}
   1.370 +			continue;
   1.371 +			}
   1.372 +		}
   1.373 +
   1.374 +	// Fix Certificate IDs in fileCertStoreContainer
   1.375 +	for(TUint32 entryIndex=0; entryIndex < fileCertStoreContainer.size(); ++entryIndex)
   1.376 +		{
   1.377 +		CertStoreEntry &entry = static_cast<CertStoreEntry &>(fileCertStoreContainer[entryIndex]);
   1.378 +		entry.Info().SetOutputCertificateId(entryIndex);
   1.379 +		}
   1.380 +	
   1.381 +	// Fix Certificate IDs in swicertstore container.
   1.382 +	for(TUint32 entryIndex=0; entryIndex < swiCertStoreContainer.size(); ++entryIndex)
   1.383 +		{
   1.384 +		SwiCertStoreEntry &entry = static_cast<SwiCertStoreEntry &>(swiCertStoreContainer[entryIndex]);
   1.385 +		entry.Info().SetOutputCertificateId(entryIndex);
   1.386 +		}
   1.387 +
   1.388 +	//
   1.389 +	// Fix auto IssuerKeyId values
   1.390 +	//
   1.391 +	SubjectToSubjectKeyIdMap subjectMap;
   1.392 +	//
   1.393 +	// Fix IssuerKeyId values in swiCertStoreContainer
   1.394 +	//
   1.395 +	// We do not use the AuthorityKeyId extension and only consider
   1.396 +	// certificates in swi certstores.
   1.397 +	//
   1.398 +	// First map all the SWI certificate subject names to SubjectKeyId values
   1.399 +	BuildSubjectToSubjectKeyIdMap(swiCertStoreContainer, subjectMap);
   1.400 +	// Now update IssuerKeyId fields which are set to auto.
   1.401 +	// The AuthorityKeyId extension value will be ignored.
   1.402 +	// The SubjectKeyId of a matching certificate (if there is a
   1.403 +	// single match on issuer name) in the swi cert store will be
   1.404 +	// used.
   1.405 +	SetIssuerKeyId(subjectMap, KIgnoreCertificateExtension, swiCertStoreContainer);
   1.406 +
   1.407 +
   1.408 +	//
   1.409 +	// Fix IssuerKeyId values in fileCertStoreContainer
   1.410 +	//
   1.411 +	// Add all filecertstore certificates to the
   1.412 +	// subjectName/SubjectKeyId map
   1.413 +	BuildSubjectToSubjectKeyIdMap(fileCertStoreContainer, subjectMap);
   1.414 +	// Now update IssuerKeyId fields which are set to auto.  If an the
   1.415 +	// AuthorityKeyId extension is present and <160bits use it,
   1.416 +	// otherwise use the SubjectKeyId of the matching certificate (if
   1.417 +	// there is a single match on issuer name).
   1.418 +	SetIssuerKeyId(subjectMap, KUseCertificateExtension, fileCertStoreContainer);
   1.419 +
   1.420 +	//
   1.421 +	// Now generate output files
   1.422 +	//
   1.423 +	GenerateOutputFiles(certAppInfoContainer, fileCertStoreContainer, swiCertStoreContainer,
   1.424 +						baseDir, outputFiles, outputDirs, outputFileTypes, verbose, pemOut);
   1.425 +	
   1.426 +
   1.427 +	}
   1.428 +	catch(...)
   1.429 +		{
   1.430 +		dbg << Log::Indent() << "C++ expection!" << Log::Endl();
   1.431 +		FatalError();
   1.432 +		}
   1.433 +	
   1.434 +	prog << Log::Indent() << "Normal exit" << Log::Endl();
   1.435 +	prog.Stream().flush();
   1.436 +	dbg.Stream().flush();
   1.437 +	return 0; // All ok
   1.438 +}
   1.439 +
   1.440 +/**
   1.441 +   ProcessCommandLine
   1.442 +*/
   1.443 +void ProcessCommandLine(int aArgc, char **aArgv, 
   1.444 +						StringVector &aInputFiles, StringVector &aInputDirs, CertStoreFileTypeVector &aInputFileTypes,
   1.445 +						StringVector &aOutputFiles, StringVector &aOutputDirs, CertStoreFileTypeVector &aOutputFileTypes,
   1.446 +						bool &aVerbose, bool &aPemOut, bool &aAllowDuplicates)
   1.447 +{
   1.448 +	std::string progressFile("-");
   1.449 +	static std::fstream sProgressStream;
   1.450 +
   1.451 +	std::string dbgFile("-");
   1.452 +	static std::fstream sDbgStream;
   1.453 +
   1.454 +	StringVector *files = &aInputFiles;
   1.455 +	StringVector *dirs = &aInputDirs;
   1.456 +	CertStoreFileTypeVector *fileTypes = &aInputFileTypes;
   1.457 +
   1.458 +	int argIndex=1;
   1.459 +	// Process overall arguments (-h --progress --errors)
   1.460 +	for(; argIndex < aArgc; ++argIndex)
   1.461 +		{
   1.462 +		std::string arg(aArgv[argIndex]);
   1.463 +
   1.464 +		if(arg == "--license")
   1.465 +			{
   1.466 +			prog << sVersion << Log::Endl();
   1.467 +			prog << "Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies)." << Log::Endl();
   1.468 +			prog << "All rights reserved." << Log::Endl();
   1.469 +			prog << "This component and the accompanying materials are made available" << Log::Endl();
   1.470 +			prog << "under the terms of the License \"Eclipse Public License v1.0\"" << Log::Endl();
   1.471 +			prog << "which accompanies this distribution, and is available" << Log::Endl();
   1.472 +			prog << "at the URL \"http://www.eclipse.org/legal/epl-v10.html\"." << Log::Endl();
   1.473 +			prog << "Initial Contributors:" << Log::Endl();
   1.474 +			prog << "Nokia Corporation - initial contribution." << Log::Endl() << Log::Endl();
   1.475 +			
   1.476 +			prog << "Linked against openssl. Credits and license for openssl follow:-" << Log::Endl();
   1.477 +			prog << openssl_license << Log::Endl();
   1.478 +			
   1.479 +			continue;
   1.480 +			}
   1.481 +
   1.482 +		if(arg == OPT_VERBOSE)
   1.483 +			{
   1.484 +			prog << "Enabling additional output file comments" << Log::Endl();
   1.485 +			aVerbose = true;
   1.486 +			
   1.487 +			continue;
   1.488 +			}
   1.489 +
   1.490 +		if(arg == "--pemout")
   1.491 +			{
   1.492 +			prog << "Setting output certificate format to PEM" << Log::Endl();
   1.493 +			aPemOut = true;
   1.494 +			
   1.495 +			continue;
   1.496 +			}
   1.497 +
   1.498 +		if(arg == OPT_ALLOWDUPLICATES)
   1.499 +			{
   1.500 +			prog << "Allowing addition of duplicate labels in stores and UIDs in certclients when reading human readable input (testing ONLY)" << Log::Endl();
   1.501 +			aAllowDuplicates = true;
   1.502 +			
   1.503 +			continue;
   1.504 +			}
   1.505 +
   1.506 +		if((arg.find(OPT_PROGRESS) == 0) ||
   1.507 +		   (arg.find(OPT_ERRORS) == 0))
   1.508 +			{
   1.509 +			// The following logic is required so that if both streams
   1.510 +			// are set to the same destination we share a streams
   1.511 +			// object and hence avoid buffering issues.
   1.512 +			std::string *thisFile;
   1.513 +			std::fstream *thisStream;
   1.514 +			Log *thisLog;
   1.515 +			std::string *otherFile;
   1.516 +			std::fstream *otherStream;
   1.517 +			Log *otherLog;
   1.518 +
   1.519 +			if(arg.find(OPT_PROGRESS) == 0)
   1.520 +				{
   1.521 +				thisFile = &progressFile;
   1.522 +				thisStream = &sProgressStream;
   1.523 +				thisLog = &prog;
   1.524 +				otherFile = &dbgFile;
   1.525 +				otherStream = &sDbgStream;
   1.526 +				otherLog = &dbg;
   1.527 +
   1.528 +				*thisFile = arg.substr(OPT_PROGRESS.size(), arg.npos);
   1.529 +				}
   1.530 +			else
   1.531 +				{
   1.532 +				thisFile = &dbgFile;
   1.533 +				thisStream = &sDbgStream;
   1.534 +				thisLog = &dbg;
   1.535 +				otherFile = &progressFile;
   1.536 +				otherStream = &sProgressStream;
   1.537 +				otherLog = &prog;
   1.538 +
   1.539 +				*thisFile = arg.substr(OPT_ERRORS.size(), arg.npos);
   1.540 +				}
   1.541 +
   1.542 +			if(*thisFile == *otherFile)
   1.543 +				{
   1.544 +				// Reuse existing stream. This avoids two streams opening the same file...
   1.545 +				thisLog->SetStream(&otherLog->Stream());
   1.546 +				continue;
   1.547 +				}
   1.548 +
   1.549 +			// Need to open a new stream
   1.550 +			if(thisStream->is_open()) thisStream->close();
   1.551 +			if(*thisFile == "-")
   1.552 +				{
   1.553 +				thisLog->SetStream(&std::cout);
   1.554 +				continue;
   1.555 +				}
   1.556 +			
   1.557 +			OpenUtf8FStreamForWrite(*thisStream, thisFile->c_str());
   1.558 +			if(thisStream->fail())
   1.559 +				{
   1.560 +				if(thisLog == &dbg)
   1.561 +					{
   1.562 +					dbg.SetStream(&std::cout);
   1.563 +					}
   1.564 +				dbg << Log::Indent() << "Failed to open log file specified by " << aArgv[argIndex-1] << " '" << *thisFile << "'" << Log::Endl();
   1.565 +				return;
   1.566 +				}
   1.567 +			thisLog->SetStream(thisStream);
   1.568 +			continue;
   1.569 +			}
   1.570 +
   1.571 +		if((strcmp(aArgv[argIndex], "--help") == 0) || (strcmp(aArgv[argIndex], "-h") == 0))
   1.572 +			{
   1.573 +			usage();
   1.574 +			continue;
   1.575 +			}
   1.576 +
   1.577 +		// Not a general option, probably an input file...
   1.578 +		break;
   1.579 +		}
   1.580 +	
   1.581 +	// Process main arguments
   1.582 +	for(; argIndex < aArgc; ++argIndex)
   1.583 +		{
   1.584 +		std::string arg(aArgv[argIndex]);
   1.585 +
   1.586 +		bool gotFile = false;
   1.587 +		if((strcmp(aArgv[argIndex], "--help") == 0) || (strcmp(aArgv[argIndex], "-h") == 0))
   1.588 +			{
   1.589 +			usage();
   1.590 +			continue;
   1.591 +			}
   1.592 +		
   1.593 +		if(arg.find(OPT_CHDIR) == 0)
   1.594 +			{
   1.595 +			dirs->push_back(arg.substr(OPT_CHDIR.size(), arg.npos));
   1.596 +			// Move to next option
   1.597 +			++argIndex;
   1.598 +			if(argIndex >= aArgc) break;
   1.599 +			arg = aArgv[argIndex];
   1.600 +			}
   1.601 +		else
   1.602 +			{
   1.603 +			dirs->push_back(".");
   1.604 +			}
   1.605 +
   1.606 +		std::string fileArg;
   1.607 +		if(arg.find(OPT_BCERTCLIENTS_L) == 0)
   1.608 +			{
   1.609 +			fileTypes->push_back(EBinCertClients);
   1.610 +			fileArg = arg.substr(OPT_BCERTCLIENTS_L.size(), arg.npos);
   1.611 +			gotFile = true;
   1.612 +			}
   1.613 +		if(arg.find(OPT_BCERTCLIENTS_S) == 0)
   1.614 +			{
   1.615 +			fileTypes->push_back(EBinCertClients);
   1.616 +			fileArg = arg.substr(OPT_BCERTCLIENTS_S.size(), arg.npos);
   1.617 +			gotFile = true;
   1.618 +			}
   1.619 +		if(arg.find(OPT_HCERTCLIENTS_L) == 0)
   1.620 +			{
   1.621 +			fileTypes->push_back(EHumanCertClients);
   1.622 +			fileArg = arg.substr(OPT_HCERTCLIENTS_L.size(), arg.npos);
   1.623 +			gotFile = true;
   1.624 +			}
   1.625 +		if(arg.find(OPT_HCERTCLIENTS_S) == 0)
   1.626 +			{
   1.627 +			fileTypes->push_back(EHumanCertClients);
   1.628 +			fileArg = arg.substr(OPT_HCERTCLIENTS_S.size(), arg.npos);
   1.629 +			gotFile = true;
   1.630 +			}
   1.631 +		if(arg.find(OPT_BFILECERTSTORE_L) == 0)
   1.632 +			{
   1.633 +			fileTypes->push_back(EBinFileCertStore);
   1.634 +			fileArg = arg.substr(OPT_BFILECERTSTORE_L.size(), arg.npos);
   1.635 +			gotFile = true;
   1.636 +			}
   1.637 +		if(arg.find(OPT_BFILECERTSTORE_S) == 0)
   1.638 +			{
   1.639 +			fileTypes->push_back(EBinFileCertStore);
   1.640 +			fileArg = arg.substr(OPT_BFILECERTSTORE_S.size(), arg.npos);
   1.641 +			gotFile = true;
   1.642 +			}
   1.643 +		if(arg.find(OPT_HFILECERTSTORE_L) == 0)
   1.644 +			{
   1.645 +			fileTypes->push_back(EHumanFileCertStore);
   1.646 +			fileArg = arg.substr(OPT_HFILECERTSTORE_L.size(), arg.npos);
   1.647 +			gotFile = true;
   1.648 +			}
   1.649 +		if(arg.find(OPT_HFILECERTSTORE_S) == 0)
   1.650 +			{
   1.651 +			fileTypes->push_back(EHumanFileCertStore);
   1.652 +			fileArg = arg.substr(OPT_HFILECERTSTORE_S.size(), arg.npos);
   1.653 +			gotFile = true;
   1.654 +			}
   1.655 +		if(arg.find(OPT_BSWICERTSTORE_L) == 0)
   1.656 +			{
   1.657 +			fileTypes->push_back(EBinSwiCertStore);
   1.658 +			fileArg = arg.substr(OPT_BSWICERTSTORE_L.size(), arg.npos);
   1.659 +			gotFile = true;
   1.660 +			}
   1.661 +		if(arg.find(OPT_BSWICERTSTORE_S) == 0)
   1.662 +			{
   1.663 +			fileTypes->push_back(EBinSwiCertStore);
   1.664 +			fileArg = arg.substr(OPT_BSWICERTSTORE_S.size(), arg.npos);
   1.665 +			gotFile = true;
   1.666 +			}
   1.667 +		if(arg.find(OPT_HSWICERTSTORE_L) == 0)
   1.668 +			{
   1.669 +			fileTypes->push_back(EHumanSwiCertStore);
   1.670 +			fileArg = arg.substr(OPT_HSWICERTSTORE_L.size(), arg.npos);
   1.671 +			gotFile = true;
   1.672 +			}
   1.673 +		if(arg.find(OPT_HSWICERTSTORE_S) == 0)
   1.674 +			{
   1.675 +			fileTypes->push_back(EHumanSwiCertStore);
   1.676 +			fileArg = arg.substr(OPT_HSWICERTSTORE_S.size(), arg.npos);
   1.677 +			gotFile = true;
   1.678 +			}
   1.679 +
   1.680 +		if(arg.find("--out") == 0)
   1.681 +			{
   1.682 +			files = &aOutputFiles;
   1.683 +			dirs = &aOutputDirs;
   1.684 +			fileTypes = &aOutputFileTypes;
   1.685 +			continue;
   1.686 +			}
   1.687 +
   1.688 +		if(arg.find("--in") == 0)
   1.689 +			{
   1.690 +			files = &aInputFiles;
   1.691 +			dirs = &aInputDirs;
   1.692 +			fileTypes = &aInputFileTypes;
   1.693 +			continue;
   1.694 +			}
   1.695 +
   1.696 +		if(gotFile)
   1.697 +			{
   1.698 +			files->push_back(fileArg);
   1.699 +			continue;
   1.700 +			}
   1.701 +		
   1.702 +		usage();
   1.703 +		dbg << Log::Indent() << "Unknown option " << (const char *) aArgv[argIndex] << Log::Endl();
   1.704 +		FatalError();
   1.705 +		}
   1.706 +	return;
   1.707 +}
   1.708 +
   1.709 +void ProcessCertClientFiles(const std::string &aBaseDir,
   1.710 +							const StringVector &aInputFiles,
   1.711 +							const StringVector &aInputDirs,
   1.712 +							const CertStoreFileTypeVector &aInputFileTypes,
   1.713 +							bool &aAllowDuplicates,
   1.714 +							EncDecContainer &aCertAppInfoContainer)
   1.715 +{
   1.716 +	AppMap appMap;
   1.717 +	for(int fileIndex = aInputFiles.size()-1; fileIndex >= 0 ; --fileIndex)
   1.718 +		{
   1.719 +		CertStoreFileType fileType = aInputFileTypes[fileIndex];
   1.720 +		if((fileType != EBinCertClients) && (fileType != EHumanCertClients))
   1.721 +			{
   1.722 +			continue;
   1.723 +			}
   1.724 +		
   1.725 +		// Change to correct directory
   1.726 +		ChangeDir(aBaseDir, aInputDirs[fileIndex]);
   1.727 +
   1.728 +		EncDecContainer tmpCertInfoContainer("ClientInfo", CertificateAppInfo::Factory);
   1.729 +
   1.730 +		if(fileType == EBinCertClients)
   1.731 +			{
   1.732 +			prog << Log::Indent() << "Reading binary certclients file '" << aInputFiles[fileIndex] << "'" << Log::Endl();
   1.733 +			AutoIndent ai(prog);
   1.734 +			readContainer(aInputFiles[fileIndex], false, tmpCertInfoContainer);
   1.735 +			}
   1.736 +		else
   1.737 +			{
   1.738 +			prog << Log::Indent() << "Reading human certclients file '" << aInputFiles[fileIndex] << "'" << Log::Endl();
   1.739 +			AutoIndent ai(prog);
   1.740 +			readContainer(aInputFiles[fileIndex], true, tmpCertInfoContainer);
   1.741 +			}
   1.742 +
   1.743 +		// Now merge the new file into the running store.
   1.744 +		prog << Log::Indent() << "Merging certclients data" << Log::Endl();
   1.745 +		AutoIndent ai(prog);
   1.746 +		AutoIndent ai2(dbg);
   1.747 +		for(TUint32 entryIndex = 0; entryIndex < tmpCertInfoContainer.size(); ++entryIndex)
   1.748 +			{
   1.749 +			const CertificateAppInfo &info = static_cast<const CertificateAppInfo &>(tmpCertInfoContainer[entryIndex]);
   1.750 +			std::string nname = stringFromUtf16(info.Name());
   1.751 +			//prog << Log::Indent() << "checking " << nname << Log::Endl();
   1.752 +
   1.753 +
   1.754 +			TInt32 lastIndex;
   1.755 +			std::string firstDef;
   1.756 +			if(!AppUidMap::InsertUidDefinition(info.Id().iUid, nname, fileIndex,
   1.757 +											   lastIndex, firstDef))
   1.758 +				{
   1.759 +				// Duplicate entry for UID
   1.760 +				if(nname == firstDef)
   1.761 +					{
   1.762 +					// But both entries have the same value
   1.763 +					prog << Log::Indent() << "Duplicate, but identical, entries for UID 0x" << info.Id().iUid << " '" << nname << "'." << Log::Endl();
   1.764 +					AutoIndent ai(prog);
   1.765 +					prog << Log::Indent() << "From files '" << aInputFiles[lastIndex] << "' and '" << aInputFiles[fileIndex] << "'." << Log::Endl();
   1.766 +					}
   1.767 +				else
   1.768 +					{
   1.769 +					// Entries have different values
   1.770 +					dbg << Log::Indent() << "DUPLICATE entry for UID 0x" << info.Id().iUid << Log::Endl();
   1.771 +					AutoIndent ai(dbg);
   1.772 +					dbg << Log::Indent() << "Ignoring '" << nname << "' from '"  << aInputFiles[fileIndex] << "'." << Log::Endl();
   1.773 +					dbg << Log::Indent() << "Keeping '" << firstDef << "' from '" << aInputFiles[lastIndex] << "'." << Log::Endl();
   1.774 +					if(lastIndex == fileIndex)
   1.775 +						{
   1.776 +						if(fileType == EBinCertClients)
   1.777 +							{
   1.778 +							dbg << Log::Indent() << "Both entries are in the same binary same file!" << Log::Endl();
   1.779 +							continue; // Skip adding duplicate
   1.780 +							}
   1.781 +						dbg << Log::Indent() << "Clash is within a single text configuration file!" << Log::Endl();
   1.782 +						if(!aAllowDuplicates)
   1.783 +							{
   1.784 +							FatalError();
   1.785 +							}
   1.786 +						}
   1.787 +					}
   1.788 +
   1.789 +				// Only add duplicates when debugging and the add is
   1.790 +				// from a human readable config file.
   1.791 +				if(!aAllowDuplicates || (fileType != EHumanCertClients))
   1.792 +					{
   1.793 +					continue; // Skip adding duplicate
   1.794 +					}
   1.795 +				dbg << Log::Indent() << "Adding anyway due to " << OPT_ALLOWDUPLICATES << Log::Endl();
   1.796 +				}
   1.797 +
   1.798 +			// Add entry
   1.799 +			CertificateAppInfo *newInfo = new CertificateAppInfo;
   1.800 +			*newInfo = info;
   1.801 +			aCertAppInfoContainer.push_back(newInfo);
   1.802 +			}
   1.803 +		}
   1.804 +}
   1.805 +
   1.806 +
   1.807 +
   1.808 +/**
   1.809 +   Write output files to disk
   1.810 + */
   1.811 +void GenerateOutputFiles(const EncDecContainer &aCertAppInfoContainer,
   1.812 +						 const EncDecContainer &aFileCertStoreContainer,
   1.813 +						 const EncDecContainer &aSwiCertStoreContainer,
   1.814 +						 const std::string &aBaseDir,
   1.815 +						 const StringVector &aOutputFiles, 
   1.816 +						 const StringVector &aOutputDirs,
   1.817 +						 const CertStoreFileTypeVector &aOutputFileTypes,
   1.818 +						 bool aVerbose, bool aPemOut)
   1.819 +{
   1.820 +	for(int fileIndex = aOutputFiles.size()-1; fileIndex >= 0 ; --fileIndex)
   1.821 +		{
   1.822 +		// Change to correct directory
   1.823 +		ChangeDir(aBaseDir, aOutputDirs[fileIndex]);
   1.824 +		
   1.825 +		CertStoreFileType fileType = aOutputFileTypes[fileIndex];
   1.826 +		//
   1.827 +		// Set the container and write mode to use
   1.828 +		//
   1.829 +		const EncDecContainer *container = 0;
   1.830 +		bool humanReadable = false;
   1.831 +		if(fileType == EBinCertClients)
   1.832 +			{
   1.833 +			container = &aCertAppInfoContainer;
   1.834 +			humanReadable = false;
   1.835 +			}
   1.836 +		if(fileType == EHumanCertClients)
   1.837 +			{
   1.838 +			container = &aCertAppInfoContainer;
   1.839 +			humanReadable = true;
   1.840 +			}
   1.841 +		if(fileType == EBinFileCertStore)
   1.842 +			{
   1.843 +			container = &aFileCertStoreContainer;
   1.844 +			humanReadable = false;
   1.845 +			}
   1.846 +		if(fileType == EHumanFileCertStore)
   1.847 +			{
   1.848 +			container = &aFileCertStoreContainer;
   1.849 +			humanReadable = true;
   1.850 +			}
   1.851 +		if(fileType == EBinSwiCertStore)
   1.852 +			{
   1.853 +			container = &aSwiCertStoreContainer;
   1.854 +			humanReadable = false;
   1.855 +			}
   1.856 +		if(fileType == EHumanSwiCertStore)
   1.857 +			{
   1.858 +			container = &aSwiCertStoreContainer;
   1.859 +			humanReadable = true;
   1.860 +			}
   1.861 +		
   1.862 +		if(container == 0)
   1.863 +			{
   1.864 +			// failed to decode the output file type!
   1.865 +			FatalError();
   1.866 +			}
   1.867 +		//
   1.868 +		// Write the container out
   1.869 +		//
   1.870 +		writeContainer(aOutputFiles[fileIndex].c_str(), humanReadable, aPemOut, aVerbose, *container);
   1.871 +		}
   1.872 +	return;
   1.873 +}
   1.874 +
   1.875 +
   1.876 +
   1.877 +/**
   1.878 +   ValidateLabel
   1.879 +
   1.880 +   This function maintains a map of certificate labels to input file
   1.881 +   (ie file index) and definition.
   1.882 +   
   1.883 +   If the label is NOT already defined in the map, then the function
   1.884 +   returns true, which instructs the caller to include the
   1.885 +   label/certificate in the generated store.
   1.886 +
   1.887 +   If the label is already defined in the map, then the function
   1.888 +   returns false, which instructs the caller to NOT include the
   1.889 +   label/certificate in the generated store.
   1.890 +
   1.891 +   The files on the command line are processed right to left, so if
   1.892 +   multiple definitions (for the same label) are seen, only the first
   1.893 +   will be included in the generated store.
   1.894 +
   1.895 +   The information saved in the map is used to generate helpful
   1.896 +   warning/error messages as follows:-
   1.897 +
   1.898 +   1) The saved definition is the first definition encountered, and is
   1.899 +   therefore the one which has been included in the store.
   1.900 +
   1.901 +   2) The saved file index is the index of the LAST file processed
   1.902 +   containing a definition for this label. This may be different to
   1.903 +   the one containing the first definition.
   1.904 +
   1.905 +   Consider the following sequence:-
   1.906 +
   1.907 +   First processed file - Definition for label Fred
   1.908 +   Second processed file - Another two definitions for label Fred
   1.909 +
   1.910 +   When processing the third definition (in the second file), the
   1.911 +   saved file index will be that of the second file. The code uses
   1.912 +   this to check if there are multiple definitions within a SINGLE
   1.913 +   input file, for the same label.
   1.914 +
   1.915 +   If the multiple definitions are within a single human readable
   1.916 +   file, then this is considered a fatal error, otherwise only a
   1.917 +   warning is generated.
   1.918 +
   1.919 +   Duplicate definitions in different files, generate a warning.
   1.920 + */
   1.921 +bool ValidateLabel(FCSLabelMap &aLabelMap, 
   1.922 +				   const StringVector &aInputFiles, 
   1.923 +				   CertStoreFileType aFileType,
   1.924 +				   TUint32 aFileIndex, 
   1.925 +				   const TCertLabel &aCertLabel)
   1.926 +{
   1.927 +	std::string nname = stringFromUtf16(aCertLabel);
   1.928 +	FCSLabelMap::value_type e(nname, aFileIndex);
   1.929 +	std::pair<FCSLabelMap::iterator,bool> result = aLabelMap.insert(e);
   1.930 +	if(result.second == true)
   1.931 +		{
   1.932 +		// Not a duplicate
   1.933 +		return true;
   1.934 +		}
   1.935 +	
   1.936 +	// Duplicate label entry
   1.937 +	dbg << Log::Indent() << "DUPLICATE label detected in '" << aInputFiles[aFileIndex] << "'." << Log::Endl();
   1.938 +	AutoIndent ai(dbg);
   1.939 +	dbg << Log::Indent() << "Duplicate entry for '" << e.first << "' ignored. Keeping entry from '" << aInputFiles[(*result.first).second] << "'" <<Log::Endl();
   1.940 +	if((result.first)->second == TUint32(aFileIndex))
   1.941 +		{
   1.942 +		dbg << Log::Indent() << "Both entries are in the same file." << Log::Endl();
   1.943 +		if((aFileType == EHumanFileCertStore) || (aFileType == EHumanSwiCertStore))
   1.944 +			{
   1.945 +			dbg << Log::Indent() << "FATAL error - Clash is within a single text configuration file - aborting!" << Log::Endl();
   1.946 +			FatalError();
   1.947 +			}
   1.948 +		return false; // Insert failed, keep earlier def
   1.949 +		}
   1.950 +	else
   1.951 +		{
   1.952 +		// Update file index for last definition. This is used to
   1.953 +		// detect if the last two defs were within a single file.
   1.954 +		(result.first)->second = TUint32(aFileIndex);
   1.955 +		return false; // Insert failed, keep earlier def
   1.956 +		}
   1.957 +	return false;
   1.958 +}
   1.959 +
   1.960 +void BuildSubjectToSubjectKeyIdMap(const EncDecContainer &aCertStoreContainer,
   1.961 +								   SubjectToSubjectKeyIdMap &aSubjectMap)
   1.962 +{
   1.963 +	// Collect subjectName/SubjectKeyId for all certs
   1.964 +	for(TUint32 entryIndex=0; entryIndex < aCertStoreContainer.size(); ++entryIndex)
   1.965 +		{
   1.966 +		const CertStoreEntry &entry = static_cast<const CertStoreEntry &>(aCertStoreContainer[entryIndex]);
   1.967 +		if(entry.Info().CertificateFormat() !=  EX509Certificate)
   1.968 +			{
   1.969 +			continue;
   1.970 +			}
   1.971 +
   1.972 +		std::pair<SubjectToSubjectKeyIdMap::key_type, SubjectToSubjectKeyIdMap::mapped_type> e;
   1.973 +		e.first = entry.CertSubject();
   1.974 +		e.second.iDuplicate = false;
   1.975 +		e.second.iLabel = stringFromUtf16(entry.Label());
   1.976 +		e.second.iSubjectKeyIdentifier =  entry.Info().SubjectKeyId().iHash;
   1.977 +		std::pair<SubjectToSubjectKeyIdMap::iterator, bool> result = aSubjectMap.insert(e);
   1.978 +		if(result.second == false)
   1.979 +			{
   1.980 +			dbg << Log::Indent() << "WARNING: Certificate '" << e.second.iLabel << "' has a subject name of '" << e.first << "' which clashes with certificate '" << (*result.first).second.iLabel <<"'" << Log::Endl();
   1.981 +			(*result.first).second.iDuplicate = true;
   1.982 +			}
   1.983 +		}
   1.984 +	
   1.985 +}
   1.986 +
   1.987 +
   1.988 +void SetIssuerKeyId(SubjectToSubjectKeyIdMap &aSubjectMap,
   1.989 +					EUseCertificateExtension aUseExtension,
   1.990 +					EncDecContainer &aCertStoreContainer)
   1.991 +{
   1.992 +	// Now loop across certs setting the issuer key id.
   1.993 +	for(TUint32 entryIndex=0; entryIndex < aCertStoreContainer.size(); ++entryIndex)
   1.994 +		{
   1.995 +		CertStoreEntry &entry = static_cast<CertStoreEntry &>(aCertStoreContainer[entryIndex]);
   1.996 +		if(entry.Info().CertificateFormat() !=  EX509Certificate)
   1.997 +			{
   1.998 +			continue;
   1.999 +			}
  1.1000 +		if(!entry.Info().IssuerKeyId().iAutoKey)
  1.1001 +			{
  1.1002 +			continue;
  1.1003 +			}
  1.1004 +
  1.1005 +		std::string certLabel = stringFromUtf16(entry.Label());
  1.1006 +		
  1.1007 +		prog << Log::Indent() << "Attempting to auto set IssuerIeyId for '" << certLabel << "'" << Log::Endl();
  1.1008 +
  1.1009 +		AutoIndent ai(prog);
  1.1010 +
  1.1011 +		// Lookup issuer key id in certificate extension and if found use that.
  1.1012 +		// 
  1.1013 +		// X509IssuerKeyId will always set the issuerName.
  1.1014 +		// If aIgnoreExtension is false, then it will attempt to read
  1.1015 +		// the AuthorityKeyId extension. If found (and <160bits), it
  1.1016 +		// will write the ID to issuerId and return true.
  1.1017 +		// Otherwise it will return false.
  1.1018 +		// Certificate read errors are fatal.
  1.1019 +		std::string issuerName;
  1.1020 +		TKeyIdentifier issuerId;
  1.1021 +		if(X509IssuerKeyId(aUseExtension,
  1.1022 +						   entry.CertData(), entry.Info().CertSize(),
  1.1023 +						   issuerName, issuerId))
  1.1024 +			{
  1.1025 +			// There is an authority key id extension so use its value
  1.1026 +			prog << Log::Indent() << "Using value from certificate '" << certLabel << "' extension" << Log::Endl();
  1.1027 +			entry.Info().IssuerKeyId().iHash = issuerId;
  1.1028 +			}
  1.1029 +		else
  1.1030 +			{
  1.1031 +			// No extension so lookup issuerName in the map
  1.1032 +			prog << Log::Indent() << "Looking up issuer '" << issuerName << "' in map" << Log::Endl();
  1.1033 +			SubjectToSubjectKeyIdMap::const_iterator it = aSubjectMap.find(issuerName);
  1.1034 +			if(it == aSubjectMap.end())
  1.1035 +				{
  1.1036 +				prog << Log::Indent() << "Not found - Using empty IssuerKeyId " << Log::Endl();
  1.1037 +				}
  1.1038 +			else
  1.1039 +				{
  1.1040 +				if((*it).second.iDuplicate)
  1.1041 +					{
  1.1042 +					prog << Log::Indent() << "Found - but multiple certs with matching subject name - Using empty IssuerKeyId" << Log::Endl();
  1.1043 +					}
  1.1044 +				else
  1.1045 +					{
  1.1046 +					prog << Log::Indent() << "Found - Using Subject Key of matching cert" << Log::Endl();
  1.1047 +					entry.Info().IssuerKeyId().iHash = (*it).second.iSubjectKeyIdentifier;
  1.1048 +					}
  1.1049 +				}
  1.1050 +			}
  1.1051 +		}
  1.1052 +
  1.1053 +}
  1.1054 +
  1.1055 +
  1.1056 +
  1.1057 +// End of file