[cse] Update the encrypt and decrypt algorithm to GCM

This commit is contained in:
Tomaz Canabrava 2017-09-15 16:17:37 +02:00 committed by Roeland Jago Douma
parent 4f7265c04f
commit e0d368cbb3
No known key found for this signature in database
GPG key ID: F941078878347C0C

View file

@ -38,40 +38,65 @@ namespace {
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 *ciphertext,
unsigned char *tag)
{
EVP_CIPHER_CTX *ctx = nullptr;
int len = 0;
int ciphertext_len = 0;
EVP_CIPHER_CTX *ctx;
int len;
int ciphertext_len;
/* Create and initialise the context */
if(!(ctx = EVP_CIPHER_CTX_new())) {
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_gcm(), NULL, key, iv)) {
/* Initialise the encryption operation. */
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)) {
handleErrors();
}
// Figure out if I need to call this multiple times.
/* 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;
// Finalize Encryption
/* 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);
@ -80,46 +105,77 @@ namespace {
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 = nullptr;
int len = 0;
int plaintext_len = 0;
EVP_CIPHER_CTX *ctx;
int len;
int plaintext_len;
int ret;
/* 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
* 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_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, key, iv)) {
/* Initialise the decryption operation. */
if(!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)) {
handleErrors();
}
// Verify if we need to call this more than one time
if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) {
/* 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;
// Finalize Decrypt
if(1 != EVP_DecryptFinal_ex(ctx, 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();
}
plaintext_len += len;
/* 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);
return plaintext_len;
if(ret > 0)
{
/* Success */
plaintext_len += len;
return plaintext_len;
}
else
{
/* Verify failed */
return -1;
}
}
}