Many years people believed that enrolling user certificate into Windows Mobile is possible only through PC connected to corporate network and ActiveSync connection to device. Unfortunately such a solution requires a bit skilled user and foreclose possibility of automation process or over-the-air provisioning.

CertificateEnroller CSP

Luckily in Windows Mobile 6.0 new configuration service provider was introduced. CertificateEnroller CSP enables installation and enrollment of certificates overt-the-air. It’s definitely worth to read the reference page on MSDN to get a better idea of what CertificateEnroller can do.

Let’s assume following scenario. Certification authority service is running on Windows Server with URL dc.intra.contoso.com and Windows Mobile device is able to reach this server. Now it’s desired to enroll user certificate for user pavel into device using the certificate template called user. Following provisioning XML utilize CertificateEnroller to perform this operation.

<wap-provisioningdoc>
    <characteristic type="CertificateEnroller">
       <characteristic type="Configuration">
          <characteristic type="PERSONAL_CERT">                    
                    <parm name="ServerName" value="dc.intra.contoso.com" />
                    <parm name="Template" value="user"/>             
                    <parm name="NoSSL" value="1" datatype="boolean"/>
          </characteristic>
       </characteristic>
       <characteristic type="Operation">
          <characteristic type="Enroll">
             <characteristic type="DC5BD3D0-C0E8-4c42-8516-09882DBD2769">
                <parm name="CertificateTypeFriendlyName" value="PERSONAL_CERT"/>
                <parm name="Username" value="pavel" />
                <parm name="Password" value="P@ssw0rd" />                
             </characteristic>
          </characteristic>
       </characteristic>
    </characteristic>
</wap-provisioningdoc>

Check the enrollment status

In the previous XML there is a GUID string starting with DC5BD3D0-C0E8-4c…. This is unique identifier for certificate to be enrolled. It’s not necessary to use string in valid GUID format, the identifier can be any unique value. It’s obvious that enrolling another certificate will need another unique identifier! If the enrollment is done from application code that invokes previous XML, identifier can be used to track status of enrollment process. Following XMLs shows query and result for enrollment process.

<wap-provisioningdoc>
    <characteristic type="CertificateEnroller">
        <characteristic type="Operation">
            <characteristic type="Enroll">
                <characteristic type="DC5BD3D0-C0E8-4c42-8516-09882DBD2769">
                    <parm-query name="Status" />
                    <parm-query name="EnrolledCertificateHash" />
                </characteristic>
            </characteristic>
        </characteristic>
    </characteristic>
</wap-provisioningdoc>
<wap-provisioningdoc>
  <characteristic type="CertificateEnroller">
    <characteristic type="Operation">
      <characteristic type="Enroll">
        <characteristic type="DC5BD3D0-C0E8-4c42-8516-09882DBD2769">
          <parm name="Status" value="Success"/>
          <parm name="EnrolledCertificateHash" value="FFD8E1FEC106BBE220B03051979883B0B70C2325"/>
        </characteristic>
      </characteristic>
    </characteristic>
  </characteristic>
</wap-provisioningdoc>

Values of the Status parameter can be InProgress, Success or Error. The blank Status means that the query was made to fast after the enrollment command.

When operation ends successfully, the EnrolledCertificateHash parameter will be filled with the certificate hash. Such a hash can be used to query MY certificate store to get details about the certificate. Details can be obtained using certificate applet in Settings->System menu. Following XMLs shows query for certificate in the store and the result.

<wap-provisioningdoc>
    <characteristic type="CertificateStore"> 
       <characteristic type="MY">
            <characteristic-query type="FFD8E1FEC106BBE220B03051979883B0B70C2325" />
       </characteristic>
    </characteristic>  
</wap-provisioningdoc>
<wap-provisioningdoc>
  <characteristic type="CertificateStore">
    <characteristic type="MY">
      <characteristic type="FFD8E1FEC106BBE220B03051979883B0B70C2325">
        <parm name="EncodedCertificate" value="MIIGkT..(shortened)..4IexLo=" datatype="binary"/>
        <noparm name="Role"/>
        <parm name="ValidFrom" value="2008-11-05T11:34:27Z"/>
        <parm name="ValidTo" value="2009-11-05T11:34:27Z"/>
        <parm name="IssuedBy" value="DC"/>
        <parm name="IssuedTo" value="Pavel Bansky"/>
        <noparm name="TemplateName"/>
      </characteristic>
    </characteristic>
  </characteristic>
</wap-provisioningdoc>

Conclusion

This article assumes some experience with Windows Mobile devices. All XML mentioned can be packed into a CAB file or invoked through RapiConfig.exe. I was in need to perform this tasks from C# utilizing the ProcessConfiguration method.