Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update AES implementation to be compatible with API levels >= 12 #432

Merged
merged 2 commits into from
Nov 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 64 additions & 13 deletions src/bolos/cx_aes_sdk2.c
Original file line number Diff line number Diff line change
@@ -1,51 +1,102 @@
#define _SDK_2_0_
#include <openssl/aes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "bolos/cx_utils.h"
#include "bolos/cxlib.h"

//-----------------------------------------------------------------------------
static cx_aes_key_t local_aes_key;
static AES_KEY local_aes_key;
static bool local_aes_ready;
static uint32_t local_aes_mode;
static uint32_t local_aes_op;
static uint32_t local_aes_chain_mode;
bool hdw_cbc = false;
bool set_aes_iv;
static uint8_t aes_current_block[AES_BLOCK_SIZE] = { 0 };

//-----------------------------------------------------------------------------
// AES related functions:
//-----------------------------------------------------------------------------
cx_err_t sys_cx_aes_set_key_hw(const cx_aes_key_t *key, uint32_t mode)
{
memcpy(&local_aes_key, key, sizeof(local_aes_key));
local_aes_mode = mode;
switch (mode & CX_MASK_SIGCRYPT) {
case CX_ENCRYPT:
case CX_SIGN:
case CX_VERIFY:
AES_set_encrypt_key(key->keys, (int)key->size * 8, &local_aes_key);
break;
case CX_DECRYPT:
AES_set_decrypt_key(key->keys, (int)key->size * 8, &local_aes_key);
break;
default:
local_aes_ready = false;
return CX_INVALID_PARAMETER;
}
local_aes_op = mode & CX_MASK_SIGCRYPT;
local_aes_chain_mode = mode & CX_MASK_CHAIN;
set_aes_iv = true;
local_aes_ready = true;

return CX_OK;
}

// This function aims at reproducing a CBC mode performed in hardware
static cx_err_t cx_aes_block_hw_cbc(const unsigned char *inblock,
unsigned char *outblock)
{
if (local_aes_op == CX_DECRYPT) {
AES_decrypt(inblock, outblock, &local_aes_key);
// XOR the decryption result with aes_current_block
cx_memxor(outblock, aes_current_block, AES_BLOCK_SIZE);

// Store the input block for next block decryption
memcpy(aes_current_block, inblock, AES_BLOCK_SIZE);
} else { // CX_SIGN, CX_VERIFY, CX_ENCRYPT:

// Before the encryption, XOR the input block with the
// previous value of aes_current_block which is either
// the IV or the previous ciphertext block
cx_memxor(aes_current_block, inblock, AES_BLOCK_SIZE);

AES_encrypt(aes_current_block, outblock, &local_aes_key);

// Store the ciphertext block for next block encryption
memcpy(aes_current_block, outblock, AES_BLOCK_SIZE);
}

return CX_OK;
}

cx_err_t sys_cx_aes_block_hw(const unsigned char *inblock,
unsigned char *outblock)
{
AES_KEY aes_key;

if (!local_aes_ready) {
return CX_INTERNAL_ERROR;
}
if ((local_aes_mode & CX_MASK_SIGCRYPT) == CX_DECRYPT) {
AES_set_decrypt_key(local_aes_key.keys, (int)local_aes_key.size * 8,
&aes_key);
AES_decrypt(inblock, outblock, &aes_key);
// Stores the IV
if (set_aes_iv && (local_aes_chain_mode == CX_CHAIN_CBC)) {
memcpy(aes_current_block, inblock, AES_BLOCK_SIZE);
set_aes_iv = false;
return CX_OK;
}
if (hdw_cbc && (local_aes_chain_mode == CX_CHAIN_CBC)) {
return cx_aes_block_hw_cbc(inblock, outblock);
}
if (local_aes_op == CX_DECRYPT) {
AES_decrypt(inblock, outblock, &local_aes_key);
} else { // CX_SIGN, CX_VERIFY, CX_ENCRYPT:
AES_set_encrypt_key(local_aes_key.keys, (int)local_aes_key.size * 8,
&aes_key);
AES_encrypt(inblock, outblock, &aes_key);
AES_encrypt(inblock, outblock, &local_aes_key);
}
OPENSSL_cleanse(&aes_key, sizeof(aes_key));

return CX_OK;
}

void sys_cx_aes_reset_hw(void)
{
OPENSSL_cleanse(&local_aes_key, sizeof(local_aes_key));
local_aes_ready = false;
}
13 changes: 12 additions & 1 deletion src/emulate_unified_sdk.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
#define SYSCALL_HANDLED 1
#define SYSCALL_NOT_HANDLED 0

// Indicates whether the XOR in the CBC mode is implemented in the CX lib
// or in the AES low level function
extern bool hdw_cbc;

/* Handle bagl related syscalls which behavior are defined in src/bolos/bagl.c
*/
int emulate_syscall_bagl(unsigned long syscall, unsigned long *parameters,
Expand Down Expand Up @@ -166,9 +170,16 @@ int emulate_syscall_cx(unsigned long syscall, unsigned long *parameters,
unsigned long *ret, bool verbose, sdk_version_t version,
hw_model_t model)
{
(void)version;
(void)model;

// Starting from API level 12, the XOR operation of the CBC mode
// is not in CX LIB anymore
// CBC mode must be implemented
// in the AES low level functions
if (version >= SDK_API_LEVEL_12) {
hdw_cbc = true;
}

switch (syscall) {
/* clang-format off */
SYSCALL0(get_api_level);
Expand Down
Loading