Bcrypt - AES256 CBC
Source
Source of encrypt function
C
char *aes256_encrypt(const char *input, const unsigned char *key, size_t *output_len) {
BCRYPT_ALG_HANDLE hAlgorithm = NULL;
BCRYPT_KEY_HANDLE hKey = NULL;
DWORD cbKeyObject = 0, cbData = 0, cbCipherText = 0;
PBYTE pbKeyObject = NULL;
PBYTE pbCipherText = NULL;
PBYTE pbIV = NULL;
NTSTATUS status;
char *output = NULL;
// Open an algorithm handle
status = BCryptOpenAlgorithmProvider(&hAlgorithm, BCRYPT_AES_ALGORITHM, NULL, 0);
if (!BCRYPT_SUCCESS(status)) {
fprintf(stderr, "Failed to open algorithm provider: 0x%x\n", status);
return NULL;
}
// Set the chaining mode to CBC
status = BCryptSetProperty(hAlgorithm, BCRYPT_CHAINING_MODE, (PBYTE)BCRYPT_CHAIN_MODE_CBC, sizeof(BCRYPT_CHAIN_MODE_CBC), 0);
if (!BCRYPT_SUCCESS(status)) {
fprintf(stderr, "Failed to set chaining mode: 0x%x\n", status);
goto cleanup;
}
// Calculate the size of the key object
status = BCryptGetProperty(hAlgorithm, BCRYPT_OBJECT_LENGTH, (PBYTE)&cbKeyObject, sizeof(cbKeyObject), &cbData, 0);
if (!BCRYPT_SUCCESS(status)) {
fprintf(stderr, "Failed to get object length: 0x%x\n", status);
goto cleanup;
}
pbKeyObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbKeyObject);
if (!pbKeyObject) {
fprintf(stderr, "Memory allocation failed for key object\n");
goto cleanup;
}
// Generate the key
status = BCryptGenerateSymmetricKey(hAlgorithm, &hKey, pbKeyObject, cbKeyObject, (PUCHAR)key, AES_KEY_SIZE, 0);
if (!BCRYPT_SUCCESS(status)) {
fprintf(stderr, "Failed to generate symmetric key: 0x%x\n", status);
goto cleanup;
}
// Allocate IV (initialization vector)
pbIV = (PBYTE)HeapAlloc(GetProcessHeap(), 0, AES_BLOCK_SIZE);
if (!pbIV) {
fprintf(stderr, "Memory allocation failed for IV\n");
goto cleanup;
}
ZeroMemory(pbIV, AES_BLOCK_SIZE);
// Calculate the required buffer size for ciphertext
status = BCryptEncrypt(hKey, (PUCHAR)input, (ULONG)strlen(input), NULL, pbIV, AES_BLOCK_SIZE, NULL, 0, &cbCipherText, BCRYPT_BLOCK_PADDING);
if (!BCRYPT_SUCCESS(status)) {
fprintf(stderr, "Failed to calculate ciphertext size: 0x%x\n", status);
goto cleanup;
}
pbCipherText = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbCipherText);
if (!pbCipherText) {
fprintf(stderr, "Memory allocation failed for ciphertext\n");
goto cleanup;
}
// Perform the encryption
status = BCryptEncrypt(hKey, (PUCHAR)input, (ULONG)strlen(input), NULL, pbIV, AES_BLOCK_SIZE, pbCipherText, cbCipherText, &cbData, BCRYPT_BLOCK_PADDING);
if (!BCRYPT_SUCCESS(status)) {
fprintf(stderr, "Encryption failed: 0x%x\n", status);
goto cleanup;
}
// Allocate output buffer and copy ciphertext
output = (char *)HeapAlloc(GetProcessHeap(), 0, cbData);
if (!output) {
fprintf(stderr, "Memory allocation failed for output\n");
goto cleanup;
}
memcpy(output, pbCipherText, cbData);
*output_len = cbData;
cleanup:
if (hAlgorithm) BCryptCloseAlgorithmProvider(hAlgorithm, 0);
if (hKey) BCryptDestroyKey(hKey);
if (pbKeyObject) HeapFree(GetProcessHeap(), 0, pbKeyObject);
if (pbCipherText) HeapFree(GetProcessHeap(), 0, pbCipherText);
if (pbIV) HeapFree(GetProcessHeap(), 0, pbIV);
return output;
}
Source of decrypt function
C
char *aes256_decrypt(const char *input, size_t input_len, const unsigned char *key, size_t *output_len) {
BCRYPT_ALG_HANDLE hAlgorithm = NULL;
BCRYPT_KEY_HANDLE hKey = NULL;
DWORD cbKeyObject = 0, cbData = 0, cbPlainText = 0;
PBYTE pbKeyObject = NULL;
PBYTE pbPlainText = NULL;
PBYTE pbIV = NULL;
NTSTATUS status;
char *output = NULL;
// Open an algorithm handle
status = BCryptOpenAlgorithmProvider(&hAlgorithm, BCRYPT_AES_ALGORITHM, NULL, 0);
if (!BCRYPT_SUCCESS(status)) {
fprintf(stderr, "Failed to open algorithm provider: 0x%x\n", status);
return NULL;
}
// Set the chaining mode to CBC
status = BCryptSetProperty(hAlgorithm, BCRYPT_CHAINING_MODE, (PBYTE)BCRYPT_CHAIN_MODE_CBC, sizeof(BCRYPT_CHAIN_MODE_CBC), 0);
if (!BCRYPT_SUCCESS(status)) {
fprintf(stderr, "Failed to set chaining mode: 0x%x\n", status);
goto cleanup;
}
// Calculate the size of the key object
status = BCryptGetProperty(hAlgorithm, BCRYPT_OBJECT_LENGTH, (PBYTE)&cbKeyObject, sizeof(cbKeyObject), &cbData, 0);
if (!BCRYPT_SUCCESS(status)) {
fprintf(stderr, "Failed to get object length: 0x%x\n", status);
goto cleanup;
}
pbKeyObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbKeyObject);
if (!pbKeyObject) {
fprintf(stderr, "Memory allocation failed for key object\n");
goto cleanup;
}
// Generate the key
status = BCryptGenerateSymmetricKey(hAlgorithm, &hKey, pbKeyObject, cbKeyObject, (PUCHAR)key, AES_KEY_SIZE, 0);
if (!BCRYPT_SUCCESS(status)) {
fprintf(stderr, "Failed to generate symmetric key: 0x%x\n", status);
goto cleanup;
}
// Allocate IV (initialization vector)
pbIV = (PBYTE)HeapAlloc(GetProcessHeap(), 0, AES_BLOCK_SIZE);
if (!pbIV) {
fprintf(stderr, "Memory allocation failed for IV\n");
goto cleanup;
}
ZeroMemory(pbIV, AES_BLOCK_SIZE);
// Calculate the required buffer size for plaintext
status = BCryptDecrypt(hKey, (PUCHAR)input, (ULONG)input_len, NULL, pbIV, AES_BLOCK_SIZE, NULL, 0, &cbPlainText, BCRYPT_BLOCK_PADDING);
if (!BCRYPT_SUCCESS(status)) {
fprintf(stderr, "Failed to calculate plaintext size: 0x%x\n", status);
goto cleanup;
}
pbPlainText = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbPlainText);
if (!pbPlainText) {
fprintf(stderr, "Memory allocation failed for plaintext\n");
goto cleanup;
}
// Perform the decryption
status = BCryptDecrypt(hKey, (PUCHAR)input, (ULONG)input_len, NULL, pbIV, AES_BLOCK_SIZE, pbPlainText, cbPlainText, &cbData, BCRYPT_BLOCK_PADDING);
if (!BCRYPT_SUCCESS(status)) {
fprintf(stderr, "Decryption failed: 0x%x\n", status);
goto cleanup;
}
// Allocate output buffer and copy plaintext
output = (char *)HeapAlloc(GetProcessHeap(), 0, cbData + 1); // Add 1 for null terminator
if (!output) {
fprintf(stderr, "Memory allocation failed for output\n");
goto cleanup;
}
memcpy(output, pbPlainText, cbData);
output[cbData] = '\0'; // Null-terminate the string
*output_len = cbData;
cleanup:
if (hAlgorithm) BCryptCloseAlgorithmProvider(hAlgorithm, 0);
if (hKey) BCryptDestroyKey(hKey);
if (pbKeyObject) HeapFree(GetProcessHeap(), 0, pbKeyObject);
if (pbPlainText) HeapFree(GetProcessHeap(), 0, pbPlainText);
if (pbIV) HeapFree(GetProcessHeap(), 0, pbIV);
return output;
}