Windows Mobile Secure Socket Implementation Series 1: General Idea
====>SiteMap of this Blog<===
Windows Mobile Secure Socket Implementation Series 1: General Idea
Whenever you need to write socket-based programs, very possibly you need to implement a secure socket. For example, if you develop your own mini-http client, you have to deal with HTTPS; if you write an IMAP4 client, you may need to support STARTTLS command. Or, you are writing both the server in the desktop and the client for Windows Mobile device, and need to support a secure communication channel.
I plan to write four articles on the series of secure socket implementation:
- General idea
- Sample source code
- X.509 Certificate and how to deal with wildcard certificate
- Changes in Windows Mobile 5.0 platform (vs. 2003 devices on 4.2 platform)
Different from Windows desktop environment, Windows CE platform exposes a very nice way to write secure socket program. Adding a security infrastructure requires few code changes to "normal non-secure" socket-based applications. Once a secure socket is connected, the application may send and receive data on that socket unaware that the data over the wire is encoded. You can just write the boilerplate socket code and functions: socket(), connect(), read(), recv(), closesocket().
The procedure to establish a secure socket connection is well documented by Microsoft, ever since 3.0:
- Microsoft Windows CE 3.0/ .NET 4.2 Implementing a Secure Socket
- Microsoft Windows CE .NET 5.0 Implementing a Secure Socket
Below are the two critical steps:
- Set the socket in secure mode with the setsockopt function. Set level to SOL_SOCKET, optname to SO_SECURE, and optval to a DWORD set to SO_SEC_SSL.
- Specify the certificate validation callback function by calling WSAIoctl with the SO_SSL_SET_VALIDATE_CERT_HOOK control code.
Notice the certificate validation callback function:
int SslValidate (
DWORD dwType
LPVOID pvArg
DWORD dwChainLen
LPBLOB pCertChain
DWORD dwFlags
);
Below are explanations of some important parameters:
- The dwType parameter specifies the data type pointed to by pCertChain. It must be SSL_CERT_X.509.
- The pvArg parameter is the application-defined context. It is a nice place to pass information against which you want to verify, for example, remote host name.
- The pCertChain parameter is a pointer to a BLOB struct, which contains a X.509 certificate (ISO standard). The certificate is the server certificate. You can parse the certificate to extract the pertinent data like the subject and life cycle.
- dwFlags parameter will contain SSL_CERT_FLAG_ISSUER_UNKNOWN, if the root issuer of the certificate could not be found in the client device's CA database. Notice WinSock sometimes passes false alarms in this parameter.
If you simply return SSL_ERR_OKEY in your certificate validation callback, then any faked or invalid SSL certificate is deemed valid. This obviously defeats the purpose of establishing a trusted secure communication channel. You need to do your due diligence by testing at least three things:
- to test the dwFlags passed to you by WinSock,
- to test the server certificate to see whether the certificate subject name matches the remote host name,
- and, to test whether the server certificate is already expired.
Most probably you do not need to test the issuer, since Winsock already did the job by checking the server certificate against the root CA store in the device.
One tricky business of how to parse the pCertChain Blob to get the following structure:
typedef struct _X509Certificate {
DWORD Version;
DWORD SerialNumber[4];
ALG_ID SignatureAlgorithm;
FILETIME ValidFrom;
FILETIME ValidUntil;
PSTR pszIssuer;
PSTR pszSubject;
PctPublicKey *pPublicKey;
} X509Certificate, * PX509Certificate;
The way to crack the Blob is not documented by Microsoft, but it it not difficult to find out by searching in major search engines: to use SslCrackCertificate and SslFreeCertificate that are exported from schannel.dll. Once you have the X.509 structure, you can easily validate it against the remote host name (by checking pszSubject), and life cycle (by checking ValidFrom and ValidUtil).
I'll post ready-to-compile source code in my next post.
Category: [SSL / Socket / Networking / Connection Manager]