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?
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.