Merge Bug 1301 - missing SWI certificate store and Bug 1170 - Browser root certs RCL_3 PDK_3.0.4
authorandy simpson <andrews@symbian.org>
Mon, 25 Oct 2010 16:13:35 +0100
branchRCL_3
changeset 107 c3d26e45acc2
parent 106 2d42ddd721e9 (current diff)
parent 103 e1f6ec9fb9b4 (diff)
Merge Bug 1301 - missing SWI certificate store and Bug 1170 - Browser root certs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptoservices/browserrootcertificates/browserrootcerts.mrp	Mon Oct 25 16:13:35 2010 +0100
@@ -0,0 +1,9 @@
+component browserrootcertificates
+source \sf\os\security\cryptoservices\browserrootcertificates
+notes_source \component_defs\release.src 
+
+
+#  == IPR section auto-inserted from distribution.policy files  ==
+ipr E 
+
+# == end auto-inserted section ==
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptoservices/browserrootcertificates/certconvert.py	Mon Oct 25 16:13:35 2010 +0100
@@ -0,0 +1,349 @@
+#
+# Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of the License "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+#
+# Description: 
+# Script to convert the Mozilla certificate store into the store format Symbian OS understands.
+#
+# Mozilla certificate store and its associated license is available at
+# http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1
+#
+#
+
+import string, getopt, sys, subprocess, glob, os
+
+#
+# Default input files
+#
+inFileMozillaCerts = "certdata.txt"
+inFileTrustMapping = "trustmapping.txt"
+
+#
+# Output path (don't change this!) and other temp files
+#
+outPath = ".\\"
+outFileCaCerts = "cacerts_text.txt"
+outFileCertClients = "certclients_text.txt"
+outCertAppOutput = "output.txt"
+
+#
+# Constants
+#
+ERROR_NONE = 0
+ERROR_EOF = -1
+ERROR_GENERAL = -2
+
+#
+# Class CertRecord
+#
+class CertRecord:
+    def __init__(self, file):
+        self.file = file
+        # Read over the first CKA_CLASS record
+        value = ""
+        self.ReadTokenValue("CKA_CLASS")
+        # Can we assert if value != "CKO_NETSCAPE_BUILTIN_ROOT_LIST"
+
+    # Read and parse next record, return 0 if no more records exist
+    def Next(self):
+        # Read next certificate token
+        err, value = self.ReadTokenValue("CKA_CLASS")
+        if (err == ERROR_EOF):
+            return err
+        if (err != ERROR_NONE or value != "CKO_CERTIFICATE"):
+            return err
+
+        # Read the cert label
+        err, self.certLabel = self.ReadTokenValue("CKA_LABEL")
+        if (err != ERROR_NONE):
+            return err
+
+        # Read the cert type
+        err, self.certType = self.ReadTokenValue("CKA_CERTIFICATE_TYPE")
+        if (err != ERROR_NONE):
+            return err
+
+        # Read the cert serial number
+        err, self.certSerialNum = self.ReadTokenValue("CKA_SERIAL_NUMBER")
+        if (err != ERROR_NONE):
+            return err
+
+        # Read the actual cert data (DER encoded)
+        err, self.certData = self.ReadTokenValue("CKA_VALUE")
+        if (err != ERROR_NONE):
+            return err
+
+        # Read the trust details
+        err, value = self.ReadTokenValue("CKA_CLASS")
+        if (err != ERROR_NONE or value != "CKO_NETSCAPE_TRUST"):
+            return err
+
+        # Read the trust label and match it with cert label
+        err, self.trustLabel = self.ReadTokenValue("CKA_LABEL")
+        if (err != ERROR_NONE or self.trustLabel != self.certLabel):
+            print "Certificate and Trust label mismatch or not found for cert " + self.certLabel
+            return err
+
+        # Read the SHA1 hash (aka thumbprint)
+        err, self.trustSha1Hash = self.ReadTokenValue("CKA_CERT_SHA1_HASH")
+
+        # Read the trust serial number and match it with cert serial number
+        err, self.trustSerialNum = self.ReadTokenValue("CKA_SERIAL_NUMBER")
+        if (err != ERROR_NONE or self.trustSerialNum != self.certSerialNum):
+            print "Warning: Certificate and Trust serial number mismatch or not found for cert " + self.certLabel
+
+        # Read the trust list. This has a variable token so can't use ReadTokenValue method
+        err, self.trustTrustList = self.ReadTrustValues()
+        if (err != ERROR_NONE):
+            return err
+
+        return ERROR_NONE
+
+    def ReadTrustValues(self):
+        # Keep reading lines till token "CKA_TRUST_STEP_UP_APPROVED" found
+        trustList = []
+        for line in self.file:
+            line = line.rstrip('\n')
+            fields = line.split(" ")
+            if (len(fields) == 0):
+                continue
+            if (fields[0] == "CKA_TRUST_STEP_UP_APPROVED"):
+                # Done reading trust settings
+                return ERROR_NONE, trustList
+                break
+            if (fields[1] == "CK_TRUST"):
+                if ((fields[2] == "CKT_NETSCAPE_TRUSTED_DELEGATOR")):
+                    trustList.append(fields[0].strip())
+            else:
+                # Something is wrong
+                print "Error reading trust settings. " + line
+                return ERROR_GENERAL, []
+
+        # End of file?
+        if (line == ""):
+            return ERROR_EOF, ""
+        print "Error in ReadTrustValues(). Token ('CKA_TRUST_STEP_UP_APPROVED') not found!"
+        return ERROR_GENERAL, ""
+
+    def ReadTokenValue(self, token):
+        # Keep reading lines till token found
+        for line in self.file:
+            line = line.rstrip('\n')
+            fields = line.split(" ")
+            if (len(fields) == 0):
+                continue
+            if (fields[0] == token):
+                if (fields[1] != "MULTILINE_OCTAL"):
+                    value = " ".join(fields[2:])
+                    return ERROR_NONE, value
+                else:
+                    # Read multiline octal value till END
+                    value=""
+                    for nextline in self.file:
+                        nextline = nextline.rstrip('\n')
+                        if (nextline == "END"):
+                            break
+                        if (nextline != ""):
+                            # Convert string of octal to binary data
+                            # There must be an easier way than this!
+                            octalWordList = nextline.split("\\")
+                            for octalWord in octalWordList:
+                                if (octalWord != ""):
+                                    value = value + chr(int(octalWord, 8))
+                        else:
+                            print "ReadTokenValue(" + token + ") awaiting END. Unexpected end of file!"
+                            return ERROR_EOF, ""
+                    return ERROR_NONE, value
+
+        #print "ReadTokenValue(" + token + "). Token not found!"
+        return ERROR_EOF, ""
+
+#
+# Global function ReadTrustMapping()
+#
+def ReadTrustMapping(file):
+    trustMapping = []
+    for line in file:
+        line = line.rstrip('\n')
+        if (line == "" or line[0] == "#"):
+            continue
+        fields = line.split(",")
+        if (len(fields) == 0):
+            continue
+        if ((len(fields) % 2) != 1):
+            print "Error in file '%s' in line '%s'\n" % inFileTrustMapping % line
+            return GENERAL_ERROR, [[]]
+        mozTrust = fields[0].strip()
+        for index in range(1, len(fields), 2):
+            appUID = fields[index].strip()
+            appName = fields[index + 1].strip()
+            trustMapping.append([mozTrust, appUID, appName])
+    return ERROR_NONE, trustMapping
+
+#
+# Global function ReadCommandlineArgs()
+#
+def ReadCommandlineArgs(argv):
+    try:
+        flags, args = getopt.getopt(argv[1:], "hm:t:", ["help", "mozilla=", "trust="])
+    except getopt.GetoptError, err:
+        # Print usage
+        print str(err) + "\n"
+        PrintUsage()
+        sys.exit(-1)
+    for flag, arg in flags:
+        if flag in ("-h", "--help"):
+            PrintUsage()
+            sys.exit()
+        elif flag in ("-m", "--mozilla"):
+            globals()["inFileMozillaCerts"] = arg
+        elif flag in ("-t", "--trust"):
+            globals()["inFileTrustMapping"] = arg
+    print "certconvert - This script converts the Mozilla certificate store into Symbian OS certificate store."
+    print "\nInput Mozilla store file: %s" % globals()["inFileMozillaCerts"]
+    print "Input trust mapping: %s" % globals()["inFileTrustMapping"]
+
+#
+#
+#
+def PrintUsage():
+    print "certconvert - This script converts the Mozilla certificate store into Symbian OS certificate store."
+    print "It uses certapp for the conversion so certapp must be in the path."
+    print "Usage: certconvert [-h] | [-m <file> -t <file>] [-o <outpath>]"
+    print "where:"
+    print "-h | --help\tshows this help"
+    print "-m | --mozilla\tis used to specify the Mozilla certificate store input file."
+    print "\t\tIf not specified default is taken as 'certdata.txt'."
+    print "-t | --trust\tis used to specify the input trust mapping input file."
+    print "\t\tThis file maps the trust settings from the Mozilla store to "
+    print "\t\tSymbian's applications and uids."
+    print "\t\tIf not specified default is taken as 'trustmapping.txt'."
+
+#
+# Main starts here
+#
+
+# Read and process command line arguments
+ReadCommandlineArgs(sys.argv)
+
+# First read the trust mappings file
+print "Reading trust mapping file...",
+file = open(inFileTrustMapping, "r")
+err, trustMapping = ReadTrustMapping(file)
+if (err != ERROR_NONE):
+    print "\nError reading trust mapping file!\n"
+    sys.exit(-1)
+file.close()
+print "done."
+
+print "Reading Mozilla certificate store and processing certificates",
+inFileMoz=open(inFileMozillaCerts, "r")
+record = CertRecord(inFileMoz)
+inRecNum = outRecNum = 0
+while (record.Next() == ERROR_NONE):
+    inRecNum = inRecNum + 1
+    #print "Read record %d: %s" % (inRecNum, record.certLabel)
+    # Do filtering of records (if any)
+    
+    outRecNum = outRecNum + 1
+    # Create the human readable filecertstore entry
+    if (outRecNum == 1):
+        if (os.path.exists(outPath) == False):
+            os.makedirs(outPath)
+        if (os.path.exists(outPath + "\\certs") == False):
+            os.makedirs(outPath + "\\certs")
+        outFileSym = open(outPath + outFileCaCerts, "w")
+        outFileSym.write("StartCertStoreEntries\n")
+
+    outFileSym.write("\t# Entry %d\n" % outRecNum)
+
+    # Write out the SHA1 hash of the certificate (to make it easier to compare certs)
+    # Convert to hex
+    sha1hash = ""
+    #octalWordList = record.trustSha1Hash.split("\\")
+    for index in range(0, len(record.trustSha1Hash)):
+        hexdigits = hex(ord(record.trustSha1Hash[index]))[2:]
+        hexdigits = hexdigits.zfill(2)
+        sha1hash = sha1hash + hexdigits + " "
+    outFileSym.write("\t# Thumbprint(hex) %s\n" % sha1hash)
+
+    outFileSym.write("\tStartEntry " + record.certLabel + "\n")
+    outFileSym.write("\t\tDeletable true\n")
+    outFileSym.write("\t\tFormat EX509Certificate\n")
+    outFileSym.write("\t\tCertOwnerType ECACertificate\n")
+    outFileSym.write("\t\tSubjectKeyId auto\n")
+    outFileSym.write("\t\tIssuerKeyId auto\n")
+
+    # Write out trust details
+    outFileSym.write("\t\tStartApplicationList\n")
+    for trust in record.trustTrustList:
+        # Look for the mapping
+        for mapping in trustMapping:
+            if (trust == mapping[0]):
+                # Found a mapping. Add it and keep on looking since
+                # there could be more than one app mapping
+                outFileSym.write('\t\t\tApplication "' + mapping[2] + '"\n');
+    outFileSym.write("\t\tEndApplicationList\n")
+    outFileSym.write("\t\tTrusted true\n")
+    certFileName = "certs\\\\cert%04d" % outRecNum + ".der"
+    outFileSym.write('\t\tDataFileName "' + certFileName + '"\n')
+    outFileSym.write("\tEndEntry\n\n")
+    # Write the certificate file
+    outFileCert = open(outPath + certFileName, "wb")
+    outFileCert.write(record.certData)
+    outFileCert.close()
+    print ".",
+
+if (outRecNum > 0):
+    outFileSym.write("EndCertStoreEntries\n")
+    outFileSym.close()
+print "done."
+
+# Finally create the app to uid mapping file for Symbian OS
+if (outRecNum > 0):
+    outFileSym = open(outPath + outFileCertClients, "w")
+    outFileSym.write("StartClientInfo\n")
+    for index in range(0, len(trustMapping)):
+        outFileSym.write("\t#Entry %d\n" % (index + 1))
+        outFileSym.write("\t\tUid %s\n" % trustMapping[index][1])
+        outFileSym.write('\t\tName "%s"\n' % trustMapping[index][2])
+    outFileSym.write("EndClientInfo\n")
+    outFileSym.close()
+inFileMoz.close()
+
+print "Invoking certapp tool to create the Symbian certificate store...",
+certappCmd = "certapp" + \
+             " --in --hca=" + outPath + outFileCaCerts + " --hcc=" + outPath + outFileCertClients + \
+             " --out --bca=" + outPath + "cacerts.dat" + " --bcc=" + outPath + "certclients.dat"
+
+dummyFile = open(outPath + outCertAppOutput, "w")
+p = subprocess.Popen(certappCmd, 0, None, None, dummyFile, dummyFile)
+retcode = p.wait()
+dummyFile.close()
+
+if (retcode != 0):
+    print "\ncertapp returned error code: %d" % retcode
+    print certappCmd
+    print "For details see file " + outPath + outCertAppOutput
+    print "Leaving temp files untouched for debugging"
+else:
+    print "done."
+    print "Cleaning up temp files...",
+    files = glob.glob(outPath + "certs\\*")
+    for file in files:
+       os.remove(file)
+    os.rmdir(outPath + "certs")
+    os.remove(outPath + outFileCaCerts)
+    os.remove(outPath + outFileCertClients)
+    os.remove(outPath + outCertAppOutput)
+    print "done."
+    print "Done. Read %d" % inRecNum + " certificates. Written %d" % outRecNum + " certificates.\n"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptoservices/browserrootcertificates/readme.txt	Mon Oct 25 16:13:35 2010 +0100
@@ -0,0 +1,5 @@
+This component just contains the python script to convert the Mozilla root certificate store into the file format that can be used by the Symbian OS file-based certificates store.
+
+The latest Mozilla certificate store can be obtained from http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1
+
+After fetching the above certificate store file (certdata.txt) run the script (certconvert.py --help) for more information.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptoservices/browserrootcertificates/trustmapping.txt	Mon Oct 25 16:13:35 2010 +0100
@@ -0,0 +1,21 @@
+#
+# Trust mapping file used by the certconvert.py script to match the Mozilla certificate trust to Symbian's application uid and name
+# The fomat is:
+# <Mozilla Trust Entry>[, <Symbian app UID>, <Name>
+#
+
+CKA_TRUST_DIGITAL_SIGNATURE
+CKA_TRUST_NON_REPUDIATION
+CKA_TRUST_KEY_ENCIPHERMENT
+CKA_TRUST_DATA_ENCIPHERMENT
+CKA_TRUST_KEY_AGREEMENT
+CKA_TRUST_KEY_CERT_SIGN
+CKA_TRUST_CRL_SIGN
+CKA_TRUST_SERVER_AUTH, 0x1000183D, Server Authentication, 0x1000A8B6, OCSP
+CKA_TRUST_CLIENT_AUTH
+CKA_TRUST_CODE_SIGNING, 0x101F9B28, MIDlet Installation
+CKA_TRUST_EMAIL_PROTECTION
+CKA_TRUST_IPSEC_END_SYSTEM
+CKA_TRUST_IPSEC_TUNNEL
+CKA_TRUST_IPSEC_USER
+CKA_TRUST_TIME_STAMPING
Binary file cryptoservices/rootcertificates/data/SymbianA.der has changed
Binary file cryptoservices/rootcertificates/data/SymbianB.der has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptoservices/rootcertificates/data/SymbianSignedCerts.txt	Mon Oct 25 16:13:35 2010 +0100
@@ -0,0 +1,103 @@
+# SymbianSignedCerts.txt
+#
+# Populates the SWI cert store with the Symbian Signed certificates
+
+[SymbianA]
+file = c:\rootcerts\SymbianA.der
+capability = TCB
+capability = CommDD
+capability = PowerMgmt
+capability = MultimediaDD
+capability = ReadDeviceData
+capability = WriteDeviceData
+capability = DRM
+capability = TrustedUI
+capability = ProtServ
+capability = DiskAdmin
+capability = NetworkControl
+capability = AllFiles
+capability = SwEvent
+capability = NetworkServices
+capability = LocalServices
+capability = ReadUserData
+capability = WriteUserData
+capability = Location
+capability = SurroundingsDD
+capability = UserEnvironment
+application = SWInstall
+application = SWInstallOCSP
+
+[SymbianB]
+file = c:\rootcerts\SymbianB.der
+capability = TCB
+capability = CommDD
+capability = PowerMgmt
+capability = MultimediaDD
+capability = ReadDeviceData
+capability = WriteDeviceData
+capability = DRM
+capability = TrustedUI
+capability = ProtServ
+capability = DiskAdmin
+capability = NetworkControl
+capability = AllFiles
+capability = SwEvent
+capability = NetworkServices
+capability = LocalServices
+capability = ReadUserData
+capability = WriteUserData
+capability = Location
+capability = SurroundingsDD
+capability = UserEnvironment
+application = SWInstall
+application = SWInstallOCSP
+
+[SymbianC]
+file = c:\rootcerts\SymbianC.der
+capability = TCB
+capability = CommDD
+capability = PowerMgmt
+capability = MultimediaDD
+capability = ReadDeviceData
+capability = WriteDeviceData
+capability = DRM
+capability = TrustedUI
+capability = ProtServ
+capability = DiskAdmin
+capability = NetworkControl
+capability = AllFiles
+capability = SwEvent
+capability = NetworkServices
+capability = LocalServices
+capability = ReadUserData
+capability = WriteUserData
+capability = Location
+capability = SurroundingsDD
+capability = UserEnvironment
+application = SWInstall
+application = SWInstallOCSP
+
+[SymbianD]
+file = c:\rootcerts\SymbianD.der
+capability = TCB
+capability = CommDD
+capability = PowerMgmt
+capability = MultimediaDD
+capability = ReadDeviceData
+capability = WriteDeviceData
+capability = DRM
+capability = TrustedUI
+capability = ProtServ
+capability = DiskAdmin
+capability = NetworkControl
+capability = AllFiles
+capability = SwEvent
+capability = NetworkServices
+capability = LocalServices
+capability = ReadUserData
+capability = WriteUserData
+capability = Location
+capability = SurroundingsDD
+capability = UserEnvironment
+application = SWInstall
+application = SWInstallOCSP
Binary file cryptoservices/rootcertificates/data/swicertstore.dat has changed
Binary file cryptoservices/rootcertificates/data/symbianc.der has changed
Binary file cryptoservices/rootcertificates/data/symbiand.der has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptoservices/rootcertificates/group/bld.inf	Mon Oct 25 16:13:35 2010 +0100
@@ -0,0 +1,32 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+* Exports SWI certificate store 
+*
+*/
+
+/**
+ @file
+*/
+
+PRJ_PLATFORMS
+DEFAULT
+
+PRJ_EXPORTS
+../data/swicertstore.dat  /epoc32/release/winscw/udeb/Z/resource/swicertstore.dat
+../data/swicertstore.dat  /epoc32/release/winscw/urel/Z/resource/swicertstore.dat
+../data/swicertstore.dat  /epoc32/data/z/resource/swicertstore.dat
+
+// ROMKIT includes
+rootcerts.iby 	/epoc32/rom/include/rootcerts.iby
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptoservices/rootcertificates/group/rootcerts.iby	Mon Oct 25 16:13:35 2010 +0100
@@ -0,0 +1,27 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+/**
+ @file 
+*/
+
+#ifndef __ROOTCERTS_IBY__
+#define __ROOTCERTS_IBY__
+
+data=ZRESOURCE\swicertstore.dat resource\swicertstore.dat
+
+#endif // __ROOTCERTS_IBY__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptoservices/rootcertificates/group/rootcerts.mrp	Mon Oct 25 16:13:35 2010 +0100
@@ -0,0 +1,8 @@
+component rootcerts
+source \sf\os\security\cryptoservices\rootcertificates
+exports \sf\os\security\cryptoservices\rootcertificates\group
+notes_source \component_defs\release.src 
+
+
+ipr E 
+
--- a/package_definition.xml	Wed Oct 13 16:33:20 2010 +0300
+++ b/package_definition.xml	Mon Oct 25 16:13:35 2010 +0100
@@ -68,6 +68,12 @@
       <component id="filebasedcertificateandkeystores" name="File-based Certificate and Key Stores" introduced="8.0" purpose="optional">
         <unit bldFile="cryptoservices/filebasedcertificateandkeystores/group" mrp="cryptoservices/filebasedcertificateandkeystores/group/security_filetokens.mrp"/>
       </component>
+      <component id="rootcertificates" name="Root Certificates" introduced="7.0s" purpose="optional">
+        <unit bldFile="cryptoservices/rootcertificates/group" mrp="cryptoservices/rootcertificates/group/rootcerts.mrp"/>
+      </component>
+      <component id="browserrootcertificates" name="Browser Root Certificates" introduced="symbian^2" purpose="optional">
+        <unit mrp="cryptoservices/browserrootcertificates/browserrootcerts.mrp"/>
+      </component>
       <component id="asnpkcs" name="ASN PKCS" introduced="8.0" purpose="optional">
         <unit bldFile="cryptoservices/asnpkcs/group" mrp="cryptoservices/asnpkcs/group/security_asnpkcs.mrp"/>
       </component>