Initial import.
authorFlorian Forster <octo@leeloo.octo.it>
Tue, 28 Sep 2010 21:27:28 +0000 (23:27 +0200)
committerFlorian Forster <octo@leeloo.octo.it>
Tue, 28 Sep 2010 21:27:28 +0000 (23:27 +0200)
create_hmac/create_hmac.c [new file with mode: 0644]
create_hmac/create_hmac.h [new file with mode: 0644]
create_hmac/create_hmac.vcproj [new file with mode: 0644]
hmac_test.sln [new file with mode: 0644]
hmac_test/hmac_test.cpp [new file with mode: 0644]
hmac_test/hmac_test.vcproj [new file with mode: 0644]
hmac_test/hmac_testcases.h [new file with mode: 0644]

diff --git a/create_hmac/create_hmac.c b/create_hmac/create_hmac.c
new file mode 100644 (file)
index 0000000..e966bca
--- /dev/null
@@ -0,0 +1,257 @@
+/**\r
+ * Copyright (c) 2010 Florian Forster\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy\r
+ * of this software and associated documentation files (the "Software"), to deal\r
+ * in the Software without restriction, including without limitation the rights\r
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+ * copies of the Software, and to permit persons to whom the Software is\r
+ * furnished to do so, subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in\r
+ * all copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
+ * THE SOFTWARE.\r
+ **/\r
+\r
+#include "create_hmac.h"\r
+\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <assert.h>\r
+\r
+/*\r
+ * Creating a HCRYPTKEY from a plain text password is probably the most tricky\r
+ * part when calculating an RFC2104 HMAC using Microsoft CryptoAPI. The\r
+ * examples provided at the MSDN website encourage you to use "CryptDeriveKey",\r
+ * which doesn't do the conditional hashing required by HMAC. (That is, it\r
+ * might. The documentation on any of the functions is so vague that it's well\r
+ * possible the elegant solution is just not documented nor demonstrated.\r
+ */\r
+static HCRYPTKEY create_hmac_key_exact (HCRYPTPROV hProv,\r
+                                                                               BYTE *pbKey, DWORD dwKeySize)\r
+{\r
+       /* Layout of the memory expected when importing a plain text blob is\r
+        * documented at the "CryptImportKey" under "Remarks". The four bytes\r
+        * following the PUBLICKEYSTRUC structure hold the size of the key, then\r
+        * follows the key itself. */\r
+       struct plain_text_data_s\r
+       {\r
+               PUBLICKEYSTRUC blob;\r
+               DWORD key_size;\r
+       } *data;\r
+       DWORD data_size;\r
+       HCRYPTKEY ret_key = 0;\r
+       BOOL status;\r
+\r
+       data_size = sizeof (*data) + dwKeySize;\r
+       data = (struct plain_text_data_s *) malloc (data_size);\r
+       if (data == NULL)\r
+               return (0);\r
+       memset (data, 0, data_size);\r
+\r
+       /* The key is not encrypted. */\r
+       data->blob.bType = PLAINTEXTKEYBLOB;\r
+       data->blob.bVersion = CUR_BLOB_VERSION;\r
+       data->blob.reserved = 0;\r
+       /* The "CryptImportKey" page explicitly states that "RC2" is to be used for\r
+        * HMAC keys. What anyone might have been thinking, I don't know. */\r
+       data->blob.aiKeyAlg = CALG_RC2;\r
+\r
+       /* Copy the key to the memory right behind the struct. "memcpy" should only\r
+        * add memory protection crap *after* the region written to, so the blob\r
+        * shouldn't be destroyed. We play it save, though, and set the key size\r
+        * last. Should problems arise, we should switch to a loop just to be sure. */\r
+       memcpy (data + 1, pbKey, dwKeySize);\r
+       data->key_size = dwKeySize;\r
+\r
+       /* Actually convert our memory region to this mysterious key structure.\r
+        * The "CRYPT_IPSEC_HMAC_KEY" is required to allow RC2 keys longer than\r
+        * 16 byte. Again, this is documented on the "CryptImportKey" page as a\r
+        * side note. */\r
+       status = CryptImportKey (hProv, (BYTE *) data, sizeof (data),\r
+               /* public key = */ 0,\r
+               /* flags = */ CRYPT_IPSEC_HMAC_KEY,\r
+               &ret_key);\r
+       if (!status)\r
+       {\r
+               free (data);\r
+               return (0);\r
+       }\r
+\r
+       free (data);\r
+       return (ret_key);\r
+} /* HCRYPTKEY create_hmac_key_exact */\r
+\r
+/* If the key of the HMAC is larger than the hash size, use the hash of the\r
+ * key instead of using the key directly. */\r
+static HCRYPTKEY create_hmac_key_hashed (HCRYPTPROV hProv,\r
+                                                                                BYTE *pbKey, DWORD dwKeySize,\r
+                                                                                DWORD dwHashSize, HCRYPTHASH hHash)\r
+{\r
+       BOOL status;\r
+       BYTE *hash_data;\r
+       DWORD hash_data_size;\r
+       HCRYPTKEY key;\r
+\r
+       assert (dwKeySize > dwHashSize);\r
+\r
+       status = CryptHashData (hHash, pbKey, dwKeySize, /* dwFlags = */ 0);\r
+       if (!status)\r
+               return (0);\r
+\r
+       hash_data = (BYTE *) malloc (dwHashSize);\r
+       if (hash_data == NULL)\r
+               return (0);\r
+       memset (hash_data, 0, dwHashSize);\r
+       hash_data_size = dwHashSize;\r
+\r
+       status = CryptGetHashParam (hHash, HP_HASHVAL,\r
+               hash_data, &hash_data_size, /* flags = */ 0);\r
+       if (!status)\r
+       {\r
+               free (hash_data);\r
+               return (0);\r
+       }\r
+\r
+       assert (hash_data_size == dwHashSize);\r
+\r
+       key = create_hmac_key_exact (hProv, hash_data, hash_data_size);\r
+\r
+       free (hash_data);\r
+       return (key);\r
+} /* HCRYPTKEY create_hmac_key_hashed */\r
+\r
+/* If the key is short enough, it is (right-)padded with zeros and otherwise\r
+ * used as-is. */\r
+static HCRYPTKEY create_hmac_key_padded (HCRYPTPROV hProv,\r
+                                                                                BYTE *pbKey, DWORD dwKeySize,\r
+                                                                                DWORD dwHashSize)\r
+{\r
+       BYTE *padded_key;\r
+       HCRYPTKEY key;\r
+       DWORD i;\r
+\r
+       assert (dwKeySize <= dwHashSize);\r
+\r
+       if (dwKeySize == dwHashSize)\r
+               return (create_hmac_key_exact (hProv, pbKey, dwKeySize));\r
+\r
+       padded_key = (BYTE *) malloc (dwHashSize);\r
+       if (padded_key == NULL)\r
+               return (0);\r
+\r
+       /* Copy the key and right-pad with zeros. Don't use "memcpy" here because\r
+        * the fucked up version of VS will corrupt memory. */\r
+       for (i = 0; i < dwHashSize; i++)\r
+               padded_key[i] = (i < dwKeySize) ? pbKey[i] : 0;\r
+\r
+       key = create_hmac_key_exact (hProv, padded_key, dwHashSize);\r
+\r
+       free (padded_key);\r
+       return (key);\r
+} /* HCRYPTKEY create_hmac_key_padded */\r
+\r
+static HCRYPTKEY create_hmac_key (HCRYPTPROV hProv,\r
+                                                                 ALG_ID Algid,\r
+                                                                 BYTE *pbKey, DWORD dwKeySize)\r
+{\r
+       HCRYPTHASH hash = 0;\r
+       HCRYPTKEY key;\r
+       DWORD hash_size = 0;\r
+       DWORD param_size;\r
+       BOOL status;\r
+\r
+       /* Allocate a hash object to determine the hash size. */\r
+       status = CryptCreateHash (hProv, Algid,\r
+               /* hKey = */ 0,\r
+               /* dwFlags = */ 0,\r
+               /* out phHash = */ &hash);\r
+       if (!status)\r
+               return (0);\r
+\r
+       param_size = (DWORD) sizeof (hash_size);\r
+       status = CryptGetHashParam (hash, HP_HASHSIZE,\r
+               (BYTE *) &hash_size, &param_size,\r
+               /* flags = */ 0);\r
+       if (!status)\r
+       {\r
+               CryptDestroyHash (hash);\r
+               return (0);\r
+       }\r
+\r
+       /* Determine whether we need to calculate the hash of the key or if\r
+        * padding is sufficient. */\r
+       if (dwKeySize > hash_size)\r
+               key = create_hmac_key_hashed (hProv, pbKey, dwKeySize, hash_size, hash);\r
+       else\r
+               key = create_hmac_key_padded (hProv, pbKey, dwKeySize, hash_size);\r
+\r
+       CryptDestroyHash (hash);\r
+       return (key);\r
+} /* HCRYPTKEY create_hmac_key */\r
+\r
+BOOL CreateHMAC (HCRYPTPROV hProv,\r
+                                ALG_ID Algid,\r
+                                BYTE *pbKey, DWORD dwKeySize,\r
+                                DWORD dwFlags,\r
+                                HCRYPTHASH *phHash,\r
+                                HCRYPTKEY *phKey)\r
+{\r
+       HCRYPTKEY hmac_key;\r
+       HCRYPTHASH hash = 0;\r
+       HMAC_INFO hmac_info;\r
+       BOOL status;\r
+\r
+       hmac_key = create_hmac_key (hProv, Algid, pbKey, dwKeySize);\r
+       if (hmac_key == 0)\r
+               return (FALSE);\r
+\r
+       status = CryptCreateHash (hProv, CALG_HMAC, hmac_key,\r
+               /* flags = */ dwFlags,\r
+               &hash);\r
+       if (!status)\r
+       {\r
+               CryptDestroyKey (hmac_key);\r
+               return (status);\r
+       }\r
+\r
+       memset (&hmac_info, 0, sizeof (hmac_info));\r
+       hmac_info.HashAlgid = Algid;\r
+       hmac_info.pbInnerString = NULL;\r
+       hmac_info.cbInnerString = 0;\r
+       hmac_info.pbOuterString = NULL;\r
+       hmac_info.cbOuterString = 0;\r
+\r
+       status = CryptSetHashParam (hash, HP_HMAC_INFO, (BYTE *) &hmac_info,\r
+               /* flags = */ 0);\r
+       if (!status)\r
+       {\r
+               CryptDestroyHash (hash);\r
+               CryptDestroyKey (hmac_key);\r
+               return (status);\r
+       }\r
+\r
+       *phHash = hash;\r
+       *phKey = hmac_key;\r
+       return (TRUE);\r
+} /* BOOL CreateHMAC */\r
+\r
+BOOL DestroyHMAC (HCRYPTHASH hHash, HCRYPTKEY hKey)\r
+{\r
+       if (hHash != 0)\r
+               CryptDestroyHash (hHash);\r
+\r
+       if (hKey != 0)\r
+               CryptDestroyKey (hKey);\r
+\r
+       return (TRUE);\r
+} /* BOOL DestroyHMAC */\r
+\r
+/* vim: set ts=4 sw=4 noet : */\r
diff --git a/create_hmac/create_hmac.h b/create_hmac/create_hmac.h
new file mode 100644 (file)
index 0000000..e6e28b8
--- /dev/null
@@ -0,0 +1,49 @@
+/**\r
+ * Copyright (c) 2010 Florian Forster\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy\r
+ * of this software and associated documentation files (the "Software"), to deal\r
+ * in the Software without restriction, including without limitation the rights\r
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+ * copies of the Software, and to permit persons to whom the Software is\r
+ * furnished to do so, subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in\r
+ * all copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
+ * THE SOFTWARE.\r
+ **/\r
+\r
+#ifndef CREATE_HMAC_H\r
+#define CREATE_HMAC_H 1\r
+\r
+#include <windows.h>\r
+#include <wincrypt.h>\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+__declspec(dllexport)\r
+BOOL CreateHMAC (HCRYPTPROV hProv,\r
+                                ALG_ID Algid,\r
+                                BYTE *pbKey, DWORD dwKeySize,\r
+                                DWORD dwFlags,\r
+                                HCRYPTHASH *phHash,\r
+                                HCRYPTKEY *phKey);\r
+\r
+__declspec(dllexport)\r
+BOOL DestroyHMAC (HCRYPTHASH hHash, HCRYPTKEY hKey);\r
+\r
+#ifdef __cplusplus\r
+} /* extern "C" */\r
+#endif\r
+\r
+/* vim: set ts=4 : */\r
+#endif /* CREATE_HMAC_H */\r
diff --git a/create_hmac/create_hmac.vcproj b/create_hmac/create_hmac.vcproj
new file mode 100644 (file)
index 0000000..e449a9a
--- /dev/null
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="8,00"\r
+       Name="create_hmac"\r
+       ProjectGUID="{3A3F7A71-1B91-45B1-9885-F2C09BB884FD}"\r
+       RootNamespace="create_hmac"\r
+       >\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"\r
+               />\r
+       </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG"\r
+                               ExceptionHandling="0"\r
+                               RuntimeLibrary="1"\r
+                               DisableLanguageExtensions="false"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               CallingConvention="0"\r
+                               CompileAs="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               ExceptionHandling="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="true"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"\r
+                       >\r
+                       <File\r
+                               RelativePath=".\create_hmac.c"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"\r
+                       >\r
+                       <File\r
+                               RelativePath=".\create_hmac.h"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Resource Files"\r
+                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"\r
+                       UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"\r
+                       >\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/hmac_test.sln b/hmac_test.sln
new file mode 100644 (file)
index 0000000..46c7a98
--- /dev/null
@@ -0,0 +1,29 @@
+\r
+Microsoft Visual Studio Solution File, Format Version 9.00\r
+# Visual Studio 2005\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hmac_test", "hmac_test\hmac_test.vcproj", "{96B41CDE-A88A-42AD-A6AA-2A7A1DD62EE5}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {3A3F7A71-1B91-45B1-9885-F2C09BB884FD} = {3A3F7A71-1B91-45B1-9885-F2C09BB884FD}\r
+       EndProjectSection\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "create_hmac", "create_hmac\create_hmac.vcproj", "{3A3F7A71-1B91-45B1-9885-F2C09BB884FD}"\r
+EndProject\r
+Global\r
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
+               Debug|Win32 = Debug|Win32\r
+               Release|Win32 = Release|Win32\r
+       EndGlobalSection\r
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution\r
+               {96B41CDE-A88A-42AD-A6AA-2A7A1DD62EE5}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {96B41CDE-A88A-42AD-A6AA-2A7A1DD62EE5}.Debug|Win32.Build.0 = Debug|Win32\r
+               {96B41CDE-A88A-42AD-A6AA-2A7A1DD62EE5}.Release|Win32.ActiveCfg = Release|Win32\r
+               {96B41CDE-A88A-42AD-A6AA-2A7A1DD62EE5}.Release|Win32.Build.0 = Release|Win32\r
+               {3A3F7A71-1B91-45B1-9885-F2C09BB884FD}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {3A3F7A71-1B91-45B1-9885-F2C09BB884FD}.Debug|Win32.Build.0 = Debug|Win32\r
+               {3A3F7A71-1B91-45B1-9885-F2C09BB884FD}.Release|Win32.ActiveCfg = Release|Win32\r
+               {3A3F7A71-1B91-45B1-9885-F2C09BB884FD}.Release|Win32.Build.0 = Release|Win32\r
+       EndGlobalSection\r
+       GlobalSection(SolutionProperties) = preSolution\r
+               HideSolutionNode = FALSE\r
+       EndGlobalSection\r
+EndGlobal\r
diff --git a/hmac_test/hmac_test.cpp b/hmac_test/hmac_test.cpp
new file mode 100644 (file)
index 0000000..43e5a9f
--- /dev/null
@@ -0,0 +1,145 @@
+#include "create_hmac.h"\r
+#include "hmac_testcases.h"\r
+\r
+#include <tchar.h>\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <assert.h>\r
+\r
+static int run_single_test (HCRYPTPROV hProv, ALG_ID Algid,\r
+                                                       BYTE *data, DWORD data_size,\r
+                                                       BYTE *key,  DWORD key_size,\r
+                                                       const BYTE *hash, DWORD hash_size)\r
+{\r
+       HCRYPTHASH hmac_hash = 0;\r
+       HCRYPTKEY hmac_key = 0;\r
+       BYTE output[1024];\r
+       DWORD output_size = 1024;\r
+       BOOL status;\r
+\r
+       status = CreateHMAC (hProv, Algid,\r
+               key, key_size,\r
+               /* flags = */ 0,\r
+               /* phHash = */ &hmac_hash, /* phKey = */ &hmac_key);\r
+       if (!status)\r
+       {\r
+               fprintf (stderr, "CreateHMAC failed with status %#x.\n",\r
+                       GetLastError ());\r
+               return (-1);\r
+       }\r
+\r
+       status = CryptHashData (hmac_hash,\r
+               data, data_size,\r
+               /* flags = */ 0);\r
+       if (!status)\r
+       {\r
+               fprintf (stderr, "CryptHashData failed with status %#x.\n",\r
+                       GetLastError ());\r
+               CryptDestroyHash (hmac_hash);\r
+               CryptDestroyKey (hmac_key);\r
+               return (-1);\r
+       }\r
+\r
+       memset (output, 0, sizeof (output));\r
+       status = CryptGetHashParam (hmac_hash, HP_HASHVAL,\r
+               output, &output_size, /* flags = */ 0);\r
+       if (!status)\r
+       {\r
+               fprintf (stderr, "CryptHashData failed with status %#x.\n",\r
+                       GetLastError ());\r
+               CryptDestroyHash (hmac_hash);\r
+               CryptDestroyKey (hmac_key);\r
+               return (-1);\r
+       }\r
+\r
+       CryptDestroyHash (hmac_hash);\r
+       CryptDestroyKey (hmac_key);\r
+\r
+       if (output_size != hash_size)\r
+       {\r
+               fprintf (stderr, "Hash size mismatch: Got %lu, expected %lu.\n",\r
+                       output_size, hash_size);\r
+               return (-1);\r
+       }\r
+\r
+       if (memcmp (output, hash, hash_size) != 0)\r
+       {\r
+               fprintf (stderr, "Hash sum mismatch.\n");\r
+               return (-1);\r
+       }\r
+       else\r
+       {\r
+               printf ("    Success!\n");\r
+       }\r
+\r
+       return (0);\r
+} /* int run_single_test */\r
+\r
+static int run_testcase (HCRYPTPROV hProv,\r
+                                                const testcase_t *tc)\r
+{\r
+       printf ("  SHA-256:\n");\r
+       run_single_test (hProv, CALG_SHA_256,\r
+               tc->data, tc->data_size,\r
+               tc->key, tc->key_size,\r
+               tc->sha256, sizeof (tc->sha256));\r
+       printf ("\n");\r
+\r
+       printf ("  SHA-384:\n");\r
+       run_single_test (hProv, CALG_SHA_384,\r
+               tc->data, tc->data_size,\r
+               tc->key, tc->key_size,\r
+               tc->sha384, sizeof (tc->sha384));\r
+       printf ("\n");\r
+\r
+       printf ("  SHA-512:\n");\r
+       run_single_test (hProv, CALG_SHA_512,\r
+               tc->data, tc->data_size,\r
+               tc->key, tc->key_size,\r
+               tc->sha512, sizeof (tc->sha512));\r
+       printf ("\n");\r
+\r
+       return (0);\r
+} /* int run_testcase */\r
+\r
+int _tmain(int argc, _TCHAR* argv[])\r
+{\r
+       HCRYPTPROV cry_provider;\r
+       BOOL status;\r
+\r
+       status = CryptAcquireContext (&cry_provider,\r
+               /* szContainer = */ NULL,\r
+               /* CSP name = */ NULL,\r
+               /* provider type = */ PROV_RSA_AES,\r
+               /* flags = */ CRYPT_VERIFYCONTEXT);\r
+       if (!status)\r
+       {\r
+               fprintf (stderr, "CryptAcquireContext failed: %#x\n", GetLastError ());\r
+               exit (EXIT_FAILURE);\r
+       }\r
+\r
+       printf ("Testcase 1\n");\r
+       printf ("----------\n");\r
+       run_testcase (cry_provider, &testcase1);\r
+       printf ("\n");\r
+\r
+       printf ("Testcase 2\n");\r
+       printf ("----------\n");\r
+       run_testcase (cry_provider, &testcase2);\r
+       printf ("\n");\r
+\r
+       printf ("Testcase 3\n");\r
+       printf ("----------\n");\r
+       run_testcase (cry_provider, &testcase3);\r
+       printf ("\n");\r
+\r
+       printf ("Testcase 6\n");\r
+       printf ("----------\n");\r
+       run_testcase (cry_provider, &testcase6);\r
+       printf ("\n");\r
+\r
+       CryptReleaseContext (cry_provider, /* flags = */ 0);\r
+\r
+       return 0;\r
+}\r
+\r
diff --git a/hmac_test/hmac_test.vcproj b/hmac_test/hmac_test.vcproj
new file mode 100644 (file)
index 0000000..e325ba4
--- /dev/null
@@ -0,0 +1,207 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="8,00"\r
+       Name="hmac_test"\r
+       ProjectGUID="{96B41CDE-A88A-42AD-A6AA-2A7A1DD62EE5}"\r
+       RootNamespace="hmac_test"\r
+       Keyword="Win32Proj"\r
+       >\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"\r
+               />\r
+       </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="..\create_hmac"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"\r
+                               MinimalRebuild="true"\r
+                               ExceptionHandling="0"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="4"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               LinkIncremental="2"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="1"\r
+                       WholeProgramOptimization="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"\r
+                               RuntimeLibrary="2"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"\r
+                       >\r
+                       <File\r
+                               RelativePath=".\hmac_test.cpp"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"\r
+                       >\r
+                       <File\r
+                               RelativePath=".\hmac_testcases.h"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Resource Files"\r
+                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"\r
+                       UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"\r
+                       >\r
+               </Filter>\r
+               <File\r
+                       RelativePath=".\ReadMe.txt"\r
+                       >\r
+               </File>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/hmac_test/hmac_testcases.h b/hmac_test/hmac_testcases.h
new file mode 100644 (file)
index 0000000..ba283d6
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * These SHA-2 test vectors were taken from RFC 4231 which is available from
+ * the IETF website.
+ */
+
+struct testcase_s
+{
+       BYTE *key;
+       DWORD key_size;
+       BYTE *data;
+       DWORD data_size;
+
+       BYTE sha224[28];
+       BYTE sha256[32];
+       BYTE sha384[48];
+       BYTE sha512[64];
+};
+typedef struct testcase_s testcase_t;
+
+BYTE testcase1_key[] =
+{
+  0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+  0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b
+};
+
+BYTE testcase1_data[] =
+{
+  0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65
+};
+
+testcase_t testcase1 =
+{
+  testcase1_key,
+  sizeof (testcase1_key),
+  testcase1_data,
+  sizeof (testcase1_data),
+  { /* SHA-224 */
+    0x89, 0x6f, 0xb1, 0x12, 0x8a, 0xbb, 0xdf, 0x19, 0x68, 0x32, 0x10, 0x7c, 0xd4, 0x9d,
+    0xf3, 0x3f, 0x47, 0xb4, 0xb1, 0x16, 0x99, 0x12, 0xba, 0x4f, 0x53, 0x68, 0x4b, 0x22
+  },
+  { /* SHA-256 */
+    0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b,
+    0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7
+  },
+  { /* SHA-384 */
+    0xaf, 0xd0, 0x39, 0x44, 0xd8, 0x48, 0x95, 0x62, 0x6b, 0x08, 0x25, 0xf4, 0xab, 0x46, 0x90, 0x7f,
+    0x15, 0xf9, 0xda, 0xdb, 0xe4, 0x10, 0x1e, 0xc6, 0x82, 0xaa, 0x03, 0x4c, 0x7c, 0xeb, 0xc5, 0x9c,
+    0xfa, 0xea, 0x9e, 0xa9, 0x07, 0x6e, 0xde, 0x7f, 0x4a, 0xf1, 0x52, 0xe8, 0xb2, 0xfa, 0x9c, 0xb6
+  },
+  { /* SHA-512 */
+    0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d, 0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0,
+    0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78, 0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde,
+    0xda, 0xa8, 0x33, 0xb7, 0xd6, 0xb8, 0xa7, 0x02, 0x03, 0x8b, 0x27, 0x4e, 0xae, 0xa3, 0xf4, 0xe4,
+    0xbe, 0x9d, 0x91, 0x4e, 0xeb, 0x61, 0xf1, 0x70, 0x2e, 0x69, 0x6c, 0x20, 0x3a, 0x12, 0x68, 0x54
+  }
+};
+
+BYTE testcase2_key[] =
+{
+  0x4a, 0x65, 0x66, 0x65
+};
+
+BYTE testcase2_data[] =
+{
+  0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20, 0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20,
+  0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x3f
+};
+
+testcase_t testcase2 =
+{
+  testcase2_key,
+  sizeof (testcase2_key),
+  testcase2_data,
+  sizeof (testcase2_data),
+  { /* SHA-224 */
+    0xa3, 0x0e, 0x01, 0x09, 0x8b, 0xc6, 0xdb, 0xbf, 0x45, 0x69, 0x0f, 0x3a, 0x7e, 0x9e, 0x6d, 0x0f,
+    0x8b, 0xbe, 0xa2, 0xa3, 0x9e, 0x61, 0x48, 0x00, 0x8f, 0xd0, 0x5e, 0x44
+  },
+  { /* SHA-256 */
+    0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7,
+    0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43
+  },
+  { /* SHA-384 */
+    0xaf, 0x45, 0xd2, 0xe3, 0x76, 0x48, 0x40, 0x31, 0x61, 0x7f, 0x78, 0xd2, 0xb5, 0x8a, 0x6b, 0x1b,
+    0x9c, 0x7e, 0xf4, 0x64, 0xf5, 0xa0, 0x1b, 0x47, 0xe4, 0x2e, 0xc3, 0x73, 0x63, 0x22, 0x44, 0x5e,
+    0x8e, 0x22, 0x40, 0xca, 0x5e, 0x69, 0xe2, 0xc7, 0x8b, 0x32, 0x39, 0xec, 0xfa, 0xb2, 0x16, 0x49
+  },
+  { /* SHA-512 */
+    0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, 0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3,
+    0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6, 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54,
+    0x97, 0x58, 0xbf, 0x75, 0xc0, 0x5a, 0x99, 0x4a, 0x6d, 0x03, 0x4f, 0x65, 0xf8, 0xf0, 0xe6, 0xfd,
+    0xca, 0xea, 0xb1, 0xa3, 0x4d, 0x4a, 0x6b, 0x4b, 0x63, 0x6e, 0x07, 0x0a, 0x38, 0xbc, 0xe7, 0x37
+  }
+};
+
+BYTE testcase3_key[] =
+{
+  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+  0xaa, 0xaa, 0xaa, 0xaa
+};
+
+BYTE testcase3_data[] =
+{
+  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+  0xdd, 0xdd
+};
+
+testcase_t testcase3 =
+{
+  testcase3_key,
+  sizeof (testcase3_key),
+  testcase3_data,
+  sizeof (testcase3_data),
+  { /* SHA-224 */
+    0x7f, 0xb3, 0xcb, 0x35, 0x88, 0xc6, 0xc1, 0xf6, 0xff, 0xa9, 0x69, 0x4d, 0x7d, 0x6a, 0xd2, 0x64,
+    0x93, 0x65, 0xb0, 0xc1, 0xf6, 0x5d, 0x69, 0xd1, 0xec, 0x83, 0x33, 0xea
+  },
+  { /* SHA-256 */
+    0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7,
+    0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe
+  },
+  { /* SHA-384 */
+    0x88, 0x06, 0x26, 0x08, 0xd3, 0xe6, 0xad, 0x8a, 0x0a, 0xa2, 0xac, 0xe0, 0x14, 0xc8, 0xa8, 0x6f,
+    0x0a, 0xa6, 0x35, 0xd9, 0x47, 0xac, 0x9f, 0xeb, 0xe8, 0x3e, 0xf4, 0xe5, 0x59, 0x66, 0x14, 0x4b,
+    0x2a, 0x5a, 0xb3, 0x9d, 0xc1, 0x38, 0x14, 0xb9, 0x4e, 0x3a, 0xb6, 0xe1, 0x01, 0xa3, 0x4f, 0x27
+  },
+  { /* SHA-512 */
+    0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84, 0xef, 0xb0, 0xf0, 0x75, 0x6c, 0x89, 0x0b, 0xe9,
+    0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36, 0x55, 0xf8, 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39,
+    0xbf, 0x3e, 0x84, 0x82, 0x79, 0xa7, 0x22, 0xc8, 0x06, 0xb4, 0x85, 0xa4, 0x7e, 0x67, 0xc8, 0x07,
+    0xb9, 0x46, 0xa3, 0x37, 0xbe, 0xe8, 0x94, 0x26, 0x74, 0x27, 0x88, 0x59, 0xe1, 0x32, 0x92, 0xfb
+  }
+};
+
+BYTE testcase6_key[] =
+{
+  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+  0xaa, 0xaa, 0xaa
+};
+
+BYTE testcase6_data[] =
+{
+  0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65,
+  0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a,
+  0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x2d, 0x20, 0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79,
+  0x20, 0x46, 0x69, 0x72, 0x73, 0x74
+};
+
+testcase_t testcase6 =
+{
+  testcase6_key,
+  sizeof (testcase6_key),
+  testcase6_data,
+  sizeof (testcase6_data),
+  { /* SHA-224 */
+    0x95, 0xe9, 0xa0, 0xdb, 0x96, 0x20, 0x95, 0xad, 0xae, 0xbe, 0x9b, 0x2d, 0x6f, 0x0d, 0xbc, 0xe2,
+    0xd4, 0x99, 0xf1, 0x12, 0xf2, 0xd2, 0xb7, 0x27, 0x3f, 0xa6, 0x87, 0x0e
+  },
+  { /* SHA-256 */
+    0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f,
+    0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54
+  },
+  { /* SHA-384 */
+    0x4e, 0xce, 0x08, 0x44, 0x85, 0x81, 0x3e, 0x90, 0x88, 0xd2, 0xc6, 0x3a, 0x04, 0x1b, 0xc5, 0xb4,
+    0x4f, 0x9e, 0xf1, 0x01, 0x2a, 0x2b, 0x58, 0x8f, 0x3c, 0xd1, 0x1f, 0x05, 0x03, 0x3a, 0xc4, 0xc6,
+    0x0c, 0x2e, 0xf6, 0xab, 0x40, 0x30, 0xfe, 0x82, 0x96, 0x24, 0x8d, 0xf1, 0x63, 0xf4, 0x49, 0x52
+  },
+  { /* SHA-512 */
+    0x80, 0xb2, 0x42, 0x63, 0xc7, 0xc1, 0xa3, 0xeb, 0xb7, 0x14, 0x93, 0xc1, 0xdd, 0x7b, 0xe8, 0xb4,
+    0x9b, 0x46, 0xd1, 0xf4, 0x1b, 0x4a, 0xee, 0xc1, 0x12, 0x1b, 0x01, 0x37, 0x83, 0xf8, 0xf3, 0x52,
+    0x6b, 0x56, 0xd0, 0x37, 0xe0, 0x5f, 0x25, 0x98, 0xbd, 0x0f, 0xd2, 0x21, 0x5d, 0x6a, 0x1e, 0x52,
+    0x95, 0xe6, 0x4f, 0x73, 0xf6, 0x3f, 0x0a, 0xec, 0x8b, 0x91, 0x5a, 0x98, 0x5d, 0x78, 0x65, 0x98
+  }
+};
+
+/* vim: set sw=2 sts=2 et : */