CE6 Module Security

Posted by Upender Sandadi

Happy New Year to everyone!!! I hope you all had a wonderful start to the new year. This was one of those articles I had written before the year end but never got it posted. So here we go. One more aritcle on CE 6.0. This time the topic is: Module security.

In Windows CE releases previous to CE 6.0, there was a concept of trust associated with each module (dll or exe). Each module can be categorized as:

  • Loaded with “full trust” privileges: This is typically the case for a dll/exe signed with a certificate that chains to a privileged certification store on the device. In this case the module is allowed to load and the module code can also call all the APIs in the system.
  • Loaded with “run” privileges: This is typically the case for a dll/exe signed with a certificate that chains to an unprivileged certification store on the device. In this case the module is allowed to load but certain API calls (such as SetKMode) cannot be made from this module.
  • No privileges: This is typically the case if the dll/exe signed with a certificate which is not in any of the certification stores on the device or the module is not signed at all and the module is being loaded on a trust enabled system.

As you can see module trust is fully governed by the certificate (or there lack of) associated with the given module. On general embedded systems where generally certification subsystem is not in the image by default one can still limit the API calls to only those modules which are in ROM.

Now coming to CE 6.0, concept of module trust is treated slightly differently and is actually divided into two parts:

  • Load Privilege: This is used to decide if a module can be loaded or not (for example when an application calls CreateProcess or LoadLibrary to launch or load a module). Decision for this is based on whether certification module is built into the device or not. I will explain this little later.
  • API Privilege: This is used to decide if a module code can call certain APIs which are marked as kernel mode only. Decision for this is based on where the module is loaded. Any code which is loaded above 0x8000_0000 is considered to be running in kernel mode and any code which is loaded below that address is considered to be running in user mode. So whether a module can call certain APIs purely depends on in which address space the module is loaded in and has no bearing to what certificate might be associated with the given module.

Now let us look at “Load Privilege” in CE 6.0 in little bit more detail. In CE 6.0, load privilege for a module is based on the following rules:

  • Any module with ROM attribute set on the file is considered fully trusted.
  • Any module which is signed with a certificate that chains to a codesign certificate store on the device is considered fully trusted.
  • All other modules are considered “untrusted”.

Given the above rules, here are the possible ways a CE6 device can be built.

Case 1: if an OEM wants to develop a closed box solution using CE 6.0, one possible approach would be to

  • Enable SYSGEN_CERTMOD in the image
  • Do not add any certificates to the codesign store on the device
  • Ensure that all the modules which needed to run on the closed box system are in ROM.

Once an image is built with the above properties, then no third party applications or modules can be loaded on that system.

Case 2: if an OEM wants to develop a semi-closed box solution using CE 6.0, where only signed modules can be loaded in the system, then the approach would be to:

  • Enable SYSGEN_CERTMOD in the image
  • Add one or more certificates to the codesign store on the device
  • Ensure that all the modules which needed to run on this sytem are either in ROM or signed with a certificate that is in the codesign store on the device.

This would be a good solution if OEM wants to publish an SDK for their device so that ISVs can write applications targeting their platform. By enforcing that the applications be signed with an OEM certificate, OEMs can control what applications are allowed to run on the device.

Case 3: if an OEM wants to develop a completely open solution using CE 6.0, then the approach would be to:

  • Ensure that SYSGEN_CERTMOD is not set in the image.

In this case where SYSGEN_CERTMOD is not set, then all modules in the system are considered as fully trusted for load privilege and any attempt to load any module will proceed normally. Note that SYSGEN_CERTMOD just governs the load privileges for a module. Once the module is loaded what APIs the module can call depends on which mode (kernel mode or user mode) threads in that module are running in. This is given by which address space the module is loaded in. See the API call privileges notes given above.

I hope this clarifies the role certmod plays in CE6.0 images.

UPDATE (April 2nd 2007):

The default sources file in public\common\oak\drivers\security\certmod\dll lists the DLLENTRY as "DllMain". This is not a problem for CE build since that uses the settings specified in public\common\cesysgen\makefile which sets the right DLLENTRY. So if you are going to replace certmod with your own certification module, make sure you set the DLLENTRY to "_DllMainCRTStartup". This is required for evgen (library which certmod links with) to be properly initialized when certmod.dll loads.