|
@@ -321,5 +321,84 @@ int generate_sha256_hash(const unsigned char *message, size_t message_len, unsig
|
|
|
EVP_MD_CTX_destroy(mdctx);
|
|
|
return 0;
|
|
|
}
|
|
|
+EVP_CIPHER_CTX* ctx;
|
|
|
|
|
|
+// Code adapted from here: https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption
|
|
|
+int aes_gcm(int enc, unsigned char *key, unsigned char *iv, unsigned char* plaintext, int plaintext_len, unsigned char *ciphertext, int* op_ciphertext_len, unsigned char* tag)
|
|
|
+{
|
|
|
+ int len;
|
|
|
+ int ciphertext_len;
|
|
|
+ int reset_return;
|
|
|
+ if(ctx == NULL)
|
|
|
+ {
|
|
|
+ // Create and initialise the context //
|
|
|
+ if(!(ctx = EVP_CIPHER_CTX_new())) { return 0x1; }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // Initialise the encryption operation. //
|
|
|
+ if(1 != EVP_CipherInit_ex(ctx, EVP_aes_256_gcm(), NULL, key, iv, enc))
|
|
|
+ {
|
|
|
+ reset_return = EVP_CIPHER_CTX_reset(ctx);
|
|
|
+ if(reset_return != 1)
|
|
|
+ return 0xf2;
|
|
|
+ return 0x2;
|
|
|
+ }
|
|
|
+ // Provide the message to be encrypted, and obtain the encrypted output. * EVP_EncryptUpdate can be called multiple times if necessary
|
|
|
+ //
|
|
|
+ if(1 != EVP_CipherUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
|
|
|
+ {
|
|
|
+ reset_return = EVP_CIPHER_CTX_reset(ctx);
|
|
|
+ if(1 != reset_return)
|
|
|
+ return 0xF3;
|
|
|
+ return 0x3;
|
|
|
+ }
|
|
|
+ ciphertext_len = len;
|
|
|
+
|
|
|
+ if(enc == 0)
|
|
|
+ {
|
|
|
+ if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag))
|
|
|
+ {
|
|
|
+ reset_return = EVP_CIPHER_CTX_reset(ctx);
|
|
|
+ if(1 != reset_return)
|
|
|
+ return 0xF5;
|
|
|
+ return 0x5;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // Finalise the encryption. Normally ciphertext bytes may be written at this stage, but this does not occur in GCM mode
|
|
|
+ //
|
|
|
+ // TODO: ^^^ Why the heck does it not occur in GCM mode ?
|
|
|
+ if(1 != EVP_CipherFinal_ex(ctx, ciphertext + len, &len))
|
|
|
+ {
|
|
|
+ reset_return = EVP_CIPHER_CTX_reset(ctx);
|
|
|
+ if(1 != reset_return)
|
|
|
+ return 0xF4;
|
|
|
+ return 0x4;
|
|
|
+ }
|
|
|
+ ciphertext_len += len;
|
|
|
+
|
|
|
+ // Get the tag
|
|
|
+ if(enc == 1)
|
|
|
+ {
|
|
|
+ if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag))
|
|
|
+ {
|
|
|
+ reset_return = EVP_CIPHER_CTX_reset(ctx);
|
|
|
+ if(1 != reset_return)
|
|
|
+ return 0xF5;
|
|
|
+ return 0x5;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Clean up //
|
|
|
+ if(1 != EVP_CIPHER_CTX_reset(ctx))
|
|
|
+ {
|
|
|
+ return 0xF0;
|
|
|
+ }
|
|
|
+
|
|
|
+ *op_ciphertext_len=ciphertext_len;
|
|
|
+ //EVP_CIPHER_CTX_free(ctx); // TODO: memory leaks here - need to free this for erroneous cases too.
|
|
|
+ return 0;
|
|
|
+}
|
|
|
|