Update contrib.
2 * Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
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".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
19 static const char * const sVersion = "certapp version 1.1.++";
26 #include "certclients.h"
27 #include "filecertstore.h"
28 #include "swicertstore.h"
30 #include "stringconv.h"
32 #include "appuidmap.h"
33 #include "openssl_license.h"
36 #ifdef __TOOLS2_LINUX__
41 #endif // __TOOLS2_LINUX__
43 #ifdef __TOOLS2_LINUX__
44 #define DIR_SEPARATOR "/"
46 #define DIR_SEPARATOR "\\"
49 enum CertStoreFileType
62 TUint32 iInputFileIndex;
64 typedef std::map<std::string, AppMapEntry> AppMap;
66 typedef std::map<std::string, TUint32> FCSLabelMap; // maps cert label to inputFileIndex
68 typedef std::vector<std::string> StringVector;
69 typedef std::vector<CertStoreFileType> CertStoreFileTypeVector;
71 void ProcessCommandLine(int aArgc, char **aArgv,
72 StringVector &aInputFiles,
73 StringVector &aInputDirs,
74 CertStoreFileTypeVector &aInputFileTypes,
75 StringVector &aOutputFiles,
76 StringVector &aOutputDirs,
77 CertStoreFileTypeVector &aOutputFileTypes,
78 bool &aVerbose, bool &aPemOut, bool &aAllowDuplicates);
80 void ProcessCertClientFiles(const std::string &aBaseDir,
81 const StringVector &aInputFiles,
82 const StringVector &aInputDirs,
83 const CertStoreFileTypeVector &aInputFileTypes,
84 bool &aAllowDuplicates,
85 EncDecContainer &aCertAppInfoContainer);
87 void GenerateOutputFiles(const EncDecContainer &aCertAppInfoContainer,
88 const EncDecContainer &aFileCertStoreContainer,
89 const EncDecContainer &aSwiCertStoreContainer,
90 const std::string &aBaseDir,
91 const StringVector &aOutputFiles,
92 const StringVector &aOutputDirs,
93 const CertStoreFileTypeVector &aOutputFileTypes,
94 bool aVerbose, bool aPemOut);
96 bool ValidateLabel(FCSLabelMap &aLabelMap,
97 const StringVector &aInputFiles,
98 CertStoreFileType aFileType,
100 const TCertLabel &aCertLabel);
103 struct SubjectToSubjectKeyIdEntry
107 TKeyIdentifier iSubjectKeyIdentifier;
109 typedef std::map<std::string, SubjectToSubjectKeyIdEntry> SubjectToSubjectKeyIdMap;
110 void BuildSubjectToSubjectKeyIdMap(const EncDecContainer &aCertStoreContainer,
111 SubjectToSubjectKeyIdMap &aSubjectMap);
113 void SetIssuerKeyId(SubjectToSubjectKeyIdMap &aSubjectMap,
114 EUseCertificateExtension aUseExtension,
115 EncDecContainer &aCertStoreContainer);
117 static const std::string OPT_PROGRESS("--progress=");
118 static const std::string OPT_ERRORS("--errors=");
119 static const std::string OPT_VERBOSE("--verbose");
120 static const std::string OPT_ALLOWDUPLICATES("--allowduplicates");
121 static const std::string OPT_CHDIR("--chdir=");
122 static const std::string OPT_HCERTCLIENTS_L("--hcertclients=");
123 static const std::string OPT_HCERTCLIENTS_S("--hcc=");
124 static const std::string OPT_BCERTCLIENTS_L("--bcertclients=");
125 static const std::string OPT_BCERTCLIENTS_S("--bcc=");
126 static const std::string OPT_HFILECERTSTORE_L("--hfilecertstore=");
127 static const std::string OPT_HFILECERTSTORE_S("--hca=");
128 static const std::string OPT_BFILECERTSTORE_L("--bfilecertstore=");
129 static const std::string OPT_BFILECERTSTORE_S("--bca=");
130 static const std::string OPT_HSWICERTSTORE_L("--hswicertstore=");
131 static const std::string OPT_HSWICERTSTORE_S("--hswi=");
132 static const std::string OPT_BSWICERTSTORE_L("--bswicertstore=");
133 static const std::string OPT_BSWICERTSTORE_S("--bswi=");
139 prog << "certapp: general_options file_options --out file_options" << Log::Endl();
141 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();
142 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();
144 prog << "general_options contains one or more of the following options:-" << Log::Endl();
145 prog << "\t--help|-h\tDisplay this usage message" << Log::Endl();
146 prog << "\t" << OPT_PROGRESS << "filename\tSave progress output to specified file" << Log::Endl();
147 prog << "\t" << OPT_ERRORS << "filename\tSave error output to specified file" << Log::Endl();
148 prog << "\t" << OPT_VERBOSE << "Include additional debug comments in output files" << Log::Endl();
149 prog << "\t--license Display license information" << Log::Endl();
150 prog << "\t--pemout Output certificates in PEM format (nb. format is auto-detected when reading)" << Log::Endl();
151 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();
152 prog << "An errors/progress filename of - will write to the standard output." << Log::Endl();
153 prog << "If the errors/progress filenames are identical, the output will be merged." << Log::Endl();
155 prog << "Both instances of file_options contains one or more of the following options:-" << Log::Endl();
156 prog << "\t" << OPT_HCERTCLIENTS_L << "|" << OPT_HCERTCLIENTS_S << "filename\t\tHuman readable certclients file" << Log::Endl();
157 prog << "\t" << OPT_BCERTCLIENTS_L << "|" << OPT_BCERTCLIENTS_S << "filename\t\tBinary certclients file" << Log::Endl();
159 prog << "\t" << OPT_HFILECERTSTORE_L << "|" << OPT_HFILECERTSTORE_S << "filename\tHuman readable filecertstore" << Log::Endl();
160 prog << "\t" << OPT_BFILECERTSTORE_L << "|" << OPT_BFILECERTSTORE_S << "filename\tBinary filecertstore" << Log::Endl();
162 prog << "\t" << OPT_HSWICERTSTORE_L << "|" << OPT_HSWICERTSTORE_S << "filename\tHuman readable swicertstore" << Log::Endl();
163 prog << "\t" << OPT_BSWICERTSTORE_L << "|" << OPT_BSWICERTSTORE_S << "filename\tBinary swicertstore" << Log::Endl();
165 prog << "\t" << "--out Change to specifying output files" << Log::Endl();
166 prog << "\t" << "--in Change to specifying input files" << Log::Endl();
167 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();
170 prog << "Examples" << Log::Endl();
171 prog << "Read/dump a swicertstore" << Log::Endl();
172 prog << "\tcertapp --bcertclients=certclients.dat --bswicertstore=swicertstore.dat --out --hswicertstore=swicertstore.txt" << Log::Endl();
173 prog << "Read/dump a filecertstore" << Log::Endl();
174 prog << "\tcertapp --bcertclients=certclients.dat --bfilecertstore=cacerts.dat --out --hfilecertstore=cacerts.txt" << Log::Endl();
175 prog << "Augment a filecertstore" << Log::Endl();
176 prog << "\tcertapp --bcertclients=certclients.dat --bfilecertstore=cacerts.dat --hfilecertstore=cacerts_extras.txt --out --bfilecertstore=cacerts_new.dat" << Log::Endl();
178 prog << "Device file locations" << Log::Endl();
179 prog << "ROM swicertstore - z:\\resource\\swicertstore.dat" << Log::Endl();
180 prog << "Writable swicertstore - !:\\resource\\swicertstore\\dat\\* where ! is the system drive" << Log::Endl();
181 prog << "Initial filecertstore and certclients z:\\private\\101f72a6\\cacerts.dat and certclients.dat. Copied to sys drive on first use." << Log::Endl();
182 prog << "Filecertstore !:\\private\\101f72a6\\cacerts.dat and certclients.dat. where ! is the system drive." << Log::Endl();
185 void ChangeDir(const std::string &aBaseDir, const std::string &aRelativeDir)
187 std::string dir(aBaseDir);
188 if(aRelativeDir != ".")
190 // Build dir to create and change into
191 dir.append(DIR_SEPARATOR);
192 dir.append(aRelativeDir);
195 prog << Log::Indent() << "Setting dir to " << dir << Log::Endl();
197 (void) mkdir(dir.c_str(),0755); // May already exist so no need to check return code
199 (void) mkdir(dir.c_str()); // May already exist so no need to check return code
201 if(chdir(dir.c_str()) < 0)
203 dbg << Log::Indent() << "failed to change dir to " << dir << Log::Endl();
209 int main(int argc, char **argv)
211 dbg.SetStream(&std::cout);
212 prog.SetStream(&std::cout);
217 prog << sVersion << " Use -h for help." << Log::Endl();
220 StringVector inputFiles;
221 StringVector inputDirs;
222 CertStoreFileTypeVector inputFileTypes;
224 StringVector outputFiles;
225 StringVector outputDirs;
226 CertStoreFileTypeVector outputFileTypes;
229 bool verbose = false;
231 bool allowDuplicates = false;
233 // Process all the command line options and file arguments
234 ProcessCommandLine(argc, argv,
235 inputFiles, inputDirs, inputFileTypes,
236 outputFiles, outputDirs, outputFileTypes,
237 verbose, pemOut, allowDuplicates);
240 // Save current directory
243 char tmp[FILENAME_MAX];
244 if(getcwd(tmp, FILENAME_MAX) == 0)
246 dbg << Log::Indent() << "Failed to read current dir" << Log::Endl();
254 // Process input files starting with certclient files and working from right to left
256 EncDecContainer certAppInfoContainer("ClientInfo", CertificateAppInfo::Factory);
257 ProcessCertClientFiles(baseDir, inputFiles, inputDirs, inputFileTypes,
259 certAppInfoContainer);
262 // Generate config data for application uid EncDecEnum object in AppUidListEntry
263 AppUidMap::GenerateEnumEntries();
266 // Process remaining input files working from right to left
268 EncDecContainer fileCertStoreContainer("CertStoreEntries", CertStoreEntry::Factory);
269 FCSLabelMap fcsLabels;
270 EncDecContainer swiCertStoreContainer("SwiCertStoreEntries", SwiCertStoreEntry::Factory);
271 FCSLabelMap swiLabels;
272 for(int fileIndex = inputFiles.size()-1; fileIndex >= 0 ; --fileIndex)
274 CertStoreFileType fileType = inputFileTypes[fileIndex];
275 if((fileType == EBinFileCertStore) || (fileType == EHumanFileCertStore))
277 // Change to correct directory
278 ChangeDir(baseDir, inputDirs[fileIndex]);
280 EncDecContainer tmpFileCertStoreContainer("CertStoreEntries", CertStoreEntry::Factory);
281 if(fileType == EBinFileCertStore)
283 prog << "Reading binary filecertstore file '" << inputFiles[fileIndex] << "'" << Log::Endl();
285 readContainer(inputFiles[fileIndex], false, tmpFileCertStoreContainer);
287 if(fileType == EHumanFileCertStore)
289 prog << "Reading human filecertstore file '" << inputFiles[fileIndex] << "'" << Log::Endl();
291 readContainer(inputFiles[fileIndex], true, tmpFileCertStoreContainer);
294 // Now merge the new file into the running store.
295 prog << Log::Indent() << "Merging filecertstore data" << Log::Endl();
297 for(TUint32 entryIndex = 0; entryIndex < tmpFileCertStoreContainer.size(); ++entryIndex)
299 const CertStoreEntry &entry = static_cast<const CertStoreEntry &>(tmpFileCertStoreContainer[entryIndex]);
300 std::string nname = stringFromUtf16(entry.Label());
302 if(!ValidateLabel(fcsLabels, inputFiles, fileType, fileIndex, entry.Label()))
304 // Duplicate detected
305 if(!allowDuplicates || (fileType == EBinFileCertStore))
307 continue; // Skip adding duplicate
309 // Only allow duplicates if debugging and reading
310 // human readable config file.
311 dbg << Log::Indent() << "Adding anyway due to " << OPT_ALLOWDUPLICATES << Log::Endl();
315 CertStoreEntry *newEntry = new CertStoreEntry;
317 fileCertStoreContainer.push_back(newEntry);
323 if((fileType == EBinSwiCertStore) || (fileType == EHumanSwiCertStore))
325 // Change to correct directory
326 ChangeDir(baseDir, inputDirs[fileIndex]);
328 EncDecContainer tmpSwiCertStoreContainer("SwiCertStoreEntries", SwiCertStoreEntry::Factory);
329 if(fileType == EBinSwiCertStore)
331 prog << "Reading binary swicertstore file '" << inputFiles[fileIndex] << "'" << Log::Endl();
333 readContainer(inputFiles[fileIndex], false, tmpSwiCertStoreContainer);
335 if(fileType == EHumanSwiCertStore)
337 prog << "Reading human swicertstore file '" << inputFiles[fileIndex] << "'" << Log::Endl();
339 readContainer(inputFiles[fileIndex], true, tmpSwiCertStoreContainer);
342 // Now merge the new file into the running store.
343 prog << Log::Indent() << "Merging swicerstore data" << Log::Endl();
345 for(TUint32 entryIndex = 0; entryIndex < tmpSwiCertStoreContainer.size(); ++entryIndex)
347 const SwiCertStoreEntry &entry = static_cast<const SwiCertStoreEntry &>(tmpSwiCertStoreContainer[entryIndex]);
348 std::string nname = stringFromUtf16(entry.Label());
350 if(!ValidateLabel(swiLabels, inputFiles, fileType, fileIndex, entry.Label()))
352 // Duplicate detected
353 if(!allowDuplicates || (fileType == EBinSwiCertStore))
355 continue; // Skip adding duplicate
357 // Only allow duplicates if debugging and reading
358 // human readable config file.
359 dbg << Log::Indent() << "Adding anyway due to " << OPT_ALLOWDUPLICATES << Log::Endl();
363 SwiCertStoreEntry *newEntry = new SwiCertStoreEntry;
365 swiCertStoreContainer.push_back(newEntry);
371 // Fix Certificate IDs in fileCertStoreContainer
372 for(TUint32 entryIndex=0; entryIndex < fileCertStoreContainer.size(); ++entryIndex)
374 CertStoreEntry &entry = static_cast<CertStoreEntry &>(fileCertStoreContainer[entryIndex]);
375 entry.Info().SetOutputCertificateId(entryIndex);
378 // Fix Certificate IDs in swicertstore container.
379 for(TUint32 entryIndex=0; entryIndex < swiCertStoreContainer.size(); ++entryIndex)
381 SwiCertStoreEntry &entry = static_cast<SwiCertStoreEntry &>(swiCertStoreContainer[entryIndex]);
382 entry.Info().SetOutputCertificateId(entryIndex);
386 // Fix auto IssuerKeyId values
388 SubjectToSubjectKeyIdMap subjectMap;
390 // Fix IssuerKeyId values in swiCertStoreContainer
392 // We do not use the AuthorityKeyId extension and only consider
393 // certificates in swi certstores.
395 // First map all the SWI certificate subject names to SubjectKeyId values
396 BuildSubjectToSubjectKeyIdMap(swiCertStoreContainer, subjectMap);
397 // Now update IssuerKeyId fields which are set to auto.
398 // The AuthorityKeyId extension value will be ignored.
399 // The SubjectKeyId of a matching certificate (if there is a
400 // single match on issuer name) in the swi cert store will be
402 SetIssuerKeyId(subjectMap, KIgnoreCertificateExtension, swiCertStoreContainer);
406 // Fix IssuerKeyId values in fileCertStoreContainer
408 // Add all filecertstore certificates to the
409 // subjectName/SubjectKeyId map
410 BuildSubjectToSubjectKeyIdMap(fileCertStoreContainer, subjectMap);
411 // Now update IssuerKeyId fields which are set to auto. If an the
412 // AuthorityKeyId extension is present and <160bits use it,
413 // otherwise use the SubjectKeyId of the matching certificate (if
414 // there is a single match on issuer name).
415 SetIssuerKeyId(subjectMap, KUseCertificateExtension, fileCertStoreContainer);
418 // Now generate output files
420 GenerateOutputFiles(certAppInfoContainer, fileCertStoreContainer, swiCertStoreContainer,
421 baseDir, outputFiles, outputDirs, outputFileTypes, verbose, pemOut);
427 dbg << Log::Indent() << "C++ expection!" << Log::Endl();
431 prog << Log::Indent() << "Normal exit" << Log::Endl();
432 prog.Stream().flush();
433 dbg.Stream().flush();
440 void ProcessCommandLine(int aArgc, char **aArgv,
441 StringVector &aInputFiles, StringVector &aInputDirs, CertStoreFileTypeVector &aInputFileTypes,
442 StringVector &aOutputFiles, StringVector &aOutputDirs, CertStoreFileTypeVector &aOutputFileTypes,
443 bool &aVerbose, bool &aPemOut, bool &aAllowDuplicates)
445 std::string progressFile("-");
446 static std::fstream sProgressStream;
448 std::string dbgFile("-");
449 static std::fstream sDbgStream;
451 StringVector *files = &aInputFiles;
452 StringVector *dirs = &aInputDirs;
453 CertStoreFileTypeVector *fileTypes = &aInputFileTypes;
456 // Process overall arguments (-h --progress --errors)
457 for(; argIndex < aArgc; ++argIndex)
459 std::string arg(aArgv[argIndex]);
461 if(arg == "--license")
463 prog << sVersion << Log::Endl();
464 prog << "Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies)." << Log::Endl();
465 prog << "All rights reserved." << Log::Endl();
466 prog << "This component and the accompanying materials are made available" << Log::Endl();
467 prog << "under the terms of the License \"Eclipse Public License v1.0\"" << Log::Endl();
468 prog << "which accompanies this distribution, and is available" << Log::Endl();
469 prog << "at the URL \"http://www.eclipse.org/legal/epl-v10.html\"." << Log::Endl();
470 prog << "Initial Contributors:" << Log::Endl();
471 prog << "Nokia Corporation - initial contribution." << Log::Endl() << Log::Endl();
473 prog << "Linked against openssl. Credits and license for openssl follow:-" << Log::Endl();
474 prog << openssl_license << Log::Endl();
479 if(arg == OPT_VERBOSE)
481 prog << "Enabling additional output file comments" << Log::Endl();
487 if(arg == "--pemout")
489 prog << "Setting output certificate format to PEM" << Log::Endl();
495 if(arg == OPT_ALLOWDUPLICATES)
497 prog << "Allowing addition of duplicate labels in stores and UIDs in certclients when reading human readable input (testing ONLY)" << Log::Endl();
498 aAllowDuplicates = true;
503 if((arg.find(OPT_PROGRESS) == 0) ||
504 (arg.find(OPT_ERRORS) == 0))
506 // The following logic is required so that if both streams
507 // are set to the same destination we share a streams
508 // object and hence avoid buffering issues.
509 std::string *thisFile;
510 std::fstream *thisStream;
512 std::string *otherFile;
513 std::fstream *otherStream;
516 if(arg.find(OPT_PROGRESS) == 0)
518 thisFile = &progressFile;
519 thisStream = &sProgressStream;
521 otherFile = &dbgFile;
522 otherStream = &sDbgStream;
525 *thisFile = arg.substr(OPT_PROGRESS.size(), arg.npos);
530 thisStream = &sDbgStream;
532 otherFile = &progressFile;
533 otherStream = &sProgressStream;
536 *thisFile = arg.substr(OPT_ERRORS.size(), arg.npos);
539 if(*thisFile == *otherFile)
541 // Reuse existing stream. This avoids two streams opening the same file...
542 thisLog->SetStream(&otherLog->Stream());
546 // Need to open a new stream
547 if(thisStream->is_open()) thisStream->close();
550 thisLog->SetStream(&std::cout);
554 OpenUtf8FStreamForWrite(*thisStream, thisFile->c_str());
555 if(thisStream->fail())
559 dbg.SetStream(&std::cout);
561 dbg << Log::Indent() << "Failed to open log file specified by " << aArgv[argIndex-1] << " '" << *thisFile << "'" << Log::Endl();
564 thisLog->SetStream(thisStream);
568 if((strcmp(aArgv[argIndex], "--help") == 0) || (strcmp(aArgv[argIndex], "-h") == 0))
574 // Not a general option, probably an input file...
578 // Process main arguments
579 for(; argIndex < aArgc; ++argIndex)
581 std::string arg(aArgv[argIndex]);
583 bool gotFile = false;
584 if((strcmp(aArgv[argIndex], "--help") == 0) || (strcmp(aArgv[argIndex], "-h") == 0))
590 if(arg.find(OPT_CHDIR) == 0)
592 dirs->push_back(arg.substr(OPT_CHDIR.size(), arg.npos));
593 // Move to next option
595 if(argIndex >= aArgc) break;
596 arg = aArgv[argIndex];
600 dirs->push_back(".");
604 if(arg.find(OPT_BCERTCLIENTS_L) == 0)
606 fileTypes->push_back(EBinCertClients);
607 fileArg = arg.substr(OPT_BCERTCLIENTS_L.size(), arg.npos);
610 if(arg.find(OPT_BCERTCLIENTS_S) == 0)
612 fileTypes->push_back(EBinCertClients);
613 fileArg = arg.substr(OPT_BCERTCLIENTS_S.size(), arg.npos);
616 if(arg.find(OPT_HCERTCLIENTS_L) == 0)
618 fileTypes->push_back(EHumanCertClients);
619 fileArg = arg.substr(OPT_HCERTCLIENTS_L.size(), arg.npos);
622 if(arg.find(OPT_HCERTCLIENTS_S) == 0)
624 fileTypes->push_back(EHumanCertClients);
625 fileArg = arg.substr(OPT_HCERTCLIENTS_S.size(), arg.npos);
628 if(arg.find(OPT_BFILECERTSTORE_L) == 0)
630 fileTypes->push_back(EBinFileCertStore);
631 fileArg = arg.substr(OPT_BFILECERTSTORE_L.size(), arg.npos);
634 if(arg.find(OPT_BFILECERTSTORE_S) == 0)
636 fileTypes->push_back(EBinFileCertStore);
637 fileArg = arg.substr(OPT_BFILECERTSTORE_S.size(), arg.npos);
640 if(arg.find(OPT_HFILECERTSTORE_L) == 0)
642 fileTypes->push_back(EHumanFileCertStore);
643 fileArg = arg.substr(OPT_HFILECERTSTORE_L.size(), arg.npos);
646 if(arg.find(OPT_HFILECERTSTORE_S) == 0)
648 fileTypes->push_back(EHumanFileCertStore);
649 fileArg = arg.substr(OPT_HFILECERTSTORE_S.size(), arg.npos);
652 if(arg.find(OPT_BSWICERTSTORE_L) == 0)
654 fileTypes->push_back(EBinSwiCertStore);
655 fileArg = arg.substr(OPT_BSWICERTSTORE_L.size(), arg.npos);
658 if(arg.find(OPT_BSWICERTSTORE_S) == 0)
660 fileTypes->push_back(EBinSwiCertStore);
661 fileArg = arg.substr(OPT_BSWICERTSTORE_S.size(), arg.npos);
664 if(arg.find(OPT_HSWICERTSTORE_L) == 0)
666 fileTypes->push_back(EHumanSwiCertStore);
667 fileArg = arg.substr(OPT_HSWICERTSTORE_L.size(), arg.npos);
670 if(arg.find(OPT_HSWICERTSTORE_S) == 0)
672 fileTypes->push_back(EHumanSwiCertStore);
673 fileArg = arg.substr(OPT_HSWICERTSTORE_S.size(), arg.npos);
677 if(arg.find("--out") == 0)
679 files = &aOutputFiles;
681 fileTypes = &aOutputFileTypes;
685 if(arg.find("--in") == 0)
687 files = &aInputFiles;
689 fileTypes = &aInputFileTypes;
695 files->push_back(fileArg);
700 dbg << Log::Indent() << "Unknown option " << (const char *) aArgv[argIndex] << Log::Endl();
706 void ProcessCertClientFiles(const std::string &aBaseDir,
707 const StringVector &aInputFiles,
708 const StringVector &aInputDirs,
709 const CertStoreFileTypeVector &aInputFileTypes,
710 bool &aAllowDuplicates,
711 EncDecContainer &aCertAppInfoContainer)
714 for(int fileIndex = aInputFiles.size()-1; fileIndex >= 0 ; --fileIndex)
716 CertStoreFileType fileType = aInputFileTypes[fileIndex];
717 if((fileType != EBinCertClients) && (fileType != EHumanCertClients))
722 // Change to correct directory
723 ChangeDir(aBaseDir, aInputDirs[fileIndex]);
725 EncDecContainer tmpCertInfoContainer("ClientInfo", CertificateAppInfo::Factory);
727 if(fileType == EBinCertClients)
729 prog << Log::Indent() << "Reading binary certclients file '" << aInputFiles[fileIndex] << "'" << Log::Endl();
731 readContainer(aInputFiles[fileIndex], false, tmpCertInfoContainer);
735 prog << Log::Indent() << "Reading human certclients file '" << aInputFiles[fileIndex] << "'" << Log::Endl();
737 readContainer(aInputFiles[fileIndex], true, tmpCertInfoContainer);
740 // Now merge the new file into the running store.
741 prog << Log::Indent() << "Merging certclients data" << Log::Endl();
744 for(TUint32 entryIndex = 0; entryIndex < tmpCertInfoContainer.size(); ++entryIndex)
746 const CertificateAppInfo &info = static_cast<const CertificateAppInfo &>(tmpCertInfoContainer[entryIndex]);
747 std::string nname = stringFromUtf16(info.Name());
748 //prog << Log::Indent() << "checking " << nname << Log::Endl();
752 std::string firstDef;
753 if(!AppUidMap::InsertUidDefinition(info.Id().iUid, nname, fileIndex,
754 lastIndex, firstDef))
756 // Duplicate entry for UID
757 if(nname == firstDef)
759 // But both entries have the same value
760 prog << Log::Indent() << "Duplicate, but identical, entries for UID 0x" << info.Id().iUid << " '" << nname << "'." << Log::Endl();
762 prog << Log::Indent() << "From files '" << aInputFiles[lastIndex] << "' and '" << aInputFiles[fileIndex] << "'." << Log::Endl();
766 // Entries have different values
767 dbg << Log::Indent() << "DUPLICATE entry for UID 0x" << info.Id().iUid << Log::Endl();
769 dbg << Log::Indent() << "Ignoring '" << nname << "' from '" << aInputFiles[fileIndex] << "'." << Log::Endl();
770 dbg << Log::Indent() << "Keeping '" << firstDef << "' from '" << aInputFiles[lastIndex] << "'." << Log::Endl();
771 if(lastIndex == fileIndex)
773 if(fileType == EBinCertClients)
775 dbg << Log::Indent() << "Both entries are in the same binary same file!" << Log::Endl();
776 continue; // Skip adding duplicate
778 dbg << Log::Indent() << "Clash is within a single text configuration file!" << Log::Endl();
779 if(!aAllowDuplicates)
786 // Only add duplicates when debugging and the add is
787 // from a human readable config file.
788 if(!aAllowDuplicates || (fileType != EHumanCertClients))
790 continue; // Skip adding duplicate
792 dbg << Log::Indent() << "Adding anyway due to " << OPT_ALLOWDUPLICATES << Log::Endl();
796 CertificateAppInfo *newInfo = new CertificateAppInfo;
798 aCertAppInfoContainer.push_back(newInfo);
806 Write output files to disk
808 void GenerateOutputFiles(const EncDecContainer &aCertAppInfoContainer,
809 const EncDecContainer &aFileCertStoreContainer,
810 const EncDecContainer &aSwiCertStoreContainer,
811 const std::string &aBaseDir,
812 const StringVector &aOutputFiles,
813 const StringVector &aOutputDirs,
814 const CertStoreFileTypeVector &aOutputFileTypes,
815 bool aVerbose, bool aPemOut)
817 for(int fileIndex = aOutputFiles.size()-1; fileIndex >= 0 ; --fileIndex)
819 // Change to correct directory
820 ChangeDir(aBaseDir, aOutputDirs[fileIndex]);
822 CertStoreFileType fileType = aOutputFileTypes[fileIndex];
824 // Set the container and write mode to use
826 const EncDecContainer *container = 0;
827 bool humanReadable = false;
828 if(fileType == EBinCertClients)
830 container = &aCertAppInfoContainer;
831 humanReadable = false;
833 if(fileType == EHumanCertClients)
835 container = &aCertAppInfoContainer;
836 humanReadable = true;
838 if(fileType == EBinFileCertStore)
840 container = &aFileCertStoreContainer;
841 humanReadable = false;
843 if(fileType == EHumanFileCertStore)
845 container = &aFileCertStoreContainer;
846 humanReadable = true;
848 if(fileType == EBinSwiCertStore)
850 container = &aSwiCertStoreContainer;
851 humanReadable = false;
853 if(fileType == EHumanSwiCertStore)
855 container = &aSwiCertStoreContainer;
856 humanReadable = true;
861 // failed to decode the output file type!
865 // Write the container out
867 writeContainer(aOutputFiles[fileIndex].c_str(), humanReadable, aPemOut, aVerbose, *container);
877 This function maintains a map of certificate labels to input file
878 (ie file index) and definition.
880 If the label is NOT already defined in the map, then the function
881 returns true, which instructs the caller to include the
882 label/certificate in the generated store.
884 If the label is already defined in the map, then the function
885 returns false, which instructs the caller to NOT include the
886 label/certificate in the generated store.
888 The files on the command line are processed right to left, so if
889 multiple definitions (for the same label) are seen, only the first
890 will be included in the generated store.
892 The information saved in the map is used to generate helpful
893 warning/error messages as follows:-
895 1) The saved definition is the first definition encountered, and is
896 therefore the one which has been included in the store.
898 2) The saved file index is the index of the LAST file processed
899 containing a definition for this label. This may be different to
900 the one containing the first definition.
902 Consider the following sequence:-
904 First processed file - Definition for label Fred
905 Second processed file - Another two definitions for label Fred
907 When processing the third definition (in the second file), the
908 saved file index will be that of the second file. The code uses
909 this to check if there are multiple definitions within a SINGLE
910 input file, for the same label.
912 If the multiple definitions are within a single human readable
913 file, then this is considered a fatal error, otherwise only a
914 warning is generated.
916 Duplicate definitions in different files, generate a warning.
918 bool ValidateLabel(FCSLabelMap &aLabelMap,
919 const StringVector &aInputFiles,
920 CertStoreFileType aFileType,
922 const TCertLabel &aCertLabel)
924 std::string nname = stringFromUtf16(aCertLabel);
925 FCSLabelMap::value_type e(nname, aFileIndex);
926 std::pair<FCSLabelMap::iterator,bool> result = aLabelMap.insert(e);
927 if(result.second == true)
933 // Duplicate label entry
934 dbg << Log::Indent() << "DUPLICATE label detected in '" << aInputFiles[aFileIndex] << "'." << Log::Endl();
936 dbg << Log::Indent() << "Duplicate entry for '" << e.first << "' ignored. Keeping entry from '" << aInputFiles[(*result.first).second] << "'" <<Log::Endl();
937 if((result.first)->second == TUint32(aFileIndex))
939 dbg << Log::Indent() << "Both entries are in the same file." << Log::Endl();
940 if((aFileType == EHumanFileCertStore) || (aFileType == EHumanSwiCertStore))
942 dbg << Log::Indent() << "FATAL error - Clash is within a single text configuration file - aborting!" << Log::Endl();
945 return false; // Insert failed, keep earlier def
949 // Update file index for last definition. This is used to
950 // detect if the last two defs were within a single file.
951 (result.first)->second = TUint32(aFileIndex);
952 return false; // Insert failed, keep earlier def
957 void BuildSubjectToSubjectKeyIdMap(const EncDecContainer &aCertStoreContainer,
958 SubjectToSubjectKeyIdMap &aSubjectMap)
960 // Collect subjectName/SubjectKeyId for all certs
961 for(TUint32 entryIndex=0; entryIndex < aCertStoreContainer.size(); ++entryIndex)
963 const CertStoreEntry &entry = static_cast<const CertStoreEntry &>(aCertStoreContainer[entryIndex]);
964 if(entry.Info().CertificateFormat() != EX509Certificate)
969 std::pair<SubjectToSubjectKeyIdMap::key_type, SubjectToSubjectKeyIdMap::mapped_type> e;
970 e.first = entry.CertSubject();
971 e.second.iDuplicate = false;
972 e.second.iLabel = stringFromUtf16(entry.Label());
973 e.second.iSubjectKeyIdentifier = entry.Info().SubjectKeyId().iHash;
974 std::pair<SubjectToSubjectKeyIdMap::iterator, bool> result = aSubjectMap.insert(e);
975 if(result.second == false)
977 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();
978 (*result.first).second.iDuplicate = true;
985 void SetIssuerKeyId(SubjectToSubjectKeyIdMap &aSubjectMap,
986 EUseCertificateExtension aUseExtension,
987 EncDecContainer &aCertStoreContainer)
989 // Now loop across certs setting the issuer key id.
990 for(TUint32 entryIndex=0; entryIndex < aCertStoreContainer.size(); ++entryIndex)
992 CertStoreEntry &entry = static_cast<CertStoreEntry &>(aCertStoreContainer[entryIndex]);
993 if(entry.Info().CertificateFormat() != EX509Certificate)
997 if(!entry.Info().IssuerKeyId().iAutoKey)
1002 std::string certLabel = stringFromUtf16(entry.Label());
1004 prog << Log::Indent() << "Attempting to auto set IssuerIeyId for '" << certLabel << "'" << Log::Endl();
1006 AutoIndent ai(prog);
1008 // Lookup issuer key id in certificate extension and if found use that.
1010 // X509IssuerKeyId will always set the issuerName.
1011 // If aIgnoreExtension is false, then it will attempt to read
1012 // the AuthorityKeyId extension. If found (and <160bits), it
1013 // will write the ID to issuerId and return true.
1014 // Otherwise it will return false.
1015 // Certificate read errors are fatal.
1016 std::string issuerName;
1017 TKeyIdentifier issuerId;
1018 if(X509IssuerKeyId(aUseExtension,
1019 entry.CertData(), entry.Info().CertSize(),
1020 issuerName, issuerId))
1022 // There is an authority key id extension so use its value
1023 prog << Log::Indent() << "Using value from certificate '" << certLabel << "' extension" << Log::Endl();
1024 entry.Info().IssuerKeyId().iHash = issuerId;
1028 // No extension so lookup issuerName in the map
1029 prog << Log::Indent() << "Looking up issuer '" << issuerName << "' in map" << Log::Endl();
1030 SubjectToSubjectKeyIdMap::const_iterator it = aSubjectMap.find(issuerName);
1031 if(it == aSubjectMap.end())
1033 prog << Log::Indent() << "Not found - Using empty IssuerKeyId " << Log::Endl();
1037 if((*it).second.iDuplicate)
1039 prog << Log::Indent() << "Found - but multiple certs with matching subject name - Using empty IssuerKeyId" << Log::Endl();
1043 prog << Log::Indent() << "Found - Using Subject Key of matching cert" << Log::Endl();
1044 entry.Info().IssuerKeyId().iHash = (*it).second.iSubjectKeyIdentifier;