char *username;
char *password;
-#if HAVE_LIBGCRYPT
+#if WIN32
+ HCRYPTPROV hProv;
+ size_t encr_header_len;
+ BYTE encr_iv[16];
+#elif HAVE_LIBGCRYPT
gcry_cipher_hd_t encr_cypher;
size_t encr_header_len;
char encr_iv[16];
return (0);
} /* }}} int nb_add_value_list */
-/* TODO: Add encryption for Windows */
#if WIN32
static int nb_add_signature (lcc_network_buffer_t *nb) /* {{{ */
{
BYTE hash[32] = { 0 };
DWORD hash_size = sizeof (hash) / sizeof (hash[0]);
- HCRYPTPROV hProv;
HCRYPTHASH hHash;
HCRYPTKEY hKey;
BOOL status;
assert (nb->size >= (nb->free + PART_SIGNATURE_SHA256_SIZE));
buffer_size = (DWORD) (nb->size - (nb->free + PART_SIGNATURE_SHA256_SIZE));
- status = CryptAcquireContext (&hProv,
- /* szContainer = */ NULL,
- /* CSP name = */ NULL,
- /* provider type = */ PROV_RSA_AES,
- /* flags = */ CRYPT_VERIFYCONTEXT);
- if (!status)
- return (-1);
+ if (!nb->hProv)
+ {
+ status = CryptAcquireContext (&nb->hProv,
+ /* szContainer = */ NULL,
+ /* CSP name = */ NULL,
+ /* provider type = */ PROV_RSA_AES,
+ /* flags = */ CRYPT_VERIFYCONTEXT);
+ if (!status)
+ return (-1);
+ }
- status = CreateHMAC (hProv,
+ status = CreateHMAC (nb->hProv,
/* algorithm = */ CALG_SHA_256,
/* lpbKey = */ (LPBYTE) nb->password,
/* dwKeySize = */ (DWORD) strlen (nb->password),
/* lphHash = */ &hHash,
/* lphKey = */ &hKey);
if (!status)
- {
- CryptReleaseContext (hProv, /* dwFlags = */ 0);
return (-1);
- }
status = CryptHashData (hHash,
/* pbData = */ buffer,
{
CryptDestroyHash (hHash);
CryptDestroyKey (hKey);
- CryptReleaseContext (hProv, /* dwFlags = */ 0);
return (-1);
}
{
CryptDestroyHash (hHash);
CryptDestroyKey (hKey);
- CryptReleaseContext (hProv, /* dwFlags = */ 0);
return (-1);
}
CryptDestroyHash (hHash);
CryptDestroyKey (hKey);
- CryptReleaseContext (hProv, /* dwFlags = */ 0);
return (0);
} /* }}} int nb_add_signature */
+
+static int nb_key_from_password (HCRYPTPROV hProv, /* {{{ */
+ LPCSTR pbPassword, LPBYTE pbIv, HCRYPTKEY *phKey)
+{
+ HCRYPTHASH hHash = 0;
+ HCRYPTKEY hKey = 0;
+
+ struct
+ {
+ PUBLICKEYSTRUC pks;
+ DWORD dwKeySize;
+ BYTE pbKey[32];
+ } keyData;
+ DWORD cypherMode = CRYPT_MODE_OFB;
+
+ BOOL status;
+
+ memset (&keyData, 0, sizeof (keyData));
+ keyData.pks.bType = PLAINTEXTKEYBLOB;
+ keyData.pks.bVersion = CUR_BLOB_VERSION;
+ keyData.pks.reserved = 0;
+ keyData.dwKeySize = 32;
+
+ status = CryptCreateHash (hProv,
+ /* algorithm = */ CALG_SHA_256,
+ /* hKey = */ 0,
+ /* dwFlags = */ 0,
+ /* out phHash = */ &hHash);
+ if (!status)
+ return (-1);
+
+ status = CryptHashData (hHash,
+ /* pbData = */ (void *) pbPassword,
+ /* dwDataSize = */ strlen (pbPassword),
+ /* dwFlags = */ 0);
+ if (!status)
+ {
+ CryptDestroyHash (hHash);
+ return (-1);
+ }
+
+ status = CryptGetHashParam (hHash,
+ /* dwParam = */ HP_HASHVAL,
+ /* pbData = */ keyData.pbKey,
+ /* pwdDataLen = */ &keyData.dwKeySize,
+ /* dwFlags = */ 0);
+ if (!status)
+ {
+ CryptDestroyHash (hHash);
+ return (-1);
+ }
+ CryptDestroyHash (hHash);
+ assert (keyData.dwKeySize == 32);
+
+ status = CryptImportKey (hProv,
+ /* pbData = */ (void *) &keyData,
+ /* dwDataLen = */ sizeof (keyData),
+ /* hPubKey = */ 0,
+ /* dwFlags = */ 0,
+ /* phKey = */ &hKey);
+ if (!status)
+ return (-1);
+
+ status = CryptSetKeyParam (hKey,
+ /* dwParam = */ KP_MODE,
+ /* pbData = */ (void *) &cypherMode,
+ /* dwFlags = */ 0);
+ if (!status)
+ {
+ CryptDestroyKey (hKey);
+ return (-1);
+ }
+
+ status = CryptSetKeyParam (hKey,
+ /* dwParam = */ KP_IV,
+ /* pbData = */ (void *) pbIv,
+ /* dwFlags = */ 0);
+ if (!status)
+ {
+ CryptDestroyKey (hKey);
+ return (-1);
+ }
+
+ *phKey = hKey;
+ return (0);
+} /* }}} nb_key_from_password */
+
+static int nb_add_encryption (lcc_network_buffer_t *nb) /* {{{ */
+{
+ HCRYPTHASH hHash = 0;
+ HCRYPTKEY hKey = 0;
+ DWORD package_length;
+ BYTE *encr_ptr; /* pointer to data being encrypted */
+ DWORD encr_size;
+
+ BYTE *hash_data_ptr; /* pointer to data being hashed */
+ DWORD hash_data_size;
+ DWORD hash_code_size = 20;
+
+ WORD pkg_length;
+ BOOL status;
+
+ /* Fill in the package length */
+ package_length = nb->size - nb->free;
+ pkg_length = htons ((uint16_t) package_length);
+ memcpy (nb->buffer + 2, &pkg_length, sizeof (pkg_length));
+
+ /* Calculate what to hash */
+ hash_data_ptr = (BYTE *) (nb->buffer + PART_ENCRYPTION_AES256_SIZE);
+ hash_data_size = package_length - nb->encr_header_len;
+
+ /* Calculate what to encrypt */
+ encr_ptr = hash_data_ptr - hash_code_size;
+ encr_size = hash_data_size + hash_code_size;
+
+ if (!nb->hProv)
+ {
+ status = CryptAcquireContext (&nb->hProv,
+ /* szContainer = */ NULL,
+ /* CSP name = */ NULL,
+ /* provider type = */ PROV_RSA_AES,
+ /* flags = */ CRYPT_VERIFYCONTEXT);
+ if (!status)
+ return (-1);
+ }
+
+ status = CryptCreateHash (nb->hProv,
+ /* algorithm = */ CALG_SHA1,
+ /* hKey = */ 0,
+ /* dwFlags = */ 0,
+ /* out phHash = */ &hHash);
+ if (!status)
+ return (-1);
+
+ status = CryptHashData (hHash,
+ /* pbData = */ hash_data_ptr,
+ /* dwDataSize = */ hash_data_size,
+ /* dwFlags = */ 0);
+ if (!status)
+ {
+ CryptDestroyHash (hHash);
+ return (-1);
+ }
+
+ status = CryptGetHashParam (hHash,
+ /* dwParam = */ HP_HASHVAL,
+ /* pbData = */ (void *) encr_ptr,
+ /* pwdDataLen = */ &hash_code_size,
+ /* dwFlags = */ 0);
+ if (!status)
+ {
+ CryptDestroyHash (hHash);
+ return (-1);
+ }
+ CryptDestroyHash (hHash);
+
+ status = nb_key_from_password (nb->hProv,
+ nb->password, nb->encr_iv, &hKey);
+ if (!status)
+ return (-1);
+
+ status = CryptEncrypt (hKey,
+ /* hHash = */ 0,
+ /* Final = */ 1, /* last call to CryptEncrypt() */
+ /* dwFlags = */ 0,
+ /* pbData = */ encr_ptr,
+ /* pdwDataLen = */ &encr_size,
+ /* dwBufLen = */ encr_size);
+ if (!status)
+ {
+ CryptDestroyKey (hKey);
+ return (-1);
+ }
+
+ CryptDestroyKey (hKey);
+ return (0);
+} /* }}} int nb_add_encryption */
#elif HAVE_LIBGCRYPT
static int nb_add_signature (lcc_network_buffer_t *nb) /* {{{ */
{
if (nb == NULL)
return (EINVAL);
-#if WIN32
- if (nb->seclevel == SIGN)
- nb_add_signature (nb);
-#elif HAVE_LIBGCRYPT
+#if WIN32 || HAVE_LIBGCRYPT
if (nb->seclevel == SIGN)
nb_add_signature (nb);
else if (nb->seclevel == ENCRYPT)