Skip to content

Commit

Permalink
Add implementation for AES CBC in Sys.Security.Crypto
Browse files Browse the repository at this point in the history
- Add wrapper for mbedTLS API.
- Update assembly declaration.
  • Loading branch information
josesimoes committed Feb 28, 2024
1 parent 23c9532 commit 566c60c
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@ static const CLR_RT_MethodHandler method_lookup[] =
NULL,
NULL,
NULL,
NULL,
NULL,
Library_nf_sys_sec_cryptography_System_Security_Cryptography_Aes::EncryptAesEcb___SZARRAY_U1__SZARRAY_U1,
Library_nf_sys_sec_cryptography_System_Security_Cryptography_Aes::DecryptAesEcb___SZARRAY_U1__SZARRAY_U1,
Library_nf_sys_sec_cryptography_System_Security_Cryptography_Aes::EncryptAesCbc___SZARRAY_U1__SZARRAY_U1,
Library_nf_sys_sec_cryptography_System_Security_Cryptography_Aes::DecryptAesCbc___SZARRAY_U1__SZARRAY_U1,
NULL,
NULL,
NULL,
Expand All @@ -33,9 +37,9 @@ static const CLR_RT_MethodHandler method_lookup[] =
const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_System_Security_Cryptography =
{
"nanoFramework.System.Security.Cryptography",
0xF4AEFE6C,
0x343142CA,
method_lookup,
{ 100, 0, 0, 2 }
{ 100, 0, 0, 3 }
};

// clang-format on
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,20 @@
typedef enum __nfpack CipherMode
{
CipherMode_None = 0,
CipherMode_CBC = 1,
CipherMode_ECB = 2,
} CipherMode;

struct Library_nf_sys_sec_cryptography_System_Security_Cryptography_Aes
{
static const int FIELD___mode = 1;
static const int FIELD___key = 2;
static const int FIELD___iv = 3;

NANOCLR_NATIVE_DECLARE(EncryptAesEcb___SZARRAY_U1__SZARRAY_U1);
NANOCLR_NATIVE_DECLARE(DecryptAesEcb___SZARRAY_U1__SZARRAY_U1);
NANOCLR_NATIVE_DECLARE(EncryptAesCbc___SZARRAY_U1__SZARRAY_U1);
NANOCLR_NATIVE_DECLARE(DecryptAesCbc___SZARRAY_U1__SZARRAY_U1);

//--//
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,149 @@ HRESULT Library_nf_sys_sec_cryptography_System_Security_Cryptography_Aes::Decryp

NANOCLR_CLEANUP_END();
}

HRESULT Library_nf_sys_sec_cryptography_System_Security_Cryptography_Aes::EncryptAesCbc___SZARRAY_U1__SZARRAY_U1(
CLR_RT_StackFrame &stack)
{
NANOCLR_HEADER();

mbedtls_aes_context encodeContext;

CLR_RT_HeapBlock_Array *keyArray;
CLR_RT_HeapBlock_Array *ivArray;
CLR_RT_HeapBlock_Array *plainTextArray;
CLR_RT_HeapBlock_Array *cipherTextArray;
CLR_RT_HeapBlock *pThis;

pThis = (CLR_RT_HeapBlock *)stack.This();
FAULT_ON_NULL(pThis);

// grab key and check for NULL
keyArray = pThis[FIELD___key].DereferenceArray();
if (keyArray == NULL)
{
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_OPERATION);
}

// grab IV
// (expecting this to be filled with the IV from managed code)
ivArray = pThis[FIELD___key].DereferenceArray();

// grab plain text and check for NULL
plainTextArray = stack.Arg1().DereferenceArray();
FAULT_ON_NULL_ARG(plainTextArray);

// data has to be multiple of 16
if (plainTextArray->m_numOfElements % 16 != 0)
{
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
}

// create the return array (same length as the input)
stack.PushValueAndClear();
NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(
stack.TopValue(),
plainTextArray->m_numOfElements,
g_CLR_RT_WellKnownTypes.m_UInt8));
cipherTextArray = stack.TopValue().DereferenceArray();

// init mbedtls context
mbedtls_aes_init(&encodeContext);

if (mbedtls_aes_setkey_enc(&encodeContext, keyArray->GetFirstElement(), keyArray->m_numOfElements * 8) ==
MBEDTLS_ERR_AES_INVALID_KEY_LENGTH)
{
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
}

if (mbedtls_aes_crypt_cbc(
&encodeContext,
MBEDTLS_AES_ENCRYPT,
plainTextArray->m_numOfElements,
ivArray->GetFirstElement(),
plainTextArray->GetFirstElement(),
cipherTextArray->GetFirstElement()) != 0)
{
NANOCLR_SET_AND_LEAVE(CLR_E_FAIL);
}

NANOCLR_CLEANUP();

// make sure nothing is left in memory
mbedtls_aes_free(&encodeContext);

NANOCLR_CLEANUP_END();
}

HRESULT Library_nf_sys_sec_cryptography_System_Security_Cryptography_Aes::DecryptAesCbc___SZARRAY_U1__SZARRAY_U1(
CLR_RT_StackFrame &stack)
{
NANOCLR_HEADER();

mbedtls_aes_context decodeContext;

CLR_RT_HeapBlock_Array *keyArray;
CLR_RT_HeapBlock_Array *ivArray;
CLR_RT_HeapBlock_Array *plainTextArray;
CLR_RT_HeapBlock_Array *cipherTextArray;
CLR_RT_HeapBlock *pThis;

pThis = (CLR_RT_HeapBlock *)stack.This();
FAULT_ON_NULL(pThis);

// grab key and check for NULL
keyArray = pThis[FIELD___key].DereferenceArray();
if (keyArray == NULL)
{
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_OPERATION);
}

// grab cipher text and check for NULL
cipherTextArray = stack.Arg1().DereferenceArray();
FAULT_ON_NULL_ARG(cipherTextArray);

// data has to be multiple of 16
if (cipherTextArray->m_numOfElements % 16 != 0)
{
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
}

// grab IV
// (expecting this to be filled with the IV from managed code)
ivArray = pThis[FIELD___key].DereferenceArray();

// create the return array (same length as the input)
stack.PushValueAndClear();
NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(
stack.TopValue(),
cipherTextArray->m_numOfElements,
g_CLR_RT_WellKnownTypes.m_UInt8));
plainTextArray = stack.TopValue().DereferenceArray();

// init mbedtls context
mbedtls_aes_init(&decodeContext);

if (mbedtls_aes_setkey_dec(&decodeContext, keyArray->GetFirstElement(), keyArray->m_numOfElements * 8) ==
MBEDTLS_ERR_AES_INVALID_KEY_LENGTH)
{
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
}

if (mbedtls_aes_crypt_cbc(
&decodeContext,
MBEDTLS_AES_DECRYPT,
plainTextArray->m_numOfElements,
ivArray->GetFirstElement(),
plainTextArray->GetFirstElement(),
cipherTextArray->GetFirstElement()) != 0)
{
NANOCLR_SET_AND_LEAVE(CLR_E_FAIL);
}

NANOCLR_CLEANUP();

// make sure nothing is left in memory
mbedtls_aes_free(&decodeContext);

NANOCLR_CLEANUP_END();
}

0 comments on commit 566c60c

Please sign in to comment.