Encrypt using OpenSSL API in C [duplicate] - c

This question already has answers here:
Simple AES encryption decryption with openssl library in C
(4 answers)
Closed 7 years ago.
Its not duplicate since I was not asking how to encrypt, but I was asking whats wrong in my encryption. Dont like this Question you are free to delete it. I dont care.
I am trying to encrypt one simple hello text file.
Here is my code to encrypt the data.
int encrypt(EVP_CIPHER_CTX *ctx, FILE *ifp,FILE *ofp)
{
int bytes_read, bytes_written, enc_bytes,tlen;
unsigned char indata[AES_BLOCK_SIZE];
unsigned char encdata[AES_BLOCK_SIZE];
unsigned char outdata[AES_BLOCK_SIZE];
while (1) {
bytes_read = fread(indata, 1, AES_BLOCK_SIZE, ifp);
if (EVP_EncryptUpdate (ctx, encdata, &enc_bytes, indata, bytes_read) != 1)
{
printf ("error in encrypt update\n");
return -1;
}
printf ("INPUT\n");
print_memory(indata, bytes_read);
if (EVP_EncryptFinal (ctx, encdata + enc_bytes, &tlen) != 1)
{
printf ("error in encrypt final\n");
return -1;
}
printf ("OUTPUT\n");
print_memory(encdata,enc_bytes+tlen);
bytes_written = fwrite(encdata, 1,enc_bytes + tlen, ofp);
if (bytes_read < AES_BLOCK_SIZE)
break;
}
Here is key and ivec, I have used for initialization
unsigned char ckey[] = {0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF};
unsigned char ivec[] = {0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF};
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init (&ctx);
EVP_EncryptInit (&ctx, EVP_bf_cbc (), ckey, ivec);
Here is the output encrypted data in hex 24 47 50 58 93 0B 04 9C D5 54 65 93 D1 6B AD 5A
but when i try to decode the data using openSSL cmd
I get following error
anshul:~/> openssl aes-128-cbc -d -in otext -K 000102030405060708090A0B0C0D0E0F -iv 000102030405060708090A0B0C0D0E0F -nosalt
bad decrypt
3075450556:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:529:
This is the same error I get if I use wrong ivec or key.
So I do have wild guess that there is something different in c program key or ivec and openssl cmd key or ivek

I am trying to encrypt one simple hello text file...
I took code from http://openssl.org/docs/crypto/EVP_EncryptInit.html#EXAMPLES...
Here's the example from the OpenSSL wiki on EVP Authenticated Encryption and Decryption. It uses GCM mode because you often want/need confidentiality and authenticity assurances, and not just confidentiality.
OpenSSL routines work on byte strings in memory. So you will have to read the file and present a byte string to the OpenSSL functions.
int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *aad,
int aad_len, unsigned char *key, unsigned char *iv,
unsigned char *ciphertext, unsigned char *tag)
{
EVP_CIPHER_CTX *ctx;
int len, 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_gcm(), NULL, NULL, NULL))
handleErrors();
/* Set IV length if default 12 bytes (96 bits) is not appropriate */
if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL))
handleErrors();
/* Initialise key and IV */
if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors();
/* Provide any AAD data. This can be called zero or more times as
* required
*/
if(1 != EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_len))
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. Normally ciphertext bytes may be written at
* this stage, but this does not occur in GCM mode
*/
if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors();
ciphertext_len += len;
/* Get the tag */
if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag))
handleErrors();
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
return ciphertext_len;
}
And the decryption routine:
int decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *aad,
int aad_len, unsigned char *tag, unsigned char *key, unsigned char *iv,
unsigned char *plaintext)
{
EVP_CIPHER_CTX *ctx;
int len, plaintext_len, ret;
/* Create and initialise the context */
if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
/* Initialise the decryption operation. */
if(!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
handleErrors();
/* Set IV length. Not necessary if this is 12 bytes (96 bits) */
if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL))
handleErrors();
/* Initialise key and IV */
if(!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors();
/* Provide any AAD data. This can be called zero or more times as
* required
*/
if(!EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len))
handleErrors();
/* Provide the message to be decrypted, and obtain the plaintext output.
* EVP_DecryptUpdate can be called multiple times if necessary
*/
if(!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
handleErrors();
plaintext_len = len;
/* Set expected tag value. Works in OpenSSL 1.0.1d and later */
if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag))
handleErrors();
/* Finalise the decryption. A positive return value indicates success,
* anything else is a failure - the plaintext is not trustworthy.
*/
ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
if(ret > 0)
{
/* Success */
plaintext_len += len;
return plaintext_len;
}
else
{
/* Verify failed */
return -1;
}
}
anshul:~/> openssl aes-128-cbc -d -in ...
For GCM mode, this won't work. GCM has not been cut-in for the OpenSSL encrypt and decrypt subcommands. See AES-GCM failing from Command Line Interface on the OpenSSL mailing list.
And in case you are wondering, that's not a valid reason to use a different mode, like CBC or OFB. Use GCM mode.

Related

C, OpenSSL and AES 256 CTR, then mkfs

I am encrypting XFS filesystem using OpenSSL 1.0.2 (cannot update) and AES-256 in ctr mode (using sector number as a IV). I am encrypting only blocks of 512B at one time.
At first I started with EVP_aes_256_ecb() ECB mode for testing and en/decrypt is working fine.
With same code I am also going for CTR (EVP_aes_256_ctr()):
encrypt(...) {
EVP_CIPHER_CTX *ctx;
int len;
int ciphertext_len;
if (!(ctx = EVP_CIPHER_CTX_new()))
handleErrors();
if (EVP_EncryptInit_ex(ctx, evp_cipher, NULL, key, iv) != 1)
handleErrors();
if (EVP_CIPHER_CTX_set_padding(ctx, 0) != 1)
handleErrors();
if (EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len) != 1)
handleErrors();
ciphertext_len = len;
if (EVP_EncryptFinal_ex(ctx, ciphertext + len, &len) != 1)
handleErrors();
ciphertext_len += len;
if (tag && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag) != 1)
handleErrors();
EVP_CIPHER_CTX_free(ctx);
return ciphertext_len;
}
int decrypt(...) {
EVP_CIPHER_CTX *ctx;
int len;
int plaintext_len;
if (!(ctx = EVP_CIPHER_CTX_new()))
handleErrors();
if (EVP_DecryptInit_ex(ctx, evp_cipher, NULL, key, iv) != 1)
handleErrors();
if (EVP_CIPHER_CTX_set_padding(ctx, 0) != 1)
handleErrors();
if (EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len) != 1)
handleErrors();
plaintext_len = len;
if (tag && !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag))
handleErrors();
if (EVP_DecryptFinal_ex(ctx, plaintext + len, &len) != 1) {
if (tag) {
printf("Tag verify failed.\n");
return 0;
}
handleErrors();
}
plaintext_len += len;
EVP_CIPHER_CTX_free(ctx);
return plaintext_len;
}
Only in this case after mkfs.xfs I am getting:
specified blocksize 4096 is less than device physical sector size 4194304
switching to logical sector size 512
meta-data=/dev/sdb isize=512 agcount=4, agsize=2097152 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=0, sparse=0
data = bsize=4096 blocks=8388608, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=1
log =internal log bsize=4096 blocks=4096, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
bad magic number
bad magic number
Metadata corruption detected at xfs_sb block 0x0/0x200
libxfs_writebufr: write verifer failed on xfs_sb bno 0x0/0x200
releasing dirty buffer (bulk) to free list!
This isn't very nice. Is there any problem with my approach?
Although I haven't found a reason, I inspired my code by this: https://raw.githubusercontent.com/saju/misc/master/misc/openssl_aes.c and it is working now. Code in this link seems to be compatible with OpenSSL 1.0.2.

How to use bcrypt in OpenSSL?

I want to use bcrypt encryption for storing passwords and I know OpenSSL implements Blowfish Cipher (which I'm assuming is the same thing).
I made some adaptations from the code shown in this page https://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption
and came up with this:
int OpenSSLEncrypt(
unsigned char* plaintext,
int plaintext_len,
unsigned char* key,
unsigned char* iv,
unsigned char* ciphertext)
{
EVP_CIPHER_CTX *ctx;
int len;
int ciphertext_len;
if (!(ctx = EVP_CIPHER_CTX_new())) OpenSSLHandleErrors();
if (1 != EVP_EncryptInit_ex(ctx, EVP_bf_cbc(), 0, key, 0))
OpenSSLHandleErrors();
if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
OpenSSLHandleErrors();
ciphertext_len = len;
if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
OpenSSLHandleErrors();
ciphertext_len += len;
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
return ciphertext_len;
}
int OpenSSLDecrypt(
unsigned char* ciphertext,
int ciphertext_len,
unsigned char* key,
unsigned char* iv,
unsigned char* plaintext)
{
EVP_CIPHER_CTX *ctx;
int len;
int plaintext_len;
if (!(ctx = EVP_CIPHER_CTX_new())) OpenSSLHandleErrors();
if (1 != EVP_DecryptInit_ex(ctx, EVP_bf_cbc(), NULL, key, 0))
OpenSSLHandleErrors();
if (1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
OpenSSLHandleErrors();
plaintext_len = len;
if (1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len))
OpenSSLHandleErrors();
plaintext_len += len;
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
return plaintext_len;
}
But the length of the cipher that I get from OpenSSLEncrypt(...) depends on the length of the plaintext input parameter, which is not what I was expecting. I was expecting the output to be 64 bytes long no matter the length of the password.
Also, I don't know if EVP_EncryptInit_ex needs an iv (initialization vector) or not for EVP_bf_cbc, and I found no documentation that could help me with this.
As it was pointed out in the comments, I was wrong in assuming Blowfish and BCrypt are the same thing, just because I read somewhere B stands for Blowfish.
I ended up following the suggestion from Cinder Biscuits of using the OpenBSD implementation of bcrypt, avaiable at
https://github.com/libressl-portable/openbsd/blob/master/src/lib/libc/crypt/bcrypt.c

Calculating maximum length of AES encrypted message

I'm using this function to encrypt data using openssl AES 256 CBC:
int encryptAES(unsigned char *plaintext, int plaintext_len, unsigned char *key,
unsigned char *iv, unsigned char *ciphertext)
{
EVP_CIPHER_CTX *ctx;
int len;
int ciphertext_len;
/* Create and initialise the context */
if(!(ctx = EVP_CIPHER_CTX_new())) return handleErrors();
/* Initialise the encryption operation. IMPORTANT - ensure you use a key
* and IV size appropriate for your cipher
* In this example we are using 256 bit AES (i.e. a 256 bit key). The
* IV size for *most* modes is the same as the block size. For AES this
* is 128 bits */
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
return 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))
return 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)) return handleErrors();
ciphertext_len += len;
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
return ciphertext_len;
}
I want to provide to this function a fixed sized buffer ciphertext, How can I calculate the maximum possible length of the encrypted message (ciphertext)
Thanks.
Assuming PKCS#7 padding, which is the default for OpenSSL ECB and CBC mode, the encrypted length will be:
plaintext_len + block_size - (plaintext_len % block_size)
where
block_size = 16
for AES. The end result is always a multiple of block_size.

Segmentation fault in EVP_CIPHER_CTX_new() when using OpenSSL in C

I am a total beginner with the OpenSSL Library in C but was working on a code to encrypt using the libraries while taking a pass phrase as input and generating the salt,IV and key from the pass phrase. This is what I have tried till now:
int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *ciphertext)
{
char *passphrase;
printf("\nEnter a Pass Phrase:");
scanf("%s",passphrase);
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
OPENSSL_config(NULL);
EVP_CIPHER_CTX *ctx;
const EVP_CIPHER *cipher;
const EVP_MD *dgst = NULL;
unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
const char *salt;
int len;
int ciphertext_len;
/* Create and initialise the context */
if(!(ctx = EVP_CIPHER_CTX_new())) //This line causes the error
handleErrors();
cipher = EVP_get_cipherbyname("aes-256-cbc");
if(!cipher) { fprintf(stderr, "no such cipher\n"); return -1; }
dgst=EVP_get_digestbyname("md5");
if(!dgst) { fprintf(stderr, "no such digest\n"); return -1; }
if(!EVP_BytesToKey(cipher, dgst, salt, (unsigned char *) passphrase, strlen(passphrase), 1, key, iv))
{
fprintf(stderr, "EVP_BytesToKey failed\n");
return -1;
}
/* Initialise the encryption operation. IMPORTANT - ensure you use a key
* and IV size appropriate for your cipher
* In this example we are using 256 bit AES (i.e. a 256 bit key). The
* IV size for *most* modes is the same as the block size. For AES this
* is 128 bits */
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
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);
EVP_cleanup();
ERR_free_strings();
return ciphertext_len;
}
I tried this out but kept getting a segmentation fault. I tried to debug and found out that the EVP_CIPHER_CTX_new() was the one cussing it. I am at my wits end right now trying to debug it and could really appreciate some help.
Thanks in advance.
This is incorrect:
char *passphrase;
printf("\nEnter a Pass Phrase:");
scanf("%s",passphrase);
char *pasphrase is just a pointer point to unknown location.
Change this to:
char passphrase[2048];
printf("\nEnter a Pass Phrase:");
scanf("%s", passphrase);

EVP AES Encryption on PSP

I am trying to make a MMORPG for PSP and I will be encrypting al data sent over the network in some form. I have chosen AES for this.
I have this code:
int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, unsigned char *iv, unsigned char *ciphertext){
int len;
int ciphertext_len;
/* Create and initialise the context */
EVP_CIPHER_CTX_init(&ctx);
appendLog("CTX Init", LOG_CRYPTO);
/* Initialise the encryption operation. IMPORTANT - ensure you use a key
* and IV size appropriate for your cipher
* In this example we are using 256 bit AES (i.e. a 256 bit key). The
* IV size for *most* modes is the same as the block size. For AES this
* is 128 bits */
if(1 != EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, key, iv))
printLastError("2");
appendLog("Encrypt started", LOG_CRYPTO);
/* 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))
printLastError("3");
ciphertext_len = len;
appendLog("Mid encrypt", LOG_CRYPTO);
/* Finalise the encryption. Further ciphertext bytes may be written at
* this stage.
*/
if(1 != EVP_EncryptFinal_ex(&ctx, ciphertext + len, &len)) printLastError("4");
ciphertext_len += len;
appendLog("Encrypt final", LOG_CRYPTO);
/* Clean up */
EVP_CIPHER_CTX_cleanup(&ctx);
appendLog("CTX Cleanup", LOG_CRYPTO);
return ciphertext_len;
}
It freezes my PSP after writing "Mid encrypt" to the logs. I was wondering if there is anything noticeably wrong with this code. I am using openSSL v0.9.7j for PSP.
The original AES encrypt code:
int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, unsigned char *iv, unsigned char *ciphertext){
EVP_CIPHER_CTX *ctx;
int len;
int ciphertext_len;
/* Create and initialise the context */
if(!(ctx = EVP_CIPHER_CTX_new())) exit(0);
/* Initialise the encryption operation. IMPORTANT - ensure you use a key
* and IV size appropriate for your cipher
* In this example we are using 256 bit AES (i.e. a 256 bit key). The
* IV size for *most* modes is the same as the block size. For AES this
* is 128 bits */
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
exit(0);
/* 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))
exit(0);
ciphertext_len = len;
/* Finalise the encryption. Further ciphertext bytes may be written at
* this stage.
*/
if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) exit(0);
ciphertext_len += len;
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
return ciphertext_len;
}
The PSPSDK openSSL does not have functions EVP_CIPHER_CTX_new() or EVP_CIPHER_CTX_free() and my EVP_CIPHER_CTX is declared globally and not in the function anymore.
My function call:
char *newS;
char AESKey[32];
char IV[16];
sprintf(AESKey, "12345678901234567890123456789012");
sprintf(IV, "1234567890123456");
encrypted_length = encrypt("HelloFromPSP", strlen("HelloFromPSP"), AESKey, IV, newS);
Can anyone help me figure out why the EVP_EncryptFinal_ex is frezing?
EDIT: Somehow managed to fix by going back to my old code(which was also freezing, odd)
char encrypted[4098]; //Could be smaller but is this size because it holds RSA data at some points in the code
char AESKey[32]; //Recieved from server, no sprintf filling this
char IV[16]; //Recieved from server, no sprintf filling this
encrypted_length = encrypt("HelloFromPSP", strlen("HelloFromPSP"), AESKey, IV, encrypted);

Resources