NETCF follows the Windows Mobile security model described here.  The link provides a fair amount of detail, but I thought it would be useful to give the view from 10,000 feet (which in many cases should be more than enough!)

Code Signing

Code signing falls into one of three categories:

  1. Unsigned code
  2. Signed unprivileged
  3. Signed privileged

These categories are pretty straightforward.  The signing itself has no meaning without device policy to enforce different behavior for different code, which brings us to...

Security Policy

The security policy matrix can get pretty complicated.  There are a couple of basic ideas from which the matrix is built:

  1. 1-Tier vs. 2-Tier
  2. Prompt mode vs. no prompting

In 1-Tier mode, the security engine decides whether code can run or it can't.  There is no distinction between different kinds of running code: any code that can run can do anything that any other code can.

In 2-Tier mode, the security engine assigns a "Trust Level" to the code.  This level is a number (0, 1, or 2) that defines what that code can do.  Code assigned a 2 (Full Trust) can access anything on the device, including protected APIs (see Appendix B, although this list may change for the next release).  Code assigned a 1 can do anything except access these privileged APIs.  (Note that in 1-Tier mode, all code is either assigned 0 or 2, there are no processes running with a trust level of 1).

Something that is important to understand is that a process gets a trust level based on the trust level assigned to the primary executable.  The process trust level is immutable once it is set.  This means that a trusted process (assigned level 2) cannot load a library that is assigned a trust level of 1.  Why?  If the library were loaded into the process, it would inherit the process trust level, leading to possible elevation of privilege attacks.  This has an interesting side effect: an application that is given full trust has more restrictions on what libraries it can load.

Prompting allows users to override security policy when code is loaded.  You may have seen the security dialog when you run an app on Smartphone--this is generated by the security infrastructure with prompting enabled.  Answering "yes" to the security dialog effectively assigns a new trust level to a library (or executable) when it is loaded.  In 1-Tier mode, the prompt simply promotes the library to a level 2 (the only "Run" level).  In 2-Tier mode, the prompt can only promote a library to level 1.

Signing & Policy

So we've looked at signing and at the policy.  How do they relate?  Each kind of signing can be assigned different behavior by the security policy engine.  For example, a standard policy for 2-Tier security might be:

  • Signed privileged code gets a trust level of 2 (full trust).
  • Signed unprivileged code gets a trust level of 1.
  • Unsigned code generates a prompt.

A tighter policy may not let unsigned code execute under any circumstances.  A lighter one may allow any signed code to run at a trust level of 2 and may let all unsigned code run at a trust level of 1.  And so forth.  The different combinations can get pretty confusing, but breaking them down as described here can help make sense of the whole thing.