crypto_windows.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. * crypto_windows.c
  3. */
  4. #ifndef CONFIG
  5. #define CONFIG "config.h"
  6. #endif // CONFIG
  7. #include CONFIG
  8. #ifdef _CRYPTO_WINDOWS
  9. #if !_WIN32 && !__CYGWIN__
  10. #error You cannot use Windows CryptoAPI on non-Windows platforms
  11. #else // _WIN32 || __CYGWIN__
  12. #include "crypto_windows.h"
  13. typedef struct _HMAC_KEYBLOB
  14. {
  15. BLOBHEADER hdr;
  16. DWORD dwKeySize;
  17. BYTE KeyData[16];
  18. } HMAC_KEYBLOB;
  19. /*
  20. * MingW and Cygwin define NULL as ((void*)0) (Posix standard) which you can't assign to
  21. * non-pointer types without compiler warning. Thus we use the following
  22. */
  23. #define NULLHANDLE 0
  24. #define NULLFLAGS 0
  25. static HCRYPTPROV hRsaAesProvider = 0; // Needs to be initialized just once per process
  26. static int_fast8_t AcquireCryptContext()
  27. {
  28. if (!hRsaAesProvider)
  29. {
  30. return (int_fast8_t)CryptAcquireContextW
  31. (
  32. &hRsaAesProvider, // Provider handle
  33. NULL, // No key container name
  34. NULL, // Default provider
  35. PROV_RSA_AES, // Provides SHA and AES
  36. CRYPT_VERIFYCONTEXT // We don't need access to persistent keys
  37. );
  38. }
  39. return TRUE;
  40. }
  41. int_fast8_t Sha256(BYTE* restrict data, DWORD DataSize, BYTE* restrict hash)
  42. {
  43. HCRYPTHASH hHash = 0;
  44. DWORD HashSize = 32;
  45. int_fast8_t success =
  46. AcquireCryptContext() &&
  47. CryptCreateHash
  48. (
  49. hRsaAesProvider,// Provider handle
  50. CALG_SHA_256, // Algorithm
  51. NULLHANDLE, // SHA256 requires no key
  52. NULLFLAGS, // Use default flags
  53. &hHash // Handle for hashing
  54. ) &&
  55. CryptHashData
  56. (
  57. hHash, // Handle
  58. data, // data to hash
  59. DataSize, // size of data
  60. NULLFLAGS // Use default flags
  61. ) &&
  62. CryptGetHashParam
  63. (
  64. hHash, // Handle
  65. HP_HASHVAL, // what you actually want to get (the resulting hash)
  66. hash, // data to retrieve
  67. &HashSize, // size of data
  68. NULLFLAGS // currently reserved (as of this writing)
  69. );
  70. if (hHash) CryptDestroyHash(hHash);
  71. return success;
  72. }
  73. int_fast8_t Sha256Hmac(const BYTE* key, BYTE* restrict data, DWORD len, BYTE* restrict hmac)
  74. {
  75. # ifndef USE_THREADS // In fork() mode thread-safety is not required
  76. static
  77. # endif
  78. HMAC_KEYBLOB hmackeyblob = {
  79. // Type, Version, Algorithm
  80. { PLAINTEXTKEYBLOB, CUR_BLOB_VERSION, 0, CALG_RC2 },
  81. // Key length
  82. 16
  83. };
  84. HCRYPTKEY hKey = NULLHANDLE;
  85. HCRYPTHASH hHmacHash = NULLHANDLE;
  86. HMAC_INFO HmacInfo = { 0 };
  87. DWORD dwHmacSize = 32;
  88. HmacInfo.HashAlgid = CALG_SHA_256;
  89. memcpy(hmackeyblob.KeyData, key, sizeof(hmackeyblob.KeyData));
  90. BOOL success =
  91. AcquireCryptContext() &&
  92. CryptImportKey
  93. (
  94. hRsaAesProvider, // provider handle
  95. (PBYTE)&hmackeyblob, // the actual key MS blob format
  96. sizeof(HMAC_KEYBLOB), // size of the entire blob
  97. NULLHANDLE, // password/key for the key store (none required here)
  98. NULLFLAGS, // default flags
  99. &hKey // key handle to retrieve (must be kept until you finish hashing)
  100. ) &&
  101. CryptCreateHash
  102. (
  103. hRsaAesProvider, // provider handle
  104. CALG_HMAC, // the actual key MS blob format
  105. hKey, // size of the entire blob
  106. NULLFLAGS, // password/key for the key store (none required here)
  107. &hHmacHash // default flags
  108. ) && // key handle to retrieve (must be kept until you finish hashing)
  109. CryptSetHashParam
  110. (
  111. hHmacHash, // hash handle
  112. HP_HMAC_INFO, // parameter you want to set
  113. (PBYTE)&HmacInfo, // the HMAC parameters (SHA256 with default ipad and opad)
  114. NULLFLAGS // flags are reserved up to Windows 8.1
  115. ) &&
  116. CryptHashData
  117. (
  118. hHmacHash, // hash handle
  119. data, // Pointer to data you want to hash
  120. len, // data length
  121. NULLFLAGS // default flags
  122. ) &&
  123. CryptGetHashParam
  124. (
  125. hHmacHash, // hash handle
  126. HP_HASHVAL, // what you actually want to get (the resulting HMAC)
  127. hmac, // data to retrieve
  128. &dwHmacSize, // size of data
  129. NULLFLAGS // currently reserved (as of this writing)
  130. );
  131. if (hKey) CryptDestroyKey(hKey);
  132. if (hHmacHash) CryptDestroyHash(hHmacHash);
  133. return (int_fast8_t)success;
  134. }
  135. #endif // _WIN32 || __CYGWIN__
  136. #endif // _CRYPTO_WINDOWS