Windows Mobile Code Signing

Mobile2Market

Mobile2Market is Microsoft's branding for a process that enables Windows Mobile applications to be signed for privileged execution on Windows Mobile devices. With it comes the "Designed for Windows Mobile" sticker and the application's addition to Microsoft's directory of "Designed for Windows Mobile" applications. It requires creating an ACS account with VeriSign ($350 for 10 signing events), filling out the Privileged Request Form, submitting your application to an independent test vendor to test the application's fitness amongst a number of Microsoft guidelines (around $400), and a lot of waiting. It's a lot of hoops and a lot of money for essentially very little value, unless you're a large enterprise software vendor. A much better route to go is self-signing, as described below.


Self-Signing

Creating the Certificates

Instead of going with a trusted third-party to issue your certificate (i.e. VeriSign and Microsoft's whole Mobile2Market obstacle course) and sign your code, you can create your own certificates - called self-signed certificates - and sign your code with those. There are a variety of ways to go about this, but the simplest one is probably using the tools available in the Windows Mobile SDK.

When creating a self-signed certificate, you can either create the certificate (an SPC certificate) by itself, or you can first create a self-signed Certificate Authority (a certificate unto itself), and then have your SPC certificate issued from that CA. That SPC certificate is then used to sign your code (this part is the same despite whatever methodology you choose). Note that in order for the signed code to access the Microsoft privileged APIs, this certificate and the CA certificate (or the SPC certificate again, since the CA certificate isn't strictly necessary) must exist in the SPC store and privileged store on the Windows Mobile device, respectively.


Steps:

Now, the code is signed. However, it won't make a difference if the code is signed if the certificate it was signed with doesn't exist in the privileged store on the device (you will still get a warning at install). There are three known ways to import the certificates prior to installing your signed CAB file on the device:

  1. Using Device Security Manager in Visual Studio 2008 to add the certificates to the privileged and SPC stores.
  2. Creating a setup.dll for your CAB installer that installs the certificates in the Install_Init function. (Needs to be tested)
  3. Creating dedicated CAB installers for your certificates and putting them in the CustomROM.

Device Security Manager

Custom Setup.dll

NOTE: For this solution to work, the CAB must be signed with a certificate that is already trusted, such as a Microsoft Normal (VeriSign unprivileged) certificate, and the code must be signed with the certificate you're importing into the privileged and SPC stores. This means you will need a VeriSign ACS Portal account to sign your CAB with.

NOTE: You can also inject provisioning XML containing your certificates into the _setup.xml file of your application cab. See Injecting Provisioning XML into a cab using VS 2005. This will still require that the CAB itself be signed by VeriSign, and the code within your CAB signed by the certificate you're importing.

Crypto API Example
      HANDLE hFile = CreateFile(L"\\MyPrivilegedCert.cer", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
      
      // create a byte array to read the contents
      DWORD cbCert = GetFileSize(hFile, NULL);
      DWORD cbRead = 0;
      BYTE *byteCert = (BYTE *)malloc(sizeof(BYTE) * cbCert);
      ReadFile(hFile, (LPVOID)byteCert, cbCert, &cbRead, NULL);

      CloseHandle(hFile);
      
      PCCERT_CONTEXT pCertCtx = CertCreateCertificateContext(
            X509_ASN_ENCODING,
            byteCert,
            cbCert);

      HCERTSTORE hCertStore = CertOpenStore (
            CERT_STORE_PROV_SYSTEM,
            0, 0,
            CERT_STORE_OPEN_EXISTING_FLAG |
            CERT_SYSTEM_STORE_LOCAL_MACHINE, L"Privileged Execution Trust Authorities");

      if (hCertStore != NULL)
      {
            // determine if the candidate certificate exists in the target store
            CertAddCertificateContextToStore (
                   hCertStore,
                   pCertCtx,
                   CERT_STORE_ADD_ALWAYS,
                   NULL);

            CertCloseStore (hCertStore, 0);
      }

      if (pCertCtx)
      {
            CertFreeCertificateContext (pCertCtx);
      }


Separate CAB Installer

NOTE: For this solution to work, the CAB must be signed with a certificate that is already trusted, such as a Microsoft Normal (VeriSign unprivileged) certificate. (The CAB installer for your application will be signed with the certificate you're importing into the privileged and SPC stores.) This means you will need a VeriSign ACS Portal account to sign your CAB with.

Related Links