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:

  • Use makecert.exe to create a self-signed certificate (.cer) and its private key file (.pvk). Have it stored in the CA store on creation.
    • Example: makecert -r -n "CN=My CA" -ss CA -sr CurrentUser -a sha1 -sky signature -sv MyCA.pvk MyCA.cer
  • Import the certificate in the root certificate store.
  • Use makecert.exe again to create the self-signed SPC certificate (.cer or .spc) and its private key file (.pvk). Specify the issuer certificate and private key file when doing this, to "issue" the self-signed SPC certificate from the CA authority you made.
    • Example: makecert -n "CN=My SPC" -a sha1 -sky signature -ic MyCA.cer -iv MyCA.pvk -sv MySPC.pvk MySPC.cer
  • Convert the certificate and its key into a PFX file using pvk2pfx.exe. This will be used to sign the code.
    • Example: pvk2pfx -pvk MySPC.pvk -spc MySPC.cer -pfx MySPC.pfx
  • Use cabsigntool.exe to sign the CAB file containing your code. This will sign the CAB and all the code it contains.
    • Example: cabsigntool.exe SmartDeviceCab1.cab SmartDeviceCab1.cab -f MySPC.pfx

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

  • Connect your device to Visual Studio.
  • Go to Tools -> Device Security Manager.
  • In the tabbed window that appears, hit the Certificate Management button near the top-left, under the tabs.
  • Right-click on the store you want to add a certificate to, and choose Add Certificate.
    • NOTE: The certificate you want to add must be in your personal store. If it's not in the list of the window that appears, click the Manage Certificates button and proceed to import the certificate. Highlight the certificate, and hit the Close button. The certificate should now appear in the list.
  • Choose the certificate and hit the OK button.
  • Visual Studio will add the certificate and update the list; after a few moments, you should see your chosen certificate in the store you chose.

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.

  • Create a new project within your solution for your custom setup.dll.
  • Add code to customize the Install_Init function. This is where you will need to install your certificates. You can either use the DMProcessConfigXML function, passing it a string of formatted XML containing your certificates' information, or the Microsoft Crypto APIs.
  • Sign your project output with the certificate you're importing into the privileged/SPC stores. This can be done in the project properties of each project in your solution.
  • Build the CAB file and sign it with your VeriSign publisher ID certificate.
  • Submit the CAB file to VeriSign for Microsoft Normal signing.
  • Download the signed CAB file and test it on your device.
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.

  • Create an XML file called _setup.xml. Insert into it the wap-provisioning information as described in the Custom setup.dll instructions. Then build it using makecab.exe.
  • Sign the CAB file with your VeriSign publisher ID certificate.
  • Submit your CAB file to VeriSign for Microsoft Normal signing.
  • Download the signed CAB file and deploy it to your device. You should see no warning messages.
  • Deploy your application CAB file. You will see no warning messages.

Related Links