Skip to content

Instantly share code, notes, and snippets.

@bigbrett
Created May 22, 2018 23:44
Show Gist options
  • Save bigbrett/1301bbf947c9cb0f7f86dbc1daab9d25 to your computer and use it in GitHub Desktop.
Save bigbrett/1301bbf947c9cb0f7f86dbc1daab9d25 to your computer and use it in GitHub Desktop.
#include <openssl/engine.h>
#include <openssl/ossl_typ.h>
#include <openssl/evp.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "wsaes_api.h"
#define LOAD_ENGINE 1
#define HWSUCCESS 0
#define MAXBYTES 1048576
static const char* engine_id = "wsaesengine";
const char* devstr = "/dev/wsaeschar";
const uint8_t key[AESKEYSIZE] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F };
const uint8_t iv[AESIVSIZE] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
// string to encrypt
const char teststr[] = "The Quick Brown Fox Jumped Over The Lazy Dog!";
static void aesErr(char *msg) {
char *err = malloc(130);
ERR_load_crypto_strings();
ERR_error_string(ERR_get_error(), err);
printf("[ERROR %s] %s\n",msg, err);
free(err);
}
static int32_t wsencrypt(uint8_t *plaintext, uint32_t plaintext_len,
uint8_t *key,uint8_t *iv,
uint8_t *ciphertext,uint32_t *ciphertext_lenp, ENGINE* eng) {
EVP_CIPHER_CTX *ctx;
int len;
uint32_t ciphertext_len;
/* Create and initialise the context */
if(!(ctx = EVP_CIPHER_CTX_new()))
aesErr("wsencrypt new ctx");
/* 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 */
printf("TEST: EVP_EncryptInit_ex()\n");
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), eng, (unsigned char*)key, (unsigned char*)iv))
aesErr("wsencrypt init");
/* Provide the message to be encrypted, and obtain the encrypted output.
* EVP_EncryptUpdate can be called multiple times if necessary
*/
printf("TEST: CALLING EVP_EncryptUpdate...()\n");
if(1 != EVP_EncryptUpdate(ctx, (unsigned char*)ciphertext, &len, (unsigned char*)plaintext, (int)plaintext_len))
aesErr("wsencrypt update");
printf("TEST: EVP_EncryptUpdate() returned \n\tciphertext[%d] = ",len);
for (int i=0; i<len; i++)
printf("0x%02X ",ciphertext[i]);
printf("\n");
ciphertext_len = (uint32_t)len;
printf("TEST: ciphertext_len = len = %d\n",len);
/* Finalise the encryption. Further ciphertext bytes may be written at
* this stage. */
printf("TEST: CALLING EVP_EncryptFinal_ex(ciphertext + %d, ...)\n",len);
unsigned char* testptr = ((unsigned char*)ciphertext) + len;
if(1 != EVP_EncryptFinal_ex(ctx, ((unsigned char*)ciphertext) + len, &len))
aesErr("wsencrypt final");
printf("TEST: EVP_EncryptFinal() returned \n\tciphertext+len[%d] = ",len);
for (int i=0; i<len; i++) {
printf("0x%02X ",*testptr);
testptr++;
}
printf("\n");
ciphertext_len += (uint32_t)len;
printf("TEST: ciphertext_len += len = %d\n",ciphertext_len);
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
*ciphertext_lenp = ciphertext_len;
return HWSUCCESS;
}
static int32_t wsdecrypt(uint8_t *ciphertext,uint32_t ciphertext_len,
uint8_t *key,uint8_t *iv,
uint8_t *plaintext,uint32_t *plaintext_lenp, ENGINE* eng) {
EVP_CIPHER_CTX *ctx;
int len;
uint32_t plaintext_len;
/* Create and initialise the context */
if(!(ctx = EVP_CIPHER_CTX_new()))
aesErr("wsdecrypt new ctx");
/* 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 */
printf("TEST: EVP_DecryptInit_ex()\n");
if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), eng, (unsigned char*)key, (unsigned char*)iv))
aesErr("wsdecrypt init");
/* Provide the message to be decrypted, and obtain the plaintext output.
* EVP_DecryptUpdate can be called multiple times if necessary
*/
printf("TEST: CALLING EVP_DecryptUpdate...()\n");
if(1 != EVP_DecryptUpdate(ctx, (unsigned char*)plaintext, &len, (unsigned char*)ciphertext, (int)ciphertext_len))
aesErr("wsdecrypt update");
printf("TEST: EVP_DecryptUpdate() returned \n\tplaintext[%d] = ",len);
for (int i=0; i<len; i++)
printf("0x%02X ",plaintext[i]);
printf("\n");
plaintext_len = (uint32_t)len;
printf("TEST: plaintext_len = len = %d\n",len);
/* Finalise the decryption. Further plaintext bytes may be written at
* this stage.
*/
printf("TEST: CALLING EVP_DecryptFinal_ex(plaintext + %d,...)\n",len);
unsigned char* testptr = ((unsigned char*)plaintext) + len;
if(1 != EVP_DecryptFinal_ex(ctx, ((unsigned char*)plaintext + len), &len))
aesErr("wsdecrypt final");
printf("TEST: EVP_DecryptFinal() returned \n\tplaintext+len[%d] = ",len);
for (int i=0; i<len; i++) {
printf("0x%02X ",*testptr);
testptr++;
}
printf("\n");
plaintext_len += (uint32_t)len;
printf("TEST: plaintext_len += len = %d\n",plaintext_len);
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
*plaintext_lenp = plaintext_len;
return HWSUCCESS;
}
int main(int argc, char* argv[])
{
printf("Entering engine test program...\n");
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
int status = 0;
#ifdef LOAD_ENGINE
// store path to engine shared object
const char* engine_so_path = argv[1];
// load dynamic engine support
ENGINE_load_dynamic();
// (copy of the) instance of a generic "dynamic" engine that will magically morph into an instance of our
// shared library engine once it is loaded by the LOAD command string
ENGINE *eng = ENGINE_by_id("dynamic");
if (eng == NULL)
{
fprintf(stderr,"ERROR: Could not load engine \"dynamic\", ENGINE_by_id(\"dynamic\") == NULL\n");
exit(1);
}
// BRIEF: Specify the path to our shared library engine, set the ID, and load it.
//
// The "SO_PATH" control command should be used to identify the
// shared-library that contains the ENGINE implementation, and "NO_VCHECK"
// might possibly be useful if there is a minor version conflict and you
// (or a vendor helpdesk) is convinced you can safely ignore it.
// "ID" is probably only needed if a shared-library implements
// multiple ENGINEs, but if you know the engine id you expect to be using,
// it doesn't hurt to specify it (and this provides a sanity check if
// nothing else). "LIST_ADD" is only required if you actually wish the
// loaded ENGINE to be discoverable by application code later on using the
// ENGINE's "id". For most applications, this isn't necessary - but some
// application authors may have nifty reasons for using it
// The "LOAD" command is the only one that takes no parameters and is the command
// that uses the settings from any previous commands to actually *load*
// the shared-library ENGINE implementation. If this command succeeds, the
// (copy of the) 'dynamic' ENGINE will magically morph into the ENGINE
// that has been loaded from the shared-library. As such, any control
// commands supported by the loaded ENGINE could then be executed as per
// normal. Eg. if ENGINE "foo" is implemented in the shared-library
// "libfoo.so" and it supports some special control command "CMD_FOO", the
// following code would load and use it (NB: obviously this code has no error checking);
// ENGINE *e = ENGINE_by_id("dynamic");
// ENGINE_ctrl_cmd_string(e, "SO_PATH", "/lib/libfoo.so", 0);
// ENGINE_ctrl_cmd_string(e, "ID", "foo", 0);
// ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0);
// ENGINE_ctrl_cmd_string(e, "CMD_FOO", "some input data", 0);
ENGINE_ctrl_cmd_string(eng, "SO_PATH", engine_so_path, 0);
ENGINE_ctrl_cmd_string(eng, "ID", engine_id, 0);
ENGINE_ctrl_cmd_string(eng, "LOAD", NULL, 0);
if (eng == NULL)
{
fprintf(stderr,"*TEST: ERROR, COULD NOT LOAD ENGINE:\n\tSO_PATH = %s\n\tID = %s\n", engine_so_path, engine_id);
exit(1);
}
printf("wsaes Engine successfully loaded:\n\tSO_PATH = %s\n\tID = %s\n", engine_so_path, engine_id);
// initialize engine
status = ENGINE_init(eng);
if (status < 0)
{
fprintf(stderr,"*TEST: ERROR, COULD NOT INITIALIZE ENGINE\n\tENGINE_init(eng) == %d\n",status);
exit(1);
}
printf("*TEST: Initialized engine [%s]\n\tinit result = %d\n",ENGINE_get_name(eng), status);
#endif
int datalen = strlen(teststr);
uint8_t encrypted[MAXBYTES+1024];
uint8_t decrypted[MAXBYTES+1024];
uint32_t encrypted_length, decrypted_length;
printf("Initial_plaintext = \n");
for (int i=0; i<datalen; i++)
printf("0x%02X ",teststr[i]);
printf("\nplaintext length = %d\n",datalen);
printf("\n################### ENCRYPTING ########################\n");
status = wsencrypt( (uint8_t*)teststr, (uint32_t)datalen, (uint8_t*)key,
(uint8_t*)iv, (uint8_t*)encrypted, &encrypted_length, eng);
if(0 != status || encrypted_length == 0) {
printf("\nEncrypt failed\n");
exit(EXIT_FAILURE);
}
printf("\n################### DONE ENCRYPTING########################\n");
printf("encrypted text = ");
for (int i=0; i<encrypted_length; i++)
printf("0x%02X ",encrypted[i]);
printf("\nencrypted length = %d\n\n",encrypted_length);
printf("\n################### DECRYPTING########################\n");
status = wsdecrypt( (uint8_t*)encrypted, encrypted_length, (uint8_t*)key,
(uint8_t*)iv, (uint8_t*)decrypted, &decrypted_length, eng);
if(0 != status || decrypted_length == 0) {
printf("\nDecrypt failed\n");
exit(EXIT_FAILURE);
}
printf("\n################### DONE DECRYPTING########################\n");
printf("decrypted text = \n");
for (int i=0; i<decrypted_length; i++)
printf("0x%02X ",decrypted[i]);
printf("\ndecrypted length = %d\n\n",decrypted_length);
printf("Or, in plaintext: \n");
for (int i=0; i<decrypted_length; i++)
printf("%c",decrypted[i]);
printf("\n\n");
int errcnt=0;
for (int i=0; i < datalen; i++)
{
if (decrypted[i] != teststr[i])
{
errcnt++;
printf("\t****Error, incorrect digest value at element %i!\n",i);
}
}
printf("decrypted text = ");
for (int i=0; i<datalen; i++)
printf("%c",decrypted[i]);
printf("\n");
// report erroneous values
if (errcnt == 0)
printf("****Test status: SUCCESS\n\n");
else
{
printf("****Test vector status: FAILED\n\n");
return -1;
}
return HWSUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment