Hi,
I am now looking on the app_easy_timer api in SDK5. This is a very great tool - no need to think of messages, just pass a callback that you want to be called when the timer expires (Are there any javascript developers here?).
In our app we are using GAPM_USE_ENC_BLOCK_CMD and GAPM_USER_ENC_BLOCK_IND directly to encrypt some user data.
A similar api could be implemented for encrypting blocks. Unlike the timers, two encryption requests cannot run in parallel. Therefore, there should be a queue of encryption requests & callbacks (with push, pop and peek).
The function can be called:
app_easy_encrypt_block(const uint8_t *operand_1, const uint8_t *operand_2, void(*fn)(const uint8_t*))
It can either return a boolean or a uint8_t, containing an error in case of failure (for example, if the queue is full).
When the function is called, it should create a struct-element of operand_1, operand_2 and fn, and try to push it to the queue.
If the queue was empty right before this push, it means there are no parallel encryptions - the function should send a new GAPM_USER_ENC_BLOCK_CMD with operand_1 and operand_2 that were just inserted.
When a GAPM_USER_ENC_BLOCK_IND arrives, we should pop an element from the queue and save it aside in a temporary variable (an assertion should make sure that the queue was not empty).
Then, if the queue is still not empty, we should peek its head and send a new GAPM_USER_ENC_BLOCK_CMD in order to continue the encryption process.
At last, we should call the fn callback from the element that was saved aside, with the result field from the GAPM_USER_ENC_BLOCK_IND.
Let me know what you think about it,
Oren Zomer
Are there any news regarding this feature?
I am trying to understand the architecture of SDK5, and to figure the right way to implement my asynchronous encryption function.
I can see that some GAPM_.._IND handlers are defined in
app_gap_process_handlers[]
in app_task.c.Do you think I should add the GAPM_USER_ENC_BLOCK_IND handler there?
The way I see it, the handler should be implemented in app_task.c and use EXECUTE_CALLBACK_PARAM to call
app_on_user_enc_block_ind
which should be added toapp_callbacks
in app_callbacks.h and user_callback_config.h, and refer touser_app_on_user_enc_block_ind
...I am sure there was a lot of effort to separate the generic code from the app-specific code, so that users like us will not have to touch code outside the target_apps dir, but unfortunately there are still many features missing...
The AES hardware is lightning fast according to me so there should be no need to do it asynchronously.
Use this code below to do your AES-ECB encryption. It makes sure it doesn't collide with a pending encryption in the stack.
All parameters are assumed to be in big endian (the way the AES standard is) and not reversed.
void encrypt(const uint8_t key[16], const uint8_t plaintext[16], uint8_t ciphertext[16]) {
volatile uint8_t* plaintext_ptr = (volatile uint8_t*)0x80000 + jump_table_struct[offset_em_enc_plain];
volatile uint8_t* ciphertext_ptr = (volatile uint8_t*)0x80000 + jump_table_struct[offset_em_enc_cipher];
uint8_t saved_data[16];
if (llm_le_env.enc_pend) {
while(GetWord32(BLE_AESCNTL_REG)==1){}
memcpy(saved_data, (void*)ciphertext_ptr, 16);
}
uint32_t key32aligned[4];
memcpy(key32aligned, key, 16);
SetWord32(BLE_AESKEY31_0_REG, __rev(key32aligned[3]));
SetWord32(BLE_AESKEY63_32_REG, __rev(key32aligned[2]));
SetWord32(BLE_AESKEY95_64_REG, __rev(key32aligned[1]));
SetWord32(BLE_AESKEY127_96_REG, __rev(key32aligned[0]));
for(int i = 0; i < 16; i++) {
plaintext_ptr[i] = plaintext[15 - i];
}
SetWord32(BLE_AESPTR_REG, (uint32_t)(plaintext_ptr - 0x80000));
SetWord32(BLE_AESCNTL_REG, 1);
while (GetWord32(BLE_AESCNTL_REG) == 1) {}
memcpy(ciphertext, (void*)ciphertext_ptr, 16);
if (llm_le_env.enc_pend) {
memcpy((void*)ciphertext_ptr, saved_data, 16);
}
}