We talk a lot about security and signing apps, we don’t spend enough time talking about how it all works and how to troubleshoot failures—so, I thought it would make a good post—or two. Like jolly green Ogres, the topic of security is like an onion—you remove one layer, there’s another worthy of yet another discussion.
Why should developers care?
If you are a Windows Mobile developer and don’t spend the time to understand signatures and security on this platform, well-- it may leave you scratching your head at some point. In the desktop world, we (developers) tend to let the IT guys and administrators carry the bulk of security burden. If you want to tighten things down or open it up, you have the administrator tweak some permissions and life is good. Unless you were developing drivers or widely used ActiveX controls, most of us never had to deal with code signing in the desktop world.
In the mobile world, you can’t escape it – the underlying security model is all rooted to certs. When an operator decides to ship a new device, they work with an OEM to customize and brand the ROM image. As part of this process, they also decide what the final security policy configuration looks like and which certificates the device will honor. They typically include Mobile2Market certificates (we strongly encourage this) and their own private certs or OEM certs for management purposes. Certificates control access to anything protected on the device and policies define how a device behaves. That’s the nature of Windows Mobile security.
Okay, so how does this apply to my code?
I’m going to simplify this a bit and say that each Windows Mobile device has a certificate store called Privileged Execution Trust Authorities and another called Unprivileged Execution Trust Authorities. When code executes, we look to determine if the signature on your app roots back to certificates stored in either of these places -- then grant your trust level accordingly (okay, there's another SPC store that plays into this along with a ROLE mask but don't worry about that for now). For example, an application signed with a standard Mobile2Market certificate would link to the unprivileged store and run with standard trust. An application signed with the privileged Mobile2Market certificate would link to the privileged store and run with privileged (manager) trust. An unsigned application would be untrusted. Untrusted application are at the mercy of the device’s security policies.
The security configuration of a Windows Mobile device is actually made of up a collection of security policies. There is no single policy that controls whether a device is “locked”. Some of these you may know about and some you may not. For most developers—the ones you are really care about are 4123 (tier), 4102 (unsigned apps), 4122 (prompt), and 4097 (RAPI). There are a bunch of other policies that apply to OEMs, LAP developers, etc. The four I mention are especially important to any developer, and here’s why…
Policy 4123 controls whether you are running in a 1-tier or 2-tier security model. This may be the single most misunderstood concept in our mobile developer landscape. Today, all PPC platforms (Professional and Classic) run in 1-tier. Smartphone platforms (Standard) run in either 1 or 2-tier configurations. Simply put, this means that for any device running a 1-tier configuration—IF YOU ARE ALLOWED TO RUN, you always run with full trust regardless of your signature. This makes it very easy to do whatever you want on a 1-tier device. For a 2-tier configuration, your trust level is always determined by your signature. This means that 2-tier devices may lock down a lot of the things that seemed unrestricted on 1-tier devices—protected registry areas, certificate stores, privileged APIs, debugging support, etc.
Remember I said “If you are allowed to run”. Well, Policy 4102 determines if unsigned apps are allowed to run at all. Most commercial devices allow this, but they vary widely in terms of the 4122 policy which control whether the user is prompted when unsigned apps are launched. This is why running your unsigned app may throw “unknown publisher” prompts on some devices and not on others.
Last but not least is 4097 which controls RAPI policy. This policy can be configured one of three ways:
0 - all communication with the desktop is disabled
1 - open, all desktop communication is permitted
2 - desktop communication is restricted (limited)
Like I said, there are numerous policies but these are the ones that are likely to affect you the most…You can use the QueryPolicy API to get the value of any policy in your code and/or examine to them via [HKEY_LOCAL_MACHINE\Security\Policies\Policies] or SecurityPolicy CSP. Privileged access is generally required to alter any policy settings on a device.
Interested… what next?
If you want to dig deeper into these topics, check out this excellent whitepaper that Jason Fuller put together and spend some time looking in the SDK tools directory. We include configuration scripts (XML) to make the emulators run in various modes (to simulate many retail devices). We also include test certificates and all the configuration XML which you can examine to see how it all works – from changing individual policies to provisioning test certs.
Now that we touched on some fundamentals, let’s revisit that question – why should developers care?
In my opinion, if you want to build an app with a predicable trust level and an optimal user experience across the widest range of devices, you will want to have it signed. Unsigned apps are at the mercy of security policies. As a developer, if you don’t understand how all this works, you can burn a lot of time trying to figure it out under fire. For instance, your unsigned code may throw that “unknown publisher” prompt on some devices but not others (not a good user experience). At a lower level, if you use privileged APIs, you will need a privileged signature to work on 2-tier devices. If you want to load add-ins, context menus, etc., into system processes, you will need to be properly signed. Restricted RAPI requires that device-side components be properly signed and may restrict certain types of operations. Services and drivers must always be signed with privileged certificates (regardless of the tier configuration). Once you understand the basics, you can also easily leverage the SDK emulators and utilities to test under a variety of security configurations…and save yourself a lot of time.
Bottom line – if you spend the time to learn the security fundamentals of Windows Mobile, it will go a long way toward understanding why apps behave the way they do… and ensure your app is on its best behavior at all times. =)