Last active
May 24, 2024 20:58
-
-
Save dvtalk/edca1d9753503cd03f04b495b040f0e3 to your computer and use it in GitHub Desktop.
AES encryption/decryption using OpenSSL Library
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://dvtalk.me/2021/08/29/systemverilog-dpi-example-with-aes-openssl-cmodel/ | |
#ifndef __AES_C__ | |
#define __AES_C__ | |
#include "aes.h" | |
#include <openssl/conf.h> | |
#include <openssl/evp.h> | |
#include <openssl/err.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
void handleErrors(void) { | |
ERR_print_errors_fp(stderr); | |
abort(); | |
} | |
int aes_encrypt(enum AES_OP_MODE aes_mode, | |
unsigned char *plaintext, | |
int plaintext_len, | |
unsigned char *key, | |
int key_len, | |
unsigned char *ivec, | |
unsigned char *ciphertext) { | |
/* Initialise the library */ | |
ERR_load_crypto_strings(); | |
OpenSSL_add_all_algorithms(); | |
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. */ | |
switch (aes_mode) { | |
case AES_OP_MODE_ECB: | |
if (key_len == 128){ if( 1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, NULL)) handleErrors();}; | |
if (key_len == 192){ if( 1 != EVP_EncryptInit_ex(ctx, EVP_aes_192_ecb(), NULL, key, NULL)) handleErrors();}; | |
if (key_len == 256){ if( 1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_ecb(), NULL, key, NULL)) handleErrors();}; | |
break; | |
case AES_OP_MODE_CBC: | |
if (key_len == 128){ if( 1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, ivec)) handleErrors();}; | |
if (key_len == 192){ if( 1 != EVP_EncryptInit_ex(ctx, EVP_aes_192_cbc(), NULL, key, ivec)) handleErrors();}; | |
if (key_len == 256){ if( 1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, ivec)) handleErrors();} | |
break; | |
case AES_OP_MODE_CFB: | |
if (key_len == 128){ if( 1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_cfb(), NULL, key, ivec)) handleErrors();}; | |
if (key_len == 192){ if( 1 != EVP_EncryptInit_ex(ctx, EVP_aes_192_cfb(), NULL, key, ivec)) handleErrors();}; | |
if (key_len == 256){ if( 1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cfb(), NULL, key, ivec)) handleErrors();} | |
break; | |
case AES_OP_MODE_XTS: | |
if (key_len == 128){ if( 1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_xts(), NULL, key, ivec)) handleErrors();}; | |
//if (key_len == 192){ if( 1 != EVP_EncryptInit_ex(ctx, EVP_aes_192_xts(), NULL, key, ivec)) handleErrors();}; | |
if (key_len == 256){ if( 1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_xts(), NULL, key, ivec)) handleErrors();}; | |
break; | |
case AES_OP_MODE_OFB: | |
if (key_len == 128){ if( 1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_ofb(), NULL, key, ivec)) handleErrors();}; | |
if (key_len == 192){ if( 1 != EVP_EncryptInit_ex(ctx, EVP_aes_192_ofb(), NULL, key, ivec)) handleErrors();}; | |
if (key_len == 256){ if( 1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_ofb(), NULL, key, ivec)) handleErrors();} | |
break; | |
case AES_OP_MODE_CTR: | |
if (key_len == 128){ if( 1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_ctr(), NULL, key, ivec)) handleErrors();}; | |
if (key_len == 192){ if( 1 != EVP_EncryptInit_ex(ctx, EVP_aes_192_ctr(), NULL, key, ivec)) handleErrors();}; | |
if (key_len == 256){ if( 1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_ctr(), NULL, key, ivec)) handleErrors();} | |
break; | |
} | |
/* Disable padding */ | |
EVP_CIPHER_CTX_set_padding(ctx, 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)) 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); | |
/* Some printing */ | |
printf("\nEncypt key is : \n"); | |
BIO_dump_fp (stdout, (const char *)key, key_len/8); | |
printf("\nEncypt ivec is:\n"); | |
BIO_dump_fp (stdout, (const char *)ivec, 16 ); //16 bytes | |
printf("\nPlain text is:\n"); | |
BIO_dump_fp (stdout, (const char *)plaintext, plaintext_len); | |
printf("\nCiphertext is:\n"); | |
BIO_dump_fp (stdout, (const char *)ciphertext, ciphertext_len); | |
return ciphertext_len; | |
} | |
/* Turn "aabbcc22" to an array of 0xaa, 0xbb, 0xcc, 0x22*/ | |
unsigned int hexstring2hexarray(const unsigned char *inputstring, unsigned char *outputstring) { | |
int inputstrsize = (int) strlen((char *)inputstring); | |
for(int i =0; i < inputstrsize; i+=2) { | |
unsigned char hexstr[2]; | |
hexstr[0] = inputstring[i]; | |
hexstr[1] = inputstring[i+1]; | |
int num = (int) strtol((char*)hexstr, NULL, 16); | |
outputstring[i/2] = num; | |
} | |
return inputstrsize/2; | |
} | |
/* Implement main() for debugging */ | |
int main (void) { | |
unsigned char plaintext[4096], key[4096], ivec[4096], decryptedtext[4096], ciphertext[4096]; | |
unsigned int plaintext_len, key_len, ivec_len, decryptedtext_len, ciphertext_len; | |
/* Test with NIST KAT CBC GFSbox 192 COUNT=1*/ | |
plaintext_len = hexstring2hexarray((unsigned char *)"00000000000000000000000000000000" , plaintext); | |
key_len = hexstring2hexarray((unsigned char *)"000000000000000000000000000000000000000000000000" , key); | |
ivec_len = hexstring2hexarray((unsigned char *)"9c2d8842e5f48f57648205d39a239af1" , ivec); | |
/* Encrypt the plaintext */ | |
ciphertext_len = aes_encrypt( AES_OP_MODE_CBC, | |
plaintext, | |
plaintext_len, | |
key, | |
key_len*8, | |
ivec, | |
ciphertext); | |
/* Clean up */ | |
EVP_cleanup(); | |
ERR_free_strings(); | |
return 0; | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment