MSBuild (Command Line)

From Crypto++ Wiki
Jump to: navigation, search

The Crypto++ library ships with a Visual Studio solution on Windows. The solution and project files are Visual Studio 2010, and the solution can be built from the IDE. It is just as easy to build the solution from the command line with MSBuild. This article will walk you through building the project and running the self tests using MSBuild.

Using MSBuild is a little more straight forward than the IDE if you are willing to manage dependencies by building components in the necessary order. MSBuild is also more helpful in getting the output of the tools so you can see if items like include directories and link libraries are correct.

Build Tools

The procedure below works equally well with the full version of Visual Studio and Visual C++ Build Tools. The Build Tools include the compiler, linker and other tools like Nmake and MSBuild. Build Tools are lighter weight than Visual Studio and does not suffer the expiring trial syndrome.

Platform Toolset

Before you begin, you should change the PlatformToolset to match your toolchain. Visual Studio 2010 uses v100, Visual Studio 2012 uses v110, Visual Studio 2013 uses v120, and so on. There are two ways to upgrade the platform toolset.

First, you can run VCUpgrade on the Solution to upgrade it. If you open the solution in Visual Studio, then you will be prompted to perform an upgrade. Second, you can upgrade the toolset by hand by editing the four vcxproj files with a text editor.

If editing the with a text editor, you can find the PlatformToolset on the PropertyGroup labeled Globals in the Visual C++ project files (the four vcxproj files):

<!-- From cryptdll.vcxproj project -->
<PropertyGroup Label="Globals">
  <ProjectGuid>{94a428a1-9ba8-4db2-b76e-bd2e3c08f257}</ProjectGuid>
  <RootNamespace>cryptdll</RootNamespace>
  <PlatformToolset>v100</PlatformToolset>
  <ConfigurationType>DynamicLibrary</ConfigurationType>
</PropertyGroup>

If you change the version by hand, then be sure to do it in all the project files (-n provides line numbers, not occurrence count):

$ grep -n PlatformToolset *.vcxproj
cryptdll.vcxproj:24:    <PlatformToolset>v100</PlatformToolset>
cryptest.vcxproj:41:    <PlatformToolset>v100</PlatformToolset>
cryptlib.vcxproj:41:    <PlatformToolset>v100</PlatformToolset>
dlltest.vcxproj:24:     <PlatformToolset>v100</PlatformToolset>

If you have a Git Bash shell open, you can issue the following to change from VS2010 to VS2012:

sed -i 's|Toolset>v100|Toolset>v110|g' *vcxproj*
unix2dos *vcxproj*

ARM Platforms

Over the course of about a week, we tried to add support for Windows Phone and Windows Store apps to the Visual C++ project files. The configurations were the modest Debug|ARM and Release|ARM, but neither built under ARM Cross Tools Command Prompt despite the effort. We tried both Windows Phone (WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP) and Windows Store (WINAPI_FAMILY=WINAPI_FAMILY_APP) apps.

At this point, until Microsoft releases documentation on the procedure, we are calling ARM-based MSBuilds completely broken. You should not attempt to build the library using MSBuild on Microsoft's ARM platforms. If you have an MSDN account, then please file bug reports on Microsoft Connect requesting the documentation to add Windows Phone and Windows Store support and the ARM platform to an existing C++ project.

If you want to submit a patch to provide the support, then see the following questions on Stack Overflow. The SO questions are the beginner steps for the support, and they have helpful feedback from the SO community.

If you need to build the cryptlib.lib or cryptest.exe for Windows Phone or Windows Store, then use cryptest.nmake. Its a Nmake-based makefile, and the project uses it to test the ARM builds.

Building Cryptest

This section will build the Win32/Debug version of cryptest.exe. Navigate to StartProgram FilesVisual Studio 2010Visual Studio Tools and open a Developer Command Prompt. Then cd into your Crypto++ directory.

First, build the Win32/Debug version of cryptlib. The output artifacts will be placed in Win32\Output\Debug. Win32/Debug is a procedural requirement, and all version of the FIPS DLL use it to embed the MAC used for integrity checking in the DLL.

c:\cryptopp>msbuild /t:Build /p:Configuration=Debug;Platform=Win32 cryptlib.vcxproj
Microsoft (R) Build Engine version 4.6.1055.0

Build started 10/5/2016 9:16:06 PM.
Project "c:\cryptopp\cryptest.vcxproj" on node 1 (Build target(s)).
PrepareForBuild:
  Creating directory "Win32\cryptest\Debug\".
  Creating directory "Win32\Output\Debug\".
...

ClCompile:
  c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\CL.exe /c /Zi /nol
  ogo /W4 /WX- /Od /Oi /Oy- /D USE_PRECOMPILED_HEADERS /Gm- /EHsc /RTC1 /MTd /G
  S /arch:SSE2 /fp:precise /Zc:wchar_t /Zc:forScope /Yc"pch.h" /Fp"Win32\cryptl
  ib\Debug\cryptlib.pch" /Fo"Win32\cryptlib\Debug\\" /Fd"Win32\cryptlib\Debug\v
  c100.pdb" /Gd /TP /analyze- /errorReport:none pch.cpp
  pch.cpp
...

Done Building Project "c:\cryptopp\cryptlib.vcxproj" (Build target(s)).

Build succeeded.
    3 Warning(s)
    0 Error(s)

Next, build the Win32/Debug version of cryptest. The output artifacts also land in Win32\Output\Debug.

c:\cryptopp>msbuild /t:Build /p:Configuration=Debug;Platform=Win32 cryptest.vcxproj
Microsoft (R) Build Engine version 4.6.1055.0

Build started 10/5/2016 9:31:42 PM.
Project "c:\cryptopp\cryptest.vcxproj" on node 1 (Build target(s)).
PrepareForBuild:
  Creating directory "Win32\cryptest\Debug\".
...

ClCompile:
  c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\CL.exe /c /Zi /nol
  ogo /W4 /WX- /Od /Oi /Oy- /Gm- /EHsc /RTC1 /MTd /GS /arch:SSE2 /fp:precise /Z
  c:wchar_t /Zc:forScope /Fo"Win32\cryptest\Debug\\" /Fd"Win32\cryptest\Debug\v
  c100.pdb" /Gd /TP /analyze- /errorReport:none adhoc.cpp bench1.cpp bench2.cpp
   datatest.cpp dlltest.cpp fipsalgt.cpp regtest.cpp test.cpp validat1.cpp vali
  dat2.cpp validat3.cpp
...

Done Building Project "c:\cryptopp\cryptest.vcxproj" (Build target(s)).

Build succeeded.
    0 Warning(s)
    0 Error(s)

After building, verify the file is where you expect it:

c:\cryptopp>dir Win32\Output\Debug

 Directory of c:\cryptopp\Win32\Output\Debug

10/05/2016  10:15 PM    <DIR>          .
10/05/2016  10:15 PM    <DIR>          ..
10/05/2016  10:15 PM         6,868,992 cryptest.exe
10/05/2016  10:15 PM        79,706,968 cryptlib.lib
10/05/2016  10:15 PM        28,625,920 cryptlib.pdb
               4 File(s)    141,225,976 bytes
               2 Dir(s)   3,237,699,584 bytes free

If we stay in the cryptopp root directory, then we can run the self tests because TestData and TestVectors are in the present working directory, and that's where cryptest.exe expects them.

c:\cryptopp>.\Win32\Output\Debug\cryptest.exe v
Using seed: 1475718161

Testing Settings...

passed:  Your machine is little endian.
passed:  CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS is not defined. Will restrict to a
ligned data access.
passed:  sizeof(byte) == 1
passed:  sizeof(word16) == 2
passed:  sizeof(word32) == 4
passed:  sizeof(word64) == 8
passed:  sizeof(hword) == 2, sizeof(word) == 4, sizeof(dword) == 8
passed:  hasMMX == 1, hasISSE == 1, hasSSE2 == 1, hasSSSE3 == 1, hasSSE4 == 1, h
asAESNI == 1, hasCLMUL == 1, hasRDRAND == 0, hasRDSEED == 0, isP4 == 0, cacheLin
eSize == 64
...

Building FIPS DLL

The FIPS DLL is a special purpose DLL. You cannot build the DLL and claim FIPS validation. If the library were attempting a validation, it would build the library and then submit the binary for validation. Some folks are curious about the DLL, so here's what it looks like when things work as if the output artifacts were FIPS validated.

You should still be in the Crypto++ root directory. Start by building the Win32/Release configuration of Cryptdll. The output artifacts will be placed in Win32\DLL_Output\Release. Notice the DLL has a MAC embedded in it for integrity checking, and the debug version of cryptest.exe embeds it.

c:\cryptopp>msbuild /t:Build /p:Configuration=Release;Platform=Win32 cryptdll.vcxproj
Microsoft (R) Build Engine version 4.6.1055.0

Build started 10/5/2016 10:28:58 PM.
Project "c:\cryptopp\cryptdll.vcxproj" on node 1 (Build target(s)).
PrepareForBuild:
  Creating directory "Win32\cryptdll\Release\".
...

PostBuildEvent:
  Description: Adding MAC to DLL
  Win32\output\debug\cryptest.exe mac_dll "c:\cryptopp\Win32\DLL_Output\Release
  \cryptopp.dll"
  IF %ERRORLEVEL% EQU 0 (echo mac done > "Win32\DLL_Output\Release\"\cryptopp.m
  ac.done)

  :VCEnd
  Placing MAC 21E0952977359F545209517176E8E98DE1141810 in c:\cryptopp\Win32\DLL
  _Output\Release\cryptopp.dll at file offset 979816 (0xef368).
...

Build succeeded.
    0 Warning(s)
    0 Error(s)

Next, build the DLLtest project.

c:\cryptopp>msbuild /t:Build /p:Configuration=Release;Platform=Win32 dlltest.vcxproj
Microsoft (R) Build Engine version 4.6.1055.0

Build started 10/5/2016 10:34:50 PM.
Project "c:\cryptopp\dlltest.vcxproj" on node 1 (Build target(s)).
PrepareForBuild:
  Creating directory "Win32\dlltest\Release\".
...

Build succeeded.
    0 Warning(s)
    0 Error(s)

At this point, we have a working DLL and a working DLL test program. Here's what running the DLL test program looks like. The failures are desired, and the FIPS self tests exits normally. If you set a software breakpoint in the image, then the tests will fail because a 0xCC is written which causes the CPU to trap. The new 0xCC instruction makes the integrity check fail.

c:\cryptopp>.\Win32\DLL_Output\Release\dlltest.exe
0. Automatic power-up self test passed.
1. Caught expected exception when simulating self test failure. Exception messag
e follows: Cryptographic algorithms are disabled after a power-up self test fail
ed.
2. Re-do power-up self test passed.
3. DES-EDE3-CFB Encryption/decryption succeeded.
4. SHA-1 hash succeeded.
5. DSA key generation succeeded.
6. DSA key encode/decode succeeded.
7. DSA signature and verification succeeded.
8. DSA signature verification successfully detected bad signature.
9. Caught expected exception when using invalid key length. Exception message fo
llows: DES-EDE3: 5 is not a valid key length

FIPS 140-2 Sample Application completed normally.

CopyCryptestToRoot

The cryptest.vcxproj has a target called CopyCryptestToRoot. It was added at Commit 556e3610e875c985 for AppVeyor. The recipe copies the output artifact to the root of the Crypto++ directory. It allows you to run the test harness from the root directory in four steps:

> msbuild /t:Build cryptlib.vcxproj
...
> msbuild /t:Build cryptest.vcxproj
...
> msbuild /t:CopyCryptestToRoot cryptest.vcxproj
...

After performing the copy, the self tests can be run from the root directory:

> .\cryptest.exe v
Using seed: 1492237450

Testing Settings...

passed:  Your machine is little endian.
passed:  Library version (library): 600, header version (app): 600
passed:  CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS is not defined. Will restrict to a
ligned data access.
passed:  sizeof(byte) == 1
passed:  sizeof(word16) == 2
passed:  sizeof(word32) == 4
passed:  sizeof(word64) == 8
passed:  sizeof(hword) == 4, sizeof(word) == 8
passed:  hasMMX == 1, hasISSE == 1, hasSSE2 == 1, hasSSSE3 == 1, hasSSE4 == 1, h
asAESNI == 1, hasCLMUL == 1, hasRDRAND == 1, hasRDSEED == 0, hasSHA == 0, isP4 =
= 0, cacheLineSize == 64
...