For AES-GCM encryption/decryption, I tried this, but it has a problem.
ctx = EVP_CIPHER_CTX_new();
//Get the cipher.
cipher = EVP_aes_128_gcm ();
#define GCM_IV "000000000000"
#define GCM_ADD "0000"
#define TAG_SIZE 16
#define ENC_SIZE 64
//Encrypt the data first.
//Set the cipher and context only.
retv = EVP_EncryptInit (ctx, cipher, NULL, NULL);
//Set the nonce and tag sizes.
//Set IV length. [Optional for GCM].
retv = EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_IVLEN, strlen((const char *)GCM_IV), NULL);
//Now initialize the context with key and IV.
retv = EVP_EncryptInit (ctx, NULL, (const unsigned char *)keybuf, (const unsigned char *)GCM_IV);
//Add Additional associated data (AAD). [Optional for GCM]
retv = EVP_EncryptUpdate (ctx, NULL, (int *)&enclen, (const unsigned char *)GCM_ADD, strlen(GCM_ADD));
//Now encrypt the data.
retv = EVP_EncryptUpdate (ctx, (unsigned char *)encm, (int *)&enclen, (const unsigned char *)msg, _tcslen (msg) *sizeof(Char));
//Finalize.
retv = EVP_EncryptFinal (ctx, (unsigned char *)encm + enclen, (int *)&enclen2);
enclen += enclen2;
//Append authentication tag at the end.
retv = EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_GET_TAG, TAG_SIZE, (unsigned char *)encm + enclen);
//DECRYPTION PART
//Now Decryption of the data.
//Then decrypt the data.
//Set just cipher.
retv = EVP_DecryptInit(ctx, cipher, NULL, NULL);
//Set Nonce size.
retv = EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_IVLEN, strlen((const char *)GCM_IV), NULL);
//Set Tag from the data.
retv = EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_TAG, TAG_SIZE, (unsigned char *)encm + enclen);
//Set key and IV (nonce).
retv = EVP_DecryptInit (ctx, NULL, (const unsigned char*)keybuf, (const unsigned char *)GCM_IV);
//Add Additional associated data (AAD).
retv = EVP_DecryptUpdate (ctx, NULL, (int *)&declen, (const unsigned char *)GCM_ADD,
strlen((const char *)GCM_ADD));
//Decrypt the data.
retv = EVP_DecryptUpdate (ctx, decm, (int *)&declen, (const unsigned char *)encm, enclen);
//Finalize.
retv = EVP_DecryptFinal (ctx, (unsigned char*)decm + declen, (int *)&declen2);
This code is working fine (with some modifications). It is encrypting and decrypting the message. The problem is that when cipher text is modified before decryption, it still decrypts the text (however, wrong). As per my understanding of authenticated encryption, in such cases, it should not decrypt the modified cipher texts.
Where am I wrong? Can I get any suitable example of AES-GCM using EVP interfaces of OpenSSL?
If you don't mind writing your own software, there are plenty of crypto libraries supporting AES-GCM, such as OpenSSL itself (even if not available from the command line tool).
The EVP functions provide a high level interface to OpenSSL cryptographic functions. They provide the following features: A single consistent interface regardless of the underlying algorithm or mode. Support for an extensive range of algorithms. Encryption/Decryption using both symmetric and asymmetric algorithms.
AES-GCM have two main functions are block cipher encryption and multiplication over the field . The authenticated encryption operation takes Initialization Vector (IV), Additional Authenticated Data (AAD),secret key and plaintext as an input in128-bit and gives a 128-bit ciphertext and authentication tag,T.
Here is an example to encrypt and decrypt 128 bytes every call to update for example:
int howmany, dec_success, len;
const EVP_CIPHER *cipher;
switch(key_len)
{
case 128: cipher = EVP_aes_128_gcm ();break;
case 192: cipher = EVP_aes_192_gcm ();break;
case 256: cipher = EVP_aes_256_gcm ();break;
default:break;
}
// Encrypt
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit (ctx, cipher, KEY, IV);
EVP_EncryptUpdate (ctx, NULL, &howmany, AAD, aad_len);
len = 0;
while(len <= in_len-128)
{
EVP_EncryptUpdate (ctx, CIPHERTEXT+len, &howmany, PLAINTEXT+len, 128);
len+=128;
}
EVP_EncryptUpdate (ctx, CIPHERTEXT+len, &howmany, PLAINTEXT+len, in_len - len);
EVP_EncryptFinal (ctx, TAG, &howmany);
EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_GET_TAG, 16, TAG);
EVP_CIPHER_CTX_free(ctx);
// Decrypt
ctx = EVP_CIPHER_CTX_new();
EVP_DecryptInit (ctx, cipher, KEY, IV);
EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_TAG, 16, ref_TAG);
EVP_DecryptInit (ctx, NULL, KEY, IV);
EVP_DecryptUpdate (ctx, NULL, &howmany, AAD, aad_len);
len = 0;
while(len <= in_len-128)
{
EVP_DecryptUpdate (ctx, decrypted_CT+len, &howmany, CIPHERTEXT+len, 128);
len+=128;
}
EVP_DecryptUpdate (ctx, decrypted_CT+len, &howmany, CIPHERTEXT+len, in_len-len);
dec_success = EVP_DecryptFinal (ctx, dec_TAG, &howmany);
EVP_CIPHER_CTX_free(ctx);
In the end you should check that the value of dec_success is 1. If you modify the CIPHERTEXT, before you decrypt it, you should get value of 0.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With