openssl EVP fails randomly in decryption - c++

I have a problem in using higher level envelope decryption fron openssl/evp.h
EVP_OpenFinal and EVP_OpenInit fail randomly when I try to run the same program multiple times with the same values. I am working on it for last 5 days but no luck. I am writing my complete code here. Please help me out. It would be very nice if someone can try to reproduce the errors, and let me know where I am wrong.
Error message:
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
4944:error:0606506D:lib(6):func(101):reason(109):.\crypto\evp\evp_enc.c:460:
And here is the code
#include <iostream>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <stdio.h>
void handleErrors(void);
int envelope_seal(EVP_PKEY **pub_key, unsigned char *plaintext, int plaintext_len,
unsigned char **encrypted_key, int *encrypted_key_len, unsigned char *iv,
unsigned char *ciphertext);
int envelope_open(EVP_PKEY *priv_key, unsigned char *ciphertext, int ciphertext_len,
unsigned char *encrypted_key, int encrypted_key_len, unsigned char *iv,
unsigned char *plaintext);
using namespace std;
int main()
{
RSA *rsa_pubkey= RSA_new();
RSA *rsa_prikey= RSA_new();
EVP_PKEY *evp_pubkey = EVP_PKEY_new();
EVP_PKEY *evp_prikey = EVP_PKEY_new();
FILE *rsa_prikey_file = NULL;
FILE *rsa_pubkey_file = NULL;
rsa_pubkey_file = fopen("pubkey.pem", "r");
if (!rsa_pubkey_file)
{
fprintf(stderr, "Error loading PEM RSA Public Key File.\n");
exit(2);
}
PEM_read_RSA_PUBKEY(rsa_pubkey_file, &rsa_pubkey,NULL, NULL);
EVP_PKEY_assign_RSA(evp_pubkey,rsa_pubkey);
rsa_prikey_file = fopen("key.pem", "r");
if (!rsa_prikey_file)
{
fprintf(stderr, "Error loading PEM RSA private Key File.\n");
exit(2);
}
PEM_read_RSAPrivateKey(rsa_prikey_file, &rsa_prikey,NULL, NULL);
EVP_PKEY_assign_RSA(evp_prikey,rsa_prikey);
unsigned char *plaintext = (unsigned char*) "The quick brown fox jumps over thes lazy dog";
unsigned char ciphertext[256] = {};
unsigned char plaintextt[256] = {};
int ciphertextlength;
unsigned char *encKey = (unsigned char*)malloc(RSA_size(rsa_pubkey));
unsigned char iv[16] = {};
envelope_seal(&evp_pubkey, plaintext,strlen((const char*)plaintext),&encKey, &ciphertextlength,iv,ciphertext);
envelope_open(evp_prikey, ciphertext, strlen((const char*)ciphertext), encKey, strlen((const char*)encKey),iv,plaintextt);
std::cout <<"Result: "<<plaintextt<<std::endl;
EVP_PKEY_free(evp_pubkey);
EVP_PKEY_free(evp_prikey);
free(ciphertext);
free(encKey);
}
int envelope_seal(EVP_PKEY **pub_key, unsigned char *plaintext, int plaintext_len,
unsigned char **encrypted_key, int *encrypted_key_len, unsigned char *iv,
unsigned char *ciphertext)
{
EVP_CIPHER_CTX *ctx;
int ciphertext_len;
int len;
if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
if(1 != EVP_SealInit(ctx, EVP_aes_128_cbc(),
encrypted_key,
encrypted_key_len,
iv,
pub_key, 1))
{
handleErrors();
}
if(1 != EVP_SealUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
{
handleErrors();
}
ciphertext_len = len;
if(1 != EVP_SealFinal(ctx, ciphertext + len, &len))
{
handleErrors();
}
ciphertext_len += len;
EVP_CIPHER_CTX_free(ctx);
return ciphertext_len;
}
int envelope_open(EVP_PKEY *priv_key, unsigned char *ciphertext, int ciphertext_len,
unsigned char *encrypted_key, int encrypted_key_len, unsigned char *iv,
unsigned char *plaintext)
{
EVP_CIPHER_CTX *ctx;
int len;
int plaintext_len;
if(!(ctx = EVP_CIPHER_CTX_new()))
{
handleErrors();
}
if(1 != EVP_OpenInit(ctx, EVP_aes_128_cbc(), encrypted_key,
encrypted_key_len, iv, priv_key))
{
handleErrors();
}
if(1 != EVP_OpenUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
{
handleErrors();
}
plaintext_len = len;
if(1 != EVP_OpenFinal(ctx, plaintext + len, &len))
{
handleErrors();
}
plaintext_len += len;
EVP_CIPHER_CTX_free(ctx);
plaintext[plaintext_len] = '\0';
return plaintext_len;
}
void handleErrors(void)
{
perror("Error: ");
ERR_print_errors_fp(stderr);
abort();
}

envelope_seal() gives back the length of the encrypted string, I have to put this length in envelope_open()
int **length** = envelope_seal(&evp_pubkey, plaintext,strlen((const char*)plaintext),&encKey, &ciphertextlength,iv,ciphertext);
envelope_open(evp_prikey, ciphertext, **length**, encKey, strlen((const char*)encKey),iv,plaintextt);

The random crashing is caused by your length calculations before envelope_seal and envelope_open. The lengths should look like:
unsigned char *plaintext = (unsigned char*) "The quick brown fox jumps over thes lazy dog";
int ciphertextlength;
unsigned int enclen = EVP_PKEY_size(evp_prikey);
unsigned char *encKey = (unsigned char*)malloc(enclen);
unsigned char *ciphertext = (unsigned char*)malloc(enclen);
unsigned char plaintextt[enclen] = {};
unsigned char iv[16] = {};
unsigned int length = envelope_seal(&evp_pubkey, plaintext,strlen((const char*)plaintext),&encKey, &ciphertextlength,iv,ciphertext);
envelope_open(evp_prikey, ciphertext, length, encKey, enclen,iv,plaintextt);
As your answer states envelope_seal returns the size. You cannot get the size of a char* as your crashing always occured when the size of your plaintext was less than 48.

Related

converting from string to unsigned char * and vice versa

I have two functions: 1. encryption (string text, string key) and 2. decryption (string text, string key). these functions encrypt/decrypt text under key . I use openssl library and functions:EVP_EncryptUpdate and EVP_DecryptUpdate the input arguments of these two functions are (EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl). my functions are below and the output is :
"Hello world\x5\x5\x5\x5\x5"
which should be "Hello world"
i suppose there is something wrong with castings.
std::string encrypt(std::string text, std::string k){
const unsigned char *plaintext=(const unsigned char*) text.c_str();
const unsigned char *key=(const unsigned char*) k.c_str();
EVP_CIPHER_CTX *ctx;
int len;
int plaintext_len=strlen((const char *)plaintext);
int ciphertext_len=plaintext_len+256;
unsigned char * ciphertext=new unsigned char[ciphertext_len];
/* Create and initialise the context */
if(!(ctx = EVP_CIPHER_CTX_new()))
handleErrors();
/*
* Initialise the encryption operation.
*/
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, NULL))
handleErrors();
/*
* Provide the message to be encrypted, and obtain the encrypted output.
* EVP_EncryptUpdate can be called multiple times if necessary
*/
if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
handleErrors();
ciphertext_len = len;
/*
* Finalise the encryption. Further ciphertext bytes may be written at
* this stage.
*/
if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
handleErrors();
ciphertext_len += len;
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
std::string cipherteststring=(char const* )ciphertext ;
delete []ciphertext;
return cipherteststring;
}
std::string decrypt(std::string text, std::string k)
{
const unsigned char *ciphertext=(const unsigned char*)text.c_str();
const unsigned char *key=(const unsigned char*) k.c_str();
int ciphertext_len=strlen((const char *)ciphertext);
EVP_CIPHER_CTX *ctx;
int len;
int plaintext_len=ciphertext_len;
unsigned char *decryptedtext=new unsigned char[plaintext_len];
/* Create and initialise the context */
if(!(ctx = EVP_CIPHER_CTX_new()))
handleErrors();
/*
* Initialise the decryption operation.
*/
if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, NULL))
handleErrors();
/*
* Provide the message to be decrypted, and obtain the plaintext output.
* EVP_DecryptUpdate can be called multiple times if necessary.
*/
if(1 != EVP_DecryptUpdate(ctx, decryptedtext, &len, ciphertext, ciphertext_len))
handleErrors();
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
//std::string plaintextstring( reinterpret_cast< char const* >(decryptedtext) ) ;
std::string plaintextstring=(char const*)decryptedtext;
decryptedtext[plaintext_len] = '\0';
delete []decryptedtext;
return plaintextstring;
}
int main (){
std::string key ="01234567890123456789012345678901";
std::string plaintext ="Hello world";
std::string encrypted;
std::string decrypted;
std::string decryptedhexstr;
encrypted=encrypt (plaintext,key);
decrypted = decrypt(encrypted, key);
cout<<decrypted;
return 0;
}``

How to translate openssl command pbkdf2 in c languge?

Hy guys, another problem about openssl:
I have this command:
openssl enc -aes-192-cbc -pbkdf2 -e -in <infile> -out <outfile> -pass pass:password
Now i have only the ciphertext of this command and i know the password and then i know also the salt that is the first 8 bytes of the ciphertext after the string "Salted__". I know also that openssl as default parameter take 1000 iteration count and sha256 as a digest. My problem is: how i can go back to the derived key and derived iv from c language?
My code is this but it not return the right values:
void decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *plaintext, const char *password, unsigned char* salt){
EVP_CIPHER_CTX *ctx;
int len;
int plaintext_len;
//unsigned char* key = "EF04020D6979FC09CC1859A2BFB832FFFCF57C64BA61F682"; right value
//unsigned char* iv = "722EDDC813763C9AAB96A0A6885CE1DB"; right value
unsigned char key[24], iv[16];
int i;
PKCS5_PBKDF2_HMAC(password, strlen(password), (unsigned char*)salt, strlen(salt), 1000, EVP_sha256(), 16, key);
EVP_BytesToKey(EVP_aes_192_cbc(), EVP_sha256(), (unsigned char*)salt, (unsigned char*)password, strlen(password), 1000, key+16, iv);
printf("Key: "); for(i=0; i < 24; ++i){ printf("%02x", key[i]); } printf("\n");
printf("IV: "); for(i=0; i < 16; ++i){ printf("%02x", iv[i]); } printf("\n\n");
//Create and initialise the context
if(!(ctx = EVP_CIPHER_CTX_new()))
handleErrors();
//Initialise the decryption operation. IMPORTANT - ensure you use a key
//and IV size appropriate for your cipher
if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_192_cbc(), NULL, key, iv))
handleErrors();
//Provide the message to be decrypted, and obtain the plaintext output.
//EVP_DecryptUpdate can be called multiple times if necessary.
if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
handleErrors();
plaintext_len = len;
//Finalise the decryption. Further plaintext bytes may be written at
//this stage.
if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len))
handleErrors();
plaintext_len += len;
//Clean up
EVP_CIPHER_CTX_free(ctx);
}
The right values are commented and i take it from the terminal.... but my c code don't return that values.
I think this depends by the fact that i don't translate well the -pbkdf2 derivation key...Help me please
I solved this problem seeing in the source code of openssl on GitHub:
https://github.com/openssl/openssl/blob/master/apps/enc.c

bad decrypt Error OpenSSL C++ & QT AES 256 CBC

I'm trying to add plaintext encryption/decryption (AES 256 CBC) functionality to a personal project built using QT and C++. I'm using OpenSSL v1.1.1. I followed few guides and build a class to handle encryption and decryption. Encryption seems to work fine. But decryption function sometimes throws error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
This works:
sample text here....
These does not ( . = newline ):
i.
sample text here...
.
.
.
.
.
ii.
sample text here... sample text here...
I'm new to QT, C++ and OpenSSL so I have no idea how to fix this.
My Class:
#define KEYSIZE 32
#define IVSIZE 32
#define BLOCKSIZE 256
#define SALTSIZE 8
QByteArray Encryptor::randBytes(int size) {
unsigned char array[size];
RAND_bytes(array, size);
QByteArray output = QByteArray(reinterpret_cast<char*> (array), size);
return output;
}
QByteArray Encryptor::encrypt(QByteArray passphrase, QByteArray &content) {
QByteArray msalt = randBytes(SALTSIZE);
int rounds = 1;
unsigned char key[KEYSIZE];
unsigned char iv[IVSIZE];
const unsigned char *password = (const unsigned char*) passphrase.constData();
const unsigned char *salt = (const unsigned char*) msalt.constData();
int i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), salt, password, passphrase.length(), rounds, key, iv);
if (i != KEYSIZE) {
qCritical() << "EVP_BytesToKey() -- " << ERR_error_string(ERR_get_error(), NULL);
return QByteArray();
}
EVP_CIPHER_CTX *en = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(en);
if (!EVP_EncryptInit_ex(en, EVP_aes_256_cbc(), NULL, key, iv)) {
qCritical() << "EVP_EncryptInit_ex() -- " << ERR_error_string(ERR_get_error(), NULL);
return QByteArray();
}
char *input = content.data();
char *out;
int length = content.size();
int cLength = length + AES_BLOCK_SIZE;
int fLength = 0;
unsigned char *cipherText = (unsigned char*) malloc(cLength);
if (!EVP_EncryptInit_ex(en, NULL, NULL, NULL, NULL)) {
qCritical() << "EVP_EncryptInit_ex() -- " << ERR_error_string(ERR_get_error(), NULL);
return QByteArray();
}
if (!EVP_EncryptUpdate(en, cipherText, &cLength, (unsigned char*) input, length)) {
qCritical() << "EVP_EncryptUpdate() -- " << ERR_error_string(ERR_get_error(), NULL);
free(cipherText);
return QByteArray();
}
if (!EVP_EncryptFinal(en, cipherText + cLength, &fLength)) {
qCritical() << "EVP_EncryptFinal() -- " << ERR_error_string(ERR_get_error(), NULL);
free(cipherText);
return QByteArray();
}
length = cLength + fLength;
out = (char*) cipherText;
EVP_CIPHER_CTX_cipher(en);
free(cipherText);
QByteArray output;
output.append("Salted__");
output.append(msalt);
output.append(out, length);
return output;
}
QByteArray Encryptor::decrypt(QByteArray passphrase, QByteArray &content) {
QByteArray msalt;
if (QString(content.mid(0, 8)) != "Salted__") {
qCritical() << "can not extrect the salt...";
return QByteArray();
}
msalt = content.mid(8, 8);
content = content.mid(16);
int rounds = 1;
unsigned char key[KEYSIZE];
unsigned char iv[IVSIZE];
const unsigned char *password = (const unsigned char*) passphrase.constData();
const unsigned char *salt = (const unsigned char*) msalt.constData();
int i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), salt, password, passphrase.length(), rounds, key, iv);
if (i != KEYSIZE) {
qCritical() << "EVP_BytesToKey() -- " << ERR_error_string(ERR_get_error(), NULL);
return QByteArray();
}
EVP_CIPHER_CTX *de = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(de);
if (!EVP_DecryptInit_ex(de, EVP_aes_256_cbc(), NULL, key, iv)) {
qCritical() << "EVP_DecryptInit_ex() -- " << ERR_error_string(ERR_get_error(), NULL);
return QByteArray();
}
char *input = content.data();
int length = content.size();
int pLength = length;
int fLength = 0;
unsigned char *plainText = (unsigned char*) malloc(pLength + AES_BLOCK_SIZE);
if (!EVP_DecryptUpdate(de, plainText, &pLength, (unsigned char*) input, length)) {
qCritical() << "EVP_DecryptUpdate() -- " << ERR_error_string(ERR_get_error(), NULL);
free(plainText);
return QByteArray();
}
if (!EVP_DecryptFinal_ex(de, plainText + pLength, &fLength)) {
qCritical() << "EVP_DecryptFinal_ex() -- " << ERR_error_string(ERR_get_error(), NULL);
free(plainText);
return QByteArray();
}
length = pLength + fLength;
EVP_CIPHER_CTX_cleanup(de);
QByteArray output = QByteArray(reinterpret_cast<char*> (plainText), length);
free(plainText);
return output;
}

Generate encrypted data with size not multiple of 16

I want to develop functions for encrypt and decrypt. the key size should be at least 128 bits (16 bytes).
I used the AES* api functions from the OpenSSL. but there is some restriction in the AES* functions: the input data buffers should be multiple of 16!
Here after my functions:
unsigned char encrypt_aes_key[]={0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};
static inline int enc_array_decrypt(unsigned char *encarray, unsigned char *decarray, int size)
{
int i;
AES_KEY dec_key;
unsigned char apibuf[512] = {0};
unsigned char iv[AES_BLOCK_SIZE];
memset(iv, 0x00, AES_BLOCK_SIZE);
AES_set_decrypt_key(encrypt_aes_key, sizeof(encrypt_aes_key)*8, &dec_key); // Size of key is in bits
AES_cbc_encrypt(encarray, apibuf, size, &dec_key, iv, AES_DECRYPT);
memcpy(decarray, apibuf, size);
return 0;
}
static inline int enc_array_encrypt(unsigned char *array, unsigned char *encarray, int size)
{
int i;
AES_KEY enc_key;
unsigned char apibuf[512] = {0};
unsigned char iv[AES_BLOCK_SIZE];
memset(iv, 0x00, AES_BLOCK_SIZE);
AES_set_encrypt_key(encrypt_aes_key, sizeof(encrypt_aes_key)*8, &enc_key); // Size of key is in bits
AES_cbc_encrypt((unsigned char *)array, apibuf, size, &enc_key, iv, AES_ENCRYPT);
memcpy(encarray, apibuf, size);
return 0;
}
if I call my functions with buffer size 9 for example, the functions will return wron output
example:
int main(int argc, char *argv[] )
{
char buf[9] = {0}, encbuf[9] = {0}, decbuf[9] = {0};
strcpy(buf, argv[1]);
enc_array_encrypt(buf, encbuf, 9);
enc_array_decrypt(encbuf, decbuf, 9);
printf("%s \n%s\n", buf, decbuf);
return 0;
}
The program returns:
$ ./myprogram any
any
2�����S�
How I can fix that?
by the way I can not force the buffer to be 16x multiplier size. because I will integrate my functions in a big source code (SDK) in which I will call my functions in many places with different input buffer sizes.
I m open to use any other kind of encryption (other than AES), but should support key of 128 bits length. The input buffer and the encrypted buffer should have the same size
It's generally not recommended to use the AES* function directly in OpenSSL. It's better to use the EVP family of functions. These will allow you to give an input buffer of any length.
void log_ssl_err(const char *mes)
{
unsigned long err;
char errstr[1000];
while ((err = ERR_get_error())) {
ERR_error_string(err, errstr);
printf("%s: %s", mes, errstr);
}
}
int encrypt_block(const unsigned char *IV, const unsigned char *key,
const unsigned char *src, unsigned int srclen,
unsigned char *dest, unsigned int *destlen)
{
EVP_CIPHER_CTX ctx;
const EVP_CIPHER *cipher = EVP_get_cipherbyname("AES-256-CBC");
int mode, len;
if (cipher == NULL) {
printf("Invalid keytype");
return 0;
}
mode = EVP_CIPHER_mode(cipher);
EVP_CIPHER_CTX_init(&ctx);
if (!EVP_EncryptInit_ex(&ctx, cipher, NULL, NULL, NULL)) {
log_ssl_err("EncryptInit for cipher failed");
return 0;
}
if (!EVP_EncryptInit_ex(&ctx, NULL, NULL, key, IV)) {
log_ssl_err("EncryptInit for key/IV failed");
return 0;
}
len = 0;
if (!EVP_EncryptUpdate(&ctx, dest, &len, src, srclen)) {
log_ssl_err("EncryptUpdate for data failed");
EVP_CIPHER_CTX_cleanup(&ctx);
return 0;
}
*destlen = len;
if (!EVP_EncryptFinal_ex(&ctx, dest + *destlen, &len)) {
log_ssl_err("EncryptFinal failed");
EVP_CIPHER_CTX_cleanup(&ctx);
return 0;
}
*destlen += len;
EVP_CIPHER_CTX_cleanup(&ctx);
return 1;
}
int decrypt_block(const unsigned char *IV, const unsigned char *key,
unsigned char *src, unsigned int srclen,
unsigned char *dest, unsigned int *destlen)
{
EVP_CIPHER_CTX ctx;
const EVP_CIPHER *cipher = EVP_get_cipherbyname("AES-256-CBC");
int mode, len;
if (cipher == NULL) {
printf("Invalid keytype");
return 0;
}
mode = EVP_CIPHER_mode(cipher);
EVP_CIPHER_CTX_init(&ctx);
if (!EVP_DecryptInit_ex(&ctx, cipher, NULL, NULL, NULL)) {
log_ssl_err("DecryptInit for cipher failed");
return 0;
}
if (!EVP_DecryptUpdate(&ctx, dest, &len, src, srclen)) {
log_ssl_err("DecryptUpdate for data failed");
EVP_CIPHER_CTX_cleanup(&ctx);
return 0;
}
*destlen = len;
if (!EVP_DecryptFinal_ex(&ctx, dest + *destlen, &len)) {
log_ssl_err("DecryptFinal failed");
EVP_CIPHER_CTX_cleanup(&ctx);
return 0;
}
*destlen += len;
EVP_CIPHER_CTX_cleanup(&ctx);
return 1;
}

mysql udf respond is random

I call the function AES_Dec with the same Parameters. In most of the cases it returns the correct respond. But with a randomness of around 15% the respond is different.
char* AES_Dec(UDF_INIT* initid, UDF_ARGS* args, char* result, unsigned long* length, char* is_null, char* error)
{
//initialize variables
//initialize key
char *keyPlain = args->args[1];
int keylength = (static_cast<int>(args->lengths[1])) / 2;
uint16_t *key = new uint16_t;
hex2bin(keyPlain, reinterpret_cast<unsigned char*>(key));
//output
char *output = new char;
bin2hex(key , keylength, output);
*length = keylength* 2;
return output;
}
void hex2bin(const char* src, unsigned char* target)
{
while (*src && src[1])
{
*(target++) = char2int(*src) * 16 + char2int(src[1]);
src += 2;
}
}
int char2int(char input)
{
if (input >= '0' && input <= '9')
return input - '0';
if (input >= 'A' && input <= 'F')
return input - 'A' + 10;
if (input >= 'a' && input <= 'f')
return input - 'a' + 10;
return 0;
}
void bin2hex(unsigned short* pv, size_t len, char *output)
{
const unsigned char * buf = reinterpret_cast<const unsigned char*>(pv);
static const char* hex_lookup = "0123456789ABCDEF";
char *p = output;
for (int i = 0; i < len; i++) {
*p++ = hex_lookup[buf[i] >> 4];
*p++ = hex_lookup[buf[i] & 0x0F];
}
*p = '\0';
}
I call this function with the following parameters:
SELECT AES_Dec('2C4E907536FBB3C9FADD4CFBD45950EF03517AA5F7F402DA9E3ABD03FC6E0068EF39F3DFC26A92B871E8D8CE521EAF6C', 'B99DD1D646CDBC8505419D069B5C0209', '1')
The correct respond which is returned most of the time is:
B99DD1D646CDBC8505419D069B5C0209
And the respond which comes randomly is
B2323332333333323333333333333332
There are only these two responses. And I have no idea why the random respond appears. In a console application it all works fine without any problems. So the code should work.
Have anyone a solution?
Thank you.
Edit: the full quellcode:
#include "Header.h"
#ifdef HAVE_DLOPEN
my_bool AES_Dec_init(UDF_INIT *initid, UDF_ARGS *args, char *message) {
if (args->arg_count != 3) {
return 1;
}
else if (args->arg_type[0] != STRING_RESULT ||
args->arg_type[1] != STRING_RESULT ||
args->arg_type[2] != STRING_RESULT) {
return 1;
}
return 0;
}
void AES_Dec_clear(UDF_INIT *initid, char *is_null, char *message) {
}
void AES_Dec_add(UDF_INIT *initid, UDF_ARGS *args,
char *is_null, char *message) {
}
char* AES_Dec(UDF_INIT* initid, UDF_ARGS* args, char* result, unsigned long* length, char* is_null, char* error)
{
//initialize variables
//initialize modus
char* modChar = args->args[2];
int mod;
if (modChar[0] == '1')
mod = 1;
else
mod = 0;
//initialize key
char *keyPlain = args->args[1];
int keylength = (static_cast<int>(args->lengths[1])) / 2;
uint16_t *key = new uint16_t;
hex2bin(keyPlain, reinterpret_cast<unsigned char*>(key));
//initialize value
const char *plain = args->args[0];
int plainLength = 0;
if (mod == 0)
plainLength = args->lengths[0] / 2;
else
plainLength = args->lengths[0] / 2 - 16;
uint16_t *contentWithIv = new uint16_t;
uint16_t *iv = new uint16_t;
hex2bin(plain, (unsigned char*)contentWithIv);
if (mod == 1) {
for (int i = 0; i < 8; i++) {
iv[i] = *contentWithIv;
contentWithIv++;
}
}
else
iv == NULL;
uint16_t *plaintext = contentWithIv;
// Buffer for the decrypted text
uint16_t *decryptedtext = new uint16_t;
int decryptedtext_len, ciphertext_len;
// Initialise the library
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
OPENSSL_config(NULL);
// Encrypt the plaintext
decryptedtext_len = decrypt((unsigned char*)plaintext, plainLength, (unsigned char*)key, (unsigned char*)iv, (unsigned char*)decryptedtext, keylength * 8, mod);
// Add a NULL terminator. We are expecting printable text
decryptedtext[decryptedtext_len] = '\0';
// Clean up
EVP_cleanup();
ERR_free_strings();
char *finalDec = (char*)malloc(decryptedtext_len * 2);
bin2hex(decryptedtext, decryptedtext_len, finalDec);
*length = decryptedtext_len * 2;
return finalDec;
}
void AES_Dec_deinit(UDF_INIT *initid) {
free(initid->ptr);
}
void handleErrors(void) {
ERR_print_errors_fp(stderr);
abort();
}
int decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, unsigned char *iv, unsigned char *plaintext, int keylength, int mod)
{
EVP_CIPHER_CTX *ctx;
int len;
int plaintext_len;
// Create and initialise the context
if (!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
// Initialise the decryption operation.
if (mod == 0) {
if (keylength == 128)
if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, NULL))
handleErrors();
if (keylength == 192)
if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_192_ecb(), NULL, key, NULL))
handleErrors();
if (keylength == 256)
if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_ecb(), NULL, key, NULL))
handleErrors();
}
else if (mod == 1) {
if (keylength == 128)
if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv))
handleErrors();
if (keylength == 192)
if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_192_cbc(), NULL, key, iv))
handleErrors();
if (keylength == 256)
if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
handleErrors();
}
else
handleErrors();
// Provide the message to be decrypted, and obtain the plaintext output.
if (1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
handleErrors();
plaintext_len = len;
// Finalise the decryption.
if (1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) handleErrors();
plaintext_len += len;
// Clean up
EVP_CIPHER_CTX_free(ctx);
return plaintext_len;
}
void hex2bin(const char* src, unsigned char* target)
{
while (*src && src[1])
{
*(target++) = char2int(*src) * 16 + char2int(src[1]);
src += 2;
}
}
int char2int(char input)
{
if (input >= '0' && input <= '9')
return input - '0';
if (input >= 'A' && input <= 'F')
return input - 'A' + 10;
if (input >= 'a' && input <= 'f')
return input - 'a' + 10;
return 0;
}
void bin2hex(unsigned short* pv, size_t len, char *output)
{
const unsigned char * buf = reinterpret_cast<const unsigned char*>(pv);
static const char* hex_lookup = "0123456789ABCDEF";
char *p = output;
for (int i = 0; i < len; i++) {
*p++ = hex_lookup[buf[i] >> 4];
*p++ = hex_lookup[buf[i] & 0x0F];
}
*p = '\0';
}
#endif /* HAVE_DLOPEN */