Windows Mobile
Windows Mobile is Microsoft's mobile operating system and was used from about 2005 to around 2010. In 2010, Microsoft debuted Windows Phone; see Microsoft Unveils Windows Phone 7 Series. This page will demonstrate a Windows Mobile 5, 6, and 6.5 port of Crypto++ 5.6.1.
Windows Mobile is built upon Windows CE. Windows CE is Microsoft's embedded operating system and runs devices from smart-toasters to SmartPhones and Pocket PCs. The CE to Mobile relationship is similar to the Linux kernel and Linux distributions. While Windows Mobile is built upon Windows CE, versioning between the two is slightly different. For example, Windows Mobile 5, 6, and 6.5 use Windows CE 5.0. Windows CE 4.0 (and earlier) powered earlier Windows Mobile devices (before they were officially called 'Windows Mobile').
While Windows CE targets four processors (SHx, MIPS, ARM, and x86), versions 5 and 6 of Windows Mobile target ARM processors (ARM v4 and v5). This means Crypto++'s CRYPTOPP_DISABLE_ASM
and CRYPTOPP_DISABLE_SSE2
should be defined. The macros can be defined in Visual Studio environment or the Crypto++ library's config.h
. This article will define the macros in config.h
.
Dr. Ugo Chirico maintains a port of Crypto++ 5.5.2 to Windows Mobile 2005 at Crypto++ 5.5.2 on Windows Mobile 2005. Chirico's original announcement can be found at Successful porting on Window CE Done.
Finally, nowadays you probably want Windows Phone or <Microsoft's next great way to do things>.
Windows Mobile SDKs
There are a number of Windows Mobile SDKs available. Older versions of Visual Studio (for example, 7.1 and 2005) offer older versions of the Windows Mobile development tools (for example, a PocketPC 2003 project). In general, prefer to use the 6.0 and 6.5 SDKs:
- Windows Mobile 6.5 SDK
- Windows Mobile 6.0 SDK
- Windows Mobile 5.0 SDK - PocketPC
- Windows Mobile 5.0 SDK - SmartPhone
Crypto++ Library
Download Crypto++ from the website, or fetch the library from Sourceforge. Below, a terminal was used and the project was retrieved from Sourceforge.
$ svn checkout https://cryptopp.svn.sourceforge.net/svnroot/cryptopp/trunk/c5 cryptopp A cryptopp/winpipes.cpp A cryptopp/safer.cpp A cryptopp/adler32.h ... A cryptopp/dlltest.vcproj A cryptopp/rijndael.h U cryptopp Checked out revision 521.
cryptopp.proj file
Copy the existing cryptlib.proj
to cryptopp.proj
. After the copy, create a new project and add cryptopp.proj
to the new project. The new project does not need to be part of the existing Crypto++ solution. In fact, one of the easiest paths is to create a new MFC project (Windows Mobile does not offer a command line).
Open cryptopp.proj
and delete the DLL-Import configurations of the library using Configuration Manager (this simplifies the project). With Configuration Manager still open, add two new platforms: Windows Mobile 6 Standard (SmartPhone) and Windows Mobile 6 Professional (Pocket PC).
If you don't have the platforms available, visit Windows Mobile 6.5 Developer Tool Kit at the Microsoft Download Center and install Windows Mobile 6.5 Professional Developer Tool Kit and Windows Mobile 6.5 Standard Developer Tool Kit. Note that Visual Studio must be above Express edition (i.e., Professional, Enterprise, Team, etc).
There are two settings of great importance with the new project. First, the Crypto++ library uses static linking by default. So set the MFC program to use static linking as shown in Figure 1. If you need to dynamically link to MFC, change Crypto++ to use a dynamic runtime library (Properties → Code Generation → C/C++ → Runtime Library).
Second, Crypto++ performs dynamic casts. So the MFC executable must enable RTTI as shown in Figure 2. If you don't enable RTTI under the new project, the device will unexpectedly lock or cause an access violation during a dynamic_cast
.
Character Set
Windows Mobile is Unicode, so ensure that the character set is set to Unicode. Setting Character Set to multi-byte will invoke ANSI routines for all Windows functions, most of which are not implemented.
Using Unicode requires fipstest.cpp
to be changed since it uses OutputDebugString
, which will be changed to OutputDebugStringW
by the preprocessor. This will cause problems because the strings are narrow. Change OutputDebugString
to OutputDebugStringA
(notice the addition of the letter A). OutputDebugStringA
is implemented on Windows Mobile. A typical change is shown below.
OutputDebugStringA("In memory integrity check failed.\n");
Alternately, wrap the string in Window's TCHAR macro:
OutputDebugString(_T("In memory integrity check failed.\n"));
Preprocessor Defines
At this point, the modified Crypto++ project (cryptopp.proj
) should have Win32, Win64, SmartPhone (Windows Mobile Standard) and Pocket PC (Windows Mobile Professional) platforms.
Ensure the following symbols are defined for SmartPhone and PocketPC under Properties → C/C++ → Preprocessor → Preprocessor Definitions as shown in Figure 3. Most symbols are defined by the Wizard. _LIB
specifies Crypto++ will be used in a static library. USE_PRECOMPILED_HEADERS
, a Crypto++ define, was added manually. WIN32_PLATFORM_WFSP
is a Microsoft define and used for SmartPhones (i.e., the Standard SDK). WIN32_PLATFORM_PSPC
is used for PocketPCs (i.e., the Professional SDK).
Debug Builds (SmartPhone, uses WIN32_PLATFORM_WFSP
):
DEBUG;_DEBUG;_LIB;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;$(ARCHFAM);$(_ARCHFAM_);WIN32_PLATFORM_WFSP;USE_PRECOMPILED_HEADERS
Release Builds (SmartPhone, uses WIN32_PLATFORM_WFSP
):
NDEBUG;_NDEBUG;_LIB;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;$(ARCHFAM);$(_ARCHFAM_);WIN32_PLATFORM_WFSP;USE_PRECOMPILED_HEADERS
Debug Builds (PocketPC, uses WIN32_PLATFORM_PSPC
):
DEBUG;_DEBUG;_LIB;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;$(ARCHFAM);$(_ARCHFAM_);WIN32_PLATFORM_PSPC;USE_PRECOMPILED_HEADERS
Release Builds (PocketPC, uses WIN32_PLATFORM_PSPC
):
NDEBUG;_NDEBUG;_LIB;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;$(ARCHFAM);$(_ARCHFAM_);WIN32_PLATFORM_PSPC;USE_PRECOMPILED_HEADERS
The differences between SmartPhone and Pocket PC are minor - for example, a Pocket PC usually has a touch screen and offers a device-top shell, while a SmartPhone does not. The PocketPC will usually have a Soft Input Panel (SIP), while a SmartPhone will have a complete keypad. Both will cause grief and misery when working with COM since many COM related functions are missing and devices typically only support single-threaded apartments.
config.h
config.h
needs a few adjustments. First, we need to detect if the Crypto++ library is running under Windows Mobile. If so, we will turn off some thread, socket and pipe functionality. Windows Mobile is not fully featured, so its easiest to reduce [non-crypto] features in the Crypto++ library to compile and link.
The first change to config.h
and should occur near the beginning of the file (for example, around line 15). The change picks up Windows Mobile (versions 5 and later) or Windows CE. Because CE is detected, the conditional should also pick up earlier embedded environments, such as embedded Visual C++ 4.2. If Crypto++ is ported to a Windows powered toaster or refrigerator, the CE defines will already be in place.
#if defined(WIN32_PLATFORM_WFSP) || defined(WIN32_PLATFORM_PSPC) || defined(UNDER_CE) || defined(WINCE) # define CRYPTOPP_WINMOBILE 1 # define CRYPTOPP_DISABLE_ASM 1 # define CRYPTOPP_DISABLE_SSE2 1 # define NOMINMAX // windows.h clash with std::min() and std::max() #endif
The next change should occur near the end of the file (for example, near line 425 before the DLL related gear). Windows Mobile does not support the desktop's GetOverlappedResult
(see GetOverlappedResult in WinCE), so threads, sockets, and pipes are removed for expediency. If you need an asynchronous socket, use WSASend
, WSAReceive
and friends manually (see Winsock Overlapped I/O and Event Objects). HIGHRES_TIMER_AVAILABLE
is removed for similar reasons - if HIGHRES_TIMER_AVAILABLE
is defined, there will be compile problems with CryptoPP::WaitObjectContainer
on Windows Mobile.
#if defined(CRYPTOPP_WINMOBILE) # if defined(SOCKETS_AVAILABLE) # undef SOCKETS_AVAILABLE # endif # if defined(WINDOWS_PIPES_AVAILABLE) # undef WINDOWS_PIPES_AVAILABLE # endif # if defined(THREADS_AVAILABLE) # undef THREADS_AVAILABLE # endif # if defined(HIGHRES_TIMER_AVAILABLE) # undef HIGHRES_TIMER_AVAILABLE # endif #endif // CRYPTOPP_WINMOBILE
The final change occurs near line 465 and modifies CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS
. Below, CRYPTOPP_WINMOBILE
is used with __BORLANDC__
and __SUNPRO_CC
.
#if defined(__MWERKS__) # define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS extern class CRYPTOPP_DLL #elif defined(__BORLANDC__) || defined(__SUNPRO_CC) || defined(CRYPTOPP_WINMOBILE) # define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS template class CRYPTOPP_DLL #else # define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS extern template class CRYPTOPP_DLL #endif
time.h, time, and clock
Though Windows Mobile declares all (or nearly all) of the time functions, the operating system and runtimes do not implement all the functions. We need to add a source file and provide implementations for clock
and time
. clock
and time
are used by the ANSI X9.17 pseudo random number generator (X917RNG
).
Create a new file named mobtime.cpp
, and add it to the Crypto++ source files. Right click on the new file, select Properties → General → Exclude from Build. Set Win32 and Win64 to Yes since the desktop has the functions (hence, the desktop does not need the file).
time
returns the number of seconds since Epoch (January 1, 1970). The implementation below uses roughly the same steps as RtlTimeToSecondsSince1970
. That is, subtract Epoch from the Current time, and adjust for nano-seconds since the time
function returns seconds. time_t
is defined as an unsigned long
on Windows Mobile, so truncation should not occur until about 2037.
Note that the FILETIME
's are converted to a Crypto++ word64
rather than taking the address of tmNow
and tm1970
, casting the address as an unsigned __int64*
or LARGE_INTEGER*
, and then performing the subtract through indirection. ARM processors will not tolerate an unaligned data access, and casting l33t-ness will lead to intermittent crashes.
// http://pubs.opengroup.org/onlinepubs/009695399/functions/time.html time_t time(time_t * out) { static const FILETIME tm1970 = FileTime1970(); const FILETIME tmNow = FileTimeNow(); if(!tmNow.dwHighDateTime && !tmNow.dwLowDateTime) { if(out) *out = (time_t)-1; return (time_t)-1; } const word64 t1 = ((word64) tmNow.dwHighDateTime << 32) + tmNow.dwLowDateTime; const word64 t2 = ((word64)tm1970.dwHighDateTime << 32) + tm1970.dwLowDateTime; const word64 d = (t1-t2)/10000000; if(out) *out = (time_t)d; return (time_t)d; }
clock
returns an approximation of processor time used by the program, in the system's time granularity. In the mobtime.cpp
implementation, only the calling thread's time is returned due to limitations in the mobile operating system. In addition, clock_t
is defined as a long
, so truncation of significant bits can (but probably will not) occur.
// http://pubs.opengroup.org/onlinepubs/009695399/functions/clock.html clock_t clock(void) { FILETIME k = {0,0}, u, unused; // Kernel time is not returned on Windows Mobile. Initializing K ensures // a sane result if K is not written in GetThreadTimes. if(!GetThreadTimes(GetCurrentThread(), &unused, &unused, &k, &u)) return (clock_t)-1; return (clock_t)(((word64)k.dwHighDateTime << 32) + k.dwLowDateTime + ((word64)u.dwHighDateTime << 32) + u.dwLowDateTime); }
mobtime.cpp
includes two additional helper functions and an include guard based on CRYPTOPP_WINMOBILE
, so take a look at the supplied patch. mobtime.cpp
has been placed in public domain, so there are no licensing issues.
hrtimer.h
Locate the declaration for TimerWord
, and ensure TimerWord
is defined through a 64 bit type (clock_t
is a long
, which is 32 bits on Windows Mobile).
#if defined(HIGHRES_TIMER_AVAILABLE) || defined(CRYPTOPP_WINMOBILE) typedef word64 TimerWord; #else typedef clock_t TimerWord; #endif
intrin.h
Find locations which #include intrin.h
. Add an additional guard on CRYPTOPP_WINMOBILE
. Note that the following is taken from integer.cpp
, but its representative of what to expect. Similar changes should be made to misc.h
, stdcpp.h
, and vmac.cpp
.
#if _MSC_VER >= 1400 && !defined(CRYPTOPP_WINMOBILE) #include <intrin.h> #endif
Windows Mobile does offer a selection of intrinsics by including <armintr.h>
. See Microsoft's Compilers for Microprocessors, Common Intrinsic Functions for Device Compilers, and Intrinsic Functions for ARM Microprocessors. Equally import is Unsupported Intrinsic Functions.
BitScanForward and Rotates
Guarding intrin.h
in misc.h
will result in undefined references to BitScanForward
, so change TrailingZeros
as follows (notice the additional test based on !defined(CRYPTOPP_WINMOBILE)
.
inline unsigned int TrailingZeros(word32 v) { #if defined(__GNUC__) && CRYPTOPP_GCC_VERSION >= 30400 return __builtin_ctz(v); #elif defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(CRYPTOPP_WINMOBILE) unsigned long result; _BitScanForward(&result, v); return result; #else // from http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup static const int MultiplyDeBruijnBitPosition[32] = { 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 }; return MultiplyDeBruijnBitPosition[((word32)((v & -v) * 0x077CB531U)) >> 27]; #endif }
Only a subset of built-in rotates will be available, so add an additional guard around line 700. This guard removes _rotl16
and _rotr16
, while leaving _rotl
, _rotl64
, and friends in place.
#if _MSC_VER >= 1400 && !defined(__INTEL_COMPILER) && !defined(CRYPTOPP_WINMOBILE) // Intel C++ Compiler 10.0 gives undefined externals with these template<> inline word16 rotlFixed<word16>(word16 x, unsigned int y) { assert(y < 8*sizeof(x)); return y ? _rotl16(x, y) : x; } ...
integer.cpp
integer.cpp
will need a couple of guards. The first guard was already applied due to <intrin.h>
. The second guard should be placed on __emulu
near line 140 as follows.
#if _MSC_VER >= 1400 && !defined(__INTEL_COMPILER) && !defined(CRYPTOPP_WINMOBILE) #define MultiplyWords(p, a, b) p = __emulu(a, b); #else #define MultiplyWords(p, a, b) p = (dword)a*b; #endif
vmac.cpp
vmac.cpp
will also need a couple of guards. The first guard was already placed on <intrin.h>
. The second guard should be placed on __emulu
near line 400 as follows.
#if _MSC_VER >= 1400 && !defined(__INTEL_COMPILER) && !defined(CRYPTOPP_WINMOBILE) #define MUL32(a, b) __emulu(word32(a), word32(b)) #else #define MUL32(a, b) ((word64)((word32)(a)) * (word32)(b)) #endif
Downloads
winmobile-cryptopp.zip - Visual Studio project with Crypto++ 5.6.1 (revision 525) for Windows Mobile (SmartPhone and Pocket PC) targets. The patch (and cryptopp.proj & mobtime.cpp) are already applied to the cryptopp/ directory.