Windows Mobile

From Crypto++ Wiki
Jump to navigation Jump to search

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:

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.

Figure 1: Static MFC linking
Figure 2: Enable RTTI

Character Set

Figure 3: Project 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

Figure 4: 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

Figure 5: mobtime.cpp build setting

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.