In a database there is string encrypted with glibc's xencrypt which is using internally cbc_crypt and the decryption was happening with xdecrypt function which also uses cbc_crypt.
Since glibc 2.32 there is no way to enable again xencrypt and xdecrypt functions.
So I am trying to decrypt the encrypted string with openssl with command:
openssl enc -des-cbc -d -in encrypted.enc -out decrypted.txt -iv 0000000000000000 -K <my key in hex>
But I get:
bad decrypt 140401522647424:error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length:../openssl-1.1.1k/crypto/evp/evp_enc.c:599
What am I doing wrong and is there an openssl command or function call that can provide the same result as xdecrypt (cbc_encrypt)?
***** UPDATE *****
I tried to solve the above question also programmatically.
So I used the following code in order to be also in topic as #dave_thompson_085 mentioned in comment.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rpc/des_crypt.h>
#include <openssl/des.h>
#include <openssl/pkcs7.h>
#define BUFFSIZE 420
int glibc_encrypt(const char *, const char *, const char *, char **, unsigned int *);
int glibc_decrypt(const char *, const char *, const char *, char **);
int openssl_encrypt(const char *, const char *, const char *, unsigned int, char *, unsigned int *);
int openssl_decrypt(const char *, const char *, char *, unsigned int, char **);
int main(void) {
const char *key = "abcdefgh";
const char *ivec = "87654321";
const char *data = "mypass1234test";
char *dst_buf;
unsigned int dst_size;
char *final_buf;
glibc_encrypt(key, ivec, data, &dst_buf, &dst_size);
glibc_decrypt(key, ivec, (const char *) dst_buf, &final_buf);
openssl_encrypt(key, ivec, data, strlen(data), dst_buf, &dst_size);
openssl_decrypt(key, ivec, dst_buf, dst_size, &final_buf);
return 0;
}
int glibc_encrypt(const char *key, const char *ivec, const char *data, char **dst, unsigned int *dst_size) {
char tmpkey[BUFFSIZE], tmpivec[BUFFSIZE];
unsigned int rawsize, i, result, pading;
printf("*** glibc encrytion ***\n");
strncpy(tmpkey, key, strlen(key));
strncpy(tmpivec, ivec, strlen(ivec));
des_setparity(tmpkey);
rawsize = strlen(data);
printf("data to be ecrypted is : %s\n", data);
printf("size of data to be encrypted is : %d\n", rawsize);
/* Add to data to ensure size is divisable by 8. */
pading = 8 - (rawsize % 8);
*dst_size = rawsize + pading;
printf("data size were rounded to : %d\n", *dst_size);
/* Allocate the containing ecryption buffer */
*dst = malloc(*dst_size);
memcpy(*dst, data, *dst_size);
for (i = rawsize ; i < *dst_size; i++)
dst[i] = '\0';
result = cbc_crypt(tmpkey, *dst, *dst_size, DES_ENCRYPT | DES_SW, tmpivec);
if (DES_FAILED(result) || strcmp(*dst, "") == 0) {
if(strcmp(*dst, "") == 0)
printf("*** Null Output ***\n");
else
printf("*** Encryption Error ***\n");
} else {
snprintf(tmpkey, *dst_size, "%s", *dst);
printf("glibc encrypted data : %s\n", tmpkey);
}
return 0;
}
int glibc_decrypt(const char *key, const char *ivec, const char *data, char **dst) {
char tmpkey[BUFFSIZE], tmpivec[BUFFSIZE];
unsigned int dstsize;
int result;
printf("\n*** glibc decryption ***\n");
strncpy(tmpkey, key, strlen(key));
strncpy(tmpivec, ivec, strlen(ivec));
des_setparity(tmpkey);
dstsize = strlen(data);
printf("data to be decrypted is : %s\n", data);
printf("size of data to be decrypted is : %d\n", dstsize);
/* Allocate the containing ecryption buffer */
*dst = malloc(dstsize);
memcpy(*dst, data, dstsize);
result = cbc_crypt(tmpkey, *dst, dstsize, DES_DECRYPT | DES_SW, tmpivec);
if(DES_FAILED(result) || strcmp(*dst, "") == 0) {
if(strcmp(*dst, "") == 0)
printf("*** Null Output ***\n");
else
printf("*** Decryption Error ***\n");
} else {
snprintf(tmpkey, dstsize, "%s", *dst);
printf("glibc decrypted data : %s\n", tmpkey);
}
return 0;
}
int openssl_encrypt(const char *key, const char *ivec, const char *_raw_ptr, unsigned int _raw_size, char *_dst_buf, unsigned int *_dst_size) {
DES_key_schedule schedule;
char tmpkey[BUFFSIZE];
DES_cblock *iv3;
int pading;
size_t i, vt_size;
char *mid_buf;
printf("\n*** openssl ecryption ***\n");
strncpy(tmpkey, key, strlen(key));
printf("data to be ecrypted is : %s\n", _raw_ptr);
printf("size of data to be encrypted is : %d\n", _raw_size);
DES_set_key_unchecked((const_DES_cblock*) &tmpkey, &schedule);
vt_size = strlen(ivec);
iv3 = (DES_cblock *) malloc(vt_size * sizeof(unsigned char));
memcpy(iv3, ivec, vt_size);
pading = 8 - (_raw_size % 8);
*_dst_size = _raw_size + pading;
printf("data size were rounded to : %d\n", *_dst_size);
mid_buf = malloc(*_dst_size);
memcpy(mid_buf, _raw_ptr, _raw_size );
/* Add to data to ensure size is divisable by 8. */
for (i = _raw_size ; i < *_dst_size; i++ )
mid_buf[i] = '\0';
DES_ncbc_encrypt((const unsigned char*) mid_buf, (unsigned char *) _dst_buf, *_dst_size, &schedule, iv3, DES_ENCRYPT);
printf("openssl ecrypted data : %s\n", _dst_buf);
printf("openssl ecrypted data size : %d\n", *_dst_size);
free(iv3);
free(mid_buf);
return 0;
}
int openssl_decrypt(const char *key, const char *ivec, char *_raw_ptr, unsigned int _raw_size, char **_dst_buf) {
DES_key_schedule schedule;
char tmpkey[BUFFSIZE];
DES_cblock *iv3;
size_t vt_size;
printf("\n*** openssl decryption ***\n");
strncpy(tmpkey, key, strlen(key));
printf("data to be decrypted is : %s\n", _raw_ptr);
printf("size of data to be dencrypted is: %d\n", _raw_size);
DES_set_key_unchecked((const_DES_cblock*) &tmpkey, &schedule);
vt_size = strlen(ivec);
iv3 = (DES_cblock *) malloc(vt_size * sizeof(unsigned char));
memcpy(iv3, ivec, vt_size);
*_dst_buf = (char*) malloc(_raw_size);
DES_ncbc_encrypt((const unsigned char*) _raw_ptr, (unsigned char *) *_dst_buf, _raw_size, &schedule, iv3, DES_DECRYPT);
printf("openssl decrypted data : %s\n", *_dst_buf);
free(iv3);
return 0;
}
And here is the output:
*** glibc encrytion ***
data to be ecrypted is : mypass1234test
size of data to be encrypted is : 14
data size were rounded to : 16
glibc encrypted data :▒!▒e͛▒4▒ k
▒▒
*** glibc decryption ***
data to be decrypted is :▒!▒e͛▒4▒ k
▒▒d
size of data to be decrypted is : 16
glibc decrypted data : mypass1234test
*** openssl ecryption ***
data to be ecrypted is : mypass1234test
size of data to be encrypted is : 14
data size were rounded to : 16
openssl ecrypted data : ▒▒▒▒˛▒▒▒uc▒
openssl ecrypted data size : 16
*** openssl decryption ***
data to be decrypted is : ▒▒▒▒˛▒▒▒uc▒
size of data to be dencrypted is: 16
openssl decrypted data : mypass1234test
Both openssl and glibc implementations encrypt and decrypt the data.
But if used interchangeably the outcome if not correct.
I would expect the encrypted data from both of them to be exactly the same if the DES implementation is the same, as it should be I guess since the algorithm should produce the same output.
So why openssl and glibc produce seemingly different encrypted data when the same algorithm is used?
DISCLAIMER
This is not the correct answer but rather a work around I found and used in case some else wants to use the same solution.
The main problem is that recent glibc version do not provide any more the function cbc_crypt and hence xencrypt and xdecrypt.
But libtirpc (http://sourceforge.net/projects/libtirpc) includes the missing cbc_crypt function.
So instead of using openssl to decrypt the cbc_crypted staff I used the libtirp library.
Related
I'm trying to write a C program to brute force AES decryption using openssl. However, when I tried to decrypt the message by passing a key attackKey, I got and error printed from the decrypt() function. The error is as follows
There was an error calling the decrypted final object...: Success
The code is given below, I tried reading the book on Openssl for more information but as it is quite outdated it was not helpful. I also googled and barely found any resources on my issue and yes I am well aware of the fact that brute forcing aes_128 is a pipe dream. I am just testing some things with this library to see if the key is only a few combinations ahead, so can I iterate on the attackKey and try to get the decrypted text.
#include <string.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <stdbool.h>
#include <openssl/err.h>
#define BUFFER_SIZE 64
// void addPadding(unsigned char *buff, );
int encrypt(const unsigned char *plaintext, const int plaintext_len, const unsigned char *key, unsigned char *ciphertext);
int decrypt(const unsigned char *ciphertext, const int ciphertext_len, const unsigned char *key, unsigned char *decryptedtext);
void iterateKey(unsigned char *key, const int length);
bool compareKeys(const unsigned char *key1, const unsigned char *key2, const int length);
void *bruteForceAttack(void *arg);
int main(int argc, char *argv[])
{
OpenSSL_add_all_algorithms(); // load all cipher algorithms
ERR_load_crypto_strings(); // load human readable errors
/* A 256 bit key */
unsigned char key[] = "abcdefghijklmnqp"; // 6 + 1 bytes
unsigned char plaintext[] = "Hello, my name is shaheryar ;)."; // 32 + 1 bytes
/* Buffer to store the ciphertext. The size may be different due to padding. */
unsigned char ciphertext[BUFFER_SIZE];
int ciphertext_len = 0;
/* Encryption. */
ciphertext_len = encrypt(plaintext, strlen((char *)plaintext), key, ciphertext);
printf("Length of text:%d, Ciphertext is:\n", ciphertext_len);
BIO_dump_fp(stdout, (const char *)ciphertext, ciphertext_len);
//----------------MAIN DECRYPTION LOGIC
/* Buffer for the decrypted text for verifying decryption. */
unsigned char decryptedtext[BUFFER_SIZE];
int decryptedtext_len = 0;
unsigned char attackKey[] = "abcdefghijklmnop";
const int attackKey_len = 17;
for (int i = 0; i < 10e2; i++)
{
// printf("Key : %s\n", attackKey);
decryptedtext_len = 0;
decryptedtext_len = decrypt(ciphertext, ciphertext_len, attackKey, decryptedtext);
decryptedtext[decryptedtext_len] = '\0';
if (strcmp((const char *)attackKey, (const char *)key) == 0)
{
printf("\nLength of text: %d, Decryptedtext is: %s\n", decryptedtext_len, decryptedtext);
}
iterateKey(attackKey, attackKey_len);
}
//------------END OF DECRYPTION PHASE
if (strncmp((const char *)plaintext, (const char *)decryptedtext, decryptedtext_len))
{
printf("FAIL: enc/dec failed for \"%s\"\n", decryptedtext);
}
else
{
printf("OK: enc/dec ok for \"%s\"\n", plaintext);
}
return 0;
}
int encrypt(const unsigned char *plaintext, const int plaintext_len, const unsigned char *key, unsigned char *ciphertext)
{
/* The following object is used to keep track of the key and internal states*/
EVP_CIPHER_CTX *ctx = NULL;
int len = 0, ciphertext_len = 0;
/* Create and initialize the context and returns a pointer for success and null for failure*/
if (!(ctx = EVP_CIPHER_CTX_new()))
{
printf("There was an error creating the encryption object...");
}
/* Initialize the encryption operation. */
if (!EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, NULL))
{
printf("There was an error loading the encryption object...");
}
if (plaintext)
{
if (!EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
{
printf("There was an error creating the update the encryption object...");
}
ciphertext_len = len;
}
if (!EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
{
printf("There was an error encrypting the final object...");
}
ciphertext_len += len;
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
return ciphertext_len;
}
int decrypt(const unsigned char *ciphertext, const int ciphertext_len, const unsigned char *key, unsigned char *decryptedtext)
{
/* The following object is used to keep track of the key and internal states*/
EVP_CIPHER_CTX *ctx = NULL;
int len = 0, decryptedtext_len = 0;
/* Create and initialize the context and returns a pointer for success and null for failure*/
if (!(ctx = EVP_CIPHER_CTX_new()))
{
printf("There was an error creating the decryption object...");
}
/* Initialize the encryption operation. */
if (!EVP_DecryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, NULL))
{
printf("There was an error initializing the cipher object...");
}
if (ciphertext)
{
if (!EVP_DecryptUpdate(ctx, decryptedtext, &len, ciphertext, ciphertext_len))
{
printf("There was an error decrypting the cipher text...");
}
decryptedtext_len = len;
}
if (!EVP_DecryptFinal_ex(ctx, decryptedtext + len, &len))
{
printf("There was an error calling the decrypted final object...");
}
decryptedtext_len += len;
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
return decryptedtext_len;
}
bool compareKeys(const unsigned char *key1, const unsigned char *key2, const int length)
{
for (int i = 0; i < length; i++)
{
if (key1[i] != key2[i])
{
return false;
}
}
return true;
}
void iterateKey(unsigned char *key, const int length)
{
for (int i = 0; i < (length - 1); i++)
{
if (key[length - 2 - i] == 'z')
{
key[length - 2 - i] = 'a';
}
else
{
key[length - 2 - i]++;
return;
}
}
}
void *bruteForceAttack(void *arg)
{
return NULL;
}
Below are the resources I used for implementing the code:
https://www.cs.ucy.ac.cy/courses/EPL326/labs/lab3/aesimplentation.pdf
https://www.oreilly.com/library/view/network-security-with/059600270X/
I am working on AES-128/192/256, basically I am getting data from a broker as string, I just need to encrypt that data and I need to verify that.
I already come across these https://github.com/empyreanx/tiny-AES128-C, https://github.com/kokke/tiny-AES-c links.
My code is:
static void test_encrypt_cbc(void)
{
unsigned char input[] =
"So_letmeknowRuinterested/towork#thiscompany.comElsewilllookother";
//64bits
unsigned char cipher[sizeof input];
printf("size of in:%lu\n",strlen(input));
unsigned char key[] = "Gns7AauH3dnaod=="; //16 bits
unsigned char iv[] = "vhdNaleuTHenaOlL"; //16 bits
AES128_CBC_encrypt_buffer(cipher, input, 64, key, iv);
if(0 == memcmp((char*) cipher, (char*) input, 64))
{
printf("SUCCESS!\n");
}
else
{
printf("FAILURE!\n");
}
}
I also printed cipher text after encryption it is printing some undefined character.
I don't know but I am comparing "cipher" with "input", Its FAILURE finally!
Please anyone can tell me where I am doing wrong.
Thanks in advance.
This is logical to cipher to be different from input, isn't?
To check that encryption worked, you should decrypt the encoded message and check that they are equal:
static void test_encrypt_cbc(void)
{
/* 64 bytes, or 512 bits */
unsigned char input[] =
"So_letmeknowRuinterested/towork#thiscompany.comElsewilllookother";
unsigned char cipher[sizeof input];
unsigned char output[sizeof input];
printf("size of in:%lu\n",strlen(input));
/* 16 bytes or 128 bits */
unsigned char key[] = "Gns7AauH3dnaod==";
unsigned char iv[] = "vhdNaleuTHenaOlL";
/* input --> cipher */
AES128_CBC_encrypt_buffer(cipher, input, 64, key, iv);
/* cipher --> output */
AES128_CBC_decrypt_buffer(output, cipher, 64, key, iv);
if(0 == memcmp((char*) output, (char*) input, 64))
{
printf("SUCCESS!\n");
}
else
{
int i;
printf("FAILURE!\nInput and output are different:\n");
for (i = 0; i < sizeof input; ++i)
{
printf("%02x - %02x\n", input[i], output[i]);
}
}
}
This is a continuation of my previous question: Intermittent decryption failures in EVP_DecryptFinal_ex when using AES-128/CBC.
I am trying to encrypt and decrypt using the C OpenSSL EVP library. After I received an answer to my question above, I updated my code accordingly:
This variable:
int len = outlen1 + outlen2;
Stores the number of bytes encrypted in the encrypt function. I then pass that variable to the decrypt function (the passing is not shown in the code below) which then uses what is supposedly the actual number of bytes.
However on some input strings, I get segmentation faults at the EVP_DecryptFinal_ex() function.
Something is obviously wrong with the number of bytes encrypted/decrypted or padding. I just don't know what that is.
char* encrypt(char *key, char *s) {
unsigned char iv[16] = {[0 ... 15 ] = 0};
unsigned char outbuf[1024] = {[0 ... 1023] = 0};
int outlen1, outlen2;
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv);
if (EVP_EncryptUpdate(&ctx, outbuf, &outlen1, s, strlen(s)) == 1) {
if (EVP_EncryptFinal_ex(&ctx, outbuf + outlen1, &outlen2) == 1) {
EVP_CIPHER_CTX_cleanup(&ctx);
len = outlen1 + outlen2;
return strdup(outbuf);
}
}
EVP_CIPHER_CTX_cleanup(&ctx);
return NULL;
}
char* decrypt(char *key, char *s, int len) {
unsigned char iv[16] = {[0 ... 15 ] = 0};
unsigned char outbuf[1024] = {[0 ... 1023] = 0};
int outlen1, outlen2;
printf("len: %d\n", len);
printf("strlen(s): %d\n", strlen(s));
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv);
if (EVP_DecryptUpdate(&ctx, outbuf, &outlen1, s, len) == 1) {
printf("After update\n");
if (EVP_DecryptFinal_ex(&ctx, outbuf + outlen1, &outlen2) == 1) {
printf("After final\n");
EVP_CIPHER_CTX_cleanup(&ctx);
return strdup(outbuf);
}
}
EVP_CIPHER_CTX_cleanup(&ctx);
return NULL;
}
NOTE:
I was able to fix the problems I previously had where decrypt final would fail to decrypt certain strings. Those strings can be decrypted fine now. However, some other strings are facing the same problem but this time I am getting seg faults.
You cannot use string functions on binary data. This is especially the case if that binary data is indistinguishable from random. Random binary data may contain null characters anywhere, or not at all. strdup uses strcpy internally, which relies on the null character to be present.
I am using the following code to encrypt and decrypt binary data with C in windows using openssl. As you can see, in both functions, I know the size of the plain text. Is there any way I can decrypt messages without knowing the size of the plain text?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/des.h>
char * Encrypt(char *Key, char *Msg, int size)
{
static char* Res;
int n = 0;
DES_cblock Key2;
DES_key_schedule schedule;
Res = (char *)malloc(size);
/* Prepare the key for use with DES_cfb64_encrypt */
memcpy(Key2, Key, 8);
DES_set_odd_parity(&Key2);
DES_set_key_checked(&Key2, &schedule);
/* Encryption occurs here */
DES_cfb64_encrypt((unsigned char *)Msg, (unsigned char *)Res,size, &schedule, &Key2, &n, DES_ENCRYPT);
return (Res);
}
char * Decrypt(char *Key, char *Msg, int size)
{
static char* Res;
int n = 0;
DES_cblock Key2;
DES_key_schedule schedule;
Res = (char *)malloc(size);
/* Prepare the key for use with DES_cfb64_encrypt */
memcpy(Key2, Key, 8);
DES_set_odd_parity(&Key2);
DES_set_key_checked(&Key2, &schedule);
/* Decryption occurs here */
DES_cfb64_encrypt((unsigned char *)Msg, (unsigned char *)Res,size, &schedule, &Key2, &n, DES_DECRYPT);
return (Res);
}
int _tmain(int argc, _TCHAR* argv[])
{
char key[] = "password";
char clear[] = "This is a secret message";
char *decrypted;
char *encrypted;
encrypted = (char *)malloc(sizeof(clear));
decrypted = (char *)malloc(sizeof(clear));
printf("Clear text\t : %s : sizeof: %i\n", clear, strlen (clear));
memcpy(encrypted, Encrypt(key, clear, sizeof(clear)), sizeof(clear));
printf("Encrypted text\t : %s sizeof: %i\n", encrypted, strlen(encrypted));
memcpy(decrypted, Decrypt(key, encrypted, sizeof(clear)), sizeof(clear));
printf("Decrypted text\t : %s sizeof: %i\n", decrypted, strlen(decrypted));
return 0;
}
With just cipher feedback? Sure thing, as long as you know where the block boundaries are you are golden (i.e. you need to know where you are in the ciphertext).
Following the OpenSSL docs, I /think/ that what I'm doing is correct.. but apparently it's not. Compiling the file (with gcc -g -Wall -Wextra -lssl sign.c) yields no errors or warnings. EVP_VerifyFinal() always returns 0 (Meaning the check failed). What is causing that?
static const EVP_MD * type;
unsigned char * sha(char * input)
{
EVP_MD_CTX c;
unsigned char *md;
unsigned int md_len;
md = malloc(EVP_MAX_MD_SIZE);
EVP_MD_CTX_init(&c);
EVP_DigestInit_ex(&c, type, NULL);
EVP_DigestUpdate(&c, input, strlen(input));
EVP_DigestFinal_ex(&c, md, &md_len);
EVP_MD_CTX_cleanup(&c);
return md;
}
unsigned char * sign(EVP_PKEY * key, unsigned char * data)
{
EVP_MD_CTX c;
unsigned char *sig;
unsigned int len;
EVP_MD_CTX_init(&c);
sig = malloc(EVP_PKEY_size(key));
EVP_SignInit(&c, type);
EVP_SignUpdate(&c, data, strlen((char *)data));
EVP_SignFinal(&c, sig, &len, key);
EVP_MD_CTX_cleanup(&c);
return sig;
}
int verify(EVP_PKEY * key, unsigned char * data, unsigned char * original)
{
EVP_MD_CTX c;
int ret;
EVP_MD_CTX_init(&c);
EVP_VerifyInit(&c, type);
EVP_VerifyUpdate(&c, data, (unsigned int)sizeof(data));
ret = EVP_VerifyFinal(&c, original, (unsigned int)strlen((char *)original), key);
return ret;
}
int main(void)
{
EVP_PKEY *sk, *pk;
FILE *sfd, *pfd;
unsigned char *hash, *sig;
unsigned int i;
sfd = fopen("secret.pem", "r");
pfd = fopen("public.pem", "r");
sk = PEM_read_PrivateKey(sfd, NULL, NULL, NULL);
pk = PEM_read_PUBKEY(pfd, NULL, NULL, NULL);
fclose(sfd);
fclose(pfd);
OpenSSL_add_all_digests();
type = EVP_get_digestbyname("SHA1");
hash = sha("moo");
for(i = 0; i < sizeof(hash); i++)
printf("%02x", hash[i]);
printf("\n");
sig = sign(sk, hash);
switch( verify(pk, sig, hash) )
{
case 0:
printf("Check failed.\n");
break;
case 1:
printf("Check succeeded!\n");
break;
default:
printf("Oh look, an error: %d", ERR_get_error());
break;
}
return 0;
}
You are not passing the correct size:
EVP_VerifyUpdate(&c, data, (unsigned int)sizeof(data));
Since data is defined as unsigned char *, sizeof(data) is probably 4 or 8 (number of bytes required to hold a pointer).
Try passing the actual number of bytes that you've allocated, i.e. EVP_PKEY_size(key). You will have to pass that to your verify() function.
It's possible that something else is also wrong, but this one caught my eye.
I know this is an old question, but one bug could confuse users.
In the verify function original and data should be swapped, original past to EVP_VerifyUpdate and data to EVP_VerifyFinal. String length should not be used as a byte array can contain 0x00 as a valid value which will be recognized as "\0".